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