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