1 /*
2  * Copyright (C) 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 "accessibility_touchEvent_injector.h"
17 #include "accessible_ability_manager_service.h"
18 #include "hilog_wrapper.h"
19 #include "utils.h"
20 
21 namespace OHOS {
22 namespace Accessibility {
23 namespace {
24     constexpr int32_t MS_TO_US = 1000;
25     constexpr int32_t MOVE_GESTURE_MIN_PATH_COUNT = 2;
26 } // namespace
27 
TouchInjectHandler(const std::shared_ptr<AppExecFwk::EventRunner> & runner,TouchEventInjector & server)28 TouchInjectHandler::TouchInjectHandler(const std::shared_ptr<AppExecFwk::EventRunner> &runner,
29     TouchEventInjector &server) : AppExecFwk::EventHandler(runner), server_(server)
30 {
31 }
32 
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)33 void TouchInjectHandler::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
34 {
35     std::shared_ptr<SendEventArgs> parameters = nullptr;
36     if (!event) {
37         HILOG_ERROR("event is nullptr");
38         return;
39     }
40     switch (event->GetInnerEventId()) {
41         case TouchEventInjector::SEND_TOUCH_EVENT_MSG:
42             parameters = event->GetSharedObject<SendEventArgs>();
43             if (parameters == nullptr) {
44                 HILOG_ERROR("parameters is nullptr");
45                 return;
46             }
47             if (!parameters->event_) {
48                 HILOG_WARN("pointer event is nullptr");
49                 return;
50             }
51             server_.SendPointerEvent(*parameters->event_);
52             break;
53         default:
54             break;
55     }
56 }
57 
TouchEventInjector()58 TouchEventInjector::TouchEventInjector()
59 {
60     runner_ = Singleton<AccessibleAbilityManagerService>::GetInstance().GetMainRunner();
61     if (!runner_) {
62         HILOG_ERROR("get runner failed");
63         return;
64     }
65     handler_ = std::make_shared<TouchInjectHandler>(runner_, *this);
66     if (!handler_) {
67         HILOG_ERROR("create event handler failed");
68         return;
69     }
70 }
71 
OnPointerEvent(MMI::PointerEvent & event)72 bool TouchEventInjector::OnPointerEvent(MMI::PointerEvent &event)
73 {
74     HILOG_DEBUG();
75 
76     EventTransmission::OnPointerEvent(event);
77     return false;
78 }
79 
DestroyEvents()80 void TouchEventInjector::DestroyEvents()
81 {
82     HILOG_DEBUG();
83     CancelInjectedEvents();
84     isDestroyEvent_ = true;
85     EventTransmission::DestroyEvents();
86 }
87 
SendPointerEvent(MMI::PointerEvent & event)88 void TouchEventInjector::SendPointerEvent(MMI::PointerEvent &event)
89 {
90     HILOG_DEBUG();
91     if (GetNext() != nullptr) {
92         EventTransmission::OnPointerEvent(event);
93         if (event.GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_DOWN) {
94             isGestureUnderway_ = true;
95         }
96         if (event.GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_UP) {
97             isGestureUnderway_ = false;
98         }
99     }
100 }
101 
CancelGesture()102 void TouchEventInjector::CancelGesture()
103 {
104     HILOG_DEBUG();
105     std::shared_ptr<MMI::PointerEvent> event;
106     MMI::PointerEvent::PointerItem pointer = {};
107     int64_t time = GetSystemTime();
108     pointer.SetDownTime(time);
109     pointer.SetPointerId(0);
110     if (GetNext() != nullptr && isGestureUnderway_) {
111         event = obtainTouchEvent(MMI::PointerEvent::POINTER_ACTION_CANCEL, pointer, time);
112         if (event == nullptr) {
113             HILOG_ERROR("event is nullptr");
114             return;
115         }
116 
117         SendPointerEvent(*event);
118         isGestureUnderway_ = false;
119     }
120 }
121 
CancelInjectedEvents()122 void TouchEventInjector::CancelInjectedEvents()
123 {
124     HILOG_DEBUG();
125     if (handler_ == nullptr) {
126         HILOG_ERROR("handler_ is nullptr");
127         return;
128     }
129     if (handler_->HasInnerEvent(SEND_TOUCH_EVENT_MSG)) {
130         handler_->RemoveEvent(SEND_TOUCH_EVENT_MSG);
131         CancelGesture();
132     }
133 }
134 
obtainTouchEvent(int32_t action,MMI::PointerEvent::PointerItem point,int64_t actionTime)135 std::shared_ptr<MMI::PointerEvent> TouchEventInjector::obtainTouchEvent(int32_t action,
136     MMI::PointerEvent::PointerItem point, int64_t actionTime)
137 {
138     HILOG_DEBUG();
139     std::shared_ptr<MMI::PointerEvent> pointerEvent = MMI::PointerEvent::Create();
140     if (pointerEvent == nullptr) {
141         HILOG_ERROR("pointerEvent is nullptr");
142         return nullptr;
143     }
144 
145     pointerEvent->SetPointerId(point.GetPointerId());
146     pointerEvent->SetTargetDisplayId(0);
147     pointerEvent->SetPointerAction(action);
148     pointerEvent->SetActionTime(actionTime);
149     pointerEvent->SetActionStartTime(point.GetDownTime());
150     pointerEvent->AddPointerItem(point);
151     pointerEvent->SetSourceType(MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN);
152     return pointerEvent;
153 }
154 
GetSystemTime()155 int64_t TouchEventInjector::GetSystemTime()
156 {
157     HILOG_DEBUG();
158 
159     int64_t microsecond = Utils::GetSystemTime() * 1000;
160     return microsecond;
161 }
162 
InjectEvents(const std::shared_ptr<AccessibilityGestureInjectPath> & gesturePath)163 void TouchEventInjector::InjectEvents(const std::shared_ptr<AccessibilityGestureInjectPath>& gesturePath)
164 {
165     HILOG_DEBUG();
166 
167     int64_t curTime = GetSystemTime();
168     if (isDestroyEvent_ || !GetNext()) {
169         HILOG_WARN("Inject gesture fail");
170         return;
171     }
172     CancelInjectedEvents();
173     CancelGesture();
174 
175     ParseTouchEventsFromGesturePath(curTime, gesturePath);
176 
177     if (injectedEvents_.empty()) {
178         HILOG_WARN("No injected events");
179         return;
180     }
181     for (size_t i = 0; i < injectedEvents_.size(); i++) {
182         std::shared_ptr<SendEventArgs> parameters = std::make_shared<SendEventArgs>();
183         parameters->event_ = injectedEvents_[i];
184         if (injectedEvents_[i]) {
185             int64_t timeout = (injectedEvents_[i]->GetActionTime() - curTime) / MS_TO_US;
186             if (timeout < 0) {
187                 HILOG_WARN("timeout is error.%{public}" PRId64 "", timeout);
188             } else {
189                 handler_->SendEvent(SEND_TOUCH_EVENT_MSG, parameters, timeout);
190             }
191         }
192     }
193     injectedEvents_.clear();
194 }
195 
ParseTapsEvents(int64_t startTime,const std::shared_ptr<AccessibilityGestureInjectPath> & gesturePath)196 void TouchEventInjector::ParseTapsEvents(int64_t startTime,
197     const std::shared_ptr<AccessibilityGestureInjectPath>& gesturePath)
198 {
199     HILOG_DEBUG();
200 
201     if (!gesturePath) {
202         HILOG_ERROR("gesturePath is null.");
203         return;
204     }
205     const std::vector<AccessibilityGesturePosition> &positions = gesturePath->GetPositions();
206     size_t positionSize = positions.size();
207     if (!positionSize) {
208         HILOG_WARN("PositionSize is zero.");
209         return;
210     }
211     int64_t durationTime = gesturePath->GetDurationTime();
212     if (durationTime < 0) {
213         HILOG_WARN("DurationTime is wrong.");
214         return;
215     }
216     int64_t perDurationTime = static_cast<int64_t>(static_cast<uint64_t>(durationTime) / positionSize);
217     int64_t downTime = startTime;
218     for (size_t i = 0; i < positionSize; i++) {
219         std::shared_ptr<MMI::PointerEvent> event;
220         MMI::PointerEvent::PointerItem pointer = {};
221         pointer.SetPointerId(0);
222         // Append down event
223         int32_t px = static_cast<int32_t>(positions[i].positionX_);
224         int32_t py = static_cast<int32_t>(positions[i].positionY_);
225         pointer.SetDisplayX(px);
226         pointer.SetDisplayY(py);
227         pointer.SetDownTime(downTime);
228         event = obtainTouchEvent(MMI::PointerEvent::POINTER_ACTION_DOWN, pointer, downTime);
229         if (event == nullptr) {
230             HILOG_ERROR("event is nullptr");
231             return;
232         }
233 
234         HILOG_DEBUG("append down event");
235         injectedEvents_.push_back(event);
236 
237         // Append up event
238         int64_t upTime = downTime + perDurationTime * MS_TO_US;
239         event = obtainTouchEvent(MMI::PointerEvent::POINTER_ACTION_UP, pointer, upTime);
240         if (event == nullptr) {
241             HILOG_ERROR("event is nullptr");
242             return;
243         }
244 
245         HILOG_DEBUG("append up event");
246         injectedEvents_.push_back(event);
247         downTime = upTime + DOUBLE_TAP_MIN_TIME;
248     }
249 }
250 
ParseMovesEvents(int64_t startTime,const std::shared_ptr<AccessibilityGestureInjectPath> & gesturePath)251 void TouchEventInjector::ParseMovesEvents(int64_t startTime,
252     const std::shared_ptr<AccessibilityGestureInjectPath>& gesturePath)
253 {
254     HILOG_DEBUG();
255 
256     if (!gesturePath) {
257         HILOG_ERROR("gesturePath is null.");
258         return;
259     }
260     std::vector<AccessibilityGesturePosition> positions = gesturePath->GetPositions();
261     size_t positionSize = positions.size();
262     if (positionSize < MOVE_GESTURE_MIN_PATH_COUNT) {
263         HILOG_WARN("PositionSize is wrong.");
264         return;
265     }
266     int64_t durationTime = gesturePath->GetDurationTime();
267     if (durationTime < 0) {
268         HILOG_WARN("DurationTime is wrong.");
269         return;
270     }
271     int64_t perDurationTime = static_cast<int64_t>(static_cast<uint64_t>(durationTime) / (positionSize - 1));
272     int64_t downTime = startTime;
273     int64_t nowTime = startTime;
274     for (size_t i = 0; i < positionSize; i++) {
275         std::shared_ptr<MMI::PointerEvent> event;
276         MMI::PointerEvent::PointerItem pointer = {};
277         int32_t px = static_cast<int32_t>(positions[i].positionX_);
278         int32_t py = static_cast<int32_t>(positions[i].positionY_);
279         pointer.SetPointerId(0);
280         pointer.SetDisplayX(px);
281         pointer.SetDisplayY(py);
282         pointer.SetDownTime(downTime);
283         if (i == 0) { // Append down event
284             HILOG_DEBUG("append down event");
285             event = obtainTouchEvent(MMI::PointerEvent::POINTER_ACTION_DOWN, pointer, downTime);
286             if (event == nullptr) {
287                 HILOG_ERROR("event is nullptr");
288                 return;
289             }
290 
291             injectedEvents_.push_back(event);
292         } else if (i < (positionSize - 1)) { // Append move event
293             HILOG_DEBUG("append move event");
294             nowTime += perDurationTime * MS_TO_US;
295             event = obtainTouchEvent(MMI::PointerEvent::POINTER_ACTION_MOVE, pointer, nowTime);
296             if (event == nullptr) {
297                 HILOG_ERROR("event is nullptr");
298                 return;
299             }
300 
301             injectedEvents_.push_back(event);
302         } else { // Append up event
303             HILOG_DEBUG("append move event");
304             nowTime += perDurationTime * MS_TO_US;
305             event = obtainTouchEvent(MMI::PointerEvent::POINTER_ACTION_MOVE, pointer, nowTime);
306             if (event == nullptr) {
307                 HILOG_ERROR("event is nullptr");
308                 return;
309             }
310 
311             injectedEvents_.push_back(event);
312 
313             HILOG_DEBUG("append up event");
314             event = obtainTouchEvent(MMI::PointerEvent::POINTER_ACTION_UP, pointer, nowTime);
315             if (event == nullptr) {
316                 HILOG_ERROR("event is nullptr");
317                 return;
318             }
319 
320             injectedEvents_.push_back(event);
321         }
322     }
323 }
324 
ParseTouchEventsFromGesturePath(int64_t startTime,const std::shared_ptr<AccessibilityGestureInjectPath> & gesturePath)325 void TouchEventInjector::ParseTouchEventsFromGesturePath(int64_t startTime,
326     const std::shared_ptr<AccessibilityGestureInjectPath>& gesturePath)
327 {
328     HILOG_DEBUG();
329     if (!gesturePath) {
330         HILOG_ERROR("gesturePath is null.");
331         return;
332     }
333     const std::vector<AccessibilityGesturePosition> &positions = gesturePath->GetPositions();
334     if (positions.size() == 0) {
335         HILOG_ERROR("position size is 0.");
336         return;
337     }
338     if ((positions.size() == 1) ||
339         ((positions[0].positionX_ == positions[1].positionX_) &&
340         (positions[0].positionY_ == positions[1].positionY_))) {
341         ParseTapsEvents(startTime, gesturePath);
342     } else {
343         ParseMovesEvents(startTime, gesturePath);
344     }
345 }
346 } // namespace Accessibility
347 } // namespace OHOS