diff --git a/README_zh.md b/README_zh.md index c40a606191..c5a4769987 100644 --- a/README_zh.md +++ b/README_zh.md @@ -150,7 +150,7 @@ aa start -d 12345 -a com.ohos.app.MainAbility -b com.ohos.app -D | 命令 | 描述 | | -------------------------------------------------------------- | ------------------------ | -| aa force-stop | 强制停止application | +| aa force-stop [-p ] [-r ] | 强制停止application,支持传递pid和进程退出原因 | ``` 示例: diff --git a/frameworks/js/napi/ability/ability.js b/frameworks/js/napi/ability/ability.js index c043d6d578..d349f46f5d 100644 --- a/frameworks/js/napi/ability/ability.js +++ b/frameworks/js/napi/ability/ability.js @@ -13,6 +13,7 @@ * limitations under the License. */ let Callee = requireNapi('application.Callee'); +let AbilityConstant = requireNapi('app.ability.AbilityConstant'); class Ability { constructor() { @@ -41,7 +42,9 @@ class Ability { dump(params) { } onDump(params) { } - onSaveState(state, wantParams) { } + onSaveState(state, wantParams) { + return AbilityConstant.OnSaveResult.RECOVERY_AGREE; + } onShare(wantParams) { } } diff --git a/frameworks/js/napi/ability_context/ability_context.js b/frameworks/js/napi/ability_context/ability_context.js index 9aeca43209..a261d4e0dd 100644 --- a/frameworks/js/napi/ability_context/ability_context.js +++ b/frameworks/js/napi/ability_context/ability_context.js @@ -207,10 +207,14 @@ class AbilityContext extends Context { openAtomicService(appId, options, callback) { return this.__context_impl__.openAtomicService(appId, options, callback); } - + moveAbilityToBackground(callback) { return this.__context_impl__.moveAbilityToBackground(callback); } + + setRestoreEnabled(enabled) { + this.__context_impl__.setRestoreEnabled(enabled); + } } export default AbilityContext; diff --git a/frameworks/native/ability/ability_runtime/ability_context_impl.cpp b/frameworks/native/ability/ability_runtime/ability_context_impl.cpp index cddef12571..3fdd8e364c 100644 --- a/frameworks/native/ability/ability_runtime/ability_context_impl.cpp +++ b/frameworks/native/ability/ability_runtime/ability_context_impl.cpp @@ -988,5 +988,15 @@ ErrCode AbilityContextImpl::OpenAtomicService(AAFwk::Want& want, const AAFwk::St } return err; } + +void AbilityContextImpl::SetRestoreEnabled(bool enabled) +{ + restoreEnabled_.store(enabled); +} + +bool AbilityContextImpl::GetRestoreEnabled() +{ + return restoreEnabled_.load(); +} } // namespace AbilityRuntime } // namespace OHOS diff --git a/frameworks/native/ability/native/ability_runtime/js_ability_context.cpp b/frameworks/native/ability/native/ability_runtime/js_ability_context.cpp index c66f9a59f2..3d0b408218 100644 --- a/frameworks/native/ability/native/ability_runtime/js_ability_context.cpp +++ b/frameworks/native/ability/native/ability_runtime/js_ability_context.cpp @@ -350,6 +350,11 @@ napi_value JsAbilityContext::MoveAbilityToBackground(napi_env env, napi_callback GET_NAPI_INFO_AND_CALL(env, info, JsAbilityContext, OnMoveAbilityToBackground); } +napi_value JsAbilityContext::SetRestoreEnabled(napi_env env, napi_callback_info info) +{ + GET_NAPI_INFO_AND_CALL(env, info, JsAbilityContext, OnSetRestoreEnabled); +} + void JsAbilityContext::ClearFailedCallConnection( const std::weak_ptr& abilityContext, const std::shared_ptr &callback) { @@ -1616,6 +1621,7 @@ napi_value CreateJsAbilityContext(napi_env env, std::shared_ptr BindNativeFunction(env, object, "openAtomicService", moduleName, JsAbilityContext::OpenAtomicService); BindNativeFunction(env, object, "moveAbilityToBackground", moduleName, JsAbilityContext::MoveAbilityToBackground); + BindNativeFunction(env, object, "setRestoreEnabled", moduleName, JsAbilityContext::SetRestoreEnabled); #ifdef SUPPORT_GRAPHICS BindNativeFunction(env, object, "setMissionLabel", moduleName, JsAbilityContext::SetMissionLabel); @@ -2215,5 +2221,32 @@ napi_value JsAbilityContext::OnMoveAbilityToBackground(napi_env env, NapiCallbac env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result)); return result; } + +napi_value JsAbilityContext::OnSetRestoreEnabled(napi_env env, NapiCallbackInfo& info) +{ + TAG_LOGD(AAFwkTag::CONTEXT, "Set if support restore."); + if (info.argc == ARGC_ZERO) { + TAG_LOGE(AAFwkTag::CONTEXT, "Not enough params."); + ThrowTooFewParametersError(env); + return CreateJsUndefined(env); + } + + auto abilityContext = context_.lock(); + if (abilityContext == nullptr) { + TAG_LOGW(AAFwkTag::CONTEXT, "Context has already released."); + ThrowError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT); + return CreateJsUndefined(env); + } + + bool enabled = true; + if (!ConvertFromJsValue(env, info.argv[INDEX_ZERO], enabled)) { + TAG_LOGE(AAFwkTag::CONTEXT, "Parse param failed."); + ThrowInvalidParamError(env, "Parse param enabled failed."); + return CreateJsUndefined(env); + } + + abilityContext->SetRestoreEnabled(enabled); + return CreateJsUndefined(env); +} } // namespace AbilityRuntime } // namespace OHOS diff --git a/frameworks/native/ability/native/ability_runtime/js_ui_ability.cpp b/frameworks/native/ability/native/ability_runtime/js_ui_ability.cpp index c76eb8c191..93f481ac8c 100644 --- a/frameworks/native/ability/native/ability_runtime/js_ui_ability.cpp +++ b/frameworks/native/ability/native/ability_runtime/js_ui_ability.cpp @@ -488,6 +488,7 @@ void JsUIAbility::OnSceneCreated() void JsUIAbility::OnSceneRestored() { + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); UIAbility::OnSceneRestored(); TAG_LOGD(AAFwkTag::UIABILITY, "called."); HandleScope handleScope(jsRuntime_); @@ -719,7 +720,8 @@ void JsUIAbility::AbilityContinuationOrRecover(const Want &want) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); // multi-instance ability continuation - TAG_LOGD(AAFwkTag::UIABILITY, "Launch reason is %{public}d.", launchParam_.launchReason); + TAG_LOGD(AAFwkTag::UIABILITY, "Launch reason is %{public}d, last exit reasion is %{public}d.", + launchParam_.launchReason, launchParam_.lastExitReason); if (IsRestoredInContinuation()) { RestorePageStack(want); OnSceneRestored(); @@ -731,12 +733,20 @@ void JsUIAbility::AbilityContinuationOrRecover(const Want &want) auto mainWindow = scene_->GetMainWindow(); if (mainWindow != nullptr) { mainWindow->NapiSetUIContent(pageStack, env, abilityContext_->GetContentStorage()->GetNapiValue(), - Rosen::BackupAndRestoreType::CONTINUATION); + Rosen::BackupAndRestoreType::APP_RECOVERY); } else { TAG_LOGE(AAFwkTag::UIABILITY, "MainWindow is nullptr."); } OnSceneRestored(); } else { + if (ShouldDefaultRecoverState(want) && abilityRecovery_ != nullptr && scene_ != nullptr) { + TAG_LOGD(AAFwkTag::UIABILITY, "Need restore."); + std::string pageStack = abilityRecovery_->GetSavedPageStack(AppExecFwk::StateReason::DEVELOPER_REQUEST); + auto mainWindow = scene_->GetMainWindow(); + if (!pageStack.empty() && mainWindow != nullptr) { + mainWindow->SetRestoredRouterStack(pageStack); + } + } OnSceneCreated(); } } diff --git a/frameworks/native/ability/native/recovery/ability_recovery.cpp b/frameworks/native/ability/native/recovery/ability_recovery.cpp index 807803e2e3..fb9512876a 100644 --- a/frameworks/native/ability/native/recovery/ability_recovery.cpp +++ b/frameworks/native/ability/native/recovery/ability_recovery.cpp @@ -26,6 +26,7 @@ #include "file_ex.h" #include "hilog_tag_wrapper.h" #include "hilog_wrapper.h" +#include "hitrace_meter.h" #include "js_runtime.h" #include "js_runtime_utils.h" #include "napi/native_api.h" @@ -39,6 +40,8 @@ namespace OHOS { namespace AppExecFwk { namespace { +constexpr size_t DEFAULT_RECOVERY_MAX_RESTORE_SIZE = 10 * 1024; + static std::string GetSaveAppCachePath(int32_t savedStateId) { auto context = AbilityRuntime::Context::GetApplicationContext(); @@ -82,11 +85,13 @@ bool AbilityRecovery::InitAbilityInfo(const std::shared_ptrGetContentInfo(); + std::string pageStack = DefaultRecovery() ? ability->GetContentInfoForDefaultRecovery() : + ability->GetContentInfoForRecovery(); if (!pageStack.empty()) { wantParams.SetParam("pageStack", AAFwk::String::Box(pageStack)); } else { TAG_LOGE(AAFwkTag::RECOVERY, "AppRecovery Failed to get page stack."); } + TAG_LOGD(AAFwkTag::RECOVERY, "pageStack size: %{public}zu.", pageStack.size()); #endif if (saveMode_ == SaveModeFlag::SAVE_WITH_FILE) { SerializeDataToFile(missionId_, wantParams); @@ -135,6 +143,7 @@ bool AbilityRecovery::SaveAbilityState() bool AbilityRecovery::SerializeDataToFile(int32_t savedStateId, WantParams& params) { + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); std::string file = GetSaveAppCachePath(savedStateId); if (file.empty()) { TAG_LOGE(AAFwkTag::RECOVERY, "AppRecovery %{public}s failed to persisted file path.", __func__); @@ -157,23 +166,33 @@ bool AbilityRecovery::SerializeDataToFile(int32_t savedStateId, WantParams& para close(fd); return false; } + + if (DefaultRecovery() && (sz > DEFAULT_RECOVERY_MAX_RESTORE_SIZE)) { + TAG_LOGE(AAFwkTag::RECOVERY, "data is too large, size: %{public}zu.", sz); + close(fd); + return false; + } + ssize_t nwrite = write(fd, reinterpret_cast(buf), sz); if (nwrite <= 0) { TAG_LOGE(AAFwkTag::RECOVERY, "AppRecovery%{public}s failed to persist parcel data %{public}d.", __func__, errno); } + TAG_LOGD(AAFwkTag::RECOVERY, "file size: %{public}zu.", sz); close(fd); return true; } bool AbilityRecovery::ReadSerializeDataFromFile(int32_t savedStateId, WantParams& params) { + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); std::string file = GetSaveAppCachePath(savedStateId); if (file.empty()) { TAG_LOGE(AAFwkTag::RECOVERY, "AppRecovery %{public}s failed to persisted file path.", __func__); return false; } + TAG_LOGD(AAFwkTag::RECOVERY, "file path %{public}s.", file.c_str()); char path[PATH_MAX] = {0}; if (realpath(file.c_str(), path) == nullptr) { TAG_LOGE(AAFwkTag::RECOVERY, "AppRecovery realpath error, errno is %{public}d.", errno); @@ -228,6 +247,7 @@ bool AbilityRecovery::ReadSerializeDataFromFile(int32_t savedStateId, WantParams bool AbilityRecovery::ScheduleSaveAbilityState(StateReason reason) { + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); if (!isEnable_) { TAG_LOGE(AAFwkTag::RECOVERY, "AppRecovery not enable"); return false; @@ -263,6 +283,7 @@ bool AbilityRecovery::ScheduleSaveAbilityState(StateReason reason) bool AbilityRecovery::ScheduleRecoverAbility(StateReason reason, const Want *want) { + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); if (!isEnable_) { TAG_LOGE(AAFwkTag::RECOVERY, "AppRecovery not enable"); return false; @@ -315,6 +336,7 @@ bool AbilityRecovery::IsOnForeground() bool AbilityRecovery::LoadSavedState(StateReason reason) { + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); auto abilityInfo = abilityInfo_.lock(); if (abilityInfo == nullptr) { TAG_LOGE(AAFwkTag::RECOVERY, "AppRecovery LoadSavedState abilityInfo is nullptr"); @@ -347,6 +369,7 @@ bool AbilityRecovery::LoadSavedState(StateReason reason) bool AbilityRecovery::ScheduleRestoreAbilityState(StateReason reason, const Want &want) { + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); if (!isEnable_) { TAG_LOGE(AAFwkTag::RECOVERY, "AppRecovery not enable"); return false; @@ -372,6 +395,7 @@ bool AbilityRecovery::ScheduleRestoreAbilityState(StateReason reason, const Want std::string AbilityRecovery::GetSavedPageStack(StateReason reason) { + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); if (!LoadSavedState(reason)) { TAG_LOGE(AAFwkTag::RECOVERY, "AppRecovery GetSavedPageStack no saved state "); return ""; @@ -428,5 +452,10 @@ uint16_t AbilityRecovery::GetSaveModeFlag() const { return saveMode_; } + +bool AbilityRecovery::DefaultRecovery() const +{ + return !(useAppSettedValue_.load()); +} } // namespace AbilityRuntime } // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/ability/native/recovery/app_recovery.cpp b/frameworks/native/ability/native/recovery/app_recovery.cpp index 8bb0686e87..f97af3e911 100644 --- a/frameworks/native/ability/native/recovery/app_recovery.cpp +++ b/frameworks/native/ability/native/recovery/app_recovery.cpp @@ -116,20 +116,20 @@ bool AppRecovery::InitApplicationInfo(const std::shared_ptr& mainH bool AppRecovery::AddAbility(std::shared_ptr ability, const std::shared_ptr& abilityInfo, const sptr& token) { - if (!isEnable_) { - TAG_LOGE(AAFwkTag::RECOVERY, "AppRecovery not enabled."); + if (abilityInfo == nullptr) { + TAG_LOGE(AAFwkTag::RECOVERY, "Ability info invalid."); return false; } - if (!abilityRecoverys_.empty() && !abilityInfo->recoverable) { + if (isEnable_ && !abilityRecoverys_.empty() && !abilityInfo->recoverable) { TAG_LOGE(AAFwkTag::RECOVERY, "AppRecovery abilityRecoverys is not empty but ability recoverable is false."); return false; } ability_ = ability; std::shared_ptr abilityRecovery = std::make_shared(); abilityRecovery->InitAbilityInfo(ability, abilityInfo, token); - abilityRecovery->EnableAbilityRecovery(restartFlag_, saveOccasion_, saveMode_); - ability->EnableAbilityRecovery(abilityRecovery); + abilityRecovery->EnableAbilityRecovery(useAppSettedValue_.load(), restartFlag_, saveOccasion_, saveMode_); + ability->EnableAbilityRecovery(abilityRecovery, useAppSettedValue_.load()); abilityRecoverys_.push_back(abilityRecovery); auto handler = mainHandler_.lock(); if (handler != nullptr) { @@ -145,11 +145,6 @@ bool AppRecovery::AddAbility(std::shared_ptr ability, bool AppRecovery::RemoveAbility(const sptr& tokenId) { - if (!isEnable_) { - TAG_LOGE(AAFwkTag::RECOVERY, "AppRecovery not enabled. not removeAbility"); - return false; - } - if (!tokenId) { TAG_LOGE(AAFwkTag::RECOVERY, "AppRecovery removeAbility tokenId is null."); return false; @@ -339,6 +334,7 @@ void AppRecovery::EnableAppRecovery(uint16_t restartFlag, uint16_t saveFlag, uin restartFlag_ = restartFlag; saveOccasion_ = saveFlag; saveMode_ = saveMode; + useAppSettedValue_.store(true); } bool AppRecovery::ShouldSaveAppState(StateReason reason) diff --git a/frameworks/native/ability/native/ui_ability.cpp b/frameworks/native/ability/native/ui_ability.cpp index cc8d372401..9ac24dfe61 100644 --- a/frameworks/native/ability/native/ui_ability.cpp +++ b/frameworks/native/ability/native/ui_ability.cpp @@ -30,6 +30,9 @@ #include "reverse_continuation_scheduler_primary_stage.h" #include "runtime.h" #include "resource_config_helper.h" +#ifdef SUPPORT_GRAPHICS +#include "wm_common.h" +#endif namespace OHOS { namespace AbilityRuntime { @@ -196,9 +199,6 @@ void UIAbility::OnStop() HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); TAG_LOGD(AAFwkTag::UIABILITY, "Begin."); #ifdef SUPPORT_SCREEN - if (abilityRecovery_ != nullptr) { - abilityRecovery_->ScheduleSaveAbilityState(AppExecFwk::StateReason::LIFECYCLE); - } TAG_LOGI(AAFwkTag::UIABILITY, "UnregisterDisplayInfoChangedListener."); (void)Rosen::WindowManager::GetInstance().UnregisterDisplayInfoChangedListener(token_, abilityDisplayListener_); auto &&window = GetWindow(); @@ -283,6 +283,18 @@ bool UIAbility::ShouldRecoverState(const AAFwk::Want &want) return true; } +bool UIAbility::ShouldDefaultRecoverState(const AAFwk::Want &want) +{ + auto launchParam = GetLaunchParam(); + if (CheckDefaultRecoveryEnabled() && IsStartByScb() && + want.GetBoolParam(Want::PARAM_ABILITY_RECOVERY_RESTART, false) && + (launchParam.lastExitReason == AAFwk::LastExitReason::LASTEXITREASON_PERFORMANCE_CONTROL || + launchParam.lastExitReason == AAFwk::LastExitReason::LASTEXITREASON_RESOURCE_CONTROL)) { + return true; + } + return false; +} + void UIAbility::NotifyContinuationResult(const AAFwk::Want &want, bool success) { TAG_LOGD(AAFwkTag::UIABILITY, "Called."); @@ -543,9 +555,11 @@ bool UIAbility::IsUseNewStartUpRule() return startUpNewRule_; } -void UIAbility::EnableAbilityRecovery(const std::shared_ptr &abilityRecovery) +void UIAbility::EnableAbilityRecovery(const std::shared_ptr &abilityRecovery, + bool useAppSettedRecoveryValue) { abilityRecovery_ = abilityRecovery; + useAppSettedRecoveryValue_.store(useAppSettedRecoveryValue); } int32_t UIAbility::OnShare(AAFwk::WantParams &wantParams) @@ -621,7 +635,9 @@ void UIAbility::OnBackground() TAG_LOGD(AAFwkTag::UIABILITY, "GoBackground sceneFlag: %{public}d.", sceneFlag_); scene_->GoBackground(sceneFlag_); } - if (abilityRecovery_ != nullptr) { + + if (abilityRecovery_ != nullptr && abilityContext_ != nullptr && abilityContext_->GetRestoreEnabled() && + CheckRecoveryEnabled()) { abilityRecovery_->ScheduleSaveAbilityState(AppExecFwk::StateReason::LIFECYCLE); } @@ -670,10 +686,32 @@ void UIAbility::OnLeaveForeground() std::string UIAbility::GetContentInfo() { + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); if (scene_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "Scene invalid."); return ""; } - return scene_->GetContentInfo(); + return scene_->GetContentInfo(Rosen::BackupAndRestoreType::CONTINUATION); +} + +std::string UIAbility::GetContentInfoForRecovery() +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + if (scene_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "Scene invalid."); + return ""; + } + return scene_->GetContentInfo(Rosen::BackupAndRestoreType::APP_RECOVERY); +} + +std::string UIAbility::GetContentInfoForDefaultRecovery() +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + if (scene_ == nullptr) { + TAG_LOGE(AAFwkTag::UIABILITY, "Scene invalid."); + return ""; + } + return scene_->GetContentInfo(Rosen::BackupAndRestoreType::RESOURCESCHEDULE_RECOVERY); } void UIAbility::SetSceneListener(const sptr &listener) @@ -1138,6 +1176,49 @@ std::string UIAbility::GetIdentityToken() const { return identityToken_; } + +bool UIAbility::CheckRecoveryEnabled() +{ + if (useAppSettedRecoveryValue_.load()) { + TAG_LOGD(AAFwkTag::UIABILITY, "Use app setted value."); + // Check in app recovery, here return true. + return true; + } + + return CheckDefaultRecoveryEnabled(); +} + +bool UIAbility::CheckDefaultRecoveryEnabled() +{ + if (setting_ == nullptr) { + TAG_LOGW(AAFwkTag::UIABILITY, "setting is nullptr."); + return false; + } + + auto value = setting_->GetProperty(AppExecFwk::AbilityStartSetting::DEFAULT_RECOVERY_KEY); + if ((!useAppSettedRecoveryValue_.load()) && (value == "true")) { + TAG_LOGD(AAFwkTag::UIABILITY, "default recovery enabled."); + return true; + } + + return false; +} + +bool UIAbility::IsStartByScb() +{ + if (setting_ == nullptr) { + TAG_LOGW(AAFwkTag::UIABILITY, "setting is nullptr."); + return false; + } + + auto value = setting_->GetProperty(AppExecFwk::AbilityStartSetting::IS_START_BY_SCB_KEY); + if (value == "true") { + TAG_LOGD(AAFwkTag::UIABILITY, "Start by scb."); + return true; + } + + return false; +} #endif } // namespace AbilityRuntime } // namespace OHOS diff --git a/interfaces/inner_api/ability_manager/include/ability_start_setting.h b/interfaces/inner_api/ability_manager/include/ability_start_setting.h index 2b606df6df..08e1feeab6 100644 --- a/interfaces/inner_api/ability_manager/include/ability_start_setting.h +++ b/interfaces/inner_api/ability_manager/include/ability_start_setting.h @@ -29,6 +29,8 @@ public: static const std::string BOUNDS_KEY; static const std::string WINDOW_DISPLAY_ID_KEY; static const std::string WINDOW_MODE_KEY; + static const std::string DEFAULT_RECOVERY_KEY; + static const std::string IS_START_BY_SCB_KEY; /** * @brief Construct copy function. diff --git a/interfaces/kits/native/ability/ability_runtime/ability_context.h b/interfaces/kits/native/ability/ability_runtime/ability_context.h index e157191db8..4a05e9daab 100644 --- a/interfaces/kits/native/ability/ability_runtime/ability_context.h +++ b/interfaces/kits/native/ability/ability_runtime/ability_context.h @@ -340,6 +340,9 @@ public: virtual void UnregisterAbilityLifecycleObserver( const std::shared_ptr &observer) = 0; + virtual void SetRestoreEnabled(bool enabled) = 0; + virtual bool GetRestoreEnabled() = 0; + #ifdef SUPPORT_GRAPHICS #ifdef SUPPORT_SCREEN /** diff --git a/interfaces/kits/native/ability/ability_runtime/ability_context_impl.h b/interfaces/kits/native/ability/ability_runtime/ability_context_impl.h index f6190a4483..4046a9e512 100644 --- a/interfaces/kits/native/ability/ability_runtime/ability_context_impl.h +++ b/interfaces/kits/native/ability/ability_runtime/ability_context_impl.h @@ -230,6 +230,9 @@ public: void InsertResultCallbackTask(int requestCode, RuntimeTask&& task) override; + void SetRestoreEnabled(bool enabled) override; + bool GetRestoreEnabled() override; + #ifdef SUPPORT_SCREEN /** * @brief Set mission label of this ability. @@ -296,6 +299,7 @@ private: wptr sessionToken_; std::mutex uiExtensionMutex_; std::map uiExtensionMap_; + std::atomic restoreEnabled_ = true; static void RequestDialogResultJSThreadWorker(uv_work_t* work, int status); void OnAbilityResultInner(int requestCode, int resultCode, const AAFwk::Want &resultData); diff --git a/interfaces/kits/native/ability/native/ability_runtime/js_ability_context.h b/interfaces/kits/native/ability/native/ability_runtime/js_ability_context.h index df4f41f53e..3dffb32d12 100644 --- a/interfaces/kits/native/ability/native/ability_runtime/js_ability_context.h +++ b/interfaces/kits/native/ability/native/ability_runtime/js_ability_context.h @@ -67,6 +67,7 @@ public: static napi_value HideAbility(napi_env env, napi_callback_info info); static napi_value OpenAtomicService(napi_env env, napi_callback_info info); static napi_value MoveAbilityToBackground(napi_env env, napi_callback_info info); + static napi_value SetRestoreEnabled(napi_env env, napi_callback_info info); static void ConfigurationUpdated(napi_env env, std::shared_ptr &jsContext, const std::shared_ptr &config); @@ -120,6 +121,7 @@ private: napi_value OpenAtomicServiceInner(napi_env env, NapiCallbackInfo& info, AAFwk::Want &want, AAFwk::StartOptions &options); napi_value OnMoveAbilityToBackground(napi_env env, NapiCallbackInfo& info); + napi_value OnSetRestoreEnabled(napi_env env, NapiCallbackInfo& info); bool CreateOpenLinkTask(const napi_env &env, const napi_value &lastParam, AAFwk::Want &want, int &requestCode); diff --git a/interfaces/kits/native/ability/native/recovery/ability_recovery.h b/interfaces/kits/native/ability/native/recovery/ability_recovery.h index 635cb29245..0c3eba1646 100644 --- a/interfaces/kits/native/ability/native/recovery/ability_recovery.h +++ b/interfaces/kits/native/ability/native/recovery/ability_recovery.h @@ -35,7 +35,7 @@ class AbilityRecovery { public: AbilityRecovery(); virtual ~AbilityRecovery(); - void EnableAbilityRecovery(uint16_t restartFlag, uint16_t saveFlag, uint16_t saveMode); + void EnableAbilityRecovery(bool useAppSettedValue, uint16_t restartFlag, uint16_t saveFlag, uint16_t saveMode); bool InitAbilityInfo(const std::shared_ptr ability, const std::shared_ptr &abilityInfo, const sptr &token); bool ScheduleSaveAbilityState(StateReason reason); @@ -62,6 +62,7 @@ private: bool ReadSerializeDataFromFile(int32_t savedStateId, AAFwk::WantParams& params); bool LoadSavedState(StateReason reason); bool IsSaveAbilityState(StateReason reason); + bool DefaultRecovery() const; bool isEnable_; uint16_t restartFlag_; @@ -76,6 +77,7 @@ private: bool hasTryLoad_ = false; bool hasLoaded_ = false; std::mutex lock_; + std::atomic useAppSettedValue_ = false; // If the value is true means app call appRecovery.enableAppRecovery }; } // namespace AbilityRuntime } // namespace OHOS diff --git a/interfaces/kits/native/ability/native/recovery/app_recovery.h b/interfaces/kits/native/ability/native/recovery/app_recovery.h index be2863eb6e..772ae76598 100644 --- a/interfaces/kits/native/ability/native/recovery/app_recovery.h +++ b/interfaces/kits/native/ability/native/recovery/app_recovery.h @@ -74,6 +74,7 @@ private: std::weak_ptr ability_; std::vector> abilityRecoverys_; std::shared_ptr want_ = nullptr; + std::atomic useAppSettedValue_ = false; // If the value is true means app call appRecovery.enableAppRecovery }; } // namespace AbilityRuntime } // namespace OHOS diff --git a/interfaces/kits/native/ability/native/ui_ability.h b/interfaces/kits/native/ability/native/ui_ability.h index d56c43f80b..78c299eeac 100644 --- a/interfaces/kits/native/ability/native/ui_ability.h +++ b/interfaces/kits/native/ability/native/ui_ability.h @@ -307,8 +307,10 @@ public: /** * @brief enable ability recovery. * @param abilityRecovery shared_ptr of abilityRecovery + * @param useAppSettedRecoveryValue Indicates use default recovery or not. */ - void EnableAbilityRecovery(const std::shared_ptr &abilityRecovery); + void EnableAbilityRecovery(const std::shared_ptr &abilityRecovery, + bool useAppSettedRecoveryValue); /** * @brief Callback when the ability is shared.You can override this function to implement your own sharing logic. @@ -326,6 +328,7 @@ protected: bool IsRestoredInContinuation() const; void NotifyContinuationResult(const AAFwk::Want &want, bool success); bool ShouldRecoverState(const AAFwk::Want &want); + bool ShouldDefaultRecoverState(const AAFwk::Want &want); bool IsUseNewStartUpRule(); std::shared_ptr abilityContext_ = nullptr; @@ -355,6 +358,7 @@ private: bool isNewRuleFlagSetted_ = false; bool startUpNewRule_ = false; bool isSilentForeground_ = false; + std::atomic useAppSettedRecoveryValue_ = false; #ifdef SUPPORT_SCREEN public: @@ -433,6 +437,8 @@ public: * @return A string represents page ability stack info, empty if failed; */ virtual std::string GetContentInfo(); + virtual std::string GetContentInfoForRecovery(); + virtual std::string GetContentInfoForDefaultRecovery(); /** * @brief Set WindowScene listener @@ -587,6 +593,9 @@ protected: virtual void DoOnForeground(const AAFwk::Want &want); sptr GetWindowOption(const AAFwk::Want &want); virtual void ContinuationRestore(const AAFwk::Want &want); + bool CheckRecoveryEnabled(); + bool CheckDefaultRecoveryEnabled(); + bool IsStartByScb(); std::shared_ptr scene_ = nullptr; sptr sceneListener_ = nullptr; diff --git a/services/abilitymgr/BUILD.gn b/services/abilitymgr/BUILD.gn index 5151d9fe11..d1f16ce26f 100644 --- a/services/abilitymgr/BUILD.gn +++ b/services/abilitymgr/BUILD.gn @@ -256,10 +256,17 @@ ohos_prebuilt_etc("ams_extension_config.json") { part_name = "ability_runtime" } +ohos_prebuilt_etc("default_recovery_config.json") { + source = "resource/default_recovery_config.json" + subsystem_name = "ability" + part_name = "ability_runtime" +} + group("ams_service_config") { deps = [ ":ams_service_config.json", ":deeplink_reserve_config.json", + ":default_recovery_config.json", ":uiextension_picker_config.json", ] } diff --git a/services/abilitymgr/abilitymgr.gni b/services/abilitymgr/abilitymgr.gni index 1f788a4c8c..89ed7ddb77 100644 --- a/services/abilitymgr/abilitymgr.gni +++ b/services/abilitymgr/abilitymgr.gni @@ -104,6 +104,7 @@ abilityms_files = [ "src/scene_board/status_bar_delegate_manager.cpp", "src/scene_board/ui_ability_lifecycle_manager.cpp", "src/deeplink_reserve/deeplink_reserve_config.cpp", + "src/app_recovery/default_recovery_config.cpp", #connection observer "src/connection_observer_controller.cpp", diff --git a/services/abilitymgr/include/ability_manager_service.h b/services/abilitymgr/include/ability_manager_service.h index 6166b5626f..15f91c5ce3 100644 --- a/services/abilitymgr/include/ability_manager_service.h +++ b/services/abilitymgr/include/ability_manager_service.h @@ -2132,6 +2132,7 @@ private: void InitInterceptor(); void InitPushTask(); void InitDeepLinkReserve(); + void InitDefaultRecoveryList(); bool CheckSenderWantInfo(int32_t callerUid, const WantSenderInfo &wantSenderInfo); diff --git a/services/abilitymgr/include/app_recovery/default_recovery_config.h b/services/abilitymgr/include/app_recovery/default_recovery_config.h new file mode 100755 index 0000000000..7f0cee8467 --- /dev/null +++ b/services/abilitymgr/include/app_recovery/default_recovery_config.h @@ -0,0 +1,61 @@ +/* + * 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_ABILITY_RUNTIME_DEFAULT_RECOVERY_CONFIG_H +#define OHOS_ABILITY_RUNTIME_DEFAULT_RECOVERY_CONFIG_H + +#include +#include +#include + +#include "singleton.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace DefaultRecoveryConstants { +constexpr int32_t RESERVE_NUMBER_INVALID = 0; +constexpr int32_t TIMEOUT_DELETE_TIME_INVALID = 0; +} // namespace DefaultRecoveryConstants + +class DefaultRecoveryConfig { +public: + static DefaultRecoveryConfig &GetInstance() + { + static DefaultRecoveryConfig instance; + return instance; + } + + ~DefaultRecoveryConfig() = default; + bool LoadConfiguration(); + bool IsBundleDefaultRecoveryEnabled(const std::string &bundleName); + int32_t GetReserveNumber(); + int32_t GetTimeoutDeleteTime(); + +private: + std::string GetConfigPath(); + bool ReadFileInfoJson(const std::string &filePath, nlohmann::json &jsonBuf); + bool LoadDefaultRecovery(const nlohmann::json &object); + DefaultRecoveryConfig() = default; + DISALLOW_COPY_AND_MOVE(DefaultRecoveryConfig); + +private: + // It was set in Init() of abilityms. + std::unordered_set bundleNameList_; + int32_t reserveNumber_ = DefaultRecoveryConstants::RESERVE_NUMBER_INVALID; + int32_t timeoutDeleteTime_ = DefaultRecoveryConstants::TIMEOUT_DELETE_TIME_INVALID; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_DEFAULT_RECOVERY_CONFIG_H diff --git a/services/abilitymgr/resource/default_recovery_config.json b/services/abilitymgr/resource/default_recovery_config.json new file mode 100755 index 0000000000..72971ae9cd --- /dev/null +++ b/services/abilitymgr/resource/default_recovery_config.json @@ -0,0 +1,7 @@ +{ + "default_recovery": { + "support_bundle_name_list": [], + "reserve_number_when_timeout": 5, + "recovery_data_timeout_delete_time": 168 + } +} diff --git a/services/abilitymgr/src/ability_manager_service.cpp b/services/abilitymgr/src/ability_manager_service.cpp index aa0a739721..8ab657d031 100644 --- a/services/abilitymgr/src/ability_manager_service.cpp +++ b/services/abilitymgr/src/ability_manager_service.cpp @@ -41,6 +41,7 @@ #include "accesstoken_kit.h" #include "app_utils.h" #include "app_exit_reason_data_manager.h" +#include "app_recovery/default_recovery_config.h" #include "application_util.h" #include "assert_fault_callback_death_mgr.h" #include "assert_fault_proxy.h" @@ -419,6 +420,7 @@ bool AbilityManagerService::Init() InitInterceptor(); InitStartAbilityChain(); InitDeepLinkReserve(); + InitDefaultRecoveryList(); abilityAutoStartupService_ = std::make_shared(); #ifdef SUPPORT_SCREEN @@ -439,6 +441,13 @@ void AbilityManagerService::InitDeepLinkReserve() } } +void AbilityManagerService::InitDefaultRecoveryList() +{ + if (!DefaultRecoveryConfig::GetInstance().LoadConfiguration()) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Load default recovery list failed."); + } +} + void AbilityManagerService::InitInterceptor() { interceptorExecuter_ = std::make_shared(); @@ -1988,6 +1997,19 @@ int AbilityManagerService::StartUIAbilityBySCB(sptr sessionInfo, bo TAG_LOGE(AAFwkTag::ABILITYMGR, "Generate ability request local error."); return result; } + + if (sessionInfo->want.GetBoolParam(IS_CALL_BY_SCB, true)) { + if (sessionInfo->startSetting != nullptr) { + TAG_LOGD(AAFwkTag::ABILITYMGR, "Start by scb, last not."); + sessionInfo->startSetting->AddProperty(AbilityStartSetting::IS_START_BY_SCB_KEY, "true"); + } + + if (abilityRequest.startSetting != nullptr) { + TAG_LOGD(AAFwkTag::ABILITYMGR, "Start by scb."); + abilityRequest.startSetting->AddProperty(AbilityStartSetting::IS_START_BY_SCB_KEY, "true"); + } + } + abilityRequest.collaboratorType = sessionInfo->collaboratorType; uint32_t specifyTokenId = static_cast(sessionInfo->want.GetIntParam(SPECIFY_TOKEN_ID, 0)); (sessionInfo->want).RemoveParam(SPECIFY_TOKEN_ID); @@ -2035,6 +2057,8 @@ int AbilityManagerService::StartUIAbilityBySCB(sptr sessionInfo, bo ResourceSchedule::ResType::AssociatedStartType::SCB_START_ABILITY), sessionInfo->callerToken); auto uiAbilityManager = GetUIAbilityManagerByUid(IPCSkeleton::GetCallingUid()); CHECK_POINTER_AND_RETURN(uiAbilityManager, ERR_INVALID_VALUE); + // here we don't need want param "IS_CALL_BY_SCB" any more, remove it. + (sessionInfo->want).RemoveParam(IS_CALL_BY_SCB); return uiAbilityManager->StartUIAbility(abilityRequest, sessionInfo, isColdStart); } @@ -2140,7 +2164,8 @@ int32_t AbilityManagerService::RecordProcessExitReason(const int32_t pid, const TAG_LOGI(AAFwkTag::ABILITYMGR, "RecordProcessExitReason pid:%{public}d, reason:%{public}d, exitMsg: %{public}s", pid, exitReason.reason, exitReason.exitMsg.c_str()); - if (!AAFwk::PermissionVerification::GetInstance()->IsSACall()) { + if (!AAFwk::PermissionVerification::GetInstance()->IsSACall() && + !AAFwk::PermissionVerification::GetInstance()->IsShellCall()) { TAG_LOGE(AAFwkTag::ABILITYMGR, "Not sa call"); return ERR_PERMISSION_DENIED; } @@ -3299,9 +3324,12 @@ int AbilityManagerService::CloseUIAbilityBySCB(const sptr &sessionI if (sessionInfo->isClearSession) { const auto &abilityInfo = abilityRecord->GetAbilityInfo(); + std::string abilityName = abilityInfo.name; + if (abilityInfo.launchMode == AppExecFwk::LaunchMode::STANDARD) { + abilityName += std::to_string(sessionInfo->persistentId); + } (void)DelayedSingleton::GetInstance()-> - DeleteAbilityRecoverInfo(abilityInfo.applicationInfo.accessTokenId, abilityInfo.moduleName, - abilityInfo.name); + DeleteAbilityRecoverInfo(abilityInfo.applicationInfo.accessTokenId, abilityInfo.moduleName, abilityName); } EventInfo eventInfo; @@ -5710,7 +5738,16 @@ int AbilityManagerService::GenerateAbilityRequest(const Want &want, int requestC request.want = want; request.requestCode = requestCode; request.callerToken = callerToken; - request.startSetting = nullptr; + auto setting = AbilityStartSetting::GetEmptySetting(); + if (setting != nullptr) { + auto bundleName = want.GetElement().GetBundleName(); + auto defaultRecovery = DefaultRecoveryConfig::GetInstance().IsBundleDefaultRecoveryEnabled(bundleName); + TAG_LOGD(AAFwkTag::ABILITYMGR, "bundleName: %{public}s, defaultRecovery: %{public}d.", bundleName.c_str(), + defaultRecovery); + setting->AddProperty(AbilityStartSetting::DEFAULT_RECOVERY_KEY, defaultRecovery ? "true" : "false"); + setting->AddProperty(AbilityStartSetting::IS_START_BY_SCB_KEY, "false"); // default is false + request.startSetting = std::make_shared(*(setting.get())); + } auto abilityInfo = StartAbilityUtils::startAbilityInfo; if (abilityInfo == nullptr || abilityInfo->GetAppBundleName() != want.GetElement().GetBundleName()) { @@ -5762,6 +5799,7 @@ int AbilityManagerService::GenerateAbilityRequest(const Want &want, int requestC if (want.GetBoolParam(Want::PARAM_RESV_START_RECENT, false) && AAFwk::PermissionVerification::GetInstance()->VerifyStartRecentAbilityPermission()) { + TAG_LOGD(AAFwkTag::ABILITYMGR, "Set start recent."); request.startRecent = true; } if (isNeedSetDebugApp) { @@ -7100,6 +7138,7 @@ void AbilityManagerService::UpdateMissionSnapShot(const sptr &tok #endif // SUPPORT_SCREEN void AbilityManagerService::EnableRecoverAbility(const sptr& token) { + TAG_LOGD(AAFwkTag::ABILITYMGR, "Enable recovery ability."); if (token == nullptr) { return; } @@ -7127,9 +7166,13 @@ void AbilityManagerService::EnableRecoverAbility(const sptr& toke auto uiAbilityManager = GetUIAbilityManagerByUserId(userId); CHECK_POINTER(uiAbilityManager); const auto& abilityInfo = record->GetAbilityInfo(); + std::string abilityName = abilityInfo.name; + auto sessionId = uiAbilityManager->GetSessionIdByAbilityToken(token); + if (abilityInfo.launchMode == AppExecFwk::LaunchMode::STANDARD) { + abilityName += std::to_string(sessionId); + } (void)DelayedSingleton::GetInstance()->AddAbilityRecoverInfo( - abilityInfo.applicationInfo.accessTokenId, abilityInfo.moduleName, abilityInfo.name, - uiAbilityManager->GetSessionIdByAbilityToken(token)); + abilityInfo.applicationInfo.accessTokenId, abilityInfo.moduleName, abilityName, sessionId); } else { auto missionListMgr = GetMissionListManagerByUserId(userId); if (missionListMgr == nullptr) { diff --git a/services/abilitymgr/src/ability_start_setting.cpp b/services/abilitymgr/src/ability_start_setting.cpp index 19ef8c3101..52c6a00d37 100644 --- a/services/abilitymgr/src/ability_start_setting.cpp +++ b/services/abilitymgr/src/ability_start_setting.cpp @@ -24,6 +24,8 @@ namespace AAFwk { const std::string AbilityStartSetting::BOUNDS_KEY = "bounds"; const std::string AbilityStartSetting::WINDOW_DISPLAY_ID_KEY = "windowId"; const std::string AbilityStartSetting::WINDOW_MODE_KEY = "windowMode"; +const std::string AbilityStartSetting::DEFAULT_RECOVERY_KEY = "defaultRecovery"; +const std::string AbilityStartSetting::IS_START_BY_SCB_KEY = "isStartByScb"; constexpr uint32_t CYCLE_LIMIT = 1000; /** diff --git a/services/abilitymgr/src/app_exit_reason_data_manager.cpp b/services/abilitymgr/src/app_exit_reason_data_manager.cpp index fb5bfd08fe..3a9af8d34e 100644 --- a/services/abilitymgr/src/app_exit_reason_data_manager.cpp +++ b/services/abilitymgr/src/app_exit_reason_data_manager.cpp @@ -181,7 +181,8 @@ int32_t AppExitReasonDataManager::GetAppExitReason(const std::string &bundleName TAG_LOGW(AAFwkTag::ABILITYMGR, "invalid value!"); return ERR_INVALID_VALUE; } - TAG_LOGD(AAFwkTag::ABILITYMGR, "bundleName: %{public}s, tokenId: %{private}u", bundleName.c_str(), accessTokenId); + TAG_LOGD(AAFwkTag::ABILITYMGR, "bundleName: %{public}s, tokenId: %{private}u, abilityName: %{public}s.", + bundleName.c_str(), accessTokenId, abilityName.c_str()); { std::lock_guard lock(kvStorePtrMutex_); if (!CheckKvStore()) { diff --git a/services/abilitymgr/src/app_recovery/default_recovery_config.cpp b/services/abilitymgr/src/app_recovery/default_recovery_config.cpp new file mode 100755 index 0000000000..964dfb3fe0 --- /dev/null +++ b/services/abilitymgr/src/app_recovery/default_recovery_config.cpp @@ -0,0 +1,150 @@ +/* + * 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 "app_recovery/default_recovery_config.h" +#include +#include +#include +#include + +#include "config_policy_utils.h" +#include "hilog_tag_wrapper.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr const char* CONFIG_PATH = "/etc/default_recovery_config.json"; +constexpr const char* DEFAULT_RESERVE_CONFIG_PATH = "/system/etc/default_recovery_config.json"; +constexpr const char* ITEM_DEFAULT_RECOVERY_NAME = "default_recovery"; +constexpr const char* SUPPORT_BUNDLE_NAME_LIST = "support_bundle_name_list"; +constexpr const char* RESERVE_NUMBER_WHEN_TIMEOUT = "reserve_number_when_timeout"; +constexpr const char* RECOVERY_DATA_TIMEOUT_DELETE_TIME = "recovery_data_timeout_delete_time"; +} + +std::string DefaultRecoveryConfig::GetConfigPath() +{ + char buf[MAX_PATH_LEN] = { 0 }; + char *configPath = GetOneCfgFile(CONFIG_PATH, buf, MAX_PATH_LEN); + if (configPath == nullptr || configPath[0] == '\0' || strlen(configPath) > MAX_PATH_LEN) { + return DEFAULT_RESERVE_CONFIG_PATH; + } + return configPath; +} + +bool DefaultRecoveryConfig::LoadConfiguration() +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "Load configuration."); + std::string configPath = GetConfigPath(); + TAG_LOGI(AAFwkTag::ABILITYMGR, "Default recovery config path is: %{public}s.", configPath.c_str()); + nlohmann::json jsonBuf; + if (ReadFileInfoJson(configPath, jsonBuf)) { + if (!LoadDefaultRecovery(jsonBuf)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Load configuration failed."); + return false; + } + } + + return true; +} + +bool DefaultRecoveryConfig::IsBundleDefaultRecoveryEnabled(const std::string &bundleName) +{ + if (bundleNameList_.find(bundleName) != bundleNameList_.end()) { + TAG_LOGD(AAFwkTag::ABILITYMGR, "Find bundleName %{public}s.", bundleName.c_str()); + return true; + } + return false; +} + +int32_t DefaultRecoveryConfig::GetReserveNumber() +{ + return reserveNumber_; +} + +int32_t DefaultRecoveryConfig::GetTimeoutDeleteTime() +{ + return timeoutDeleteTime_; +} + +bool DefaultRecoveryConfig::LoadDefaultRecovery(const nlohmann::json &object) +{ + if (!object.contains(ITEM_DEFAULT_RECOVERY_NAME)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Default recovery config not existed."); + return false; + } + + const nlohmann::json &jsonObject = object.at(ITEM_DEFAULT_RECOVERY_NAME); + if (jsonObject.contains(SUPPORT_BUNDLE_NAME_LIST) && jsonObject[SUPPORT_BUNDLE_NAME_LIST].is_array()) { + for (const auto &value : jsonObject.at(SUPPORT_BUNDLE_NAME_LIST)) { + if (value.is_string()) { + auto bundleName = value.get(); + TAG_LOGD(AAFwkTag::ABILITYMGR, "Bundle name is %{public}s.", bundleName.c_str()); + bundleNameList_.emplace(bundleName); + } + } + } + + if (jsonObject.contains(RESERVE_NUMBER_WHEN_TIMEOUT) && jsonObject[RESERVE_NUMBER_WHEN_TIMEOUT].is_number()) { + reserveNumber_ = jsonObject.at(RESERVE_NUMBER_WHEN_TIMEOUT).get(); + } + + if (jsonObject.contains(RECOVERY_DATA_TIMEOUT_DELETE_TIME) && + jsonObject[RECOVERY_DATA_TIMEOUT_DELETE_TIME].is_number()) { + timeoutDeleteTime_ = jsonObject.at(RECOVERY_DATA_TIMEOUT_DELETE_TIME).get(); + } + + return true; +} + +bool DefaultRecoveryConfig::ReadFileInfoJson(const std::string &filePath, nlohmann::json &jsonBuf) +{ + if (access(filePath.c_str(), F_OK) != 0) { + TAG_LOGW(AAFwkTag::ABILITYMGR, "%{public}s, not existed.", filePath.c_str()); + return false; + } + + if (filePath.empty()) { + TAG_LOGW(AAFwkTag::ABILITYMGR, "File path is empty."); + return false; + } + + std::fstream in; + in.open(filePath, std::ios_base::in); + if (!in.is_open()) { + TAG_LOGW(AAFwkTag::ABILITYMGR, "Open file failed with %{public}d.", errno); + return false; + } + + in.seekg(0, std::ios::end); + int64_t size = in.tellg(); + if (size <= 0) { + TAG_LOGW(AAFwkTag::ABILITYMGR, "The file is empty."); + in.close(); + return false; + } + + in.seekg(0, std::ios::beg); + jsonBuf = nlohmann::json::parse(in, nullptr, false); + in.close(); + if (jsonBuf.is_discarded()) { + TAG_LOGW(AAFwkTag::ABILITYMGR, "bad profile file."); + return false; + } + + return true; +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/services/abilitymgr/src/scene_board/ui_ability_lifecycle_manager.cpp b/services/abilitymgr/src/scene_board/ui_ability_lifecycle_manager.cpp index 6c9f64f476..d016da1c81 100644 --- a/services/abilitymgr/src/scene_board/ui_ability_lifecycle_manager.cpp +++ b/services/abilitymgr/src/scene_board/ui_ability_lifecycle_manager.cpp @@ -176,6 +176,7 @@ std::shared_ptr UIAbilityLifecycleManager::CreateAbilityRecord(Ab sptr sessionInfo) const { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + TAG_LOGD(AAFwkTag::ABILITYMGR, "Create ability record."); if (sessionInfo->startSetting != nullptr) { TAG_LOGD(AAFwkTag::ABILITYMGR, "startSetting is valid."); abilityRequest.startSetting = sessionInfo->startSetting; @@ -921,10 +922,12 @@ void UIAbilityLifecycleManager::CallUIAbilityBySCB(const sptr &sess sptr UIAbilityLifecycleManager::CreateSessionInfo(const AbilityRequest &abilityRequest) const { + TAG_LOGD(AAFwkTag::ABILITYMGR, "Create session."); sptr sessionInfo = new SessionInfo(); sessionInfo->callerToken = abilityRequest.callerToken; sessionInfo->want = abilityRequest.want; if (abilityRequest.startSetting != nullptr) { + TAG_LOGD(AAFwkTag::ABILITYMGR, "Assign start setting to session."); sessionInfo->startSetting = abilityRequest.startSetting; } sessionInfo->callingTokenId = static_cast(abilityRequest.want.GetIntParam(Want::PARAM_RESV_CALLER_TOKEN, @@ -1785,18 +1788,23 @@ int32_t UIAbilityLifecycleManager::GetSessionIdByAbilityToken(const sptr &abilityRecord) const { + CHECK_POINTER(abilityRecord); const auto &abilityInfo = abilityRequest.abilityInfo; + std::string abilityName = abilityInfo.name; auto isStandard = abilityInfo.launchMode == AppExecFwk::LaunchMode::STANDARD && !abilityRequest.startRecent; - if (!isStandard) { - bool hasRecoverInfo = false; - (void)DelayedSingleton::GetInstance()-> - GetAbilityRecoverInfo(abilityInfo.applicationInfo.accessTokenId, abilityInfo.moduleName, abilityInfo.name, - hasRecoverInfo); - abilityRecord->UpdateRecoveryInfo(hasRecoverInfo); - (void)DelayedSingleton::GetInstance()-> - DeleteAbilityRecoverInfo(abilityInfo.applicationInfo.accessTokenId, abilityInfo.moduleName, - abilityInfo.name); + if (isStandard && abilityRequest.sessionInfo != nullptr) { + // Support standard launch type. + auto persistentId = abilityRequest.sessionInfo->persistentId; + abilityName += std::to_string(abilityRequest.sessionInfo->persistentId); } + + bool hasRecoverInfo = false; + (void)DelayedSingleton::GetInstance()-> + GetAbilityRecoverInfo(abilityInfo.applicationInfo.accessTokenId, abilityInfo.moduleName, abilityName, + hasRecoverInfo); + abilityRecord->UpdateRecoveryInfo(hasRecoverInfo); + (void)DelayedSingleton::GetInstance()-> + DeleteAbilityRecoverInfo(abilityInfo.applicationInfo.accessTokenId, abilityInfo.moduleName, abilityName); } void UIAbilityLifecycleManager::SetLastExitReason(std::shared_ptr &abilityRecord) const @@ -1812,14 +1820,26 @@ void UIAbilityLifecycleManager::SetLastExitReason(std::shared_ptr return; } + auto sessionInfo = abilityRecord->GetSessionInfo(); + if (sessionInfo == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Session info invalid."); + return; + } + + std::string abilityName = abilityRecord->GetAbilityInfo().name; + if (abilityRecord->GetAbilityInfo().launchMode == AppExecFwk::LaunchMode::STANDARD) { + abilityName += std::to_string(sessionInfo->persistentId); + } + ExitReason exitReason; bool isSetReason; auto accessTokenId = abilityRecord->GetAbilityInfo().applicationInfo.accessTokenId; DelayedSingleton::GetInstance()->GetAppExitReason( - abilityRecord->GetAbilityInfo().bundleName, accessTokenId, abilityRecord->GetAbilityInfo().name, - isSetReason, exitReason); + abilityRecord->GetAbilityInfo().bundleName, accessTokenId, abilityName, isSetReason, exitReason); if (isSetReason) { + TAG_LOGD(AAFwkTag::ABILITYMGR, "Set last exit reason, ability: %{public}s, reason: %{public}d.", + abilityName.c_str(), exitReason.reason); abilityRecord->SetLastExitReason(exitReason); } } @@ -1912,8 +1932,13 @@ void UIAbilityLifecycleManager::GetActiveAbilityList(const std::string &bundleNa } const auto &abilityInfo = abilityRecord->GetAbilityInfo(); if (abilityInfo.bundleName == bundleName && !abilityInfo.name.empty()) { - TAG_LOGD(AAFwkTag::ABILITYMGR, "find ability name is %{public}s", abilityInfo.name.c_str()); - abilityList.push_back(abilityInfo.name); + std::string abilityName = abilityInfo.name; + if (abilityInfo.launchMode == AppExecFwk::LaunchMode::STANDARD && + abilityRecord->GetSessionInfo() != nullptr) { + abilityName += std::to_string(abilityRecord->GetSessionInfo()->persistentId); + } + TAG_LOGD(AAFwkTag::ABILITYMGR, "find ability name is %{public}s.", abilityName.c_str()); + abilityList.push_back(abilityName); } } if (!abilityList.empty()) { @@ -1986,9 +2011,14 @@ void UIAbilityLifecycleManager::UninstallApp(const std::string &bundleName, int3 } auto &abilityInfo = it->second->GetAbilityInfo(); if (abilityInfo.bundleName == bundleName && it->second->GetUid() == uid) { + std::string abilityName = abilityInfo.name; + auto sessionInfo = it->second->GetSessionInfo(); + if (abilityInfo.launchMode == AppExecFwk::LaunchMode::STANDARD && sessionInfo != nullptr) { + abilityName += std::to_string(sessionInfo->persistentId); + } (void)DelayedSingleton::GetInstance()-> DeleteAbilityRecoverInfo(abilityInfo.applicationInfo.accessTokenId, abilityInfo.moduleName, - abilityInfo.name); + abilityName); } it++; } diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 712d1a6123..288279d3c8 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -445,6 +445,7 @@ group("unittest") { "dataobs_mgr_service_test:unittest", "dataobs_mgr_stub_test:unittest", "deeplink_reserve_config_test:unittest", + "default_recovery_config_test:unittest", "dfr_test:unittest", "dlp_state_item_test:unittest", "dlp_utils_test:unittest", diff --git a/test/unittest/app_recovery_test/ability_recovery_test.cpp b/test/unittest/app_recovery_test/ability_recovery_test.cpp index 7f60dc9de5..dcf0c54f53 100644 --- a/test/unittest/app_recovery_test/ability_recovery_test.cpp +++ b/test/unittest/app_recovery_test/ability_recovery_test.cpp @@ -118,7 +118,7 @@ HWTEST_F(AbilityRecoveryUnitTest, GetSaveModeFlag_001, TestSize.Level1) HWTEST_F(AbilityRecoveryUnitTest, EnableAbilityRecovery_001, TestSize.Level1) { EXPECT_FALSE(abilityRecovery_->isEnable_); - abilityRecovery_->EnableAbilityRecovery(RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, + abilityRecovery_->EnableAbilityRecovery(true, RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, SaveModeFlag::SAVE_WITH_FILE); EXPECT_TRUE(abilityRecovery_->isEnable_); } @@ -131,7 +131,7 @@ HWTEST_F(AbilityRecoveryUnitTest, EnableAbilityRecovery_001, TestSize.Level1) */ HWTEST_F(AbilityRecoveryUnitTest, EnableAbilityRecovery_002, TestSize.Level1) { - abilityRecovery_->EnableAbilityRecovery(RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, + abilityRecovery_->EnableAbilityRecovery(true, RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, SaveModeFlag::SAVE_WITH_FILE); EXPECT_EQ(RestartFlag::ALWAYS_RESTART, abilityRecovery_->GetRestartFlag()); EXPECT_EQ(SaveOccasionFlag::SAVE_WHEN_ERROR, abilityRecovery_->GetSaveOccasionFlag()); @@ -146,7 +146,7 @@ HWTEST_F(AbilityRecoveryUnitTest, EnableAbilityRecovery_002, TestSize.Level1) */ HWTEST_F(AbilityRecoveryUnitTest, EnableAbilityRecovery_003, TestSize.Level1) { - abilityRecovery_->EnableAbilityRecovery(RestartFlag::NO_RESTART, SaveOccasionFlag::SAVE_ALL, + abilityRecovery_->EnableAbilityRecovery(true, RestartFlag::NO_RESTART, SaveOccasionFlag::SAVE_ALL, SaveModeFlag::SAVE_WITH_SHARED_MEMORY); EXPECT_EQ(RestartFlag::NO_RESTART, abilityRecovery_->GetRestartFlag()); EXPECT_EQ(SaveOccasionFlag::SAVE_ALL, abilityRecovery_->GetSaveOccasionFlag()); @@ -172,7 +172,7 @@ HWTEST_F(AbilityRecoveryUnitTest, InitAbilityInfo_001, TestSize.Level1) */ HWTEST_F(AbilityRecoveryUnitTest, IsSaveAbilityState_001, TestSize.Level1) { - abilityRecovery_->EnableAbilityRecovery(RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, + abilityRecovery_->EnableAbilityRecovery(true, RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, SaveModeFlag::SAVE_WITH_FILE); EXPECT_FALSE(abilityRecovery_->IsSaveAbilityState(StateReason::LIFECYCLE)); } @@ -185,7 +185,7 @@ HWTEST_F(AbilityRecoveryUnitTest, IsSaveAbilityState_001, TestSize.Level1) */ HWTEST_F(AbilityRecoveryUnitTest, IsSaveAbilityState_002, TestSize.Level1) { - abilityRecovery_->EnableAbilityRecovery(RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_BACKGROUND, + abilityRecovery_->EnableAbilityRecovery(true, RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_BACKGROUND, SaveModeFlag::SAVE_WITH_FILE); EXPECT_FALSE(abilityRecovery_->IsSaveAbilityState(StateReason::CPP_CRASH)); EXPECT_FALSE(abilityRecovery_->IsSaveAbilityState(StateReason::JS_ERROR)); @@ -200,7 +200,7 @@ HWTEST_F(AbilityRecoveryUnitTest, IsSaveAbilityState_002, TestSize.Level1) */ HWTEST_F(AbilityRecoveryUnitTest, IsSaveAbilityState_003, TestSize.Level1) { - abilityRecovery_->EnableAbilityRecovery(RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_BACKGROUND, + abilityRecovery_->EnableAbilityRecovery(true, RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_BACKGROUND, SaveModeFlag::SAVE_WITH_FILE); EXPECT_TRUE(abilityRecovery_->IsSaveAbilityState(StateReason::DEVELOPER_REQUEST)); EXPECT_TRUE(abilityRecovery_->IsSaveAbilityState(StateReason::LIFECYCLE)); @@ -214,7 +214,7 @@ HWTEST_F(AbilityRecoveryUnitTest, IsSaveAbilityState_003, TestSize.Level1) */ HWTEST_F(AbilityRecoveryUnitTest, IsSaveAbilityState_004, TestSize.Level1) { - abilityRecovery_->EnableAbilityRecovery(RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, + abilityRecovery_->EnableAbilityRecovery(true, RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, SaveModeFlag::SAVE_WITH_FILE); EXPECT_TRUE(abilityRecovery_->IsSaveAbilityState(StateReason::CPP_CRASH)); EXPECT_TRUE(abilityRecovery_->IsSaveAbilityState(StateReason::JS_ERROR)); @@ -240,7 +240,7 @@ HWTEST_F(AbilityRecoveryUnitTest, ScheduleSaveAbilityState_001, TestSize.Level1) */ HWTEST_F(AbilityRecoveryUnitTest, ScheduleSaveAbilityState_002, TestSize.Level1) { - abilityRecovery_->EnableAbilityRecovery(RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, + abilityRecovery_->EnableAbilityRecovery(true, RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, SaveModeFlag::SAVE_WITH_FILE); EXPECT_FALSE(abilityRecovery_->ScheduleSaveAbilityState(StateReason::LIFECYCLE)); } @@ -291,11 +291,11 @@ HWTEST_F(AbilityRecoveryUnitTest, SaveAbilityState_003, TestSize.Level1) */ HWTEST_F(AbilityRecoveryUnitTest, SaveAbilityState_004, TestSize.Level1) { - abilityRecovery_->EnableAbilityRecovery(RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, + abilityRecovery_->EnableAbilityRecovery(true, RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, SaveModeFlag::SAVE_WITH_FILE); abilityRecovery_->ability_ = mockAbility_; EXPECT_TRUE(abilityRecovery_->SaveAbilityState()); - abilityRecovery_->EnableAbilityRecovery(RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, + abilityRecovery_->EnableAbilityRecovery(true, RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, SaveModeFlag::SAVE_WITH_SHARED_MEMORY); EXPECT_TRUE(abilityRecovery_->SaveAbilityState()); } @@ -319,7 +319,7 @@ HWTEST_F(AbilityRecoveryUnitTest, ScheduleRecoverAbility_001, TestSize.Level1) */ HWTEST_F(AbilityRecoveryUnitTest, ScheduleRecoverAbility_002, TestSize.Level1) { - abilityRecovery_->EnableAbilityRecovery(RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, + abilityRecovery_->EnableAbilityRecovery(true, RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, SaveModeFlag::SAVE_WITH_FILE); token_ = nullptr; EXPECT_FALSE(abilityRecovery_->ScheduleRecoverAbility(StateReason::DEVELOPER_REQUEST)); @@ -333,7 +333,7 @@ HWTEST_F(AbilityRecoveryUnitTest, ScheduleRecoverAbility_002, TestSize.Level1) */ HWTEST_F(AbilityRecoveryUnitTest, ScheduleRecoverAbility_003, TestSize.Level1) { - abilityRecovery_->EnableAbilityRecovery(RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, + abilityRecovery_->EnableAbilityRecovery(true, RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, SaveModeFlag::SAVE_WITH_FILE); token_ = new MockAbilityToken(); abilityRecovery_->token_ = token_; @@ -359,7 +359,7 @@ HWTEST_F(AbilityRecoveryUnitTest, ScheduleRestoreAbilityState_001, TestSize.Leve */ HWTEST_F(AbilityRecoveryUnitTest, ScheduleRestoreAbilityState_002, TestSize.Level1) { - abilityRecovery_->EnableAbilityRecovery(RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, + abilityRecovery_->EnableAbilityRecovery(true, RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, SaveModeFlag::SAVE_WITH_FILE); EXPECT_FALSE(abilityRecovery_->ScheduleRestoreAbilityState(StateReason::LIFECYCLE, want_)); } @@ -372,7 +372,7 @@ HWTEST_F(AbilityRecoveryUnitTest, ScheduleRestoreAbilityState_002, TestSize.Leve */ HWTEST_F(AbilityRecoveryUnitTest, ScheduleRestoreAbilityState_003, TestSize.Level1) { - abilityRecovery_->EnableAbilityRecovery(RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, + abilityRecovery_->EnableAbilityRecovery(true, RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, SaveModeFlag::SAVE_WITH_FILE); abilityRecovery_->abilityInfo_.reset(); EXPECT_FALSE(abilityRecovery_->ScheduleRestoreAbilityState(StateReason::CPP_CRASH, want_)); @@ -385,7 +385,7 @@ HWTEST_F(AbilityRecoveryUnitTest, ScheduleRestoreAbilityState_003, TestSize.Leve */ HWTEST_F(AbilityRecoveryUnitTest, ScheduleRestoreAbilityState_004, TestSize.Level1) { - abilityRecovery_->EnableAbilityRecovery(RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, + abilityRecovery_->EnableAbilityRecovery(true, RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, SaveModeFlag::SAVE_WITH_SHARED_MEMORY); abilityRecovery_->hasTryLoad_ = true; abilityRecovery_->hasLoaded_ = true; @@ -437,7 +437,7 @@ HWTEST_F(AbilityRecoveryUnitTest, LoadSavedState_003, TestSize.Level1) HWTEST_F(AbilityRecoveryUnitTest, GetSavedPageStack_001, TestSize.Level1) { abilityRecovery_->hasTryLoad_ = true; - abilityRecovery_->EnableAbilityRecovery(RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, + abilityRecovery_->EnableAbilityRecovery(true, RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, SaveModeFlag::SAVE_WITH_SHARED_MEMORY); EXPECT_EQ(abilityRecovery_->GetSavedPageStack(StateReason::DEVELOPER_REQUEST), ""); } @@ -452,7 +452,7 @@ HWTEST_F(AbilityRecoveryUnitTest, GetSavedPageStack_002, TestSize.Level1) { abilityRecovery_->hasTryLoad_ = true; abilityRecovery_->hasLoaded_ = true; - abilityRecovery_->EnableAbilityRecovery(RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, + abilityRecovery_->EnableAbilityRecovery(true, RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, SaveModeFlag::SAVE_WITH_SHARED_MEMORY); EXPECT_EQ(abilityRecovery_->GetSavedPageStack(StateReason::DEVELOPER_REQUEST), ""); } @@ -468,7 +468,7 @@ HWTEST_F(AbilityRecoveryUnitTest, GetSavedPageStack_003, TestSize.Level1) abilityRecovery_->hasTryLoad_ = true; abilityRecovery_->hasLoaded_ = true; abilityRecovery_->pageStack_ = "test"; - abilityRecovery_->EnableAbilityRecovery(RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, + abilityRecovery_->EnableAbilityRecovery(true, RestartFlag::ALWAYS_RESTART, SaveOccasionFlag::SAVE_WHEN_ERROR, SaveModeFlag::SAVE_WITH_SHARED_MEMORY); EXPECT_EQ(abilityRecovery_->GetSavedPageStack(StateReason::DEVELOPER_REQUEST), "test"); } diff --git a/test/unittest/app_recovery_test/app_recovery_test.cpp b/test/unittest/app_recovery_test/app_recovery_test.cpp index fd7c63b68b..b242f2dc5a 100644 --- a/test/unittest/app_recovery_test/app_recovery_test.cpp +++ b/test/unittest/app_recovery_test/app_recovery_test.cpp @@ -177,7 +177,7 @@ HWTEST_F(AppRecoveryUnitTest, AddAbility_001, TestSize.Level1) { AppRecovery::GetInstance().isEnable_ = false; bool ret = AppRecovery::GetInstance().AddAbility(ability_, abilityInfo_, token_); - EXPECT_FALSE(ret); + EXPECT_TRUE(ret); } /** @@ -231,7 +231,7 @@ HWTEST_F(AppRecoveryUnitTest, RemoveAbility_002, TestSize.Level1) { AppRecovery::GetInstance().isEnable_ = false; bool ret = AppRecovery::GetInstance().RemoveAbility(token_); - EXPECT_FALSE(ret); + EXPECT_TRUE(ret); } /** diff --git a/test/unittest/default_recovery_config_test/BUILD.gn b/test/unittest/default_recovery_config_test/BUILD.gn new file mode 100755 index 0000000000..e75cf5e5a5 --- /dev/null +++ b/test/unittest/default_recovery_config_test/BUILD.gn @@ -0,0 +1,47 @@ +# 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. + +import("//build/test.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +module_output_path = "ability_runtime/abilityms" + +ohos_unittest("default_recovery_config_test") { + module_out_path = module_output_path + + include_dirs = + [ "${ability_runtime_services_path}/abilitymgr/include/app_recovery" ] + + sources = [ + "${ability_runtime_services_path}/abilitymgr/src/app_recovery/default_recovery_config.cpp", + "default_recovery_config_test.cpp", + ] + + configs = [ "${ability_runtime_services_path}/abilitymgr:abilityms_config" ] + + deps = [ + "${ability_runtime_services_path}/abilitymgr:abilityms", + "//third_party/googletest:gmock_main", + ] + + external_deps = [ + "c_utils:utils", + "config_policy:configpolicy_util", + "hilog:libhilog", + ] +} + +group("unittest") { + testonly = true + deps = [ ":default_recovery_config_test" ] +} diff --git a/test/unittest/default_recovery_config_test/default_recovery_config_test.cpp b/test/unittest/default_recovery_config_test/default_recovery_config_test.cpp new file mode 100755 index 0000000000..2b74f9df5b --- /dev/null +++ b/test/unittest/default_recovery_config_test/default_recovery_config_test.cpp @@ -0,0 +1,99 @@ +/* + * 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 + +#include "gtest/gtest.h" +#include "hilog_tag_wrapper.h" +#define private public +#define protected public +#include "default_recovery_config.h" +#undef private +#undef protected + +using namespace testing::ext; + +namespace OHOS { +namespace AbilityRuntime { +class DefaultRecoveryConfigTest : public testing::Test { +public: + DefaultRecoveryConfigTest() = default; + virtual ~DefaultRecoveryConfigTest() = default; + + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DefaultRecoveryConfigTest::SetUpTestCase(void) +{} + +void DefaultRecoveryConfigTest::TearDownTestCase(void) +{} + +void DefaultRecoveryConfigTest::SetUp() +{} + +void DefaultRecoveryConfigTest::TearDown() +{} + +/** + * @tc.name: LoadConfiguration_0100 + * @tc.desc: basic function test of load configuration. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(DefaultRecoveryConfigTest, LoadConfiguration_0100, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "begin."); + DefaultRecoveryConfig config; + EXPECT_EQ(config.LoadConfiguration(), true); + EXPECT_EQ(config.IsBundleDefaultRecoveryEnabled("com.acts.test"), false); + EXPECT_EQ(config.GetReserveNumber(), 5); + EXPECT_EQ(config.GetTimeoutDeleteTime(), 168); + TAG_LOGI(AAFwkTag::TEST, "end."); +} + +/** + * @tc.name: LoadConfiguration_0200 + * @tc.desc: basic function test of load configuration. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(DefaultRecoveryConfigTest, LoadConfiguration_0200, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "begin."); + DefaultRecoveryConfig config; + const nlohmann::json DEFAULT_CONFIG = R"( + { + "default_recovery": { + "support_bundle_name_list": [ + "com.acts.example1", + "com.acts.example2" + ], + "reserve_number_when_timeout": 10, + "recovery_data_timeout_delete_time": 7 + } + } + )"_json; + config.LoadDefaultRecovery(DEFAULT_CONFIG); + EXPECT_EQ(config.IsBundleDefaultRecoveryEnabled("com.acts.example1"), true); + EXPECT_EQ(config.IsBundleDefaultRecoveryEnabled("com.acts.example2"), true); + EXPECT_EQ(config.GetReserveNumber(), 10); + EXPECT_EQ(config.GetTimeoutDeleteTime(), 7); + TAG_LOGI(AAFwkTag::TEST, "end."); +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/test/unittest/frameworks_kits_ability_native_test/ui_ability_test.cpp b/test/unittest/frameworks_kits_ability_native_test/ui_ability_test.cpp index 95e0640ce3..b5a7c73877 100644 --- a/test/unittest/frameworks_kits_ability_native_test/ui_ability_test.cpp +++ b/test/unittest/frameworks_kits_ability_native_test/ui_ability_test.cpp @@ -368,7 +368,7 @@ HWTEST_F(UIAbilityBaseTest, AbilityRuntime_OnStop_0300, TestSize.Level1) ASSERT_NE(ability, nullptr); auto abilityRecovery = std::make_shared(); EXPECT_NE(abilityRecovery, nullptr); - ability->EnableAbilityRecovery(abilityRecovery); + ability->EnableAbilityRecovery(abilityRecovery, false); ability->OnStop(); // window is not nullptr @@ -683,7 +683,7 @@ HWTEST_F(UIAbilityBaseTest, UIAbilityContinuation_0200, TestSize.Level1) EXPECT_EQ(ret, false); ability->HandleCreateAsRecovery(want); auto abilityRecovery = std::make_shared(); - ability->EnableAbilityRecovery(abilityRecovery); + ability->EnableAbilityRecovery(abilityRecovery, false); // branch when abilityContext_ is nullptr want.SetParam(Want::PARAM_ABILITY_RECOVERY_RESTART, true); @@ -877,7 +877,7 @@ HWTEST_F(UIAbilityBaseTest, UIAbilityFuncList_0100, TestSize.Level1) bool isNewRule = ability->IsUseNewStartUpRule(); EXPECT_EQ(isNewRule, true); auto abilityRecovery = std::make_shared(); - ability->EnableAbilityRecovery(abilityRecovery); + ability->EnableAbilityRecovery(abilityRecovery, false); TAG_LOGI(AAFwkTag::TEST, "%{public}s end.", __func__); } diff --git a/tools/aa/include/ability_command.h b/tools/aa/include/ability_command.h index e5818f9d6a..6758c334f3 100644 --- a/tools/aa/include/ability_command.h +++ b/tools/aa/include/ability_command.h @@ -153,7 +153,7 @@ const std::string HELP_MSG_APPDEBUG_APP_DEBUG = " -c, --cancel let application cancel wait debug\n" " -g, --get get wait debug mode application bundle name and persist flag\n"; -const std::string HELP_MSG_FORCE_STOP = "usage: aa force-stop \n"; +const std::string HELP_MSG_FORCE_STOP = "usage: aa force-stop [-p pid] [-r kill-reason]\n"; const std::string HELP_MSG_BLOCK_ABILITY = "usage: aa block-ability \n"; const std::string HELP_MSG_FORCE_TIMEOUT = "usage: aa force-timeout \n" @@ -247,6 +247,9 @@ private: void SetParams(const ParametersInteger& pi, Want& want); void SetParams(const ParametersString& ps, Want& want); void SetParams(const ParametersBool& pb, Want& want); + Reason CovertExitReason(std::string& reasonStr); + pid_t ConvertPid(std::string& inputPid); + #ifdef ABILITY_COMMAND_FOR_TEST ErrCode RunForceTimeoutForTest(); ErrCode RunAsSendAppNotRespondingProcessID(); diff --git a/tools/aa/src/ability_command.cpp b/tools/aa/src/ability_command.cpp index 93a72592f0..5a62af494a 100644 --- a/tools/aa/src/ability_command.cpp +++ b/tools/aa/src/ability_command.cpp @@ -36,6 +36,7 @@ namespace OHOS { namespace AAFwk { namespace { constexpr size_t PARAM_LENGTH = 1024; +constexpr int INDEX_OFFSET = 3; constexpr int EXTRA_ARGUMENTS_FOR_KEY_VALUE_PAIR = 1; constexpr int EXTRA_ARGUMENTS_FOR_NULL_STRING = 0; constexpr int OPTION_PARAMETER_VALUE_OFFSET = 1; @@ -710,14 +711,47 @@ ErrCode AbilityManagerShellCommand::RunAsDumpsysCommand() ErrCode AbilityManagerShellCommand::RunAsForceStop() { - TAG_LOGI(AAFwkTag::AA_TOOL, "[%{public}s(%{public}s)] enter", __FILE__, __FUNCTION__); + TAG_LOGI(AAFwkTag::AA_TOOL, "enter"); if (argList_.empty()) { - resultReceiver_.append(HELP_MSG_FORCE_STOP + "\n"); + resultReceiver_.append(HELP_MSG_FORCE_STOP); return OHOS::ERR_INVALID_VALUE; } - TAG_LOGI(AAFwkTag::AA_TOOL, "Bundle name : %{public}s", argList_[0].c_str()); + std::string bundleName = argList_[0]; + TAG_LOGI(AAFwkTag::AA_TOOL, "Bundle name %{public}s", bundleName.c_str()); + + auto killReason = Reason::REASON_UNKNOWN; + pid_t pid = 0; + for (auto index = INDEX_OFFSET; index < argc_; ++index) { + TAG_LOGD(AAFwkTag::AA_TOOL, "argv_[%{public}d]: %{public}s.", index, argv_[index]); + std::string opt = argv_[index]; + if (opt == "-p") { + index++; + if (index <= argc_) { + TAG_LOGD(AAFwkTag::AA_TOOL, "argv_[%{public}d]: %{public}s.", index, argv_[index]); + std::string inputPid = argv_[index]; + pid = ConvertPid(inputPid); + } + } else if (opt == "-r") { + index++; + if (index <= argc_) { + TAG_LOGD(AAFwkTag::AA_TOOL, "argv_[%{public}d]: %{public}s.", index, argv_[index]); + std::string inputReason = argv_[index]; + killReason = CovertExitReason(inputReason); + } + } + } + + TAG_LOGI(AAFwkTag::AA_TOOL, "pid %{public}d, reason %{public}d.", pid, killReason); + if (pid != 0 && killReason != Reason::REASON_UNKNOWN) { + ExitReason exitReason = {killReason, "aa force-stop"}; + if (AbilityManagerClient::GetInstance()->RecordProcessExitReason(pid, exitReason) != ERR_OK) { + TAG_LOGE(AAFwkTag::AA_TOOL, "bundle %{public}s record reason %{public}d failed.", + bundleName.c_str(), killReason); + } + } + ErrCode result = OHOS::ERR_OK; - result = AbilityManagerClient::GetInstance()->KillProcess(argList_[0]); + result = AbilityManagerClient::GetInstance()->KillProcess(bundleName); if (result == OHOS::ERR_OK) { TAG_LOGI(AAFwkTag::AA_TOOL, "%{public}s", STRING_FORCE_STOP_OK.c_str()); resultReceiver_ = STRING_FORCE_STOP_OK + "\n"; @@ -729,6 +763,44 @@ ErrCode AbilityManagerShellCommand::RunAsForceStop() return result; } +Reason AbilityManagerShellCommand::CovertExitReason(std::string& reasonStr) +{ + if (reasonStr.empty()) { + return Reason::REASON_UNKNOWN; + } + + if (reasonStr.compare("UNKNOWN") == 0) { + return Reason::REASON_UNKNOWN; + } else if (reasonStr.compare("NORMAL") == 0) { + return Reason::REASON_NORMAL; + } else if (reasonStr.compare("CPP_CRASH") == 0) { + return Reason::REASON_CPP_CRASH; + } else if (reasonStr.compare("JS_ERROR") == 0) { + return Reason::REASON_JS_ERROR; + } else if (reasonStr.compare("APP_FREEZE") == 0) { + return Reason::REASON_APP_FREEZE; + } else if (reasonStr.compare("PERFORMANCE_CONTROL") == 0) { + return Reason::REASON_PERFORMANCE_CONTROL; + } else if (reasonStr.compare("RESOURCE_CONTROL") == 0) { + return Reason::REASON_RESOURCE_CONTROL; + } else if (reasonStr.compare("UPGRADE") == 0) { + return Reason::REASON_UPGRADE; + } + + return Reason::REASON_UNKNOWN; +} + +pid_t AbilityManagerShellCommand::ConvertPid(std::string& inputPid) +{ + pid_t pid = 0; + try { + pid = static_cast(std::stoi(inputPid)); + } catch (...) { + TAG_LOGW(AAFwkTag::AA_TOOL, "pid stoi(%{public}s) failed.", inputPid.c_str()); + } + return pid; +} + ErrCode AbilityManagerShellCommand::RunAsAttachDebugCommand() { TAG_LOGD(AAFwkTag::AA_TOOL, "Called.");