diff --git a/frameworks/ets/ets/@ohos.app.ability.appRecovery.ets b/frameworks/ets/ets/@ohos.app.ability.appRecovery.ets index 2ef5809c21..33c59c686b 100644 --- a/frameworks/ets/ets/@ohos.app.ability.appRecovery.ets +++ b/frameworks/ets/ets/@ohos.app.ability.appRecovery.ets @@ -22,6 +22,7 @@ export default namespace appRecovery { ALWAYS_RESTART = 0, RESTART_WHEN_JS_CRASH = 0x0001, RESTART_WHEN_APP_FREEZE = 0x0002, + RESTART_WHEN_CPP_CRASH = 0x0008, NO_RESTART = 0xFFFF } diff --git a/frameworks/js/napi/app/recovery/app_recovery_api.cpp b/frameworks/js/napi/app/recovery/app_recovery_api.cpp index 7d40691d5e..8cac929b79 100644 --- a/frameworks/js/napi/app/recovery/app_recovery_api.cpp +++ b/frameworks/js/napi/app/recovery/app_recovery_api.cpp @@ -196,6 +196,8 @@ napi_value AppRecoveryRestartFlagInit(napi_env env) CreateJsValue(env, RestartFlag::RESTART_WHEN_JS_CRASH)); napi_set_named_property(env, objValue, "RESTART_WHEN_APP_FREEZE", CreateJsValue(env, RestartFlag::RESTART_WHEN_APP_FREEZE)); + napi_set_named_property(env, objValue, "RESTART_WHEN_CPP_CRASH", + CreateJsValue(env, RestartFlag::RESTART_WHEN_CPP_CRASH)); napi_set_named_property(env, objValue, "NO_RESTART", CreateJsValue(env, RestartFlag::NO_RESTART)); return objValue; } diff --git a/frameworks/native/ability/native/recovery/app_recovery.cpp b/frameworks/native/ability/native/recovery/app_recovery.cpp index 798f789517..11602c952f 100644 --- a/frameworks/native/ability/native/recovery/app_recovery.cpp +++ b/frameworks/native/ability/native/recovery/app_recovery.cpp @@ -143,6 +143,8 @@ bool AppRecovery::AddAbility(std::shared_ptr ability, abilityRecovery->EnableAbilityRecovery(useAppSettedValue_.load(), restartFlag_, saveOccasion_, saveMode_); ability->EnableAbilityRecovery(abilityRecovery, useAppSettedValue_.load()); abilityRecoverys_.push_back(abilityRecovery); + std::shared_ptr abilityMgr = AAFwk::AbilityManagerClient::GetInstance(); + abilityMgr->SetAppRecoveryFlag(token_.promote(), restartFlag_); return true; } 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 ae5e55d4f9..6cf3b0413c 100644 --- a/interfaces/inner_api/ability_manager/include/ability_manager_client.h +++ b/interfaces/inner_api/ability_manager/include/ability_manager_client.h @@ -2088,6 +2088,13 @@ public: */ ErrCode GetUserLockedBundleList(int32_t userId, std::unordered_set &userLockedBundleList); + /** + * @brief UnRegister preload ui extension host client. + * + * @return Returns ERR_OK on success, others on failure. + */ + int32_t SetAppRecoveryFlag(const sptr& token, int flag); + private: AbilityManagerClient(); DISALLOW_COPY_AND_MOVE(AbilityManagerClient); 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 48aa26d116..680ad079f1 100644 --- a/interfaces/inner_api/ability_manager/include/ability_manager_interface.h +++ b/interfaces/inner_api/ability_manager/include/ability_manager_interface.h @@ -2588,6 +2588,17 @@ public: { return ERR_OK; } + + /** + * @brief Set app recovery galg. + * @param token Caller ability token. + * @param flag App recovery flag. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int32_t SetAppRecoveryFlag(const sptr& token, int flag) + { + 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 e9f67fe4e6..d0f8722403 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 @@ -711,6 +711,9 @@ enum class AbilityManagerInterfaceCode { // get user locked bundle list GET_USER_LOCKED_BUNDLE_LIST = 6159, + + // set app recovery flag + SET_APP_RECOVERY_FLAG = 6160, }; } // namespace AAFwk } // namespace OHOS diff --git a/interfaces/inner_api/ability_manager/include/recovery_param.h b/interfaces/inner_api/ability_manager/include/recovery_param.h index cd56f5a95a..c5d33667b5 100644 --- a/interfaces/inner_api/ability_manager/include/recovery_param.h +++ b/interfaces/inner_api/ability_manager/include/recovery_param.h @@ -44,6 +44,7 @@ enum RestartFlag { ALWAYS_RESTART = 0, RESTART_WHEN_JS_CRASH = 0x0001, RESTART_WHEN_APP_FREEZE = 0x0002, + RESTART_WHEN_CPP_CRASH = 0x0008, NO_RESTART = 0xFFFF, }; diff --git a/interfaces/inner_api/app_manager/BUILD.gn b/interfaces/inner_api/app_manager/BUILD.gn index 33d72c9817..36c6e4cc1f 100644 --- a/interfaces/inner_api/app_manager/BUILD.gn +++ b/interfaces/inner_api/app_manager/BUILD.gn @@ -57,6 +57,7 @@ ohos_shared_library("app_manager") { "${ability_runtime_services_path}/appdfr/src/appfreeze_cpu_freq_manager.cpp", "${ability_runtime_services_path}/appdfr/src/appfreeze_event_report.cpp", "${ability_runtime_services_path}/appdfr/src/appfreeze_manager.cpp", + "${ability_runtime_services_path}/appdfr/src/app_recovery_mgr.cpp", "${ability_runtime_services_path}/appdfr/src/appfreeze_util.cpp", "${ability_runtime_services_path}/appdfr/src/cpu_data_processor.cpp", "${ability_runtime_services_path}/appdfr/src/cpu_sys_config.cpp", @@ -164,6 +165,8 @@ ohos_shared_library("app_manager") { "hicollie:libhicollie", "hilog:libhilog", "hisysevent:libhisysevent", + "eventhandler:libeventhandler", + "ability_base:session_info", "hitrace:hitrace_meter", "hitrace:libhitracechain", "init:libbegetutil", diff --git a/interfaces/kits/native/ability/native/recovery/recovery_param.h b/interfaces/kits/native/ability/native/recovery/recovery_param.h index 67db772c8e..38093fff78 100644 --- a/interfaces/kits/native/ability/native/recovery/recovery_param.h +++ b/interfaces/kits/native/ability/native/recovery/recovery_param.h @@ -45,6 +45,7 @@ enum RestartFlag { RESTART_WHEN_JS_CRASH = 0x0001, RESTART_WHEN_APP_FREEZE = 0x0002, RESTART_WHEN_CJ_CRASH = 0x0004, + RESTART_WHEN_CPP_CRASH = 0x0008, NO_RESTART = 0xFFFF, }; diff --git a/services/abilitymgr/include/ability_manager_proxy.h b/services/abilitymgr/include/ability_manager_proxy.h index d93ffb7a88..1861c3c81a 100644 --- a/services/abilitymgr/include/ability_manager_proxy.h +++ b/services/abilitymgr/include/ability_manager_proxy.h @@ -2013,6 +2013,7 @@ public: virtual int32_t GetUserLockedBundleList(int32_t userId, std::unordered_set &userLockedBundleList) override; + virtual int32_t SetAppRecoveryFlag(const sptr& token, int flag)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 42e37c51e1..de352f38f8 100644 --- a/services/abilitymgr/include/ability_manager_service.h +++ b/services/abilitymgr/include/ability_manager_service.h @@ -3356,6 +3356,14 @@ private: bool IsAllowAttachOrDetachAppDebug(AppExecFwk::ApplicationInfo &appInfo); bool IsExitReasonValid(const ExitReasonCompability &reason); void RecordRecoveryExitReason(bool isAppRecovery, int32_t callerPid, int32_t callerUid); + void SetAppDeathRecipient(const sptr& abilityToken); + void HandleAppDiedForRecovery(const sptr& remote, const AbilityInfo& abilityInfo, + int32_t pid, int32_t uid); + void startRecoveryMgr(); + int getAppRecoveryFlag(const sptr &token); + void HandleRecoveryRecipient(const std::shared_ptr& abilityRecord, + const sptr& token); + int32_t SetAppRecoveryFlag(const sptr& token, int flag) override; #ifdef BGTASKMGR_CONTINUOUS_TASK_ENABLE std::shared_ptr bgtaskObserver_; #endif diff --git a/services/abilitymgr/include/ability_manager_stub.h b/services/abilitymgr/include/ability_manager_stub.h index 50d4dd8223..0bd130a3a0 100644 --- a/services/abilitymgr/include/ability_manager_stub.h +++ b/services/abilitymgr/include/ability_manager_stub.h @@ -364,6 +364,7 @@ private: int32_t ClearAllPreloadUIExtensionAbilityInner(MessageParcel &data, MessageParcel &reply); int32_t RegisterPreloadUIExtensionHostClientInner(MessageParcel &data, MessageParcel &reply); int32_t UnRegisterPreloadUIExtensionHostClientInner(MessageParcel &data, MessageParcel &reply); + int32_t SetAppRecoveryFlagInner(MessageParcel &data, MessageParcel &reply); int OnRemoteRequestInnerFirst(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option); diff --git a/services/abilitymgr/include/ability_record.h b/services/abilitymgr/include/ability_record.h index 79a8a3fb96..03da523e76 100644 --- a/services/abilitymgr/include/ability_record.h +++ b/services/abilitymgr/include/ability_record.h @@ -830,6 +830,8 @@ public: return firstCallerBundleName_; } + void SetAppRecoveryFlag(int flag); + int GetAppRecoveryFlag() const; protected: Want want_ = {}; // want to start this ability std::unique_ptr lifecycleDeal_ = {}; // life manager used to schedule life @@ -1037,6 +1039,7 @@ protected: bool isStartingWindow_ = false; bool isCompleteFirstFrameDrawing_ = false; bool coldStart_ = false; + int appRecoveryFlag_ = 0xFFFF; #endif }; } // namespace AAFwk diff --git a/services/abilitymgr/src/ability_manager_client.cpp b/services/abilitymgr/src/ability_manager_client.cpp index f60ce50a04..56a61df5d2 100644 --- a/services/abilitymgr/src/ability_manager_client.cpp +++ b/services/abilitymgr/src/ability_manager_client.cpp @@ -2563,5 +2563,19 @@ ErrCode AbilityManagerClient::GetUserLockedBundleList(int32_t userId, CHECK_POINTER_RETURN_NOT_CONNECTED(abms); return abms->GetUserLockedBundleList(userId, userLockedBundleList); } + +int32_t AbilityManagerClient::SetAppRecoveryFlag(const sptr& token, int flag) +{ + if (token == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "token is nullptr"); + return ERR_INVALID_VALUE; + } + auto proxy = GetAbilityManager(); + if (proxy == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "GetAbilityManager proxy failed"); + return ERR_INVALID_VALUE; + } + return proxy->SetAppRecoveryFlag(token, flag); +} } // namespace AAFwk } // namespace OHOS diff --git a/services/abilitymgr/src/ability_manager_proxy.cpp b/services/abilitymgr/src/ability_manager_proxy.cpp index 0a90fb5225..abe987739b 100644 --- a/services/abilitymgr/src/ability_manager_proxy.cpp +++ b/services/abilitymgr/src/ability_manager_proxy.cpp @@ -7683,5 +7683,32 @@ int32_t AbilityManagerProxy::GetUserLockedBundleList(int32_t userId, } return NO_ERROR; } + +int32_t AbilityManagerProxy::SetAppRecoveryFlag(const sptr& token, int flag) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(AbilityManagerProxy::GetDescriptor())) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Write interface token failed"); + return ERR_INVALID_VALUE; + } + if (!data.WriteRemoteObject(token)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Write token failed"); + return ERR_INVALID_VALUE; + } + if (!data.WriteInt32(flag)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Write flag failed"); + return ERR_INVALID_VALUE; + } + + int32_t error = SendRequest(AbilityManagerInterfaceCode::SET_APP_RECOVERY_FLAG, data, reply, option); + if (error != NO_ERROR) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "SendRequest failed"); + return error; + } + return reply.ReadInt32(); +} } // namespace AAFwk } // namespace OHOS diff --git a/services/abilitymgr/src/ability_manager_service.cpp b/services/abilitymgr/src/ability_manager_service.cpp index 29160482c7..e99b19c70c 100644 --- a/services/abilitymgr/src/ability_manager_service.cpp +++ b/services/abilitymgr/src/ability_manager_service.cpp @@ -32,6 +32,7 @@ #include "app_exit_reason_data_manager.h" #include "app_mgr_constants.h" #include "app_mgr_util.h" +#include "app_recovery_mgr.h" #include "application_util.h" #include "assert_fault_callback_death_mgr.h" #include "collaborator_util.h" @@ -16739,5 +16740,100 @@ bool AbilityManagerService::IsExitReasonValid(const ExitReasonCompability &reaso } return true; } + +int32_t AbilityManagerService::SetAppRecoveryFlag(const sptr& token, int flag) +{ + auto abilityRecord = Token::GetAbilityRecordByToken(token); + if (abilityRecord == nullptr) { + TAG_LOGE(AAFwkTag::UI_EXT,"AbilityRecord not found for given token"); + return ERR_INVALID_VALUE; + } + abilityRecord->SetAppRecoveryFlag(flag); + HandleRecoveryRecipient(abilityRecord, token); + return ERR_OK; +} + +void AbilityManagerService::HandleRecoveryRecipient( + const std::shared_ptr& abilityRecord, + const sptr& token) +{ + int restartFlag = abilityRecord->GetAppRecoveryFlag(); + TAG_LOGD(AAFwkTag::ABILITYMGR, "%{public}s SetAppDeathRecipient, restartFlag is %{public}d", + abilityRecord->GetAbilityInfo().bundleName.c_str(), + restartFlag); + + if (restartFlag == AppExecFwk::RestartFlag::ALWAYS_RESTART || + (restartFlag & AppExecFwk::RestartFlag::RESTART_WHEN_CPP_CRASH) != 0) { + TAG_LOGD(AAFwkTag::ABILITYMGR, "enable OnAbilityRequestDone"); + SetAppDeathRecipient(token); + } +} + +void AbilityManagerService::SetAppDeathRecipient(const sptr &token) +{ + auto abilityRecord = Token::GetAbilityRecordByToken(token); + const auto &abilityInfo = abilityRecord->GetAbilityInfo(); + int32_t pid = abilityRecord->GetPid(); + int32_t uid = abilityRecord->GetUid(); + auto callback = [this,abilityInfo,pid,uid](const sptr& remote) { + this->HandleAppDiedForRecovery(remote,abilityInfo,pid,uid); + }; + + AppRecoveryMgr::AppRecoveryMgr::GetInstance().SetOnRemoteDieCallback(token, callback); +} + +void AbilityManagerService::HandleAppDiedForRecovery(const sptr& remote, + const AbilityInfo& abilityInfo, + int32_t pid, + int32_t uid) +{ + if (remote == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "remote is null, cannot recover app"); + return; + } + if (abilityInfo.bundleName.empty() || abilityInfo.name.empty()) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "abilityInfo is invalid: bundleName or name is empty"); + return; + } + constexpr int64_t ONE_SECOND_MS = 1000; + constexpr int64_t RECOVERY_DELAY = 5000; + constexpr int64_t MIN_RECOVERY_TIME = 60; + int64_t now = time(nullptr); + auto it = appRecoveryHistory_.find(uid); + bool isSetReason = false; + int64_t stamp = 0; + bool withKillMsg = false; + AppExecFwk::RunningProcessInfo processInfo; + auto accessTokenId = abilityInfo.applicationInfo.accessTokenId; + AAFwk::ExitReason exitReason = {AAFwk::REASON_JS_ERROR, "Js Error."}; + auto result = DelayedSingleton::GetInstance()->GetAppExitReason(abilityInfo.bundleName, accessTokenId, + abilityInfo.name, isSetReason, exitReason, processInfo, stamp, withKillMsg); + if(exitReason.reason!= AAFwk::REASON_CPP_CRASH) { + TAG_LOGI(AAFwkTag::APPMGR, "app exit reason is not REASON_CPP_CRASH"); + return; + } + if ((it != appRecoveryHistory_.end()) && + (it->second + MIN_RECOVERY_TIME > now)) { + TAG_LOGW(AAFwkTag::ABILITYMGR, + "%{public}s appRecovery recover too frequently in one minute, kill app(%{public}d). " + "Last recovery: %{public}lld, Now: %{public}lld", + __func__, + pid, + static_cast(it->second), + static_cast(now)); + } else if (std::abs(now*ONE_SECOND_MS-stamp)>RECOVERY_DELAY){ + TAG_LOGW(AAFwkTag::ABILITYMGR,"now is %{public}lld,timestamp is %{public}lld,no recovery",static_cast(now),static_cast(stamp)); + } else { + appRecoveryHistory_[uid] = now; + AAFwk::Want *newWant=new AAFwk::Want(); + newWant->SetElementName(abilityInfo.bundleName, abilityInfo.name); + newWant->SetParam(AAFwk::Want::PARAM_ABILITY_RECOVERY_RESTART, true); + StartAbility(*newWant,MAIN_USER_ID); + TAG_LOGW(AAFwkTag::ABILITYMGR,"now is %{public}lld,timestamp is %{public}lld",static_cast(now),static_cast(stamp)); + } + if (remote != nullptr) { + AppRecoveryMgr::AppRecoveryMgr::GetInstance().RemoveOnRemoteDieCallback(remote); + } +} } // namespace AAFwk } // namespace OHOS diff --git a/services/abilitymgr/src/ability_manager_stub.cpp b/services/abilitymgr/src/ability_manager_stub.cpp index 2ff00a12e9..362c448d12 100644 --- a/services/abilitymgr/src/ability_manager_stub.cpp +++ b/services/abilitymgr/src/ability_manager_stub.cpp @@ -965,6 +965,9 @@ int AbilityManagerStub::OnRemoteRequestInnerTwentySecond(uint32_t code, MessageP if (interfaceCode == AbilityManagerInterfaceCode::GET_USER_LOCKED_BUNDLE_LIST) { return GetUserLockedBundleListInner(data, reply); } + if (interfaceCode == AbilityManagerInterfaceCode::SET_APP_RECOVERY_FLAG) { + return SetAppRecoveryFlagInner(data, reply); + } return ERR_CODE_NOT_EXIST; } @@ -5327,5 +5330,18 @@ int32_t AbilityManagerStub::GetUserLockedBundleListInner(MessageParcel &data, Me } return result; } + +int32_t AbilityManagerStub::SetAppRecoveryFlagInner(MessageParcel &data, MessageParcel &reply) +{ + sptr token = data.ReadRemoteObject(); + if (token == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "Read token failed"); + return ERR_INVALID_VALUE; + } + int flag = data.ReadInt32(); + int32_t result = SetAppRecoveryFlag(token, flag); + reply.WriteInt32(result); + return NO_ERROR; +} } // namespace AAFwk } // namespace OHOS diff --git a/services/abilitymgr/src/ability_record.cpp b/services/abilitymgr/src/ability_record.cpp index c0231fb908..5cce7b17b0 100644 --- a/services/abilitymgr/src/ability_record.cpp +++ b/services/abilitymgr/src/ability_record.cpp @@ -3433,5 +3433,16 @@ void AbilityRecord::PluginCompleteTerminate() hostAbility->GetAbilityInfo().name.c_str()); } } + +void AbilityRecord::SetAppRecoveryFlag(int flag) +{ + TAG_LOGE(AAFwkTag::ABILITYMGR, "SetAppRecoveryFlag:%{public}d", flag); + appRecoveryFlag_ = flag; +} + +int AbilityRecord::GetAppRecoveryFlag() const +{ + return appRecoveryFlag_; +} } // namespace AAFwk } // namespace OHOS diff --git a/services/appdfr/include/app_recovery_mgr.h b/services/appdfr/include/app_recovery_mgr.h new file mode 100644 index 0000000000..c05e0cb4bd --- /dev/null +++ b/services/appdfr/include/app_recovery_mgr.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2023 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_APP_RECOVERY_MGR_H +#define OHOS_ABILITY_RUNTIME_APP_RECOVERY_MGR_H + +#include "cpp/mutex.h" +#include +#include "iremote_object.h" +#include "refbase.h" +#include "event_handler.h" + +namespace OHOS { +namespace AppRecoveryMgr { + +class AppRecoveryMgr { +public: + static AppRecoveryMgr& GetInstance(); + void SetOnRemoteDieCallback(const sptr& abilityToken, + const std::function&)>& callback); + + void RemoveOnRemoteDieCallback(const sptr& abilityToken); + + void HandleAppDied(const sptr& remote); + + void Init(const std::shared_ptr& handler); + + void Clear(); + +private: + AppRecoveryMgr(); + ~AppRecoveryMgr(); + std::function&)> FindCallback(const sptr& remote); + +private: + std::mutex mutex_; + std::shared_ptr handler_; + std::map, std::function&)>> dieCallbacks_; +}; + +} // namespace AppRecoveryMgr +} // namespace OHOS + +#endif // OHOS_ABILITY_RUNTIME_APP_RECOVERY_MGR_H \ No newline at end of file diff --git a/services/appdfr/src/app_recovery_mgr.cpp b/services/appdfr/src/app_recovery_mgr.cpp new file mode 100644 index 0000000000..7364197d7e --- /dev/null +++ b/services/appdfr/src/app_recovery_mgr.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2023-2025 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_mgr.h" +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AppRecoveryMgr { + +AppRecoveryMgr::AppRecoveryMgr() +{ +} + +AppRecoveryMgr::~AppRecoveryMgr() +{ +} + +AppRecoveryMgr& AppRecoveryMgr::GetInstance() +{ + static AppRecoveryMgr instance; + return instance; +} + +void AppRecoveryMgr::Init(const std::shared_ptr& handler) +{ + std::lock_guard lock(mutex_); + handler_ = handler; + TAG_LOGI(AAFwkTag::APPDFR, "AppRecoveryMgr initialized"); +} + +void AppRecoveryMgr::SetOnRemoteDieCallback(const sptr& abilityToken, + const std::function&)>& callback) +{ + if (abilityToken == nullptr || callback == nullptr) { + TAG_LOGI(AAFwkTag::APPDFR, "SetOnRemoteDieCallback: invalid parameter"); + return; + } + + std::lock_guard lock(mutex_); + auto it = dieCallbacks_.find(abilityToken); + if (it != dieCallbacks_.end()) { + TAG_LOGI(AAFwkTag::APPDFR, "SetOnRemoteDieCallback: callback already exists, updating"); + dieCallbacks_.erase(it); + } + + dieCallbacks_.emplace(abilityToken, callback); + TAG_LOGI(AAFwkTag::APPDFR, "SetOnRemoteDieCallback: callback set for ability token"); +} + +void AppRecoveryMgr::RemoveOnRemoteDieCallback(const sptr& abilityToken) +{ + if (abilityToken == nullptr) { + TAG_LOGI(AAFwkTag::APPDFR, "RemoveOnRemoteDieCallback: invalid parameter"); + return; + } + + std::lock_guard lock(mutex_); + auto it = dieCallbacks_.find(abilityToken); + if (it != dieCallbacks_.end()) { + dieCallbacks_.erase(it); + TAG_LOGI(AAFwkTag::APPDFR, "RemoveOnRemoteDieCallback: callback removed"); + } +} + +std::function&)> AppRecoveryMgr::FindCallback(const sptr& remote) +{ + std::lock_guard lock(mutex_); + if (remote == nullptr) { + return nullptr; + } + + auto it = dieCallbacks_.find(remote); + if (it != dieCallbacks_.end()) { + return it->second; + } + + return nullptr; +} + +void AppRecoveryMgr::HandleAppDied(const sptr& remote) +{ + TAG_LOGI(AAFwkTag::APPDFR, "HandleAppDied: app died event received"); + + auto callback = FindCallback(remote); + if (callback == nullptr) { + TAG_LOGI(AAFwkTag::APPDFR, "HandleAppDied: no callback found for this remote"); + return; + } + + if (handler_ != nullptr) { + auto task = [callback, remote]() { + callback(remote); + }; + handler_->PostTask(task); + TAG_LOGI(AAFwkTag::APPDFR, "HandleAppDied: callback posted to handler"); + } else { + callback(remote); + TAG_LOGI(AAFwkTag::APPDFR, "HandleAppDied: callback executed directly no handler"); + } +} + +void AppRecoveryMgr::Clear() +{ + std::lock_guard lock(mutex_); + dieCallbacks_.clear(); + handler_ = nullptr; + TAG_LOGI(AAFwkTag::APPDFR, "AppRecoveryMgr cleared"); +} + +} // namespace AppRecoveryMgr +} // namespace OHOS \ No newline at end of file diff --git a/services/appmgr/include/app_mgr_service_inner.h b/services/appmgr/include/app_mgr_service_inner.h index 6023aeea64..844f2a18fd 100644 --- a/services/appmgr/include/app_mgr_service_inner.h +++ b/services/appmgr/include/app_mgr_service_inner.h @@ -2223,6 +2223,8 @@ private: void RemoveUninstallOrUpgradeUidSet(int32_t uid); bool IsUninstallingOrUpgrading(int32_t uid); void SendProcessKillEvent(std::shared_ptr appRecord); + void HandleForegroundAbilityDied(const std::vector>& abilityTokens, + ApplicationState state); std::shared_ptr remoteClientManager_; std::shared_ptr appRunningManager_; diff --git a/services/appmgr/src/app_mgr_service_inner.cpp b/services/appmgr/src/app_mgr_service_inner.cpp index 1e0c53427b..dcdf07926a 100644 --- a/services/appmgr/src/app_mgr_service_inner.cpp +++ b/services/appmgr/src/app_mgr_service_inner.cpp @@ -36,6 +36,7 @@ #include "app_mgr_service.h" #include "app_mgr_event.h" #include "app_process_data.h" +#include "app_recovery_mgr.h" #include "app_state_observer_manager.h" #include "app_utils.h" #include "appfreeze_manager.h" @@ -5184,6 +5185,7 @@ void AppMgrServiceInner::OnRemoteDied(const wptr &remote, bool is for (const auto &token : appRecord->GetAbilities()) { abilityTokens.emplace_back(token.first); } + HandleForegroundAbilityDied(abilityTokens,appRecord->GetState()); { std::lock_guard lock(appStateCallbacksLock_); for (const auto &item : appStateCallbacks_) { @@ -11498,5 +11500,22 @@ void AppMgrServiceInner::CheckRenderAttachTimeout(std::shared_ptr AppMgrEventUtil::SendRenderProcessStartFailedEvent(renderRecord, ProcessStartFailedReason::ATTACH_TIMEOUT, elapsedMs); } + +void AppMgrServiceInner::HandleForegroundAbilityDied( + const std::vector>& abilityTokens,ApplicationState state) +{ + if (state != ApplicationState::APP_STATE_FOREGROUND) { + return; + } + TAG_LOGD(AAFwkTag::APPMGR, "Handling died abilities in foreground."); + for (const auto& token : abilityTokens) { + if (token == nullptr) { + continue; + } + AppRecoveryMgr::AppRecoveryMgr::GetInstance().HandleAppDied(token); + TAG_LOGI(AAFwkTag::APPMGR, "Notified AppRecoveryMgr for ability token: %{public}p", + token.GetRefPtr()); + } +} } // namespace AppExecFwk } // namespace OHOS diff --git a/test/unittest/ability_manager_service_fourteenth_test/mock/src/mock_ability_record.cpp b/test/unittest/ability_manager_service_fourteenth_test/mock/src/mock_ability_record.cpp index c9cc4b7c2e..8e634ea528 100644 --- a/test/unittest/ability_manager_service_fourteenth_test/mock/src/mock_ability_record.cpp +++ b/test/unittest/ability_manager_service_fourteenth_test/mock/src/mock_ability_record.cpp @@ -1724,5 +1724,15 @@ bool AbilityRecord::PromotePriority() { return false; } + +void AbilityRecord::SetAppRecoveryFlag(int flag) +{ + TAG_LOGE(AAFwkTag::ABILITYMGR, "SetAppRecoveryFlag%{public}d", flag); + appRecoveryFlag_ = flag; +} +int AbilityRecord::GetAppRecoveryFlag() const +{ + return appRecoveryFlag_; +} } // namespace AAFwk } // namespace OHOS diff --git a/test/unittest/ability_manager_service_thirteenth_test/mock/src/mock_ability_record.cpp b/test/unittest/ability_manager_service_thirteenth_test/mock/src/mock_ability_record.cpp index 77fdaac4f2..df894c2b30 100644 --- a/test/unittest/ability_manager_service_thirteenth_test/mock/src/mock_ability_record.cpp +++ b/test/unittest/ability_manager_service_thirteenth_test/mock/src/mock_ability_record.cpp @@ -1744,5 +1744,15 @@ bool AbilityRecord::PromotePriority() { return false; } + +void AbilityRecord::SetAppRecoveryFlag(int flag) +{ + TAG_LOGE(AAFwkTag::ABILITYMGR, "SetAppRecoveryFlag%{public}d", flag); + appRecoveryFlag_ = flag; +} +int AbilityRecord::GetAppRecoveryFlag() const +{ + return appRecoveryFlag_; +} } // namespace AAFwk } // namespace OHOS