1eace7efcSopenharmony_ci/* 2eace7efcSopenharmony_ci * Copyright (c) 2022-2024 Huawei Device Co., Ltd. 3eace7efcSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4eace7efcSopenharmony_ci * you may not use this file except in compliance with the License. 5eace7efcSopenharmony_ci * You may obtain a copy of the License at 6eace7efcSopenharmony_ci * 7eace7efcSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8eace7efcSopenharmony_ci * 9eace7efcSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10eace7efcSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11eace7efcSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12eace7efcSopenharmony_ci * See the License for the specific language governing permissions and 13eace7efcSopenharmony_ci * limitations under the License. 14eace7efcSopenharmony_ci */ 15eace7efcSopenharmony_ci 16eace7efcSopenharmony_ci#include "watchdog.h" 17eace7efcSopenharmony_ci 18eace7efcSopenharmony_ci#include <parameter.h> 19eace7efcSopenharmony_ci#include <unistd.h> 20eace7efcSopenharmony_ci 21eace7efcSopenharmony_ci#include "app_mgr_client.h" 22eace7efcSopenharmony_ci#include "app_recovery.h" 23eace7efcSopenharmony_ci#include "appfreeze_inner.h" 24eace7efcSopenharmony_ci#include "hisysevent.h" 25eace7efcSopenharmony_ci#include "hilog_tag_wrapper.h" 26eace7efcSopenharmony_ci#include "xcollie/watchdog.h" 27eace7efcSopenharmony_ci 28eace7efcSopenharmony_cinamespace OHOS { 29eace7efcSopenharmony_cinamespace AppExecFwk { 30eace7efcSopenharmony_cinamespace { 31eace7efcSopenharmony_ciconstexpr uint32_t CHECK_MAIN_THREAD_IS_ALIVE = 1; 32eace7efcSopenharmony_ciconstexpr int RESET_RATIO = 2; 33eace7efcSopenharmony_ci 34eace7efcSopenharmony_ciconstexpr int32_t BACKGROUND_REPORT_COUNT_MAX = 5; 35eace7efcSopenharmony_ciconstexpr int32_t WATCHDOG_REPORT_COUNT_MAX = 5; 36eace7efcSopenharmony_ci#ifdef SUPPORT_ASAN 37eace7efcSopenharmony_ciconstexpr uint32_t CHECK_INTERVAL_TIME = 45000; 38eace7efcSopenharmony_ci#else 39eace7efcSopenharmony_ciconstexpr uint32_t CHECK_INTERVAL_TIME = 3000; 40eace7efcSopenharmony_ci#endif 41eace7efcSopenharmony_ci} 42eace7efcSopenharmony_cistd::shared_ptr<EventHandler> Watchdog::appMainHandler_ = nullptr; 43eace7efcSopenharmony_ci 44eace7efcSopenharmony_ciWatchdog::Watchdog() 45eace7efcSopenharmony_ci{} 46eace7efcSopenharmony_ci 47eace7efcSopenharmony_ciWatchdog::~Watchdog() 48eace7efcSopenharmony_ci{ 49eace7efcSopenharmony_ci if (!stopWatchdog_) { 50eace7efcSopenharmony_ci TAG_LOGD(AAFwkTag::APPDFR, "Stop watchdog"); 51eace7efcSopenharmony_ci OHOS::HiviewDFX::Watchdog::GetInstance().StopWatchdog(); 52eace7efcSopenharmony_ci } 53eace7efcSopenharmony_ci} 54eace7efcSopenharmony_ci 55eace7efcSopenharmony_civoid Watchdog::Init(const std::shared_ptr<EventHandler> mainHandler) 56eace7efcSopenharmony_ci{ 57eace7efcSopenharmony_ci std::unique_lock<std::mutex> lock(cvMutex_); 58eace7efcSopenharmony_ci Watchdog::appMainHandler_ = mainHandler; 59eace7efcSopenharmony_ci if (appMainHandler_ != nullptr) { 60eace7efcSopenharmony_ci TAG_LOGD(AAFwkTag::APPDFR, "Watchdog init send event"); 61eace7efcSopenharmony_ci appMainHandler_->SendEvent(CHECK_MAIN_THREAD_IS_ALIVE, 0, EventQueue::Priority::IMMEDIATE); 62eace7efcSopenharmony_ci } 63eace7efcSopenharmony_ci lastWatchTime_ = 0; 64eace7efcSopenharmony_ci auto watchdogTask = [this] { this->Timer(); }; 65eace7efcSopenharmony_ci OHOS::HiviewDFX::Watchdog::GetInstance().RunPeriodicalTask("AppkitWatchdog", watchdogTask, 66eace7efcSopenharmony_ci CHECK_INTERVAL_TIME, INI_TIMER_FIRST_SECOND); 67eace7efcSopenharmony_ci} 68eace7efcSopenharmony_ci 69eace7efcSopenharmony_civoid Watchdog::Stop() 70eace7efcSopenharmony_ci{ 71eace7efcSopenharmony_ci TAG_LOGD(AAFwkTag::APPDFR, "called"); 72eace7efcSopenharmony_ci std::unique_lock<std::mutex> lock(cvMutex_); 73eace7efcSopenharmony_ci if (stopWatchdog_) { 74eace7efcSopenharmony_ci TAG_LOGD(AAFwkTag::APPDFR, "stoped"); 75eace7efcSopenharmony_ci return; 76eace7efcSopenharmony_ci } 77eace7efcSopenharmony_ci stopWatchdog_.store(true); 78eace7efcSopenharmony_ci cvWatchdog_.notify_all(); 79eace7efcSopenharmony_ci OHOS::HiviewDFX::Watchdog::GetInstance().StopWatchdog(); 80eace7efcSopenharmony_ci 81eace7efcSopenharmony_ci if (appMainHandler_) { 82eace7efcSopenharmony_ci appMainHandler_.reset(); 83eace7efcSopenharmony_ci appMainHandler_ = nullptr; 84eace7efcSopenharmony_ci } 85eace7efcSopenharmony_ci} 86eace7efcSopenharmony_ci 87eace7efcSopenharmony_civoid Watchdog::SetAppMainThreadState(const bool appMainThreadState) 88eace7efcSopenharmony_ci{ 89eace7efcSopenharmony_ci std::unique_lock<std::mutex> lock(cvMutex_); 90eace7efcSopenharmony_ci appMainThreadIsAlive_.store(appMainThreadState); 91eace7efcSopenharmony_ci} 92eace7efcSopenharmony_ci 93eace7efcSopenharmony_civoid Watchdog::SetBundleInfo(const std::string& bundleName, const std::string& bundleVersion) 94eace7efcSopenharmony_ci{ 95eace7efcSopenharmony_ci OHOS::HiviewDFX::Watchdog::GetInstance().SetBundleInfo(bundleName, bundleVersion); 96eace7efcSopenharmony_ci} 97eace7efcSopenharmony_ci 98eace7efcSopenharmony_civoid Watchdog::SetBackgroundStatus(const bool isInBackground) 99eace7efcSopenharmony_ci{ 100eace7efcSopenharmony_ci std::unique_lock<std::mutex> lock(cvMutex_); 101eace7efcSopenharmony_ci isInBackground_.store(isInBackground); 102eace7efcSopenharmony_ci OHOS::HiviewDFX::Watchdog::GetInstance().SetForeground(!isInBackground); 103eace7efcSopenharmony_ci} 104eace7efcSopenharmony_ci 105eace7efcSopenharmony_civoid Watchdog::AllowReportEvent() 106eace7efcSopenharmony_ci{ 107eace7efcSopenharmony_ci std::unique_lock<std::mutex> lock(cvMutex_); 108eace7efcSopenharmony_ci needReport_.store(true); 109eace7efcSopenharmony_ci isSixSecondEvent_.store(false); 110eace7efcSopenharmony_ci backgroundReportCount_.store(0); 111eace7efcSopenharmony_ci watchdogReportCount_.store(0); 112eace7efcSopenharmony_ci} 113eace7efcSopenharmony_ci 114eace7efcSopenharmony_cibool Watchdog::IsReportEvent() 115eace7efcSopenharmony_ci{ 116eace7efcSopenharmony_ci if (appMainThreadIsAlive_) { 117eace7efcSopenharmony_ci appMainThreadIsAlive_.store(false); 118eace7efcSopenharmony_ci return false; 119eace7efcSopenharmony_ci } 120eace7efcSopenharmony_ci TAG_LOGD(AAFwkTag::APPDFR, "AppMainThread not alive"); 121eace7efcSopenharmony_ci return true; 122eace7efcSopenharmony_ci} 123eace7efcSopenharmony_ci 124eace7efcSopenharmony_cibool Watchdog::IsStopWatchdog() 125eace7efcSopenharmony_ci{ 126eace7efcSopenharmony_ci std::unique_lock<std::mutex> lock(cvMutex_); 127eace7efcSopenharmony_ci return stopWatchdog_; 128eace7efcSopenharmony_ci} 129eace7efcSopenharmony_ci 130eace7efcSopenharmony_civoid Watchdog::SetBgWorkingThreadStatus(const bool isBgWorkingThread) 131eace7efcSopenharmony_ci{ 132eace7efcSopenharmony_ci std::unique_lock<std::mutex> lock(cvMutex_); 133eace7efcSopenharmony_ci isBgWorkingThread_.store(isBgWorkingThread); 134eace7efcSopenharmony_ci} 135eace7efcSopenharmony_ci 136eace7efcSopenharmony_civoid Watchdog::Timer() 137eace7efcSopenharmony_ci{ 138eace7efcSopenharmony_ci std::unique_lock<std::mutex> lock(cvMutex_); 139eace7efcSopenharmony_ci if (stopWatchdog_) { 140eace7efcSopenharmony_ci TAG_LOGD(AAFwkTag::APPDFR, "stoped"); 141eace7efcSopenharmony_ci return; 142eace7efcSopenharmony_ci } 143eace7efcSopenharmony_ci if (!needReport_) { 144eace7efcSopenharmony_ci watchdogReportCount_++; 145eace7efcSopenharmony_ci TAG_LOGE(AAFwkTag::APPDFR, "timeout, wait to recover, wait count: %{public}d", 146eace7efcSopenharmony_ci watchdogReportCount_.load()); 147eace7efcSopenharmony_ci if (watchdogReportCount_.load() >= WATCHDOG_REPORT_COUNT_MAX) { 148eace7efcSopenharmony_ci#ifndef APP_NO_RESPONSE_DIALOG 149eace7efcSopenharmony_ci AppExecFwk::AppfreezeInner::GetInstance()->AppfreezeHandleOverReportCount(true); 150eace7efcSopenharmony_ci#endif 151eace7efcSopenharmony_ci watchdogReportCount_.store(0); 152eace7efcSopenharmony_ci } else if (watchdogReportCount_.load() >= (WATCHDOG_REPORT_COUNT_MAX - 1)) { 153eace7efcSopenharmony_ci#ifndef APP_NO_RESPONSE_DIALOG 154eace7efcSopenharmony_ci AppExecFwk::AppfreezeInner::GetInstance()->AppfreezeHandleOverReportCount(false); 155eace7efcSopenharmony_ci#endif 156eace7efcSopenharmony_ci } 157eace7efcSopenharmony_ci return; 158eace7efcSopenharmony_ci } 159eace7efcSopenharmony_ci 160eace7efcSopenharmony_ci if (IsReportEvent()) { 161eace7efcSopenharmony_ci const int bufferLen = 128; 162eace7efcSopenharmony_ci char paramOutBuf[bufferLen] = {0}; 163eace7efcSopenharmony_ci const char *hook_mode = "startup:"; 164eace7efcSopenharmony_ci int ret = GetParameter("libc.hook_mode", "", paramOutBuf, bufferLen); 165eace7efcSopenharmony_ci if (ret <= 0 || strncmp(paramOutBuf, hook_mode, strlen(hook_mode)) != 0) { 166eace7efcSopenharmony_ci ReportEvent(); 167eace7efcSopenharmony_ci } 168eace7efcSopenharmony_ci } 169eace7efcSopenharmony_ci if (appMainHandler_ != nullptr) { 170eace7efcSopenharmony_ci appMainHandler_->SendEvent(CHECK_MAIN_THREAD_IS_ALIVE, 0, EventQueue::Priority::IMMEDIATE); 171eace7efcSopenharmony_ci } 172eace7efcSopenharmony_ci int64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono:: 173eace7efcSopenharmony_ci system_clock::now().time_since_epoch()).count(); 174eace7efcSopenharmony_ci if ((now - lastWatchTime_) >= (CHECK_INTERVAL_TIME / RESET_RATIO)) { 175eace7efcSopenharmony_ci lastWatchTime_ = now; 176eace7efcSopenharmony_ci } 177eace7efcSopenharmony_ci} 178eace7efcSopenharmony_ci 179eace7efcSopenharmony_civoid Watchdog::ReportEvent() 180eace7efcSopenharmony_ci{ 181eace7efcSopenharmony_ci if (isBgWorkingThread_) { 182eace7efcSopenharmony_ci TAG_LOGD(AAFwkTag::APPDFR, "Thread is working in the background, do not report this time"); 183eace7efcSopenharmony_ci return; 184eace7efcSopenharmony_ci } 185eace7efcSopenharmony_ci int64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono:: 186eace7efcSopenharmony_ci system_clock::now().time_since_epoch()).count(); 187eace7efcSopenharmony_ci if ((now - lastWatchTime_) > (RESET_RATIO * CHECK_INTERVAL_TIME) || 188eace7efcSopenharmony_ci (now - lastWatchTime_) < (CHECK_INTERVAL_TIME / RESET_RATIO)) { 189eace7efcSopenharmony_ci TAG_LOGI(AAFwkTag::APPDFR, 190eace7efcSopenharmony_ci "Thread may be blocked, not report time. currTime: %{public}llu, lastTime: %{public}llu", 191eace7efcSopenharmony_ci static_cast<unsigned long long>(now), static_cast<unsigned long long>(lastWatchTime_)); 192eace7efcSopenharmony_ci return; 193eace7efcSopenharmony_ci } 194eace7efcSopenharmony_ci 195eace7efcSopenharmony_ci if (isInBackground_ && backgroundReportCount_.load() < BACKGROUND_REPORT_COUNT_MAX) { 196eace7efcSopenharmony_ci TAG_LOGI(AAFwkTag::APPDFR, "In Background, thread may be blocked in, not report time" 197eace7efcSopenharmony_ci "currTime: %{public}" PRIu64 ", lastTime: %{public}" PRIu64 "", 198eace7efcSopenharmony_ci static_cast<uint64_t>(now), static_cast<uint64_t>(lastWatchTime_)); 199eace7efcSopenharmony_ci backgroundReportCount_++; 200eace7efcSopenharmony_ci return; 201eace7efcSopenharmony_ci } 202eace7efcSopenharmony_ci backgroundReportCount_++; 203eace7efcSopenharmony_ci 204eace7efcSopenharmony_ci if (!needReport_) { 205eace7efcSopenharmony_ci return; 206eace7efcSopenharmony_ci } 207eace7efcSopenharmony_ci 208eace7efcSopenharmony_ci#ifndef APP_NO_RESPONSE_DIALOG 209eace7efcSopenharmony_ci if (isSixSecondEvent_) { 210eace7efcSopenharmony_ci needReport_.store(false); 211eace7efcSopenharmony_ci } 212eace7efcSopenharmony_ci#endif 213eace7efcSopenharmony_ci AppExecFwk::AppfreezeInner::GetInstance()->ThreadBlock(isSixSecondEvent_); 214eace7efcSopenharmony_ci} 215eace7efcSopenharmony_ci} // namespace AppExecFwk 216eace7efcSopenharmony_ci} // namespace OHOS 217