• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 #include "ui_record.h"
16 #include "ability_manager_client.h"
17 
18 using namespace std;
19 using namespace std::chrono;
20 namespace OHOS::uitest {
21     enum TouchOpt : uint8_t {
22         OP_CLICK, OP_LONG_CLICK, OP_DOUBLE_CLICK, OP_SWIPE, OP_DRAG, \
23         OP_FLING, OP_HOME, OP_RECENT, OP_RETURN
24     };
25     std::string g_operationType[9] = { "click", "longClick", "doubleClick", "swipe", "drag", \
26                                        "fling", "home", "recent", "back" };
27     TouchOpt g_touchop = OP_CLICK;
28     VelocityTracker g_velocityTracker;
29     bool g_isClick = false;
30     int g_clickEventCount = 0;
31     constexpr int32_t NAVI_VERTI_THRE_V = 200;
32     constexpr int32_t NAVI_THRE_D = 10;
33     constexpr float MAX_THRESHOLD = 15.0;
34     constexpr float FLING_THRESHOLD = 45.0;
35     constexpr float DURATIOIN_THRESHOLD = 0.6;
36     constexpr float INTERVAL_THRESHOLD = 0.2;
37     constexpr int32_t MaxVelocity = 40000;
38     bool g_isOpDect = false;
39     std::string g_filePath;
40     std::string g_defaultDir = "/data/local/tmp/layout";
41     std::ofstream g_outFile;
42     auto driver = UiDriver();
43     Rect windowBounds = Rect(0, 0, 0, 0);
44     DataWrapper g_dataWrapper;
45 
GetForeAbility()46     std::vector<std::string> GetForeAbility()
47     {
48         std::vector<std::string> elements;
49         auto amcPtr = AAFwk::AbilityManagerClient::GetInstance();
50         if (amcPtr == nullptr) {
51             std::cout<<"AbilityManagerClient is nullptr"<<std::endl;
52             return elements;
53         }
54         auto elementName = amcPtr->GetTopAbility();
55         if (elementName.GetBundleName().empty()) {
56             std::cout<<"GetTopAbility GetBundleName is nullptr"<<std::endl;
57             return elements;
58         }
59         std::string bundleName = elementName.GetBundleName();
60         std::string abilityName = elementName.GetAbilityName();
61         elements.push_back(bundleName);
62         elements.push_back(abilityName);
63         return elements;
64     }
PrintLine(const TouchEventInfo & downEvent,const TouchEventInfo & upEvent,const std::string & actionType)65     void PrintLine(const TouchEventInfo &downEvent, const TouchEventInfo &upEvent, const std::string &actionType)
66     {
67         std::cout << "Interval: " << g_velocityTracker.GetInterVal() << std::endl;
68         std::cout << actionType << ": " ;
69         if (actionType == "fling" || actionType == "swipe" || actionType == "drag") {
70             if (downEvent.attributes.find("id")->second != "" || downEvent.attributes.find("text")->second != "") {
71                 std::cout << "from Widget(id: " << downEvent.attributes.find("id")->second << ", "
72                             << "type: " << downEvent.attributes.find("type")->second << ", "
73                             << "text: " << downEvent.attributes.find("text")->second << ") " << std::endl;
74             } else {
75                 std::cout << "from Point(x:" << downEvent.x << ", y:" << downEvent.y
76                             << ") to Point(x:" << upEvent.x << ", y:" << upEvent.y << ") " << std::endl;
77             }
78             if (actionType == "fling" || actionType == "swipe") {
79                 std::cout << "Off-hand speed:" << g_velocityTracker.GetMainVelocity() << ", "
80                             << "Step length:" << g_velocityTracker.GetStepLength() << std::endl;
81             }
82         } else if (actionType == "click" || actionType == "longClick" || actionType == "doubleClick") {
83             std::cout << actionType << ": " ;
84             if (downEvent.attributes.find("id")->second != "" || downEvent.attributes.find("text")->second != "") {
85                 std::cout << " at Widget( id: " << downEvent.attributes.find("id")->second << ", "
86                         << "text: " << downEvent.attributes.find("text")->second << ", "
87                         << "type: " << downEvent.attributes.find("type")->second<< ") "<< std::endl;
88             } else {
89                 std::cout <<" at Point(x:" << downEvent.x << ", y:" << downEvent.y << ") "<< std::endl;
90             }
91         } else {
92             std::cout << std::endl;
93         }
94     }
CommonPrintLine(TouchEventInfo & downEvent,TouchEventInfo & upEvent,const std::string & actionType)95     void CommonPrintLine(TouchEventInfo &downEvent, TouchEventInfo &upEvent, const std::string &actionType)
96     {
97         std::cout << " PointerEvent:" << g_operationType[g_touchop]
98                     << " X_posi:" << g_velocityTracker.GetFirstTrackPoint().x
99                     << " Y_posi:" << g_velocityTracker.GetFirstTrackPoint().y
100                     << " X2_posi:" << g_velocityTracker.GetLastTrackPoint().x
101                     << " Y2_posi:" << g_velocityTracker.GetLastTrackPoint().y
102                     << " Interval:" << g_velocityTracker.GetInterVal()
103                     << " Step:" << g_velocityTracker.GetStepLength()
104                     << " Velocity:" << g_velocityTracker.GetMainVelocity()
105                     << " Max_Velocity:" << MaxVelocity
106                     << std::endl;
107     }
WriteEventData(const VelocityTracker & velocityTracker,const std::string & actionType)108     void EventData::WriteEventData(const VelocityTracker &velocityTracker, const std::string &actionType)
109     {
110         v = velocityTracker;
111         action = actionType;
112         TouchEventInfo downEvent = v.GetFirstTrackPoint();
113         TouchEventInfo upEvent = v.GetLastTrackPoint();
114         if (g_recordMode == "point") {
115             CommonPrintLine(downEvent, upEvent, action);
116         } else {
117             PrintLine(downEvent, upEvent, action);
118         }
119         if (g_outFile.is_open()) {
120             g_outFile << actionType << ',';
121             g_outFile << downEvent.x << ',';
122             g_outFile << downEvent.y << ',';
123             g_outFile << upEvent.x << ',';
124             g_outFile << upEvent.y << ',';
125             g_outFile << v.GetInterVal() << ',';
126             g_outFile << v.GetStepLength() << ',';
127             g_outFile << v.GetMainVelocity() << ',';
128             g_outFile << MaxVelocity << ',';
129             if (g_recordMode == "point") {
130                 g_outFile << ",,,,,,,,";
131             } else {
132                 g_outFile << downEvent.attributes.find("id")->second << ',';
133                 g_outFile << downEvent.attributes.find("type")->second << ',';
134                 g_outFile << downEvent.attributes.find("text")->second << ',';
135                 if (actionType == "drag") {
136                     g_outFile << upEvent.attributes.find("id")->second << ',';
137                     g_outFile << upEvent.attributes.find("type")->second << ',';
138                     g_outFile << upEvent.attributes.find("text")->second << ',';
139                 } else {
140                     g_outFile << ",,,";
141                 }
142                 if (actionType == "click") {
143                     std::vector<std::string> names = GetForeAbility();
144                     g_outFile << names[ZERO] << ',';
145                     g_outFile << names[ONE] << ',';
146                 } else {
147                     g_outFile << ",,";
148                 }
149             }
150             g_outFile << std::endl;
151             if (g_outFile.fail()) {
152                 std::cout<< " outFile failed. " <<std::endl;
153             }
154         } else {
155             std::cout << "outFile is not opened!"<< std::endl;
156         }
157     }
ReadEventLine()158     void EventData::ReadEventLine()
159     {
160         std::ifstream inFile(g_defaultDir + "/" + "record.csv");
161         enum CaseTypes : uint8_t {
162             OP_TYPE = 0, X_POSI, Y_POSI, X2_POSI, Y2_POSI, INTERVAL, LENGTH, VELO, \
163             MAX_VEL, W_ID, W_TYPE, W_TEXT, W2_ID, W2_TYPE, W2_TEXT, BUNDLE, ABILITY
164         };
165         char buffer[100];
166         while (!inFile.eof()) {
167             inFile >> buffer;
168             std::string delim = ",";
169             auto caseInfo = TestUtils::split(buffer, delim);
170             if (inFile.fail()) {
171                 break;
172             } else {
173                 std::cout << caseInfo[OP_TYPE] << ";"
174                         << std::stoi(caseInfo[X_POSI]) << ";"
175                         << std::stoi(caseInfo[Y_POSI]) << ";"
176                         << std::stoi(caseInfo[X2_POSI]) << ";"
177                         << std::stoi(caseInfo[Y2_POSI]) << ";"
178                         << std::stoi(caseInfo[INTERVAL]) << ";"
179                         << std::stoi(caseInfo[LENGTH]) << ";"
180 						<< std::stoi(caseInfo[VELO]) << ";"
181 						<< std::stoi(caseInfo[MAX_VEL]) << ";"
182                         << caseInfo[W_ID] << ";"
183                         << caseInfo[W_TYPE] << ";"
184                         << caseInfo[W_TEXT] << ";"
185                         << caseInfo[W2_ID] << ";"
186                         << caseInfo[W2_TYPE] << ";"
187                         << caseInfo[W2_TEXT] << ";"
188                         << caseInfo[BUNDLE] << ";"
189                         << caseInfo[ABILITY] << ";"
190 						<< std::endl;
191             }
192             int gTimeIndex = 1000;
193             usleep(std::stoi(caseInfo[INTERVAL]) * gTimeIndex);
194         }
195     }
SetEventData(EventData & eventData)196     void SetEventData(EventData &eventData)
197     {
198         eventData.WriteEventData(g_velocityTracker, g_operationType[g_touchop]);
199     }
SaveEventData()200     void SaveEventData()
201     {
202         g_dataWrapper.ProcessData(SetEventData);
203     }
OnInputEvent(std::shared_ptr<MMI::KeyEvent> keyEvent) const204     void InputEventCallback::OnInputEvent(std::shared_ptr<MMI::KeyEvent> keyEvent) const
205     {
206         if (keyEvent->GetKeyCode() == KEYCODE_BACK) {
207             g_touchop = OP_RETURN;
208         }
209         std::thread t(SaveEventData);
210         t.join();
211     }
HandleDownEvent(TouchEventInfo & event) const212     void InputEventCallback::HandleDownEvent(TouchEventInfo& event) const
213     {
214         if (g_recordMode != "point") {
215             event.attributes = FindWidget(driver, event.x, event.y).GetAttrMap();
216         }
217         g_velocityTracker.UpdateTouchEvent(event, false);
218     }
HandleMoveEvent(const TouchEventInfo & event) const219     void InputEventCallback::HandleMoveEvent(const TouchEventInfo& event) const
220     {
221         g_velocityTracker.UpdateTouchEvent(event, false);
222         if (g_velocityTracker.GetDurationTime() >= DURATIOIN_THRESHOLD &&
223            g_velocityTracker.GetMoveDistance() < MAX_THRESHOLD) {
224             g_touchop = OP_LONG_CLICK;
225             g_isOpDect = true;
226             g_isClick = false;
227         }
228     }
HandleUpEvent(const TouchEventInfo & event) const229     void InputEventCallback::HandleUpEvent(const TouchEventInfo& event) const
230     {
231         g_velocityTracker.UpdateTouchEvent(event, true);
232         int moveDistance = g_velocityTracker.GetMoveDistance();
233         if (!g_isOpDect) {
234             double mainVelocity = g_velocityTracker.GetMainAxisVelocity();
235             if (g_velocityTracker.GetDurationTime() >= DURATIOIN_THRESHOLD &&
236                 moveDistance < MAX_THRESHOLD) {
237                 g_touchop = OP_LONG_CLICK;
238                 g_isClick = false;
239             } else if (moveDistance > MAX_THRESHOLD) {
240                 int startY = g_velocityTracker.GetFirstTrackPoint().y;
241                 Axis maxAxis_ = g_velocityTracker.GetMaxAxis();
242                 if (fabs(mainVelocity) > FLING_THRESHOLD) {
243                     g_touchop = OP_FLING;
244                     g_isClick = false;
245                     if ((windowBounds.bottom_ - startY <= NAVI_THRE_D) && (maxAxis_ == Axis::VERTICAL) && \
246 						(moveDistance >= NAVI_VERTI_THRE_V)) {
247                         g_touchop = OP_HOME;
248                     }
249                 } else {
250                     g_touchop = OP_SWIPE;
251                     g_isClick = false;
252                     if ((windowBounds.bottom_ - startY <= NAVI_THRE_D) && (maxAxis_ == Axis::VERTICAL) && \
253 						(moveDistance >= NAVI_VERTI_THRE_V)) {
254                         g_touchop = OP_RECENT;
255                     }
256                 }
257                 g_velocityTracker.UpdateStepLength();
258             } else {
259                 // up-down>=0.6s => longClick
260                 if (g_isClick && g_velocityTracker.GetInterVal() < INTERVAL_THRESHOLD) {
261                     // if lastOp is click && downTime-lastDownTime < 0.1 => double_click
262                     g_touchop = OP_DOUBLE_CLICK;
263                     g_isClick = false;
264                 } else {
265                     g_touchop = OP_CLICK;
266                     g_isClick = true;
267                 }
268             }
269         } else if (moveDistance >= MAX_THRESHOLD) {
270             g_touchop = OP_DRAG;
271             g_isClick = false;
272         }
273         if (g_touchop == OP_DRAG && g_recordMode != "point") {
274             g_velocityTracker.GetLastTrackPoint().attributes = FindWidget(driver, event.x, event.y).GetAttrMap();
275         }
276         std::thread t(SaveEventData);
277         t.join();
278         g_velocityTracker.Resets();
279         g_isOpDect = false;
280     }
OnInputEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent) const281     void InputEventCallback::OnInputEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent) const
282     {
283         MMI::PointerEvent::PointerItem item;
284         bool result = pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), item);
285         if (!result) {
286             std::cout << "GetPointerItem Fail" << std::endl;
287         }
288         TouchEventInfo touchEvent {};
289         g_touchTime = GetCurrentMillisecond();
290         TimeStamp t {std::chrono::duration_cast<TimeStamp::duration>( \
291                      std::chrono::nanoseconds(pointerEvent->GetActionTime()*1000))};
292         touchEvent.time = t;
293         touchEvent.x = item.GetDisplayX();
294         touchEvent.y = item.GetDisplayY();
295         touchEvent.wx = item.GetWindowX();
296         touchEvent.wy = item.GetWindowY();
297         if (pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_DOWN) {
298             HandleDownEvent(touchEvent);
299         } else if (pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_MOVE) {
300             HandleMoveEvent(touchEvent);
301         } else if (pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_UP) {
302             HandleUpEvent(touchEvent);
303         }
304     }
GetPtr()305     std::shared_ptr<InputEventCallback> InputEventCallback::GetPtr()
306     {
307         return std::make_shared<InputEventCallback>();
308     }
InitReportFolder()309     bool InitReportFolder()
310     {
311         if (opendir(g_defaultDir.c_str()) == nullptr) {
312             int ret = mkdir(g_defaultDir.c_str(), S_IROTH | S_IRWXU | S_IRWXG);
313             if (ret != 0) {
314                 std::cerr << "failed to create dir: " << g_defaultDir << std::endl;
315                 return false;
316             }
317         }
318         return true;
319     }
InitEventRecordFile()320     bool InitEventRecordFile()
321     {
322         if (!InitReportFolder()) {
323             return false;
324         }
325         g_filePath = g_defaultDir + "/" + "record.csv";
326         g_outFile.open(g_filePath, std::ios_base::out | std::ios_base::trunc);
327         if (!g_outFile) {
328             std::cerr << "Failed to create csv file at:" << g_filePath << std::endl;
329             return false;
330         }
331         std::cout << "The result will be written in csv file at location: " << g_filePath << std::endl;
332         return true;
333     }
RecordInitEnv(const std::string & modeOpt)334     void RecordInitEnv(const std::string &modeOpt)
335     {
336         g_recordMode = modeOpt;
337         g_velocityTracker.TrackResets();
338         ApiCallErr err(NO_ERROR);
339         auto selector = WidgetSelector();
340         vector<std::unique_ptr<Widget>> rev;
341         driver.FindWidgets(selector, rev, err, true);
342         auto tree = driver.GetWidgetTree();
343         windowBounds = tree->GetRootWidget()->GetBounds();
344         std::cout<< "windowBounds : (" << windowBounds.left_ << ","
345                 << windowBounds.top_ << "," << windowBounds.right_ << ","
346                 << windowBounds.bottom_ << ")" << std::endl;
347         std::vector<std::string> names = GetForeAbility();
348         std::cout << "Current ForAbility :" << names[ZERO] << ", " << names[ONE] << std::endl;
349         if (g_outFile.is_open()) {
350             g_outFile << "windowBounds" << ',';
351             g_outFile << windowBounds.left_ << ',';
352             g_outFile << windowBounds.top_ << ',';
353             g_outFile << windowBounds.right_ << ',';
354             g_outFile << windowBounds.bottom_ << ',';
355             g_outFile << "0,0,0,0,,,,,,,";
356             g_outFile << names[ZERO] << ',';
357             g_outFile << names[ONE] << ',' << std::endl;
358         }
359     }
360 } // namespace OHOS::uitest