Support recovery when background.

Signed-off-by: zhangyafei-echo <zhangyafei12@huawei.com>
Change-Id: I0e000924ab5fa17ad59d998c573e41177803a562
This commit is contained in:
zhangyafei-echo 2024-06-01 19:05:59 +08:00
parent 9434023218
commit b00ac99924
34 changed files with 789 additions and 75 deletions

View File

@ -150,7 +150,7 @@ aa start -d 12345 -a com.ohos.app.MainAbility -b com.ohos.app -D
| 命令 | 描述 |
| -------------------------------------------------------------- | ------------------------ |
| aa force-stop <bundle-name> | 强制停止application |
| aa force-stop <bundle-name> [-p <pid>] [-r <kill-reason>] | 强制停止application支持传递pid和进程退出原因 |
```
示例:

View File

@ -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) { }
}

View File

@ -211,6 +211,10 @@ class AbilityContext extends Context {
moveAbilityToBackground(callback) {
return this.__context_impl__.moveAbilityToBackground(callback);
}
setRestoreEnabled(enabled) {
this.__context_impl__.setRestoreEnabled(enabled);
}
}
export default AbilityContext;

View File

@ -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

View File

@ -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>& abilityContext, const std::shared_ptr<CallerCallBack> &callback)
{
@ -1616,6 +1621,7 @@ napi_value CreateJsAbilityContext(napi_env env, std::shared_ptr<AbilityContext>
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

View File

@ -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();
}
}

View File

@ -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_ptr<AbilityRuntime::UIAb
return true;
}
void AbilityRecovery::EnableAbilityRecovery(uint16_t restartFlag, uint16_t saveFlag, uint16_t saveMode)
void AbilityRecovery::EnableAbilityRecovery(bool useAppSettedValue, uint16_t restartFlag, uint16_t saveFlag,
uint16_t saveMode)
{
isEnable_ = true;
restartFlag_ = restartFlag;
saveOccasion_ = saveFlag;
useAppSettedValue_.store(useAppSettedValue);
saveOccasion_ = useAppSettedValue ? saveFlag : SaveOccasionFlag::SAVE_WHEN_BACKGROUND;
saveMode_ = saveMode;
}
@ -102,6 +107,7 @@ void AbilityRecovery::SetJsAbility(uintptr_t ability)
bool AbilityRecovery::SaveAbilityState()
{
HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
TAG_LOGD(AAFwkTag::RECOVERY, "SaveAbilityState begin");
auto ability = ability_.lock();
auto abilityInfo = abilityInfo_.lock();
@ -118,12 +124,14 @@ bool AbilityRecovery::SaveAbilityState()
}
#ifdef SUPPORT_SCREEN
std::string pageStack = ability->GetContentInfo();
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<uint8_t*>(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

View File

@ -116,20 +116,20 @@ bool AppRecovery::InitApplicationInfo(const std::shared_ptr<EventHandler>& mainH
bool AppRecovery::AddAbility(std::shared_ptr<AbilityRuntime::UIAbility> ability,
const std::shared_ptr<AbilityInfo>& abilityInfo, const sptr<IRemoteObject>& 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> abilityRecovery = std::make_shared<AbilityRecovery>();
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<AbilityRuntime::UIAbility> ability,
bool AppRecovery::RemoveAbility(const sptr<IRemoteObject>& 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)

View File

@ -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<AppExecFwk::AbilityRecovery> &abilityRecovery)
void UIAbility::EnableAbilityRecovery(const std::shared_ptr<AppExecFwk::AbilityRecovery> &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<Rosen::IWindowLifeCycle> &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

View File

@ -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.

View File

@ -340,6 +340,9 @@ public:
virtual void UnregisterAbilityLifecycleObserver(
const std::shared_ptr<AppExecFwk::ILifecycleObserver> &observer) = 0;
virtual void SetRestoreEnabled(bool enabled) = 0;
virtual bool GetRestoreEnabled() = 0;
#ifdef SUPPORT_GRAPHICS
#ifdef SUPPORT_SCREEN
/**

View File

@ -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<IRemoteObject> sessionToken_;
std::mutex uiExtensionMutex_;
std::map<int32_t, Want> uiExtensionMap_;
std::atomic<bool> restoreEnabled_ = true;
static void RequestDialogResultJSThreadWorker(uv_work_t* work, int status);
void OnAbilityResultInner(int requestCode, int resultCode, const AAFwk::Want &resultData);

View File

@ -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<NativeReference> &jsContext,
const std::shared_ptr<AppExecFwk::Configuration> &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);

View File

@ -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<AbilityRuntime::UIAbility> ability,
const std::shared_ptr<AbilityInfo> &abilityInfo, const sptr<IRemoteObject> &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<bool> useAppSettedValue_ = false; // If the value is true means app call appRecovery.enableAppRecovery
};
} // namespace AbilityRuntime
} // namespace OHOS

View File

@ -74,6 +74,7 @@ private:
std::weak_ptr<AbilityRuntime::UIAbility> ability_;
std::vector<std::shared_ptr<AbilityRecovery>> abilityRecoverys_;
std::shared_ptr<AAFwk::Want> want_ = nullptr;
std::atomic<bool> useAppSettedValue_ = false; // If the value is true means app call appRecovery.enableAppRecovery
};
} // namespace AbilityRuntime
} // namespace OHOS

View File

@ -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<AppExecFwk::AbilityRecovery> &abilityRecovery);
void EnableAbilityRecovery(const std::shared_ptr<AppExecFwk::AbilityRecovery> &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<AbilityRuntime::AbilityContext> abilityContext_ = nullptr;
@ -355,6 +358,7 @@ private:
bool isNewRuleFlagSetted_ = false;
bool startUpNewRule_ = false;
bool isSilentForeground_ = false;
std::atomic<bool> 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<Rosen::WindowOption> GetWindowOption(const AAFwk::Want &want);
virtual void ContinuationRestore(const AAFwk::Want &want);
bool CheckRecoveryEnabled();
bool CheckDefaultRecoveryEnabled();
bool IsStartByScb();
std::shared_ptr<Rosen::WindowScene> scene_ = nullptr;
sptr<Rosen::IWindowLifeCycle> sceneListener_ = nullptr;

View File

@ -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",
]
}

View File

@ -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",

View File

@ -2132,6 +2132,7 @@ private:
void InitInterceptor();
void InitPushTask();
void InitDeepLinkReserve();
void InitDefaultRecoveryList();
bool CheckSenderWantInfo(int32_t callerUid, const WantSenderInfo &wantSenderInfo);

View File

@ -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 <nlohmann/json.hpp>
#include <string>
#include <unordered_set>
#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<std::string> 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

View File

@ -0,0 +1,7 @@
{
"default_recovery": {
"support_bundle_name_list": [],
"reserve_number_when_timeout": 5,
"recovery_data_timeout_delete_time": 168
}
}

View File

@ -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<AbilityRuntime::AbilityAutoStartupService>();
#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<AbilityInterceptorExecuter>();
@ -1988,6 +1997,19 @@ int AbilityManagerService::StartUIAbilityBySCB(sptr<SessionInfo> 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<uint32_t>(sessionInfo->want.GetIntParam(SPECIFY_TOKEN_ID, 0));
(sessionInfo->want).RemoveParam(SPECIFY_TOKEN_ID);
@ -2035,6 +2057,8 @@ int AbilityManagerService::StartUIAbilityBySCB(sptr<SessionInfo> 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<SessionInfo> &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<AbilityRuntime::AppExitReasonDataManager>::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<AbilityStartSetting>(*(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<IRemoteObject> &tok
#endif // SUPPORT_SCREEN
void AbilityManagerService::EnableRecoverAbility(const sptr<IRemoteObject>& token)
{
TAG_LOGD(AAFwkTag::ABILITYMGR, "Enable recovery ability.");
if (token == nullptr) {
return;
}
@ -7127,9 +7166,13 @@ void AbilityManagerService::EnableRecoverAbility(const sptr<IRemoteObject>& 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<AbilityRuntime::AppExitReasonDataManager>::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) {

View File

@ -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;
/**

View File

@ -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<std::mutex> lock(kvStorePtrMutex_);
if (!CheckKvStore()) {

View File

@ -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 <fstream>
#include <sstream>
#include <unistd.h>
#include <regex>
#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<std::string>();
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<int32_t>();
}
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<int32_t>();
}
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

View File

@ -176,6 +176,7 @@ std::shared_ptr<AbilityRecord> UIAbilityLifecycleManager::CreateAbilityRecord(Ab
sptr<SessionInfo> 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<SessionInfo> &sess
sptr<SessionInfo> UIAbilityLifecycleManager::CreateSessionInfo(const AbilityRequest &abilityRequest) const
{
TAG_LOGD(AAFwkTag::ABILITYMGR, "Create session.");
sptr<SessionInfo> 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<uint32_t>(abilityRequest.want.GetIntParam(Want::PARAM_RESV_CALLER_TOKEN,
@ -1785,18 +1788,23 @@ int32_t UIAbilityLifecycleManager::GetSessionIdByAbilityToken(const sptr<IRemote
void UIAbilityLifecycleManager::SetRevicerInfo(const AbilityRequest &abilityRequest,
std::shared_ptr<AbilityRecord> &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) {
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<AbilityRuntime::AppExitReasonDataManager>::GetInstance()->
GetAbilityRecoverInfo(abilityInfo.applicationInfo.accessTokenId, abilityInfo.moduleName, abilityInfo.name,
GetAbilityRecoverInfo(abilityInfo.applicationInfo.accessTokenId, abilityInfo.moduleName, abilityName,
hasRecoverInfo);
abilityRecord->UpdateRecoveryInfo(hasRecoverInfo);
(void)DelayedSingleton<AbilityRuntime::AppExitReasonDataManager>::GetInstance()->
DeleteAbilityRecoverInfo(abilityInfo.applicationInfo.accessTokenId, abilityInfo.moduleName,
abilityInfo.name);
}
DeleteAbilityRecoverInfo(abilityInfo.applicationInfo.accessTokenId, abilityInfo.moduleName, abilityName);
}
void UIAbilityLifecycleManager::SetLastExitReason(std::shared_ptr<AbilityRecord> &abilityRecord) const
@ -1812,14 +1820,26 @@ void UIAbilityLifecycleManager::SetLastExitReason(std::shared_ptr<AbilityRecord>
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<AbilityRuntime::AppExitReasonDataManager>::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<AbilityRuntime::AppExitReasonDataManager>::GetInstance()->
DeleteAbilityRecoverInfo(abilityInfo.applicationInfo.accessTokenId, abilityInfo.moduleName,
abilityInfo.name);
abilityName);
}
it++;
}

View File

@ -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",

View File

@ -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");
}

View File

@ -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);
}
/**

View File

@ -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" ]
}

View File

@ -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 <memory>
#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

View File

@ -368,7 +368,7 @@ HWTEST_F(UIAbilityBaseTest, AbilityRuntime_OnStop_0300, TestSize.Level1)
ASSERT_NE(ability, nullptr);
auto abilityRecovery = std::make_shared<AbilityRecovery>();
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<AbilityRecovery>();
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<AbilityRecovery>();
ability->EnableAbilityRecovery(abilityRecovery);
ability->EnableAbilityRecovery(abilityRecovery, false);
TAG_LOGI(AAFwkTag::TEST, "%{public}s end.", __func__);
}

View File

@ -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 <bundle-name>\n";
const std::string HELP_MSG_FORCE_STOP = "usage: aa force-stop <bundle-name> [-p pid] [-r kill-reason]\n";
const std::string HELP_MSG_BLOCK_ABILITY = "usage: aa block-ability <abilityrecordid>\n";
const std::string HELP_MSG_FORCE_TIMEOUT =
"usage: aa force-timeout <ability-name> <INITIAL|INACTIVE|COMMAND|FOREGROUND|BACKGROUND|TERMINATING>\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();

View File

@ -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<pid_t>(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.");