• 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 <chrono>
16 #include <thread>
17 #include "external_calls.h"
18 #include "ui_record.h"
19 
20 namespace OHOS::uitest {
21     using namespace std;
22     using namespace std::chrono;
23     using nlohmann::json;
24 
25     static bool g_uiRecordRun = false;
26     std::string ts;
27     std::string savePath;
28     int operationCount = 0;
29     int g_callBackId = -1;
30     int64_t g_downTime = 0;
31     static std::shared_ptr<InputEventCallback> g_uiCallBackInstance = nullptr;
32     const std::map <int32_t, TouchOpt> SPECIAL_KET_MAP = {
33         {MMI::KeyEvent::KEYCODE_BACK, TouchOpt::OP_RETURN},
34         {MMI::KeyEvent::KEYCODE_HOME, TouchOpt::OP_HOME},
35     };
36 
37     static std::vector<SubscribeKeyevent> NEED_SUBSCRIBE_KEY = {
38         {MMI::KeyEvent::KEYCODE_POWER, true, 0}, // 电源键按下订阅
39         {MMI::KeyEvent::KEYCODE_POWER, false, 0}, // 电源键抬起订阅
40         {MMI::KeyEvent::KEYCODE_VOLUME_UP, true, 0}, // 音量UP键按下订阅
41         {MMI::KeyEvent::KEYCODE_VOLUME_DOWN, true, 0}, // 音量DOWN键按下订阅
42         {MMI::KeyEvent::KEYCODE_ESCAPE, true, 0}, // esc键按下订阅
43         {MMI::KeyEvent::KEYCODE_ESCAPE, false, 0}, // esc键抬起订阅
44         {MMI::KeyEvent::KEYCODE_F1, true, 0}, // f1键按下订阅
45         {MMI::KeyEvent::KEYCODE_F1, false, 0}, // f1键抬起订阅
46         {MMI::KeyEvent::KEYCODE_ALT_LEFT, true, 0}, // alt-left键按下订阅
47         {MMI::KeyEvent::KEYCODE_ALT_LEFT, false, 0}, // alt-left键抬起订阅
48         {MMI::KeyEvent::KEYCODE_ALT_RIGHT, true, 0}, // alt-right键按下订阅
49         {MMI::KeyEvent::KEYCODE_ALT_RIGHT, false, 0}, // alt-right键抬起订阅
50         {MMI::KeyEvent::KEYCODE_FN, true, 0}, // fn键按下订阅
51         {MMI::KeyEvent::KEYCODE_FN, false, 0}, // fn键抬起订阅
52     };
53     enum MessageStage : uint8_t {
54         StartUp = 0, StartEnd, StartFindWidgets, FindWidgetsEnd
55     };
56 
57     inline const std::string InputEventCallback::DEFAULT_DIR = "/data/local/tmp";
58     std::string EventData::defaultDir = InputEventCallback::DEFAULT_DIR;
59 
SpecialKeyMapExistKey(int32_t keyCode,TouchOpt & touchop)60     bool SpecialKeyMapExistKey(int32_t keyCode, TouchOpt &touchop)
61     {
62         auto iter = SPECIAL_KET_MAP.find(keyCode);
63         if (iter!=SPECIAL_KET_MAP.end()) {
64             touchop = iter->second;
65             return true;
66         }
67         return false;
68     }
69 
70     // KEY订阅模板函数
KeyEventSubscribeTemplate(SubscribeKeyevent & subscribeKeyevent)71     void InputEventCallback::KeyEventSubscribeTemplate(SubscribeKeyevent& subscribeKeyevent)
72     {
73         std::set<int32_t> preKeys;
74         std::shared_ptr<MMI::KeyOption> keyOption = std::make_shared<MMI::KeyOption>();
75         keyOption->SetPreKeys(preKeys);
76         keyOption->SetFinalKey(subscribeKeyevent.keyCode);
77         keyOption->SetFinalKeyDown(subscribeKeyevent.isDown);
78         keyOption->SetFinalKeyDownDuration(KEY_DOWN_DURATION);
79         subscribeKeyevent.subId = MMI::InputManager::GetInstance()->SubscribeKeyEvent(keyOption,
80             [this](std::shared_ptr<MMI::KeyEvent> keyEvent) {
81             OnInputEvent(keyEvent);
82         });
83     }
84 
85     // key订阅
SubscribeMonitorInit()86     void InputEventCallback::SubscribeMonitorInit()
87     {
88         for (size_t i = 0; i < NEED_SUBSCRIBE_KEY.size(); i++) {
89             KeyEventSubscribeTemplate(NEED_SUBSCRIBE_KEY[i]);
90         }
91     }
92     // key取消订阅
SubscribeMonitorCancel()93     void InputEventCallback::SubscribeMonitorCancel()
94     {
95         MMI::InputManager* inputManager = MMI::InputManager::GetInstance();
96         if (inputManager == nullptr) {
97             return;
98         }
99         for (size_t i = 0; i < NEED_SUBSCRIBE_KEY.size(); i++) {
100             if (NEED_SUBSCRIBE_KEY[i].subId >= 0) {
101                 inputManager->UnsubscribeKeyEvent(NEED_SUBSCRIBE_KEY[i].subId);
102             }
103         }
104     }
105 
ReadEventLine()106     void EventData::ReadEventLine()
107     {
108         std::ifstream inFile(defaultDir + "/" + "record.csv");
109         std::string line;
110         if (inFile.is_open()) {
111             while (std::getline(inFile, line)) {
112                 std::cout << line << std::endl;
113             }
114             inFile.close();
115         }
116     }
WriteLayout(nlohmann::json layout) const117     void InputEventCallback::WriteLayout(nlohmann::json layout) const
118     {
119         savePath = "/data/local/tmp/layout_" + ts + "_" + to_string(operationCount) + ".json";
120         ofstream fout;
121         fout.open(savePath, ios::out | ios::binary);
122         if (!fout) {
123             LOG_E("Layout save to %{public}s failed: open failed!", savePath.c_str());
124             fout.close();
125         } else {
126             fout << layout.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace);
127             fout.close();
128             std::cout << "Layout saved to :" + savePath << std::endl;
129             LOG_I("Layout saved to : %{public}s", savePath.c_str());
130         }
131     }
132 
OnInputEventDown(std::shared_ptr<MMI::KeyEvent> keyEvent,KeyEventInfo & info) const133     void InputEventCallback::OnInputEventDown(std::shared_ptr<MMI::KeyEvent> keyEvent, KeyEventInfo &info) const
134     {
135         // 三键以上的同时按键无效
136         if (keyeventTracker_.GetInfos().size() >= KeyeventTracker::MAX_COMBINATION_SIZE) {
137             LOG_I("More than three keys are invalid at the same time");
138             std::cout << "More than three keys are invalid at the same time" << std::endl;
139             return;
140         }
141         if (KeyeventTracker::IsCombinationKey(info.GetKeyCode())) {
142             keyeventTracker_.SetNeedRecord(true);
143             keyeventTracker_.AddDownKeyEvent(info);
144         } else {
145             keyeventTracker_.SetNeedRecord(false);
146             KeyeventTracker snapshootKeyTracker = keyeventTracker_.GetSnapshootKey(info);
147             if (recordMode.terminalCout) {
148                 snapshootKeyTracker.WriteSingleData(info, cout_lock);
149             }
150             auto json = snapshootKeyTracker.WriteSingleData(info, outFile, csv_lock);
151             DoAbcCallBack(json);
152         }
153     }
154 
OnInputEventUp(std::shared_ptr<MMI::KeyEvent> keyEvent,KeyEventInfo & info) const155     void InputEventCallback::OnInputEventUp(std::shared_ptr<MMI::KeyEvent> keyEvent, KeyEventInfo &info) const
156     {
157         if (recordMode.saveLayout) {
158             // 抬手时记录跳转后页面控件树
159             DumpOption option;
160             auto layout = nlohmann::json();
161             ApiCallErr err(NO_ERROR);
162             driver.DumpUiHierarchy(layout, option, err);
163             operationCount++;
164             if (recordMode.saveLayout && err.code_ == NO_ERROR) {
165                 WriteLayout(layout);
166             } else if (err.code_ != NO_ERROR) {
167                 LOG_E("DumpLayout failed");
168             }
169         }
170         if (!KeyeventTracker::IsCombinationKey(info.GetKeyCode())) {
171             KeyeventTracker snapshootKeyTracker = keyeventTracker_.GetSnapshootKey(info);
172             if (recordMode.terminalCout) {
173                 snapshootKeyTracker.WriteSingleData(info, cout_lock);
174             }
175             auto json = snapshootKeyTracker.WriteSingleData(info, outFile, csv_lock, savePath);
176             DoAbcCallBack(json);
177         }
178         if (keyeventTracker_.IsNeedRecord()) {
179             keyeventTracker_.SetNeedRecord(false);
180             KeyeventTracker snapshootKeyTracker = keyeventTracker_.GetSnapshootKey(info);
181             if (recordMode.terminalCout) {
182                 snapshootKeyTracker.WriteCombinationData(cout_lock);
183             }
184             auto json = snapshootKeyTracker.WriteCombinationData(outFile, csv_lock, savePath);
185             DoAbcCallBack(json);
186         }
187         keyeventTracker_.AddUpKeyEvent(info);
188     }
189 
190     // KEY_ACTION
OnInputEvent(std::shared_ptr<MMI::KeyEvent> keyEvent) const191     void InputEventCallback::OnInputEvent(std::shared_ptr<MMI::KeyEvent> keyEvent) const
192     {
193         if (dealSpecialKey(keyEvent)) {
194             return;
195         }
196         touchTime = GetCurrentMillisecond();
197         auto item = keyEvent->GetKeyItem(keyEvent->GetKeyCode());
198         if (!item) {
199             std::cout << "GetPointerItem Fail" << std::endl;
200         }
201         KeyEventInfo info;
202         info.SetActionTime(keyEvent->GetActionTime());
203         info.SetKeyCode(keyEvent->GetKeyCode());
204         if (keyEvent->GetKeyAction() == MMI::KeyEvent::KEY_ACTION_DOWN) {
205             OnInputEventDown(keyEvent, info);
206         } else if (keyEvent->GetKeyAction() == MMI::KeyEvent::KEY_ACTION_UP) {
207             OnInputEventUp(keyEvent, info);
208         }
209     }
210 
DoAbcCallBack(nlohmann::json jsonData) const211     void InputEventCallback::DoAbcCallBack(nlohmann::json jsonData) const
212     {
213         if (abcCallBack != nullptr) {
214             auto data = nlohmann::json();
215             data["code"] = MessageStage::FindWidgetsEnd;
216             data["data"] = jsonData;
217             abcCallBack(data);
218         }
219     }
220 
dealSpecialKey(std::shared_ptr<MMI::KeyEvent> keyEvent) const221     bool InputEventCallback::dealSpecialKey(std::shared_ptr<MMI::KeyEvent> keyEvent) const
222     {
223         TouchOpt touchOpt;
224         if (SpecialKeyMapExistKey(keyEvent->GetKeyCode(), touchOpt)) {
225             if (keyEvent->GetKeyAction() == MMI::KeyEvent::KEY_ACTION_DOWN) {
226                 return true;
227             } else if (keyEvent->GetKeyAction() == MMI::KeyEvent::KEY_ACTION_UP) {
228                 PointerInfo& info = pointerTracker_.GetSnapshootPointerInfo();
229                 info.SetTouchOpt(touchOpt);
230                 findWidgetsAllow_ = true;
231                 widgetsCon.notify_all();
232                 pointerTracker_.SetLastClickInTracker(false);
233                 return true;
234             }
235         }
236         return false;
237     }
238 
239     // AXIS_ACTION
OnInputEvent(std::shared_ptr<MMI::AxisEvent> axisEvent) const240     void InputEventCallback::OnInputEvent(std::shared_ptr<MMI::AxisEvent> axisEvent) const {
241     }
242 
TimerReprintClickFunction()243     void InputEventCallback::TimerReprintClickFunction()
244     {
245         while (g_uiRecordRun) {
246             std::unique_lock <std::mutex> clickLck(g_clickMut);
247             while (!isLastClick_) {
248                 clickCon.wait(clickLck);
249             }
250             std::this_thread::sleep_for(
251                 std::chrono::milliseconds(
252                     static_cast<int>(PointerTracker::INTERVAL_THRESHOLD * VelocityTracker::TIME_INDEX)));
253             if (isLastClick_) {
254                 isLastClick_ = false;
255                 pointerTracker_.SetLastClickInTracker(false);
256                 findWidgetsAllow_ = true;
257                 widgetsCon.notify_all();
258             }
259         }
260     }
261 
TimerTouchCheckFunction()262     void InputEventCallback::TimerTouchCheckFunction()
263     {
264         while (g_uiRecordRun) {
265             unique_lock<mutex> lock(timerMut);
266             timerCon.wait_for(lock, std::chrono::milliseconds(TIMEINTERVAL), [this] {return stopFlag;});
267             int currentTime = GetCurrentMillisecond();
268             int diff = currentTime - touchTime;
269             if (diff >= TIMEINTERVAL) {
270                 std::cout << "No operation detected for 5 seconds, press ctrl + c to save this file?" << std::endl;
271             }
272         }
273     }
274 
FindWidgetsandWriteData()275     void InputEventCallback::FindWidgetsandWriteData()
276     {
277         while (g_uiRecordRun) {
278             std::unique_lock<std::mutex> widgetsLck(widgetsMut);
279             while (!findWidgetsAllow_) {
280                 widgetsCon.wait(widgetsLck);
281             }
282             if (!g_uiRecordRun) {
283                 return;
284             }
285             if (abcCallBack != nullptr) {
286                 auto data = nlohmann::json();
287                 data["code"] = MessageStage::StartFindWidgets;
288                 abcCallBack(data);
289             }
290             std::this_thread::sleep_for(std::chrono::milliseconds(VelocityTracker::TIME_INDEX)); // 确保界面已更新
291             ApiCallErr err(NO_ERROR);
292             auto layout = nlohmann::json();
293             DumpOption option;
294             driver.DumpUiHierarchy(layout, option, err);
295             operationCount++;
296             if (recordMode.saveLayout && err.code_ == NO_ERROR) {
297                 WriteLayout(layout);
298             } else if (err.code_ != NO_ERROR) {
299                 LOG_E("DumpLayout failed");
300             }
301             selector.SetWantMulti(true);
302             driver.FindWidgets(selector, rev, err, true);
303             PointerInfo& info = pointerTracker_.GetSnapshootPointerInfo();
304             info.SetSavePath(savePath);
305             if (recordMode.terminalCout) {
306                 pointerTracker_.WriteData(info, cout_lock); // Terminal
307             }
308             auto json = pointerTracker_.WriteData(info, outFile, csv_lock); // csv
309             if (abcCallBack != nullptr) {
310                 auto data = nlohmann::json();
311                 data["code"] = MessageStage::FindWidgetsEnd;
312                 data["data"] = json;
313                 data["layout"] = layout;
314                 abcCallBack(data);
315             }
316             findWidgetsAllow_ = false;
317             widgetsCon.notify_all();
318         }
319     }
320 
WritePointerInfo() const321     void InputEventCallback::WritePointerInfo() const
322     {
323         if (pointerTracker_.IsNeedWrite()) {
324             PointerInfo info = pointerTracker_.GetSnapshootPointerInfo();
325             if (info.GetTouchOpt() != OP_CLICK) {
326                 isLastClick_ = false;
327                 findWidgetsAllow_ = true;
328                 widgetsCon.notify_all();
329             }
330             if (info.GetTouchOpt() == OP_CLICK) {
331                 isLastClick_ = true;
332                 clickCon.notify_all();
333             }
334             pointerTracker_.SetNeedWrite(false);
335         }
336     }
337 
OnInputEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent) const338     void InputEventCallback::OnInputEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent) const
339     {
340         MMI::PointerEvent::PointerItem item;
341         bool result = pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), item);
342         if (!result) {
343             std::cout << "GetPointerItem Fail" << std::endl;
344         }
345         touchTime = GetCurrentMillisecond();
346         TouchEventInfo touchEvent {};
347         if (pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_DOWN) {
348             g_downTime = pointerEvent->GetActionTime();
349         }
350         touchEvent.actionTime = pointerEvent->GetActionTime();
351         touchEvent.downTime = item.GetDownTime() == 0 ? g_downTime : item.GetDownTime();
352         touchEvent.x = item.GetDisplayX();
353         touchEvent.y = item.GetDisplayY();
354         touchEvent.wx = item.GetWindowX();
355         touchEvent.wy = item.GetWindowY();
356         std::chrono::duration<double>  duration = touchEvent.GetActionTimeStamp() - touchEvent.GetDownTimeStamp();
357         touchEvent.durationSeconds = duration.count();
358         if (pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_DOWN) {
359             std::unique_lock<std::mutex> widgetsLck(widgetsMut);
360             while (findWidgetsAllow_) {
361                 widgetsCon.wait(widgetsLck);
362             }
363             if (recordMode.saveWidget) {
364                 touchEvent.attributes = FindWidget(driver, touchEvent.x, touchEvent.y);
365             }
366             pointerTracker_.HandleDownEvent(touchEvent);
367         } else if (pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_MOVE) {
368             pointerTracker_.HandleMoveEvent(touchEvent);
369         } else if (pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_PULL_MOVE) {
370             pointerTracker_.HandleMoveEvent(touchEvent, OP_DRAG);
371         } else if (pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_UP) {
372             if (recordMode.saveWidget)  {
373                 touchEvent.attributes = FindWidget(driver, touchEvent.x, touchEvent.y);
374             }
375             pointerTracker_.HandleUpEvent(touchEvent);
376             WritePointerInfo();
377         } else if (pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_PULL_UP) {
378             if (recordMode.saveWidget) {
379                 touchEvent.attributes = FindWidget(driver, touchEvent.x, touchEvent.y);
380             }
381             pointerTracker_.HandleUpEvent(touchEvent, OP_DRAG);
382             WritePointerInfo();
383         }
384     }
385 
InitReportFolder()386     bool InputEventCallback::InitReportFolder()
387     {
388         if (opendir(DEFAULT_DIR.c_str()) == nullptr) {
389             int ret = mkdir(DEFAULT_DIR.c_str(), S_IROTH | S_IRWXU | S_IRWXG);
390             if (ret != 0) {
391                 std::cerr << "failed to create dir: " << DEFAULT_DIR << std::endl;
392                 return false;
393             }
394         }
395         return true;
396     }
397 
InitEventRecordFile()398     bool InputEventCallback::InitEventRecordFile()
399     {
400         if (!InitReportFolder()) {
401             return false;
402         }
403         filePath = DEFAULT_DIR + "/" + "record.csv";
404         outFile.open(filePath, std::ios_base::out | std::ios_base::trunc);
405         if (!outFile) {
406             std::cerr << "Failed to create csv file at:" << filePath << std::endl;
407             return false;
408         }
409         std::cout << "The result will be written in csv file at location: " << filePath << std::endl;
410         return true;
411     }
RecordInitEnv(const RecordOption & option)412     void InputEventCallback::RecordInitEnv(const RecordOption &option)
413     {
414         recordMode = option;
415         ApiCallErr err(NO_ERROR);
416         selector.SetWantMulti(true);
417         driver.FindWidgets(selector, rev, err, true);
418         auto screenSize = driver.GetDisplaySize(err);
419         Rect windowBounds = Rect(0, screenSize.px_, 0,  screenSize.py_);
420         std::cout<< "windowBounds : (" << windowBounds.left_ << ","
421                 << windowBounds.top_ << "," << windowBounds.right_ << ","
422                 << windowBounds.bottom_ << ")" << std::endl;
423         pointerTracker_.SetWindow(windowBounds);
424         std::vector<std::string> names = GetFrontAbility();
425         std::cout << "Current ForAbility :" << names[ZERO] << ", " << names[ONE] << std::endl;
426         if (outFile.is_open()) {
427             outFile << "windowBounds" << ',';
428             outFile << windowBounds.left_ << ',';
429             outFile << windowBounds.top_ << ',';
430             outFile << windowBounds.right_ << ',';
431             outFile << windowBounds.bottom_ << ',';
432             outFile << "0,0,0,0,,,,,,,";
433             outFile << names[ZERO] << ',';
434             outFile << names[ONE] << ',' << std::endl;
435         }
436     }
437 
UiDriverRecordStart(RecordOption modeOpt)438     int32_t UiDriverRecordStart(RecordOption modeOpt)
439     {
440         g_uiCallBackInstance = std::make_shared<InputEventCallback>();
441         return UiDriverRecordStartTemplate(modeOpt);
442     }
443 
UiDriverRecordStart(std::function<void (nlohmann::json)> handler,std::string modeOpt)444     int32_t UiDriverRecordStart(std::function<void(nlohmann::json)> handler,  std::string modeOpt)
445     {
446         g_uiCallBackInstance = std::make_shared<InputEventCallback>();
447         g_uiCallBackInstance->SetAbcCallBack(handler);
448         RecordOption opt;
449         if (modeOpt == "point") {
450             opt.saveWidget = false;
451         }
452         return UiDriverRecordStartTemplate(opt);
453     }
454 
UiDriverRecordStartTemplate(RecordOption modeOpt)455     int32_t UiDriverRecordStartTemplate(RecordOption modeOpt)
456     {
457         if (g_uiCallBackInstance == nullptr) {
458             std::cout << "nullptr" << std::endl;
459             return OHOS::ERR_INVALID_VALUE;
460         }
461         auto abcCallBack = g_uiCallBackInstance->GetAbcCallBack();
462         if (abcCallBack != nullptr) {
463             auto data = nlohmann::json();
464             data["code"] = MessageStage::StartUp;
465             abcCallBack(data);
466         }
467         g_uiCallBackInstance->RecordInitEnv(modeOpt);
468         if (!g_uiCallBackInstance->InitEventRecordFile()) {
469             return OHOS::ERR_INVALID_VALUE;
470         }
471         // 按键订阅
472         g_uiCallBackInstance->SubscribeMonitorInit();
473         g_callBackId = MMI::InputManager::GetInstance()->AddMonitor(g_uiCallBackInstance);
474         if (g_callBackId == -1) {
475             std::cout << "Startup Failed!" << std::endl;
476             return OHOS::ERR_INVALID_VALUE;
477         }
478         g_uiRecordRun = true;
479         ts = to_string(GetCurrentMicroseconds());
480         // 补充click打印线程
481         std::thread clickThread(&InputEventCallback::TimerReprintClickFunction, g_uiCallBackInstance);
482         // touch计时线程
483         std::thread toughTimerThread(&InputEventCallback::TimerTouchCheckFunction, g_uiCallBackInstance);
484         // widget&data 线程
485         std::thread dataThread(&InputEventCallback::FindWidgetsandWriteData, g_uiCallBackInstance);
486         std::cout << "Started Recording Successfully..." << std::endl;
487         if (abcCallBack != nullptr) {
488             auto data = nlohmann::json();
489             data["code"] = MessageStage::StartEnd;
490             abcCallBack(data);
491         }
492         clickThread.join();
493         toughTimerThread.join();
494         dataThread.join();
495         return OHOS::ERR_OK;
496     }
497 
UiDriverRecordStop()498     void UiDriverRecordStop()
499     {
500         g_uiRecordRun = false;
501         if (g_uiCallBackInstance != nullptr) {
502             g_uiCallBackInstance->isLastClick_ = true;
503             g_uiCallBackInstance->findWidgetsAllow_ = true;
504             g_uiCallBackInstance->stopFlag = true;
505             g_uiCallBackInstance->widgetsCon.notify_all();
506             g_uiCallBackInstance->clickCon.notify_all();
507             g_uiCallBackInstance->timerCon.notify_all();
508             g_uiCallBackInstance->SubscribeMonitorCancel();
509             MMI::InputManager::GetInstance()->RemoveMonitor(g_callBackId);
510             g_callBackId = -1;
511             g_uiCallBackInstance = nullptr;
512         }
513     }
514 } // namespace OHOS::uitest
515