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