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 "core/common/event_dump.h"
17
18 namespace OHOS::Ace::NG {
19 namespace {
20 constexpr size_t MAX_EVENT_TREE_RECORD_CNT = 5;
21 constexpr size_t MAX_FRAME_NODE_CNT = 256;
22 constexpr int32_t MAX_EVENT_TREE_TOUCH_DOWN_CNT = 10;
23 constexpr int32_t MAX_EVENT_TREE_TOUCH_POINT_CNT = 20;
24 constexpr int32_t MAX_EVENT_TREE_GESTURE_CNT = 100;
25 } // end of namespace
26
Dump(std::list<std::pair<int32_t,std::string>> & dumpList,int32_t depth) const27 void FrameNodeSnapshot::Dump(std::list<std::pair<int32_t, std::string>>& dumpList, int32_t depth) const
28 {
29 std::stringstream oss;
30 oss << "nodeId: " << nodeId << ", "
31 << "parentId: " << parentNodeId << ", "
32 << "tag: " << tag << ", ";
33 if (!comId.empty()) {
34 oss << "comId: " << comId << ", ";
35 }
36 oss << "monopolizeEvents: " << monopolizeEvents << ", "
37 << "isHit: " << isHit << ", "
38 << "hitTestMode: " << hitTestMode << ", ";
39 #ifndef IS_RELEASE_VERSION
40 oss << "responseRegion: ";
41 for (const auto& rect : responseRegionList) {
42 oss << rect.ToString().c_str();
43 }
44 #endif
45 dumpList.emplace_back(std::make_pair(depth, oss.str()));
46 }
47
TouchPointSnapshot(const TouchEvent & event)48 TouchPointSnapshot::TouchPointSnapshot(const TouchEvent& event)
49 {
50 id = event.id;
51 point = OffsetF(event.x, event.y);
52 screenPoint = OffsetF(event.screenX, event.screenY);
53 type = event.type;
54 timestamp = GetCurrentTimestamp();
55 isInjected = event.isInjected;
56 }
57
Dump(std::list<std::pair<int32_t,std::string>> & dumpList,int32_t depth) const58 void TouchPointSnapshot::Dump(std::list<std::pair<int32_t, std::string>>& dumpList, int32_t depth) const
59 {
60 std::stringstream oss;
61 #ifdef IS_RELEASE_VERSION
62 oss << "id: " << id << ", "
63 << "type: " << GestureSnapshot::TransTouchType(type) << ", "
64 << "timestamp: " << ConvertTimestampToStr(timestamp) << ", "
65 << "isInjected: " << isInjected;
66 #else
67 oss << "id: " << id << ", "
68 << "point: " << point.ToString() << ", "
69 << "screenPoint: " << screenPoint.ToString() << ", "
70 << "type: " << GestureSnapshot::TransTouchType(type) << ", "
71 << "timestamp: " << ConvertTimestampToStr(timestamp) << ", "
72 << "isInjected: " << isInjected;
73 #endif
74 dumpList.emplace_back(std::make_pair(depth, oss.str()));
75 }
76
AddTouchPoint(const TouchEvent & event)77 void EventTreeRecord::AddTouchPoint(const TouchEvent& event)
78 {
79 if (!eventTreeList.empty()) {
80 if (eventTreeList.back().touchPoints.size() > MAX_EVENT_TREE_TOUCH_POINT_CNT) {
81 eventTreeList.pop_back();
82 TAG_LOGW(AceLogTag::ACE_INPUTTRACKING,
83 "EventTreeList last record touchPoint size is over limit! Last record is cleaned.");
84 }
85 if (!eventTreeList.empty() && event.type == Ace::TouchType::DOWN &&
86 eventTreeList.back().downFingerIds_.count(event.id) > 0) {
87 eventTreeList.pop_back();
88 TAG_LOGW(AceLogTag::ACE_INPUTTRACKING,
89 "EventTreeList last record receive DOWN event twice. Last record is cleaned.");
90 }
91 }
92 TouchType type = event.type;
93 if (type == Ace::TouchType::DOWN) {
94 // multi fingers touch down will be in one tree
95 if (eventTreeList.empty() || eventTreeList.back().touchDownCount <= 0 ||
96 eventTreeList.back().touchDownCount >= MAX_EVENT_TREE_TOUCH_DOWN_CNT) {
97 eventTreeList.emplace_back(EventTree());
98 if (eventTreeList.size() > MAX_EVENT_TREE_RECORD_CNT) {
99 eventTreeList.erase(eventTreeList.begin());
100 }
101 }
102 eventTreeList.back().touchDownCount++;
103 eventTreeList.back().downFingerIds_.insert(event.id);
104 }
105
106 if (eventTreeList.empty()) {
107 return;
108 }
109
110 if (type == TouchType::UP || type == TouchType::CANCEL || type == TouchType::PULL_UP ||
111 type == TouchType::PULL_OUT_WINDOW) {
112 eventTreeList.back().touchDownCount--;
113 eventTreeList.back().downFingerIds_.erase(event.id);
114 }
115 eventTreeList.back().touchPoints.emplace_back(TouchPointSnapshot(event));
116 }
117
AddFrameNodeSnapshot(FrameNodeSnapshot && node)118 void EventTreeRecord::AddFrameNodeSnapshot(FrameNodeSnapshot&& node)
119 {
120 if (eventTreeList.empty()) {
121 return;
122 }
123 if (eventTreeList.back().hitTestTree.size() < MAX_FRAME_NODE_CNT) {
124 bool isInList = false;
125 for (auto& iter : eventTreeList.back().hitTestTree) {
126 if (iter.nodeId == node.nodeId) {
127 isInList = true;
128 break;
129 }
130 }
131 if (isInList) {
132 return;
133 }
134 eventTreeList.back().hitTestTree.emplace_back(node);
135 }
136 }
137
AddGestureSnapshot(int32_t finger,RefPtr<GestureSnapshot> && gesture)138 void EventTreeRecord::AddGestureSnapshot(int32_t finger, RefPtr<GestureSnapshot>&& gesture)
139 {
140 if (eventTreeList.empty()) {
141 return;
142 }
143 if (eventTreeList.size() > MAX_EVENT_TREE_RECORD_CNT) {
144 eventTreeList.clear();
145 TAG_LOGW(AceLogTag::ACE_INPUTTRACKING, "EventTreeList size is over MAX, clean event tree.");
146 return;
147 }
148 auto& gestureTree = eventTreeList.back().gestureTree;
149 auto& gestureMap = eventTreeList.back().gestureMap;
150 if (gestureMap.size() > MAX_EVENT_TREE_GESTURE_CNT) {
151 eventTreeList.clear();
152 TAG_LOGW(AceLogTag::ACE_INPUTTRACKING, "GestureMap size is over MAX, clean event tree.");
153 return;
154 }
155 gestureMap[gesture->id] = gesture;
156 gestureTree[finger].emplace_back(gesture);
157 }
158
AddGestureProcedure(uint64_t id,const std::string & procedure,const std::string & state,const std::string & disposal,int64_t timestamp)159 void EventTreeRecord::AddGestureProcedure(uint64_t id,
160 const std::string& procedure, const std::string& state, const std::string& disposal, int64_t timestamp)
161 {
162 if (eventTreeList.empty()) {
163 return;
164 }
165 auto& gestureMap = eventTreeList.back().gestureMap;
166 auto iter = gestureMap.find(id);
167 if (iter == gestureMap.end()) {
168 return;
169 }
170 // TouchEventActuator don't record move
171 if (iter->second->type == "TouchEventActuator" && procedure == "HandleTouchMove") {
172 return;
173 }
174 iter->second->AddProcedure(procedure, state, disposal, timestamp);
175 }
176
AddGestureProcedure(uint64_t id,const TouchEvent & point,const std::string & state,const std::string & disposal,int64_t timestamp)177 void EventTreeRecord::AddGestureProcedure(uint64_t id,
178 const TouchEvent& point, const std::string& state, const std::string& disposal, int64_t timestamp)
179 {
180 if (eventTreeList.empty()) {
181 return;
182 }
183 auto& gestureMap = eventTreeList.back().gestureMap;
184 auto iter = gestureMap.find(id);
185 if (iter == gestureMap.end()) {
186 return;
187 }
188
189 if ((point.type == TouchType::MOVE || point.type == TouchType::PULL_MOVE) &&
190 !iter->second->CheckNeedAddMove(state, disposal)) {
191 return;
192 }
193 std::string procedure = std::string("Handle").append(GestureSnapshot::TransTouchType(point.type));
194 iter->second->AddProcedure(procedure, state, disposal, timestamp);
195 }
196
Dump(std::list<std::pair<int32_t,std::string>> & dumpList,int32_t depth,int32_t startNumber) const197 void EventTreeRecord::Dump(std::list<std::pair<int32_t, std::string>>& dumpList,
198 int32_t depth, int32_t startNumber) const
199 {
200 int32_t index = 0;
201 int32_t listDepth = depth + 1;
202 int32_t detailDepth = listDepth + 1;
203 for (auto& tree : eventTreeList) {
204 if (index < startNumber) {
205 index++;
206 continue;
207 }
208 std::string header = std::to_string(index).append(": event tree =>");
209
210 // dump needful touch points:
211 dumpList.emplace_back(std::make_pair(depth, header));
212 dumpList.emplace_back(std::make_pair(listDepth, "touch points:"));
213 for (auto& item : tree.touchPoints) {
214 item.Dump(dumpList, detailDepth);
215 }
216
217 // dump hit test frame nodes:
218 dumpList.emplace_back(std::make_pair(listDepth, "hittest:"));
219 for (auto& item : tree.hitTestTree) {
220 item.Dump(dumpList, detailDepth);
221 }
222
223 // dump gesture event and procedure:
224 dumpList.emplace_back(std::make_pair(listDepth, "event procedures:"));
225 for (auto iter = tree.gestureTree.begin(); iter != tree.gestureTree.end(); ++iter) {
226 dumpList.emplace_back(std::make_pair(detailDepth,
227 std::string("finger:").append(std::to_string(iter->first))));
228 for (const auto& item : iter->second) {
229 item->Dump(dumpList, detailDepth + 1);
230 }
231 }
232 ++index;
233 }
234 }
235 } // end of namespace
236