mirror of
https://github.com/openharmony/ability_ability_runtime.git
synced 2026-08-24 22:21:36 -04:00
!18555 merge lscdev0305 into master
cpp_crash场景使能APPrecover Created-by: tsuk1ii Commit-by: l00814634 Merged-by: openharmony_ci Description: **IssueNo**: [新需求]: cpp_crash场景使能APPrecover **Description**: cpp_crash场景使能APPrecover **稳定性自检:** | 自检项 | 自检结果 | | ------------------------------------------------------------ | -------- | | 涉及跨进程调用的相关操作需要抛至主线程或加锁防止并发 | ok | | 成员变量进行赋值或创建需要排查并发 | ok | | 谨慎在lambda表达式中使用引用捕获 | ok | | 谨慎在未经拷贝的情况下使用外部传入的string、C字符串 | ok | | map\vector\list\set等stl模板类使用时需要排查并发 | ok | | 谨慎考虑加锁范围 | ok | | 在IPC通信中谨慎使用同步通信方式 | ok | | 禁止传递this指针至其他模块或线程(特别是eventhandler任务) | ok | | 禁止将外部传入的裸指针在内部直接构造智能指针 | ok | | 禁止多个独立创建的智能指针管理同一地址 | ok | | 禁止在析构函数中抛异步任务 | ok | | 禁止js对象在非js线程(例如在IPC线程)创建、使用或销毁 | ok | | 禁止在对外接口中未经判空直接使用外部传入的指针 | ok | | 禁止接口返回局部变量引用 | ok | | 禁止在信号函数中加锁 | ok | | 禁止在关键流程(SA启动、应用启动等主流程)执行耗时的操作 | ok | | 禁止将同一个cpp编译在不同的so中 | ok | **安全编码自检:** | 自检项 | 自检结果 | | -------------------------------------------------------------- | -------- | | 裸指针避免通过隐式转换构造为sptr | ok | | json对象在取值之前必须先判断类型,避免类型不匹配 | ok | | 序列化时必须对传入的数组大小进行校验,避免出现超大数组 | ok | | 避免使用未明确位宽的整型,选择使用int8_t、uint8_t等类型 | ok | | 外部传入的路径要做规范化校验,对路径中的.、..、../等特殊字符严格校验 | ok | | 指针变量、表示资源描述符的变量、bool变量必须赋初值 | ok | | readParcelable获取的对象使用前需要判空 | ok | | 申请内存后异常退出前需要及时进行内存释放 | ok | | 内存申请前必须对内存大小进行合法性校验 | ok | | 内存分配后必须判断是否成功 | ok | | 禁止使用realloc、alloca函数 | ok | | 禁止打印文件路径、口令等敏感信息,如有需要,使用private修饰 | ok | | 禁止打印内存地址 | ok | | 整数之间运算时必须严格检查,确保不会出现溢出、反转、除0 | ok | | 禁止对有符号整数进行位操作符运算 | ok | | 禁止对指针进行逻辑或位运算 | ok | | 循环次数如果收外部数据控制,需要检验其合法性 | ok | | 禁止使用内存操作类危险函数,需要使用安全函数 | ok | | 谨慎使用不可重入函数 | ok | | 必须检查安全函数的返回值,并进行正确处理 | ok | | 禁止仅通过TokenType类型判断绕过权限校验 | ok | **TDD Result**: OK **XTS Result**: OK ### 是否已执行L0用例 已验证 See merge request: openharmony/ability_ability_runtime!18555
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -143,6 +143,8 @@ bool AppRecovery::AddAbility(std::shared_ptr<AbilityRuntime::UIAbility> ability,
|
||||
abilityRecovery->EnableAbilityRecovery(useAppSettedValue_.load(), restartFlag_, saveOccasion_, saveMode_);
|
||||
ability->EnableAbilityRecovery(abilityRecovery, useAppSettedValue_.load());
|
||||
abilityRecoverys_.push_back(abilityRecovery);
|
||||
std::shared_ptr<AAFwk::AbilityManagerClient> abilityMgr = AAFwk::AbilityManagerClient::GetInstance();
|
||||
abilityMgr->SetAppRecoveryFlag(token_.promote(), restartFlag_);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -2088,6 +2088,13 @@ public:
|
||||
*/
|
||||
ErrCode GetUserLockedBundleList(int32_t userId, std::unordered_set<std::string> &userLockedBundleList);
|
||||
|
||||
/**
|
||||
* @brief UnRegister preload ui extension host client.
|
||||
*
|
||||
* @return Returns ERR_OK on success, others on failure.
|
||||
*/
|
||||
int32_t SetAppRecoveryFlag(const sptr<IRemoteObject>& token, int flag);
|
||||
|
||||
private:
|
||||
AbilityManagerClient();
|
||||
DISALLOW_COPY_AND_MOVE(AbilityManagerClient);
|
||||
|
||||
@@ -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<IRemoteObject>& token, int flag)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
} // namespace AAFwk
|
||||
} // namespace OHOS
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -2013,6 +2013,7 @@ public:
|
||||
virtual int32_t GetUserLockedBundleList(int32_t userId,
|
||||
std::unordered_set<std::string> &userLockedBundleList) override;
|
||||
|
||||
virtual int32_t SetAppRecoveryFlag(const sptr<IRemoteObject>& token, int flag)override;
|
||||
private:
|
||||
template <typename T>
|
||||
int GetParcelableInfos(MessageParcel &reply, std::vector<T> &parcelableInfos);
|
||||
|
||||
@@ -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<IRemoteObject>& abilityToken);
|
||||
void HandleAppDiedForRecovery(const sptr<IRemoteObject>& remote, const AbilityInfo& abilityInfo,
|
||||
int32_t pid, int32_t uid);
|
||||
void startRecoveryMgr();
|
||||
int getAppRecoveryFlag(const sptr<IRemoteObject> &token);
|
||||
void HandleRecoveryRecipient(const std::shared_ptr<AbilityRecord>& abilityRecord,
|
||||
const sptr<IRemoteObject>& token);
|
||||
int32_t SetAppRecoveryFlag(const sptr<IRemoteObject>& token, int flag) override;
|
||||
#ifdef BGTASKMGR_CONTINUOUS_TASK_ENABLE
|
||||
std::shared_ptr<BackgroundTaskObserver> bgtaskObserver_;
|
||||
#endif
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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> 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
|
||||
|
||||
@@ -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<IRemoteObject>& 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
|
||||
|
||||
@@ -7683,5 +7683,32 @@ int32_t AbilityManagerProxy::GetUserLockedBundleList(int32_t userId,
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int32_t AbilityManagerProxy::SetAppRecoveryFlag(const sptr<IRemoteObject>& 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
|
||||
|
||||
@@ -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<IRemoteObject>& 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>& abilityRecord,
|
||||
const sptr<IRemoteObject>& 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<IRemoteObject> &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<IRemoteObject>& remote) {
|
||||
this->HandleAppDiedForRecovery(remote,abilityInfo,pid,uid);
|
||||
};
|
||||
|
||||
AppRecoveryMgr::AppRecoveryMgr::GetInstance().SetOnRemoteDieCallback(token, callback);
|
||||
}
|
||||
|
||||
void AbilityManagerService::HandleAppDiedForRecovery(const sptr<IRemoteObject>& 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<AppExitReasonDataManager>::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<long long>(it->second),
|
||||
static_cast<long long>(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<long long>(now),static_cast<long long>(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<long long>(now),static_cast<long long>(stamp));
|
||||
}
|
||||
if (remote != nullptr) {
|
||||
AppRecoveryMgr::AppRecoveryMgr::GetInstance().RemoveOnRemoteDieCallback(remote);
|
||||
}
|
||||
}
|
||||
} // namespace AAFwk
|
||||
} // namespace OHOS
|
||||
|
||||
@@ -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<IRemoteObject> 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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 <map>
|
||||
#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<IRemoteObject>& abilityToken,
|
||||
const std::function<void(const sptr<IRemoteObject>&)>& callback);
|
||||
|
||||
void RemoveOnRemoteDieCallback(const sptr<IRemoteObject>& abilityToken);
|
||||
|
||||
void HandleAppDied(const sptr<IRemoteObject>& remote);
|
||||
|
||||
void Init(const std::shared_ptr<AppExecFwk::EventHandler>& handler);
|
||||
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
AppRecoveryMgr();
|
||||
~AppRecoveryMgr();
|
||||
std::function<void(const sptr<IRemoteObject>&)> FindCallback(const sptr<IRemoteObject>& remote);
|
||||
|
||||
private:
|
||||
std::mutex mutex_;
|
||||
std::shared_ptr<AppExecFwk::EventHandler> handler_;
|
||||
std::map<sptr<IRemoteObject>, std::function<void(const sptr<IRemoteObject>&)>> dieCallbacks_;
|
||||
};
|
||||
|
||||
} // namespace AppRecoveryMgr
|
||||
} // namespace OHOS
|
||||
|
||||
#endif // OHOS_ABILITY_RUNTIME_APP_RECOVERY_MGR_H
|
||||
@@ -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<AppExecFwk::EventHandler>& handler)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
handler_ = handler;
|
||||
TAG_LOGI(AAFwkTag::APPDFR, "AppRecoveryMgr initialized");
|
||||
}
|
||||
|
||||
void AppRecoveryMgr::SetOnRemoteDieCallback(const sptr<IRemoteObject>& abilityToken,
|
||||
const std::function<void(const sptr<IRemoteObject>&)>& callback)
|
||||
{
|
||||
if (abilityToken == nullptr || callback == nullptr) {
|
||||
TAG_LOGI(AAFwkTag::APPDFR, "SetOnRemoteDieCallback: invalid parameter");
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> 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<IRemoteObject>& abilityToken)
|
||||
{
|
||||
if (abilityToken == nullptr) {
|
||||
TAG_LOGI(AAFwkTag::APPDFR, "RemoveOnRemoteDieCallback: invalid parameter");
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
auto it = dieCallbacks_.find(abilityToken);
|
||||
if (it != dieCallbacks_.end()) {
|
||||
dieCallbacks_.erase(it);
|
||||
TAG_LOGI(AAFwkTag::APPDFR, "RemoveOnRemoteDieCallback: callback removed");
|
||||
}
|
||||
}
|
||||
|
||||
std::function<void(const sptr<IRemoteObject>&)> AppRecoveryMgr::FindCallback(const sptr<IRemoteObject>& remote)
|
||||
{
|
||||
std::lock_guard<std::mutex> 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<IRemoteObject>& 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<std::mutex> lock(mutex_);
|
||||
dieCallbacks_.clear();
|
||||
handler_ = nullptr;
|
||||
TAG_LOGI(AAFwkTag::APPDFR, "AppRecoveryMgr cleared");
|
||||
}
|
||||
|
||||
} // namespace AppRecoveryMgr
|
||||
} // namespace OHOS
|
||||
@@ -2223,6 +2223,8 @@ private:
|
||||
void RemoveUninstallOrUpgradeUidSet(int32_t uid);
|
||||
bool IsUninstallingOrUpgrading(int32_t uid);
|
||||
void SendProcessKillEvent(std::shared_ptr<AppRunningRecord> appRecord);
|
||||
void HandleForegroundAbilityDied(const std::vector<sptr<IRemoteObject>>& abilityTokens,
|
||||
ApplicationState state);
|
||||
|
||||
std::shared_ptr<RemoteClientManager> remoteClientManager_;
|
||||
std::shared_ptr<AppRunningManager> appRunningManager_;
|
||||
|
||||
@@ -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<IRemoteObject> &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<RenderRecord>
|
||||
AppMgrEventUtil::SendRenderProcessStartFailedEvent(renderRecord,
|
||||
ProcessStartFailedReason::ATTACH_TIMEOUT, elapsedMs);
|
||||
}
|
||||
|
||||
void AppMgrServiceInner::HandleForegroundAbilityDied(
|
||||
const std::vector<sptr<IRemoteObject>>& 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
|
||||
|
||||
+10
@@ -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
|
||||
|
||||
+10
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user