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