1 /*
2 * Copyright (c) 2023 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 "anr_handler.h"
17
18 #include <algorithm>
19 #include <cinttypes>
20 #include <functional>
21 #include <string>
22
23 #include "entrance_log.h"
24 #include "proto.h"
25 #include "util.h"
26 #include "window_manager_hilog.h"
27
28 namespace OHOS {
29 namespace Rosen {
30 namespace {
31 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "ANRHandler" };
32 constexpr int64_t MAX_MARK_PROCESS_DELAY_TIME_US { 3000000 };
33 constexpr int64_t MARK_PROCESS_DELAY_TIME_BIAS_US { 1500000 };
34 constexpr int32_t INVALID_EVENT_ID { -1 };
35 constexpr int32_t INVALID_PERSISTENT_ID { -1 };
36 constexpr int32_t TIME_TRANSITION { 1000 };
37 const std::string ANR_HANDLER_RUNNER { "ANR_HANDLER" };
38 } // namespace
39
ANRHandler()40 ANRHandler::ANRHandler()
41 {
42 auto runner = AppExecFwk::EventRunner::Create(ANR_HANDLER_RUNNER);
43 if (runner == nullptr) {
44 WLOGFE("Create eventRunner failed");
45 return;
46 }
47 eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
48 }
49
~ANRHandler()50 ANRHandler::~ANRHandler() {}
51
SetSessionStage(int32_t eventId,const wptr<ISessionStage> & sessionStage)52 void ANRHandler::SetSessionStage(int32_t eventId, const wptr<ISessionStage> &sessionStage)
53 {
54 auto task = [this, eventId, sessionStage]() {
55 sptr<ISessionStage> session = sessionStage.promote();
56 if (session == nullptr) {
57 WLOGFE("SessionStage for eventId:%{public}d is nullptr", eventId);
58 sessionStageMap_[eventId] = { INVALID_PERSISTENT_ID, nullptr };
59 return;
60 }
61 int32_t persistentId = session->GetPersistentId();
62 sessionStageMap_[eventId] = { persistentId, sessionStage };
63 WLOGFD("SetSessionStage for eventId:%{public}d, persistentId:%{public}d", eventId, persistentId);
64 };
65 PostTask(task, "SetSessionStage:EID:" + std::to_string(eventId));
66 }
67
HandleEventConsumed(int32_t eventId,int64_t actionTime)68 void ANRHandler::HandleEventConsumed(int32_t eventId, int64_t actionTime)
69 {
70 auto task = [this, eventId, actionTime]() {
71 int32_t currentPersistentId = GetPersistentIdOfEvent(eventId);
72 WLOGFD("Processed eventId:%{public}d, persistentId:%{public}d", eventId, currentPersistentId);
73 if (IsOnEventHandler(currentPersistentId)) {
74 UpdateLatestEventId(eventId);
75 return;
76 }
77 int64_t currentTime = GetSysClockTime();
78 int64_t timeoutTime = ANRTimeOutTime::INPUT_UI_TIMEOUT_TIME * TIME_TRANSITION - (currentTime - actionTime);
79 WLOGFD("Processed eventId:%{public}d, persistentId:%{public}d, actionTime:%{public}" PRId64 ", "
80 "currentTime:%{public}" PRId64 ", timeoutTime:%{public}" PRId64,
81 eventId, currentPersistentId, actionTime, currentTime, timeoutTime);
82 if (timeoutTime >= MAX_MARK_PROCESS_DELAY_TIME_US) {
83 int64_t delayTime = std::min(timeoutTime - MARK_PROCESS_DELAY_TIME_BIAS_US, MAX_MARK_PROCESS_DELAY_TIME_US);
84 SendEvent(eventId, delayTime / TIME_TRANSITION);
85 } else {
86 SendEvent(eventId, 0);
87 }
88 };
89 PostTask(task, "HandleEventConsumed:EID:" + std::to_string(eventId));
90 }
91
OnWindowDestroyed(int32_t persistentId)92 void ANRHandler::OnWindowDestroyed(int32_t persistentId)
93 {
94 auto task = [this, persistentId]() {
95 anrHandlerState_.sendStatus.erase(persistentId);
96 for (auto iter = sessionStageMap_.begin(); iter != sessionStageMap_.end();) {
97 if (iter->second.persistentId == persistentId) {
98 iter = sessionStageMap_.erase(iter);
99 } else {
100 ++iter;
101 }
102 }
103 WLOGFD("PersistentId:%{public}d and its events erased in ANRHandler", persistentId);
104 };
105 PostTask(task, "OnWindowDestroyed:PID:" + std::to_string(persistentId));
106 }
107
PostTask(Task && task,const std::string & name,int64_t delayTime)108 bool ANRHandler::PostTask(Task &&task, const std::string& name, int64_t delayTime)
109 {
110 if (eventHandler_ == nullptr) {
111 WLOGFE("EventHandler is nullptr");
112 return false;
113 }
114 if (eventHandler_->GetEventRunner()->IsCurrentRunnerThread()) {
115 WLOGFE("Already running on eventHandler");
116 task();
117 return true;
118 }
119 if (!eventHandler_->PostTask(std::move(task), "wms:" + name, delayTime,
120 AppExecFwk::EventQueue::Priority::IMMEDIATE)) {
121 WLOGFE("PostTask failed");
122 return false;
123 }
124 return true;
125 }
126
SetAnrHandleState(int32_t eventId,bool status)127 void ANRHandler::SetAnrHandleState(int32_t eventId, bool status)
128 {
129 CALL_DEBUG_ENTER;
130 int32_t persistentId = GetPersistentIdOfEvent(eventId);
131 anrHandlerState_.sendStatus[persistentId] = status;
132 if (status) {
133 anrHandlerState_.eventsToReceipt.push_back(eventId);
134 } else {
135 if(anrHandlerState_.eventsToReceipt.empty()){
136 WLOGFE("EventsToReceipt is empty");
137 return;
138 }
139 anrHandlerState_.eventsToReceipt.pop_front();
140 ClearExpiredEvents(eventId);
141 }
142 }
143
MarkProcessed()144 void ANRHandler::MarkProcessed()
145 {
146 CALL_DEBUG_ENTER;
147 if (anrHandlerState_.eventsToReceipt.empty()) {
148 WLOGFE("Events to receipt is empty");
149 SetAnrHandleState(INVALID_EVENT_ID, false);
150 return;
151 }
152 int32_t eventId = anrHandlerState_.eventsToReceipt.front();
153 WLOGFI("InputTracking MarkProcessed eventId:%{public}d, persistentId:%{public}d",
154 eventId, GetPersistentIdOfEvent(eventId));
155 if (sessionStageMap_.find(eventId) == sessionStageMap_.end()) {
156 WLOGFW("SessionStage for eventId:%{public}d is not in sessionStageMap", eventId);
157 } else {
158 sptr<ISessionStage> session = sessionStageMap_[eventId].sessionStage.promote();
159 if (session == nullptr) {
160 WLOGFE("SessionStage for eventId:%{public}d is nullptr", eventId);
161 } else if (WSError ret = session->MarkProcessed(eventId); ret != WSError::WS_OK) {
162 WLOGFE("Send to sceneBoard failed, ret:%{public}d", ret);
163 }
164 }
165 SetAnrHandleState(eventId, false);
166 }
167
SendEvent(int32_t eventId,int64_t delayTime)168 void ANRHandler::SendEvent(int32_t eventId, int64_t delayTime)
169 {
170 CALL_DEBUG_ENTER;
171 SetAnrHandleState(eventId, true);
172 auto task = [this]() {
173 MarkProcessed();
174 };
175 if (eventHandler_ != nullptr &&
176 eventHandler_->PostHighPriorityTask(task, "MarkProcessed", delayTime)) {
177 WLOGFD("Post eventId:%{public}d, delayTime:%{public}" PRId64 " successfully", eventId, delayTime);
178 } else {
179 WLOGFE("Post eventId:%{public}d, delayTime:%{public}" PRId64 " failed", eventId, delayTime);
180 SetAnrHandleState(eventId, false);
181 }
182 }
183
ClearExpiredEvents(int32_t eventId)184 void ANRHandler::ClearExpiredEvents(int32_t eventId)
185 {
186 CALL_DEBUG_ENTER;
187 int32_t persistentId = GetPersistentIdOfEvent(eventId);
188 for (auto iter = sessionStageMap_.begin(); iter != sessionStageMap_.end();) {
189 auto currentPersistentId = GetPersistentIdOfEvent(iter->first);
190 if (iter->first < eventId &&
191 (currentPersistentId == persistentId || currentPersistentId == INVALID_PERSISTENT_ID)) {
192 iter = sessionStageMap_.erase(iter);
193 } else {
194 ++iter;
195 }
196 }
197 }
198
GetPersistentIdOfEvent(int32_t eventId)199 int32_t ANRHandler::GetPersistentIdOfEvent(int32_t eventId)
200 {
201 if (sessionStageMap_.find(eventId) != sessionStageMap_.end()) {
202 return sessionStageMap_[eventId].persistentId;
203 }
204 WLOGFW("No sessionStage for eventId:%{public}d", eventId);
205 return INVALID_PERSISTENT_ID;
206 }
207
IsOnEventHandler(int32_t persistentId)208 bool ANRHandler::IsOnEventHandler(int32_t persistentId)
209 {
210 if (anrHandlerState_.sendStatus.find(persistentId) != anrHandlerState_.sendStatus.end() &&
211 anrHandlerState_.sendStatus[persistentId]) {
212 return true;
213 }
214 return false;
215 }
216
UpdateLatestEventId(int32_t eventId)217 void ANRHandler::UpdateLatestEventId(int32_t eventId)
218 {
219 auto currentPersistentId = GetPersistentIdOfEvent(eventId);
220 for (auto &event : anrHandlerState_.eventsToReceipt) {
221 if ((GetPersistentIdOfEvent(event) == currentPersistentId) && (eventId > event)) {
222 WLOGFD("Replace eventId:%{public}d by newer eventId:%{public}d", event, eventId);
223 event = eventId;
224 break;
225 }
226 }
227 }
228
229 } // namespace Rosen
230 } // namespace OHOS
231