• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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