• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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_touch_exploration.h"
17 #include "accessibility_window_manager.h"
18 #include "accessibility_event_info.h"
19 #include "hilog_wrapper.h"
20 #include "securec.h"
21 #include "utils.h"
22 
23 namespace OHOS {
24 namespace Accessibility {
25 
InitOneFingerGestureFuncMap()26 void TouchExploration::InitOneFingerGestureFuncMap()
27 {
28     handleEventFuncMap_ = {
29         {TouchExplorationState::TOUCH_INIT, {
30             {MMI::PointerEvent::POINTER_ACTION_DOWN, BIND(HandleInitStateDown)},
31             {MMI::PointerEvent::POINTER_ACTION_UP, BIND(HandleInitStateUp)},
32             {MMI::PointerEvent::POINTER_ACTION_MOVE, BIND(HandleInitStateMove)},
33             {MMI::PointerEvent::POINTER_ACTION_CANCEL, BIND(HandleCancelEvent)},
34             {MMI::PointerEvent::POINTER_ACTION_PULL_MOVE, BIND(HandleInitStateMove)},
35             {MMI::PointerEvent::POINTER_ACTION_PULL_UP, BIND(HandleInitStateUp)}}
36         },
37         {TouchExplorationState::ONE_FINGER_DOWN, {
38             {MMI::PointerEvent::POINTER_ACTION_DOWN, BIND(HandleOneFingerDownStateDown)},
39             {MMI::PointerEvent::POINTER_ACTION_UP, BIND(HandleOneFingerDownStateUp)},
40             {MMI::PointerEvent::POINTER_ACTION_MOVE, BIND(HandleOneFingerDownStateMove)},
41             {MMI::PointerEvent::POINTER_ACTION_CANCEL, BIND(HandleCancelEvent)}}
42         },
43         {TouchExplorationState::ONE_FINGER_LONG_PRESS, {
44             {MMI::PointerEvent::POINTER_ACTION_DOWN, BIND(HandleOneFingerLongPressStateDown)},
45             {MMI::PointerEvent::POINTER_ACTION_UP, BIND(HandleOneFingerLongPressStateUp)},
46             {MMI::PointerEvent::POINTER_ACTION_MOVE, BIND(HandleOneFingerLongPressStateMove)},
47             {MMI::PointerEvent::POINTER_ACTION_CANCEL, BIND(HandleCancelEvent)}}
48         },
49         {TouchExplorationState::ONE_FINGER_SWIPE, {
50             {MMI::PointerEvent::POINTER_ACTION_DOWN, BIND(HandleOneFingerSwipeStateDown)},
51             {MMI::PointerEvent::POINTER_ACTION_UP, BIND(HandleOneFingerSwipeStateUp)},
52             {MMI::PointerEvent::POINTER_ACTION_MOVE, BIND(HandleOneFingerSwipeStateMove)},
53             {MMI::PointerEvent::POINTER_ACTION_CANCEL, BIND(HandleCancelEvent)}}
54         },
55         {TouchExplorationState::ONE_FINGER_SINGLE_TAP, {
56             {MMI::PointerEvent::POINTER_ACTION_DOWN, BIND(HandleOneFingerSingleTapStateDown)},
57             {MMI::PointerEvent::POINTER_ACTION_CANCEL, BIND(HandleCancelEvent)}}
58         },
59         {TouchExplorationState::ONE_FINGER_SINGLE_TAP_THEN_DOWN, {
60             {MMI::PointerEvent::POINTER_ACTION_DOWN, BIND(HandleOneFingerSingleTapThenDownStateDown)},
61             {MMI::PointerEvent::POINTER_ACTION_UP, BIND(HandleOneFingerSingleTapThenDownStateUp)},
62             {MMI::PointerEvent::POINTER_ACTION_MOVE, BIND(HandleOneFingerSingleTapThenDownStateMove)},
63             {MMI::PointerEvent::POINTER_ACTION_CANCEL, BIND(HandleCancelEvent)}}
64         }
65     };
66 }
67 
TouchExplorationEventHandler(const std::shared_ptr<AppExecFwk::EventRunner> & runner,TouchExploration & server)68 TouchExplorationEventHandler::TouchExplorationEventHandler(
69     const std::shared_ptr<AppExecFwk::EventRunner> &runner, TouchExploration &server): AppExecFwk::EventHandler(runner),
70     server_(server)
71 {
72 }
73 
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)74 void TouchExplorationEventHandler::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
75 {
76     HILOG_INFO("TEhandler process event id = %{public}d, currentState is %{public}d", event->GetInnerEventId(),
77         server_.GetCurrentState());
78 
79     TouchExplorationMsg msg = static_cast<TouchExplorationMsg>(event->GetInnerEventId());
80     switch (msg) {
81         case TouchExplorationMsg::SEND_HOVER_MSG:
82             server_.HoverEventRunner();
83             server_.Clear();
84             server_.SetCurrentState(TouchExplorationState::TOUCH_INIT);
85             break;
86         case TouchExplorationMsg::LONG_PRESS_MSG:
87             server_.CancelPostEvent(TouchExplorationMsg::SEND_HOVER_MSG);
88             server_.HoverEventRunner();
89             server_.SetCurrentState(TouchExplorationState::ONE_FINGER_LONG_PRESS);
90             break;
91         case TouchExplorationMsg::DOUBLE_TAP_AND_LONG_PRESS_MSG:
92             if (!(server_.SendDoubleTapAndLongPressDownEvent())) {
93                 server_.SetCurrentState(TouchExplorationState::INVALID);
94                 return;
95             }
96             server_.SetCurrentState(TouchExplorationState::ONE_FINGER_DOUBLE_TAP_AND_LONG_PRESS);
97             break;
98         case TouchExplorationMsg::SWIPE_COMPLETE_TIMEOUT_MSG:
99             server_.HoverEventRunner();
100             server_.SetCurrentState(TouchExplorationState::ONE_FINGER_LONG_PRESS);
101             break;
102         case TouchExplorationMsg::WAIT_ANOTHER_FINGER_DOWN_MSG:
103             if (server_.GetCurrentState() == TouchExplorationState::TWO_FINGERS_TAP ||
104                 server_.GetCurrentState() == TouchExplorationState::THREE_FINGERS_TAP ||
105                 server_.GetCurrentState() == TouchExplorationState::FOUR_FINGERS_TAP) {
106                 server_.Clear();
107                 server_.SetCurrentState(TouchExplorationState::INVALID);
108             }
109             break;
110         default:
111             server_.ProcessMultiFingerGesture(msg);
112             break;
113     }
114 }
115 
TouchExploration()116 TouchExploration::TouchExploration()
117 {
118     InitOneFingerGestureFuncMap();
119     InitTwoFingerGestureFuncMap();
120     InitThreeFingerGestureFuncMap();
121     InitFourFingerGestureFuncMap();
122 
123 #ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER
124     AccessibilityDisplayManager &displayMgr = Singleton<AccessibilityDisplayManager>::GetInstance();
125     auto display = displayMgr.GetDefaultDisplay();
126     if (display == nullptr) {
127         HILOG_ERROR("get display is nullptr");
128         return;
129     }
130     moveThreshold_ = CalculateMoveThreshold(display->GetDpi());
131     xMinPixels_ = display->GetWidth() * PIXEL_MULTIPLIER;
132     yMinPixels_ = display->GetHeight() * PIXEL_MULTIPLIER;
133     float density = display->GetVirtualPixelRatio();
134     multiTapOffsetThresh_ = static_cast<int32_t>(density * MULTI_TAP_SLOP + MULTI_TAP_SLOP_DELTA);
135     mMinPixelsBetweenSamplesX_ = display->GetWidth() * PIXEL_MULTIPLIER;
136     mMinPixelsBetweenSamplesY_ = display->GetHeight() * PIXEL_MULTIPLIER;
137 #else
138     HILOG_WARN("not support display manager");
139     moveThreshold_ = 1;
140     xMinPixels_ = 1;
141     yMinPixels_ = 1;
142     multiTapOffsetThresh_ = static_cast<int32_t>(1 * MULTI_TAP_SLOP + MULTI_TAP_SLOP_DELTA);
143     mMinPixelsBetweenSamplesX_ = 1;
144     mMinPixelsBetweenSamplesY_ = 1;
145 #endif
146 }
147 
StartUp()148 void TouchExploration::StartUp()
149 {
150     runner_ = Singleton<AccessibleAbilityManagerService>::GetInstance().GetInputManagerRunner();
151     if (!runner_) {
152         HILOG_ERROR("get runner failed");
153         return;
154     }
155 
156     handler_ = std::make_shared<TouchExplorationEventHandler>(runner_, *this);
157     if (!handler_) {
158         HILOG_ERROR("create event handler failed");
159         return;
160     }
161 
162     gestureHandler_ = std::make_shared<AppExecFwk::EventHandler>(
163         Singleton<AccessibleAbilityManagerService>::GetInstance().GetGestureRunner());
164 }
165 
OnPointerEvent(MMI::PointerEvent & event)166 bool TouchExploration::OnPointerEvent(MMI::PointerEvent &event)
167 {
168     HILOG_DEBUG("PointerAction:%{public}d, PointerId:%{public}d, currentState:%{public}d.", event.GetPointerAction(),
169         event.GetPointerId(), static_cast<int32_t>(GetCurrentState()));
170     if (event.GetSourceType() != MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN) {
171         EventTransmission::OnPointerEvent(event);
172         return false;
173     }
174 
175     MMI::PointerEvent::PointerItem pointerIterm;
176     std::vector<int32_t> pIds = event.GetPointerIds();
177     for (auto& pId : pIds) {
178         if (!event.GetPointerItem(pId, pointerIterm)) {
179             HILOG_ERROR("get pointerItem(%{public}d) failed", pId);
180             return false;
181         }
182         if (pointerIterm.GetToolType() == MMI::PointerEvent::TOOL_TYPE_PEN) {
183             EventTransmission::OnPointerEvent(event);
184             return false;
185         }
186     }
187 
188     // Send touch event to AA to control volume adjustment.
189     SendTouchEventToAA(event);
190 
191     HandlePointerEvent(event);
192     return true;
193 }
194 
HandlePointerEvent(MMI::PointerEvent & event)195 void TouchExploration::HandlePointerEvent(MMI::PointerEvent &event)
196 {
197     HILOG_DEBUG();
198     if (GetCurrentState() == TouchExplorationState::PASSING_THROUGH) {
199         HandlePassingThroughState(event);
200         return;
201     }
202     if (GetCurrentState() == TouchExplorationState::INVALID) {
203         HandleInvalidState(event);
204         return;
205     }
206     if (GetCurrentState() == TouchExplorationState::ONE_FINGER_DOUBLE_TAP_AND_LONG_PRESS) {
207         HandleOneFingerDoubleTapAndLongPressState(event);
208         return;
209     }
210 
211     auto iter = handleEventFuncMap_.find(GetCurrentState());
212     if (iter != handleEventFuncMap_.end()) {
213         auto funcMap = iter->second.find(event.GetPointerAction());
214         if (funcMap != iter->second.end()) {
215             funcMap->second(event);
216             return;
217         }
218     }
219 
220     MMI::PointerEvent::PointerItem pointerIterm;
221     event.GetPointerItem(event.GetPointerId(), pointerIterm);
222     // If the event is not processed, GetCurrentState() is set to TOUCH_INIT when the last finger is lifted.
223     if (event.GetPointerIds().size() == static_cast<uint32_t>(PointerCount::POINTER_COUNT_1) ||
224         !pointerIterm.IsPressed()) {
225         Clear();
226         SetCurrentState(TouchExplorationState::TOUCH_INIT);
227     }
228 }
229 
SendAccessibilityEventToAA(EventType eventType)230 void TouchExploration::SendAccessibilityEventToAA(EventType eventType)
231 {
232     HILOG_INFO("eventType is 0x%{public}x.", eventType);
233 
234     AccessibilityEventInfo eventInfo {};
235     eventInfo.SetEventType(eventType);
236     int32_t windowsId = Singleton<AccessibilityWindowManager>::GetInstance().GetActiveWindowId();
237     eventInfo.SetWindowId(windowsId);
238     AccessibilityEventInfoParcel eventInfoParcel(eventInfo);
239     Singleton<AccessibleAbilityManagerService>::GetInstance().SendEvent(eventInfoParcel, 0);
240 }
241 
SendTouchEventToAA(MMI::PointerEvent & event)242 void TouchExploration::SendTouchEventToAA(MMI::PointerEvent &event)
243 {
244     if (event.GetPointerIds().size() != static_cast<uint32_t>(PointerCount::POINTER_COUNT_1) ||
245         event.GetPointerId() >= SIMULATE_POINTER_ID) {
246         return;
247     }
248 
249     MMI::PointerEvent::PointerItem pointerIterm {};
250     event.GetPointerItem(event.GetPointerId(), pointerIterm);
251     if (event.GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_DOWN) {
252         SendAccessibilityEventToAA(EventType::TYPE_TOUCH_BEGIN);
253     } else if (!pointerIterm.IsPressed()) {
254         SendAccessibilityEventToAA(EventType::TYPE_TOUCH_END);
255     }
256 }
257 
SendGestureEventToAA(GestureType gestureId)258 void TouchExploration::SendGestureEventToAA(GestureType gestureId)
259 {
260     HILOG_INFO("gestureId is %{public}d.", static_cast<int32_t>(gestureId));
261 
262     AccessibilityEventInfo eventInfo {};
263     int32_t windowsId = Singleton<AccessibilityWindowManager>::GetInstance().GetActiveWindowId();
264     eventInfo.SetWindowId(windowsId);
265     eventInfo.SetEventType(EventType::TYPE_GESTURE_EVENT);
266     eventInfo.SetGestureType(gestureId);
267     AccessibilityEventInfoParcel eventInfoParcel(eventInfo);
268     Singleton<AccessibleAbilityManagerService>::GetInstance().SendEvent(eventInfoParcel, 0);
269 }
270 
SendEventToMultimodal(MMI::PointerEvent event,ChangeAction action)271 void TouchExploration::SendEventToMultimodal(MMI::PointerEvent event, ChangeAction action)
272 {
273     HILOG_DEBUG("action:%{public}d, SourceType:%{public}d.", action, event.GetSourceType());
274 
275     switch (action) {
276         case ChangeAction::HOVER_MOVE:
277             event.SetPointerAction(MMI::PointerEvent::POINTER_ACTION_HOVER_MOVE);
278             break;
279         case ChangeAction::POINTER_DOWN:
280             event.SetPointerAction(MMI::PointerEvent::POINTER_ACTION_DOWN);
281             break;
282         case ChangeAction::POINTER_UP:
283             event.SetPointerAction(MMI::PointerEvent::POINTER_ACTION_UP);
284             break;
285         case ChangeAction::HOVER_ENTER:
286             event.SetPointerAction(MMI::PointerEvent::POINTER_ACTION_HOVER_ENTER);
287             break;
288         case ChangeAction::HOVER_EXIT:
289             event.SetPointerAction(MMI::PointerEvent::POINTER_ACTION_HOVER_EXIT);
290             break;
291         case ChangeAction::HOVER_CANCEL:
292             event.SetPointerAction(MMI::PointerEvent::POINTER_ACTION_HOVER_CANCEL);
293             break;
294         default:
295             break;
296     }
297     EventTransmission::OnPointerEvent(event);
298 }
299 
SendScreenWakeUpEvent(MMI::PointerEvent & event)300 void TouchExploration::SendScreenWakeUpEvent(MMI::PointerEvent &event)
301 {
302     HILOG_DEBUG();
303     // Send move event to wake up the screen and prevent the screen from turning off.
304     MMI::PointerEvent::PointerItem pointerItem {};
305     for (auto& pId : event.GetPointerIds()) {
306         event.GetPointerItem(pId, pointerItem);
307         pointerItem.SetPressed(false);
308         event.RemovePointerItem(pId);
309         event.AddPointerItem(pointerItem);
310     }
311     SendEventToMultimodal(event, ChangeAction::NO_CHANGE);
312 }
313 
HoverEventRunner()314 void TouchExploration::HoverEventRunner()
315 {
316     for (auto& event : receivedPointerEvents_) {
317         if (event.GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_DOWN) {
318             SendEventToMultimodal(event, ChangeAction::HOVER_ENTER);
319         } else if (event.GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_MOVE) {
320             SendEventToMultimodal(event, ChangeAction::HOVER_MOVE);
321         } else if (event.GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_UP) {
322             SendEventToMultimodal(event, ChangeAction::HOVER_EXIT);
323         }
324     }
325 }
326 
HandleInitStateDown(MMI::PointerEvent & event)327 void TouchExploration::HandleInitStateDown(MMI::PointerEvent &event)
328 {
329     if (event.GetPointerIds().size() == static_cast<uint32_t>(PointerCount::POINTER_COUNT_1)) {
330         receivedPointerEvents_.push_back(event);
331         SetCurrentState(TouchExplorationState::ONE_FINGER_DOWN);
332         handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::SEND_HOVER_MSG), 0,
333             static_cast<int32_t>(TimeoutDuration::DOUBLE_TAP_TIMEOUT));
334         handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::LONG_PRESS_MSG), 0,
335             static_cast<int32_t>(TimeoutDuration::LONG_PRESS_TIMEOUT));
336         handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::WAIT_ANOTHER_FINGER_DOWN_MSG), 0,
337             static_cast<int32_t>(TimeoutDuration::MULTI_FINGER_TAP_INTERVAL_TIMEOUT));
338         return;
339     }
340 
341     SendEventToMultimodal(event, ChangeAction::NO_CHANGE);
342     SetCurrentState(TouchExplorationState::PASSING_THROUGH);
343 }
344 
HandleInitStateUp(MMI::PointerEvent & event)345 void TouchExploration::HandleInitStateUp(MMI::PointerEvent &event)
346 {
347     SendEventToMultimodal(event, ChangeAction::NO_CHANGE);
348 
349     if (event.GetPointerIds().size() != static_cast<uint32_t>(PointerCount::POINTER_COUNT_1)) {
350         SetCurrentState(TouchExplorationState::PASSING_THROUGH);
351     }
352 }
353 
HandleInitStateMove(MMI::PointerEvent & event)354 void TouchExploration::HandleInitStateMove(MMI::PointerEvent &event)
355 {
356     SendEventToMultimodal(event, ChangeAction::NO_CHANGE);
357     SetCurrentState(TouchExplorationState::PASSING_THROUGH);
358 }
359 
HandlePassingThroughState(MMI::PointerEvent & event)360 void TouchExploration::HandlePassingThroughState(MMI::PointerEvent &event)
361 {
362     SendEventToMultimodal(event, ChangeAction::NO_CHANGE);
363 
364     MMI::PointerEvent::PointerItem pointerIterm {};
365     event.GetPointerItem(event.GetPointerId(), pointerIterm);
366 
367     // the last finger is lifted
368     if ((event.GetPointerIds().size() == static_cast<uint32_t>(PointerCount::POINTER_COUNT_1)) &&
369         (!pointerIterm.IsPressed())) {
370         SetCurrentState(TouchExplorationState::TOUCH_INIT);
371     }
372 }
373 
HandleInvalidState(MMI::PointerEvent & event)374 void TouchExploration::HandleInvalidState(MMI::PointerEvent &event)
375 {
376     MMI::PointerEvent::PointerItem pointerIterm {};
377     event.GetPointerItem(event.GetPointerId(), pointerIterm);
378 
379     if (event.GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_MOVE) {
380         SendScreenWakeUpEvent(event);
381     }
382 
383     // the last finger is lifted
384     if ((event.GetPointerIds().size() == static_cast<uint32_t>(PointerCount::POINTER_COUNT_1)) &&
385         (!pointerIterm.IsPressed())) {
386         SetCurrentState(TouchExplorationState::TOUCH_INIT);
387     }
388 }
389 
HandleCancelEvent(MMI::PointerEvent & event)390 void TouchExploration::HandleCancelEvent(MMI::PointerEvent &event)
391 {
392     if (GetCurrentState() == TouchExplorationState::TWO_FINGERS_DRAG && event.GetPointerId() == draggingPid_) {
393         SendEventToMultimodal(event, ChangeAction::NO_CHANGE);
394     }
395     SendEventToMultimodal(event, ChangeAction::HOVER_CANCEL);
396 
397     MMI::PointerEvent::PointerItem pointerIterm {};
398     event.GetPointerItem(event.GetPointerId(), pointerIterm);
399 
400     // the last finger is lifted
401     if ((event.GetPointerIds().size() == static_cast<uint32_t>(PointerCount::POINTER_COUNT_1)) &&
402         (!pointerIterm.IsPressed())) {
403         Clear();
404         SetCurrentState(TouchExplorationState::TOUCH_INIT);
405     }
406 }
407 
HandleOneFingerDownStateDown(MMI::PointerEvent & event)408 void TouchExploration::HandleOneFingerDownStateDown(MMI::PointerEvent &event)
409 {
410     receivedPointerEvents_.push_back(event);
411     CancelPostEvent(TouchExplorationMsg::SEND_HOVER_MSG);
412     CancelPostEvent(TouchExplorationMsg::LONG_PRESS_MSG);
413     draggingPid_ = event.GetPointerId();
414     if (!handler_->HasInnerEvent(static_cast<uint32_t>(TouchExplorationMsg::WAIT_ANOTHER_FINGER_DOWN_MSG))) {
415         SetCurrentState(TouchExplorationState::TWO_FINGERS_UNKNOWN);
416         return;
417     }
418 
419     CancelPostEvent(TouchExplorationMsg::WAIT_ANOTHER_FINGER_DOWN_MSG);
420     handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::WAIT_ANOTHER_FINGER_DOWN_MSG), 0,
421         static_cast<int32_t>(TimeoutDuration::MULTI_FINGER_TAP_INTERVAL_TIMEOUT));
422     handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::TWO_FINGER_SINGLE_TAP_MSG), 0,
423         static_cast<int32_t>(TimeoutDuration::DOUBLE_TAP_TIMEOUT));
424     handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::TWO_FINGER_LONG_PRESS_MSG), 0,
425         static_cast<int32_t>(TimeoutDuration::DOUBLE_TAP_TIMEOUT));
426     SetCurrentState(TouchExplorationState::TWO_FINGERS_DOWN);
427 }
428 
HandleOneFingerDownStateUp(MMI::PointerEvent & event)429 void TouchExploration::HandleOneFingerDownStateUp(MMI::PointerEvent &event)
430 {
431     CancelPostEvent(TouchExplorationMsg::LONG_PRESS_MSG);
432     CancelPostEvent(TouchExplorationMsg::WAIT_ANOTHER_FINGER_DOWN_MSG);
433     receivedPointerEvents_.push_back(event);
434     SetCurrentState(TouchExplorationState::ONE_FINGER_SINGLE_TAP);
435 }
436 
HandleOneFingerDownStateMove(MMI::PointerEvent & event)437 void TouchExploration::HandleOneFingerDownStateMove(MMI::PointerEvent &event)
438 {
439     receivedPointerEvents_.push_back(event);
440 
441     MMI::PointerEvent::PointerItem pointerIterm;
442     event.GetPointerItem(event.GetPointerId(), pointerIterm);
443 
444     MMI::PointerEvent startPointerEvent = receivedPointerEvents_.front();
445     MMI::PointerEvent::PointerItem startPointerIterm;
446     startPointerEvent.GetPointerItem(startPointerEvent.GetPointerId(), startPointerIterm);
447 
448     float offsetX = startPointerIterm.GetDisplayX() - pointerIterm.GetDisplayX();
449     float offsetY = startPointerIterm.GetDisplayY() - pointerIterm.GetDisplayY();
450     double duration = hypot(offsetX, offsetY);
451     if (duration > moveThreshold_) {
452         CancelPostEvent(TouchExplorationMsg::SEND_HOVER_MSG);
453         CancelPostEvent(TouchExplorationMsg::WAIT_ANOTHER_FINGER_DOWN_MSG);
454         CancelPostEvent(TouchExplorationMsg::LONG_PRESS_MSG);
455         receivedPointerEvents_.clear();
456         receivedPointerEvents_.push_back(event);
457         oneFingerSwipePrePointer_ = startPointerIterm;
458         Pointer mp;
459         mp.px_ = static_cast<float>(startPointerIterm.GetDisplayX());
460         mp.py_ = static_cast<float>(startPointerIterm.GetDisplayY());
461         oneFingerSwipeRoute_.clear();
462         oneFingerSwipeRoute_.push_back(mp);
463         handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::SWIPE_COMPLETE_TIMEOUT_MSG), 0,
464             static_cast<int32_t>(TimeoutDuration::SWIPE_COMPLETE_TIMEOUT));
465         SetCurrentState(TouchExplorationState::ONE_FINGER_SWIPE);
466         SendScreenWakeUpEvent(event);
467     }
468 }
469 
HandleOneFingerLongPressStateDown(MMI::PointerEvent & event)470 void TouchExploration::HandleOneFingerLongPressStateDown(MMI::PointerEvent &event)
471 {
472     receivedPointerEvents_.push_back(event);
473     draggingPid_ = event.GetPointerId();
474     SetCurrentState(TouchExplorationState::TWO_FINGERS_UNKNOWN);
475 }
476 
HandleOneFingerLongPressStateUp(MMI::PointerEvent & event)477 void TouchExploration::HandleOneFingerLongPressStateUp(MMI::PointerEvent &event)
478 {
479     Clear();
480     SendEventToMultimodal(event, ChangeAction::HOVER_EXIT);
481     SetCurrentState(TouchExplorationState::TOUCH_INIT);
482 }
483 
HandleOneFingerLongPressStateMove(MMI::PointerEvent & event)484 void TouchExploration::HandleOneFingerLongPressStateMove(MMI::PointerEvent &event)
485 {
486     SendEventToMultimodal(event, ChangeAction::HOVER_MOVE);
487 }
488 
HandleOneFingerSwipeStateDown(MMI::PointerEvent & event)489 void TouchExploration::HandleOneFingerSwipeStateDown(MMI::PointerEvent &event)
490 {
491     Clear();
492     CancelPostEvent(TouchExplorationMsg::SWIPE_COMPLETE_TIMEOUT_MSG);
493     SetCurrentState(TouchExplorationState::INVALID);
494 }
495 
AddOneFingerSwipeEvent(MMI::PointerEvent & event)496 void TouchExploration::AddOneFingerSwipeEvent(MMI::PointerEvent &event)
497 {
498     HILOG_DEBUG();
499     MMI::PointerEvent::PointerItem pointerIterm {};
500     event.GetPointerItem(event.GetPointerId(), pointerIterm);
501 
502     if (receivedPointerEvents_.empty()) {
503         HILOG_ERROR("received pointer event is null!");
504         return;
505     }
506 
507     MMI::PointerEvent preMoveEvent = receivedPointerEvents_.back();
508     MMI::PointerEvent::PointerItem preMovePointerIterm {};
509     preMoveEvent.GetPointerItem(preMoveEvent.GetPointerId(), preMovePointerIterm);
510     float offsetX = preMovePointerIterm.GetDisplayX() - pointerIterm.GetDisplayX();
511     float offsetY = preMovePointerIterm.GetDisplayY() - pointerIterm.GetDisplayY();
512     double duration = hypot(offsetX, offsetY);
513     if (duration > moveThreshold_) {
514         receivedPointerEvents_.push_back(event);
515         CancelPostEvent(TouchExplorationMsg::SWIPE_COMPLETE_TIMEOUT_MSG);
516         handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::SWIPE_COMPLETE_TIMEOUT_MSG), 0,
517             static_cast<int32_t>(TimeoutDuration::SWIPE_COMPLETE_TIMEOUT));
518     }
519 
520     if ((abs(pointerIterm.GetDisplayX() - oneFingerSwipePrePointer_.GetDisplayX())) >= xMinPixels_ ||
521         (abs(pointerIterm.GetDisplayY() - oneFingerSwipePrePointer_.GetDisplayY())) >= yMinPixels_) {
522         Pointer mp;
523         oneFingerSwipePrePointer_ = pointerIterm;
524         mp.px_ = pointerIterm.GetDisplayX();
525         mp.py_ = pointerIterm.GetDisplayY();
526         oneFingerSwipeRoute_.push_back(mp);
527     }
528 }
529 
GetOneFingerSwipePath()530 std::vector<Pointer> TouchExploration::GetOneFingerSwipePath()
531 {
532     HILOG_DEBUG();
533     std::vector<Pointer> pointerPath;
534     Pointer firstSeparation = oneFingerSwipeRoute_[0];
535     Pointer nextPoint;
536     Pointer newSeparation;
537     float xUnitVector = 0;
538     float yUnitVector = 0;
539     float xVector = 0;
540     float yVector = 0;
541     float vectorLength = 0;
542     int32_t numSinceFirstSep = 0;
543 
544     pointerPath.push_back(firstSeparation);
545     for (size_t i = 1; i < oneFingerSwipeRoute_.size(); i++) {
546         nextPoint = oneFingerSwipeRoute_[i];
547         if (numSinceFirstSep > 0) {
548             xVector = xUnitVector / numSinceFirstSep;
549             yVector = yUnitVector / numSinceFirstSep;
550             newSeparation.px_ = vectorLength * xVector + firstSeparation.px_;
551             newSeparation.py_ = vectorLength * yVector + firstSeparation.py_;
552 
553             float xNextUnitVector = nextPoint.px_ - newSeparation.px_;
554             float yNextUnitVector = nextPoint.py_ - newSeparation.py_;
555             float nextVectorLength = hypot(xNextUnitVector, yNextUnitVector);
556             if (nextVectorLength > EPSINON) {
557                 xNextUnitVector /= nextVectorLength;
558                 yNextUnitVector /= nextVectorLength;
559             }
560 
561             if ((xVector * xNextUnitVector + yVector * yNextUnitVector) < DEGREES_THRESHOLD) {
562                 pointerPath.push_back(newSeparation);
563                 firstSeparation = newSeparation;
564                 xUnitVector = 0;
565                 yUnitVector = 0;
566                 numSinceFirstSep = 0;
567             }
568         }
569         xVector = nextPoint.px_ - firstSeparation.px_;
570         yVector = nextPoint.py_ - firstSeparation.py_;
571         vectorLength = hypot(xVector, yVector);
572         numSinceFirstSep += 1;
573         if (vectorLength > EPSINON) {
574             xUnitVector += xVector / vectorLength;
575             yUnitVector += yVector / vectorLength;
576         }
577     }
578     pointerPath.push_back(nextPoint);
579     return pointerPath;
580 }
581 
GetSwipeDirection(const int32_t dx,const int32_t dy)582 int32_t TouchExploration::GetSwipeDirection(const int32_t dx, const int32_t dy)
583 {
584     if (abs(dx) > abs(dy)) {
585         return dx > EPSINON ? SWIPE_RIGHT : SWIPE_LEFT;
586     } else {
587         return dy < EPSINON ? SWIPE_UP : SWIPE_DOWN;
588     }
589 }
590 
HandleOneFingerSwipeStateUp(MMI::PointerEvent & event)591 void TouchExploration::HandleOneFingerSwipeStateUp(MMI::PointerEvent &event)
592 {
593     AddOneFingerSwipeEvent(event);
594     CancelPostEvent(TouchExplorationMsg::SWIPE_COMPLETE_TIMEOUT_MSG);
595 
596     if (oneFingerSwipeRoute_.size() < LIMIT_SIZE_TWO) {
597         Clear();
598         SetCurrentState(TouchExplorationState::TOUCH_INIT);
599         return;
600     }
601 
602     std::vector<Pointer> pointerPath = GetOneFingerSwipePath();
603     if (pointerPath.size() == LIMIT_SIZE_TWO) {
604         int32_t swipeDirection = GetSwipeDirection(pointerPath[1].px_ - pointerPath[0].px_,
605             pointerPath[1].py_ - pointerPath[0].py_);
606         SendGestureEventToAA(GESTURE_DIRECTION[swipeDirection]);
607     } else if (pointerPath.size() == LIMIT_SIZE_THREE) {
608         int32_t swipeDirectionH = GetSwipeDirection(pointerPath[1].px_ - pointerPath[0].px_,
609             pointerPath[1].py_ - pointerPath[0].py_);
610         int32_t swipeDirectionHV = GetSwipeDirection(pointerPath[2].px_ - pointerPath[1].px_,
611             pointerPath[2].py_ - pointerPath[1].py_);
612         SendGestureEventToAA(GESTURE_DIRECTION_TO_ID[swipeDirectionH][swipeDirectionHV]);
613     }
614 
615     Clear();
616     SetCurrentState(TouchExplorationState::TOUCH_INIT);
617 }
618 
HandleOneFingerSwipeStateMove(MMI::PointerEvent & event)619 void TouchExploration::HandleOneFingerSwipeStateMove(MMI::PointerEvent &event)
620 {
621     AddOneFingerSwipeEvent(event);
622     SendScreenWakeUpEvent(event);
623 }
624 
RecordFocusedLocation(MMI::PointerEvent & event)625 bool TouchExploration::RecordFocusedLocation(MMI::PointerEvent &event)
626 {
627     HILOG_DEBUG();
628     AccessibilityElementInfo focusedElementInfo {};
629     bool ret = Singleton<AccessibleAbilityManagerService>::GetInstance().FindFocusedElement(focusedElementInfo,
630         FIND_FOCUS_TIMEOUT);
631     if (!ret) {
632         HILOG_ERROR("find focused element failed.");
633         return false;
634     }
635 
636     MMI::PointerEvent::PointerItem pointer {};
637     event.GetPointerItem(event.GetPointerId(), pointer);
638 
639     focusedWindowId_ = focusedElementInfo.GetWindowId();
640 
641     offsetX_ = (focusedElementInfo.GetRectInScreen().GetLeftTopXScreenPostion() +
642         focusedElementInfo.GetRectInScreen().GetRightBottomXScreenPostion()) / DIVIDE_NUM - pointer.GetDisplayX();
643     offsetY_ = (focusedElementInfo.GetRectInScreen().GetLeftTopYScreenPostion() +
644         focusedElementInfo.GetRectInScreen().GetRightBottomYScreenPostion()) / DIVIDE_NUM - pointer.GetDisplayY();
645     return true;
646 }
647 
HandleOneFingerSingleTapStateDown(MMI::PointerEvent & event)648 void TouchExploration::HandleOneFingerSingleTapStateDown(MMI::PointerEvent &event)
649 {
650     CancelPostEvent(TouchExplorationMsg::SEND_HOVER_MSG);
651     if (receivedPointerEvents_.empty()) {
652         Clear();
653         SetCurrentState(TouchExplorationState::INVALID);
654         return;
655     }
656 
657     MMI::PointerEvent::PointerItem curPointerItem;
658     event.GetPointerItem(event.GetPointerId(), curPointerItem);
659     MMI::PointerEvent preDownEvent = receivedPointerEvents_.front();
660     MMI::PointerEvent::PointerItem preDownPointerItem;
661     preDownEvent.GetPointerItem(preDownEvent.GetPointerId(), preDownPointerItem);
662     int32_t durationX = preDownPointerItem.GetDisplayX() - curPointerItem.GetDisplayX();
663     int32_t durationY = preDownPointerItem.GetDisplayY() - curPointerItem.GetDisplayY();
664     if (durationX * durationX + durationY * durationY > multiTapOffsetThresh_ * multiTapOffsetThresh_) {
665         HoverEventRunner();
666         Clear();
667         receivedPointerEvents_.push_back(event);
668         SetCurrentState(TouchExplorationState::ONE_FINGER_DOWN);
669         handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::SEND_HOVER_MSG), 0,
670             static_cast<int32_t>(TimeoutDuration::DOUBLE_TAP_TIMEOUT));
671         handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::LONG_PRESS_MSG), 0,
672             static_cast<int32_t>(TimeoutDuration::LONG_PRESS_TIMEOUT));
673         handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::WAIT_ANOTHER_FINGER_DOWN_MSG), 0,
674             static_cast<int32_t>(TimeoutDuration::MULTI_FINGER_TAP_INTERVAL_TIMEOUT));
675         return;
676     }
677 
678     Clear();
679     receivedPointerEvents_.push_back(event);
680     handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::DOUBLE_TAP_AND_LONG_PRESS_MSG), 0,
681         static_cast<int32_t>(TimeoutDuration::LONG_PRESS_TIMEOUT));
682     SetCurrentState(TouchExplorationState::ONE_FINGER_SINGLE_TAP_THEN_DOWN);
683 }
684 
HandleOneFingerSingleTapThenDownStateDown(MMI::PointerEvent & event)685 void TouchExploration::HandleOneFingerSingleTapThenDownStateDown(MMI::PointerEvent &event)
686 {
687     Clear();
688     CancelPostEvent(TouchExplorationMsg::DOUBLE_TAP_AND_LONG_PRESS_MSG);
689     SetCurrentState(TouchExplorationState::INVALID);
690 }
691 
HandleOneFingerSingleTapThenDownStateUp(MMI::PointerEvent & event)692 void TouchExploration::HandleOneFingerSingleTapThenDownStateUp(MMI::PointerEvent &event)
693 {
694     CancelPostEvent(TouchExplorationMsg::DOUBLE_TAP_AND_LONG_PRESS_MSG);
695     Clear();
696     SetCurrentState(TouchExplorationState::TOUCH_INIT);
697 
698     if (!gestureHandler_) {
699         HILOG_ERROR("gestureHandler is nullptr!");
700         return;
701     }
702 
703     gestureHandler_->PostTask([this]() {
704         Singleton<AccessibleAbilityManagerService>::GetInstance().ExecuteActionOnAccessibilityFocused(
705             ActionType::ACCESSIBILITY_ACTION_CLICK);
706         }, "TASK_CLICK_ON_FOCUS");
707 }
708 
HandleOneFingerSingleTapThenDownStateMove(MMI::PointerEvent & event)709 void TouchExploration::HandleOneFingerSingleTapThenDownStateMove(MMI::PointerEvent &event)
710 {
711     MMI::PointerEvent::PointerItem pointerIterm;
712     event.GetPointerItem(event.GetPointerId(), pointerIterm);
713 
714     MMI::PointerEvent startPointerEvent = receivedPointerEvents_.front();
715     MMI::PointerEvent::PointerItem startPointerIterm;
716     startPointerEvent.GetPointerItem(startPointerEvent.GetPointerId(), startPointerIterm);
717 
718     float offsetX = startPointerIterm.GetDisplayX() - pointerIterm.GetDisplayX();
719     float offsetY = startPointerIterm.GetDisplayY() - pointerIterm.GetDisplayY();
720     double duration = hypot(offsetX, offsetY);
721     if (duration > moveThreshold_) {
722         CancelPostEvent(TouchExplorationMsg::DOUBLE_TAP_AND_LONG_PRESS_MSG);
723         Clear();
724         SetCurrentState(TouchExplorationState::INVALID);
725     }
726 }
727 
OffsetEvent(MMI::PointerEvent & event)728 void TouchExploration::OffsetEvent(MMI::PointerEvent &event)
729 {
730     HILOG_DEBUG();
731     if (receivedPointerEvents_.empty()) {
732         HILOG_ERROR("received pointer event is null!");
733         return;
734     }
735 
736     MMI::PointerEvent startPointerEvent = receivedPointerEvents_.front();
737     if (event.GetPointerId() != startPointerEvent.GetPointerId()) {
738         return;
739     }
740 
741     AccessibilityWindowInfo windowInfo = {};
742     if (Singleton<AccessibilityWindowManager>::GetInstance().GetAccessibilityWindow(focusedWindowId_, windowInfo)) {
743         event.SetZOrder(static_cast<float>(windowInfo.GetWindowLayer() + 1));
744     } else {
745         HILOG_ERROR("get windowInfo failed");
746     }
747 
748     MMI::PointerEvent::PointerItem pointer {};
749     event.GetPointerItem(event.GetPointerId(), pointer);
750     pointer.SetTargetWindowId(focusedWindowId_);
751     int32_t x = offsetX_ + pointer.GetDisplayX();
752     int32_t y = offsetY_ + pointer.GetDisplayY();
753 #ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER
754     AccessibilityDisplayManager &displayMgr = Singleton<AccessibilityDisplayManager>::GetInstance();
755     int32_t displayWidth = displayMgr.GetWidth();
756     int32_t displayHeight = displayMgr.GetHeight();
757     x = x < 0 ? 0 : (x >= displayWidth ? displayWidth - 1 : x);
758     y = y < 0 ? 0 : (y >= displayHeight ? displayHeight - 1 : y);
759 #endif
760     pointer.SetDisplayX(x);
761     pointer.SetDisplayY(y);
762     event.RemovePointerItem(event.GetPointerId());
763     event.AddPointerItem(pointer);
764 }
765 
SendDoubleTapAndLongPressDownEvent()766 bool TouchExploration::SendDoubleTapAndLongPressDownEvent()
767 {
768     if (receivedPointerEvents_.empty()) {
769         HILOG_ERROR("receivedPointerEvents_ is empty!");
770         return false;
771     }
772     if (!RecordFocusedLocation(receivedPointerEvents_.front())) {
773         return false;
774     }
775     OffsetEvent(receivedPointerEvents_.front());
776     SendEventToMultimodal(receivedPointerEvents_.front(), ChangeAction::NO_CHANGE);
777     return true;
778 }
779 
HandleOneFingerDoubleTapAndLongPressState(MMI::PointerEvent & event)780 void TouchExploration::HandleOneFingerDoubleTapAndLongPressState(MMI::PointerEvent &event)
781 {
782     OffsetEvent(event);
783     SendEventToMultimodal(event, ChangeAction::NO_CHANGE);
784 
785     MMI::PointerEvent::PointerItem pointer {};
786     event.GetPointerItem(event.GetPointerId(), pointer);
787     if ((event.GetPointerIds().size() == static_cast<uint32_t>(PointerCount::POINTER_COUNT_1)) &&
788         (!pointer.IsPressed())) {
789         Clear();
790         SetCurrentState(TouchExplorationState::TOUCH_INIT);
791     }
792 }
793 
Clear()794 void TouchExploration::Clear()
795 {
796     receivedPointerEvents_.clear();
797     draggingDownEvent_ = nullptr;
798     offsetX_ = 0;
799     offsetY_ = 0;
800     oneFingerSwipeRoute_.clear();
801     oneFingerSwipePrePointer_ = {};
802     draggingPid_ = -1;
803     multiTapNum_ = 0;
804     multiFingerSwipeDirection_ = -1;
805     multiFingerSwipeRoute_.clear();
806     multiFingerSwipePrePoint_.clear();
807 }
808 
DestroyEvents()809 void TouchExploration::DestroyEvents()
810 {
811     HILOG_INFO();
812     Clear();
813     handler_->RemoveAllEvents();
814     SetCurrentState(TouchExplorationState::TOUCH_INIT);
815     EventTransmission::DestroyEvents();
816 }
817 } // namespace Accessibility
818 } // namespace OHOS