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