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