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
OnEvent(struct libinput_event * event)233 std::shared_ptr<PointerEvent> TouchTransformProcessor::OnEvent(struct libinput_event *event)
234 {
235 CALL_DEBUG_ENTER;
236 CHKPP(event);
237 if (pointerEvent_ == nullptr) {
238 pointerEvent_ = PointerEvent::Create();
239 CHKPP(pointerEvent_);
240 }
241 auto type = libinput_event_get_type(event);
242 uint64_t sensorTime = libinput_event_get_sensortime(event);
243 pointerEvent_->SetSensorInputTime(sensorTime);
244 switch (type) {
245 case LIBINPUT_EVENT_TOUCH_DOWN: {
246 CHKFR(OnEventTouchDown(event), nullptr, "Get OnEventTouchDown failed");
247 break;
248 }
249 case LIBINPUT_EVENT_TOUCH_UP: {
250 CHKFR(OnEventTouchUp(event), nullptr, "Get OnEventTouchUp failed");
251 break;
252 }
253 case LIBINPUT_EVENT_TOUCH_MOTION: {
254 CHKFR(OnEventTouchMotion(event), nullptr, "Get OnEventTouchMotion failed");
255 break;
256 }
257 default: {
258 MMI_HILOGE("Unknown event type, touchType:%{public}d", type);
259 return nullptr;
260 }
261 }
262 pointerEvent_->SetSourceType(PointerEvent::SOURCE_TYPE_TOUCHSCREEN);
263 pointerEvent_->UpdateId();
264 pointerEvent_->AddFlag(InputEvent::EVENT_FLAG_GENERATE_FROM_REAL);
265 StartLogTraceId(pointerEvent_->GetId(), pointerEvent_->GetEventType(), pointerEvent_->GetPointerAction());
266 auto device = INPUT_DEV_MGR->GetInputDevice(pointerEvent_->GetDeviceId());
267 CHKPP(device);
268 WIN_MGR->UpdateTargetPointer(pointerEvent_);
269 if (pointerEvent_->GetPointerAction() != PointerEvent::POINTER_ACTION_MOVE &&
270 pointerEvent_->GetPointerAction() != PointerEvent::POINTER_ACTION_SWIPE_UPDATE) {
271 aggregator_.Record(MMI_LOG_FREEZE, device->GetName() + ", TW: " +
272 std::to_string(pointerEvent_->GetTargetWindowId()), std::to_string(pointerEvent_->GetId()));
273 }
274 EventLogHelper::PrintEventData(pointerEvent_, pointerEvent_->GetPointerAction(),
275 pointerEvent_->GetPointerIds().size(), MMI_LOG_FREEZE);
276 WIN_MGR->DrawTouchGraphic(pointerEvent_);
277 return pointerEvent_;
278 }
279
GetTouchToolType(struct libinput_event_touch * data,struct libinput_device * device)280 int32_t TouchTransformProcessor::GetTouchToolType(struct libinput_event_touch *data,
281 struct libinput_device *device)
282 {
283 int32_t toolType = libinput_event_touch_get_tool_type(data);
284 switch (toolType) {
285 case MT_TOOL_NONE: {
286 return GetTouchToolType(device);
287 }
288 case MT_TOOL_FINGER: {
289 return PointerEvent::TOOL_TYPE_FINGER;
290 }
291 case MT_TOOL_PEN: {
292 return PointerEvent::TOOL_TYPE_PEN;
293 }
294 default : {
295 MMI_HILOGW("Unknown tool type, identified as finger, toolType:%{public}d", toolType);
296 return PointerEvent::TOOL_TYPE_FINGER;
297 }
298 }
299 }
300
GetTouchToolType(struct libinput_device * device)301 int32_t TouchTransformProcessor::GetTouchToolType(struct libinput_device *device)
302 {
303 for (const auto &item : vecToolType_) {
304 if (libinput_device_touch_btn_tool_type_down(device, item.first) == BTN_DOWN) {
305 return item.second;
306 }
307 }
308 MMI_HILOGD("Unknown Btn tool type, identified as finger");
309 return PointerEvent::TOOL_TYPE_FINGER;
310 }
311
InitToolTypes()312 void TouchTransformProcessor::InitToolTypes()
313 {
314 vecToolType_.emplace_back(std::make_pair(BTN_TOOL_PEN, PointerEvent::TOOL_TYPE_PEN));
315 vecToolType_.emplace_back(std::make_pair(BTN_TOOL_RUBBER, PointerEvent::TOOL_TYPE_RUBBER));
316 vecToolType_.emplace_back(std::make_pair(BTN_TOOL_BRUSH, PointerEvent::TOOL_TYPE_BRUSH));
317 vecToolType_.emplace_back(std::make_pair(BTN_TOOL_PENCIL, PointerEvent::TOOL_TYPE_PENCIL));
318 vecToolType_.emplace_back(std::make_pair(BTN_TOOL_AIRBRUSH, PointerEvent::TOOL_TYPE_AIRBRUSH));
319 vecToolType_.emplace_back(std::make_pair(BTN_TOOL_FINGER, PointerEvent::TOOL_TYPE_FINGER));
320 vecToolType_.emplace_back(std::make_pair(BTN_TOOL_MOUSE, PointerEvent::TOOL_TYPE_MOUSE));
321 vecToolType_.emplace_back(std::make_pair(BTN_TOOL_LENS, PointerEvent::TOOL_TYPE_LENS));
322 }
323 } // namespace MMI
324 } // namespace OHOS
325