• 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 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