• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }