1 /*
2 * Copyright (c) 2021-2022 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 "touch_transform_processor.h"
17
18 #include <linux/input.h>
19
20 #include "aggregator.h"
21 #include "event_log_helper.h"
22 #include "input_device_manager.h"
23 #include "i_input_windows_manager.h"
24 #include "fingersense_wrapper.h"
25 #include "mmi_log.h"
26 #include "timer_manager.h"
27
28 #undef MMI_LOG_DOMAIN
29 #define MMI_LOG_DOMAIN MMI_LOG_DISPATCH
30 #undef MMI_LOG_TAG
31 #define MMI_LOG_TAG "TouchTransformProcessor"
32
33 namespace OHOS {
34 namespace MMI {
35 namespace {
36 constexpr int32_t MT_TOOL_NONE { -1 };
37 constexpr int32_t BTN_DOWN { 1 };
38 constexpr int32_t DRIVER_NUMBER { 8 };
39 constexpr uint32_t TOUCH_CANCEL_MASK { 1U << 29U };
40 } // namespace
41
TouchTransformProcessor(int32_t deviceId)42 TouchTransformProcessor::TouchTransformProcessor(int32_t deviceId)
43 : deviceId_(deviceId)
44 {
45 InitToolTypes();
46 }
47
OnEventTouchDown(struct libinput_event * event)48 bool TouchTransformProcessor::OnEventTouchDown(struct libinput_event *event)
49 {
50 CALL_DEBUG_ENTER;
51 CHKPF(event);
52 auto touch = libinput_event_get_touch_event(event);
53 CHKPF(touch);
54 auto device = libinput_event_get_device(event);
55 CHKPF(device);
56 EventTouch touchInfo;
57 int32_t logicalDisplayId = -1;
58 if (!WIN_MGR->TouchPointToDisplayPoint(deviceId_, touch, touchInfo, logicalDisplayId)) {
59 MMI_HILOGE("TouchDownPointToDisplayPoint failed");
60 return false;
61 }
62 auto pointIds = pointerEvent_->GetPointerIds();
63 uint64_t time = libinput_event_touch_get_time_usec(touch);
64 if (pointIds.empty()) {
65 pointerEvent_->SetActionStartTime(time);
66 pointerEvent_->SetTargetDisplayId(logicalDisplayId);
67 }
68 pointerEvent_->SetActionTime(time);
69 pointerEvent_->SetPointerAction(PointerEvent::POINTER_ACTION_DOWN);
70 PointerEvent::PointerItem item;
71 double pressure = libinput_event_touch_get_pressure(touch);
72 int32_t seatSlot = libinput_event_touch_get_seat_slot(touch);
73 // we clean up pointerItem's cancel mark at down stage to ensure newer event
74 // always starts with a clean and inital state
75 if (pointerItemCancelMarks_.find(seatSlot) != pointerItemCancelMarks_.end()) {
76 pointerItemCancelMarks_.erase(seatSlot);
77 }
78 int32_t longAxis = libinput_event_get_touch_contact_long_axis(touch);
79 int32_t shortAxis = libinput_event_get_touch_contact_short_axis(touch);
80 item.SetPressure(pressure);
81 item.SetLongAxis(longAxis);
82 item.SetShortAxis(shortAxis);
83 item.SetPointerId(seatSlot);
84 item.SetDownTime(time);
85 item.SetPressed(true);
86 UpdatePointerItemProperties(item, touchInfo);
87 item.SetDeviceId(deviceId_);
88 int32_t toolType = GetTouchToolType(touch, device);
89 #ifdef OHOS_BUILD_ENABLE_FINGERSENSE_WRAPPER
90 NotifyFingersenseProcess(item, toolType);
91 #endif // OHOS_BUILD_ENABLE_FINGERSENSE_WRAPPER
92 item.SetToolType(toolType);
93 pointerEvent_->SetDeviceId(deviceId_);
94 pointerEvent_->AddPointerItem(item);
95 pointerEvent_->SetPointerId(seatSlot);
96 pointerEvent_->ClearFlag(InputEvent::EVENT_FLAG_ACCESSIBILITY);
97 return true;
98 }
99
UpdatePointerItemProperties(PointerEvent::PointerItem & item,EventTouch & touchInfo)100 void TouchTransformProcessor::UpdatePointerItemProperties(PointerEvent::PointerItem &item, EventTouch &touchInfo)
101 {
102 CALL_DEBUG_ENTER;
103 item.SetDisplayX(touchInfo.point.x);
104 item.SetDisplayY(touchInfo.point.y);
105 item.SetDisplayXPos(touchInfo.point.x);
106 item.SetDisplayYPos(touchInfo.point.y);
107 item.SetRawDisplayX(touchInfo.point.x);
108 item.SetRawDisplayY(touchInfo.point.y);
109 item.SetToolDisplayX(touchInfo.toolRect.point.x);
110 item.SetToolDisplayY(touchInfo.toolRect.point.y);
111 item.SetToolWidth(touchInfo.toolRect.width);
112 item.SetToolHeight(touchInfo.toolRect.height);
113 }
114
115 #ifdef OHOS_BUILD_ENABLE_FINGERSENSE_WRAPPER
NotifyFingersenseProcess(PointerEvent::PointerItem & pointerItem,int32_t & toolType)116 void TouchTransformProcessor::NotifyFingersenseProcess(PointerEvent::PointerItem &pointerItem,
117 int32_t &toolType)__attribute__((no_sanitize("cfi")))
118 {
119 CALL_DEBUG_ENTER;
120 TransformTouchProperties(rawTouch_, pointerItem);
121 if (FINGERSENSE_WRAPPER->setCurrentToolType_) {
122 MMI_HILOGD("Fingersense start classify touch down event");
123 TouchType rawTouchTmp = rawTouch_;
124 int32_t displayX = pointerItem.GetRawDisplayX();
125 int32_t displayY = pointerItem.GetRawDisplayY();
126 #ifdef OHOS_BUILD_ENABLE_TOUCH
127 WIN_MGR->ReverseXY(displayX, displayY);
128 #endif // OHOS_BUILD_ENABLE_TOUCH
129 rawTouchTmp.x = displayX * DRIVER_NUMBER;
130 rawTouchTmp.y = displayY * DRIVER_NUMBER;
131 FINGERSENSE_WRAPPER->setCurrentToolType_(rawTouchTmp, toolType);
132 }
133 }
TransformTouchProperties(TouchType & rawTouch,PointerEvent::PointerItem & pointerItem)134 void TouchTransformProcessor::TransformTouchProperties(TouchType &rawTouch, PointerEvent::PointerItem &pointerItem)
135 {
136 CALL_DEBUG_ENTER;
137 rawTouch.id = pointerItem.GetPointerId();
138 rawTouch.pressure = pointerItem.GetPressure();
139 rawTouch.x = pointerItem.GetRawDisplayX();
140 rawTouch.y = pointerItem.GetRawDisplayY();
141 }
142 #endif // OHOS_BUILD_ENABLE_FINGERSENSE_WRAPPER
143
OnEventTouchMotion(struct libinput_event * event)144 bool TouchTransformProcessor::OnEventTouchMotion(struct libinput_event *event)
145 {
146 CALL_DEBUG_ENTER;
147 CHKPF(event);
148 auto touch = libinput_event_get_touch_event(event);
149 CHKPF(touch);
150 uint64_t time = libinput_event_touch_get_time_usec(touch);
151 pointerEvent_->SetActionTime(time);
152 pointerEvent_->SetPointerAction(PointerEvent::POINTER_ACTION_MOVE);
153 EventTouch touchInfo;
154 int32_t logicalDisplayId = pointerEvent_->GetTargetDisplayId();
155 if (!WIN_MGR->TouchPointToDisplayPoint(deviceId_, touch, touchInfo, logicalDisplayId)) {
156 MMI_HILOGE("Get TouchMotionPointToDisplayPoint failed");
157 return false;
158 }
159 PointerEvent::PointerItem item;
160 int32_t seatSlot = libinput_event_touch_get_seat_slot(touch);
161 if (!(pointerEvent_->GetPointerItem(seatSlot, item))) {
162 MMI_HILOGE("Get pointer parameter failed");
163 return false;
164 }
165 double pressure = libinput_event_touch_get_pressure(touch);
166 int32_t longAxis = libinput_event_get_touch_contact_long_axis(touch);
167 if (static_cast<uint32_t>(longAxis) & TOUCH_CANCEL_MASK) {
168 pointerItemCancelMarks_.emplace(seatSlot, true);
169 }
170 int32_t shortAxis = libinput_event_get_touch_contact_short_axis(touch);
171 item.SetPressure(pressure);
172 item.SetLongAxis(longAxis);
173 item.SetShortAxis(shortAxis);
174 item.SetDisplayX(touchInfo.point.x);
175 item.SetDisplayY(touchInfo.point.y);
176 item.SetDisplayXPos(touchInfo.point.x);
177 item.SetDisplayYPos(touchInfo.point.y);
178 item.SetRawDisplayX(touchInfo.point.x);
179 item.SetRawDisplayY(touchInfo.point.y);
180 item.SetToolDisplayX(touchInfo.toolRect.point.x);
181 item.SetToolDisplayY(touchInfo.toolRect.point.y);
182 item.SetToolWidth(touchInfo.toolRect.width);
183 item.SetToolHeight(touchInfo.toolRect.height);
184 pointerEvent_->UpdatePointerItem(seatSlot, item);
185 pointerEvent_->SetPointerId(seatSlot);
186 pointerEvent_->ClearFlag(InputEvent::EVENT_FLAG_ACCESSIBILITY);
187 return true;
188 }
189
OnEventTouchUp(struct libinput_event * event)190 bool TouchTransformProcessor::OnEventTouchUp(struct libinput_event *event) __attribute__((no_sanitize("cfi")))
191 {
192 CALL_DEBUG_ENTER;
193 CHKPF(event);
194 auto touch = libinput_event_get_touch_event(event);
195 CHKPF(touch);
196 uint64_t time = libinput_event_touch_get_time_usec(touch);
197 pointerEvent_->SetActionTime(time);
198 int32_t seatSlot = libinput_event_touch_get_seat_slot(touch);
199 if (pointerItemCancelMarks_.find(seatSlot) != pointerItemCancelMarks_.end()) {
200 pointerEvent_->SetPointerAction(PointerEvent::POINTER_ACTION_CANCEL);
201 pointerItemCancelMarks_.erase(seatSlot);
202 } else {
203 pointerEvent_->SetPointerAction(PointerEvent::POINTER_ACTION_UP);
204 }
205
206 PointerEvent::PointerItem item;
207 if (!(pointerEvent_->GetPointerItem(seatSlot, item))) {
208 MMI_HILOGE("Get pointer parameter failed");
209 return false;
210 }
211 item.SetPressed(false);
212 #ifdef OHOS_BUILD_ENABLE_FINGERSENSE_WRAPPER
213 TransformTouchProperties(rawTouch_, item);
214 if (FINGERSENSE_WRAPPER->notifyTouchUp_) {
215 MMI_HILOGD("Notify fingersense touch up event");
216 TouchType rawTouchTmp = rawTouch_;
217 int32_t displayX = item.GetRawDisplayX();
218 int32_t displayY = item.GetRawDisplayY();
219 #ifdef OHOS_BUILD_ENABLE_TOUCH
220 WIN_MGR->ReverseXY(displayX, displayY);
221 #endif // OHOS_BUILD_ENABLE_TOUCH
222 rawTouchTmp.x = displayX * DRIVER_NUMBER;
223 rawTouchTmp.y = displayY * DRIVER_NUMBER;
224 FINGERSENSE_WRAPPER->notifyTouchUp_(&rawTouchTmp);
225 }
226 #endif // OHOS_BUILD_ENABLE_FINGERSENSE_WRAPPER
227 pointerEvent_->UpdatePointerItem(seatSlot, item);
228 pointerEvent_->SetPointerId(seatSlot);
229 pointerEvent_->ClearFlag(InputEvent::EVENT_FLAG_ACCESSIBILITY);
230 return true;
231 }
232
DumpInner()233 bool TouchTransformProcessor::DumpInner()
234 {
235 static int32_t lastDeviceId = -1;
236 static std::string lastDeviceName("default");
237 auto nowId = pointerEvent_->GetDeviceId();
238 if (lastDeviceId != nowId) {
239 auto device = INPUT_DEV_MGR->GetInputDevice(nowId);
240 CHKPF(device);
241 lastDeviceId = nowId;
242 lastDeviceName = device->GetName();
243 }
244 WIN_MGR->UpdateTargetPointer(pointerEvent_);
245 if (pointerEvent_->GetPointerAction() != PointerEvent::POINTER_ACTION_MOVE &&
246 pointerEvent_->GetPointerAction() != PointerEvent::POINTER_ACTION_SWIPE_UPDATE) {
247 aggregator_.Record(MMI_LOG_FREEZE, lastDeviceName + ", TW: " +
248 std::to_string(pointerEvent_->GetTargetWindowId()), std::to_string(pointerEvent_->GetId()));
249 }
250 return true;
251 }
252
OnEvent(struct libinput_event * event)253 std::shared_ptr<PointerEvent> TouchTransformProcessor::OnEvent(struct libinput_event *event)
254 {
255 CALL_DEBUG_ENTER;
256 CHKPP(event);
257 if (pointerEvent_ == nullptr) {
258 pointerEvent_ = PointerEvent::Create();
259 CHKPP(pointerEvent_);
260 }
261 auto type = libinput_event_get_type(event);
262 uint64_t sensorTime = libinput_event_get_sensortime(event);
263 pointerEvent_->SetSensorInputTime(sensorTime);
264 switch (type) {
265 case LIBINPUT_EVENT_TOUCH_DOWN: {
266 CHKFR(OnEventTouchDown(event), nullptr, "Get OnEventTouchDown failed");
267 break;
268 }
269 case LIBINPUT_EVENT_TOUCH_UP: {
270 CHKFR(OnEventTouchUp(event), nullptr, "Get OnEventTouchUp failed");
271 break;
272 }
273 case LIBINPUT_EVENT_TOUCH_MOTION: {
274 CHKFR(OnEventTouchMotion(event), nullptr, "Get OnEventTouchMotion failed");
275 break;
276 }
277 default: {
278 MMI_HILOGE("Unknown event type, touchType:%{public}d", type);
279 return nullptr;
280 }
281 }
282 pointerEvent_->SetSourceType(PointerEvent::SOURCE_TYPE_TOUCHSCREEN);
283 pointerEvent_->UpdateId();
284 pointerEvent_->AddFlag(InputEvent::EVENT_FLAG_GENERATE_FROM_REAL);
285 StartLogTraceId(pointerEvent_->GetId(), pointerEvent_->GetEventType(), pointerEvent_->GetPointerAction());
286 if (!DumpInner()) {
287 return nullptr;
288 }
289 EventLogHelper::PrintEventData(pointerEvent_, pointerEvent_->GetPointerAction(),
290 pointerEvent_->GetPointerIds().size(), MMI_LOG_FREEZE);
291 WIN_MGR->DrawTouchGraphic(pointerEvent_);
292 return pointerEvent_;
293 }
294
GetTouchToolType(struct libinput_event_touch * data,struct libinput_device * device)295 int32_t TouchTransformProcessor::GetTouchToolType(struct libinput_event_touch *data,
296 struct libinput_device *device)
297 {
298 int32_t toolType = libinput_event_touch_get_tool_type(data);
299 switch (toolType) {
300 case MT_TOOL_NONE: {
301 return GetTouchToolType(device);
302 }
303 case MT_TOOL_FINGER: {
304 return PointerEvent::TOOL_TYPE_FINGER;
305 }
306 case MT_TOOL_PEN: {
307 return PointerEvent::TOOL_TYPE_PEN;
308 }
309 default : {
310 MMI_HILOGW("Unknown tool type, identified as finger, toolType:%{public}d", toolType);
311 return PointerEvent::TOOL_TYPE_FINGER;
312 }
313 }
314 }
315
GetTouchToolType(struct libinput_device * device)316 int32_t TouchTransformProcessor::GetTouchToolType(struct libinput_device *device)
317 {
318 for (const auto &item : vecToolType_) {
319 if (libinput_device_touch_btn_tool_type_down(device, item.first) == BTN_DOWN) {
320 return item.second;
321 }
322 }
323 MMI_HILOGD("Unknown Btn tool type, identified as finger");
324 return PointerEvent::TOOL_TYPE_FINGER;
325 }
326
InitToolTypes()327 void TouchTransformProcessor::InitToolTypes()
328 {
329 vecToolType_.emplace_back(std::make_pair(BTN_TOOL_PEN, PointerEvent::TOOL_TYPE_PEN));
330 vecToolType_.emplace_back(std::make_pair(BTN_TOOL_RUBBER, PointerEvent::TOOL_TYPE_RUBBER));
331 vecToolType_.emplace_back(std::make_pair(BTN_TOOL_BRUSH, PointerEvent::TOOL_TYPE_BRUSH));
332 vecToolType_.emplace_back(std::make_pair(BTN_TOOL_PENCIL, PointerEvent::TOOL_TYPE_PENCIL));
333 vecToolType_.emplace_back(std::make_pair(BTN_TOOL_AIRBRUSH, PointerEvent::TOOL_TYPE_AIRBRUSH));
334 vecToolType_.emplace_back(std::make_pair(BTN_TOOL_FINGER, PointerEvent::TOOL_TYPE_FINGER));
335 vecToolType_.emplace_back(std::make_pair(BTN_TOOL_MOUSE, PointerEvent::TOOL_TYPE_MOUSE));
336 vecToolType_.emplace_back(std::make_pair(BTN_TOOL_LENS, PointerEvent::TOOL_TYPE_LENS));
337 }
338 } // namespace MMI
339 } // namespace OHOS
340