mirror of
https://github.com/openharmony/ability_ability_runtime.git
synced 2026-08-25 12:23:20 -04:00
@@ -107,6 +107,7 @@ ohos_shared_library("appkit_native") {
|
||||
"${ability_runtime_native_path}/appkit/app/ability_manager.cpp",
|
||||
"${ability_runtime_native_path}/appkit/app/ability_record_mgr.cpp",
|
||||
"${ability_runtime_native_path}/appkit/app/app_loader.cpp",
|
||||
"${ability_runtime_native_path}/appkit/app/appfreeze_inner.cpp",
|
||||
"${ability_runtime_native_path}/appkit/app/application_data_manager.cpp",
|
||||
"${ability_runtime_native_path}/appkit/app/application_env.cpp",
|
||||
"${ability_runtime_native_path}/appkit/app/application_env_impl.cpp",
|
||||
|
||||
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#include "appfreeze_inner.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "ability_manager_client.h"
|
||||
#include "ability_state.h"
|
||||
#include "app_recovery.h"
|
||||
#include "hilog_wrapper.h"
|
||||
#include "hisysevent.h"
|
||||
#include "mix_stack_dumper.h"
|
||||
#include "parameter.h"
|
||||
#include "xcollie/watchdog.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace AppExecFwk {
|
||||
namespace {
|
||||
constexpr char EVENT_UID[] = "UID";
|
||||
constexpr char EVENT_PID[] = "PID";
|
||||
constexpr char EVENT_MESSAGE[] = "MSG";
|
||||
constexpr char EVENT_PACKAGE_NAME[] = "PACKAGE_NAME";
|
||||
constexpr char EVENT_PROCESS_NAME[] = "PROCESS_NAME";
|
||||
constexpr char EVENT_STACK[] = "STACK";
|
||||
}
|
||||
std::weak_ptr<EventHandler> AppfreezeInner::appMainHandler_;
|
||||
std::shared_ptr<AppfreezeInner> AppfreezeInner::instance_ = nullptr;
|
||||
std::mutex AppfreezeInner::singletonMutex_;
|
||||
|
||||
AppfreezeInner::AppfreezeInner()
|
||||
{}
|
||||
|
||||
AppfreezeInner::~AppfreezeInner()
|
||||
{}
|
||||
|
||||
void AppfreezeInner::SetMainHandler(const std::shared_ptr<EventHandler>& eventHandler)
|
||||
{
|
||||
appMainHandler_ = eventHandler;
|
||||
}
|
||||
|
||||
void AppfreezeInner::SetApplicationInfo(const std::shared_ptr<ApplicationInfo>& applicationInfo)
|
||||
{
|
||||
applicationInfo_ = applicationInfo;
|
||||
}
|
||||
|
||||
std::shared_ptr<AppfreezeInner> AppfreezeInner::GetInstance()
|
||||
{
|
||||
if (instance_ == nullptr) {
|
||||
std::lock_guard<std::mutex> lock(singletonMutex_);
|
||||
if (instance_ == nullptr) {
|
||||
instance_ = std::make_shared<AppfreezeInner>();
|
||||
}
|
||||
}
|
||||
return instance_;
|
||||
}
|
||||
|
||||
void AppfreezeInner::DestroyInstance()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(singletonMutex_);
|
||||
if (instance_ != nullptr) {
|
||||
instance_.reset();
|
||||
instance_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool AppfreezeInner::IsHandleAppfreeze()
|
||||
{
|
||||
auto applicationInfo = applicationInfo_.lock();
|
||||
if (applicationInfo == nullptr) {
|
||||
HILOG_ERROR("applicationInfo_ is nullptr.");
|
||||
return false;
|
||||
}
|
||||
|
||||
const int buffSize = 128;
|
||||
char paramOutBuff[buffSize] = {0};
|
||||
GetParameter("hiviewdfx.appfreeze.filter_bundle_name", "", paramOutBuff, buffSize - 1);
|
||||
|
||||
std::string str(paramOutBuff);
|
||||
std::string& bundleName = applicationInfo->bundleName;
|
||||
if (bundleName.empty()) {
|
||||
return true;
|
||||
}
|
||||
if (str.find(bundleName) != std::string::npos) {
|
||||
HILOG_WARN("appfreeze filtration %{public}s.", bundleName.c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int AppfreezeInner::AppfreezeHandle(const FaultData& faultData, bool onlyMainThread)
|
||||
{
|
||||
if (!IsHandleAppfreeze()) {
|
||||
NotifyANR(faultData);
|
||||
return -1;
|
||||
}
|
||||
auto reportFreeze = [faultData, onlyMainThread]() {
|
||||
if (faultData.errorObject.name == "") {
|
||||
HILOG_ERROR("name is nullptr, AppfreezeHandle failed.");
|
||||
return;
|
||||
}
|
||||
AppExecFwk::AppfreezeInner::GetInstance()->AcquireStack(faultData, onlyMainThread);
|
||||
};
|
||||
|
||||
OHOS::HiviewDFX::Watchdog::GetInstance().RunOneShotTask("reportAppFreeze", reportFreeze);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool AppfreezeInner::IsExitApp(const std::string& name)
|
||||
{
|
||||
if (name == AppFreezeType::THREAD_BLOCK_6S) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (name == AppFreezeType::APP_INPUT_BLOCK) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int AppfreezeInner::AcquireStack(const FaultData& faultInfo, bool onlyMainThread)
|
||||
{
|
||||
HILOG_DEBUG("Start dump mixstack.");
|
||||
std::string stack = MixStackDumper::GetMixStack(onlyMainThread);
|
||||
|
||||
HILOG_DEBUG("Start dump MainHandler message.");
|
||||
std::string msgContent = faultInfo.errorObject.message + "\n";
|
||||
|
||||
auto mainHandler = appMainHandler_.lock();
|
||||
if (mainHandler == nullptr) {
|
||||
msgContent += "mainHandler is destructed!";
|
||||
} else {
|
||||
MainHandlerDumper handlerDumper;
|
||||
msgContent += "mainHandler dump is:\n";
|
||||
mainHandler->Dump(handlerDumper);
|
||||
msgContent += handlerDumper.GetDumpInfo();
|
||||
}
|
||||
|
||||
HILOG_DEBUG("end dump message is %{public}s", msgContent.c_str());
|
||||
|
||||
FaultData faultData;
|
||||
faultData.errorObject.message = msgContent;
|
||||
faultData.errorObject.stack = stack;
|
||||
faultData.errorObject.name = faultInfo.errorObject.name;
|
||||
faultData.faultType = FaultDataType::APP_FREEZE;
|
||||
faultData.timeoutMarkers = faultInfo.timeoutMarkers;
|
||||
faultData.notifyApp = false;
|
||||
faultData.waitSaveState = false;
|
||||
faultData.forceExit = false;
|
||||
bool isExit = IsExitApp(faultInfo.errorObject.name);
|
||||
if (isExit) {
|
||||
faultData.forceExit = true;
|
||||
faultData.waitSaveState = AppRecovery::GetInstance().IsEnabled();
|
||||
}
|
||||
int ret = NotifyANR(faultData);
|
||||
if (isExit) {
|
||||
AppFreezeRecovery();
|
||||
}
|
||||
HILOG_DEBUG("End notify appfreeze");
|
||||
return ret;
|
||||
}
|
||||
|
||||
void AppfreezeInner::ThreadBlock(std::atomic_bool& isSixSecondEvent)
|
||||
{
|
||||
FaultData faultData;
|
||||
faultData.errorObject.message = "App main thread is not response!";
|
||||
faultData.faultType = FaultDataType::APP_FREEZE;
|
||||
faultData.timeoutMarkers = "";
|
||||
bool onlyMainThread = false;
|
||||
|
||||
if (isSixSecondEvent) {
|
||||
faultData.errorObject.name = AppFreezeType::THREAD_BLOCK_6S;
|
||||
onlyMainThread = true;
|
||||
} else {
|
||||
faultData.errorObject.name = AppFreezeType::THREAD_BLOCK_3S;
|
||||
isSixSecondEvent.store(true);
|
||||
}
|
||||
|
||||
AppfreezeHandle(faultData, onlyMainThread);
|
||||
}
|
||||
|
||||
int AppfreezeInner::NotifyANR(const FaultData& faultData)
|
||||
{
|
||||
auto applicationInfo = applicationInfo_.lock();
|
||||
if (applicationInfo == nullptr) {
|
||||
HILOG_ERROR("reportEvent fail, applicationInfo_ is nullptr.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t pid = static_cast<int32_t>(getpid());
|
||||
HILOG_INFO("reportEvent:%{public}s, pid:%{public}d, bundleName:%{public}s. success",
|
||||
faultData.errorObject.name.c_str(), pid, applicationInfo->bundleName.c_str());
|
||||
|
||||
// move this call before force stop app ? such as merge to NotifyAppFault ?
|
||||
DelayedSingleton<AbilityManagerClient>::GetInstance()->RecordAppExitReason(REASON_APP_FREEZE);
|
||||
int ret = DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance()->NotifyAppFault(faultData);
|
||||
if (ret != 0) {
|
||||
HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::AAFWK, faultData.errorObject.name,
|
||||
OHOS::HiviewDFX::HiSysEvent::EventType::FAULT, EVENT_UID, applicationInfo->uid,
|
||||
EVENT_PID, pid, EVENT_PACKAGE_NAME, applicationInfo->bundleName,
|
||||
EVENT_PROCESS_NAME, applicationInfo->process, EVENT_MESSAGE,
|
||||
faultData.errorObject.message, EVENT_STACK, faultData.errorObject.stack);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void AppfreezeInner::AppFreezeRecovery()
|
||||
{
|
||||
AppRecovery::GetInstance().ScheduleSaveAppState(StateReason::APP_FREEZE);
|
||||
AppRecovery::GetInstance().ScheduleRecoverApp(StateReason::APP_FREEZE);
|
||||
}
|
||||
|
||||
void MainHandlerDumper::Dump(const std::string &message)
|
||||
{
|
||||
dumpInfo += message;
|
||||
}
|
||||
|
||||
std::string MainHandlerDumper::GetTag()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string MainHandlerDumper::GetDumpInfo()
|
||||
{
|
||||
return dumpInfo;
|
||||
}
|
||||
} // namespace AAFwk
|
||||
} // namespace OHOS
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "ability_util.h"
|
||||
#include "app_loader.h"
|
||||
#include "app_recovery.h"
|
||||
#include "appfreeze_inner.h"
|
||||
#include "application_data_manager.h"
|
||||
#include "application_env_impl.h"
|
||||
#include "bundle_mgr_proxy.h"
|
||||
@@ -893,10 +894,7 @@ bool MainThread::InitCreate(
|
||||
HILOG_ERROR("MainThread::InitCreate create contextDeal failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (watchdog_ != nullptr) {
|
||||
watchdog_->SetApplicationInfo(applicationInfo_);
|
||||
}
|
||||
AppExecFwk::AppfreezeInner::GetInstance()->SetApplicationInfo(applicationInfo_);
|
||||
|
||||
application_->SetProcessInfo(processInfo_);
|
||||
contextDeal->SetApplicationInfo(applicationInfo_);
|
||||
@@ -2032,6 +2030,7 @@ void MainThread::Init(const std::shared_ptr<EventRunner> &runner)
|
||||
TaskTimeoutDetected(runner);
|
||||
|
||||
watchdog_->Init(mainHandler_);
|
||||
AppExecFwk::AppfreezeInner::GetInstance()->SetMainHandler(mainHandler_);
|
||||
extensionConfigMgr_->Init();
|
||||
}
|
||||
|
||||
@@ -2511,6 +2510,11 @@ int32_t MainThread::ScheduleNotifyAppFault(const FaultData &faultData)
|
||||
HILOG_ERROR("mainHandler is nullptr");
|
||||
return ERR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
if (faultData.faultType == FaultDataType::APP_FREEZE) {
|
||||
return AppExecFwk::AppfreezeInner::GetInstance()->AppfreezeHandle(faultData, false);
|
||||
}
|
||||
|
||||
wptr<MainThread> weak = this;
|
||||
auto task = [weak, faultData] {
|
||||
auto appThread = weak.promote();
|
||||
@@ -2526,12 +2530,14 @@ int32_t MainThread::ScheduleNotifyAppFault(const FaultData &faultData)
|
||||
|
||||
void MainThread::NotifyAppFault(const FaultData &faultData)
|
||||
{
|
||||
ErrorObject faultErrorObj = {
|
||||
.name = faultData.errorObject.name,
|
||||
.message = faultData.errorObject.message,
|
||||
.stack = faultData.errorObject.stack
|
||||
};
|
||||
ApplicationDataManager::GetInstance().NotifyExceptionObject(faultErrorObj);
|
||||
if (faultData.notifyApp) {
|
||||
ErrorObject faultErrorObj = {
|
||||
.name = faultData.errorObject.name,
|
||||
.message = faultData.errorObject.message,
|
||||
.stack = faultData.errorObject.stack
|
||||
};
|
||||
ApplicationDataManager::GetInstance().NotifyExceptionObject(faultErrorObj);
|
||||
}
|
||||
}
|
||||
|
||||
void MainThread::SetProcessExtensionType(const std::shared_ptr<AbilityLocalRecord> &abilityRecord)
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "app_mgr_client.h"
|
||||
#include "app_recovery.h"
|
||||
#include "appfreeze_inner.h"
|
||||
#include "hisysevent.h"
|
||||
#include "hilog_wrapper.h"
|
||||
#include "mix_stack_dumper.h"
|
||||
@@ -28,12 +29,6 @@
|
||||
namespace OHOS {
|
||||
namespace AppExecFwk {
|
||||
namespace {
|
||||
constexpr char EVENT_KEY_UID[] = "UID";
|
||||
constexpr char EVENT_KEY_PID[] = "PID";
|
||||
constexpr char EVENT_KEY_MESSAGE[] = "MSG";
|
||||
constexpr char EVENT_KEY_PACKAGE_NAME[] = "PACKAGE_NAME";
|
||||
constexpr char EVENT_KEY_PROCESS_NAME[] = "PROCESS_NAME";
|
||||
constexpr char EVENT_KEY_STACK[] = "STACK";
|
||||
constexpr uint32_t CHECK_MAIN_THREAD_IS_ALIVE = 1;
|
||||
constexpr int RESET_RATIO = 2;
|
||||
|
||||
@@ -87,11 +82,6 @@ void Watchdog::Stop()
|
||||
}
|
||||
}
|
||||
|
||||
void Watchdog::SetApplicationInfo(const std::shared_ptr<ApplicationInfo> &applicationInfo)
|
||||
{
|
||||
applicationInfo_ = applicationInfo;
|
||||
}
|
||||
|
||||
void Watchdog::SetAppMainThreadState(const bool appMainThreadState)
|
||||
{
|
||||
appMainThreadIsAlive_.store(appMainThreadState);
|
||||
@@ -170,65 +160,14 @@ void Watchdog::ReportEvent()
|
||||
return;
|
||||
}
|
||||
|
||||
if (applicationInfo_ == nullptr) {
|
||||
HILOG_ERROR("reportEvent fail, applicationInfo_ is nullptr.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!needReport_) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string eventType;
|
||||
std::string stack = "";
|
||||
if (isSixSecondEvent_) {
|
||||
eventType = "THREAD_BLOCK_6S";
|
||||
needReport_.store(false);
|
||||
stack = MixStackDumper::GetMixStack(true);
|
||||
} else {
|
||||
eventType = "THREAD_BLOCK_3S";
|
||||
isSixSecondEvent_.store(true);
|
||||
stack = MixStackDumper::GetMixStack(false);
|
||||
}
|
||||
|
||||
HILOG_DEBUG("Start dump message.");
|
||||
std::string msgContent = "App main thread is not response!";
|
||||
MainHandlerDumper handlerDumper;
|
||||
appMainHandler_->Dump(handlerDumper);
|
||||
msgContent += handlerDumper.GetDumpInfo();
|
||||
HILOG_DEBUG("msgContent is %{public}s", msgContent.c_str());
|
||||
HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::AAFWK, eventType,
|
||||
OHOS::HiviewDFX::HiSysEvent::EventType::FAULT, EVENT_KEY_UID, applicationInfo_->uid,
|
||||
EVENT_KEY_PID, static_cast<int32_t>(getpid()), EVENT_KEY_PACKAGE_NAME, applicationInfo_->bundleName,
|
||||
EVENT_KEY_PROCESS_NAME, applicationInfo_->process, EVENT_KEY_MESSAGE, msgContent, EVENT_KEY_STACK, stack);
|
||||
HILOG_INFO("reportEvent success");
|
||||
HILOG_DEBUG("reportEvent info, %{public}zu %{public}s", msgContent.size(), msgContent.c_str());
|
||||
// should call error manager-> appRecovery
|
||||
if (eventType == "THREAD_BLOCK_6S") {
|
||||
AppRecovery::GetInstance().ScheduleSaveAppState(StateReason::APP_FREEZE);
|
||||
AppRecovery::GetInstance().ScheduleRecoverApp(StateReason::APP_FREEZE);
|
||||
FaultData faultData;
|
||||
faultData.faultType = FaultDataType::APP_FREEZE;
|
||||
faultData.errorObject.message = msgContent;
|
||||
faultData.errorObject.stack = stack;
|
||||
faultData.errorObject.name = eventType;
|
||||
DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance()->NotifyAppFault(faultData);
|
||||
}
|
||||
}
|
||||
|
||||
void MainHandlerDumper::Dump(const std::string &message)
|
||||
{
|
||||
dumpInfo += message;
|
||||
}
|
||||
|
||||
std::string MainHandlerDumper::GetTag()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string MainHandlerDumper::GetDumpInfo()
|
||||
{
|
||||
return dumpInfo;
|
||||
AppExecFwk::AppfreezeInner::GetInstance()->ThreadBlock(isSixSecondEvent_);
|
||||
}
|
||||
} // namespace AppExecFwk
|
||||
} // namespace OHOS
|
||||
|
||||
@@ -20,6 +20,16 @@ LIFECYCLE_TIMEOUT:
|
||||
PACKAGE_NAME: {type: STRING, desc: package name}
|
||||
PROCESS_NAME: {type: STRING, desc: process name}
|
||||
MSG: {type: STRING, desc: application event message}
|
||||
STACK: {type: STRING, desc: main thread stacktrace}
|
||||
|
||||
LIFECYCLE_HALF_TIMEOUT:
|
||||
__BASE: {type: FAULT, level: CRITICAL, tag: STABILITY, desc: ability timeout}
|
||||
PID: {type: INT32, desc: process id}
|
||||
UID: {type: INT32, desc: app uid}
|
||||
PACKAGE_NAME: {type: STRING, desc: package name}
|
||||
PROCESS_NAME: {type: STRING, desc: process name}
|
||||
MSG: {type: STRING, desc: application event message}
|
||||
STACK: {type: STRING, desc: main thread stacktrace}
|
||||
|
||||
APP_LIFECYCLE_TIMEOUT:
|
||||
__BASE: {type: FAULT, level: CRITICAL, tag: STABILITY, desc: application timeout}
|
||||
@@ -57,6 +67,14 @@ THREAD_BLOCK_6S:
|
||||
MSG: {type: STRING, desc: application event message}
|
||||
STACK: {type: STRING, desc: main thread stacktrace}
|
||||
|
||||
APP_INPUT_BLOCK:
|
||||
__BASE: {type: FAULT, level: CRITICAL, tag: STABILITY, desc: application freeze}
|
||||
PID: {type: INT32, desc: process id}
|
||||
UID: {type: INT32, desc: app uid}
|
||||
PACKAGE_NAME: {type: STRING, desc: package name}
|
||||
PROCESS_NAME: {type: STRING, desc: process name}
|
||||
MSG: {type: STRING, desc: application event message}
|
||||
STACK: {type: STRING, desc: main thread stacktrace}
|
||||
# fault event
|
||||
|
||||
START_ABILITY_ERROR:
|
||||
|
||||
@@ -68,6 +68,7 @@ ohos_shared_library("app_manager") {
|
||||
"src/appmgr/app_state_callback_proxy.cpp",
|
||||
"src/appmgr/app_state_data.cpp",
|
||||
"src/appmgr/app_task_info.cpp",
|
||||
"src/appmgr/appfreeze_manager.cpp",
|
||||
"src/appmgr/application_state_observer_proxy.cpp",
|
||||
"src/appmgr/application_state_observer_stub.cpp",
|
||||
"src/appmgr/component_interception_proxy.cpp",
|
||||
@@ -107,8 +108,13 @@ ohos_shared_library("app_manager") {
|
||||
"ability_base:want",
|
||||
"bundle_framework:appexecfwk_base",
|
||||
"c_utils:utils",
|
||||
"faultloggerd:libdfx_dumpcatcher",
|
||||
"faultloggerd:libfaultloggerd",
|
||||
"ffrt:libffrt",
|
||||
"hilog:libhilog",
|
||||
"hisysevent:libhisysevent",
|
||||
"hitrace:hitrace_meter",
|
||||
"init:libbegetutil",
|
||||
"ipc:ipc_core",
|
||||
"samgr:samgr_proxy",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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_APPFREEZE_MAMAGER_H
|
||||
#define OHOS_ABILITY_RUNTIME_APPFREEZE_MAMAGER_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "cpp/mutex.h"
|
||||
#include "cpp/condition_variable.h"
|
||||
#include "fault_data.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace AppExecFwk {
|
||||
class AppfreezeManager : public std::enable_shared_from_this<AppfreezeManager> {
|
||||
public:
|
||||
struct AppInfo {
|
||||
int pid;
|
||||
int uid;
|
||||
std::string bundleName;
|
||||
std::string processName;
|
||||
};
|
||||
|
||||
enum TypeAttribute {
|
||||
NORMAL_TIMEOUT = 0,
|
||||
CRITICAL_TIMEOUT = 1,
|
||||
};
|
||||
|
||||
AppfreezeManager();
|
||||
~AppfreezeManager();
|
||||
|
||||
static std::shared_ptr<AppfreezeManager> GetInstance();
|
||||
static void DestroyInstance();
|
||||
int AppfreezeHandle(const FaultData& faultData, const AppfreezeManager::AppInfo& appInfo);
|
||||
int AppfreezeHandleWithStack(const FaultData& faultData, const AppfreezeManager::AppInfo& appInfo);
|
||||
int LifecycleTimeoutHandle(int typeId, int32_t pid, const std::string& eventName,
|
||||
const std::string& bundleName, const std::string& msg);
|
||||
bool IsHandleAppfreeze(const std::string& bundleName);
|
||||
|
||||
private:
|
||||
AppfreezeManager& operator=(const AppfreezeManager&) = delete;
|
||||
AppfreezeManager(const AppfreezeManager&) = delete;
|
||||
uint64_t GetMilliseconds();
|
||||
std::map<int, std::set<int>> BinderParser(std::ifstream& fin, std::string& stack) const;
|
||||
void ParseBinderPids(const std::map<int, std::set<int>>& binderInfo, std::set<int>& pids, int pid) const;
|
||||
std::set<int> GetBinderPeerPids(std::string& stack, int pid) const;
|
||||
std::string CatcherStacktrace(int pid) const;
|
||||
int AcquireStack(const FaultData& faultData, const AppInfo& appInfo);
|
||||
int NotifyANR(const FaultData& faultData, const AppfreezeManager::AppInfo& appInfo);
|
||||
|
||||
static const inline std::string LOGGER_DEBUG_PROC_PATH = "/proc/transaction_proc";
|
||||
ffrt::mutex lifecycleMutex_;
|
||||
ffrt::condition_variable lifecycleCv_;
|
||||
std::set<std::string> lifecycleTimeOutMarks_;
|
||||
std::string name_;
|
||||
static ffrt::mutex singletonMutex_;
|
||||
static std::shared_ptr<AppfreezeManager> instance_;
|
||||
};
|
||||
} // namespace AppExecFwk
|
||||
} // namespace OHOS
|
||||
#endif // OHOS_ABILITY_RUNTIME_APPFREEZE_MAMAGER_H
|
||||
@@ -37,6 +37,15 @@ enum class FaultDataType {
|
||||
RESOURCE_CONTROL
|
||||
};
|
||||
|
||||
class AppFreezeType {
|
||||
public:
|
||||
static constexpr char LIFECYCLE_HALF_TIMEOUT[] = "LIFECYCLE_HALF_TIMEOUT";
|
||||
static constexpr char LIFECYCLE_TIMEOUT[] = "LIFECYCLE_TIMEOUT";
|
||||
static constexpr char APP_LIFECYCLE_TIMEOUT[] = "APP_LIFECYCLE_TIMEOUT";
|
||||
static constexpr char THREAD_BLOCK_3S[] = "THREAD_BLOCK_3S";
|
||||
static constexpr char THREAD_BLOCK_6S[] = "THREAD_BLOCK_6S";
|
||||
static constexpr char APP_INPUT_BLOCK[] = "APP_INPUT_BLOCK";
|
||||
};
|
||||
/**
|
||||
* @struct FaultData
|
||||
* FaultData is used to save information about faultdata.
|
||||
@@ -48,6 +57,10 @@ struct FaultData : public Parcelable {
|
||||
// error object
|
||||
ErrorObject errorObject;
|
||||
FaultDataType faultType = FaultDataType::UNKNOWN;
|
||||
std::string timeoutMarkers;
|
||||
bool waitSaveState = false;
|
||||
bool notifyApp = false;
|
||||
bool forceExit = false;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -62,6 +75,10 @@ struct AppFaultDataBySA : public Parcelable {
|
||||
ErrorObject errorObject;
|
||||
FaultDataType faultType = FaultDataType::UNKNOWN;
|
||||
int32_t pid = -1;
|
||||
std::string timeoutMarkers;
|
||||
bool waitSaveState = false;
|
||||
bool notifyApp = false;
|
||||
bool forceExit = false;
|
||||
};
|
||||
} // namespace AppExecFwk
|
||||
} // namespace OHOS
|
||||
|
||||
@@ -577,7 +577,7 @@ int32_t AppSchedulerProxy::ScheduleNotifyAppFault(const FaultData &faultData)
|
||||
}
|
||||
|
||||
MessageParcel reply;
|
||||
MessageOption option;
|
||||
MessageOption option(MessageOption::TF_ASYNC);
|
||||
auto ret = remote->SendRequest(static_cast<uint32_t>(IAppScheduler::Message::SCHEDULE_NOTIFY_FAULT),
|
||||
data, reply, option);
|
||||
if (ret != NO_ERROR) {
|
||||
|
||||
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#include "appfreeze_manager.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "faultloggerd_client.h"
|
||||
#include "file_ex.h"
|
||||
#include "dfx_dump_catcher.h"
|
||||
#include "directory_ex.h"
|
||||
#include "hisysevent.h"
|
||||
#include "parameter.h"
|
||||
#include "singleton.h"
|
||||
|
||||
#include "app_mgr_client.h"
|
||||
#include "hilog_wrapper.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace AppExecFwk {
|
||||
namespace {
|
||||
constexpr char EVENT_UID[] = "UID";
|
||||
constexpr char EVENT_PID[] = "PID";
|
||||
constexpr char EVENT_MESSAGE[] = "MSG";
|
||||
constexpr char EVENT_PACKAGE_NAME[] = "PACKAGE_NAME";
|
||||
constexpr char EVENT_PROCESS_NAME[] = "PROCESS_NAME";
|
||||
constexpr char EVENT_STACK[] = "STACK";
|
||||
}
|
||||
std::shared_ptr<AppfreezeManager> AppfreezeManager::instance_ = nullptr;
|
||||
ffrt::mutex AppfreezeManager::singletonMutex_;
|
||||
|
||||
AppfreezeManager::AppfreezeManager()
|
||||
{
|
||||
name_ = "AppfreezeManager" + std::to_string(GetMilliseconds());
|
||||
}
|
||||
|
||||
AppfreezeManager::~AppfreezeManager()
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<AppfreezeManager> AppfreezeManager::GetInstance()
|
||||
{
|
||||
if (instance_ == nullptr) {
|
||||
std::lock_guard<ffrt::mutex> lock(singletonMutex_);
|
||||
if (instance_ == nullptr) {
|
||||
instance_ = std::make_shared<AppfreezeManager>();
|
||||
}
|
||||
}
|
||||
return instance_;
|
||||
}
|
||||
|
||||
void AppfreezeManager::DestroyInstance()
|
||||
{
|
||||
std::lock_guard<ffrt::mutex> lock(singletonMutex_);
|
||||
if (instance_ != nullptr) {
|
||||
instance_.reset();
|
||||
instance_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t AppfreezeManager::GetMilliseconds()
|
||||
{
|
||||
auto now = std::chrono::system_clock::now();
|
||||
auto millisecs = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
|
||||
return millisecs.count();
|
||||
}
|
||||
|
||||
bool AppfreezeManager::IsHandleAppfreeze(const std::string& bundleName)
|
||||
{
|
||||
if (bundleName.empty()) {
|
||||
return true;
|
||||
}
|
||||
const int buffSize = 128;
|
||||
char paramOutBuff[buffSize] = {0};
|
||||
GetParameter("hiviewdfx.appfreeze.filter_bundle_name", "", paramOutBuff, buffSize - 1);
|
||||
|
||||
std::string str(paramOutBuff);
|
||||
if (str.find(bundleName) != std::string::npos) {
|
||||
HILOG_WARN("appfreeze filtration %{public}s.", bundleName.c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int AppfreezeManager::AppfreezeHandle(const FaultData& faultData, const AppfreezeManager::AppInfo& appInfo)
|
||||
{
|
||||
HILOG_DEBUG("called %{public}s, bundleName %{public}s, name_ %{public}s",
|
||||
faultData.errorObject.name.c_str(), appInfo.bundleName.c_str(), name_.c_str());
|
||||
if (!IsHandleAppfreeze(appInfo.bundleName)) {
|
||||
return -1;
|
||||
}
|
||||
if (faultData.errorObject.name == AppFreezeType::APP_INPUT_BLOCK) {
|
||||
AcquireStack(faultData, appInfo);
|
||||
} else if (faultData.errorObject.name == AppFreezeType::LIFECYCLE_TIMEOUT ||
|
||||
faultData.errorObject.name == AppFreezeType::LIFECYCLE_HALF_TIMEOUT) {
|
||||
NotifyANR(faultData, appInfo);
|
||||
{
|
||||
std::unique_lock<ffrt::mutex> lock(lifecycleMutex_);
|
||||
lifecycleTimeOutMarks_.erase(faultData.timeoutMarkers);
|
||||
}
|
||||
lifecycleCv_.notify_all();
|
||||
} else {
|
||||
NotifyANR(faultData, appInfo);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AppfreezeManager::AppfreezeHandleWithStack(const FaultData& faultData, const AppfreezeManager::AppInfo& appInfo)
|
||||
{
|
||||
HILOG_DEBUG("called %{public}s, bundleName %{public}s, name_ %{public}s",
|
||||
faultData.errorObject.name.c_str(), appInfo.bundleName.c_str(), name_.c_str());
|
||||
if (!IsHandleAppfreeze(appInfo.bundleName)) {
|
||||
return -1;
|
||||
}
|
||||
FaultData faultNotifyData;
|
||||
faultNotifyData.errorObject.name = faultData.errorObject.name;
|
||||
faultNotifyData.errorObject.message = faultData.errorObject.message;
|
||||
faultNotifyData.errorObject.stack = faultData.errorObject.stack + "\n";
|
||||
faultNotifyData.faultType = FaultDataType::APP_FREEZE;
|
||||
faultNotifyData.errorObject.stack += CatcherStacktrace(appInfo.pid);
|
||||
return AppfreezeHandle(faultNotifyData, appInfo);
|
||||
}
|
||||
|
||||
int AppfreezeManager::LifecycleTimeoutHandle(int typeId, int32_t pid,
|
||||
const std::string& eventName, const std::string& bundleName, const std::string& msg)
|
||||
{
|
||||
if (typeId != AppfreezeManager::TypeAttribute::CRITICAL_TIMEOUT) {
|
||||
return -1;
|
||||
}
|
||||
if (!IsHandleAppfreeze(bundleName)) {
|
||||
return -1;
|
||||
}
|
||||
if (eventName != AppFreezeType::LIFECYCLE_TIMEOUT &&
|
||||
eventName != AppFreezeType::LIFECYCLE_HALF_TIMEOUT) {
|
||||
return -1;
|
||||
}
|
||||
HILOG_DEBUG("LifecycleTimeoutHandle called %{public}s, name_ %{public}s",
|
||||
bundleName.c_str(), name_.c_str());
|
||||
AppFaultDataBySA faultDataSA;
|
||||
faultDataSA.errorObject.name = eventName;
|
||||
faultDataSA.errorObject.message = msg;
|
||||
faultDataSA.faultType = FaultDataType::APP_FREEZE;
|
||||
faultDataSA.timeoutMarkers = "notifyFault" +
|
||||
std::to_string(pid) +
|
||||
"-" + std::to_string(GetMilliseconds());
|
||||
faultDataSA.pid = pid;
|
||||
DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance()->NotifyAppFaultBySA(faultDataSA);
|
||||
auto lcTimeout = 3500; // ms
|
||||
std::chrono::milliseconds timeout { lcTimeout };
|
||||
std::unique_lock<ffrt::mutex> lock(lifecycleMutex_);
|
||||
lifecycleTimeOutMarks_.insert(faultDataSA.timeoutMarkers);
|
||||
auto ret = lifecycleCv_.wait_for(lock, timeout,
|
||||
[t = shared_from_this(), marker = faultDataSA.timeoutMarkers] {
|
||||
return t->lifecycleTimeOutMarks_.find(marker) == t->lifecycleTimeOutMarks_.end();
|
||||
});
|
||||
if (!ret) {
|
||||
lifecycleTimeOutMarks_.erase(faultDataSA.timeoutMarkers);
|
||||
HILOG_WARN("LifecycleTimeoutHandle timeout, name_ %{public}s", name_.c_str());
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AppfreezeManager::AcquireStack(const FaultData& faultData, const AppfreezeManager::AppInfo& appInfo)
|
||||
{
|
||||
int ret = 0;
|
||||
int pid = appInfo.pid;
|
||||
FaultData faultNotifyData;
|
||||
faultNotifyData.errorObject.name = faultData.errorObject.name;
|
||||
faultNotifyData.errorObject.message = faultData.errorObject.message;
|
||||
faultNotifyData.errorObject.stack = faultData.errorObject.stack + "\n";
|
||||
faultNotifyData.faultType = FaultDataType::APP_FREEZE;
|
||||
std::string& stack = faultNotifyData.errorObject.stack;
|
||||
std::set<int> pids = GetBinderPeerPids(faultNotifyData.errorObject.stack, pid);
|
||||
if (pids.empty()) {
|
||||
stack += "PeerBinder pids is empty\n";
|
||||
}
|
||||
for (auto& pidTemp : pids) {
|
||||
HILOG_INFO("pidTemp pids:%{public}d", pidTemp);
|
||||
if (pidTemp != pid) {
|
||||
std::string content = "PeerBinder catcher stacktrace for pid : " + std::to_string(pidTemp) + "\n";
|
||||
content += CatcherStacktrace(pidTemp);
|
||||
stack += content;
|
||||
}
|
||||
}
|
||||
|
||||
ret = NotifyANR(faultNotifyData, appInfo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int AppfreezeManager::NotifyANR(const FaultData& faultData, const AppfreezeManager::AppInfo& appInfo)
|
||||
{
|
||||
HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::AAFWK, faultData.errorObject.name,
|
||||
OHOS::HiviewDFX::HiSysEvent::EventType::FAULT, EVENT_UID, appInfo.uid,
|
||||
EVENT_PID, appInfo.pid, EVENT_PACKAGE_NAME, appInfo.bundleName,
|
||||
EVENT_PROCESS_NAME, appInfo.processName, EVENT_MESSAGE,
|
||||
faultData.errorObject.message, EVENT_STACK, faultData.errorObject.stack);
|
||||
|
||||
HILOG_INFO("reportEvent:%{public}s, pid:%{public}d, bundleName:%{public}s. success",
|
||||
faultData.errorObject.name.c_str(), appInfo.pid, appInfo.bundleName.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::map<int, std::set<int>> AppfreezeManager::BinderParser(std::ifstream& fin, std::string& stack) const
|
||||
{
|
||||
std::map<int, std::set<int>> binderInfo;
|
||||
const int decimal = 10;
|
||||
std::string line;
|
||||
bool isBinderMatchup = false;
|
||||
stack += "BinderCatcher --\n\n";
|
||||
while (getline(fin, line)) {
|
||||
stack += line + "\n";
|
||||
if (isBinderMatchup) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.find("async") != std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::istringstream lineStream(line);
|
||||
std::vector<std::string> strList;
|
||||
std::string tmpstr;
|
||||
while (lineStream >> tmpstr) {
|
||||
strList.push_back(tmpstr);
|
||||
}
|
||||
|
||||
auto SplitPhase = [](const std::string& str, uint16_t index) -> std::string {
|
||||
std::vector<std::string> strings;
|
||||
SplitStr(str, ":", strings);
|
||||
if (index < strings.size()) {
|
||||
return strings[index];
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
||||
if (strList.size() == 7) { // 7: valid array size
|
||||
// 2: peer id,
|
||||
std::string server = SplitPhase(strList[2], 0);
|
||||
// 0: local id,
|
||||
std::string client = SplitPhase(strList[0], 0);
|
||||
// 5: wait time, s
|
||||
std::string wait = SplitPhase(strList[5], 1);
|
||||
if (server == "" || client == "" || wait == "") {
|
||||
continue;
|
||||
}
|
||||
int serverNum = std::strtol(server.c_str(), nullptr, decimal);
|
||||
int clientNum = std::strtol(client.c_str(), nullptr, decimal);
|
||||
int waitNum = std::strtol(wait.c_str(), nullptr, decimal);
|
||||
HILOG_INFO("server:%{public}d, client:%{public}d, wait:%{public}d", serverNum, clientNum, waitNum);
|
||||
binderInfo[clientNum].insert(serverNum);
|
||||
}
|
||||
if (line.find("context") != line.npos) {
|
||||
isBinderMatchup = true;
|
||||
}
|
||||
}
|
||||
HILOG_INFO("binderInfo size: %{public}zu", binderInfo.size());
|
||||
return binderInfo;
|
||||
}
|
||||
|
||||
std::set<int> AppfreezeManager::GetBinderPeerPids(std::string& stack, int pid) const
|
||||
{
|
||||
std::set<int> pids;
|
||||
std::ifstream fin;
|
||||
std::string path = LOGGER_DEBUG_PROC_PATH;
|
||||
fin.open(path.c_str());
|
||||
if (!fin.is_open()) {
|
||||
HILOG_ERROR("open file failed, %{public}s.", path.c_str());
|
||||
stack += "open file failed :" + path + "\r\n";
|
||||
return pids;
|
||||
}
|
||||
|
||||
stack += "\n\nPeerBinderCatcher -- pid==" + std::to_string(pid) + "\n\n";
|
||||
std::map<int, std::set<int>> binderInfo = BinderParser(fin, stack);
|
||||
fin.close();
|
||||
|
||||
if (binderInfo.size() == 0 || binderInfo.find(pid) == binderInfo.end()) {
|
||||
return pids;
|
||||
}
|
||||
|
||||
ParseBinderPids(binderInfo, pids, pid);
|
||||
for (auto& each : pids) {
|
||||
HILOG_DEBUG("each pids:%{public}d", each);
|
||||
}
|
||||
return pids;
|
||||
}
|
||||
|
||||
void AppfreezeManager::ParseBinderPids(const std::map<int, std::set<int>>& binderInfo,
|
||||
std::set<int>& pids, int pid) const
|
||||
{
|
||||
auto it = binderInfo.find(pid);
|
||||
if (it != binderInfo.end()) {
|
||||
for (auto& each : it->second) {
|
||||
pids.insert(each);
|
||||
ParseBinderPids(binderInfo, pids, each);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string AppfreezeManager::CatcherStacktrace(int pid) const
|
||||
{
|
||||
HiviewDFX::DfxDumpCatcher dumplog;
|
||||
std::string ret;
|
||||
std::string msg;
|
||||
if (!dumplog.DumpCatch(pid, 0, msg)) {
|
||||
ret = "Failed to dump stacktrace for " + std::to_string(pid) + "\n" + msg;
|
||||
} else {
|
||||
ret = msg;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
} // namespace AAFwk
|
||||
} // namespace OHOS
|
||||
@@ -43,6 +43,15 @@ bool FaultData::ReadFromParcel(Parcel &parcel)
|
||||
return false;
|
||||
}
|
||||
faultType = static_cast<FaultDataType>(type);
|
||||
|
||||
if (!parcel.ReadString(strValue)) {
|
||||
return false;
|
||||
}
|
||||
timeoutMarkers = strValue;
|
||||
|
||||
waitSaveState = parcel.ReadBool();
|
||||
notifyApp = parcel.ReadBool();
|
||||
forceExit = parcel.ReadBool();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -73,6 +82,22 @@ bool FaultData::Marshalling(Parcel &parcel) const
|
||||
if (!parcel.WriteInt32(static_cast<int32_t>(faultType))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!parcel.WriteString(timeoutMarkers)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!parcel.WriteBool(waitSaveState)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!parcel.WriteBool(notifyApp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!parcel.WriteBool(forceExit)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -103,6 +128,15 @@ bool AppFaultDataBySA::ReadFromParcel(Parcel &parcel)
|
||||
if (!parcel.ReadInt32(pid)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!parcel.ReadString(strValue)) {
|
||||
return false;
|
||||
}
|
||||
timeoutMarkers = strValue;
|
||||
|
||||
waitSaveState = parcel.ReadBool();
|
||||
notifyApp = parcel.ReadBool();
|
||||
forceExit = parcel.ReadBool();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -137,6 +171,22 @@ bool AppFaultDataBySA::Marshalling(Parcel &parcel) const
|
||||
if (!parcel.WriteInt32(pid)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!parcel.WriteString(timeoutMarkers)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!parcel.WriteBool(waitSaveState)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!parcel.WriteBool(notifyApp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!parcel.WriteBool(forceExit)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} // namespace AppExecFwk
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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_ABILITY_APPFREEZE_LOG_CLIENT_H
|
||||
#define OHOS_ABILITY_ABILITY_APPFREEZE_LOG_CLIENT_H
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <set>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "refbase.h"
|
||||
#include "singleton.h"
|
||||
|
||||
#include "event_handler.h"
|
||||
#include "app_mgr_client.h"
|
||||
#include "app_mgr_interface.h"
|
||||
#include "application_impl.h"
|
||||
#include "fault_data.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace AppExecFwk {
|
||||
class AppfreezeInner {
|
||||
public:
|
||||
AppfreezeInner();
|
||||
~AppfreezeInner();
|
||||
static std::shared_ptr<AppfreezeInner> GetInstance();
|
||||
static void DestroyInstance();
|
||||
static void SetMainHandler(const std::shared_ptr<EventHandler>& eventHandler);
|
||||
void SetApplicationInfo(const std::shared_ptr<ApplicationInfo>& applicationInfo);
|
||||
void ThreadBlock(std::atomic_bool& isSixSecondEvent);
|
||||
int AppfreezeHandle(const FaultData& faultInfo, bool onlyMainThread);
|
||||
int AcquireStack(const FaultData& faultInfo, bool onlyMainThread);
|
||||
private:
|
||||
static std::weak_ptr<EventHandler> appMainHandler_;
|
||||
std::weak_ptr<ApplicationInfo> applicationInfo_;
|
||||
void AppFreezeRecovery();
|
||||
int NotifyANR(const FaultData& faultData);
|
||||
bool IsExitApp(const std::string& name);
|
||||
bool IsHandleAppfreeze();
|
||||
|
||||
static std::mutex singletonMutex_;
|
||||
static std::shared_ptr<AppfreezeInner> instance_;
|
||||
};
|
||||
|
||||
class MainHandlerDumper : public Dumper {
|
||||
public:
|
||||
virtual void Dump(const std::string &message) override;
|
||||
virtual std::string GetTag() override;
|
||||
std::string GetDumpInfo();
|
||||
private:
|
||||
std::string dumpInfo;
|
||||
};
|
||||
} // namespace AppExecFwk
|
||||
} // namespace OHOS
|
||||
#endif // OHOS_ABILITY_ABILITY_APPFREEZE_LOG_CLIENT_H
|
||||
@@ -47,14 +47,6 @@ public:
|
||||
*/
|
||||
void Stop();
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Set the info of application.
|
||||
*
|
||||
* @param applicationInfo The info of application
|
||||
*/
|
||||
void SetApplicationInfo(const std::shared_ptr<ApplicationInfo> &applicationInfo);
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Set the state of main thread.
|
||||
@@ -100,21 +92,11 @@ private:
|
||||
std::atomic_bool needReport_ = true;
|
||||
std::atomic_bool isSixSecondEvent_ = false;
|
||||
std::atomic_bool isInBackground_ = true;
|
||||
std::shared_ptr<ApplicationInfo> applicationInfo_ = nullptr;
|
||||
std::mutex cvMutex_;
|
||||
std::condition_variable cvWatchdog_;
|
||||
static std::shared_ptr<EventHandler> appMainHandler_;
|
||||
int64_t lastWatchTime_ = 0;
|
||||
};
|
||||
|
||||
class MainHandlerDumper : public Dumper {
|
||||
public:
|
||||
virtual void Dump(const std::string &message) override;
|
||||
virtual std::string GetTag() override;
|
||||
std::string GetDumpInfo();
|
||||
private:
|
||||
std::string dumpInfo;
|
||||
};
|
||||
} // namespace AppExecFwk
|
||||
} // namespace OHOS
|
||||
#endif // OHOS_ABILITY_RUNTIME_WATCHDOG_H
|
||||
|
||||
@@ -41,10 +41,10 @@ public:
|
||||
void ProcessEvent(const EventWrap &event) override;
|
||||
|
||||
private:
|
||||
void ProcessLoadTimeOut(int64_t abilityRecordId);
|
||||
void ProcessLoadTimeOut(const EventWrap &event);
|
||||
void ProcessActiveTimeOut(int64_t abilityRecordId);
|
||||
void ProcessInactiveTimeOut(int64_t abilityRecordId);
|
||||
void ProcessForegroundTimeOut(int64_t abilityRecordId);
|
||||
void ProcessForegroundTimeOut(const EventWrap &event);
|
||||
void ProcessShareDataTimeOut(int64_t uniqueId);
|
||||
private:
|
||||
std::weak_ptr<AbilityManagerService> server_;
|
||||
|
||||
@@ -705,10 +705,10 @@ public:
|
||||
|
||||
void OnAbilityDied(std::shared_ptr<AbilityRecord> abilityRecord);
|
||||
void OnCallConnectDied(std::shared_ptr<CallRecord> callRecord);
|
||||
void HandleLoadTimeOut(int64_t abilityRecordId);
|
||||
void HandleLoadTimeOut(int64_t abilityRecordId, bool isHalf = false);
|
||||
void HandleActiveTimeOut(int64_t abilityRecordId);
|
||||
void HandleInactiveTimeOut(int64_t abilityRecordId);
|
||||
void HandleForegroundTimeOut(int64_t abilityRecordId);
|
||||
void HandleForegroundTimeOut(int64_t abilityRecordId, bool isHalf = false);
|
||||
void HandleShareDataTimeOut(int64_t uniqueId);
|
||||
int32_t GetShareDataPairAndReturnData(std::shared_ptr<AbilityRecord> abilityRecord,
|
||||
const int32_t &resultCode, const int32_t &uniqueId, WantParams &wantParam);
|
||||
@@ -1404,6 +1404,8 @@ private:
|
||||
void ReportAppRecoverResult(const int32_t appId, const AppExecFwk::ApplicationInfo &appInfo,
|
||||
const std::string& abilityName, const std::string& result);
|
||||
|
||||
void AppRecoverKill(pid_t pid, int32_t reason);
|
||||
|
||||
/**
|
||||
* Check if Caller is allowed to start ServiceAbility(FA) or ServiceExtension(Stage) or DataShareExtension(Stage).
|
||||
*
|
||||
|
||||
@@ -203,8 +203,9 @@ public:
|
||||
*
|
||||
* @param msgId the msg id in ability record
|
||||
* @param abilityRecordId the id of ability record
|
||||
* @param isHalf is half
|
||||
*/
|
||||
void OnTimeOut(uint32_t msgId, int64_t abilityRecordId);
|
||||
void OnTimeOut(uint32_t msgId, int64_t abilityRecordId, bool isHalf = false);
|
||||
|
||||
/**
|
||||
* @brief handle when ability died
|
||||
@@ -410,7 +411,7 @@ private:
|
||||
const std::shared_ptr<Mission> &mission);
|
||||
void MoveMissionListToTop(const std::shared_ptr<MissionList> &missionList);
|
||||
void MoveNoneTopMissionToDefaultList(const std::shared_ptr<Mission> &mission);
|
||||
void PrintTimeOutLog(const std::shared_ptr<AbilityRecord> &ability, uint32_t msgId);
|
||||
void PrintTimeOutLog(const std::shared_ptr<AbilityRecord> &ability, uint32_t msgId, bool isHalf = false);
|
||||
|
||||
int DispatchState(const std::shared_ptr<AbilityRecord> &abilityRecord, int state);
|
||||
int DispatchForeground(const std::shared_ptr<AbilityRecord> &abilityRecord, bool success,
|
||||
|
||||
@@ -132,8 +132,9 @@ public:
|
||||
*
|
||||
* @param msgId the msg id in ability record
|
||||
* @param abilityRecordId the id of ability record
|
||||
* @param isHalf is half
|
||||
*/
|
||||
void OnTimeOut(uint32_t msgId, int64_t abilityRecordId);
|
||||
void OnTimeOut(uint32_t msgId, int64_t abilityRecordId, bool isHalf = false);
|
||||
|
||||
/**
|
||||
* @brief handle when ability died
|
||||
@@ -226,7 +227,7 @@ private:
|
||||
std::string errorReason);
|
||||
void MoveToBackground(const std::shared_ptr<AbilityRecord> &abilityRecord);
|
||||
void CompleteBackground(const std::shared_ptr<AbilityRecord> &abilityRecord);
|
||||
void PrintTimeOutLog(const std::shared_ptr<AbilityRecord> &ability, uint32_t msgId);
|
||||
void PrintTimeOutLog(const std::shared_ptr<AbilityRecord> &ability, uint32_t msgId, bool isHalf = false);
|
||||
void DelayCompleteTerminate(const std::shared_ptr<AbilityRecord> &abilityRecord);
|
||||
void CompleteTerminate(const std::shared_ptr<AbilityRecord> &abilityRecord);
|
||||
bool IsContainsAbilityInner(const sptr<IRemoteObject> &token) const;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "ability_manager_errors.h"
|
||||
#include "ability_manager_service.h"
|
||||
#include "ability_util.h"
|
||||
#include "appfreeze_manager.h"
|
||||
#include "hitrace_meter.h"
|
||||
#include "hilog_wrapper.h"
|
||||
#include "in_process_call_wrapper.h"
|
||||
@@ -1810,10 +1811,12 @@ void AbilityConnectManager::PrintTimeOutLog(const std::shared_ptr<AbilityRecord>
|
||||
ability->GetAbilityInfo().name.data());
|
||||
return;
|
||||
}
|
||||
int typeId = AppExecFwk::AppfreezeManager::TypeAttribute::NORMAL_TIMEOUT;
|
||||
std::string msgContent = "ability:" + ability->GetAbilityInfo().name + " ";
|
||||
switch (msgId) {
|
||||
case AbilityManagerService::LOAD_TIMEOUT_MSG:
|
||||
msgContent += "load timeout";
|
||||
typeId = AppExecFwk::AppfreezeManager::TypeAttribute::CRITICAL_TIMEOUT;
|
||||
break;
|
||||
case AbilityManagerService::ACTIVE_TIMEOUT_MSG:
|
||||
msgContent += "active timeout";
|
||||
@@ -1823,6 +1826,7 @@ void AbilityConnectManager::PrintTimeOutLog(const std::shared_ptr<AbilityRecord>
|
||||
break;
|
||||
case AbilityManagerService::FOREGROUND_TIMEOUT_MSG:
|
||||
msgContent += "foreground timeout";
|
||||
typeId = AppExecFwk::AppfreezeManager::TypeAttribute::CRITICAL_TIMEOUT;
|
||||
break;
|
||||
case AbilityManagerService::BACKGROUND_TIMEOUT_MSG:
|
||||
msgContent += "background timeout";
|
||||
@@ -1833,18 +1837,13 @@ void AbilityConnectManager::PrintTimeOutLog(const std::shared_ptr<AbilityRecord>
|
||||
default:
|
||||
return;
|
||||
}
|
||||
std::string eventType = "LIFECYCLE_TIMEOUT";
|
||||
HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::AAFWK, eventType,
|
||||
OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
|
||||
EVENT_KEY_UID, processInfo.uid_,
|
||||
EVENT_KEY_PID, processInfo.pid_,
|
||||
EVENT_KEY_PACKAGE_NAME, ability->GetAbilityInfo().bundleName,
|
||||
EVENT_KEY_PROCESS_NAME, processInfo.processName_,
|
||||
EVENT_KEY_MESSAGE, msgContent);
|
||||
std::string eventName = AppExecFwk::AppFreezeType::LIFECYCLE_TIMEOUT;
|
||||
|
||||
HILOG_WARN("LIFECYCLE_TIMEOUT: uid: %{public}d, pid: %{public}d, bundleName: %{public}s, abilityName: %{public}s,"
|
||||
"msg: %{public}s", processInfo.uid_, processInfo.pid_, ability->GetAbilityInfo().bundleName.c_str(),
|
||||
ability->GetAbilityInfo().name.c_str(), msgContent.c_str());
|
||||
AppExecFwk::AppfreezeManager::GetInstance()->LifecycleTimeoutHandle(
|
||||
typeId, processInfo.pid_, eventName, ability->GetAbilityInfo().bundleName, msgContent);
|
||||
}
|
||||
|
||||
void AbilityConnectManager::MoveToTerminatingMap(const std::shared_ptr<AbilityRecord>& abilityRecord)
|
||||
|
||||
@@ -43,7 +43,7 @@ void AbilityEventHandler::ProcessEvent(const EventWrap &event)
|
||||
}
|
||||
switch (event.GetEventId()) {
|
||||
case AbilityManagerService::LOAD_TIMEOUT_MSG: {
|
||||
ProcessLoadTimeOut(event.GetParam());
|
||||
ProcessLoadTimeOut(event);
|
||||
break;
|
||||
}
|
||||
case AbilityManagerService::ACTIVE_TIMEOUT_MSG: {
|
||||
@@ -57,7 +57,7 @@ void AbilityEventHandler::ProcessEvent(const EventWrap &event)
|
||||
break;
|
||||
}
|
||||
case AbilityManagerService::FOREGROUND_TIMEOUT_MSG: {
|
||||
ProcessForegroundTimeOut(event.GetParam());
|
||||
ProcessForegroundTimeOut(event);
|
||||
break;
|
||||
}
|
||||
case AbilityManagerService::SHAREDATA_TIMEOUT_MSG: {
|
||||
@@ -71,12 +71,22 @@ void AbilityEventHandler::ProcessEvent(const EventWrap &event)
|
||||
}
|
||||
}
|
||||
|
||||
void AbilityEventHandler::ProcessLoadTimeOut(int64_t abilityRecordId)
|
||||
void AbilityEventHandler::ProcessLoadTimeOut(const EventWrap &event)
|
||||
{
|
||||
HILOG_INFO("Attach timeout.");
|
||||
auto server = server_.lock();
|
||||
CHECK_POINTER(server);
|
||||
server->HandleLoadTimeOut(abilityRecordId);
|
||||
if (event.GetRunCount() == 0) {
|
||||
uint32_t timeout = event.GetTimeout();
|
||||
if (timeout == 0) {
|
||||
timeout = 3000; // 3000 : default timeout
|
||||
}
|
||||
auto eventWrap = EventWrap(AbilityManagerService::LOAD_TIMEOUT_MSG, event.GetParam());
|
||||
eventWrap.SetRunCount(event.GetRunCount() + 1);
|
||||
eventWrap.SetTimeout(timeout);
|
||||
SendEvent(eventWrap, timeout);
|
||||
}
|
||||
server->HandleLoadTimeOut(event.GetParam(), event.GetRunCount() == 0);
|
||||
}
|
||||
|
||||
void AbilityEventHandler::ProcessActiveTimeOut(int64_t abilityRecordId)
|
||||
@@ -95,12 +105,22 @@ void AbilityEventHandler::ProcessInactiveTimeOut(int64_t abilityRecordId)
|
||||
server->HandleInactiveTimeOut(abilityRecordId);
|
||||
}
|
||||
|
||||
void AbilityEventHandler::ProcessForegroundTimeOut(int64_t abilityRecordId)
|
||||
void AbilityEventHandler::ProcessForegroundTimeOut(const EventWrap &event)
|
||||
{
|
||||
HILOG_INFO("Foreground timeout.");
|
||||
auto server = server_.lock();
|
||||
CHECK_POINTER(server);
|
||||
server->HandleForegroundTimeOut(abilityRecordId);
|
||||
if (event.GetRunCount() == 0) {
|
||||
uint32_t timeout = event.GetTimeout();
|
||||
if (timeout == 0) {
|
||||
timeout = 3000; // 3000 : default timeout
|
||||
}
|
||||
auto eventWrap = EventWrap(AbilityManagerService::FOREGROUND_TIMEOUT_MSG, event.GetParam());
|
||||
eventWrap.SetRunCount(event.GetRunCount() + 1);
|
||||
eventWrap.SetTimeout(timeout);
|
||||
SendEvent(eventWrap, timeout);
|
||||
}
|
||||
server->HandleForegroundTimeOut(event.GetParam(), event.GetRunCount() == 0);
|
||||
}
|
||||
|
||||
void AbilityEventHandler::ProcessShareDataTimeOut(int64_t uniqueId)
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
#include "uri_permission_manager_client.h"
|
||||
|
||||
#ifdef SUPPORT_GRAPHICS
|
||||
|
||||
#include "application_anr_listener.h"
|
||||
#include "display_manager.h"
|
||||
#include "input_manager.h"
|
||||
#include "png.h"
|
||||
@@ -320,6 +320,8 @@ bool AbilityManagerService::Init()
|
||||
int amsTimeOut = AmsConfigurationParameter::GetInstance().GetAMSTimeOutTime();
|
||||
HILOG_INFO("amsTimeOut is %{public}d", amsTimeOut);
|
||||
#ifdef SUPPORT_GRAPHICS
|
||||
auto anrListener = std::make_shared<ApplicationAnrListener>();
|
||||
MMI::InputManager::GetInstance()->SetAnrObserver(anrListener);
|
||||
DelayedSingleton<SystemDialogScheduler>::GetInstance()->SetDeviceType(OHOS::system::GetDeviceType());
|
||||
implicitStartProcessor_ = std::make_shared<ImplicitStartProcessor>();
|
||||
if (!Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
|
||||
@@ -4699,17 +4701,17 @@ bool AbilityManagerService::IsSystemUI(const std::string &bundleName) const
|
||||
return bundleName == AbilityConfig::SYSTEM_UI_BUNDLE_NAME;
|
||||
}
|
||||
|
||||
void AbilityManagerService::HandleLoadTimeOut(int64_t abilityRecordId)
|
||||
void AbilityManagerService::HandleLoadTimeOut(int64_t abilityRecordId, bool isHalf)
|
||||
{
|
||||
HILOG_DEBUG("Handle load timeout.");
|
||||
std::lock_guard<ffrt::mutex> lock(managersMutex_);
|
||||
if (Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
|
||||
uiAbilityLifecycleManager_->OnTimeOut(AbilityManagerService::LOAD_TIMEOUT_MSG, abilityRecordId);
|
||||
uiAbilityLifecycleManager_->OnTimeOut(AbilityManagerService::LOAD_TIMEOUT_MSG, abilityRecordId, isHalf);
|
||||
return;
|
||||
}
|
||||
for (auto& item : missionListManagers_) {
|
||||
if (item.second) {
|
||||
item.second->OnTimeOut(AbilityManagerService::LOAD_TIMEOUT_MSG, abilityRecordId);
|
||||
item.second->OnTimeOut(AbilityManagerService::LOAD_TIMEOUT_MSG, abilityRecordId, isHalf);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4742,17 +4744,17 @@ void AbilityManagerService::HandleInactiveTimeOut(int64_t abilityRecordId)
|
||||
}
|
||||
}
|
||||
|
||||
void AbilityManagerService::HandleForegroundTimeOut(int64_t abilityRecordId)
|
||||
void AbilityManagerService::HandleForegroundTimeOut(int64_t abilityRecordId, bool isHalf)
|
||||
{
|
||||
HILOG_DEBUG("Handle foreground timeout.");
|
||||
std::lock_guard<ffrt::mutex> lock(managersMutex_);
|
||||
if (Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
|
||||
uiAbilityLifecycleManager_->OnTimeOut(AbilityManagerService::FOREGROUND_TIMEOUT_MSG, abilityRecordId);
|
||||
uiAbilityLifecycleManager_->OnTimeOut(AbilityManagerService::FOREGROUND_TIMEOUT_MSG, abilityRecordId, isHalf);
|
||||
return;
|
||||
}
|
||||
for (auto& item : missionListManagers_) {
|
||||
if (item.second) {
|
||||
item.second->OnTimeOut(AbilityManagerService::FOREGROUND_TIMEOUT_MSG, abilityRecordId);
|
||||
item.second->OnTimeOut(AbilityManagerService::FOREGROUND_TIMEOUT_MSG, abilityRecordId, isHalf);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5526,6 +5528,28 @@ void AbilityManagerService::ReportAppRecoverResult(const int32_t appId, const Ap
|
||||
"RECOVERY_RESULT", result);
|
||||
}
|
||||
|
||||
void AbilityManagerService::AppRecoverKill(pid_t pid, int32_t reason)
|
||||
{
|
||||
AppExecFwk::AppFaultDataBySA faultDataSA;
|
||||
faultDataSA.errorObject.name = "appRecovery";
|
||||
switch (reason) {
|
||||
case AppExecFwk::StateReason::CPP_CRASH:
|
||||
faultDataSA.faultType = AppExecFwk::FaultDataType::CPP_CRASH;
|
||||
break;
|
||||
case AppExecFwk::StateReason::JS_ERROR:
|
||||
faultDataSA.faultType = AppExecFwk::FaultDataType::JS_ERROR;
|
||||
break;
|
||||
case AppExecFwk::StateReason::LIFECYCLE:
|
||||
case AppExecFwk::StateReason::APP_FREEZE:
|
||||
faultDataSA.faultType = AppExecFwk::FaultDataType::APP_FREEZE;
|
||||
break;
|
||||
default:
|
||||
faultDataSA.faultType = AppExecFwk::FaultDataType::UNKNOWN;
|
||||
}
|
||||
faultDataSA.pid = pid;
|
||||
IN_PROCESS_CALL(DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance()->NotifyAppFaultBySA(faultDataSA));
|
||||
}
|
||||
|
||||
void AbilityManagerService::ScheduleRecoverAbility(const sptr<IRemoteObject>& token, int32_t reason, const Want *want)
|
||||
{
|
||||
if (token == nullptr) {
|
||||
@@ -5568,7 +5592,7 @@ void AbilityManagerService::ScheduleRecoverAbility(const sptr<IRemoteObject>& to
|
||||
HILOG_ERROR("%{public}s AppRecovery recover app more than once in one minute, just kill app(%{public}d).",
|
||||
__func__, record->GetPid());
|
||||
ReportAppRecoverResult(record->GetUid(), appInfo, abilityInfo.name, "FAIL_WITHIN_ONE_MINUTE");
|
||||
kill(record->GetPid(), SIGKILL);
|
||||
AppRecoverKill(record->GetPid(), reason);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5621,7 +5645,7 @@ void AbilityManagerService::ScheduleRecoverAbility(const sptr<IRemoteObject>& to
|
||||
curWant.SetParam(AAFwk::Want::PARAM_ABILITY_RECOVERY_RESTART, true);
|
||||
|
||||
ReportAppRecoverResult(record->GetUid(), appInfo, abilityInfo.name, "SUCCESS");
|
||||
kill(record->GetPid(), SIGKILL);
|
||||
AppRecoverKill(record->GetPid(), reason);
|
||||
}
|
||||
|
||||
constexpr int delaytime = 1000;
|
||||
|
||||
@@ -73,6 +73,7 @@ const int32_t SEND_RESULT_CANCELED = -1;
|
||||
const int VECTOR_SIZE = 2;
|
||||
const int LOAD_TIMEOUT_ASANENABLED = 150;
|
||||
const int TERMINATE_TIMEOUT_ASANENABLED = 150;
|
||||
const int HALF_TIMEOUT = 2;
|
||||
#ifdef SUPPORT_ASAN
|
||||
const int COLDSTART_TIMEOUT_MULTIPLE = 150;
|
||||
const int LOAD_TIMEOUT_MULTIPLE = 150;
|
||||
@@ -262,10 +263,10 @@ int AbilityRecord::LoadAbility()
|
||||
if (applicationInfo_.asanEnabled) {
|
||||
loadTimeout =
|
||||
AmsConfigurationParameter::GetInstance().GetAppStartTimeoutTime() * LOAD_TIMEOUT_ASANENABLED;
|
||||
SendEvent(AbilityManagerService::LOAD_TIMEOUT_MSG, loadTimeout);
|
||||
SendEvent(AbilityManagerService::LOAD_TIMEOUT_MSG, loadTimeout / HALF_TIMEOUT);
|
||||
} else if (abilityInfo_.type != AppExecFwk::AbilityType::DATA) {
|
||||
auto delayTime = want_.GetBoolParam("coldStart", false) ? coldStartTimeout : loadTimeout;
|
||||
SendEvent(AbilityManagerService::LOAD_TIMEOUT_MSG, delayTime);
|
||||
SendEvent(AbilityManagerService::LOAD_TIMEOUT_MSG, delayTime / HALF_TIMEOUT);
|
||||
}
|
||||
|
||||
startTime_ = AbilityUtil::SystemTimeMillis();
|
||||
@@ -338,7 +339,7 @@ void AbilityRecord::ForegroundAbility(uint32_t sceneFlag)
|
||||
|
||||
int foregroundTimeout =
|
||||
AmsConfigurationParameter::GetInstance().GetAppStartTimeoutTime() * FOREGROUND_TIMEOUT_MULTIPLE;
|
||||
SendEvent(AbilityManagerService::FOREGROUND_TIMEOUT_MSG, foregroundTimeout);
|
||||
SendEvent(AbilityManagerService::FOREGROUND_TIMEOUT_MSG, foregroundTimeout / HALF_TIMEOUT);
|
||||
|
||||
// schedule active after updating AbilityState and sending timeout message to avoid ability async callback
|
||||
// earlier than above actions.
|
||||
@@ -2109,7 +2110,9 @@ void AbilityRecord::SendEvent(uint32_t msg, uint32_t timeOut, int32_t param)
|
||||
auto handler = DelayedSingleton<AbilityManagerService>::GetInstance()->GetEventHandler();
|
||||
CHECK_POINTER(handler);
|
||||
param = (param == -1) ? recordId_ : param;
|
||||
handler->SendEvent(EventWrap(msg, param), timeOut);
|
||||
auto eventWrap = EventWrap(msg, param);
|
||||
eventWrap.SetTimeout(timeOut);
|
||||
handler->SendEvent(eventWrap, timeOut);
|
||||
}
|
||||
|
||||
void AbilityRecord::SetStartSetting(const std::shared_ptr<AbilityStartSetting> &setting)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Huawei Device Co., Ltd.
|
||||
* Copyright (c) 2022-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
|
||||
@@ -15,7 +15,12 @@
|
||||
|
||||
#include "application_anr_listener.h"
|
||||
|
||||
#include "ability_manager_service.h"
|
||||
#include <sys/time.h>
|
||||
#include "singleton.h"
|
||||
|
||||
#include "app_mgr_client.h"
|
||||
#include "fault_data.h"
|
||||
#include "hilog_wrapper.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace AAFwk {
|
||||
@@ -25,7 +30,16 @@ ApplicationAnrListener::~ApplicationAnrListener() {}
|
||||
|
||||
void ApplicationAnrListener::OnAnr(int32_t pid) const
|
||||
{
|
||||
DelayedSingleton<AbilityManagerService>::GetInstance()->SendANRProcessID(pid);
|
||||
AppExecFwk::AppFaultDataBySA faultData;
|
||||
faultData.faultType = AppExecFwk::FaultDataType::APP_FREEZE;
|
||||
faultData.pid = pid;
|
||||
faultData.errorObject.message = "User input does not respond!";
|
||||
faultData.errorObject.stack = "";
|
||||
faultData.errorObject.name = AppExecFwk::AppFreezeType::APP_INPUT_BLOCK;
|
||||
faultData.waitSaveState = false;
|
||||
faultData.notifyApp = false;
|
||||
faultData.forceExit = false;
|
||||
DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance()->NotifyAppFaultBySA(faultData);
|
||||
}
|
||||
} // namespace AAFwk
|
||||
} // namespace OHOS
|
||||
} // namespace OHOS
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "ability_manager_service.h"
|
||||
#include "ability_util.h"
|
||||
#include "app_exit_reason_data_manager.h"
|
||||
#include "appfreeze_manager.h"
|
||||
#include "hitrace_meter.h"
|
||||
#include "errors.h"
|
||||
#include "hilog_wrapper.h"
|
||||
@@ -2027,7 +2028,7 @@ void MissionListManager::PostMissionLabelUpdateTask(int missionId) const
|
||||
handler->SubmitTask(task, "NotifyMissionLabelUpdated.", DELAY_NOTIFY_LABEL_TIME);
|
||||
}
|
||||
|
||||
void MissionListManager::PrintTimeOutLog(const std::shared_ptr<AbilityRecord> &ability, uint32_t msgId)
|
||||
void MissionListManager::PrintTimeOutLog(const std::shared_ptr<AbilityRecord> &ability, uint32_t msgId, bool isHalf)
|
||||
{
|
||||
if (ability == nullptr) {
|
||||
HILOG_ERROR("ability is nullptr");
|
||||
@@ -2041,10 +2042,12 @@ void MissionListManager::PrintTimeOutLog(const std::shared_ptr<AbilityRecord> &a
|
||||
ability->GetAbilityInfo().name.data());
|
||||
return;
|
||||
}
|
||||
int typeId = AppExecFwk::AppfreezeManager::TypeAttribute::NORMAL_TIMEOUT;
|
||||
std::string msgContent = "ability:" + ability->GetAbilityInfo().name + " ";
|
||||
switch (msgId) {
|
||||
case AbilityManagerService::LOAD_TIMEOUT_MSG:
|
||||
msgContent += "load timeout";
|
||||
typeId = AppExecFwk::AppfreezeManager::TypeAttribute::CRITICAL_TIMEOUT;
|
||||
break;
|
||||
case AbilityManagerService::ACTIVE_TIMEOUT_MSG:
|
||||
msgContent += "active timeout";
|
||||
@@ -2054,6 +2057,7 @@ void MissionListManager::PrintTimeOutLog(const std::shared_ptr<AbilityRecord> &a
|
||||
break;
|
||||
case AbilityManagerService::FOREGROUND_TIMEOUT_MSG:
|
||||
msgContent += "foreground timeout";
|
||||
typeId = AppExecFwk::AppfreezeManager::TypeAttribute::CRITICAL_TIMEOUT;
|
||||
break;
|
||||
case AbilityManagerService::BACKGROUND_TIMEOUT_MSG:
|
||||
msgContent += "background timeout";
|
||||
@@ -2064,18 +2068,16 @@ void MissionListManager::PrintTimeOutLog(const std::shared_ptr<AbilityRecord> &a
|
||||
default:
|
||||
return;
|
||||
}
|
||||
std::string eventType = "LIFECYCLE_TIMEOUT";
|
||||
HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::AAFWK, eventType,
|
||||
OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
|
||||
EVENT_KEY_UID, processInfo.uid_,
|
||||
EVENT_KEY_PID, processInfo.pid_,
|
||||
EVENT_KEY_PACKAGE_NAME, ability->GetAbilityInfo().bundleName,
|
||||
EVENT_KEY_PROCESS_NAME, processInfo.processName_,
|
||||
EVENT_KEY_MESSAGE, msgContent);
|
||||
|
||||
HILOG_WARN("LIFECYCLE_TIMEOUT: uid: %{public}d, pid: %{public}d, bundleName: %{public}s, abilityName: %{public}s,"
|
||||
"msg: %{public}s", processInfo.uid_, processInfo.pid_, ability->GetAbilityInfo().bundleName.c_str(),
|
||||
std::string eventName = isHalf ?
|
||||
AppExecFwk::AppFreezeType::LIFECYCLE_HALF_TIMEOUT : AppExecFwk::AppFreezeType::LIFECYCLE_TIMEOUT;
|
||||
HILOG_WARN("%{public}s: uid: %{public}d, pid: %{public}d, bundleName: %{public}s, abilityName: %{public}s,"
|
||||
"msg: %{public}s", eventName.c_str(),
|
||||
processInfo.uid_, processInfo.pid_, ability->GetAbilityInfo().bundleName.c_str(),
|
||||
ability->GetAbilityInfo().name.c_str(), msgContent.c_str());
|
||||
|
||||
AppExecFwk::AppfreezeManager::GetInstance()->LifecycleTimeoutHandle(
|
||||
typeId, processInfo.pid_, eventName, ability->GetAbilityInfo().bundleName, msgContent);
|
||||
}
|
||||
|
||||
void MissionListManager::UpdateMissionSnapshot(const std::shared_ptr<AbilityRecord>& abilityRecord) const
|
||||
@@ -2095,7 +2097,7 @@ void MissionListManager::UpdateMissionSnapshot(const std::shared_ptr<AbilityReco
|
||||
}
|
||||
}
|
||||
|
||||
void MissionListManager::OnTimeOut(uint32_t msgId, int64_t abilityRecordId)
|
||||
void MissionListManager::OnTimeOut(uint32_t msgId, int64_t abilityRecordId, bool isHalf)
|
||||
{
|
||||
HILOG_INFO("On timeout, msgId is %{public}d", msgId);
|
||||
std::lock_guard guard(managerLock_);
|
||||
@@ -2113,7 +2115,10 @@ void MissionListManager::OnTimeOut(uint32_t msgId, int64_t abilityRecordId)
|
||||
}
|
||||
#endif
|
||||
|
||||
PrintTimeOutLog(abilityRecord, msgId);
|
||||
PrintTimeOutLog(abilityRecord, msgId, isHalf);
|
||||
if (isHalf) {
|
||||
return;
|
||||
}
|
||||
switch (msgId) {
|
||||
case AbilityManagerService::LOAD_TIMEOUT_MSG:
|
||||
HandleLoadTimeout(abilityRecord);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "ability_manager_service.h"
|
||||
#include "ability_util.h"
|
||||
#include "appfreeze_manager.h"
|
||||
#include "errors.h"
|
||||
#include "hilog_wrapper.h"
|
||||
#include "hitrace_meter.h"
|
||||
@@ -663,7 +664,8 @@ void UIAbilityLifecycleManager::NotifyAbilityToken(const sptr<IRemoteObject> &to
|
||||
}
|
||||
}
|
||||
|
||||
void UIAbilityLifecycleManager::PrintTimeOutLog(const std::shared_ptr<AbilityRecord> &ability, uint32_t msgId)
|
||||
void UIAbilityLifecycleManager::PrintTimeOutLog(const std::shared_ptr<AbilityRecord> &ability,
|
||||
uint32_t msgId, bool isHalf)
|
||||
{
|
||||
if (ability == nullptr) {
|
||||
HILOG_ERROR("failed, ability is nullptr");
|
||||
@@ -677,13 +679,16 @@ void UIAbilityLifecycleManager::PrintTimeOutLog(const std::shared_ptr<AbilityRec
|
||||
ability->GetAbilityInfo().name.data());
|
||||
return;
|
||||
}
|
||||
int typeId = AppExecFwk::AppfreezeManager::TypeAttribute::NORMAL_TIMEOUT;
|
||||
std::string msgContent = "ability:" + ability->GetAbilityInfo().name + " ";
|
||||
switch (msgId) {
|
||||
case AbilityManagerService::LOAD_TIMEOUT_MSG:
|
||||
msgContent += "load timeout";
|
||||
typeId = AppExecFwk::AppfreezeManager::TypeAttribute::CRITICAL_TIMEOUT;
|
||||
break;
|
||||
case AbilityManagerService::FOREGROUND_TIMEOUT_MSG:
|
||||
msgContent += "foreground timeout";
|
||||
typeId = AppExecFwk::AppfreezeManager::TypeAttribute::CRITICAL_TIMEOUT;
|
||||
break;
|
||||
case AbilityManagerService::BACKGROUND_TIMEOUT_MSG:
|
||||
msgContent += "background timeout";
|
||||
@@ -694,18 +699,16 @@ void UIAbilityLifecycleManager::PrintTimeOutLog(const std::shared_ptr<AbilityRec
|
||||
default:
|
||||
return;
|
||||
}
|
||||
std::string eventType = "LIFECYCLE_TIMEOUT";
|
||||
HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::AAFWK, eventType,
|
||||
OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
|
||||
EVENT_KEY_UID, processInfo.uid_,
|
||||
EVENT_KEY_PID, processInfo.pid_,
|
||||
EVENT_KEY_PACKAGE_NAME, ability->GetAbilityInfo().bundleName,
|
||||
EVENT_KEY_PROCESS_NAME, processInfo.processName_,
|
||||
EVENT_KEY_MESSAGE, msgContent);
|
||||
|
||||
HILOG_WARN("LIFECYCLE_TIMEOUT: uid: %{public}d, pid: %{public}d, bundleName: %{public}s, abilityName: %{public}s,"
|
||||
"msg: %{public}s", processInfo.uid_, processInfo.pid_, ability->GetAbilityInfo().bundleName.c_str(),
|
||||
std::string eventName = isHalf ?
|
||||
AppExecFwk::AppFreezeType::LIFECYCLE_HALF_TIMEOUT : AppExecFwk::AppFreezeType::LIFECYCLE_TIMEOUT;
|
||||
HILOG_WARN("%{public}s: uid: %{public}d, pid: %{public}d, bundleName: %{public}s, abilityName: %{public}s,"
|
||||
"msg: %{public}s", eventName.c_str(),
|
||||
processInfo.uid_, processInfo.pid_, ability->GetAbilityInfo().bundleName.c_str(),
|
||||
ability->GetAbilityInfo().name.c_str(), msgContent.c_str());
|
||||
|
||||
AppExecFwk::AppfreezeManager::GetInstance()->LifecycleTimeoutHandle(
|
||||
typeId, processInfo.pid_, eventName, ability->GetAbilityInfo().bundleName, msgContent);
|
||||
}
|
||||
|
||||
void UIAbilityLifecycleManager::CompleteBackground(const std::shared_ptr<AbilityRecord> &abilityRecord)
|
||||
@@ -913,7 +916,7 @@ void UIAbilityLifecycleManager::ReportEventToSuspendManager(const AppExecFwk::Ab
|
||||
#endif // EFFICIENCY_MANAGER_ENABLE
|
||||
}
|
||||
|
||||
void UIAbilityLifecycleManager::OnTimeOut(uint32_t msgId, int64_t abilityRecordId)
|
||||
void UIAbilityLifecycleManager::OnTimeOut(uint32_t msgId, int64_t abilityRecordId, bool isHalf)
|
||||
{
|
||||
HILOG_DEBUG("call, msgId is %{public}d", msgId);
|
||||
std::lock_guard<ffrt::mutex> guard(sessionLock_);
|
||||
@@ -930,7 +933,10 @@ void UIAbilityLifecycleManager::OnTimeOut(uint32_t msgId, int64_t abilityRecordI
|
||||
}
|
||||
HILOG_DEBUG("call, msgId:%{public}d, name:%{public}s", msgId, abilityRecord->GetAbilityInfo().name.c_str());
|
||||
|
||||
PrintTimeOutLog(abilityRecord, msgId);
|
||||
PrintTimeOutLog(abilityRecord, msgId, isHalf);
|
||||
if (isHalf) {
|
||||
return;
|
||||
}
|
||||
switch (msgId) {
|
||||
case AbilityManagerService::LOAD_TIMEOUT_MSG:
|
||||
HandleLoadTimeout(abilityRecord);
|
||||
|
||||
@@ -945,6 +945,10 @@ private:
|
||||
|
||||
void SetOverlayInfo(const std::string& bundleName, const int32_t userId, AppSpawnStartMsg& startMsg);
|
||||
|
||||
void TimeoutNotifyApp(int32_t pid, int32_t uid, const std::string& bundleName, const FaultData &faultData);
|
||||
|
||||
void AppRecoveryNotifyApp(int32_t pid, const std::string& bundleName,
|
||||
FaultDataType faultType, const std::string& markers);
|
||||
private:
|
||||
/**
|
||||
* Notify application status.
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "app_mgr_service.h"
|
||||
#include "app_process_data.h"
|
||||
#include "app_state_observer_manager.h"
|
||||
#include "appfreeze_manager.h"
|
||||
#include "application_state_observer_stub.h"
|
||||
#include "appspawn_mount_permission.h"
|
||||
#include "bundle_constants.h"
|
||||
@@ -111,7 +112,6 @@ constexpr int32_t RESTART_INTERVAL_TIME = 120000;
|
||||
|
||||
constexpr ErrCode APPMGR_ERR_OFFSET = ErrCodeOffset(SUBSYS_APPEXECFWK, 0x01);
|
||||
constexpr ErrCode ERR_ALREADY_EXIST_RENDER = APPMGR_ERR_OFFSET + 100; // error code for already exist render.
|
||||
const std::string EVENT_NAME_LIFECYCLE_TIMEOUT = "APP_LIFECYCLE_TIMEOUT";
|
||||
constexpr char EVENT_KEY_UID[] = "UID";
|
||||
constexpr char EVENT_KEY_PID[] = "PID";
|
||||
constexpr char EVENT_KEY_PACKAGE_NAME[] = "PACKAGE_NAME";
|
||||
@@ -3025,46 +3025,43 @@ void AppMgrServiceInner::SendHiSysEvent(const int32_t innerEventId, const int64_
|
||||
return;
|
||||
}
|
||||
|
||||
std::string eventName = EVENT_NAME_LIFECYCLE_TIMEOUT;
|
||||
std::string eventName = AppExecFwk::AppFreezeType::LIFECYCLE_TIMEOUT;
|
||||
int32_t pid = appRecord->GetPriorityObject()->GetPid();
|
||||
int32_t uid = appRecord->GetUid();
|
||||
std::string packageName = appRecord->GetBundleName();
|
||||
std::string processName = appRecord->GetProcessName();
|
||||
std::string msg;
|
||||
std::string msg = AppExecFwk::AppFreezeType::APP_LIFECYCLE_TIMEOUT;
|
||||
msg += ",";
|
||||
int typeId = AppExecFwk::AppfreezeManager::TypeAttribute::NORMAL_TIMEOUT;
|
||||
switch (innerEventId) {
|
||||
case AMSEventHandler::TERMINATE_ABILITY_TIMEOUT_MSG:
|
||||
msg = EVENT_MESSAGE_TERMINATE_ABILITY_TIMEOUT;
|
||||
msg += EVENT_MESSAGE_TERMINATE_ABILITY_TIMEOUT;
|
||||
break;
|
||||
case AMSEventHandler::TERMINATE_APPLICATION_TIMEOUT_MSG:
|
||||
msg = EVENT_MESSAGE_TERMINATE_APPLICATION_TIMEOUT;
|
||||
msg += EVENT_MESSAGE_TERMINATE_APPLICATION_TIMEOUT;
|
||||
break;
|
||||
case AMSEventHandler::ADD_ABILITY_STAGE_INFO_TIMEOUT_MSG:
|
||||
msg = EVENT_MESSAGE_ADD_ABILITY_STAGE_INFO_TIMEOUT;
|
||||
msg += EVENT_MESSAGE_ADD_ABILITY_STAGE_INFO_TIMEOUT;
|
||||
typeId = AppExecFwk::AppfreezeManager::TypeAttribute::CRITICAL_TIMEOUT;
|
||||
break;
|
||||
case AMSEventHandler::START_PROCESS_SPECIFIED_ABILITY_TIMEOUT_MSG:
|
||||
msg = EVENT_MESSAGE_START_PROCESS_SPECIFIED_ABILITY_TIMEOUT;
|
||||
msg += EVENT_MESSAGE_START_PROCESS_SPECIFIED_ABILITY_TIMEOUT;
|
||||
typeId = AppExecFwk::AppfreezeManager::TypeAttribute::CRITICAL_TIMEOUT;
|
||||
break;
|
||||
case AMSEventHandler::START_SPECIFIED_ABILITY_TIMEOUT_MSG:
|
||||
msg = EVENT_MESSAGE_START_SPECIFIED_ABILITY_TIMEOUT;
|
||||
msg += EVENT_MESSAGE_START_SPECIFIED_ABILITY_TIMEOUT;
|
||||
typeId = AppExecFwk::AppfreezeManager::TypeAttribute::CRITICAL_TIMEOUT;
|
||||
break;
|
||||
default:
|
||||
msg = EVENT_MESSAGE_DEFAULT;
|
||||
msg += EVENT_MESSAGE_DEFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
HILOG_DEBUG("SendHiSysEvent, eventName = %{public}s, uid = %{public}d, pid = %{public}d, \
|
||||
HILOG_WARN("LIFECYCLE_TIMEOUT, eventName = %{public}s, uid = %{public}d, pid = %{public}d, \
|
||||
packageName = %{public}s, processName = %{public}s, msg = %{public}s",
|
||||
eventName.c_str(), uid, pid, packageName.c_str(), processName.c_str(), msg.c_str());
|
||||
|
||||
HiSysEventWrite(
|
||||
OHOS::HiviewDFX::HiSysEvent::Domain::AAFWK,
|
||||
eventName,
|
||||
OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
|
||||
EVENT_KEY_PID, pid,
|
||||
EVENT_KEY_UID, uid,
|
||||
EVENT_KEY_PACKAGE_NAME, packageName,
|
||||
EVENT_KEY_PROCESS_NAME, processName,
|
||||
EVENT_KEY_MESSAGE, msg);
|
||||
AppExecFwk::AppfreezeManager::GetInstance()->LifecycleTimeoutHandle(
|
||||
typeId, pid, eventName, packageName, msg);
|
||||
}
|
||||
|
||||
int AppMgrServiceInner::GetAbilityRecordsByProcessID(const int pid, std::vector<sptr<IRemoteObject>> &tokens)
|
||||
@@ -3739,6 +3736,44 @@ int32_t AppMgrServiceInner::NotifyUnLoadRepairPatch(const std::string &bundleNam
|
||||
return appRunningManager_->NotifyUnLoadRepairPatch(bundleName, callback);
|
||||
}
|
||||
|
||||
void AppMgrServiceInner::AppRecoveryNotifyApp(int32_t pid, const std::string& bundleName,
|
||||
FaultDataType faultType, const std::string& markers)
|
||||
{
|
||||
HILOG_INFO("AppRecovery NotifyApp to kill is: bundleName: %{public}s, faultType: %{public}d, pid: %{public}d",
|
||||
bundleName.c_str(), faultType, pid);
|
||||
if (faultType != FaultDataType::APP_FREEZE) {
|
||||
KillProcessByPid(pid);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string timeOutName = "waitSaveTask" + std::to_string(pid) + bundleName;
|
||||
if (markers == "appRecovery") {
|
||||
if (taskHandler_->CancelTask(timeOutName)) {
|
||||
KillProcessByPid(pid);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (markers != "recoveryTimeout") {
|
||||
return;
|
||||
}
|
||||
auto waitSaveTask = [pid, bundleName, innerService = shared_from_this()]() {
|
||||
auto appRecord = innerService->GetAppRunningRecordByPid(pid);
|
||||
if (appRecord == nullptr) {
|
||||
HILOG_ERROR("no such appRecord");
|
||||
return;
|
||||
}
|
||||
std::string name = appRecord->GetBundleName();
|
||||
if (bundleName == name) {
|
||||
HILOG_INFO("waitSaveTask timeout %{public}s,pid == %{public}d is going to exit due to AppRecovery.",
|
||||
bundleName.c_str(), pid);
|
||||
innerService->KillProcessByPid(pid);
|
||||
}
|
||||
};
|
||||
constexpr int32_t timeOut = 2000;
|
||||
taskHandler_->SubmitTask(waitSaveTask, timeOutName, timeOut);
|
||||
}
|
||||
|
||||
int32_t AppMgrServiceInner::NotifyAppFault(const FaultData &faultData)
|
||||
{
|
||||
HILOG_DEBUG("called.");
|
||||
@@ -3750,12 +3785,68 @@ int32_t AppMgrServiceInner::NotifyAppFault(const FaultData &faultData)
|
||||
return ERR_INVALID_VALUE;
|
||||
}
|
||||
std::string bundleName = appRecord->GetBundleName();
|
||||
HILOG_DEBUG("FaultData is: error name: %{public}s, faultType: %{public}s, uid: %{public}d, pid: %{public}d,\
|
||||
bundleName: %{public}s", faultData.errorObject.name.c_str(), FaultTypeToString(faultData.faultType).c_str(),
|
||||
callerUid, pid, bundleName.c_str());
|
||||
|
||||
if (faultData.faultType == FaultDataType::APP_FREEZE) {
|
||||
if (faultData.timeoutMarkers != "") {
|
||||
if (!taskHandler_->CancelTask(faultData.timeoutMarkers)) {
|
||||
return ERR_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (faultData.waitSaveState) {
|
||||
AppRecoveryNotifyApp(pid, bundleName, FaultDataType::APP_FREEZE, "recoveryTimeout");
|
||||
}
|
||||
}
|
||||
|
||||
auto notifyAppTask = [appRecord, pid, callerUid, bundleName, faultData, innerService = shared_from_this()]() {
|
||||
if (faultData.faultType == FaultDataType::APP_FREEZE) {
|
||||
AppfreezeManager::AppInfo info = {
|
||||
.pid = pid,
|
||||
.uid = callerUid,
|
||||
.bundleName = bundleName,
|
||||
.processName = bundleName,
|
||||
};
|
||||
auto appfreezeManager = AppExecFwk::AppfreezeManager::GetInstance();
|
||||
if (!appfreezeManager->IsHandleAppfreeze(bundleName)) {
|
||||
return;
|
||||
}
|
||||
appfreezeManager->AppfreezeHandle(faultData, info);
|
||||
}
|
||||
|
||||
HILOG_WARN("FaultData is: name: %{public}s, faultType: %{public}d, uid: %{public}d, pid: %{public}d,"
|
||||
"bundleName: %{public}s, faultData.forceExit==%{public}d, faultData.waitSaveState==%{public}d",
|
||||
faultData.errorObject.name.c_str(), faultData.faultType,
|
||||
callerUid, pid, bundleName.c_str(), faultData.forceExit, faultData.waitSaveState);
|
||||
|
||||
if (faultData.forceExit && !faultData.waitSaveState && appRecord->IsKeepAliveApp()) {
|
||||
HILOG_INFO("FaultData %{public}s,pid == %{public}d is going to exit due to %{public}s.",
|
||||
bundleName.c_str(), pid, innerService->FaultTypeToString(faultData.faultType).c_str());
|
||||
innerService->KillProcessByPid(pid);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
taskHandler_->SubmitTask(notifyAppTask, "notifyAppFaultTask");
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void AppMgrServiceInner::TimeoutNotifyApp(int32_t pid, int32_t uid,
|
||||
const std::string& bundleName, const FaultData &faultData)
|
||||
{
|
||||
if (faultData.faultType == FaultDataType::APP_FREEZE) {
|
||||
AppfreezeManager::AppInfo info = {
|
||||
.pid = pid,
|
||||
.uid = uid,
|
||||
.bundleName = bundleName,
|
||||
.processName = bundleName,
|
||||
};
|
||||
AppExecFwk::AppfreezeManager::GetInstance()->AppfreezeHandleWithStack(faultData, info);
|
||||
}
|
||||
HILOG_WARN("FaultData timeout NotifyApp %{public}s is going to exit due to %{public}s.",
|
||||
bundleName.c_str(), FaultTypeToString(faultData.faultType).c_str());
|
||||
KillProcessByPid(pid);
|
||||
}
|
||||
|
||||
int32_t AppMgrServiceInner::NotifyAppFaultBySA(const AppFaultDataBySA &faultData)
|
||||
{
|
||||
HILOG_DEBUG("called");
|
||||
@@ -3776,14 +3867,34 @@ int32_t AppMgrServiceInner::NotifyAppFaultBySA(const AppFaultDataBySA &faultData
|
||||
HILOG_ERROR("no such appRecord");
|
||||
return ERR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
int64_t time = SystemTimeMillisecond();
|
||||
FaultData transformedFaultData = ConvertDataTypes(faultData);
|
||||
int32_t uid = appRecord->GetUid();
|
||||
std::string bundleName = appRecord->GetBundleName();
|
||||
HILOG_DEBUG("FaultDataBySA is: error name: %{public}s, faultType: %{public}s, uid: %{public}d,\
|
||||
pid: %{public}d, bundleName: %{public}s",
|
||||
|
||||
if (faultData.errorObject.name == "appRecovery") {
|
||||
AppRecoveryNotifyApp(pid, bundleName, faultData.faultType, "appRecovery");
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
if (transformedFaultData.timeoutMarkers.empty()) {
|
||||
transformedFaultData.timeoutMarkers = "notifyFault" + std::to_string(pid) + "-" + std::to_string(time);
|
||||
}
|
||||
const int64_t timeout = 3000;
|
||||
if (faultData.faultType == FaultDataType::APP_FREEZE) {
|
||||
if (!AppExecFwk::AppfreezeManager::GetInstance()->IsHandleAppfreeze(bundleName)) {
|
||||
return ERR_OK;
|
||||
}
|
||||
auto timeoutNotifyApp = std::bind(&AppMgrServiceInner::TimeoutNotifyApp, this,
|
||||
pid, uid, bundleName, transformedFaultData);
|
||||
taskHandler_->SubmitTask(timeoutNotifyApp, transformedFaultData.timeoutMarkers, timeout);
|
||||
}
|
||||
appRecord->NotifyAppFault(transformedFaultData);
|
||||
HILOG_WARN("FaultDataBySA is: name: %{public}s, faultType: %{public}s, uid: %{public}d,"
|
||||
"pid: %{public}d, bundleName: %{public}s",
|
||||
faultData.errorObject.name.c_str(), FaultTypeToString(faultData.faultType).c_str(),
|
||||
uid, pid, bundleName.c_str());
|
||||
appRecord->NotifyAppFault(transformedFaultData);
|
||||
} else {
|
||||
HILOG_DEBUG("this is not called by SA.");
|
||||
return AAFwk::CHECK_PERMISSION_FAILED;
|
||||
@@ -3796,6 +3907,10 @@ FaultData AppMgrServiceInner::ConvertDataTypes(const AppFaultDataBySA &faultData
|
||||
FaultData newfaultData;
|
||||
newfaultData.faultType = faultData.faultType;
|
||||
newfaultData.errorObject = faultData.errorObject;
|
||||
newfaultData.timeoutMarkers = faultData.timeoutMarkers;
|
||||
newfaultData.waitSaveState = faultData.waitSaveState;
|
||||
newfaultData.notifyApp = faultData.notifyApp;
|
||||
newfaultData.forceExit = faultData.forceExit;
|
||||
return newfaultData;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,11 +71,29 @@ public:
|
||||
{
|
||||
return eventData_ == other.eventData_;
|
||||
}
|
||||
void SetRunCount(int runCount)
|
||||
{
|
||||
runCount_ = runCount;
|
||||
}
|
||||
int GetRunCount() const
|
||||
{
|
||||
return runCount_;
|
||||
}
|
||||
void SetTimeout(uint32_t timeout)
|
||||
{
|
||||
timeout_ = timeout;
|
||||
}
|
||||
uint32_t GetTimeout() const
|
||||
{
|
||||
return timeout_;
|
||||
}
|
||||
private:
|
||||
uint32_t eventId_;
|
||||
int64_t param_;
|
||||
std::shared_ptr<EventDataBase> eventData_;
|
||||
TaskHandle eventTask_;
|
||||
int runCount_ = 0;
|
||||
uint32_t timeout_ = 0;
|
||||
};
|
||||
|
||||
class EventHandlerWrap : public std::enable_shared_from_this<EventHandlerWrap> {
|
||||
|
||||
@@ -2193,7 +2193,7 @@ HWTEST_F(MainThreadTest, HandleOnOverlayChanged_0100, TestSize.Level1)
|
||||
HWTEST_F(MainThreadTest, ScheduleNotifyAppFault_0100, TestSize.Level1)
|
||||
{
|
||||
FaultData faultData;
|
||||
faultData.faultType = FaultDataType::APP_FREEZE;
|
||||
faultData.faultType = FaultDataType::JS_ERROR;
|
||||
faultData.errorObject.message = "msgContent";
|
||||
faultData.errorObject.stack = "stack";
|
||||
faultData.errorObject.name = "eventType";
|
||||
|
||||
@@ -82,7 +82,19 @@ HWTEST_F(FaultDataTest, ReadFromParcel_001, TestSize.Level1)
|
||||
messageFifth.WriteString(helloWord);
|
||||
messageFifth.WriteInt32(12);
|
||||
bool retFifth = faultData->ReadFromParcel(messageFifth);
|
||||
EXPECT_EQ(true, retFifth);
|
||||
EXPECT_EQ(false, retFifth);
|
||||
|
||||
MessageParcel messageSixth;
|
||||
messageSixth.WriteString(helloWord);
|
||||
messageSixth.WriteString(helloWord);
|
||||
messageSixth.WriteString(helloWord);
|
||||
messageSixth.WriteInt32(12);
|
||||
messageSixth.WriteString(helloWord);
|
||||
messageSixth.WriteBool(true);
|
||||
messageSixth.WriteBool(true);
|
||||
messageSixth.WriteBool(true);
|
||||
bool retSixth = faultData->ReadFromParcel(messageSixth);
|
||||
EXPECT_EQ(true, retSixth);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,6 +114,10 @@ HWTEST_F(FaultDataTest, Unmarshalling_001, TestSize.Level1)
|
||||
message.WriteString(helloWord);
|
||||
message.WriteString(helloWord);
|
||||
message.WriteInt32(12);
|
||||
message.WriteString(helloWord);
|
||||
message.WriteBool(true);
|
||||
message.WriteBool(true);
|
||||
message.WriteBool(true);
|
||||
auto retSecond = faultData->Unmarshalling(message);
|
||||
EXPECT_NE(nullptr, retSecond);
|
||||
}
|
||||
@@ -168,6 +184,10 @@ HWTEST_F(FaultDataTest, ReadFromParcel_002, TestSize.Level1)
|
||||
messageSixth.WriteString(helloWord);
|
||||
messageSixth.WriteInt32(12);
|
||||
messageSixth.WriteInt32(34);
|
||||
messageSixth.WriteString(helloWord);
|
||||
messageSixth.WriteBool(true);
|
||||
messageSixth.WriteBool(true);
|
||||
messageSixth.WriteBool(true);
|
||||
bool retSixth = appFaultDataBySA->ReadFromParcel(messageSixth);
|
||||
EXPECT_EQ(true, retSixth);
|
||||
}
|
||||
@@ -190,8 +210,10 @@ HWTEST_F(FaultDataTest, Unmarshalling_002, TestSize.Level1)
|
||||
message.WriteString(helloWord);
|
||||
message.WriteInt32(12);
|
||||
message.WriteInt32(34);
|
||||
message.WriteInt32(56);
|
||||
message.WriteString(helloWord);
|
||||
message.WriteBool(true);
|
||||
message.WriteBool(true);
|
||||
message.WriteBool(true);
|
||||
auto retSecond = appFaultDataBySA->Unmarshalling(message);
|
||||
EXPECT_NE(nullptr, retSecond);
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@ public:
|
||||
std::shared_ptr<MockHandler> mockHandler_ = nullptr;
|
||||
std::shared_ptr<EventRunner> runner_ = nullptr;
|
||||
std::shared_ptr<Watchdog> watchdog_ = nullptr;
|
||||
std::shared_ptr<MainHandlerDumper> mainHandlerDumper_;
|
||||
static void SetUpTestCase(void);
|
||||
static void TearDownTestCase(void);
|
||||
void SetUp();
|
||||
@@ -61,13 +60,11 @@ void WatchdogTest::SetUp(void)
|
||||
|
||||
watchdog_ = std::make_shared<Watchdog>();
|
||||
watchdog_->Init(mockHandler_);
|
||||
mainHandlerDumper_ = std::make_shared<MainHandlerDumper>();
|
||||
}
|
||||
|
||||
void WatchdogTest::TearDown(void)
|
||||
{
|
||||
watchdog_->Stop();
|
||||
mainHandlerDumper_ = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,8 +105,6 @@ HWTEST_F(WatchdogTest, AppExecFwk_watchdog_ReportEvent_0001, Function | MediumTe
|
||||
// be ready for ReportEvent
|
||||
watchdog_->lastWatchTime_ = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::
|
||||
steady_clock::now().time_since_epoch()).count() - TEST_INTERVAL_TIME;
|
||||
std::shared_ptr<ApplicationInfo> application = std::make_shared<ApplicationInfo>();
|
||||
watchdog_->SetApplicationInfo(application);
|
||||
watchdog_->needReport_ = true;
|
||||
|
||||
watchdog_->isSixSecondEvent_.store(true);
|
||||
@@ -129,8 +124,6 @@ HWTEST_F(WatchdogTest, AppExecFwk_watchdog_ReportEvent_0002, Function | MediumTe
|
||||
// be ready for ReportEvent
|
||||
watchdog_->lastWatchTime_ = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::
|
||||
system_clock::now().time_since_epoch()).count() - TEST_INTERVAL_TIME;
|
||||
std::shared_ptr<ApplicationInfo> application = std::make_shared<ApplicationInfo>();
|
||||
watchdog_->SetApplicationInfo(application);
|
||||
watchdog_->needReport_ = true;
|
||||
|
||||
watchdog_->isSixSecondEvent_.store(false);
|
||||
@@ -198,21 +191,6 @@ HWTEST_F(WatchdogTest, WatchdogTest_Stop_002, TestSize.Level1)
|
||||
GTEST_LOG_(INFO) << "WatchdogTest_Stop_002 end";
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.number: WatchdogTest_SetApplicationInfo_001
|
||||
* @tc.name: SetApplicationInfo
|
||||
* @tc.desc: Verify that function SetApplicationInfo.
|
||||
*/
|
||||
HWTEST_F(WatchdogTest, WatchdogTest_SetApplicationInfo_001, TestSize.Level1)
|
||||
{
|
||||
GTEST_LOG_(INFO) << "WatchdogTest_SetApplicationInfo_001 start";
|
||||
std::shared_ptr<ApplicationInfo> applicationInfo = std::make_shared<ApplicationInfo>();
|
||||
EXPECT_TRUE(watchdog_->applicationInfo_ == nullptr);
|
||||
watchdog_->SetApplicationInfo(applicationInfo);
|
||||
EXPECT_TRUE(watchdog_->applicationInfo_ != nullptr);
|
||||
GTEST_LOG_(INFO) << "WatchdogTest_SetApplicationInfo_001 end";
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.number: WatchdogTest_SetAppMainThreadState_001
|
||||
* @tc.name: SetAppMainThreadState
|
||||
@@ -397,7 +375,7 @@ HWTEST_F(WatchdogTest, WatchdogTest_ReportEvent_004, TestSize.Level1)
|
||||
watchdog_->lastWatchTime_ = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::steady_clock::now().time_since_epoch()).count();
|
||||
watchdog_->ReportEvent();
|
||||
EXPECT_TRUE(watchdog_->applicationInfo_ == nullptr);
|
||||
EXPECT_TRUE(watchdog_->appMainHandler_ != nullptr);
|
||||
GTEST_LOG_(INFO) << "WatchdogTest_ReportEvent_002 end";
|
||||
}
|
||||
|
||||
@@ -411,10 +389,8 @@ HWTEST_F(WatchdogTest, WatchdogTest_ReportEvent_005, TestSize.Level1)
|
||||
GTEST_LOG_(INFO) << "WatchdogTest_ReportEvent_005 start";
|
||||
watchdog_->lastWatchTime_ = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::steady_clock::now().time_since_epoch()).count();
|
||||
watchdog_->applicationInfo_ = std::make_shared<ApplicationInfo>();
|
||||
watchdog_->needReport_ = false;
|
||||
watchdog_->ReportEvent();
|
||||
EXPECT_TRUE(watchdog_->applicationInfo_ != nullptr);
|
||||
EXPECT_TRUE(watchdog_->needReport_ == false);
|
||||
GTEST_LOG_(INFO) << "WatchdogTest_ReportEvent_005 end";
|
||||
}
|
||||
@@ -429,10 +405,8 @@ HWTEST_F(WatchdogTest, WatchdogTest_ReportEvent_006, TestSize.Level1)
|
||||
GTEST_LOG_(INFO) << "WatchdogTest_ReportEvent_006 start";
|
||||
watchdog_->lastWatchTime_ = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::steady_clock::now().time_since_epoch()).count();
|
||||
watchdog_->applicationInfo_ = std::make_shared<ApplicationInfo>();
|
||||
watchdog_->isSixSecondEvent_ = true;
|
||||
watchdog_->ReportEvent();
|
||||
EXPECT_TRUE(watchdog_->applicationInfo_ != nullptr);
|
||||
EXPECT_TRUE(watchdog_->needReport_);
|
||||
GTEST_LOG_(INFO) << "WatchdogTest_ReportEvent_006 end";
|
||||
}
|
||||
@@ -447,40 +421,11 @@ HWTEST_F(WatchdogTest, WatchdogTest_ReportEvent_007, TestSize.Level1)
|
||||
GTEST_LOG_(INFO) << "WatchdogTest_ReportEvent_007 start";
|
||||
watchdog_->lastWatchTime_ = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::steady_clock::now().time_since_epoch()).count();
|
||||
watchdog_->applicationInfo_ = std::make_shared<ApplicationInfo>();
|
||||
watchdog_->ReportEvent();
|
||||
EXPECT_TRUE(watchdog_->applicationInfo_ != nullptr);
|
||||
EXPECT_FALSE(watchdog_->isSixSecondEvent_);
|
||||
GTEST_LOG_(INFO) << "WatchdogTest_ReportEvent_007 end";
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.number: WatchdogTest_Dump_001
|
||||
* @tc.name: Dump
|
||||
* @tc.desc: Verify that function Dump.
|
||||
*/
|
||||
HWTEST_F(WatchdogTest, WatchdogTest_Dump_001, TestSize.Level1)
|
||||
{
|
||||
GTEST_LOG_(INFO) << "WatchdogTest_Dump_001 start";
|
||||
std::string message = "message";
|
||||
mainHandlerDumper_->dumpInfo = "dump";
|
||||
mainHandlerDumper_->Dump(message);
|
||||
EXPECT_EQ(mainHandlerDumper_->GetDumpInfo(), "dumpmessage");
|
||||
GTEST_LOG_(INFO) << "WatchdogTest_Dump_001 end";
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.number: WatchdogTest_GetTag_001
|
||||
* @tc.name: GetTag
|
||||
* @tc.desc: Verify that function GetTag.
|
||||
*/
|
||||
HWTEST_F(WatchdogTest, WatchdogTest_GetTag_001, TestSize.Level1)
|
||||
{
|
||||
GTEST_LOG_(INFO) << "WatchdogTest_GetTag_001 start";
|
||||
EXPECT_EQ(mainHandlerDumper_->GetTag(), "");
|
||||
GTEST_LOG_(INFO) << "WatchdogTest_GetTag_001 end";
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.number: WatchdogTest_ReportEvent_008
|
||||
* @tc.name: ReportEvent
|
||||
@@ -491,7 +436,6 @@ HWTEST_F(WatchdogTest, WatchdogTest_ReportEvent_008, TestSize.Level1)
|
||||
watchdog_->lastWatchTime_ = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::
|
||||
system_clock::now().time_since_epoch()).count() - TEST_INTERVAL_TIME;
|
||||
std::shared_ptr<EventHandler> eventHandler = std::make_shared<EventHandler>();
|
||||
watchdog_->applicationInfo_ = std::make_shared<ApplicationInfo>();
|
||||
watchdog_->needReport_ = true;
|
||||
watchdog_->isSixSecondEvent_.store(true);
|
||||
EXPECT_TRUE(watchdog_->needReport_);
|
||||
|
||||
Reference in New Issue
Block a user