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