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