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" 17 namespace OHOS::uitest { HandleDownEvent(TouchEventInfo & event)18 void FingerTracker::HandleDownEvent(TouchEventInfo& event) 19 { 20 velocityTracker.UpdateTouchEvent(event, false); 21 fingerInfo.SetFirstTouchEventInfo(event); 22 fingerInfo.SetLastTouchEventInfo(event); 23 } 24 HandleMoveEvent(TouchEventInfo & event)25 void FingerTracker::HandleMoveEvent(TouchEventInfo& event) 26 { 27 velocityTracker.UpdateTouchEvent(event, false); 28 fingerInfo.SetLastTouchEventInfo(event); 29 } 30 UpdatevelocityTracker(TouchEventInfo & event)31 void FingerTracker::UpdatevelocityTracker(TouchEventInfo& event) 32 { 33 velocityTracker.UpdateTouchEvent(event, false); 34 } HandleUpEvent(TouchEventInfo & event)35 void FingerTracker::HandleUpEvent(TouchEventInfo& event) 36 { 37 fingerInfo.SetLastTouchEventInfo(event); 38 } 39 BuildFingerInfo()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 IsRecentSpeedLimit(TouchEventInfo & touchEvent)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 HandleDownEvent(TouchEventInfo & event)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) { 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 fTracker->HandleDownEvent(event); 98 fingerTrackers.insert({event.downTime, fTracker}); 99 100 currentFingerNum++; 101 } 102 HandleMoveEvent(TouchEventInfo & event)103 void PointerTracker::HandleMoveEvent(TouchEventInfo& event) 104 { 105 if (fingerTrackers.count(event.downTime)) { 106 if (pointerTypeJudgChain_.size() > 1) { 107 auto judgeFunction = pointerTypeJudgMap_.find(pointerTypeJudgChain_[0])->second; 108 judgeFunction(event); 109 } 110 FingerTracker* ftracker = fingerTrackers.find(event.downTime)->second; 111 ftracker->HandleMoveEvent(event); 112 } 113 } 114 HandleUpEvent(TouchEventInfo & event)115 void PointerTracker::HandleUpEvent(TouchEventInfo& event) 116 { 117 if (fingerTrackers.count(event.downTime)) { 118 // 第一个抬起的手指,记录手指总数 119 if (maxFingerNum == 0 && fingerTrackers.size() != 0) { 120 maxFingerNum = fingerTrackers.size(); 121 isUpStage = true; 122 } 123 // 抬起判断 124 bool flag = false; 125 fingerTrackers.find(event.downTime)->second->UpdatevelocityTracker(event); 126 while (pointerTypeJudgChain_.size() > 1 && !flag) { 127 auto judgeFunction = pointerTypeJudgMap_.find(pointerTypeJudgChain_[0])->second; 128 flag = judgeFunction(event); 129 } 130 fingerTrackers.find(event.downTime)->second->HandleUpEvent(event); 131 fingerTrackers.find(event.downTime)->second->BuildFingerInfo(); 132 currentFingerNum--; 133 // 最后一个抬起的手指,快照+复位 134 if (currentFingerNum == 0) { 135 snapshootPointerInfo = BuildPointerInfo(); 136 isNeedWrite = true; 137 if (snapshootPointerInfo.GetTouchOpt() == OP_CLICK && 138 isLastClickInTracker && GetInterVal() < INTERVAL_THRESHOLD) { // doubleClick 139 snapshootPointerInfo.SetTouchOpt(OP_DOUBLE_CLICK); 140 isLastClickInTracker = false; 141 } else if (snapshootPointerInfo.GetTouchOpt() == OP_CLICK) { // click 142 lastClickInfo = snapshootPointerInfo; 143 isLastClickInTracker = true; 144 } 145 maxFingerNum = 0; 146 isUpStage = false; 147 ClearFingerTrackersValues(); 148 } 149 } 150 } 151 HandleMoveEvent(TouchEventInfo & event,TouchOpt touchOpt)152 void PointerTracker::HandleMoveEvent(TouchEventInfo& event, TouchOpt touchOpt) 153 { 154 pointerTypeJudgChain_.clear(); 155 pointerTypeJudgChain_ = {touchOpt}; 156 HandleMoveEvent(event); 157 } 158 HandleUpEvent(TouchEventInfo & event,TouchOpt touchOpt)159 void PointerTracker::HandleUpEvent(TouchEventInfo& event, TouchOpt touchOpt) 160 { 161 pointerTypeJudgChain_.clear(); 162 pointerTypeJudgChain_ = {touchOpt}; 163 HandleUpEvent(event); 164 } 165 ClearFingerTrackersValues()166 void PointerTracker::ClearFingerTrackersValues() 167 { 168 for (auto it = fingerTrackers.begin(); it != fingerTrackers.end(); it++) { 169 delete it->second; 170 } 171 fingerTrackers.clear(); 172 } 173 InitJudgeChain()174 void PointerTracker::InitJudgeChain() 175 { 176 pointerTypeJudgChain_.clear(); 177 pointerTypeJudgChain_ = { 178 OP_CLICK, OP_LONG_CLICK, OP_DRAG, OP_RECENT, OP_HOME, OP_RETURN, OP_SWIPE, OP_FLING 179 }; 180 isStartRecent = false; 181 if (pointerTypeJudgMap_.size() == 0) { 182 pointerTypeJudgMap_.emplace(std::make_pair(OP_CLICK, 183 function<bool(TouchEventInfo&)>(bind(&PointerTracker::IsClick, this, placeholders::_1)))); 184 pointerTypeJudgMap_.emplace(std::make_pair(OP_LONG_CLICK, 185 function<bool(TouchEventInfo&)>(bind(&PointerTracker::IsLongClick, this, placeholders::_1)))); 186 pointerTypeJudgMap_.emplace(std::make_pair(OP_DRAG, 187 function<bool(TouchEventInfo&)>(bind(&PointerTracker::IsDrag, this, placeholders::_1)))); 188 pointerTypeJudgMap_.emplace(std::make_pair(OP_RETURN, 189 function<bool(TouchEventInfo&)>(bind(&PointerTracker::IsBack, this, placeholders::_1)))); 190 pointerTypeJudgMap_.emplace(std::make_pair(OP_SWIPE, 191 function<bool(TouchEventInfo&)>(bind(&PointerTracker::IsSwip, this, placeholders::_1)))); 192 pointerTypeJudgMap_.emplace(std::make_pair(OP_RECENT, 193 function<bool(TouchEventInfo&)>(bind(&PointerTracker::IsRecent, this, placeholders::_1)))); 194 pointerTypeJudgMap_.emplace(std::make_pair(OP_FLING, 195 function<bool(TouchEventInfo&)>(bind(&PointerTracker::IsFling, this, placeholders::_1)))); 196 pointerTypeJudgMap_.emplace(std::make_pair(OP_HOME, 197 function<bool(TouchEventInfo&)>(bind(&PointerTracker::IsHome, this, placeholders::_1)))); 198 } 199 } 200 IsClick(TouchEventInfo & touchEvent)201 bool PointerTracker::IsClick(TouchEventInfo& touchEvent) // click(back) 202 { 203 // 时间 > DURATIOIN_THRESHOLD && move > MAX_THRESHOLD 204 int moveDistance = fingerTrackers.find(touchEvent.downTime)->second->GetMoveDistance(); 205 if (touchEvent.durationSeconds > DURATIOIN_THRESHOLD || moveDistance > MAX_THRESHOLD) { 206 // 不满足点击操作,删除OP_CLICK 207 RemoveTypeJudge(pointerTypeJudgChain_, OP_CLICK); 208 return false; 209 } 210 return true; 211 } 212 IsLongClick(TouchEventInfo & touchEvent)213 bool PointerTracker::IsLongClick(TouchEventInfo& touchEvent) 214 { 215 // 先时间 > DURATIOIN_THRESHOLD,不满足则删除LONCLICK && DRAG 216 if (touchEvent.durationSeconds < DURATIOIN_THRESHOLD) { 217 RemoveTypeJudge(pointerTypeJudgChain_, OP_LONG_CLICK, OP_DRAG); 218 return false; 219 } 220 // 初始时间长,排除滑动类操作 221 RemoveTypeJudge(pointerTypeJudgChain_, OP_SWIPE, OP_FLING, OP_HOME, OP_RECENT); 222 // 后 move > MAX_THRESHOLD ,若不满足却通过时间判断则为DRAG 223 int moveDistance = fingerTrackers.find(touchEvent.downTime)->second->GetMoveDistance(); 224 if (moveDistance > MAX_THRESHOLD) { 225 RemoveTypeJudge(pointerTypeJudgChain_, OP_LONG_CLICK); 226 return false; 227 } 228 return true; 229 } 230 IsDrag(TouchEventInfo & touchEvent)231 bool PointerTracker::IsDrag(TouchEventInfo& touchEvent) 232 { 233 // 其实LongClick已经判断过了 234 // 时间 > DURATIOIN_THRESHOLD && move > MAX_THRESHOLD 235 auto ftracker = fingerTrackers.find(touchEvent.downTime)->second; 236 int moveDistance = ftracker->GetMoveDistance(); 237 if (touchEvent.durationSeconds < DURATIOIN_THRESHOLD || moveDistance < MAX_THRESHOLD) { 238 RemoveTypeJudge(pointerTypeJudgChain_, OP_DRAG); 239 return false; 240 } 241 return true; 242 } 243 244 // bool PinchJudge(TouchEventInfo& touchEvent) 245 IsRecent(TouchEventInfo & touchEvent)246 bool PointerTracker::IsRecent(TouchEventInfo& touchEvent) 247 { 248 // 起点位置判断 249 auto ftracker = fingerTrackers.find(touchEvent.downTime)->second; 250 TouchEventInfo startEvent = ftracker->GetFingerInfo().GetFirstTouchEventInfo(); 251 if (startEvent.y <= windowBounds.bottom_ * NAVI_THRE_D) { 252 RemoveTypeJudge(pointerTypeJudgChain_, OP_RECENT, OP_HOME); 253 return false; 254 } 255 if (isStartRecent) { 256 return true; 257 } else { 258 // 滑动位移判断 259 bool isDistance = (double)(windowBounds.bottom_ - touchEvent.y) / windowBounds.bottom_ >= RECENT_DISTANCE; 260 // 速度判断 261 bool isRecentSpeed = ftracker -> IsRecentSpeedLimit(touchEvent); 262 if (isDistance && isRecentSpeed) { 263 isStartRecent = true; 264 return true; 265 } else if (isUpStage) { 266 RemoveTypeJudge(pointerTypeJudgChain_, OP_RECENT); 267 return false; 268 } 269 return true; 270 } 271 } 272 IsHome(TouchEventInfo & touchEvent)273 bool PointerTracker::IsHome(TouchEventInfo& touchEvent) 274 { 275 // 起点位置已判断 276 // 滑动位移判断 277 bool isDistance = (double)(windowBounds.bottom_ - touchEvent.y) / windowBounds.bottom_ >= HOME_DISTANCE; 278 if (isDistance) { 279 return true; 280 } else if (isUpStage) { 281 RemoveTypeJudge(pointerTypeJudgChain_, OP_HOME); 282 return false; 283 } 284 return true; 285 } 286 IsBack(TouchEventInfo & touchEvent)287 bool PointerTracker::IsBack(TouchEventInfo& touchEvent) 288 { 289 // 滑动类只有起手才能判断 290 if (!isUpStage) { 291 return true; 292 } 293 auto ftracker = fingerTrackers.find(touchEvent.downTime)->second; 294 TouchEventInfo startEvent = ftracker->GetFingerInfo().GetFirstTouchEventInfo(); 295 VelocityTracker vTracker = ftracker->GetVelocityTracker(); 296 if (startEvent.x - windowBounds.left_ <= NAVI_THRE_D && 297 ftracker->GetMoveDistance() >= NAVI_VERTI_THRE_V) { 298 RemoveTypeJudge(pointerTypeJudgChain_, OP_SWIPE, OP_RECENT, OP_FLING, OP_HOME); 299 return true; 300 } 301 RemoveTypeJudge(pointerTypeJudgChain_, OP_RETURN); 302 return false; 303 } 304 IsSwip(TouchEventInfo & touchEvent)305 bool PointerTracker::IsSwip(TouchEventInfo& touchEvent) // swip 306 { 307 // 滑动类只有起手才能判断 308 if (!isUpStage) { 309 return true; 310 } 311 auto ftracker = fingerTrackers.find(touchEvent.downTime)->second; 312 double mainVelocity = ftracker->GetVelocityTracker().GetMainAxisVelocity(); 313 // 离手v < FLING_THRESHOLD 314 if (mainVelocity >= FLING_THRESHOLD) { 315 RemoveTypeJudge(pointerTypeJudgChain_, OP_SWIPE); 316 return false; 317 } 318 return true; 319 } 320 IsFling(TouchEventInfo & touchEvent)321 bool PointerTracker::IsFling(TouchEventInfo& touchEvent) // fling 322 { 323 // SWIP判断过离手速度 324 return true; 325 } 326 BuildPointerInfo()327 PointerInfo PointerTracker::BuildPointerInfo() 328 { 329 PointerInfo pointerInfo; 330 pointerInfo.SetTouchOpt(pointerTypeJudgChain_[0]); 331 pointerInfo.SetFingerNumber(maxFingerNum); 332 pointerInfo.SetFirstTrackPoint(firstTrackPoint_); 333 for (auto it = fingerTrackers.begin(); it != fingerTrackers.end(); it++) { 334 pointerInfo.AddFingerInfo(it->second->GetFingerInfo()); 335 } 336 auto fastTouch = pointerInfo.GetFingerInfoList()[0].GetLastTouchEventInfo(); 337 auto lastTouch = pointerInfo.GetFingerInfoList()[fingerTrackers.size()-1].GetLastTouchEventInfo(); 338 pointerInfo.SetDuration((lastTouch.GetActionTimeStamp() - fastTouch.GetDownTimeStamp()).count()); 339 if (pointerInfo.GetTouchOpt() == OP_CLICK || pointerInfo.GetTouchOpt() == OP_LONG_CLICK) { 340 std::vector<std::string> names = GetFrontAbility(); 341 pointerInfo.SetBundleName(names[0]); 342 pointerInfo.SetAbilityName(names[1]); 343 } 344 if (pointerInfo.GetTouchOpt() == OP_DRAG || 345 pointerInfo.GetTouchOpt() == OP_SWIPE || 346 pointerInfo.GetTouchOpt() == OP_FLING) { 347 // 平均方向->向量相加 348 Offset avgDirection; 349 int addStepLength = 0; 350 double addVelocity = 0.0; 351 for (auto it = fingerTrackers.begin(); it != fingerTrackers.end(); it++) { 352 avgDirection += it->second->GetFingerInfo().GetDirection(); 353 addStepLength += it->second->GetVelocityTracker().GetStepLength(); 354 addVelocity += it->second->GetFingerInfo().GetVelocity(); 355 } 356 pointerInfo.SetAvgDirection(avgDirection); 357 pointerInfo.SetAvgStepLength(addStepLength/fingerTrackers.size()); 358 double avgVelocity = addVelocity/fingerTrackers.size(); 359 pointerInfo.SetAvgVelocity(avgVelocity); 360 } 361 return pointerInfo; 362 } 363 364 // cout WriteData(PointerInfo pointerInfo,shared_ptr<mutex> & cout_lock)365 std::string PointerTracker::WriteData(PointerInfo pointerInfo, shared_ptr<mutex> &cout_lock) 366 { 367 auto out = pointerInfo.WriteWindowData(); 368 std::lock_guard<mutex> guard(*cout_lock); 369 std::cout << out << std::endl; 370 return out; 371 } 372 373 // record.csv WriteData(PointerInfo pointerInfo,ofstream & outFile,shared_ptr<mutex> & csv_lock)374 nlohmann::json PointerTracker::WriteData(PointerInfo pointerInfo, ofstream& outFile, shared_ptr<mutex> &csv_lock) 375 { 376 auto out = pointerInfo.WriteData(); 377 std::lock_guard<mutex> guard(*csv_lock); 378 if (outFile.is_open()) { 379 outFile << out.dump() << std::endl; 380 } 381 return out; 382 } 383 }