From 0e8182356e357cf8a2f69dc71b51c9727201cc59 Mon Sep 17 00:00:00 2001 From: savior-xzh Date: Wed, 28 Feb 2024 11:21:51 +0000 Subject: [PATCH] add restartApp Signed-off-by: savior-xzh Change-Id: I00e5fb273c0d56b4b569e366a94b13fcda536859 --- .../application_context.js | 4 + .../ability_business_error.cpp | 7 ++ frameworks/native/appkit/BUILD.gn | 2 + .../context/application_context.cpp | 13 +++ .../ability_runtime/context/context_impl.cpp | 8 ++ .../context/js_application_context_utils.cpp | 46 +++++++++ .../include/ability_manager_client.h | 7 ++ .../include/ability_manager_errors.h | 10 ++ .../include/ability_manager_interface.h | 10 ++ .../ability_manager_ipc_interface_code.h | 3 + .../include/appmgr/app_mgr_interface.h | 5 + .../appmgr/app_mgr_ipc_interface_code.h | 1 + .../include/appmgr/app_mgr_proxy.h | 1 + .../app_manager/include/appmgr/app_mgr_stub.h | 1 + .../app_manager/src/appmgr/app_mgr_proxy.cpp | 22 +++++ .../app_manager/src/appmgr/app_mgr_stub.cpp | 14 +++ .../include/ability_runtime_error_util.h | 2 + .../src/ability_runtime_error_util.cpp | 6 +- .../ability_business_error.h | 6 ++ .../context/application_context.h | 4 + .../ability_runtime/context/context_impl.h | 10 ++ .../context/js_application_context_utils.h | 2 + services/abilitymgr/abilitymgr.gni | 1 + .../include/ability_connect_manager.h | 2 + .../include/ability_manager_proxy.h | 6 ++ .../include/ability_manager_service.h | 10 ++ .../abilitymgr/include/ability_manager_stub.h | 1 + services/abilitymgr/include/ability_record.h | 4 + services/abilitymgr/include/mission_list.h | 2 + .../abilitymgr/include/mission_list_manager.h | 2 + .../abilitymgr/include/restart_app_manager.h | 72 ++++++++++++++ .../ui_ability_lifecycle_manager.h | 2 + .../src/ability_connect_manager.cpp | 11 +++ .../abilitymgr/src/ability_manager_client.cpp | 9 ++ .../abilitymgr/src/ability_manager_proxy.cpp | 21 +++++ .../src/ability_manager_service.cpp | 94 +++++++++++++++++++ .../abilitymgr/src/ability_manager_stub.cpp | 18 ++++ services/abilitymgr/src/ability_record.cpp | 12 ++- services/abilitymgr/src/mission_list.cpp | 17 ++++ .../abilitymgr/src/mission_list_manager.cpp | 18 +++- .../abilitymgr/src/restart_app_manager.cpp | 47 ++++++++++ .../ui_ability_lifecycle_manager.cpp | 13 ++- services/appmgr/include/app_mgr_service.h | 2 + .../appmgr/include/app_mgr_service_inner.h | 2 + services/appmgr/include/app_running_manager.h | 4 +- services/appmgr/include/app_running_record.h | 5 + services/appmgr/src/app_mgr_service.cpp | 16 ++++ services/appmgr/src/app_mgr_service_inner.cpp | 10 ++ services/appmgr/src/app_running_manager.cpp | 23 ++++- services/appmgr/src/app_running_record.cpp | 10 ++ test/unittest/BUILD.gn | 1 + 51 files changed, 611 insertions(+), 8 deletions(-) create mode 100644 services/abilitymgr/include/restart_app_manager.h create mode 100644 services/abilitymgr/src/restart_app_manager.cpp diff --git a/frameworks/js/napi/app/application_context/application_context.js b/frameworks/js/napi/app/application_context/application_context.js index b0901e706a..73beadd8f0 100644 --- a/frameworks/js/napi/app/application_context/application_context.js +++ b/frameworks/js/napi/app/application_context/application_context.js @@ -173,6 +173,10 @@ class ApplicationContext { return this.__context_impl__.clearUpApplicationData(callback); } + restartApp(want) { + return this.__context_impl__.restartApp(want); + } + set area(mode) { return this.__context_impl__.switchArea(mode); } diff --git a/frameworks/native/ability/native/ability_business_error/ability_business_error.cpp b/frameworks/native/ability/native/ability_business_error/ability_business_error.cpp index 3b9ca20c22..a25b2f95e3 100644 --- a/frameworks/native/ability/native/ability_business_error/ability_business_error.cpp +++ b/frameworks/native/ability/native/ability_business_error/ability_business_error.cpp @@ -57,6 +57,9 @@ constexpr const char* ERROR_MSG_GRANT_URI_PERMISSION = "Sandbox application can constexpr const char* ERROR_MSG_OPERATION_NOT_SUPPORTED = "Operation not supported."; constexpr const char* ERROR_MSG_CHILD_PROCESS_NUMBER_EXCEEDS_UPPER_BOUND = "The number of child process exceeds upper bound."; +constexpr const char* ERROR_MSG_RESTART_APP_INCORRECT_ABILITY = + "The target to restart does not belong to the current app or is not a UIAbility."; +constexpr const char* ERROR_MSG_RESTART_APP_FREQUENT = "Restart too frequently. Try again at least 10s later."; constexpr const char* ERROR_MSG_INVALID_CALLER = "The caller has been released."; constexpr const char* ERROR_MSG_NO_MISSION_ID = "The specified mission does not exist."; constexpr const char* ERROR_MSG_NO_MISSION_LISTENER = "Input error. The specified mission listener does not exist."; @@ -96,6 +99,8 @@ static std::unordered_map ERR_CODE_MAP = { { AbilityErrorCode::ERROR_CODE_OPERATION_NOT_SUPPORTED, ERROR_MSG_OPERATION_NOT_SUPPORTED }, { AbilityErrorCode::ERROR_CODE_CHILD_PROCESS_NUMBER_EXCEEDS_UPPER_BOUND, ERROR_MSG_CHILD_PROCESS_NUMBER_EXCEEDS_UPPER_BOUND }, + { AbilityErrorCode::ERROR_CODE_RESTART_APP_INCORRECT_ABILITY, ERROR_MSG_RESTART_APP_INCORRECT_ABILITY }, + { AbilityErrorCode::ERROR_CODE_RESTART_APP_FREQUENT, ERROR_MSG_RESTART_APP_FREQUENT }, { AbilityErrorCode::ERROR_CODE_INVALID_CALLER, ERROR_MSG_INVALID_CALLER }, { AbilityErrorCode::ERROR_CODE_NO_MISSION_ID, ERROR_MSG_NO_MISSION_ID }, { AbilityErrorCode::ERROR_CODE_NO_MISSION_LISTENER, ERROR_MSG_NO_MISSION_LISTENER }, @@ -142,6 +147,8 @@ static std::unordered_map INNER_TO_JS_ERROR_CODE_MAP {ERR_APP_CONTROLLED, AbilityErrorCode::ERROR_CODE_CONTROLLED}, {ERR_EDM_APP_CONTROLLED, AbilityErrorCode::ERROR_CODE_EDM_CONTROLLED}, {ERR_INSIGHT_INTENT_START_INVALID_COMPONENT, AbilityErrorCode::ERROR_CODE_OPERATION_NOT_SUPPORTED}, + {ERR_RESTART_APP_INCORRECT_ABILITY, AbilityErrorCode::ERROR_CODE_RESTART_APP_INCORRECT_ABILITY}, + {ERR_RESTART_APP_FREQUENT, AbilityErrorCode::ERROR_CODE_RESTART_APP_FREQUENT}, }; } diff --git a/frameworks/native/appkit/BUILD.gn b/frameworks/native/appkit/BUILD.gn index 28eb37321f..ef068b97c1 100644 --- a/frameworks/native/appkit/BUILD.gn +++ b/frameworks/native/appkit/BUILD.gn @@ -249,6 +249,7 @@ ohos_shared_library("app_context") { cflags += [ "-DBINDER_IPC_32BIT" ] } deps = [ + "${ability_runtime_innerkits_path}/ability_manager:ability_manager", "${ability_runtime_innerkits_path}/app_manager:app_manager", "${ability_runtime_innerkits_path}/deps_wrapper:ability_deps_wrapper", "${ability_runtime_innerkits_path}/runtime:runtime", @@ -314,6 +315,7 @@ ohos_shared_library("app_context_utils") { ] external_deps = [ + "ability_base:want", "access_token:libtokenid_sdk", "bundle_framework:appexecfwk_base", "bundle_framework:appexecfwk_core", diff --git a/frameworks/native/appkit/ability_runtime/context/application_context.cpp b/frameworks/native/appkit/ability_runtime/context/application_context.cpp index 93399d5a2e..3cb1ca0502 100644 --- a/frameworks/native/appkit/ability_runtime/context/application_context.cpp +++ b/frameworks/native/appkit/ability_runtime/context/application_context.cpp @@ -17,6 +17,7 @@ #include +#include "ability_manager_errors.h" #include "configuration_convertor.h" #include "hilog_wrapper.h" #include "running_process_info.h" @@ -418,6 +419,18 @@ std::string ApplicationContext::GetGroupDir(std::string groupId) return (contextImpl_ != nullptr) ? contextImpl_->GetGroupDir(groupId) : ""; } +int32_t ApplicationContext::RestartApp(const AAFwk::Want& want) +{ + std::string abilityName = want.GetElement().GetAbilityName(); + if (abilityName == "") { + HILOG_ERROR("abilityName is empty."); + return ERR_INVALID_VALUE; + } + std::string bundleName = GetBundleName(); + const_cast(want).SetBundle(bundleName); + return (contextImpl_ != nullptr) ? contextImpl_->RestartApp(want) : ERR_INVALID_VALUE; +} + std::string ApplicationContext::GetDistributedFilesDir() { return (contextImpl_ != nullptr) ? contextImpl_->GetDistributedFilesDir() : ""; diff --git a/frameworks/native/appkit/ability_runtime/context/context_impl.cpp b/frameworks/native/appkit/ability_runtime/context/context_impl.cpp index 9e48a93a33..d7ea1a4870 100644 --- a/frameworks/native/appkit/ability_runtime/context/context_impl.cpp +++ b/frameworks/native/appkit/ability_runtime/context/context_impl.cpp @@ -18,6 +18,7 @@ #include #include +#include "ability_manager_client.h" #include "app_mgr_client.h" #include "application_context.h" #include "bundle_mgr_helper.h" @@ -957,6 +958,13 @@ int32_t ContextImpl::GetProcessRunningInformation(AppExecFwk::RunningProcessInfo return result; } +int32_t ContextImpl::RestartApp(const AAFwk::Want& want) +{ + auto result = OHOS::AAFwk::AbilityManagerClient::GetInstance()->RestartApp(want); + HILOG_DEBUG("result is %{public}d.", result); + return result; +} + std::shared_ptr ContextImpl::GetConfiguration() const { return config_; diff --git a/frameworks/native/appkit/ability_runtime/context/js_application_context_utils.cpp b/frameworks/native/appkit/ability_runtime/context/js_application_context_utils.cpp index 6def9aa185..9f3798ef7f 100644 --- a/frameworks/native/appkit/ability_runtime/context/js_application_context_utils.cpp +++ b/frameworks/native/appkit/ability_runtime/context/js_application_context_utils.cpp @@ -32,6 +32,7 @@ #include "js_error_utils.h" #include "js_resource_manager_utils.h" #include "js_runtime_utils.h" +#include "napi_common_want.h" #include "tokenid_kit.h" namespace OHOS { @@ -450,6 +451,49 @@ napi_value JsApplicationContextUtils::OnGetGroupDir(napi_env env, NapiCallbackIn return result; } +napi_value JsApplicationContextUtils::RestartApp(napi_env env, napi_callback_info info) +{ + HILOG_DEBUG("called"); + GET_NAPI_INFO_WITH_NAME_AND_CALL(env, info, JsApplicationContextUtils, OnRestartApp, APPLICATION_CONTEXT_NAME); +} + +napi_value JsApplicationContextUtils::OnRestartApp(napi_env env, NapiCallbackInfo& info) +{ + // only support one params + if (info.argc == ARGC_ZERO) { + HILOG_ERROR("Not enough params"); + AbilityRuntimeErrorUtil::Throw(env, ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER); + return CreateJsUndefined(env); + } + auto applicationContext = applicationContext_.lock(); + if (!applicationContext) { + HILOG_WARN("applicationContext is already released"); + return CreateJsUndefined(env); + } + AAFwk::Want want; + if (!AppExecFwk::UnwrapWant(env, info.argv[INDEX_ZERO], want)) { + HILOG_ERROR("Parse want failed"); + AbilityRuntimeErrorUtil::Throw(env, ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER); + return CreateJsUndefined(env); + } + + auto errCode = applicationContext->RestartApp(want); + if (errCode == ERR_OK) { + return CreateJsUndefined(env); + } + if (errCode == ERR_INVALID_VALUE) { + AbilityRuntimeErrorUtil::Throw(env, ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_PARAMETER); + } else if (errCode == AAFwk::ERR_RESTART_APP_INCORRECT_ABILITY) { + AbilityRuntimeErrorUtil::Throw(env, ERR_ABILITY_RUNTIME_RESTART_APP_INCORRECT_ABILITY); + } else if (errCode == AAFwk::ERR_RESTART_APP_FREQUENT) { + AbilityRuntimeErrorUtil::Throw(env, ERR_ABILITY_RUNTIME_RESTART_APP_FREQUENT); + } else { + AbilityRuntimeErrorUtil::Throw(env, ERR_ABILITY_RUNTIME_EXTERNAL_INTERNAL_ERROR); + } + HILOG_ERROR("errCode is %{public}d.", errCode); + return CreateJsUndefined(env); +} + napi_value JsApplicationContextUtils::GetBundleCodeDir(napi_env env, napi_callback_info info) { HILOG_DEBUG("called"); @@ -1283,6 +1327,8 @@ void JsApplicationContextUtils::BindNativeApplicationContext(napi_env env, napi_ JsApplicationContextUtils::GetRunningProcessInformation); BindNativeFunction(env, object, "getGroupDir", MD_NAME, JsApplicationContextUtils::GetGroupDir); + BindNativeFunction(env, object, "restartApp", MD_NAME, + JsApplicationContextUtils::RestartApp); } JsAppProcessState JsApplicationContextUtils::ConvertToJsAppProcessState( diff --git a/interfaces/inner_api/ability_manager/include/ability_manager_client.h b/interfaces/inner_api/ability_manager/include/ability_manager_client.h index cefa9f3307..f696e6fb39 100644 --- a/interfaces/inner_api/ability_manager/include/ability_manager_client.h +++ b/interfaces/inner_api/ability_manager/include/ability_manager_client.h @@ -1350,6 +1350,13 @@ public: ErrCode GetUIExtensionRootHostInfo(const sptr token, UIExtensionHostInfo &hostInfo, int32_t userId = DEFAULT_INVAL_VALUE); + /** + * @brief Restart app self. + * @param want The ability type must be UIAbility. + * @return Returns ERR_OK on success, others on failure. + */ + int32_t RestartApp(const AAFwk::Want &want); + private: AbilityManagerClient(); DISALLOW_COPY_AND_MOVE(AbilityManagerClient); diff --git a/interfaces/inner_api/ability_manager/include/ability_manager_errors.h b/interfaces/inner_api/ability_manager/include/ability_manager_errors.h index e0e1ebe56c..11c2f1f539 100644 --- a/interfaces/inner_api/ability_manager/include/ability_manager_errors.h +++ b/interfaces/inner_api/ability_manager/include/ability_manager_errors.h @@ -377,6 +377,16 @@ enum { * Result(2097223) for query highest priority ability. */ ERR_QUERY_HIGHEST_PRIORITY_ABILITY, + + /** + * Result(2097224) for the target to restart does not belong to the current app or is not a UIAbility. + */ + ERR_RESTART_APP_INCORRECT_ABILITY, + + /** + * Result(2097225) for restart too frequently. Try again at least 10s later. + */ + ERR_RESTART_APP_FREQUENT, }; enum { diff --git a/interfaces/inner_api/ability_manager/include/ability_manager_interface.h b/interfaces/inner_api/ability_manager/include/ability_manager_interface.h index 451dc4bc8a..a297ff9df6 100644 --- a/interfaces/inner_api/ability_manager/include/ability_manager_interface.h +++ b/interfaces/inner_api/ability_manager/include/ability_manager_interface.h @@ -1376,6 +1376,16 @@ public: { return 0; } + + /** + * @brief Restart app self. + * @param want The ability type must be UIAbility. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int32_t RestartApp(const AAFwk::Want &want) + { + return 0; + } }; } // namespace AAFwk } // namespace OHOS diff --git a/interfaces/inner_api/ability_manager/include/ability_manager_ipc_interface_code.h b/interfaces/inner_api/ability_manager/include/ability_manager_ipc_interface_code.h index 09b26f04d1..7bfe591020 100644 --- a/interfaces/inner_api/ability_manager/include/ability_manager_ipc_interface_code.h +++ b/interfaces/inner_api/ability_manager/include/ability_manager_ipc_interface_code.h @@ -480,6 +480,9 @@ enum class AbilityManagerInterfaceCode { SET_APPLICATION_AUTO_STARTUP_BY_EDM = 6113, // ipc id for cancel application auto startup by EDM CANCEL_APPLICATION_AUTO_STARTUP_BY_EDM = 6114, + + // ipc id for restart app + RESTART_APP = 6115, }; } // namespace AAFwk } // namespace OHOS diff --git a/interfaces/inner_api/app_manager/include/appmgr/app_mgr_interface.h b/interfaces/inner_api/app_manager/include/appmgr/app_mgr_interface.h index 44c427a7e7..d8eb73aaf3 100644 --- a/interfaces/inner_api/app_manager/include/appmgr/app_mgr_interface.h +++ b/interfaces/inner_api/app_manager/include/appmgr/app_mgr_interface.h @@ -551,6 +551,11 @@ public: * @return Returns ERR_OK on success, others on failure. */ virtual int32_t UpdateRenderState(pid_t renderPid, int32_t state) = 0; + + virtual int32_t SignRestartAppFlag(const std::string &bundleName) + { + return 0; + } }; } // namespace AppExecFwk } // namespace OHOS diff --git a/interfaces/inner_api/app_manager/include/appmgr/app_mgr_ipc_interface_code.h b/interfaces/inner_api/app_manager/include/appmgr/app_mgr_ipc_interface_code.h index 753fc019c7..20c7320632 100644 --- a/interfaces/inner_api/app_manager/include/appmgr/app_mgr_ipc_interface_code.h +++ b/interfaces/inner_api/app_manager/include/appmgr/app_mgr_ipc_interface_code.h @@ -88,6 +88,7 @@ enum class AppMgrInterfaceCode { REGISTER_RENDER_STATUS_OBSERVER = 62, UNREGISTER_RENDER_STATUS_OBSERVER = 63, UPDATE_RENDER_STATUS = 64, + SIGN_RESTART_APP_FLAG = 65, }; } // AppExecFwk } // OHOS diff --git a/interfaces/inner_api/app_manager/include/appmgr/app_mgr_proxy.h b/interfaces/inner_api/app_manager/include/appmgr/app_mgr_proxy.h index 8d606a9a62..9ce7bf2d7e 100644 --- a/interfaces/inner_api/app_manager/include/appmgr/app_mgr_proxy.h +++ b/interfaces/inner_api/app_manager/include/appmgr/app_mgr_proxy.h @@ -492,6 +492,7 @@ public: */ virtual int32_t UpdateRenderState(pid_t renderPid, int32_t state) override; + int32_t SignRestartAppFlag(const std::string &bundleName) override; private: bool SendTransactCmd(AppMgrInterfaceCode code, MessageParcel &data, MessageParcel &reply); bool WriteInterfaceToken(MessageParcel &data); diff --git a/interfaces/inner_api/app_manager/include/appmgr/app_mgr_stub.h b/interfaces/inner_api/app_manager/include/appmgr/app_mgr_stub.h index c07838f290..fec31144e9 100644 --- a/interfaces/inner_api/app_manager/include/appmgr/app_mgr_stub.h +++ b/interfaces/inner_api/app_manager/include/appmgr/app_mgr_stub.h @@ -124,6 +124,7 @@ private: int32_t HandleRegisterRenderStateObserver(MessageParcel &data, MessageParcel &reply); int32_t HandleUnregisterRenderStateObserver(MessageParcel &data, MessageParcel &reply); int32_t HandleUpdateRenderState(MessageParcel &data, MessageParcel &reply); + int32_t HandleSignRestartAppFlag(MessageParcel &data, MessageParcel &reply); using AppMgrFunc = int32_t (AppMgrStub::*)(MessageParcel &data, MessageParcel &reply); std::map memberFuncMap_; diff --git a/interfaces/inner_api/app_manager/src/appmgr/app_mgr_proxy.cpp b/interfaces/inner_api/app_manager/src/appmgr/app_mgr_proxy.cpp index 6200e53a90..23c3442e52 100644 --- a/interfaces/inner_api/app_manager/src/appmgr/app_mgr_proxy.cpp +++ b/interfaces/inner_api/app_manager/src/appmgr/app_mgr_proxy.cpp @@ -1690,5 +1690,27 @@ int32_t AppMgrProxy::UpdateRenderState(pid_t renderPid, int32_t state) } return reply.ReadInt32(); } + +int32_t AppMgrProxy::SignRestartAppFlag(const std::string &bundleName) +{ + HILOG_DEBUG("Called."); + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + HILOG_ERROR("Write interface token failed."); + return IPC_PROXY_ERR; + } + if (!data.WriteString(bundleName)) { + HILOG_ERROR("parcel WriteString failed"); + return IPC_PROXY_ERR; + } + auto ret = SendRequest(AppMgrInterfaceCode::SIGN_RESTART_APP_FLAG, data, reply, option); + if (ret != NO_ERROR) { + HILOG_ERROR("Send request is failed, error code: %{public}d", ret); + return ret; + } + return reply.ReadInt32(); +} } // namespace AppExecFwk } // namespace OHOS diff --git a/interfaces/inner_api/app_manager/src/appmgr/app_mgr_stub.cpp b/interfaces/inner_api/app_manager/src/appmgr/app_mgr_stub.cpp index 6111737cad..c42d2f406a 100644 --- a/interfaces/inner_api/app_manager/src/appmgr/app_mgr_stub.cpp +++ b/interfaces/inner_api/app_manager/src/appmgr/app_mgr_stub.cpp @@ -165,6 +165,8 @@ AppMgrStub::AppMgrStub() &AppMgrStub::HandleUnregisterRenderStateObserver; memberFuncMap_[static_cast(AppMgrInterfaceCode::UPDATE_RENDER_STATUS)] = &AppMgrStub::HandleUpdateRenderState; + memberFuncMap_[static_cast(AppMgrInterfaceCode::SIGN_RESTART_APP_FLAG)] = + &AppMgrStub::HandleSignRestartAppFlag; } AppMgrStub::~AppMgrStub() @@ -1076,5 +1078,17 @@ int32_t AppMgrStub::HandleUpdateRenderState(MessageParcel &data, MessageParcel & } return NO_ERROR; } + +int32_t AppMgrStub::HandleSignRestartAppFlag(MessageParcel &data, MessageParcel &reply) +{ + HILOG_DEBUG("Called."); + std::string bundleName = data.ReadString(); + auto ret = SignRestartAppFlag(bundleName); + if (!reply.WriteInt32(ret)) { + HILOG_ERROR("Write ret error."); + return IPC_STUB_ERR; + } + return NO_ERROR; +} } // namespace AppExecFwk } // namespace OHOS diff --git a/interfaces/inner_api/error_utils/include/ability_runtime_error_util.h b/interfaces/inner_api/error_utils/include/ability_runtime_error_util.h index 324f56fc80..a2ab9982be 100644 --- a/interfaces/inner_api/error_utils/include/ability_runtime_error_util.h +++ b/interfaces/inner_api/error_utils/include/ability_runtime_error_util.h @@ -51,6 +51,8 @@ enum { ERR_ABILITY_RUNTIME_EXTERNAL_GRANT_URI_PERMISSION = 16000060, ERR_ABILITY_RUNTIME_OPERATION_NOT_SUPPORTED = 16000061, ERR_ABILITY_RUNTIME_CHILD_PROCESS_NUMBER_EXCEEDS_UPPER_BOUND = 16000062, + ERR_ABILITY_RUNTIME_RESTART_APP_INCORRECT_ABILITY = 16000063, + ERR_ABILITY_RUNTIME_RESTART_APP_FREQUENT = 16000064, ERR_ABILITY_RUNTIME_EXTERNAL_EXECUTE_SHELL_COMMAND_FAILED = 16000101, ERR_ABILITY_RUNTIME_EXTERNAL_INVALID_WANTAGENT = 16000151, ERR_ABILITY_RUNTIME_EXTERNAL_WANTAGENT_NOT_FOUND = 16000152, diff --git a/interfaces/inner_api/error_utils/src/ability_runtime_error_util.cpp b/interfaces/inner_api/error_utils/src/ability_runtime_error_util.cpp index f3b2c195ef..7dd899b9a8 100644 --- a/interfaces/inner_api/error_utils/src/ability_runtime_error_util.cpp +++ b/interfaces/inner_api/error_utils/src/ability_runtime_error_util.cpp @@ -138,7 +138,11 @@ const std::map ERROR_MSG_MAP = { { ERR_ABILITY_RUNTIME_OPERATION_NOT_SUPPORTED, "Operation not supported." }, { ERR_ABILITY_RUNTIME_CHILD_PROCESS_NUMBER_EXCEEDS_UPPER_BOUND, - "The number of child process exceeds upper bound." } + "The number of child process exceeds upper bound." }, + { ERR_ABILITY_RUNTIME_RESTART_APP_INCORRECT_ABILITY, + "The target to restart does not belong to the current app or is not a UIAbility." }, + { ERR_ABILITY_RUNTIME_RESTART_APP_FREQUENT, + "Restart too frequently. Try again at least 10s later." } }; } diff --git a/interfaces/kits/native/ability/native/ability_business_error/ability_business_error.h b/interfaces/kits/native/ability/native/ability_business_error/ability_business_error.h index c5577734c1..c755b58cdb 100644 --- a/interfaces/kits/native/ability/native/ability_business_error/ability_business_error.h +++ b/interfaces/kits/native/ability/native/ability_business_error/ability_business_error.h @@ -117,6 +117,12 @@ enum class AbilityErrorCode { // The number of child process exceeds upper bound. ERROR_CODE_CHILD_PROCESS_NUMBER_EXCEEDS_UPPER_BOUND = 16000062, + // The target to restart does not belong to the current app or is not a UIAbility. + ERROR_CODE_RESTART_APP_INCORRECT_ABILITY = 16000063, + + // Restart too frequently. Try again at least 10s later. + ERROR_CODE_RESTART_APP_FREQUENT = 16000064, + // invalid caller. ERROR_CODE_INVALID_CALLER = 16200001, diff --git a/interfaces/kits/native/appkit/ability_runtime/context/application_context.h b/interfaces/kits/native/appkit/ability_runtime/context/application_context.h index 5b768fe45a..b9cd90d996 100644 --- a/interfaces/kits/native/appkit/ability_runtime/context/application_context.h +++ b/interfaces/kits/native/appkit/ability_runtime/context/application_context.h @@ -25,6 +25,9 @@ #include "context_impl.h" #include "environment_callback.h" namespace OHOS { +namespace AAFwk { +class Want; +} namespace AbilityRuntime { using AppConfigUpdateCallback = std::function; class ApplicationContext : public Context { @@ -92,6 +95,7 @@ public: Global::Resource::DeviceType GetDeviceType() const override; void KillProcessBySelf(); int32_t GetProcessRunningInformation(AppExecFwk::RunningProcessInfo &info); + int32_t RestartApp(const AAFwk::Want& want); void AttachContextImpl(const std::shared_ptr &contextImpl); diff --git a/interfaces/kits/native/appkit/ability_runtime/context/context_impl.h b/interfaces/kits/native/appkit/ability_runtime/context/context_impl.h index e070005b35..88ed3a09bc 100644 --- a/interfaces/kits/native/appkit/ability_runtime/context/context_impl.h +++ b/interfaces/kits/native/appkit/ability_runtime/context/context_impl.h @@ -26,6 +26,9 @@ namespace AppExecFwk { struct RunningProcessInfo; class BundleMgrHelper; } +namespace AAFwk { +class Want; +} namespace AbilityRuntime { class ContextImpl : public Context { public: @@ -319,6 +322,13 @@ public: */ int32_t GetProcessRunningInformation(AppExecFwk::RunningProcessInfo &info); + /** + * @brief Restart app + * + * @return error code + */ + int32_t RestartApp(const AAFwk::Want& want); + /** * @brief Get the token witch the app launched. * diff --git a/interfaces/kits/native/appkit/ability_runtime/context/js_application_context_utils.h b/interfaces/kits/native/appkit/ability_runtime/context/js_application_context_utils.h index 698a2d7360..98a8e4d9e3 100644 --- a/interfaces/kits/native/appkit/ability_runtime/context/js_application_context_utils.h +++ b/interfaces/kits/native/appkit/ability_runtime/context/js_application_context_utils.h @@ -93,6 +93,7 @@ public: napi_value OnSetColorMode(napi_env env, NapiCallbackInfo& info); napi_value OnSetLanguage(napi_env env, NapiCallbackInfo& info); napi_value OnClearUpApplicationData(napi_env env, NapiCallbackInfo& info); + napi_value OnRestartApp(napi_env env, NapiCallbackInfo& info); static napi_value GetCacheDir(napi_env env, napi_callback_info info); static napi_value GetTempDir(napi_env env, napi_callback_info info); @@ -110,6 +111,7 @@ public: static napi_value ClearUpApplicationData(napi_env env, napi_callback_info info); static napi_value GetRunningProcessInformation(napi_env env, napi_callback_info info); static napi_value CreateJsApplicationContext(napi_env env); + static napi_value RestartApp(napi_env env, napi_callback_info info); protected: std::weak_ptr applicationContext_; diff --git a/services/abilitymgr/abilitymgr.gni b/services/abilitymgr/abilitymgr.gni index 2565a9379a..3e793fc33c 100644 --- a/services/abilitymgr/abilitymgr.gni +++ b/services/abilitymgr/abilitymgr.gni @@ -55,6 +55,7 @@ abilityms_files = [ "src/pending_want_key.cpp", "src/pending_want_manager.cpp", "src/pending_want_common_event.cpp", + "src/restart_app_manager.cpp", "src/ams_configuration_parameter.cpp", "src/image_info.cpp", "src/insight_intent_utils.cpp", diff --git a/services/abilitymgr/include/ability_connect_manager.h b/services/abilitymgr/include/ability_connect_manager.h index 0bd8999214..e66fd3fcaf 100644 --- a/services/abilitymgr/include/ability_connect_manager.h +++ b/services/abilitymgr/include/ability_connect_manager.h @@ -262,6 +262,8 @@ public: int32_t GetUIExtensionRootHostInfo(const sptr token, UIExtensionHostInfo &hostInfo); + void SignRestartAppFlag(const std::string &bundleName); + // MSG 0 - 20 represents timeout message static constexpr uint32_t LOAD_TIMEOUT_MSG = 0; static constexpr uint32_t CONNECT_TIMEOUT_MSG = 1; diff --git a/services/abilitymgr/include/ability_manager_proxy.h b/services/abilitymgr/include/ability_manager_proxy.h index dc01a67c7c..a996bb4b5b 100644 --- a/services/abilitymgr/include/ability_manager_proxy.h +++ b/services/abilitymgr/include/ability_manager_proxy.h @@ -1111,6 +1111,12 @@ public: int32_t GetUIExtensionRootHostInfo(const sptr token, UIExtensionHostInfo &hostInfo, int32_t userId = DEFAULT_INVAL_VALUE) override; + /** + * @brief Restart app self. + * @param want The ability type must be UIAbility. + * @return Returns ERR_OK on success, others on failure. + */ + int32_t RestartApp(const AAFwk::Want &want) override; private: template int GetParcelableInfos(MessageParcel &reply, std::vector &parcelableInfos); diff --git a/services/abilitymgr/include/ability_manager_service.h b/services/abilitymgr/include/ability_manager_service.h index 1e27bcff64..acb4853206 100644 --- a/services/abilitymgr/include/ability_manager_service.h +++ b/services/abilitymgr/include/ability_manager_service.h @@ -1443,6 +1443,13 @@ public: int32_t GetUIExtensionRootHostInfo(const sptr token, UIExtensionHostInfo &hostInfo, int32_t userId = DEFAULT_INVAL_VALUE) override; + /** + * @brief Restart app self. + * @param want The ability type must be UIAbility. + * @return Returns ERR_OK on success, others on failure. + */ + int32_t RestartApp(const AAFwk::Want &want) override; + // MSG 0 - 20 represents timeout message static constexpr uint32_t LOAD_TIMEOUT_MSG = 0; static constexpr uint32_t ACTIVE_TIMEOUT_MSG = 1; @@ -1874,6 +1881,9 @@ private: void WaitBootAnimationStart(); + int32_t SignRestartAppFlag(int32_t userId, const std::string &bundleName); + int32_t CheckRestartAppWant(const AAFwk::Want &want); + constexpr static int REPOLL_TIME_MICRO_SECONDS = 1000000; constexpr static int WAITING_BOOT_ANIMATION_TIMER = 5; diff --git a/services/abilitymgr/include/ability_manager_stub.h b/services/abilitymgr/include/ability_manager_stub.h index 5b6091a113..5ba6a539e6 100644 --- a/services/abilitymgr/include/ability_manager_stub.h +++ b/services/abilitymgr/include/ability_manager_stub.h @@ -277,6 +277,7 @@ private: int32_t GetForegroundUIAbilitiesInner(MessageParcel &data, MessageParcel &reply); int32_t GetUIExtensionRootHostInfoInner(MessageParcel &data, MessageParcel &reply); + int32_t RestartAppInner(MessageParcel &data, MessageParcel &reply); }; } // namespace AAFwk } // namespace OHOS diff --git a/services/abilitymgr/include/ability_record.h b/services/abilitymgr/include/ability_record.h index 55581ab046..2f6209772e 100644 --- a/services/abilitymgr/include/ability_record.h +++ b/services/abilitymgr/include/ability_record.h @@ -949,6 +949,8 @@ public: bool IsSceneBoard() const; + void SetRestartAppFlag(bool isRestartApp); + bool GetRestartAppFlag() const; protected: void SendEvent(uint32_t msg, uint32_t timeOut, int32_t param = -1); @@ -1160,6 +1162,8 @@ private: bool isAppAutoStartup_ = false; bool isConnected = false; std::atomic_bool backgroundAbilityWindowDelayed_ = false; + + bool isRestartApp_ = false; // Only app calling RestartApp can be set to true }; } // namespace AAFwk } // namespace OHOS diff --git a/services/abilitymgr/include/mission_list.h b/services/abilitymgr/include/mission_list.h index 824fc9aba8..4b06464289 100644 --- a/services/abilitymgr/include/mission_list.h +++ b/services/abilitymgr/include/mission_list.h @@ -225,6 +225,8 @@ public: int32_t GetMissionCount() const; void GetActiveAbilityList(const std::string &bundleName, std::vector &abilityList, int32_t pid = NO_PID); + + void SignRestartAppFlag(const std::string &bundleName); private: std::string GetTypeName(); diff --git a/services/abilitymgr/include/mission_list_manager.h b/services/abilitymgr/include/mission_list_manager.h index 2956623298..ce48a3ecc0 100644 --- a/services/abilitymgr/include/mission_list_manager.h +++ b/services/abilitymgr/include/mission_list_manager.h @@ -349,6 +349,8 @@ public: const AAFwk::ContinueState &state); bool IsAbilityStarted(AbilityRequest &abilityRequest, std::shared_ptr &targetRecord); + + void SignRestartAppFlag(const std::string &bundleName); #ifdef SUPPORT_GRAPHICS public: /** diff --git a/services/abilitymgr/include/restart_app_manager.h b/services/abilitymgr/include/restart_app_manager.h new file mode 100644 index 0000000000..15ba888b93 --- /dev/null +++ b/services/abilitymgr/include/restart_app_manager.h @@ -0,0 +1,72 @@ +/* + * 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_RESTART_APP_MANAGER_H +#define OHOS_ABILITY_RUNTIME_RESTART_APP_MANAGER_H + +#include +#include +#include +#include "cpp/mutex.h" +#include "nocopyable.h" + +namespace OHOS { +namespace AAFwk { +typedef struct RestartAppKey { + std::string bundleName; + int32_t userId = 100; + + RestartAppKey(std::string restartBundleName, int32_t restartUserId) + { + bundleName = restartBundleName; + userId = restartUserId; + } + bool operator ==(const struct RestartAppKey &other) const + { + return bundleName == other.bundleName && userId == other.userId; + } +} RestartAppKeyType; + +struct RestartAppKeyHash { + size_t operator()(const RestartAppKeyType &p) const + { + return std::hash()(p.bundleName) ^ std::hash()(p.userId); + } +}; + +/** + * @class RestartAppManager + * RestartAppManager provides a facility for managing restart app history. + */ +class RestartAppManager { +public: + using RestartAppMapType = std::unordered_map; + + virtual ~RestartAppManager() = default; + static RestartAppManager &GetInstance(); + + bool IsRestartAppFrequent(const RestartAppKeyType &key, time_t time); + void AddRestartAppHistory(const RestartAppKeyType &key, time_t time); + +private: + RestartAppManager() = default; + DISALLOW_COPY_AND_MOVE(RestartAppManager); + + ffrt::mutex restartAppMapLock_; + RestartAppMapType restartAppHistory_; // RestartAppKey:time +}; +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_RESTART_APP_MANAGER_H diff --git a/services/abilitymgr/include/scene_board/ui_ability_lifecycle_manager.h b/services/abilitymgr/include/scene_board/ui_ability_lifecycle_manager.h index ef6a2587b7..de06980a60 100644 --- a/services/abilitymgr/include/scene_board/ui_ability_lifecycle_manager.h +++ b/services/abilitymgr/include/scene_board/ui_ability_lifecycle_manager.h @@ -55,6 +55,8 @@ public: } }; + void SignRestartAppFlag(const std::string &bundleName); + /** * StartUIAbility with request. * diff --git a/services/abilitymgr/src/ability_connect_manager.cpp b/services/abilitymgr/src/ability_connect_manager.cpp index f84642262e..c0e3ce33f5 100644 --- a/services/abilitymgr/src/ability_connect_manager.cpp +++ b/services/abilitymgr/src/ability_connect_manager.cpp @@ -2570,5 +2570,16 @@ int32_t AbilityConnectManager::GetUIExtensionRootHostInfo(const sptrGetUIExtensionRootHostInfo(token, hostInfo); } + +void AbilityConnectManager::SignRestartAppFlag(const std::string &bundleName) +{ + std::lock_guard guard(Lock_); + for (auto &[key, abilityRecord] : serviceMap_) { + if (abilityRecord == nullptr || abilityRecord->GetApplicationInfo().bundleName != bundleName) { + continue; + } + abilityRecord->SetRestartAppFlag(true); + } +} } // namespace AAFwk } // namespace OHOS diff --git a/services/abilitymgr/src/ability_manager_client.cpp b/services/abilitymgr/src/ability_manager_client.cpp index ea92c1b7f9..7963ef53d3 100644 --- a/services/abilitymgr/src/ability_manager_client.cpp +++ b/services/abilitymgr/src/ability_manager_client.cpp @@ -1687,5 +1687,14 @@ ErrCode AbilityManagerClient::GetUIExtensionRootHostInfo(const sptrGetUIExtensionRootHostInfo(token, hostInfo, userId); } + +int32_t AbilityManagerClient::RestartApp(const AAFwk::Want &want) +{ + HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); + HILOG_DEBUG("Called."); + auto abms = GetAbilityManager(); + CHECK_POINTER_RETURN_INVALID_VALUE(abms); + return abms->RestartApp(want); +} } // namespace AAFwk } // namespace OHOS diff --git a/services/abilitymgr/src/ability_manager_proxy.cpp b/services/abilitymgr/src/ability_manager_proxy.cpp index 45d4bd1df0..fe6ecf2524 100644 --- a/services/abilitymgr/src/ability_manager_proxy.cpp +++ b/services/abilitymgr/src/ability_manager_proxy.cpp @@ -4692,5 +4692,26 @@ int32_t AbilityManagerProxy::GetUIExtensionRootHostInfo(const sptr::GetInstance()->KillApplicationSelf(); + if (result != ERR_OK) { + HILOG_ERROR("KillApplicationSelf error."); + return result; + } + + HILOG_DEBUG("StartAbility begin."); + result = OHOS::AAFwk::AbilityManagerClient::GetInstance()->StartAbility(want); + if (result != ERR_OK) { + HILOG_ERROR("StartAbility error."); + return result; + } + RestartAppManager::GetInstance().AddRestartAppHistory(key, now); + return result; +} + +int32_t AbilityManagerService::CheckRestartAppWant(const AAFwk::Want &want) +{ + std::string bundleName = want.GetElement().GetBundleName(); + if (!CheckCallingTokenId(bundleName)) { + HILOG_ERROR("Not itself called, not allowed."); + return AAFwk::ERR_RESTART_APP_INCORRECT_ABILITY; + } + + auto bms = GetBundleManager(); + CHECK_POINTER_AND_RETURN(bms, GET_ABILITY_SERVICE_FAILED); + auto abilityInfoFlag = (AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_WITH_APPLICATION | + AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_WITH_PERMISSION | + AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_WITH_METADATA); + auto userId = IPCSkeleton::GetCallingUid() / BASE_USER_RANGE; + AppExecFwk::AbilityInfo abilityInfo; + bool queryResult = IN_PROCESS_CALL(bms->QueryAbilityInfo(want, abilityInfoFlag, userId, abilityInfo)); + if (!queryResult) { + HILOG_ERROR("Query ability info fail."); + return INNER_ERR; + } + if (abilityInfo.name.empty() || abilityInfo.bundleName.empty() || abilityInfo.type != AbilityType::PAGE) { + HILOG_ERROR("Ability is invalid or not UIAbility."); + return AAFwk::ERR_RESTART_APP_INCORRECT_ABILITY; + } + return ERR_OK; +} + +int32_t AbilityManagerService::SignRestartAppFlag(int32_t userId, const std::string &bundleName) +{ + auto appMgr = GetAppMgr(); + if (appMgr == nullptr) { + HILOG_WARN("GetAppMgr failed"); + return ERR_INVALID_VALUE; + } + auto ret = IN_PROCESS_CALL(appMgr->SignRestartAppFlag(bundleName)); + if (ret != ERR_OK) { + HILOG_ERROR("AppMgr SignRestartAppFlag error"); + return ret; + } + + auto connectManager = GetConnectManagerByUserId(userId); + connectManager->SignRestartAppFlag(bundleName); + if (Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) { + uiAbilityLifecycleManager_->SignRestartAppFlag(bundleName); + return ERR_OK; + } + auto missionListManager = GetListManagerByUserId(userId); + if (missionListManager == nullptr) { + HILOG_ERROR("missionListManager is nullptr. userId:%{public}d", userId); + return ERR_INVALID_VALUE; + } + missionListManager->SignRestartAppFlag(bundleName); return ERR_OK; } } // namespace AAFwk } // namespace OHOS + \ No newline at end of file diff --git a/services/abilitymgr/src/ability_manager_stub.cpp b/services/abilitymgr/src/ability_manager_stub.cpp index 3907906566..73549a9614 100644 --- a/services/abilitymgr/src/ability_manager_stub.cpp +++ b/services/abilitymgr/src/ability_manager_stub.cpp @@ -395,6 +395,8 @@ void AbilityManagerStub::FourthStepInit() &AbilityManagerStub::CancelApplicationAutoStartupByEDMInner; requestFuncMap_[static_cast(AbilityManagerInterfaceCode::GET_FOREGROUND_UI_ABILITIES)] = &AbilityManagerStub::GetForegroundUIAbilitiesInner; + requestFuncMap_[static_cast(AbilityManagerInterfaceCode::RESTART_APP)] = + &AbilityManagerStub::RestartAppInner; } int AbilityManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) @@ -3028,5 +3030,21 @@ int32_t AbilityManagerStub::GetUIExtensionRootHostInfoInner(MessageParcel &data, return NO_ERROR; } + +int32_t AbilityManagerStub::RestartAppInner(MessageParcel &data, MessageParcel &reply) +{ + HILOG_DEBUG("call."); + std::unique_ptr want(data.ReadParcelable()); + if (want == nullptr) { + HILOG_ERROR("want is nullptr"); + return IPC_STUB_ERR; + } + auto result = RestartApp(*want); + if (!reply.WriteInt32(result)) { + HILOG_ERROR("fail to write result."); + return IPC_STUB_ERR; + } + return ERR_OK; +} } // namespace AAFwk } // namespace OHOS \ No newline at end of file diff --git a/services/abilitymgr/src/ability_record.cpp b/services/abilitymgr/src/ability_record.cpp index 0a234fbce3..e7b237896e 100644 --- a/services/abilitymgr/src/ability_record.cpp +++ b/services/abilitymgr/src/ability_record.cpp @@ -691,7 +691,7 @@ void AbilityRecord::ProcessForegroundAbility(bool isRecent, const AbilityRequest GrantUriPermission(want_, applicationInfo_.bundleName, false, 0); } - if (isReady_) { + if (isReady_ && !GetRestartAppFlag()) { auto handler = DelayedSingleton::GetInstance()->GetTaskHandler(); if (!handler) { HILOG_ERROR("Fail to get AbilityEventHandler."); @@ -3393,5 +3393,15 @@ bool AbilityRecord::IsSceneBoard() const return GetAbilityInfo().name == AbilityConfig::SCENEBOARD_ABILITY_NAME && GetAbilityInfo().bundleName == AbilityConfig::SCENEBOARD_BUNDLE_NAME; } + +void AbilityRecord::SetRestartAppFlag(bool isRestartApp) +{ + isRestartApp_ = isRestartApp; +} + +bool AbilityRecord::GetRestartAppFlag() const +{ + return isRestartApp_; +} } // namespace AAFwk } // namespace OHOS diff --git a/services/abilitymgr/src/mission_list.cpp b/services/abilitymgr/src/mission_list.cpp index 56d3c23f9c..910125a4a5 100644 --- a/services/abilitymgr/src/mission_list.cpp +++ b/services/abilitymgr/src/mission_list.cpp @@ -486,5 +486,22 @@ void MissionList::GetActiveAbilityList(const std::string &bundleName, std::vecto } } } + +void MissionList::SignRestartAppFlag(const std::string &bundleName) +{ + for (auto mission : missions_) { + if (!mission) { + continue; + } + auto abilityRecord = mission->GetAbilityRecord(); + if (!abilityRecord) { + continue; + } + if (abilityRecord->GetApplicationInfo().bundleName != bundleName) { + continue; + } + abilityRecord->SetRestartAppFlag(true); + } +} } // namespace AAFwk } // namespace OHOS diff --git a/services/abilitymgr/src/mission_list_manager.cpp b/services/abilitymgr/src/mission_list_manager.cpp index de25738d35..57d447433f 100644 --- a/services/abilitymgr/src/mission_list_manager.cpp +++ b/services/abilitymgr/src/mission_list_manager.cpp @@ -153,7 +153,7 @@ int MissionListManager::StartAbility(AbilityRequest &abilityRequest) } auto currentTopAbility = GetCurrentTopAbilityLocked(); - if (currentTopAbility) { + if (currentTopAbility && !currentTopAbility->GetRestartAppFlag()) { std::string element = currentTopAbility->GetElementName().GetURI(); auto state = currentTopAbility->GetAbilityState(); HILOG_DEBUG("current top: %{public}s, state: %{public}s", @@ -4046,5 +4046,21 @@ void MissionListManager::ReportAbilitAssociatedStartInfoToRSS(const AppExecFwk:: ResourceSchedule::ResType::RES_TYPE_APP_ASSOCIATED_START, type, eventParams); #endif } + +void MissionListManager::SignRestartAppFlag(const std::string &bundleName) +{ + for (const auto& missionList : currentMissionLists_) { + if (!missionList) { + continue; + } + missionList->SignRestartAppFlag(bundleName); + } + if (defaultStandardList_) { + defaultStandardList_->SignRestartAppFlag(bundleName); + } + if (defaultSingleList_) { + defaultSingleList_->SignRestartAppFlag(bundleName); + } +} } // namespace AAFwk } // namespace OHOS diff --git a/services/abilitymgr/src/restart_app_manager.cpp b/services/abilitymgr/src/restart_app_manager.cpp new file mode 100644 index 0000000000..9fdb3d6482 --- /dev/null +++ b/services/abilitymgr/src/restart_app_manager.cpp @@ -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. + */ + +#include "restart_app_manager.h" + +#include "hilog_wrapper.h" + +namespace OHOS { +namespace AAFwk { +RestartAppManager &RestartAppManager::GetInstance() +{ + static RestartAppManager instance; + return instance; +} + +bool RestartAppManager::IsRestartAppFrequent(const RestartAppKeyType &key, time_t time) +{ + std::lock_guard lock(restartAppMapLock_); + constexpr int64_t MIN_RESTART_TIME = 10; + auto it = restartAppHistory_.find(key); + if ((it != restartAppHistory_.end()) && (it->second + MIN_RESTART_TIME > time)) { + HILOG_ERROR("Restart too frequently. Try again at least 10s later."); + return true; + } + return false; +} + +void RestartAppManager::AddRestartAppHistory(const RestartAppKeyType &key, time_t time) +{ + std::lock_guard lock(restartAppMapLock_); + HILOG_DEBUG("Refresh history, bundleName=%{public}s, userId=%{public}d", key.bundleName.c_str(), key.userId); + restartAppHistory_[key] = time; +} +} // namespace AAFwk +} // 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 693e7e7d9e..0f0a816b26 100644 --- a/services/abilitymgr/src/scene_board/ui_ability_lifecycle_manager.cpp +++ b/services/abilitymgr/src/scene_board/ui_ability_lifecycle_manager.cpp @@ -768,7 +768,7 @@ int UIAbilityLifecycleManager::NotifySCBPendingActivation(sptr &ses const AbilityRequest &abilityRequest) const { auto abilityRecord = GetAbilityRecordByToken(abilityRequest.callerToken); - if (abilityRecord != nullptr) { + if (abilityRecord != nullptr && !abilityRecord->GetRestartAppFlag()) { auto callerSessionInfo = abilityRecord->GetSessionInfo(); CHECK_POINTER_AND_RETURN(callerSessionInfo, ERR_INVALID_VALUE); CHECK_POINTER_AND_RETURN(callerSessionInfo->sessionToken, ERR_INVALID_VALUE); @@ -2055,5 +2055,16 @@ void UIAbilityLifecycleManager::UpdateSessionInfoBySCB(const std::vector guard(sessionLock_); + for (auto &[sessionId, abilityRecord] : sessionAbilityMap_) { + if (abilityRecord == nullptr || abilityRecord->GetApplicationInfo().bundleName != bundleName) { + continue; + } + abilityRecord->SetRestartAppFlag(true); + } +} } // namespace AAFwk } // namespace OHOS \ No newline at end of file diff --git a/services/appmgr/include/app_mgr_service.h b/services/appmgr/include/app_mgr_service.h index aa39c05908..7c32a1396d 100644 --- a/services/appmgr/include/app_mgr_service.h +++ b/services/appmgr/include/app_mgr_service.h @@ -441,6 +441,8 @@ public: int32_t UpdateRenderState(pid_t renderPid, int32_t state) override; + int32_t SignRestartAppFlag(const std::string &bundleName) override; + private: /** * Init, Initialize application services. diff --git a/services/appmgr/include/app_mgr_service_inner.h b/services/appmgr/include/app_mgr_service_inner.h index 142067fc23..d07c88f311 100644 --- a/services/appmgr/include/app_mgr_service_inner.h +++ b/services/appmgr/include/app_mgr_service_inner.h @@ -926,6 +926,8 @@ public: int32_t UpdateRenderState(pid_t renderPid, int32_t state); + int32_t SignRestartAppFlag(const std::string &bundleName); + private: std::string FaultTypeToString(FaultDataType type); diff --git a/services/appmgr/include/app_running_manager.h b/services/appmgr/include/app_running_manager.h index 275a29bc0a..0b47b0d06e 100644 --- a/services/appmgr/include/app_running_manager.h +++ b/services/appmgr/include/app_running_manager.h @@ -243,7 +243,9 @@ public: * @return Returns the number of queries. */ int32_t GetAllAppRunningRecordCountByBundleName(const std::string &bundleName); - + + int32_t SignRestartAppFlag(const std::string &bundleName); + private: std::shared_ptr GetAbilityRunningRecord(const int64_t eventId); void AssignRunningProcessInfoByAppRecord( diff --git a/services/appmgr/include/app_running_record.h b/services/appmgr/include/app_running_record.h index 63553a7695..f3407c607d 100644 --- a/services/appmgr/include/app_running_record.h +++ b/services/appmgr/include/app_running_record.h @@ -706,6 +706,9 @@ public: * @param AssignTokenId, the assign tokenId. */ void SetAssignTokenId(int32_t tokenId); + + void SetRestartAppFlag(bool isRestartApp); + bool GetRestartAppFlag() const; private: /** * SearchTheModuleInfoNeedToUpdated, Get an uninitialized abilityStage data. @@ -844,6 +847,8 @@ private: std::set windowIds_; std::map> childProcessRecordMap_; ffrt::mutex childProcessRecordMapLock_; + + bool isRestartApp_ = false; // Only app calling RestartApp can be set to true }; } // namespace AppExecFwk } // namespace OHOS diff --git a/services/appmgr/src/app_mgr_service.cpp b/services/appmgr/src/app_mgr_service.cpp index ee9f3f54a6..c0908c9f59 100644 --- a/services/appmgr/src/app_mgr_service.cpp +++ b/services/appmgr/src/app_mgr_service.cpp @@ -53,6 +53,7 @@ const std::string TASK_FINISH_USER_TEST = "FinishUserTest"; const std::string TASK_ATTACH_RENDER_PROCESS = "AttachRenderTask"; const std::string TASK_ATTACH_CHILD_PROCESS = "AttachChildProcessTask"; const std::string TASK_EXIT_CHILD_PROCESS_SAFELY = "ExitChildProcessSafelyTask"; +const std::string FOUNDATION_PROCESS = "foundation"; } // namespace REGISTER_SYSTEM_ABILITY_BY_ID(AppMgrService, APP_MGR_SERVICE_ID, true); @@ -1055,5 +1056,20 @@ int32_t AppMgrService::UpdateRenderState(pid_t renderPid, int32_t state) } return appMgrServiceInner_->UpdateRenderState(renderPid, state); } + +int32_t AppMgrService::SignRestartAppFlag(const std::string &bundleName) +{ + if (!IsReady()) { + HILOG_ERROR("Not ready."); + return ERR_INVALID_OPERATION; + } + bool isCallingPermission = + AAFwk::PermissionVerification::GetInstance()->CheckSpecificSystemAbilityAccessPermission(FOUNDATION_PROCESS); + if (!isCallingPermission) { + HILOG_ERROR("VerificationAllToken failed."); + return ERR_PERMISSION_DENIED; + } + return appMgrServiceInner_->SignRestartAppFlag(bundleName); +} } // namespace AppExecFwk } // namespace OHOS diff --git a/services/appmgr/src/app_mgr_service_inner.cpp b/services/appmgr/src/app_mgr_service_inner.cpp index 78f01ddc66..f0b76dd900 100644 --- a/services/appmgr/src/app_mgr_service_inner.cpp +++ b/services/appmgr/src/app_mgr_service_inner.cpp @@ -5436,5 +5436,15 @@ int32_t AppMgrServiceInner::UpdateRenderState(pid_t renderPid, int32_t state) HILOG_ERROR("renderPid:%{pubclic}d not exist.", renderPid); return ERR_INVALID_VALUE; } + +int32_t AppMgrServiceInner::SignRestartAppFlag(const std::string &bundleName) +{ + HILOG_DEBUG("call."); + if (!appRunningManager_) { + HILOG_ERROR("appRunningManager_ is nullptr"); + return ERR_NO_INIT; + } + return appRunningManager_->SignRestartAppFlag(bundleName); +} } // namespace AppExecFwk } // namespace OHOS diff --git a/services/appmgr/src/app_running_manager.cpp b/services/appmgr/src/app_running_manager.cpp index cd41efa9e1..9f4fc81c35 100644 --- a/services/appmgr/src/app_running_manager.cpp +++ b/services/appmgr/src/app_running_manager.cpp @@ -100,7 +100,7 @@ std::shared_ptr AppRunningManager::CheckAppRunningRecordIsExis (pair.second->GetProcessName() == processName) && (pair.second->GetJointUserId() == jointUserId) && !(pair.second->IsTerminating()) && - !(pair.second->IsKilling()); + !(pair.second->IsKilling()) && !(pair.second->GetRestartAppFlag()); }; // If it is not empty, look for whether it can come in the same process @@ -114,7 +114,7 @@ std::shared_ptr AppRunningManager::CheckAppRunningRecordIsExis if (appRecord && appRecord->GetProcessName() == processName && (specifiedProcessFlag.empty() || appRecord->GetSpecifiedProcessFlag() == specifiedProcessFlag) && - !(appRecord->IsTerminating()) && !(appRecord->IsKilling())) { + !(appRecord->IsTerminating()) && !(appRecord->IsKilling()) && !(appRecord->GetRestartAppFlag())) { auto appInfoList = appRecord->GetAppInfoList(); HILOG_DEBUG("appInfoList: %{public}zu, processName: %{public}s, specifiedProcessFlag: %{public}s", appInfoList.size(), appRecord->GetProcessName().c_str(), specifiedProcessFlag.c_str()); @@ -139,7 +139,7 @@ bool AppRunningManager::CheckAppRunningRecordIsExistByBundleName(const std::stri } for (const auto &item : appRunningRecordMap_) { const auto &appRecord = item.second; - if (appRecord && appRecord->GetBundleName() == bundleName) { + if (appRecord && appRecord->GetBundleName() == bundleName && !(appRecord->GetRestartAppFlag())) { return true; } } @@ -1126,5 +1126,22 @@ std::shared_ptr AppRunningManager::OnChildProcessRemoteDied( } return nullptr; } + +int32_t AppRunningManager::SignRestartAppFlag(const std::string &bundleName) +{ + HILOG_DEBUG("Called."); + std::lock_guard guard(lock_); + for (const auto &item : appRunningRecordMap_) { + const auto &appRecord = item.second; + if (appRecord == nullptr || appRecord->GetBundleName() != bundleName) { + continue; + } + HILOG_DEBUG("sign"); + appRecord->SetRestartAppFlag(true); + return ERR_OK; + } + HILOG_ERROR("Not find apprecord."); + return ERR_INVALID_VALUE; +} } // namespace AppExecFwk } // namespace OHOS diff --git a/services/appmgr/src/app_running_record.cpp b/services/appmgr/src/app_running_record.cpp index bef8f42e17..a31ed4f179 100644 --- a/services/appmgr/src/app_running_record.cpp +++ b/services/appmgr/src/app_running_record.cpp @@ -1940,5 +1940,15 @@ void AppRunningRecord::SetAssignTokenId(int32_t assignTokenId) { assignTokenId_ = assignTokenId; } + +void AppRunningRecord::SetRestartAppFlag(bool isRestartApp) +{ + isRestartApp_ = isRestartApp; +} + +bool AppRunningRecord::GetRestartAppFlag() const +{ + return isRestartApp_; +} } // namespace AppExecFwk } // namespace OHOS diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index d6a87013eb..06a69ff30c 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -155,6 +155,7 @@ ohos_source_set("abilityms_test_source") { "${ability_runtime_services_path}/abilitymgr/src/pending_want_manager.cpp", "${ability_runtime_services_path}/abilitymgr/src/pending_want_record.cpp", "${ability_runtime_services_path}/abilitymgr/src/resident_process_manager.cpp", + "${ability_runtime_services_path}/abilitymgr/src/restart_app_manager.cpp", "${ability_runtime_services_path}/abilitymgr/src/scene_board/ui_ability_lifecycle_manager.cpp", "${ability_runtime_services_path}/abilitymgr/src/sender_info.cpp", "${ability_runtime_services_path}/abilitymgr/src/start_ability_handler.cpp",