1/* 2 * Copyright (c) 2023 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#include "external_calls.h" 16#include "pointer_tracker.h" 17namespace OHOS::uitest { 18 void FingerTracker::HandleDownEvent(TouchEventInfo& event) 19 { 20 velocityTracker.UpdateTouchEvent(event, false); 21 fingerInfo.SetFirstTouchEventInfo(event); 22 fingerInfo.SetLastTouchEventInfo(event); 23 } 24 25 void FingerTracker::HandleMoveEvent(TouchEventInfo& event) 26 { 27 velocityTracker.UpdateTouchEvent(event, false); 28 fingerInfo.SetLastTouchEventInfo(event); 29 } 30 31 void FingerTracker::UpdatevelocityTracker(TouchEventInfo& event) 32 { 33 velocityTracker.UpdateTouchEvent(event, false); 34 } 35 void FingerTracker::HandleUpEvent(TouchEventInfo& event) 36 { 37 fingerInfo.SetLastTouchEventInfo(event); 38 } 39 40 void FingerTracker::BuildFingerInfo() 41 { 42 TouchEventInfo lastTouch = fingerInfo.GetLastTouchEventInfo(); 43 TouchEventInfo firstTouch = fingerInfo.GetFirstTouchEventInfo(); 44 fingerInfo.SetStepLength(velocityTracker.GetStepLength()); 45 fingerInfo.SetVelocity(velocityTracker.GetMainAxisVelocity()); 46 fingerInfo.SetDirection(Offset(lastTouch.x-firstTouch.x, lastTouch.y-firstTouch.y)); 47 } 48 49 bool FingerTracker::IsRecentSpeedLimit(TouchEventInfo& touchEvent) 50 { 51 auto preEventTime = velocityTracker.GetPreTime(ONE); 52 double deltaT = touchEvent.durationSeconds * VelocityTracker::TIME_INDEX - 53 preEventTime * VelocityTracker::TIME_INDEX; 54 auto preX = velocityTracker.GetPreX(ONE); 55 auto preY = velocityTracker.GetPreY(ONE); 56 auto speedX = (touchEvent.wx - preX) / deltaT; 57 auto speedY = (touchEvent.wy - preY)/ deltaT; 58 auto speed = sqrt(speedX * speedX + speedY * speedY); 59 double curSpeed = touchEvent.wy > preY ? speed : -speed; 60 if (fabs(curSpeed) < 1e-6) { 61 return false; 62 } 63 auto acceleration = (curSpeed - preSpeed) / deltaT; 64 preSpeed = curSpeed; 65 return (acceleration > PointerTracker::RECENT_ACCELERAT && curSpeed > PointerTracker::RECENT_SPEED2) || 66 (curSpeed > PointerTracker::RECENT_SPEED1 && deltaT > PointerTracker::RECENT_TIME); 67 } 68 69 // POINTER_TRACKER 70 void PointerTracker::HandleDownEvent(TouchEventInfo& event) 71 { 72 // 接受down事件时,若存在上次操作时间与本次down时间相差较大情况,说明上次操作接收情况异常,本次录制异常 73 if (fingerTrackers.size() != 0) { 74 TimeStamp thisTime = event.GetDownTimeStamp(); 75 bool flag = false; 76 for (auto it = fingerTrackers.begin(); it != fingerTrackers.end(); it++) { 77 TimeStamp lastTime = it->second->GetVelocityTracker().GetLastTimePoint(); 78 double duration = (thisTime - lastTime).count(); 79 if (duration > ERROR_POINTER && it->second != nullptr) { 80 flag = true; 81 delete it->second; 82 it = fingerTrackers.erase(it); 83 LOG_E("获取回调信息存在异常,请重新录制"); 84 std::cout << "获取回调信息存在异常,请重新录制" << std::endl; 85 break; 86 } 87 } 88 if (flag) { 89 Resets(); 90 } 91 } 92 if (fingerTrackers.size() == 0) { 93 firstTrackPoint_ = event; 94 InitJudgeChain(); 95 } 96 FingerTracker* fTracker = new FingerTracker(); 97 if (fTracker == nullptr) { 98 LOG_E("Failedf to new FingerTracker"); 99 } else { 100 fTracker->HandleDownEvent(event); 101 fingerTrackers.insert({event.downTime, fTracker}); 102 currentFingerNum++; 103 } 104 } 105 106 void PointerTracker::HandleMoveEvent(TouchEventInfo& event) 107 { 108 if (fingerTrackers.count(event.downTime)) { 109 if (pointerTypeJudgChain_.size() > 1) { 110 auto judgeFunction = pointerTypeJudgMap_.find(pointerTypeJudgChain_[0])->second; 111 judgeFunction(event); 112 } 113 FingerTracker* ftracker = fingerTrackers.find(event.downTime)->second; 114 ftracker->HandleMoveEvent(event); 115 } 116 } 117 118 void PointerTracker::HandleUpEvent(TouchEventInfo& event) 119 { 120 if (fingerTrackers.count(event.downTime)) { 121 // 第一个抬起的手指,记录手指总数 122 if (maxFingerNum == 0 && fingerTrackers.size() != 0) { 123 maxFingerNum = fingerTrackers.size(); 124 isUpStage = true; 125 } 126 // 抬起判断 127 bool flag = false; 128 fingerTrackers.find(event.downTime)->second->UpdatevelocityTracker(event); 129 while (pointerTypeJudgChain_.size() > 1 && !flag) { 130 auto judgeFunction = pointerTypeJudgMap_.find(pointerTypeJudgChain_[0])->second; 131 flag = judgeFunction(event); 132 } 133 fingerTrackers.find(event.downTime)->second->HandleUpEvent(event); 134 fingerTrackers.find(event.downTime)->second->BuildFingerInfo(); 135 currentFingerNum--; 136 // 最后一个抬起的手指,快照+复位 137 if (currentFingerNum == 0) { 138 snapshootPointerInfo = BuildPointerInfo(); 139 isNeedWrite = true; 140 if (snapshootPointerInfo.GetTouchOpt() == OP_CLICK && 141 isLastClickInTracker && GetInterVal() < INTERVAL_THRESHOLD) { // doubleClick 142 snapshootPointerInfo.SetTouchOpt(OP_DOUBLE_CLICK); 143 isLastClickInTracker = false; 144 } else if (snapshootPointerInfo.GetTouchOpt() == OP_CLICK) { // click 145 lastClickInfo = snapshootPointerInfo; 146 isLastClickInTracker = true; 147 } 148 maxFingerNum = 0; 149 isUpStage = false; 150 ClearFingerTrackersValues(); 151 } 152 } 153 } 154 155 void PointerTracker::HandleMoveEvent(TouchEventInfo& event, TouchOpt touchOpt) 156 { 157 pointerTypeJudgChain_.clear(); 158 pointerTypeJudgChain_ = {touchOpt}; 159 HandleMoveEvent(event); 160 } 161 162 void PointerTracker::HandleUpEvent(TouchEventInfo& event, TouchOpt touchOpt) 163 { 164 pointerTypeJudgChain_.clear(); 165 pointerTypeJudgChain_ = {touchOpt}; 166 HandleUpEvent(event); 167 } 168 169 void PointerTracker::ClearFingerTrackersValues() 170 { 171 for (auto it = fingerTrackers.begin(); it != fingerTrackers.end(); it++) { 172 if (it->second != nullptr) { 173 delete it->second; 174 } 175 } 176 fingerTrackers.clear(); 177 } 178 179 void PointerTracker::InitJudgeChain() 180 { 181 pointerTypeJudgChain_.clear(); 182 pointerTypeJudgChain_ = { 183 OP_CLICK, OP_LONG_CLICK, OP_DRAG, OP_RECENT, OP_HOME, OP_RETURN, OP_SWIPE, OP_FLING 184 }; 185 isStartRecent = false; 186 if (pointerTypeJudgMap_.size() == 0) { 187 pointerTypeJudgMap_.emplace(std::make_pair(OP_CLICK, 188 function<bool(TouchEventInfo&)>(bind(&PointerTracker::IsClick, this, placeholders::_1)))); 189 pointerTypeJudgMap_.emplace(std::make_pair(OP_LONG_CLICK, 190 function<bool(TouchEventInfo&)>(bind(&PointerTracker::IsLongClick, this, placeholders::_1)))); 191 pointerTypeJudgMap_.emplace(std::make_pair(OP_DRAG, 192 function<bool(TouchEventInfo&)>(bind(&PointerTracker::IsDrag, this, placeholders::_1)))); 193 pointerTypeJudgMap_.emplace(std::make_pair(OP_RETURN, 194 function<bool(TouchEventInfo&)>(bind(&PointerTracker::IsBack, this, placeholders::_1)))); 195 pointerTypeJudgMap_.emplace(std::make_pair(OP_SWIPE, 196 function<bool(TouchEventInfo&)>(bind(&PointerTracker::IsSwip, this, placeholders::_1)))); 197 pointerTypeJudgMap_.emplace(std::make_pair(OP_RECENT, 198 function<bool(TouchEventInfo&)>(bind(&PointerTracker::IsRecent, this, placeholders::_1)))); 199 pointerTypeJudgMap_.emplace(std::make_pair(OP_FLING, 200 function<bool(TouchEventInfo&)>(bind(&PointerTracker::IsFling, this, placeholders::_1)))); 201 pointerTypeJudgMap_.emplace(std::make_pair(OP_HOME, 202 function<bool(TouchEventInfo&)>(bind(&PointerTracker::IsHome, this, placeholders::_1)))); 203 } 204 } 205 206 bool PointerTracker::IsClick(TouchEventInfo& touchEvent) // click(back) 207 { 208 // 时间 > DURATIOIN_THRESHOLD && move > MAX_THRESHOLD 209 int moveDistance = fingerTrackers.find(touchEvent.downTime)->second->GetMoveDistance(); 210 if (touchEvent.durationSeconds > DURATIOIN_THRESHOLD || moveDistance > MAX_THRESHOLD) { 211 // 不满足点击操作,删除OP_CLICK 212 RemoveTypeJudge(pointerTypeJudgChain_, OP_CLICK); 213 return false; 214 } 215 return true; 216 } 217 218 bool PointerTracker::IsLongClick(TouchEventInfo& touchEvent) 219 { 220 // 先时间 > DURATIOIN_THRESHOLD,不满足则删除LONCLICK && DRAG 221 if (touchEvent.durationSeconds < DURATIOIN_THRESHOLD) { 222 RemoveTypeJudge(pointerTypeJudgChain_, OP_LONG_CLICK, OP_DRAG); 223 return false; 224 } 225 // 初始时间长,排除滑动类操作 226 RemoveTypeJudge(pointerTypeJudgChain_, OP_SWIPE, OP_FLING, OP_HOME, OP_RECENT); 227 // 后 move > MAX_THRESHOLD ,若不满足却通过时间判断则为DRAG 228 int moveDistance = fingerTrackers.find(touchEvent.downTime)->second->GetMoveDistance(); 229 if (moveDistance > MAX_THRESHOLD) { 230 RemoveTypeJudge(pointerTypeJudgChain_, OP_LONG_CLICK); 231 return false; 232 } 233 return true; 234 } 235 236 bool PointerTracker::IsDrag(TouchEventInfo& touchEvent) 237 { 238 // 其实LongClick已经判断过了 239 // 时间 > DURATIOIN_THRESHOLD && move > MAX_THRESHOLD 240 auto ftracker = fingerTrackers.find(touchEvent.downTime)->second; 241 int moveDistance = ftracker->GetMoveDistance(); 242 if (touchEvent.durationSeconds < DURATIOIN_THRESHOLD || moveDistance < MAX_THRESHOLD) { 243 RemoveTypeJudge(pointerTypeJudgChain_, OP_DRAG); 244 return false; 245 } 246 return true; 247 } 248 249 // bool PinchJudge(TouchEventInfo& touchEvent) 250 251 bool PointerTracker::IsRecent(TouchEventInfo& touchEvent) 252 { 253 // 起点位置判断 254 auto ftracker = fingerTrackers.find(touchEvent.downTime)->second; 255 TouchEventInfo startEvent = ftracker->GetFingerInfo().GetFirstTouchEventInfo(); 256 if (startEvent.y <= windowBounds.bottom_ * NAVI_THRE_D) { 257 RemoveTypeJudge(pointerTypeJudgChain_, OP_RECENT, OP_HOME); 258 return false; 259 } 260 if (isStartRecent) { 261 return true; 262 } else { 263 // 滑动位移判断 264 bool isDistance = (double)(windowBounds.bottom_ - touchEvent.y) / windowBounds.bottom_ >= RECENT_DISTANCE; 265 // 速度判断 266 bool isRecentSpeed = ftracker -> IsRecentSpeedLimit(touchEvent); 267 if (isDistance && isRecentSpeed) { 268 isStartRecent = true; 269 return true; 270 } else if (isUpStage) { 271 RemoveTypeJudge(pointerTypeJudgChain_, OP_RECENT); 272 return false; 273 } 274 return true; 275 } 276 } 277 278 bool PointerTracker::IsHome(TouchEventInfo& touchEvent) 279 { 280 // 起点位置已判断 281 // 滑动位移判断 282 bool isDistance = (double)(windowBounds.bottom_ - touchEvent.y) / windowBounds.bottom_ >= HOME_DISTANCE; 283 if (isDistance) { 284 return true; 285 } else if (isUpStage) { 286 RemoveTypeJudge(pointerTypeJudgChain_, OP_HOME); 287 return false; 288 } 289 return true; 290 } 291 292 bool PointerTracker::IsBack(TouchEventInfo& touchEvent) 293 { 294 // 滑动类只有起手才能判断 295 if (!isUpStage) { 296 return true; 297 } 298 auto ftracker = fingerTrackers.find(touchEvent.downTime)->second; 299 TouchEventInfo startEvent = ftracker->GetFingerInfo().GetFirstTouchEventInfo(); 300 VelocityTracker vTracker = ftracker->GetVelocityTracker(); 301 if (startEvent.x - windowBounds.left_ <= NAVI_THRE_D && 302 ftracker->GetMoveDistance() >= NAVI_VERTI_THRE_V) { 303 RemoveTypeJudge(pointerTypeJudgChain_, OP_SWIPE, OP_RECENT, OP_FLING, OP_HOME); 304 return true; 305 } 306 RemoveTypeJudge(pointerTypeJudgChain_, OP_RETURN); 307 return false; 308 } 309 310 bool PointerTracker::IsSwip(TouchEventInfo& touchEvent) // swip 311 { 312 // 滑动类只有起手才能判断 313 if (!isUpStage) { 314 return true; 315 } 316 auto ftracker = fingerTrackers.find(touchEvent.downTime)->second; 317 double mainVelocity = ftracker->GetVelocityTracker().GetMainAxisVelocity(); 318 // 离手v < FLING_THRESHOLD 319 if (mainVelocity >= FLING_THRESHOLD) { 320 RemoveTypeJudge(pointerTypeJudgChain_, OP_SWIPE); 321 return false; 322 } 323 return true; 324 } 325 326 bool PointerTracker::IsFling(TouchEventInfo& touchEvent) // fling 327 { 328 // SWIP判断过离手速度 329 return true; 330 } 331 332 PointerInfo PointerTracker::BuildPointerInfo() 333 { 334 PointerInfo pointerInfo; 335 pointerInfo.SetTouchOpt(pointerTypeJudgChain_[0]); 336 pointerInfo.SetFingerNumber(maxFingerNum); 337 pointerInfo.SetFirstTrackPoint(firstTrackPoint_); 338 for (auto it = fingerTrackers.begin(); it != fingerTrackers.end(); it++) { 339 pointerInfo.AddFingerInfo(it->second->GetFingerInfo()); 340 } 341 auto fastTouch = pointerInfo.GetFingerInfoList()[0].GetLastTouchEventInfo(); 342 auto lastTouch = pointerInfo.GetFingerInfoList()[fingerTrackers.size()-1].GetLastTouchEventInfo(); 343 pointerInfo.SetDuration((lastTouch.GetActionTimeStamp() - fastTouch.GetDownTimeStamp()).count()); 344 if (pointerInfo.GetTouchOpt() == OP_CLICK || pointerInfo.GetTouchOpt() == OP_LONG_CLICK) { 345 std::vector<std::string> names = GetFrontAbility(); 346 pointerInfo.SetBundleName(names[0]); 347 pointerInfo.SetAbilityName(names[1]); 348 } 349 if (pointerInfo.GetTouchOpt() == OP_DRAG || 350 pointerInfo.GetTouchOpt() == OP_SWIPE || 351 pointerInfo.GetTouchOpt() == OP_FLING) { 352 // 平均方向->向量相加 353 Offset avgDirection; 354 int addStepLength = 0; 355 double addVelocity = 0.0; 356 for (auto it = fingerTrackers.begin(); it != fingerTrackers.end(); it++) { 357 avgDirection += it->second->GetFingerInfo().GetDirection(); 358 addStepLength += it->second->GetVelocityTracker().GetStepLength(); 359 addVelocity += it->second->GetFingerInfo().GetVelocity(); 360 } 361 pointerInfo.SetAvgDirection(avgDirection); 362 pointerInfo.SetAvgStepLength(addStepLength/fingerTrackers.size()); 363 double avgVelocity = addVelocity/fingerTrackers.size(); 364 pointerInfo.SetAvgVelocity(avgVelocity); 365 } 366 return pointerInfo; 367 } 368 369 // cout 370 std::string PointerTracker::WriteData(PointerInfo pointerInfo, shared_ptr<mutex> &cout_lock) 371 { 372 auto out = pointerInfo.WriteWindowData(); 373 std::lock_guard<mutex> guard(*cout_lock); 374 std::cout << out << std::endl; 375 return out; 376 } 377 378 // record.csv 379 nlohmann::json PointerTracker::WriteData(PointerInfo pointerInfo, ofstream& outFile, shared_ptr<mutex> &csv_lock) 380 { 381 auto out = pointerInfo.WriteData(); 382 std::lock_guard<mutex> guard(*csv_lock); 383 if (outFile.is_open()) { 384 outFile << out.dump() << std::endl; 385 } 386 return out; 387 } 388}