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