1885b47fbSopenharmony_ci/* 2885b47fbSopenharmony_ci * Copyright (C) 2022 Huawei Device Co., Ltd. 3885b47fbSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4885b47fbSopenharmony_ci * you may not use this file except in compliance with the License. 5885b47fbSopenharmony_ci * You may obtain a copy of the License at 6885b47fbSopenharmony_ci * 7885b47fbSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8885b47fbSopenharmony_ci * 9885b47fbSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10885b47fbSopenharmony_ci * distributed under the License is distributed On an "AS IS" BASIS, 11885b47fbSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12885b47fbSopenharmony_ci * See the License for the specific language governing permissions and 13885b47fbSopenharmony_ci * limitations under the License. 14885b47fbSopenharmony_ci */ 15885b47fbSopenharmony_ci 16885b47fbSopenharmony_ci#include "accessibility_touchEvent_injector.h" 17885b47fbSopenharmony_ci#include "accessible_ability_manager_service.h" 18885b47fbSopenharmony_ci#include "hilog_wrapper.h" 19885b47fbSopenharmony_ci#include "utils.h" 20885b47fbSopenharmony_ci#include <cinttypes> 21885b47fbSopenharmony_ci 22885b47fbSopenharmony_cinamespace OHOS { 23885b47fbSopenharmony_cinamespace Accessibility { 24885b47fbSopenharmony_cinamespace { 25885b47fbSopenharmony_ci constexpr int32_t MS_TO_US = 1000; 26885b47fbSopenharmony_ci constexpr int32_t MOVE_GESTURE_MIN_PATH_COUNT = 2; 27885b47fbSopenharmony_ci} // namespace 28885b47fbSopenharmony_ci 29885b47fbSopenharmony_ciTouchInjectHandler::TouchInjectHandler(const std::shared_ptr<AppExecFwk::EventRunner> &runner, 30885b47fbSopenharmony_ci TouchEventInjector &server) : AppExecFwk::EventHandler(runner), server_(server) 31885b47fbSopenharmony_ci{ 32885b47fbSopenharmony_ci} 33885b47fbSopenharmony_ci 34885b47fbSopenharmony_civoid TouchInjectHandler::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event) 35885b47fbSopenharmony_ci{ 36885b47fbSopenharmony_ci std::shared_ptr<SendEventArgs> parameters = nullptr; 37885b47fbSopenharmony_ci if (!event) { 38885b47fbSopenharmony_ci HILOG_ERROR("event is nullptr"); 39885b47fbSopenharmony_ci return; 40885b47fbSopenharmony_ci } 41885b47fbSopenharmony_ci switch (event->GetInnerEventId()) { 42885b47fbSopenharmony_ci case TouchEventInjector::SEND_TOUCH_EVENT_MSG: 43885b47fbSopenharmony_ci parameters = event->GetSharedObject<SendEventArgs>(); 44885b47fbSopenharmony_ci if (parameters == nullptr) { 45885b47fbSopenharmony_ci HILOG_ERROR("parameters is nullptr"); 46885b47fbSopenharmony_ci return; 47885b47fbSopenharmony_ci } 48885b47fbSopenharmony_ci if (!parameters->event_) { 49885b47fbSopenharmony_ci HILOG_WARN("pointer event is nullptr"); 50885b47fbSopenharmony_ci return; 51885b47fbSopenharmony_ci } 52885b47fbSopenharmony_ci server_.SendPointerEvent(*parameters->event_); 53885b47fbSopenharmony_ci break; 54885b47fbSopenharmony_ci default: 55885b47fbSopenharmony_ci break; 56885b47fbSopenharmony_ci } 57885b47fbSopenharmony_ci} 58885b47fbSopenharmony_ci 59885b47fbSopenharmony_ciTouchEventInjector::TouchEventInjector() 60885b47fbSopenharmony_ci{ 61885b47fbSopenharmony_ci runner_ = Singleton<AccessibleAbilityManagerService>::GetInstance().GetMainRunner(); 62885b47fbSopenharmony_ci if (!runner_) { 63885b47fbSopenharmony_ci HILOG_ERROR("get runner failed"); 64885b47fbSopenharmony_ci return; 65885b47fbSopenharmony_ci } 66885b47fbSopenharmony_ci handler_ = std::make_shared<TouchInjectHandler>(runner_, *this); 67885b47fbSopenharmony_ci if (!handler_) { 68885b47fbSopenharmony_ci HILOG_ERROR("create event handler failed"); 69885b47fbSopenharmony_ci return; 70885b47fbSopenharmony_ci } 71885b47fbSopenharmony_ci} 72885b47fbSopenharmony_ci 73885b47fbSopenharmony_cibool TouchEventInjector::OnPointerEvent(MMI::PointerEvent &event) 74885b47fbSopenharmony_ci{ 75885b47fbSopenharmony_ci HILOG_DEBUG(); 76885b47fbSopenharmony_ci 77885b47fbSopenharmony_ci EventTransmission::OnPointerEvent(event); 78885b47fbSopenharmony_ci return false; 79885b47fbSopenharmony_ci} 80885b47fbSopenharmony_ci 81885b47fbSopenharmony_civoid TouchEventInjector::DestroyEvents() 82885b47fbSopenharmony_ci{ 83885b47fbSopenharmony_ci HILOG_DEBUG(); 84885b47fbSopenharmony_ci CancelInjectedEvents(); 85885b47fbSopenharmony_ci isDestroyEvent_ = true; 86885b47fbSopenharmony_ci EventTransmission::DestroyEvents(); 87885b47fbSopenharmony_ci} 88885b47fbSopenharmony_ci 89885b47fbSopenharmony_civoid TouchEventInjector::SendPointerEvent(MMI::PointerEvent &event) 90885b47fbSopenharmony_ci{ 91885b47fbSopenharmony_ci HILOG_DEBUG(); 92885b47fbSopenharmony_ci if (GetNext() != nullptr) { 93885b47fbSopenharmony_ci EventTransmission::OnPointerEvent(event); 94885b47fbSopenharmony_ci if (event.GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_DOWN) { 95885b47fbSopenharmony_ci isGestureUnderway_ = true; 96885b47fbSopenharmony_ci } 97885b47fbSopenharmony_ci if (event.GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_UP) { 98885b47fbSopenharmony_ci isGestureUnderway_ = false; 99885b47fbSopenharmony_ci } 100885b47fbSopenharmony_ci } 101885b47fbSopenharmony_ci} 102885b47fbSopenharmony_ci 103885b47fbSopenharmony_civoid TouchEventInjector::CancelGesture() 104885b47fbSopenharmony_ci{ 105885b47fbSopenharmony_ci HILOG_DEBUG(); 106885b47fbSopenharmony_ci std::shared_ptr<MMI::PointerEvent> event; 107885b47fbSopenharmony_ci MMI::PointerEvent::PointerItem pointer = {}; 108885b47fbSopenharmony_ci int64_t time = GetSystemTime(); 109885b47fbSopenharmony_ci pointer.SetDownTime(time); 110885b47fbSopenharmony_ci pointer.SetPointerId(0); 111885b47fbSopenharmony_ci if (GetNext() != nullptr && isGestureUnderway_) { 112885b47fbSopenharmony_ci event = obtainTouchEvent(MMI::PointerEvent::POINTER_ACTION_CANCEL, pointer, time); 113885b47fbSopenharmony_ci if (event == nullptr) { 114885b47fbSopenharmony_ci HILOG_ERROR("event is nullptr"); 115885b47fbSopenharmony_ci return; 116885b47fbSopenharmony_ci } 117885b47fbSopenharmony_ci 118885b47fbSopenharmony_ci SendPointerEvent(*event); 119885b47fbSopenharmony_ci isGestureUnderway_ = false; 120885b47fbSopenharmony_ci } 121885b47fbSopenharmony_ci} 122885b47fbSopenharmony_ci 123885b47fbSopenharmony_civoid TouchEventInjector::CancelInjectedEvents() 124885b47fbSopenharmony_ci{ 125885b47fbSopenharmony_ci HILOG_DEBUG(); 126885b47fbSopenharmony_ci if (handler_ == nullptr) { 127885b47fbSopenharmony_ci HILOG_ERROR("handler_ is nullptr"); 128885b47fbSopenharmony_ci return; 129885b47fbSopenharmony_ci } 130885b47fbSopenharmony_ci if (handler_->HasInnerEvent(SEND_TOUCH_EVENT_MSG)) { 131885b47fbSopenharmony_ci handler_->RemoveEvent(SEND_TOUCH_EVENT_MSG); 132885b47fbSopenharmony_ci CancelGesture(); 133885b47fbSopenharmony_ci } 134885b47fbSopenharmony_ci} 135885b47fbSopenharmony_ci 136885b47fbSopenharmony_cistd::shared_ptr<MMI::PointerEvent> TouchEventInjector::obtainTouchEvent(int32_t action, 137885b47fbSopenharmony_ci MMI::PointerEvent::PointerItem point, int64_t actionTime) 138885b47fbSopenharmony_ci{ 139885b47fbSopenharmony_ci HILOG_DEBUG(); 140885b47fbSopenharmony_ci std::shared_ptr<MMI::PointerEvent> pointerEvent = MMI::PointerEvent::Create(); 141885b47fbSopenharmony_ci if (pointerEvent == nullptr) { 142885b47fbSopenharmony_ci HILOG_ERROR("pointerEvent is nullptr"); 143885b47fbSopenharmony_ci return nullptr; 144885b47fbSopenharmony_ci } 145885b47fbSopenharmony_ci 146885b47fbSopenharmony_ci pointerEvent->SetPointerId(point.GetPointerId()); 147885b47fbSopenharmony_ci pointerEvent->SetTargetDisplayId(0); 148885b47fbSopenharmony_ci pointerEvent->SetPointerAction(action); 149885b47fbSopenharmony_ci pointerEvent->SetActionTime(actionTime); 150885b47fbSopenharmony_ci pointerEvent->SetActionStartTime(point.GetDownTime()); 151885b47fbSopenharmony_ci pointerEvent->AddPointerItem(point); 152885b47fbSopenharmony_ci pointerEvent->SetSourceType(MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN); 153885b47fbSopenharmony_ci return pointerEvent; 154885b47fbSopenharmony_ci} 155885b47fbSopenharmony_ci 156885b47fbSopenharmony_ciint64_t TouchEventInjector::GetSystemTime() 157885b47fbSopenharmony_ci{ 158885b47fbSopenharmony_ci HILOG_DEBUG(); 159885b47fbSopenharmony_ci 160885b47fbSopenharmony_ci int64_t microsecond = Utils::GetSystemTime() * 1000; 161885b47fbSopenharmony_ci return microsecond; 162885b47fbSopenharmony_ci} 163885b47fbSopenharmony_ci 164885b47fbSopenharmony_civoid TouchEventInjector::InjectEvents(const std::shared_ptr<AccessibilityGestureInjectPath>& gesturePath) 165885b47fbSopenharmony_ci{ 166885b47fbSopenharmony_ci HILOG_DEBUG(); 167885b47fbSopenharmony_ci 168885b47fbSopenharmony_ci int64_t curTime = GetSystemTime(); 169885b47fbSopenharmony_ci if (isDestroyEvent_ || !GetNext()) { 170885b47fbSopenharmony_ci HILOG_WARN("Inject gesture fail"); 171885b47fbSopenharmony_ci return; 172885b47fbSopenharmony_ci } 173885b47fbSopenharmony_ci CancelInjectedEvents(); 174885b47fbSopenharmony_ci CancelGesture(); 175885b47fbSopenharmony_ci 176885b47fbSopenharmony_ci ParseTouchEventsFromGesturePath(curTime, gesturePath); 177885b47fbSopenharmony_ci 178885b47fbSopenharmony_ci if (injectedEvents_.empty()) { 179885b47fbSopenharmony_ci HILOG_WARN("No injected events"); 180885b47fbSopenharmony_ci return; 181885b47fbSopenharmony_ci } 182885b47fbSopenharmony_ci for (size_t i = 0; i < injectedEvents_.size(); i++) { 183885b47fbSopenharmony_ci std::shared_ptr<SendEventArgs> parameters = std::make_shared<SendEventArgs>(); 184885b47fbSopenharmony_ci parameters->event_ = injectedEvents_[i]; 185885b47fbSopenharmony_ci if (injectedEvents_[i]) { 186885b47fbSopenharmony_ci int64_t timeout = (injectedEvents_[i]->GetActionTime() - curTime) / MS_TO_US; 187885b47fbSopenharmony_ci if (timeout < 0) { 188885b47fbSopenharmony_ci HILOG_WARN("timeout is error.%{public}" PRId64 "", timeout); 189885b47fbSopenharmony_ci } else { 190885b47fbSopenharmony_ci handler_->SendEvent(SEND_TOUCH_EVENT_MSG, parameters, timeout); 191885b47fbSopenharmony_ci } 192885b47fbSopenharmony_ci } 193885b47fbSopenharmony_ci } 194885b47fbSopenharmony_ci injectedEvents_.clear(); 195885b47fbSopenharmony_ci} 196885b47fbSopenharmony_ci 197885b47fbSopenharmony_civoid TouchEventInjector::ParseTapsEvents(int64_t startTime, 198885b47fbSopenharmony_ci const std::shared_ptr<AccessibilityGestureInjectPath>& gesturePath) 199885b47fbSopenharmony_ci{ 200885b47fbSopenharmony_ci HILOG_DEBUG(); 201885b47fbSopenharmony_ci 202885b47fbSopenharmony_ci if (!gesturePath) { 203885b47fbSopenharmony_ci HILOG_ERROR("gesturePath is null."); 204885b47fbSopenharmony_ci return; 205885b47fbSopenharmony_ci } 206885b47fbSopenharmony_ci const std::vector<AccessibilityGesturePosition> &positions = gesturePath->GetPositions(); 207885b47fbSopenharmony_ci size_t positionSize = positions.size(); 208885b47fbSopenharmony_ci if (!positionSize) { 209885b47fbSopenharmony_ci HILOG_WARN("PositionSize is zero."); 210885b47fbSopenharmony_ci return; 211885b47fbSopenharmony_ci } 212885b47fbSopenharmony_ci int64_t durationTime = gesturePath->GetDurationTime(); 213885b47fbSopenharmony_ci if (durationTime < 0) { 214885b47fbSopenharmony_ci HILOG_WARN("DurationTime is wrong."); 215885b47fbSopenharmony_ci return; 216885b47fbSopenharmony_ci } 217885b47fbSopenharmony_ci int64_t perDurationTime = static_cast<int64_t>(static_cast<uint64_t>(durationTime) / positionSize); 218885b47fbSopenharmony_ci int64_t downTime = startTime; 219885b47fbSopenharmony_ci for (size_t i = 0; i < positionSize; i++) { 220885b47fbSopenharmony_ci std::shared_ptr<MMI::PointerEvent> event; 221885b47fbSopenharmony_ci MMI::PointerEvent::PointerItem pointer = {}; 222885b47fbSopenharmony_ci pointer.SetPointerId(0); 223885b47fbSopenharmony_ci // Append down event 224885b47fbSopenharmony_ci int32_t px = static_cast<int32_t>(positions[i].positionX_); 225885b47fbSopenharmony_ci int32_t py = static_cast<int32_t>(positions[i].positionY_); 226885b47fbSopenharmony_ci pointer.SetDisplayX(px); 227885b47fbSopenharmony_ci pointer.SetDisplayY(py); 228885b47fbSopenharmony_ci pointer.SetDownTime(downTime); 229885b47fbSopenharmony_ci event = obtainTouchEvent(MMI::PointerEvent::POINTER_ACTION_DOWN, pointer, downTime); 230885b47fbSopenharmony_ci if (event == nullptr) { 231885b47fbSopenharmony_ci HILOG_ERROR("event is nullptr"); 232885b47fbSopenharmony_ci return; 233885b47fbSopenharmony_ci } 234885b47fbSopenharmony_ci 235885b47fbSopenharmony_ci HILOG_DEBUG("append down event"); 236885b47fbSopenharmony_ci injectedEvents_.push_back(event); 237885b47fbSopenharmony_ci 238885b47fbSopenharmony_ci // Append up event 239885b47fbSopenharmony_ci int64_t upTime = downTime + perDurationTime * MS_TO_US; 240885b47fbSopenharmony_ci event = obtainTouchEvent(MMI::PointerEvent::POINTER_ACTION_UP, pointer, upTime); 241885b47fbSopenharmony_ci if (event == nullptr) { 242885b47fbSopenharmony_ci HILOG_ERROR("event is nullptr"); 243885b47fbSopenharmony_ci return; 244885b47fbSopenharmony_ci } 245885b47fbSopenharmony_ci 246885b47fbSopenharmony_ci HILOG_DEBUG("append up event"); 247885b47fbSopenharmony_ci injectedEvents_.push_back(event); 248885b47fbSopenharmony_ci downTime = upTime + DOUBLE_TAP_MIN_TIME; 249885b47fbSopenharmony_ci } 250885b47fbSopenharmony_ci} 251885b47fbSopenharmony_ci 252885b47fbSopenharmony_civoid TouchEventInjector::ParseMovesEvents(int64_t startTime, 253885b47fbSopenharmony_ci const std::shared_ptr<AccessibilityGestureInjectPath>& gesturePath) 254885b47fbSopenharmony_ci{ 255885b47fbSopenharmony_ci HILOG_DEBUG(); 256885b47fbSopenharmony_ci 257885b47fbSopenharmony_ci if (!gesturePath) { 258885b47fbSopenharmony_ci HILOG_ERROR("gesturePath is null."); 259885b47fbSopenharmony_ci return; 260885b47fbSopenharmony_ci } 261885b47fbSopenharmony_ci std::vector<AccessibilityGesturePosition> positions = gesturePath->GetPositions(); 262885b47fbSopenharmony_ci size_t positionSize = positions.size(); 263885b47fbSopenharmony_ci if (positionSize < MOVE_GESTURE_MIN_PATH_COUNT) { 264885b47fbSopenharmony_ci HILOG_WARN("PositionSize is wrong."); 265885b47fbSopenharmony_ci return; 266885b47fbSopenharmony_ci } 267885b47fbSopenharmony_ci int64_t durationTime = gesturePath->GetDurationTime(); 268885b47fbSopenharmony_ci if (durationTime < 0) { 269885b47fbSopenharmony_ci HILOG_WARN("DurationTime is wrong."); 270885b47fbSopenharmony_ci return; 271885b47fbSopenharmony_ci } 272885b47fbSopenharmony_ci int64_t perDurationTime = static_cast<int64_t>(static_cast<uint64_t>(durationTime) / (positionSize - 1)); 273885b47fbSopenharmony_ci int64_t downTime = startTime; 274885b47fbSopenharmony_ci int64_t nowTime = startTime; 275885b47fbSopenharmony_ci for (size_t i = 0; i < positionSize; i++) { 276885b47fbSopenharmony_ci std::shared_ptr<MMI::PointerEvent> event; 277885b47fbSopenharmony_ci MMI::PointerEvent::PointerItem pointer = {}; 278885b47fbSopenharmony_ci int32_t px = static_cast<int32_t>(positions[i].positionX_); 279885b47fbSopenharmony_ci int32_t py = static_cast<int32_t>(positions[i].positionY_); 280885b47fbSopenharmony_ci pointer.SetPointerId(0); 281885b47fbSopenharmony_ci pointer.SetDisplayX(px); 282885b47fbSopenharmony_ci pointer.SetDisplayY(py); 283885b47fbSopenharmony_ci pointer.SetDownTime(downTime); 284885b47fbSopenharmony_ci if (i == 0) { // Append down event 285885b47fbSopenharmony_ci HILOG_DEBUG("append down event"); 286885b47fbSopenharmony_ci event = obtainTouchEvent(MMI::PointerEvent::POINTER_ACTION_DOWN, pointer, downTime); 287885b47fbSopenharmony_ci if (event == nullptr) { 288885b47fbSopenharmony_ci HILOG_ERROR("event is nullptr"); 289885b47fbSopenharmony_ci return; 290885b47fbSopenharmony_ci } 291885b47fbSopenharmony_ci 292885b47fbSopenharmony_ci injectedEvents_.push_back(event); 293885b47fbSopenharmony_ci } else if (i < (positionSize - 1)) { // Append move event 294885b47fbSopenharmony_ci HILOG_DEBUG("append move event"); 295885b47fbSopenharmony_ci nowTime += perDurationTime * MS_TO_US; 296885b47fbSopenharmony_ci event = obtainTouchEvent(MMI::PointerEvent::POINTER_ACTION_MOVE, pointer, nowTime); 297885b47fbSopenharmony_ci if (event == nullptr) { 298885b47fbSopenharmony_ci HILOG_ERROR("event is nullptr"); 299885b47fbSopenharmony_ci return; 300885b47fbSopenharmony_ci } 301885b47fbSopenharmony_ci 302885b47fbSopenharmony_ci injectedEvents_.push_back(event); 303885b47fbSopenharmony_ci } else { // Append up event 304885b47fbSopenharmony_ci HILOG_DEBUG("append move event"); 305885b47fbSopenharmony_ci nowTime += perDurationTime * MS_TO_US; 306885b47fbSopenharmony_ci event = obtainTouchEvent(MMI::PointerEvent::POINTER_ACTION_MOVE, pointer, nowTime); 307885b47fbSopenharmony_ci if (event == nullptr) { 308885b47fbSopenharmony_ci HILOG_ERROR("event is nullptr"); 309885b47fbSopenharmony_ci return; 310885b47fbSopenharmony_ci } 311885b47fbSopenharmony_ci 312885b47fbSopenharmony_ci injectedEvents_.push_back(event); 313885b47fbSopenharmony_ci 314885b47fbSopenharmony_ci HILOG_DEBUG("append up event"); 315885b47fbSopenharmony_ci event = obtainTouchEvent(MMI::PointerEvent::POINTER_ACTION_UP, pointer, nowTime); 316885b47fbSopenharmony_ci if (event == nullptr) { 317885b47fbSopenharmony_ci HILOG_ERROR("event is nullptr"); 318885b47fbSopenharmony_ci return; 319885b47fbSopenharmony_ci } 320885b47fbSopenharmony_ci 321885b47fbSopenharmony_ci injectedEvents_.push_back(event); 322885b47fbSopenharmony_ci } 323885b47fbSopenharmony_ci } 324885b47fbSopenharmony_ci} 325885b47fbSopenharmony_ci 326885b47fbSopenharmony_civoid TouchEventInjector::ParseTouchEventsFromGesturePath(int64_t startTime, 327885b47fbSopenharmony_ci const std::shared_ptr<AccessibilityGestureInjectPath>& gesturePath) 328885b47fbSopenharmony_ci{ 329885b47fbSopenharmony_ci HILOG_DEBUG(); 330885b47fbSopenharmony_ci if (!gesturePath) { 331885b47fbSopenharmony_ci HILOG_ERROR("gesturePath is null."); 332885b47fbSopenharmony_ci return; 333885b47fbSopenharmony_ci } 334885b47fbSopenharmony_ci const std::vector<AccessibilityGesturePosition> &positions = gesturePath->GetPositions(); 335885b47fbSopenharmony_ci if (positions.size() == 0) { 336885b47fbSopenharmony_ci HILOG_ERROR("position size is 0."); 337885b47fbSopenharmony_ci return; 338885b47fbSopenharmony_ci } 339885b47fbSopenharmony_ci if ((positions.size() == 1) || 340885b47fbSopenharmony_ci ((positions[0].positionX_ == positions[1].positionX_) && 341885b47fbSopenharmony_ci (positions[0].positionY_ == positions[1].positionY_))) { 342885b47fbSopenharmony_ci ParseTapsEvents(startTime, gesturePath); 343885b47fbSopenharmony_ci } else { 344885b47fbSopenharmony_ci ParseMovesEvents(startTime, gesturePath); 345885b47fbSopenharmony_ci } 346885b47fbSopenharmony_ci} 347885b47fbSopenharmony_ci} // namespace Accessibility 348885b47fbSopenharmony_ci} // namespace OHOS