• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <cinttypes>
19 #include <functional>
20 #include <string>
21 
22 #include "entrance_log.h"
23 #include "proto.h"
24 #include "util.h"
25 #include "window_manager_hilog.h"
26 
27 namespace OHOS {
28 namespace Rosen {
29 namespace {
30 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "ANRHandler" };
31 constexpr int64_t MAX_MARK_PROCESS_DELAY_TIME { 3500000 };
32 constexpr int64_t MIN_MARK_PROCESS_DELAY_TIME { 50000 };
33 constexpr int32_t INVALID_EVENT_ID { -1 };
34 constexpr int32_t INVALID_PERSISTENT_ID { -1 };
35 constexpr int32_t TIME_TRANSITION { 1000 };
36 const std::string ANR_HANDLER_RUNNER { "ANR_HANDLER" };
37 } // namespace
38 
ANRHandler()39 ANRHandler::ANRHandler()
40 {
41     auto runner = AppExecFwk::EventRunner::Create(ANR_HANDLER_RUNNER);
42     if (runner == nullptr) {
43         WLOGFE("Create eventRunner failed");
44         return;
45     }
46     eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
47 }
48 
~ANRHandler()49 ANRHandler::~ANRHandler() {}
50 
SetSessionStage(int32_t eventId,const wptr<ISessionStage> & sessionStage)51 void ANRHandler::SetSessionStage(int32_t eventId, const wptr<ISessionStage> &sessionStage)
52 {
53     std::lock_guard<std::recursive_mutex> lock(mutex_);
54     sessionStageMap_[eventId] = sessionStage;
55 }
56 
HandleEventConsumed(int32_t eventId,int64_t actionTime)57 void ANRHandler::HandleEventConsumed(int32_t eventId, int64_t actionTime)
58 {
59     std::lock_guard<std::recursive_mutex> lock(mutex_);
60     int32_t currentPersistentId = GetPersistentIdOfEvent(eventId);
61     WLOGFD("Processed eventId:%{public}d, persistentId:%{public}d", eventId, currentPersistentId);
62     if (IsOnEventHandler(currentPersistentId)) {
63         UpdateLatestEventId(eventId);
64         return;
65     }
66     int64_t currentTime = GetSysClockTime();
67     int64_t timeoutTime = ANRTimeOutTime::INPUT_UI_TIMEOUT_TIME * TIME_TRANSITION - (currentTime - actionTime);
68     WLOGFD("Processed eventId:%{public}d, persistentId:%{public}d, actionTime:%{public}" PRId64 ", "
69         "currentTime:%{public}" PRId64 ", timeoutTime:%{public}" PRId64,
70         eventId, currentPersistentId, actionTime, currentTime, timeoutTime);
71     if (timeoutTime < MIN_MARK_PROCESS_DELAY_TIME) {
72         SendEvent(eventId, 0);
73     } else {
74         int64_t delayTime = 0;
75         if (timeoutTime >= MAX_MARK_PROCESS_DELAY_TIME) {
76             delayTime = MAX_MARK_PROCESS_DELAY_TIME / TIME_TRANSITION;
77         } else {
78             delayTime = timeoutTime / TIME_TRANSITION;
79         }
80         SendEvent(eventId, delayTime);
81     }
82 }
83 
ClearDestroyedPersistentId(int32_t persistentId)84 void ANRHandler::ClearDestroyedPersistentId(int32_t persistentId)
85 {
86     CALL_DEBUG_ENTER;
87     std::lock_guard<std::recursive_mutex> lock(mutex_);
88     if (anrHandlerState_.sendStatus.find(persistentId) == anrHandlerState_.sendStatus.end()) {
89         WLOGFE("PersistentId:%{public}d not in ANRHandler", persistentId);
90         return;
91     }
92     anrHandlerState_.sendStatus.erase(persistentId);
93     WLOGFD("PersistentId:%{public}d erased in ANRHandler", persistentId);
94 }
95 
SetAnrHandleState(int32_t eventId,bool status)96 void ANRHandler::SetAnrHandleState(int32_t eventId, bool status)
97 {
98     CALL_DEBUG_ENTER;
99     std::lock_guard<std::recursive_mutex> lock(mutex_);
100     int32_t persistentId = GetPersistentIdOfEvent(eventId);
101     anrHandlerState_.sendStatus[persistentId] = status;
102     if (status) {
103         anrHandlerState_.eventsToReceipt.push_back(eventId);
104     } else {
105         anrHandlerState_.eventsToReceipt.pop_front();
106         ClearExpiredEvents(eventId);
107     }
108 }
109 
MarkProcessed()110 void ANRHandler::MarkProcessed()
111 {
112     CALL_DEBUG_ENTER;
113     std::lock_guard<std::recursive_mutex> lock(mutex_);
114     if (anrHandlerState_.eventsToReceipt.empty()) {
115         WLOGFE("Events to receipt is empty");
116         SetAnrHandleState(INVALID_EVENT_ID, false);
117         return;
118     }
119     int32_t eventId = anrHandlerState_.eventsToReceipt.front();
120     WLOGFD("EventId:%{public}d ", eventId);
121     if (sessionStageMap_.find(eventId) == sessionStageMap_.end()) {
122         WLOGFE("SessionStage for eventId:%{public}d is not in sessionStageMap", eventId);
123     } else if (sessionStageMap_[eventId] == nullptr) {
124         WLOGFE("SessionStage for eventId:%{public}d is nullptr", eventId);
125     } else if (WSError ret = sessionStageMap_[eventId]->MarkProcessed(eventId); ret != WSError::WS_OK) {
126         WLOGFE("Send to sceneBoard failed, ret:%{public}d", ret);
127     }
128     SetAnrHandleState(eventId, false);
129 }
130 
SendEvent(int32_t eventId,int64_t delayTime)131 void ANRHandler::SendEvent(int32_t eventId, int64_t delayTime)
132 {
133     CALL_DEBUG_ENTER;
134     std::lock_guard<std::recursive_mutex> lock(mutex_);
135     SetAnrHandleState(eventId, true);
136     if (eventHandler_ == nullptr) {
137         WLOGFE("EventHandler is nullptr");
138         SetAnrHandleState(eventId, false);
139         return;
140     }
141     if (!eventHandler_->PostHighPriorityTask(std::bind(&ANRHandler::MarkProcessed, this), delayTime)) {
142         WLOGFE("Send dispatch event failed");
143     }
144 }
145 
ClearExpiredEvents(int32_t eventId)146 void ANRHandler::ClearExpiredEvents(int32_t eventId)
147 {
148     CALL_DEBUG_ENTER;
149     std::lock_guard<std::recursive_mutex> lock(mutex_);
150     int32_t persistentId = GetPersistentIdOfEvent(eventId);
151     for (auto iter = sessionStageMap_.begin(); iter != sessionStageMap_.end();) {
152         auto currentPersistentId = GetPersistentIdOfEvent(iter->first);
153         if (iter->first < eventId &&
154             (currentPersistentId == persistentId || currentPersistentId == INVALID_PERSISTENT_ID)) {
155             sessionStageMap_.erase(iter++);
156         } else {
157             iter++;
158         }
159     }
160 }
161 
GetPersistentIdOfEvent(int32_t eventId)162 int32_t ANRHandler::GetPersistentIdOfEvent(int32_t eventId)
163 {
164     std::lock_guard<std::recursive_mutex> lock(mutex_);
165     if (sessionStageMap_.find(eventId) == sessionStageMap_.end()) {
166         WLOGFE("No sessionStage for eventId:%{public}d", eventId);
167         return INVALID_PERSISTENT_ID;
168     }
169     auto sessionStage = sessionStageMap_[eventId];
170     if (sessionStage == nullptr) {
171         WLOGFE("SessionStage for eventId:%{public}d is nullptr", eventId);
172         return INVALID_PERSISTENT_ID;
173     }
174     return sessionStage->GetPersistentId();
175 }
176 
IsOnEventHandler(int32_t persistentId)177 bool ANRHandler::IsOnEventHandler(int32_t persistentId)
178 {
179     std::lock_guard<std::recursive_mutex> lock(mutex_);
180     if (anrHandlerState_.sendStatus.find(persistentId) != anrHandlerState_.sendStatus.end() &&
181         anrHandlerState_.sendStatus[persistentId]) {
182         return true;
183     }
184     return false;
185 }
186 
UpdateLatestEventId(int32_t eventId)187 void ANRHandler::UpdateLatestEventId(int32_t eventId)
188 {
189     std::lock_guard<std::recursive_mutex> lock(mutex_);
190     auto currentPersistentId = GetPersistentIdOfEvent(eventId);
191     for (auto& event : anrHandlerState_.eventsToReceipt) {
192         if (GetPersistentIdOfEvent(event) == currentPersistentId && eventId > event) {
193             WLOGFD("Replace eventId:%{public}d by newer eventId:%{public}d", event, eventId);
194             event = eventId;
195             break;
196         }
197     }
198 }
199 } // namespace Rosen
200 } // namespace OHOS
201