1/* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "hicollie.h" 17 18#include <unistd.h> 19#include <string> 20#include "watchdog.h" 21#include "report_data.h" 22#include "xcollie_utils.h" 23#include "iservice_registry.h" 24#include "iremote_object.h" 25 26namespace OHOS { 27namespace HiviewDFX { 28DECLARE_INTERFACE_DESCRIPTOR(u"ohos.appexecfwk.AppMgr"); 29 30#ifdef SUPPORT_ASAN 31constexpr uint32_t CHECK_INTERVAL_TIME = 45000; 32#else 33constexpr uint32_t CHECK_INTERVAL_TIME = 3000; 34#endif 35constexpr uint32_t INI_TIMER_FIRST_SECOND = 10000; 36constexpr uint32_t NOTIFY_APP_FAULT = 38; 37constexpr uint32_t APP_MGR_SERVICE_ID = 501; 38 39bool IsAppMainThread() 40{ 41 static int pid = getpid(); 42 static uint64_t uid = getuid(); 43 if (pid == gettid() && uid >= MIN_APP_UID) { 44 return true; 45 } 46 return false; 47} 48 49int32_t NotifyAppFault(const OHOS::HiviewDFX::ReportData &reportData) 50{ 51 XCOLLIE_LOGD("called."); 52 auto systemAbilityMgr = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 53 if (systemAbilityMgr == nullptr) { 54 XCOLLIE_LOGE("ReportData failed to get system ability manager."); 55 return -1; 56 } 57 auto appMgrService = systemAbilityMgr->GetSystemAbility(APP_MGR_SERVICE_ID); 58 if (appMgrService == nullptr) { 59 XCOLLIE_LOGE("ReportData failed to find APP_MGR_SERVICE_ID."); 60 return -1; 61 } 62 OHOS::MessageParcel data; 63 OHOS::MessageParcel reply; 64 OHOS::MessageOption option; 65 if (!data.WriteInterfaceToken(GetDescriptor())) { 66 XCOLLIE_LOGE("ReportData failed to WriteInterfaceToken."); 67 return -1; 68 } 69 if (!data.WriteParcelable(&reportData)) { 70 XCOLLIE_LOGE("ReportData write reportData failed."); 71 return -1; 72 } 73 auto ret = appMgrService->SendRequest(NOTIFY_APP_FAULT, data, reply, option); 74 if (ret != OHOS::NO_ERROR) { 75 XCOLLIE_LOGE("ReportData Send request failed with error code: %{public}d", ret); 76 return -1; 77 } 78 return reply.ReadInt32(); 79} 80 81int Report(bool* isSixSecond) 82{ 83 OHOS::HiviewDFX::ReportData reportData; 84 reportData.errorObject.message = "Bussiness thread is not response!"; 85 reportData.faultType = OHOS::HiviewDFX::FaultDataType::APP_FREEZE; 86 87 if (*isSixSecond) { 88 reportData.errorObject.name = "BUSSINESS_THREAD_BLOCK_6S"; 89 reportData.forceExit = true; 90 *isSixSecond = false; 91 } else { 92 reportData.errorObject.name = "BUSSINESS_THREAD_BLOCK_3S"; 93 reportData.forceExit = false; 94 *isSixSecond = true; 95 } 96 reportData.timeoutMarkers = ""; 97 reportData.errorObject.stack = ""; 98 reportData.notifyApp = false; 99 reportData.waitSaveState = false; 100 auto result = NotifyAppFault(reportData); 101 XCOLLIE_LOGI("OH_HiCollie_Report result: %{public}d", result); 102 return result; 103} 104} // end of namespace HiviewDFX 105} // end of namespace OHOS 106 107HiCollie_ErrorCode OH_HiCollie_Init_StuckDetection(OH_HiCollie_Task task) 108{ 109 if (OHOS::HiviewDFX::IsAppMainThread()) { 110 return HICOLLIE_WRONG_THREAD_CONTEXT; 111 } 112 if (!task) { 113 OHOS::HiviewDFX::Watchdog::GetInstance().RemovePeriodicalTask("BussinessWatchdog"); 114 } else { 115 OHOS::HiviewDFX::Watchdog::GetInstance().RunPeriodicalTask("BussinessWatchdog", task, 116 OHOS::HiviewDFX::CHECK_INTERVAL_TIME, OHOS::HiviewDFX::INI_TIMER_FIRST_SECOND); 117 OHOS::HiviewDFX::Watchdog::GetInstance().RemovePeriodicalTask("AppkitWatchdog"); 118 } 119 return HICOLLIE_SUCCESS; 120} 121 122HiCollie_ErrorCode OH_HiCollie_Init_JankDetection(OH_HiCollie_BeginFunc* beginFunc, 123 OH_HiCollie_EndFunc* endFunc, HiCollie_DetectionParam param) 124{ 125 if (OHOS::HiviewDFX::IsAppMainThread()) { 126 return HICOLLIE_WRONG_THREAD_CONTEXT; 127 } 128 if ((!beginFunc && endFunc) || (beginFunc && !endFunc)) { 129 return HICOLLIE_INVALID_ARGUMENT; 130 } 131 OHOS::HiviewDFX::Watchdog::GetInstance().InitMainLooperWatcher(beginFunc, endFunc); 132 return HICOLLIE_SUCCESS; 133} 134 135HiCollie_ErrorCode OH_HiCollie_Report(bool* isSixSecond) 136{ 137 if (OHOS::HiviewDFX::IsAppMainThread()) { 138 return HICOLLIE_WRONG_THREAD_CONTEXT; 139 } 140 if (isSixSecond == nullptr) { 141 return HICOLLIE_INVALID_ARGUMENT; 142 } 143 if (OHOS::HiviewDFX::Watchdog::GetInstance().GetAppDebug()) { 144 XCOLLIE_LOGD("Bussiness: Get appDebug state is true"); 145 return HICOLLIE_SUCCESS; 146 } 147 if (OHOS::HiviewDFX::Report(isSixSecond) != 0) { 148 return HICOLLIE_REMOTE_FAILED; 149 } 150 return HICOLLIE_SUCCESS; 151} 152