1 /* 2 * Copyright (c) 2021-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 <cmath> 17 #include "ui_action.h" 18 19 namespace OHOS::uitest { 20 using namespace std; 21 using namespace nlohmann; 22 WriteIntoParcel(json & data) const23 void UiDriveOptions::WriteIntoParcel(json &data) const 24 { 25 auto arr = json::array(); 26 arr.push_back(clickHoldMs_); 27 arr.push_back(longClickHoldMs_); 28 arr.push_back(doubleClickIntervalMs_); 29 arr.push_back(keyHoldMs_); 30 arr.push_back(swipeVelocityPps_); 31 arr.push_back(uiSteadyThresholdMs_); 32 arr.push_back(waitUiSteadyMaxMs_); 33 data["data"] = arr; 34 } 35 ReadFromParcel(const json & data)36 void UiDriveOptions::ReadFromParcel(const json &data) 37 { 38 auto arr = data["data"]; 39 size_t index = 0; 40 clickHoldMs_ = arr.at(index++); 41 longClickHoldMs_ = arr.at(index++); 42 doubleClickIntervalMs_ = arr.at(index++); 43 keyHoldMs_ = arr.at(index++); 44 swipeVelocityPps_ = arr.at(index++); 45 uiSteadyThresholdMs_ = arr.at(index++); 46 waitUiSteadyMaxMs_ = arr.at(index++); 47 } 48 DecomposeClick(vector<TouchEvent> & recv,const Point & point,const UiDriveOptions & options)49 static void DecomposeClick(vector<TouchEvent> &recv, const Point &point, const UiDriveOptions &options) 50 { 51 recv.push_back(TouchEvent {ActionStage::DOWN, point, 0, options.clickHoldMs_}); 52 recv.push_back(TouchEvent {ActionStage::UP, point, options.clickHoldMs_, 0}); 53 } 54 DecomposeLongClick(vector<TouchEvent> & recv,const Point & point,const UiDriveOptions & options)55 static void DecomposeLongClick(vector<TouchEvent> &recv, const Point &point, const UiDriveOptions &options) 56 { 57 // should sleep after touch-down to make long-click duration 58 recv.push_back(TouchEvent {ActionStage::DOWN, point, 0, options.longClickHoldMs_}); 59 recv.push_back(TouchEvent {ActionStage::UP, point, options.longClickHoldMs_, 0}); 60 } 61 DecomposeDoubleClick(vector<TouchEvent> & recv,const Point & point,const UiDriveOptions & options)62 static void DecomposeDoubleClick(vector<TouchEvent> &recv, const Point &point, const UiDriveOptions &options) 63 { 64 const auto msInterval = options.doubleClickIntervalMs_; 65 recv.push_back(TouchEvent {ActionStage::DOWN, point, 0, options.clickHoldMs_}); 66 recv.push_back(TouchEvent {ActionStage::UP, point, options.clickHoldMs_, msInterval}); 67 68 recv.push_back(TouchEvent {ActionStage::DOWN, point, 0, options.clickHoldMs_}); 69 recv.push_back(TouchEvent {ActionStage::UP, point, options.clickHoldMs_, 0}); 70 } 71 DecomposeComputeSwipe(vector<TouchEvent> & recv,const Point & from,const Point & to,bool drag,const UiDriveOptions & options)72 static void DecomposeComputeSwipe(vector<TouchEvent> &recv, const Point &from, const Point &to, bool drag, 73 const UiDriveOptions &options) 74 { 75 const int32_t distanceX = to.px_ - from.px_; 76 const int32_t distanceY = to.py_ - from.py_; 77 const uint32_t distance = sqrt(distanceX * distanceX + distanceY * distanceY); 78 const uint32_t timeCostMs = (distance * 1000) / options.swipeVelocityPps_; 79 if (distance < 1) { 80 // do not need to execute swipe 81 return; 82 } 83 constexpr auto steps = 50; 84 const uint32_t intervalMs = timeCostMs / steps + 1; 85 recv.push_back(TouchEvent {ActionStage::DOWN, {from.px_, from.py_}, 0, intervalMs}); 86 for (auto step = 1; step < steps; step++) { 87 const int32_t pointX = from.px_ + (distanceX * step) / steps; 88 const int32_t pointY = from.py_ + (distanceY * step) / steps; 89 const uint32_t timeOffsetMs = (timeCostMs * step) / steps; 90 recv.push_back(TouchEvent {ActionStage::MOVE, {pointX, pointY}, timeOffsetMs, intervalMs}); 91 } 92 recv.push_back(TouchEvent {ActionStage::UP, {to.px_, to.py_}, timeCostMs, intervalMs}); 93 if (drag) { 94 // drag needs longPressDown firstly 95 recv.at(0).holdMs_ += options.longClickHoldMs_; 96 for (std::size_t idx = 1; idx < recv.size(); idx++) { 97 recv.at(idx).downTimeOffsetMs_ += options.longClickHoldMs_; 98 } 99 } 100 } 101 Decompose(vector<TouchEvent> & recv,const Point & point,const UiDriveOptions & options) const102 void GenericClick::Decompose(vector<TouchEvent> &recv, const Point &point, const UiDriveOptions &options) const 103 { 104 DCHECK(type_ >= PointerOp::CLICK_P && type_ <= PointerOp::DOUBLE_CLICK_P); 105 switch (type_) { 106 case CLICK_P: 107 DecomposeClick(recv, point, options); 108 break; 109 case LONG_CLICK_P: 110 DecomposeLongClick(recv, point, options); 111 break; 112 case DOUBLE_CLICK_P: 113 DecomposeDoubleClick(recv, point, options); 114 break; 115 default: 116 break; 117 } 118 for (auto &event:recv) { 119 event.flags_ = type_; 120 } 121 } 122 Decompose(vector<TouchEvent> & recv,const Point & fromPoint,const Point & toPoint,const UiDriveOptions & options) const123 void GenericSwipe::Decompose(vector<TouchEvent> &recv, const Point &fromPoint, const Point &toPoint, 124 const UiDriveOptions &options) const 125 { 126 DCHECK(type_ >= PointerOp::SWIPE_P && type_ <= PointerOp::DRAG_P); 127 DecomposeComputeSwipe(recv, fromPoint, toPoint, type_ == PointerOp::DRAG_P, options); 128 for (auto &event:recv) { 129 event.flags_ = type_; 130 } 131 } 132 } 133