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 int32_t blobId = libinput_event_touch_get_blob_id(touch);
72 item.SetBlobId(blobId);
73 double pressure = libinput_event_touch_get_pressure(touch);
74 int32_t seatSlot = libinput_event_touch_get_seat_slot(touch);
75 // we clean up pointerItem's cancel mark at down stage to ensure newer event
76 // always starts with a clean and inital state
77 if (pointerItemCancelMarks_.find(seatSlot) != pointerItemCancelMarks_.end()) {
78 pointerItemCancelMarks_.erase(seatSlot);
79 }
80 int32_t longAxis = libinput_event_get_touch_contact_long_axis(touch);
81 int32_t shortAxis = libinput_event_get_touch_contact_short_axis(touch);
82 item.SetPressure(pressure);
83 item.SetLongAxis(longAxis);
84 item.SetShortAxis(shortAxis);
85 item.SetPointerId(seatSlot);
86 item.SetDownTime(time);
87 item.SetPressed(true);
88 UpdatePointerItemProperties(item, touchInfo);
89 item.SetDeviceId(deviceId_);
90 int32_t toolType = GetTouchToolType(touch, device);
91 #ifdef OHOS_BUILD_ENABLE_FINGERSENSE_WRAPPER
92 NotifyFingersenseProcess(item, toolType);
93 #endif // OHOS_BUILD_ENABLE_FINGERSENSE_WRAPPER
94 item.SetToolType(toolType);
95 pointerEvent_->SetDeviceId(deviceId_);
96 pointerEvent_->AddPointerItem(item);
97 pointerEvent_->SetPointerId(seatSlot);
98 pointerEvent_->ClearFlag(InputEvent::EVENT_FLAG_ACCESSIBILITY);
99 return true;
100 }
101
UpdatePointerItemProperties(PointerEvent::PointerItem & item,EventTouch & touchInfo)102 void TouchTransformProcessor::UpdatePointerItemProperties(PointerEvent::PointerItem &item, EventTouch &touchInfo)
103 {
104 CALL_DEBUG_ENTER;
105 item.SetDisplayX(touchInfo.point.x);
106 item.SetDisplayY(touchInfo.point.y);
107 item.SetDisplayXPos(touchInfo.point.x);
108 item.SetDisplayYPos(touchInfo.point.y);
109 item.SetRawDisplayX(touchInfo.point.x);
110 item.SetRawDisplayY(touchInfo.point.y);
111 item.SetToolDisplayX(touchInfo.toolRect.point.x);
112 item.SetToolDisplayY(touchInfo.toolRect.point.y);
113 item.SetToolWidth(touchInfo.toolRect.width);
114 item.SetToolHeight(touchInfo.toolRect.height);
115 }
116
117 #ifdef OHOS_BUILD_ENABLE_FINGERSENSE_WRAPPER
NotifyFingersenseProcess(PointerEvent::PointerItem & pointerItem,int32_t & toolType)118 void TouchTransformProcessor::NotifyFingersenseProcess(PointerEvent::PointerItem &pointerItem,
119 int32_t &toolType)__attribute__((no_sanitize("cfi")))
120 {
121 CALL_DEBUG_ENTER;
122 TransformTouchProperties(rawTouch_, pointerItem);
123 if (FINGERSENSE_WRAPPER->setCurrentToolType_) {
124 MMI_HILOGD("Fingersense start classify touch down event");
125 TouchType rawTouchTmp = rawTouch_;
126 int32_t displayX = pointerItem.GetRawDisplayX();
127 int32_t displayY = pointerItem.GetRawDisplayY();
128 #ifdef OHOS_BUILD_ENABLE_TOUCH
129 WIN_MGR->ReverseXY(displayX, displayY);
130 #endif // OHOS_BUILD_ENABLE_TOUCH
131 rawTouchTmp.x = displayX * DRIVER_NUMBER;
132 rawTouchTmp.y = displayY * DRIVER_NUMBER;
133 FINGERSENSE_WRAPPER->setCurrentToolType_(rawTouchTmp, toolType);
134 }
135 }
TransformTouchProperties(TouchType & rawTouch,PointerEvent::PointerItem & pointerItem)136 void TouchTransformProcessor::TransformTouchProperties(TouchType &rawTouch, PointerEvent::PointerItem &pointerItem)
137 {
138 CALL_DEBUG_ENTER;
139 rawTouch.id = pointerItem.GetPointerId();
140 rawTouch.pressure = pointerItem.GetPressure();
141 rawTouch.x = pointerItem.GetRawDisplayX();
142 rawTouch.y = pointerItem.GetRawDisplayY();
143 }
144 #endif // OHOS_BUILD_ENABLE_FINGERSENSE_WRAPPER
145
OnEventTouchMotion(struct libinput_event * event)146 bool TouchTransformProcessor::OnEventTouchMotion(struct libinput_event *event)
147 {
148 CALL_DEBUG_ENTER;
149 CHKPF(event);
150 auto touch = libinput_event_get_touch_event(event);
151 CHKPF(touch);
152 uint64_t time = libinput_event_touch_get_time_usec(touch);
153 pointerEvent_->SetActionTime(time);
154 pointerEvent_->SetPointerAction(PointerEvent::POINTER_ACTION_MOVE);
155 EventTouch touchInfo;
156 int32_t logicalDisplayId = pointerEvent_->GetTargetDisplayId();
157 if (!WIN_MGR->TouchPointToDisplayPoint(deviceId_, touch, touchInfo, logicalDisplayId)) {
158 MMI_HILOGE("Get TouchMotionPointToDisplayPoint failed");
159 return false;
160 }
161 PointerEvent::PointerItem item;
162 int32_t seatSlot = libinput_event_touch_get_seat_slot(touch);
163 if (!(pointerEvent_->GetPointerItem(seatSlot, item))) {
164 MMI_HILOGE("Get pointer parameter failed");
165 return false;
166 }
167 int32_t blobId = libinput_event_touch_get_blob_id(touch);
168 item.SetBlobId(blobId);
169 double pressure = libinput_event_touch_get_pressure(touch);
170 int32_t longAxis = libinput_event_get_touch_contact_long_axis(touch);
171 if (static_cast<uint32_t>(longAxis) & TOUCH_CANCEL_MASK) {
172 pointerItemCancelMarks_.emplace(seatSlot, true);
173 }
174 int32_t shortAxis = libinput_event_get_touch_contact_short_axis(touch);
175 item.SetPressure(pressure);
176 item.SetLongAxis(longAxis);
177 item.SetShortAxis(shortAxis);
178 item.SetDisplayX(touchInfo.point.x);
179 item.SetDisplayY(touchInfo.point.y);
180 item.SetDisplayXPos(touchInfo.point.x);
181 item.SetDisplayYPos(touchInfo.point.y);
182 item.SetRawDisplayX(touchInfo.point.x);
183 item.SetRawDisplayY(touchInfo.point.y);
184 item.SetToolDisplayX(touchInfo.toolRect.point.x);
185 item.SetToolDisplayY(touchInfo.toolRect.point.y);
186 item.SetToolWidth(touchInfo.toolRect.width);
187 item.SetToolHeight(touchInfo.toolRect.height);
188 pointerEvent_->UpdatePointerItem(seatSlot, item);
189 pointerEvent_->SetPointerId(seatSlot);
190 pointerEvent_->ClearFlag(InputEvent::EVENT_FLAG_ACCESSIBILITY);
191 return true;
192 }
193
OnEventTouchUp(struct libinput_event * event)194 bool TouchTransformProcessor::OnEventTouchUp(struct libinput_event *event) __attribute__((no_sanitize("cfi")))
195 {
196 CALL_DEBUG_ENTER;
197 CHKPF(event);
198 auto touch = libinput_event_get_touch_event(event);
199 CHKPF(touch);
200 uint64_t time = libinput_event_touch_get_time_usec(touch);
201 pointerEvent_->SetActionTime(time);
202 int32_t seatSlot = libinput_event_touch_get_seat_slot(touch);
203 if (pointerItemCancelMarks_.find(seatSlot) != pointerItemCancelMarks_.end()) {
204 pointerEvent_->SetPointerAction(PointerEvent::POINTER_ACTION_CANCEL);
205 pointerItemCancelMarks_.erase(seatSlot);
206 } else {
207 pointerEvent_->SetPointerAction(PointerEvent::POINTER_ACTION_UP);
208 }
209
210 PointerEvent::PointerItem item;
211 if (!(pointerEvent_->GetPointerItem(seatSlot, item))) {
212 MMI_HILOGE("Get pointer parameter failed");
213 return false;
214 }
215 item.SetPressed(false);
216 #ifdef OHOS_BUILD_ENABLE_FINGERSENSE_WRAPPER
217 TransformTouchProperties(rawTouch_, item);
218 if (FINGERSENSE_WRAPPER->notifyTouchUp_) {
219 MMI_HILOGD("Notify fingersense touch up event");
220 TouchType rawTouchTmp = rawTouch_;
221 int32_t displayX = item.GetRawDisplayX();
222 int32_t displayY = item.GetRawDisplayY();
223 #ifdef OHOS_BUILD_ENABLE_TOUCH
224 WIN_MGR->ReverseXY(displayX, displayY);
225 #endif // OHOS_BUILD_ENABLE_TOUCH
226 rawTouchTmp.x = displayX * DRIVER_NUMBER;
227 rawTouchTmp.y = displayY * DRIVER_NUMBER;
228 FINGERSENSE_WRAPPER->notifyTouchUp_(&rawTouchTmp);
229 }
230 #endif // OHOS_BUILD_ENABLE_FINGERSENSE_WRAPPER
231 pointerEvent_->UpdatePointerItem(seatSlot, item);
232 pointerEvent_->SetPointerId(seatSlot);
233 pointerEvent_->ClearFlag(InputEvent::EVENT_FLAG_ACCESSIBILITY);
234 return true;
235 }
236
DumpInner()237 bool TouchTransformProcessor::DumpInner()
238 {
239 static int32_t lastDeviceId = -1;
240 static std::string lastDeviceName("default");
241 auto nowId = pointerEvent_->GetDeviceId();
242 if (lastDeviceId != nowId) {
243 auto device = INPUT_DEV_MGR->GetInputDevice(nowId);
244 CHKPF(device);
245 lastDeviceId = nowId;
246 lastDeviceName = device->GetName();
247 }
248 WIN_MGR->UpdateTargetPointer(pointerEvent_);
249 if (pointerEvent_->GetPointerAction() != PointerEvent::POINTER_ACTION_MOVE &&
250 pointerEvent_->GetPointerAction() != PointerEvent::POINTER_ACTION_SWIPE_UPDATE) {
251 aggregator_.Record(MMI_LOG_FREEZE, lastDeviceName + ", TW: " +
252 std::to_string(pointerEvent_->GetTargetWindowId()), std::to_string(pointerEvent_->GetId()));
253 }
254 return true;
255 }
256
OnEvent(struct libinput_event * event)257 std::shared_ptr<PointerEvent> TouchTransformProcessor::OnEvent(struct libinput_event *event)
258 {
259 CALL_DEBUG_ENTER;
260 CHKPP(event);
261 if (pointerEvent_ == nullptr) {
262 pointerEvent_ = PointerEvent::Create();
263 CHKPP(pointerEvent_);
264 }
265 auto type = libinput_event_get_type(event);
266 uint64_t sensorTime = libinput_event_get_sensortime(event);
267 pointerEvent_->SetSensorInputTime(sensorTime);
268 switch (type) {
269 case LIBINPUT_EVENT_TOUCH_DOWN: {
270 CHKFR(OnEventTouchDown(event), nullptr, "Get OnEventTouchDown failed");
271 break;
272 }
273 case LIBINPUT_EVENT_TOUCH_UP: {
274 CHKFR(OnEventTouchUp(event), nullptr, "Get OnEventTouchUp failed");
275 break;
276 }
277 case LIBINPUT_EVENT_TOUCH_MOTION: {
278 CHKFR(OnEventTouchMotion(event), nullptr, "Get OnEventTouchMotion failed");
279 break;
280 }
281 default: {
282 MMI_HILOGE("Unknown event type, touchType:%{public}d", type);
283 return nullptr;
284 }
285 }
286 pointerEvent_->SetSourceType(PointerEvent::SOURCE_TYPE_TOUCHSCREEN);
287 pointerEvent_->UpdateId();
288 pointerEvent_->AddFlag(InputEvent::EVENT_FLAG_GENERATE_FROM_REAL);
289 StartLogTraceId(pointerEvent_->GetId(), pointerEvent_->GetEventType(), pointerEvent_->GetPointerAction());
290 if (!DumpInner()) {
291 return nullptr;
292 }
293 EventLogHelper::PrintEventData(pointerEvent_, pointerEvent_->GetPointerAction(),
294 pointerEvent_->GetPointerIds().size(), MMI_LOG_FREEZE);
295 WIN_MGR->DrawTouchGraphic(pointerEvent_);
296 return pointerEvent_;
297 }
298
GetTouchToolType(struct libinput_event_touch * data,struct libinput_device * device)299 int32_t TouchTransformProcessor::GetTouchToolType(struct libinput_event_touch *data,
300 struct libinput_device *device)
301 {
302 int32_t toolType = libinput_event_touch_get_tool_type(data);
303 switch (toolType) {
304 case MT_TOOL_NONE: {
305 return GetTouchToolType(device);
306 }
307 case MT_TOOL_FINGER: {
308 return PointerEvent::TOOL_TYPE_FINGER;
309 }
310 case MT_TOOL_PEN: {
311 return PointerEvent::TOOL_TYPE_PEN;
312 }
313 default : {
314 MMI_HILOGW("Unknown tool type, identified as finger, toolType:%{public}d", toolType);
315 return PointerEvent::TOOL_TYPE_FINGER;
316 }
317 }
318 }
319
GetTouchToolType(struct libinput_device * device)320 int32_t TouchTransformProcessor::GetTouchToolType(struct libinput_device *device)
321 {
322 for (const auto &item : vecToolType_) {
323 if (libinput_device_touch_btn_tool_type_down(device, item.first) == BTN_DOWN) {
324 return item.second;
325 }
326 }
327 MMI_HILOGD("Unknown Btn tool type, identified as finger");
328 return PointerEvent::TOOL_TYPE_FINGER;
329 }
330
InitToolTypes()331 void TouchTransformProcessor::InitToolTypes()
332 {
333 vecToolType_.emplace_back(std::make_pair(BTN_TOOL_PEN, PointerEvent::TOOL_TYPE_PEN));
334 vecToolType_.emplace_back(std::make_pair(BTN_TOOL_RUBBER, PointerEvent::TOOL_TYPE_RUBBER));
335 vecToolType_.emplace_back(std::make_pair(BTN_TOOL_BRUSH, PointerEvent::TOOL_TYPE_BRUSH));
336 vecToolType_.emplace_back(std::make_pair(BTN_TOOL_PENCIL, PointerEvent::TOOL_TYPE_PENCIL));
337 vecToolType_.emplace_back(std::make_pair(BTN_TOOL_AIRBRUSH, PointerEvent::TOOL_TYPE_AIRBRUSH));
338 vecToolType_.emplace_back(std::make_pair(BTN_TOOL_FINGER, PointerEvent::TOOL_TYPE_FINGER));
339 vecToolType_.emplace_back(std::make_pair(BTN_TOOL_MOUSE, PointerEvent::TOOL_TYPE_MOUSE));
340 vecToolType_.emplace_back(std::make_pair(BTN_TOOL_LENS, PointerEvent::TOOL_TYPE_LENS));
341 }
342 } // namespace MMI
343 } // namespace OHOS
344