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