1 /* 2 * Copyright (c) 2021-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 16 #include <atomic> 17 #include <chrono> 18 #include <fstream> 19 #include <memory> 20 #include <iostream> 21 #include <thread> 22 #include <utility> 23 #include <condition_variable> 24 #include <sys/mman.h> 25 #ifdef HIDUMPER_ENABLED 26 #include <iservice_registry.h> 27 #include <system_ability_load_callback_stub.h> 28 #include "idump_broker.h" 29 #include "dump_broker_proxy.h" 30 #include "system_ability_definition.h" 31 #endif 32 #include "accessibility_event_info.h" 33 #include "accessibility_ui_test_ability.h" 34 #include "ability_manager_client.h" 35 #include "display_manager.h" 36 #include "screen_manager.h" 37 #include "input_manager.h" 38 #include "png.h" 39 #include "wm_common.h" 40 #include "element_node_iterator_impl.h" 41 #include "system_ui_controller.h" 42 #include "test_server_client.h" 43 #include "test_server_error_code.h" 44 #include "parameters.h" 45 #include "image_packer.h" 46 47 using namespace std; 48 using namespace chrono; 49 50 namespace OHOS::uitest { 51 using namespace std; 52 using namespace nlohmann; 53 using namespace OHOS::MMI; 54 using namespace OHOS::Accessibility; 55 using namespace OHOS::Rosen; 56 using namespace OHOS::Media; 57 using namespace OHOS::HiviewDFX; 58 using namespace OHOS; 59 60 class UiEventMonitor final : public AccessibleAbilityListener { 61 public: 62 virtual ~UiEventMonitor() override = default; 63 64 void OnAbilityConnected() override; 65 66 void OnAbilityDisconnected() override; 67 68 void OnAccessibilityEvent(const AccessibilityEventInfo &eventInfo) override; 69 70 void SetOnAbilityConnectCallback(function<void()> onConnectCb); 71 72 void SetOnAbilityDisConnectCallback(function<void()> onDisConnectCb); 73 OnKeyPressEvent(const shared_ptr<MMI::KeyEvent> & keyEvent)74 bool OnKeyPressEvent(const shared_ptr<MMI::KeyEvent> &keyEvent) override 75 { 76 return false; 77 } 78 79 uint64_t GetLastEventMillis(); 80 81 bool WaitEventIdle(uint32_t idleThresholdMs, uint32_t timeoutMs); 82 83 void WaitScrollCompelete(); 84 85 void RegisterUiEventListener(shared_ptr<UiEventListener> listerner); 86 87 private: 88 function<void()> onConnectCallback_ = nullptr; 89 function<void()> onDisConnectCallback_ = nullptr; 90 atomic<uint64_t> lastEventMillis_ = 0; 91 atomic<uint64_t> lastScrollBeginEventMillis_ = 0; 92 atomic<bool> scrollCompelete_ = true; 93 vector<shared_ptr<UiEventListener>> listeners_; 94 }; 95 96 struct EventSpec { 97 std::string_view componentTyep; 98 int32_t eventType; 99 std::string_view event; 100 }; 101 102 const std::map<char, int32_t> SingleKeySymbalMap = { 103 {' ', OHOS::MMI::KeyEvent::KEYCODE_SPACE}, 104 {'`', OHOS::MMI::KeyEvent::KEYCODE_GRAVE}, 105 {'[', OHOS::MMI::KeyEvent::KEYCODE_LEFT_BRACKET}, 106 {']', OHOS::MMI::KeyEvent::KEYCODE_RIGHT_BRACKET}, 107 {'\\', OHOS::MMI::KeyEvent::KEYCODE_BACKSLASH}, 108 {',', OHOS::MMI::KeyEvent::KEYCODE_COMMA}, 109 {';', OHOS::MMI::KeyEvent::KEYCODE_SEMICOLON}, 110 {'\'', OHOS::MMI::KeyEvent::KEYCODE_APOSTROPHE}, 111 {'/', OHOS::MMI::KeyEvent::KEYCODE_SLASH}, 112 {'*', OHOS::MMI::KeyEvent::KEYCODE_NUMPAD_MULTIPLY}, 113 {'-', OHOS::MMI::KeyEvent::KEYCODE_MINUS}, 114 {'.', OHOS::MMI::KeyEvent::KEYCODE_PERIOD}, 115 {'=', OHOS::MMI::KeyEvent::KEYCODE_EQUALS} 116 }; 117 118 const std::map<char, int32_t> MultiKeySymbalMap = { 119 {'~', OHOS::MMI::KeyEvent::KEYCODE_GRAVE}, 120 {'!', OHOS::MMI::KeyEvent::KEYCODE_1}, 121 {'@', OHOS::MMI::KeyEvent::KEYCODE_2}, 122 {'#', OHOS::MMI::KeyEvent::KEYCODE_3}, 123 {'$', OHOS::MMI::KeyEvent::KEYCODE_4}, 124 {'%', OHOS::MMI::KeyEvent::KEYCODE_5}, 125 {'^', OHOS::MMI::KeyEvent::KEYCODE_6}, 126 {'&', OHOS::MMI::KeyEvent::KEYCODE_7}, 127 {'(', OHOS::MMI::KeyEvent::KEYCODE_9}, 128 {')', OHOS::MMI::KeyEvent::KEYCODE_0}, 129 {'+', OHOS::MMI::KeyEvent::KEYCODE_EQUALS}, 130 {'_', OHOS::MMI::KeyEvent::KEYCODE_MINUS}, 131 {':', OHOS::MMI::KeyEvent::KEYCODE_SEMICOLON}, 132 {'"', OHOS::MMI::KeyEvent::KEYCODE_APOSTROPHE}, 133 {'<', OHOS::MMI::KeyEvent::KEYCODE_COMMA}, 134 {'>', OHOS::MMI::KeyEvent::KEYCODE_PERIOD}, 135 {'?', OHOS::MMI::KeyEvent::KEYCODE_SLASH}, 136 {'{', OHOS::MMI::KeyEvent::KEYCODE_LEFT_BRACKET}, 137 {'}', OHOS::MMI::KeyEvent::KEYCODE_RIGHT_BRACKET}, 138 {'|', OHOS::MMI::KeyEvent::KEYCODE_BACKSLASH} 139 }; 140 141 static constexpr EventSpec WATCHED_EVENTS[] = { 142 {"Toast", WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE, "toastShow"}, 143 {"AlertDialog", WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE, "dialogShow"} 144 }; 145 GetWatchedEvent(const AccessibilityEventInfo & eventInfo)146 static std::string GetWatchedEvent(const AccessibilityEventInfo &eventInfo) 147 { 148 auto eventCounts = sizeof(WATCHED_EVENTS) / sizeof(EventSpec); 149 for (unsigned long index = 0; index < eventCounts; index++) { 150 if (WATCHED_EVENTS[index].componentTyep == eventInfo.GetComponentType() && 151 WATCHED_EVENTS[index].eventType == eventInfo.GetWindowContentChangeTypes()) { 152 LOG_W("Capture event: %{public}s", WATCHED_EVENTS[index].event.data()); 153 return string(WATCHED_EVENTS[index].event); 154 } 155 } 156 return "undefine"; 157 } 158 159 // UiEventMonitor instance. 160 static shared_ptr<UiEventMonitor> g_monitorInstance_ = make_shared<UiEventMonitor>(); 161 SetOnAbilityConnectCallback(function<void ()> onConnectCb)162 void UiEventMonitor::SetOnAbilityConnectCallback(function<void()> onConnectCb) 163 { 164 onConnectCallback_ = std::move(onConnectCb); 165 } 166 SetOnAbilityDisConnectCallback(function<void ()> onDisConnectCb)167 void UiEventMonitor::SetOnAbilityDisConnectCallback(function<void()> onDisConnectCb) 168 { 169 onDisConnectCallback_ = std::move(onDisConnectCb); 170 } 171 OnAbilityConnected()172 void UiEventMonitor::OnAbilityConnected() 173 { 174 if (onConnectCallback_ != nullptr) { 175 onConnectCallback_(); 176 } 177 } 178 OnAbilityDisconnected()179 void UiEventMonitor::OnAbilityDisconnected() 180 { 181 if (onDisConnectCallback_ != nullptr) { 182 onDisConnectCallback_(); 183 } 184 } 185 186 // the monitored events 187 static const std::vector<uint32_t> EVENT_MASK = { 188 EventType::TYPE_VIEW_TEXT_UPDATE_EVENT, 189 EventType::TYPE_PAGE_STATE_UPDATE, 190 EventType::TYPE_PAGE_CONTENT_UPDATE, 191 EventType::TYPE_VIEW_SCROLLED_EVENT, 192 EventType::TYPE_WINDOW_UPDATE, 193 EventType::TYPE_PAGE_OPEN 194 }; 195 RegisterUiEventListener(std::shared_ptr<UiEventListener> listerner)196 void UiEventMonitor::RegisterUiEventListener(std::shared_ptr<UiEventListener> listerner) 197 { 198 listeners_.emplace_back(listerner); 199 } 200 OnAccessibilityEvent(const AccessibilityEventInfo & eventInfo)201 void UiEventMonitor::OnAccessibilityEvent(const AccessibilityEventInfo &eventInfo) 202 { 203 auto eventType = eventInfo.GetEventType(); 204 LOG_D("OnEvent:0x%{public}x", eventType); 205 auto capturedEvent = GetWatchedEvent(eventInfo); 206 if (eventType == Accessibility::EventType::TYPE_VIEW_SCROLLED_START) { 207 LOG_I("Capture scroll begin"); 208 scrollCompelete_.store(false); 209 lastScrollBeginEventMillis_.store(GetCurrentMillisecond()); 210 } 211 if (eventType == Accessibility::EventType::TYPE_VIEW_SCROLLED_EVENT) { 212 LOG_I("Capture scroll end"); 213 scrollCompelete_.store(true); 214 } 215 if (capturedEvent != "undefine") { 216 auto bundleName = eventInfo.GetBundleName(); 217 auto contentList = eventInfo.GetContentList(); 218 auto text = !contentList.empty() ? contentList[0] : ""; 219 auto type = eventInfo.GetComponentType(); 220 UiEventSourceInfo uiEventSourceInfo = {bundleName, text, type}; 221 for (auto &listener : listeners_) { 222 listener->OnEvent(capturedEvent, uiEventSourceInfo); 223 } 224 } 225 if (std::find(EVENT_MASK.begin(), EVENT_MASK.end(), eventInfo.GetEventType()) != EVENT_MASK.end()) { 226 lastEventMillis_.store(GetCurrentMillisecond()); 227 } 228 } 229 GetLastEventMillis()230 uint64_t UiEventMonitor::GetLastEventMillis() 231 { 232 if (lastEventMillis_.load() <= 0) { 233 lastEventMillis_.store(GetCurrentMillisecond()); 234 } 235 return lastEventMillis_.load(); 236 } 237 WaitScrollCompelete()238 void UiEventMonitor::WaitScrollCompelete() 239 { 240 if (scrollCompelete_.load()) { 241 return; 242 } 243 auto currentMs = GetCurrentMillisecond(); 244 if (lastScrollBeginEventMillis_.load() <= 0) { 245 lastScrollBeginEventMillis_.store(currentMs); 246 } 247 const auto idleThresholdMs = 10000; 248 static constexpr auto sliceMs = 10; 249 while (currentMs - lastScrollBeginEventMillis_.load() < idleThresholdMs) { 250 if (scrollCompelete_.load()) { 251 return; 252 } 253 this_thread::sleep_for(chrono::milliseconds(sliceMs)); 254 currentMs = GetCurrentMillisecond(); 255 } 256 LOG_E("wait for scrollEnd event timeout."); 257 scrollCompelete_.store(true); 258 return; 259 } 260 WaitEventIdle(uint32_t idleThresholdMs,uint32_t timeoutMs)261 bool UiEventMonitor::WaitEventIdle(uint32_t idleThresholdMs, uint32_t timeoutMs) 262 { 263 const auto currentMs = GetCurrentMillisecond(); 264 if (lastEventMillis_.load() <= 0) { 265 lastEventMillis_.store(currentMs); 266 } 267 if (currentMs - lastEventMillis_.load() >= idleThresholdMs) { 268 return true; 269 } 270 static constexpr auto sliceMs = 10; 271 this_thread::sleep_for(chrono::milliseconds(sliceMs)); 272 if (timeoutMs <= sliceMs) { 273 return false; 274 } 275 return WaitEventIdle(idleThresholdMs, timeoutMs - sliceMs); 276 } 277 SysUiController()278 SysUiController::SysUiController() : UiController() {} 279 ~SysUiController()280 SysUiController::~SysUiController() 281 { 282 DisConnectFromSysAbility(); 283 } 284 Initialize(ApiCallErr & error)285 bool SysUiController::Initialize(ApiCallErr &error) 286 { 287 return this->ConnectToSysAbility(error); 288 } 289 GetFoldArea()290 static Rect GetFoldArea() 291 { 292 auto foldCreaseRegion = DisplayManager::GetInstance().GetCurrentFoldCreaseRegion(); 293 auto areas = foldCreaseRegion->GetCreaseRects(); 294 if (areas.size() == 1) { 295 auto foldArea = *areas.begin(); 296 LOG_D("foldArea, left: %{public}d, top: %{public}d, width: %{public}d, height: %{public}d", 297 foldArea.posX_, foldArea.posY_, foldArea.width_, foldArea.height_); 298 return Rect(foldArea.posX_, foldArea.posX_ + foldArea.width_, 299 foldArea.posY_, foldArea.posY_ + foldArea.height_); 300 } else { 301 LOG_E("Invalid display info."); 302 return Rect(0, 0, 0, 0); 303 } 304 } 305 GetVisibleRect(Rect screenBounds,AccessibilityWindowInfo & node)306 static Rect GetVisibleRect(Rect screenBounds, AccessibilityWindowInfo &node) 307 { 308 auto nodeBounds = node.GetRectInScreen(); 309 auto leftX = nodeBounds.GetLeftTopXScreenPostion(); 310 auto topY = nodeBounds.GetLeftTopYScreenPostion(); 311 auto rightX = nodeBounds.GetRightBottomXScreenPostion(); 312 auto bottomY = nodeBounds.GetRightBottomYScreenPostion(); 313 if (node.GetDisplayId() == VIRTUAL_DISPLAY_ID) { 314 auto foldArea = GetFoldArea(); 315 topY += foldArea.bottom_; 316 bottomY += foldArea.bottom_; 317 } 318 Rect newBounds((leftX < screenBounds.left_) ? screenBounds.left_ : leftX, 319 (rightX > screenBounds.right_) ? screenBounds.right_ : rightX, 320 (topY < screenBounds.top_) ? screenBounds.top_ : topY, 321 (bottomY > screenBounds.bottom_) ? screenBounds.bottom_ : bottomY); 322 return newBounds; 323 } 324 InflateWindowInfo(AccessibilityWindowInfo & node,Window & info)325 static void InflateWindowInfo(AccessibilityWindowInfo& node, Window& info) 326 { 327 info.focused_ = node.IsFocused(); 328 info.actived_ = node.IsActive(); 329 // get bundle name by root node 330 AccessibilityElementInfo element; 331 LOG_D("Start Get Bundle Name by WindowId %{public}d", node.GetWindowId()); 332 if (AccessibilityUITestAbility::GetInstance()->GetRootByWindow(node, element) != RET_OK) { 333 LOG_E("Failed Get Bundle Name by WindowId %{public}d", node.GetWindowId()); 334 } else { 335 std::string app = element.GetBundleName(); 336 LOG_I("End Get Bundle Name by WindowId %{public}d, app is %{public}s", node.GetWindowId(), app.data()); 337 info.bundleName_ = app; 338 const auto foreAbility = AAFwk::AbilityManagerClient::GetInstance()->GetTopAbility(); 339 info.abilityName_ = (app == foreAbility.GetBundleName()) ? foreAbility.GetAbilityName() : ""; 340 info.pagePath_ = (app == foreAbility.GetBundleName()) ? element.GetPagePath() : ""; 341 } 342 info.mode_ = WindowMode::UNKNOWN; 343 auto touchAreas = node.GetTouchHotAreas(); 344 for (auto area : touchAreas) { 345 Rect rect { info.bounds_.left_ + area.GetLeftTopXScreenPostion(), 346 info.bounds_.left_ + area.GetRightBottomXScreenPostion(), 347 info.bounds_.top_ + area.GetLeftTopYScreenPostion(), 348 info.bounds_.top_ + area.GetRightBottomYScreenPostion() }; 349 info.touchHotAreas_.push_back(rect); 350 } 351 const auto origMode = static_cast<OHOS::Rosen::WindowMode>(node.GetWindowMode()); 352 switch (origMode) { 353 case OHOS::Rosen::WindowMode::WINDOW_MODE_FULLSCREEN: 354 info.mode_ = WindowMode::FULLSCREEN; 355 break; 356 case OHOS::Rosen::WindowMode::WINDOW_MODE_SPLIT_PRIMARY: 357 info.mode_ = WindowMode::SPLIT_PRIMARY; 358 break; 359 case OHOS::Rosen::WindowMode::WINDOW_MODE_SPLIT_SECONDARY: 360 info.mode_ = WindowMode::SPLIT_SECONDARY; 361 break; 362 case OHOS::Rosen::WindowMode::WINDOW_MODE_FLOATING: 363 info.mode_ = WindowMode::FLOATING; 364 break; 365 case OHOS::Rosen::WindowMode::WINDOW_MODE_PIP: 366 info.mode_ = WindowMode::PIP; 367 break; 368 default: 369 info.mode_ = WindowMode::UNKNOWN; 370 break; 371 } 372 } 373 GetAamsWindowInfos(vector<AccessibilityWindowInfo> & windows,int32_t displayId)374 static bool GetAamsWindowInfos(vector<AccessibilityWindowInfo> &windows, int32_t displayId) 375 { 376 LOG_D("Get Window root info in display %{public}d", displayId); 377 auto ability = AccessibilityUITestAbility::GetInstance(); 378 g_monitorInstance_->WaitScrollCompelete(); 379 auto ret = ability->GetWindows(displayId, windows); 380 if (ret != RET_OK) { 381 LOG_W("GetWindows in display %{public}d from AccessibilityUITestAbility failed, ret: %{public}d", 382 displayId, ret); 383 return false; 384 } 385 auto hasVirtual = DisplayManager::GetInstance().GetDisplayById(VIRTUAL_DISPLAY_ID) != nullptr; 386 if (hasVirtual && displayId == 0) { 387 vector<AccessibilityWindowInfo> windowsInVirtual; 388 auto ret1 = ability->GetWindows(VIRTUAL_DISPLAY_ID, windowsInVirtual); 389 LOG_D("GetWindows in display 999 from AccessibilityUITestAbility, ret: %{public}d", ret1); 390 for (auto &win : windowsInVirtual) { 391 windows.emplace_back(win); 392 } 393 } 394 if (windows.empty()) { 395 LOG_E("Get Windows in display %{public}d failed", displayId); 396 return false; 397 } 398 sort(windows.begin(), windows.end(), [](auto &w1, auto &w2) -> bool { 399 return w1.GetWindowLayer() > w2.GetWindowLayer(); 400 }); 401 LOG_D("End Get Window root info"); 402 return true; 403 } 404 UpdateWindowAttrs(Window & win,std::vector<Rect> & overplays)405 static void UpdateWindowAttrs(Window &win, std::vector<Rect> &overplays) 406 { 407 for (const auto &overWin : overplays) { 408 Rect intersectionRect{0, 0, 0, 0}; 409 if (RectAlgorithm::ComputeIntersection(win.bounds_, overWin, intersectionRect)) { 410 win.invisibleBoundsVec_.emplace_back(overWin); 411 } 412 } 413 RectAlgorithm::ComputeMaxVisibleRegion(win.bounds_, overplays, win.visibleBounds_); 414 if (win.touchHotAreas_.empty()) { 415 overplays.emplace_back(win.bounds_); 416 } else { 417 std::string touchAreaInfo; 418 for (auto rect : win.touchHotAreas_) { 419 touchAreaInfo += rect.Describe() + " "; 420 overplays.emplace_back(rect); 421 } 422 LOG_I("window %{public}d touchArea: %{public}s", win.id_, touchAreaInfo.c_str()); 423 } 424 if (win.displayId_ == VIRTUAL_DISPLAY_ID) { 425 win.offset_ = Point(0, GetFoldArea().bottom_); 426 } 427 } 428 GetUiWindows(std::map<int32_t,vector<Window>> & out,int32_t targetDisplay)429 void SysUiController::GetUiWindows(std::map<int32_t, vector<Window>> &out, int32_t targetDisplay) 430 { 431 std::lock_guard<std::mutex> dumpLocker(dumpMtx); // disallow concurrent dumpUi 432 ApiCallErr error = ApiCallErr(NO_ERROR); 433 if (!connected_ && !ConnectToSysAbility(error)) { 434 LOG_E("%{public}s", error.message_.c_str()); 435 return; 436 } 437 DisplayManager &dpm = DisplayManager::GetInstance(); 438 auto displayIds = dpm.GetAllDisplayIds(); 439 for (auto displayId : displayIds) { 440 if ((targetDisplay != -1 && targetDisplay != static_cast<int32_t>(displayId)) || 441 displayId == VIRTUAL_DISPLAY_ID) { 442 continue; 443 } 444 vector<AccessibilityWindowInfo> windows; 445 if (!GetAamsWindowInfos(windows, displayId)) { 446 continue; 447 } 448 auto screenSize = GetDisplaySize(displayId); 449 auto screenRect = Rect(0, screenSize.px_, 0, screenSize.py_); 450 std::vector<Window> winInfos; 451 std::vector<Rect> overplays; 452 // window wrapper 453 for (auto &win : windows) { 454 Rect winRectInScreen = GetVisibleRect(screenRect, win); 455 Rect visibleArea = winRectInScreen; 456 if (!RectAlgorithm::ComputeMaxVisibleRegion(winRectInScreen, overplays, visibleArea)) { 457 LOG_I("window is covered, windowId : %{public}d, layer is %{public}d", win.GetWindowId(), 458 win.GetWindowLayer()); 459 continue; 460 } 461 LOG_I("window is visible, windowId: " 462 "%{public}d, active: %{public}d, focus: %{public}d, layer: %{public}d", 463 win.GetWindowId(), win.IsActive(), win.IsFocused(), win.GetWindowLayer()); 464 Window winWrapper{win.GetWindowId()}; 465 winWrapper.bounds_ = winRectInScreen; 466 InflateWindowInfo(win, winWrapper); 467 winWrapper.displayId_ = win.GetDisplayId(); 468 UpdateWindowAttrs(winWrapper, overplays); 469 winWrapper.displayId_ = displayId; 470 winInfos.emplace_back(move(winWrapper)); 471 } 472 out.insert(make_pair(displayId, move(winInfos))); 473 } 474 } 475 GetWidgetsInWindow(const Window & winInfo,unique_ptr<ElementNodeIterator> & elementIterator,AamsWorkMode mode)476 bool SysUiController::GetWidgetsInWindow(const Window &winInfo, unique_ptr<ElementNodeIterator> &elementIterator, 477 AamsWorkMode mode) 478 { 479 std::lock_guard<std::mutex> dumpLocker(dumpMtx); // disallow concurrent dumpUi 480 if (!connected_) { 481 LOG_W("Connect to AccessibilityUITestAbility failed"); 482 return false; 483 } 484 std::vector<AccessibilityElementInfo> elementInfos; 485 AccessibilityWindowInfo window; 486 LOG_D("Get Window by WindowId %{public}d", winInfo.id_); 487 if (AccessibilityUITestAbility::GetInstance()->GetWindow(winInfo.id_, window) != RET_OK) { 488 LOG_E("GetWindowInfo failed, windowId: %{public}d", winInfo.id_); 489 return false; 490 } 491 LOG_D("Start Get nodes from window by WindowId %{public}d", winInfo.id_); 492 auto ret = RET_ERR_FAILED; 493 auto ability = AccessibilityUITestAbility::GetInstance(); 494 if (mode == AamsWorkMode::FASTGETNODE) { 495 LOG_D("GetRootByWindowBatch in reduced mode"); 496 ret = ability->GetRootByWindowBatch(window, elementInfos, false, true); 497 } else { 498 ret = ability->GetRootByWindowBatch(window, elementInfos); 499 } 500 if (ret != RET_OK) { 501 LOG_E("GetRootByWindowBatch failed, windowId: %{public}d", winInfo.id_); 502 return false; 503 } else { 504 LOG_I("End Get nodes from window by WindowId %{public}d, node size is %{public}zu, appId: %{public}s", 505 winInfo.id_, elementInfos.size(), winInfo.bundleName_.data()); 506 elementIterator = std::make_unique<ElementNodeIteratorImpl>(elementInfos); 507 } 508 return true; 509 } 510 GetValidDisplayId(int32_t id) const511 int32_t SysUiController::GetValidDisplayId(int32_t id) const 512 { 513 if (id == UNASSIGNED) { 514 id = DisplayManager::GetInstance().GetDefaultDisplayId(); 515 } 516 return id; 517 } 518 CheckDisplayExist(int32_t displayId) const519 bool SysUiController::CheckDisplayExist(int32_t displayId) const 520 { 521 if (displayId == UNASSIGNED) { 522 return true; 523 } 524 DisplayManager &displayMgr = DisplayManager::GetInstance(); 525 return displayMgr.GetDisplayById(displayId) != nullptr; 526 } 527 SetItemByType(PointerEvent::PointerItem & pinterItem,const PointerMatrix & events)528 static void SetItemByType(PointerEvent::PointerItem &pinterItem, const PointerMatrix &events) 529 { 530 switch (events.GetToolType()) { 531 case PointerEvent::TOOL_TYPE_FINGER: 532 pinterItem.SetToolType(PointerEvent::TOOL_TYPE_FINGER); 533 break; 534 case PointerEvent::TOOL_TYPE_PEN: 535 pinterItem.SetToolType(PointerEvent::TOOL_TYPE_PEN); 536 pinterItem.SetPressure(events.GetTouchPressure()); 537 break; 538 default: 539 return; 540 } 541 } 542 AddPointerItems(PointerEvent & event,const vector<pair<bool,Point>> & fingerStatus,uint32_t currentFinger,const PointerMatrix & events)543 static void AddPointerItems(PointerEvent &event, const vector<pair<bool, Point>> &fingerStatus, 544 uint32_t currentFinger, const PointerMatrix &events) 545 { 546 PointerEvent::PointerItem pinterItem1; 547 pinterItem1.SetPointerId(currentFinger); 548 pinterItem1.SetOriginPointerId(currentFinger); 549 pinterItem1.SetDisplayX(fingerStatus[currentFinger].second.px_); 550 pinterItem1.SetDisplayY(fingerStatus[currentFinger].second.py_); 551 pinterItem1.SetRawDisplayX(fingerStatus[currentFinger].second.px_); 552 pinterItem1.SetRawDisplayY(fingerStatus[currentFinger].second.py_); 553 pinterItem1.SetPressed(fingerStatus[currentFinger].first); 554 SetItemByType(pinterItem1, events); 555 event.UpdatePointerItem(currentFinger, pinterItem1); 556 LOG_I("Add touchItem, finger:%{public}d, pressed:%{public}d, location:%{public}d, %{public}d", 557 currentFinger, fingerStatus[currentFinger].first, fingerStatus[currentFinger].second.px_, 558 fingerStatus[currentFinger].second.py_); 559 // update pinterItem of other fingers which in pressed state. 560 for (uint32_t index = 0; index < fingerStatus.size(); index++) { 561 if (index == currentFinger) { 562 continue; 563 } 564 if (fingerStatus[index].first) { 565 PointerEvent::PointerItem pinterItem; 566 pinterItem.SetPointerId(index); 567 pinterItem.SetOriginPointerId(index); 568 pinterItem.SetDisplayX(fingerStatus[index].second.px_); 569 pinterItem.SetDisplayY(fingerStatus[index].second.py_); 570 pinterItem.SetRawDisplayX(fingerStatus[index].second.px_); 571 pinterItem.SetRawDisplayY(fingerStatus[index].second.py_); 572 pinterItem.SetPressed(true); 573 SetItemByType(pinterItem, events); 574 event.UpdatePointerItem(index, pinterItem); 575 LOG_I("Add touchItem, finger:%{public}d, pressed:%{public}d, location:%{public}d, %{public}d", 576 index, fingerStatus[index].first, fingerStatus[index].second.px_, 577 fingerStatus[index].second.py_); 578 } 579 } 580 } 581 InjectTouchEventSequence(const PointerMatrix & events) const582 void SysUiController::InjectTouchEventSequence(const PointerMatrix &events) const 583 { 584 // fingerStatus stores the press status and coordinates of each finger. 585 vector<pair<bool, Point>> fingerStatus(events.GetFingers(), make_pair(false, Point(0,0))); 586 for (uint32_t step = 0; step < events.GetSteps(); step++) { 587 for (uint32_t finger = 0; finger < events.GetFingers(); finger++) { 588 auto pointerEvent = PointerEvent::Create(); 589 if (pointerEvent == nullptr) { 590 LOG_E("Creat PointerEvent failed."); 591 return; 592 } 593 bool isPressed = (events.At(finger, step).stage_ == ActionStage::DOWN) || 594 (events.At(finger, step).stage_ == ActionStage::MOVE); 595 fingerStatus[finger] = make_pair(isPressed, events.At(finger, step).point_); 596 pointerEvent->SetPointerId(finger); 597 switch (events.At(finger, step).stage_) { 598 case ActionStage::DOWN: 599 pointerEvent->SetPointerAction(PointerEvent::POINTER_ACTION_DOWN); 600 break; 601 case ActionStage::MOVE: 602 pointerEvent->SetPointerAction(PointerEvent::POINTER_ACTION_MOVE); 603 break; 604 case ActionStage::UP: 605 pointerEvent->SetPointerAction(PointerEvent::POINTER_ACTION_UP); 606 break; 607 case ActionStage::PROXIMITY_IN: 608 pointerEvent->SetPointerAction(PointerEvent::POINTER_ACTION_PROXIMITY_IN); 609 break; 610 case ActionStage::PROXIMITY_OUT: 611 pointerEvent->SetPointerAction(PointerEvent::POINTER_ACTION_PROXIMITY_OUT); 612 break; 613 default: 614 return; 615 } 616 AddPointerItems(*pointerEvent, fingerStatus, finger, events); 617 pointerEvent->SetSourceType(PointerEvent::SOURCE_TYPE_TOUCHSCREEN); 618 auto displayId = GetValidDisplayId(events.At(finger, step).point_.displayId_); 619 pointerEvent->SetTargetDisplayId(displayId); 620 InputManager::GetInstance()->SimulateInputEvent(pointerEvent, false); 621 LOG_D("Inject touchEvent to display : %{public}d", displayId); 622 if (events.At(finger, step).holdMs_ > 0) { 623 this_thread::sleep_for(chrono::milliseconds(events.At(finger, step).holdMs_)); 624 } 625 } 626 } 627 } 628 SetMousePointerItemAttr(const MouseEvent & event,PointerEvent::PointerItem & item)629 static void SetMousePointerItemAttr(const MouseEvent &event, PointerEvent::PointerItem &item) 630 { 631 item.SetPointerId(0); 632 item.SetOriginPointerId(0); 633 item.SetToolType(PointerEvent::TOOL_TYPE_MOUSE); 634 item.SetDisplayX(event.point_.px_); 635 item.SetDisplayY(event.point_.py_); 636 item.SetRawDisplayX(event.point_.px_); 637 item.SetRawDisplayY(event.point_.py_); 638 item.SetPressed(false); 639 item.SetDownTime(0); 640 LOG_I("Inject mouseEvent, pressed:%{public}d, location:%{public}d, %{public}d", 641 event.stage_ == ActionStage::DOWN, event.point_.px_, event.point_.py_); 642 } 643 SetMousePointerEventAttr(shared_ptr<PointerEvent> pointerEvent,const MouseEvent & event)644 static void SetMousePointerEventAttr(shared_ptr<PointerEvent> pointerEvent, const MouseEvent &event) 645 { 646 pointerEvent->SetSourceType(PointerEvent::SOURCE_TYPE_MOUSE); 647 pointerEvent->SetPointerId(0); 648 if (event.button_ != MouseButton::BUTTON_NONE) { 649 pointerEvent->SetButtonId(event.button_); 650 if ((event.stage_ == ActionStage::DOWN || event.stage_ == ActionStage::MOVE)) { 651 pointerEvent->SetButtonPressed(event.button_); 652 } else if (event.stage_ == ActionStage::UP) { 653 pointerEvent->DeleteReleaseButton(event.button_); 654 } 655 } 656 } 657 InjectMouseEvent(const MouseEvent & event) const658 void SysUiController::InjectMouseEvent(const MouseEvent &event) const 659 { 660 auto pointerEvent = PointerEvent::Create(); 661 if (pointerEvent == nullptr) { 662 return; 663 } 664 PointerEvent::PointerItem item; 665 SetMousePointerEventAttr(pointerEvent, event); 666 constexpr double axialValue = 15; 667 static double injectAxialValue = 0; 668 switch (event.stage_) { 669 case ActionStage::DOWN: 670 pointerEvent->SetPointerAction(OHOS::MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN); 671 item.SetPressed(true); 672 break; 673 case ActionStage::MOVE: 674 pointerEvent->SetPointerAction(OHOS::MMI::PointerEvent::POINTER_ACTION_MOVE); 675 break; 676 case ActionStage::UP: 677 pointerEvent->SetPointerAction(OHOS::MMI::PointerEvent::POINTER_ACTION_BUTTON_UP); 678 break; 679 case ActionStage::AXIS_UP: 680 pointerEvent->SetPointerAction(OHOS::MMI::PointerEvent::POINTER_ACTION_AXIS_BEGIN); 681 pointerEvent->SetAxisValue(OHOS::MMI::PointerEvent::AXIS_TYPE_SCROLL_VERTICAL, -axialValue); 682 injectAxialValue = injectAxialValue - axialValue; 683 break; 684 case ActionStage::AXIS_DOWN: 685 pointerEvent->SetPointerAction(OHOS::MMI::PointerEvent::POINTER_ACTION_AXIS_BEGIN); 686 pointerEvent->SetAxisValue(OHOS::MMI::PointerEvent::AXIS_TYPE_SCROLL_VERTICAL, axialValue); 687 injectAxialValue = injectAxialValue + axialValue; 688 break; 689 case ActionStage::AXIS_STOP: 690 pointerEvent->SetPointerAction(OHOS::MMI::PointerEvent::POINTER_ACTION_AXIS_END); 691 pointerEvent->SetAxisValue(OHOS::MMI::PointerEvent::AXIS_TYPE_SCROLL_VERTICAL, injectAxialValue); 692 injectAxialValue = 0; 693 break; 694 default: 695 return; 696 } 697 SetMousePointerItemAttr(event, item); 698 pointerEvent->AddPointerItem(item); 699 auto displayId = GetValidDisplayId(event.point_.displayId_); 700 pointerEvent->SetTargetDisplayId(displayId); 701 if (!downKeys_.empty()) { 702 pointerEvent->SetPressedKeys(downKeys_); 703 } 704 InputManager::GetInstance()->SimulateInputEvent(pointerEvent, false); 705 LOG_I("Inject mouseEvent to display : %{public}d", displayId); 706 this_thread::sleep_for(chrono::milliseconds(event.holdMs_)); 707 } 708 InjectMouseEventSequence(const vector<MouseEvent> & events) const709 void SysUiController::InjectMouseEventSequence(const vector<MouseEvent> &events) const 710 { 711 for (auto &event : events) { 712 auto keyEvents = event.keyEvents_; 713 if (!keyEvents.empty() && keyEvents.front().stage_ == ActionStage::DOWN) { 714 InjectKeyEventSequence(keyEvents, event.point_.displayId_); 715 InjectMouseEvent(event); 716 } else { 717 InjectMouseEvent(event); 718 InjectKeyEventSequence(keyEvents, event.point_.displayId_); 719 } 720 } 721 } 722 InjectKeyEventSequence(const vector<KeyEvent> & events,int32_t displayId) const723 void SysUiController::InjectKeyEventSequence(const vector<KeyEvent> &events, int32_t displayId) const 724 { 725 displayId = GetValidDisplayId(displayId); 726 for (auto &event : events) { 727 if (event.code_ == KEYCODE_NONE) { 728 continue; 729 } 730 auto keyEvent = OHOS::MMI::KeyEvent::Create(); 731 if (keyEvent == nullptr) { 732 LOG_E("Creat KeyEvent failed."); 733 return; 734 } 735 if (event.stage_ == ActionStage::UP) { 736 auto iter = std::find(downKeys_.begin(), downKeys_.end(), event.code_); 737 if (iter == downKeys_.end()) { 738 LOG_W("Cannot release a not-pressed key: %{public}d", event.code_); 739 continue; 740 } 741 downKeys_.erase(iter); 742 keyEvent->SetKeyCode(event.code_); 743 keyEvent->SetKeyAction(OHOS::MMI::KeyEvent::KEY_ACTION_UP); 744 OHOS::MMI::KeyEvent::KeyItem keyItem; 745 keyItem.SetKeyCode(event.code_); 746 keyItem.SetPressed(false); 747 keyEvent->AddKeyItem(keyItem); 748 keyEvent->SetTargetDisplayId(displayId); 749 InputManager::GetInstance()->SimulateInputEvent(keyEvent); 750 LOG_I("Inject keyEvent up, keycode:%{public}d", event.code_); 751 } else { 752 downKeys_.push_back(event.code_); 753 for (auto downKey : downKeys_) { 754 keyEvent->SetKeyCode(downKey); 755 keyEvent->SetKeyAction(OHOS::MMI::KeyEvent::KEY_ACTION_DOWN); 756 OHOS::MMI::KeyEvent::KeyItem keyItem; 757 keyItem.SetKeyCode(downKey); 758 keyItem.SetPressed(true); 759 keyEvent->AddKeyItem(keyItem); 760 } 761 keyEvent->SetTargetDisplayId(displayId); 762 InputManager::GetInstance()->SimulateInputEvent(keyEvent); 763 LOG_I("Inject keyEvent down, keycode:%{public}d", event.code_); 764 if (event.holdMs_ > 0) { 765 this_thread::sleep_for(chrono::milliseconds(event.holdMs_)); 766 } 767 } 768 } 769 // check not released keys 770 for (auto downKey : downKeys_) { 771 LOG_W("Key event sequence injections done with not-released key: %{public}d", downKey); 772 } 773 } 774 IsTouchPadExist() const775 bool SysUiController::IsTouchPadExist() const 776 { 777 std::vector<int32_t> inputDeviceIdList; 778 auto getDeviceIdsCallback = [&inputDeviceIdList](std::vector<int32_t>& deviceIds) { 779 inputDeviceIdList = deviceIds; 780 }; 781 int32_t ret1 = InputManager::GetInstance()->GetDeviceIds(getDeviceIdsCallback); 782 if (ret1 != RET_OK) { 783 LOG_E("Get device ids failed"); 784 return false; 785 } 786 const int32_t touchPadTag = 1 << 3; 787 for (auto inputDeviceId : inputDeviceIdList) { 788 std::shared_ptr<MMI::InputDevice> inputDevice; 789 auto getDeviceCallback = [&inputDevice](std::shared_ptr<MMI::InputDevice> device) { 790 inputDevice = device; 791 }; 792 int32_t ret2 = MMI::InputManager::GetInstance()->GetDevice(inputDeviceId, getDeviceCallback); 793 if (ret2 != RET_OK || inputDevice == nullptr) { 794 LOG_E("Get device failed"); 795 continue; 796 } 797 if (inputDevice->GetType() & touchPadTag) { 798 return true; 799 } 800 } 801 return false; 802 } 803 InjectTouchPadEventSequence(const vector<TouchPadEvent> & events) const804 void SysUiController::InjectTouchPadEventSequence(const vector<TouchPadEvent>& events) const 805 { 806 vector<pair<bool, Point>> fingerStatus(1, make_pair(false, Point(0, 0))); 807 for (auto &event : events) { 808 auto pointerEvent = PointerEvent::Create(); 809 if (pointerEvent == nullptr) { 810 LOG_E("Creat PointerEvent failed."); 811 return; 812 } 813 pointerEvent->SetPointerId(0); 814 switch (event.stage) { 815 case ActionStage::DOWN: 816 pointerEvent->SetPointerAction(PointerEvent::POINTER_ACTION_SWIPE_BEGIN); 817 break; 818 case ActionStage::MOVE: 819 pointerEvent->SetPointerAction(PointerEvent::POINTER_ACTION_SWIPE_UPDATE); 820 break; 821 case ActionStage::UP: 822 pointerEvent->SetPointerAction(PointerEvent::POINTER_ACTION_SWIPE_END); 823 break; 824 default: 825 break; 826 } 827 fingerStatus[0] = make_pair(false, event.point); 828 PointerMatrix pointer; 829 AddPointerItems(*pointerEvent, fingerStatus, 0, pointer); 830 pointerEvent->SetSourceType(PointerEvent::SOURCE_TYPE_TOUCHPAD); 831 pointerEvent->SetFingerCount(event.fingerCount); 832 auto displayId = GetValidDisplayId(event.point.displayId_); 833 pointerEvent->SetTargetDisplayId(displayId); 834 InputManager::GetInstance()->SimulateInputEvent(pointerEvent, false); 835 LOG_D("Inject touchEvent to display %{public}d", displayId); 836 if (event.holdMs > 0) { 837 this_thread::sleep_for(chrono::milliseconds(event.holdMs)); 838 } 839 } 840 } 841 PutTextToClipboard(string_view text,ApiCallErr & error) const842 void SysUiController::PutTextToClipboard(string_view text, ApiCallErr &error) const 843 { 844 auto ret = OHOS::testserver::TestServerClient::GetInstance().SetPasteData(string(text)); 845 if (ret != OHOS::testserver::TEST_SERVER_OK) { 846 LOG_E("Set pasteBoard data failed."); 847 error = ApiCallErr(ERR_INTERNAL, "Set pasteBoard data failed."); 848 if (ret != OHOS::testserver::TEST_SERVER_SET_PASTE_DATA_FAILED) { 849 error.code_ = ERR_NO_SYSTEM_CAPABILITY; 850 } 851 return; 852 } 853 static constexpr auto sliceMs = 500; 854 this_thread::sleep_for(chrono::milliseconds(sliceMs)); 855 } 856 ChangeWindowMode(int32_t windowId,WindowMode mode) const857 void SysUiController::ChangeWindowMode(int32_t windowId, WindowMode mode) const 858 { 859 switch (mode) { 860 case WindowMode::FULLSCREEN: 861 OHOS::testserver::TestServerClient::GetInstance().ChangeWindowMode(windowId, 862 static_cast<uint32_t>(OHOS::Rosen::WindowMode::WINDOW_MODE_FULLSCREEN)); 863 break; 864 case WindowMode::SPLIT_PRIMARY: 865 OHOS::testserver::TestServerClient::GetInstance().ChangeWindowMode(windowId, 866 static_cast<uint32_t>(OHOS::Rosen::WindowMode::WINDOW_MODE_SPLIT_PRIMARY)); 867 break; 868 case WindowMode::FLOATING: 869 OHOS::testserver::TestServerClient::GetInstance().ChangeWindowMode(windowId, 870 static_cast<uint32_t>(OHOS::Rosen::WindowMode::WINDOW_MODE_FLOATING)); 871 break; 872 case WindowMode::MINIMIZED: 873 OHOS::testserver::TestServerClient::GetInstance().MinimizeWindow(windowId); 874 break; 875 case WindowMode::CLOSED: 876 OHOS::testserver::TestServerClient::GetInstance().TerminateWindow(windowId); 877 break; 878 default: 879 break; 880 } 881 static constexpr auto sliceMs = 500; 882 this_thread::sleep_for(chrono::milliseconds(sliceMs)); 883 } 884 IsWorkable() const885 bool SysUiController::IsWorkable() const 886 { 887 return connected_; 888 } 889 IsWearable() const890 bool SysUiController::IsWearable() const 891 { 892 bool isWearable = false; 893 #ifdef ARKXTEST_WATCH_FEATURE_ENABLE 894 isWearable = true; 895 #endif 896 return isWearable; 897 } 898 IsAdjustWindowModeEnable() const899 bool SysUiController::IsAdjustWindowModeEnable() const 900 { 901 bool IsAdjustWindowModeEnable = false; 902 #ifdef ARKXTEST_ADJUST_WINDOWMODE_ENABLE 903 IsAdjustWindowModeEnable = true; 904 #endif 905 return IsAdjustWindowModeEnable; 906 } 907 GetCharKeyCode(char ch,int32_t & code,int32_t & ctrlCode) const908 bool SysUiController::GetCharKeyCode(char ch, int32_t &code, int32_t &ctrlCode) const 909 { 910 ctrlCode = KEYCODE_NONE; 911 if (ch >= 'a' && ch <= 'z') { 912 code = OHOS::MMI::KeyEvent::KEYCODE_A + static_cast<int32_t>(ch - 'a'); 913 } else if (ch >= 'A' && ch <= 'Z') { 914 ctrlCode = OHOS::MMI::KeyEvent::KEYCODE_SHIFT_LEFT; 915 code = OHOS::MMI::KeyEvent::KEYCODE_A + static_cast<int32_t>(ch - 'A'); 916 } else if (ch >= '0' && ch <= '9') { 917 code = OHOS::MMI::KeyEvent::KEYCODE_0 + static_cast<int32_t>(ch - '0'); 918 } else if (SingleKeySymbalMap.find(ch) != SingleKeySymbalMap.end()) { 919 code = SingleKeySymbalMap.find(ch)->second; 920 } else if (MultiKeySymbalMap.find(ch) != MultiKeySymbalMap.end()) { 921 ctrlCode = OHOS::MMI::KeyEvent::KEYCODE_SHIFT_LEFT; 922 code = MultiKeySymbalMap.find(ch)->second; 923 } else { 924 return false; 925 } 926 return true; 927 } 928 TakeScreenCap(int32_t fd,std::stringstream & errReceiver,int32_t displayId,Rect rect) const929 bool SysUiController::TakeScreenCap(int32_t fd, std::stringstream &errReceiver, int32_t displayId, Rect rect) const 930 { 931 DisplayManager &displayMgr = DisplayManager::GetInstance(); 932 displayId = GetValidDisplayId(displayId); 933 // get PixelMap from DisplayManager API 934 shared_ptr<PixelMap> pixelMap; 935 if (rect.GetWidth() == 0) { 936 pixelMap = displayMgr.GetScreenshot(displayId); 937 } else { 938 Media::Rect region = {.left = rect.left_, .top = rect.top_, 939 .width = rect.right_ - rect.left_, .height = rect.bottom_ - rect.top_}; 940 Media::Size size = {.width = rect.right_ - rect.left_, .height = rect.bottom_ - rect.top_}; 941 pixelMap = displayMgr.GetScreenshot(displayId, region, size, 0); 942 } 943 if (pixelMap == nullptr) { 944 errReceiver << "Failed to get display pixelMap"; 945 return false; 946 } 947 int64_t packedSize = 0L; 948 auto pixelSize = static_cast<uint32_t>(pixelMap->GetByteCount()); 949 LOG_D("PixelSize: %{public}d", pixelSize); 950 auto buffer = new (std::nothrow) uint8_t[pixelSize]; 951 Media::ImagePacker imagePacker; 952 Media::PackOption packOption; 953 packOption.format = "image/png"; 954 imagePacker.StartPacking(buffer, pixelSize, packOption); 955 imagePacker.AddImage(*pixelMap); 956 uint32_t packResult = imagePacker.FinalizePacking(packedSize); 957 LOG_D("Packed pixelMap, packResult: %{public}d", packResult); 958 LOG_D("Packed pixelMap, packedSize: %{public}" PRId64, packedSize); 959 if (packResult != NO_ERROR || buffer == nullptr) { 960 delete[] buffer; 961 return false; 962 } 963 int ret = write(fd, buffer, packedSize); 964 if (ret == -1) { 965 int err = errno; 966 LOG_E("write failed: %{public}d", err); 967 LOG_E("write failed reason: %{public}s", strerror(err)); 968 return false; 969 } 970 delete[] buffer; 971 return true; 972 } 973 ConnectToSysAbility(ApiCallErr & error)974 bool SysUiController::ConnectToSysAbility(ApiCallErr &error) 975 { 976 if (connected_) { 977 return true; 978 } 979 mutex mtx; 980 unique_lock<mutex> uLock(mtx); 981 std::shared_ptr<condition_variable> condition = make_shared<condition_variable>(); 982 auto onConnectCallback = [condition]() { 983 LOG_I("Success connect to AccessibilityUITestAbility"); 984 condition->notify_all(); 985 }; 986 auto onDisConnectCallback = [this]() { this->connected_ = false; }; 987 if (g_monitorInstance_ == nullptr) { 988 g_monitorInstance_ = make_shared<UiEventMonitor>(); 989 } 990 g_monitorInstance_->SetOnAbilityConnectCallback(onConnectCallback); 991 g_monitorInstance_->SetOnAbilityDisConnectCallback(onDisConnectCallback); 992 auto ability = AccessibilityUITestAbility::GetInstance(); 993 if (ability->RegisterAbilityListener(g_monitorInstance_) != RET_OK) { 994 error = ApiCallErr(ERR_INITIALIZE_FAILED, "Can not connect to AAMS, REGISTER_LISTENER_FAILED"); 995 return false; 996 } 997 auto ret = ability->Connect(); 998 LOG_I("Connect to AAMS, result: %{public}d", ret); 999 if (ret != RET_OK) { 1000 error = ApiCallErr(ERR_INITIALIZE_FAILED, "Can not connect to AAMS"); 1001 if (ret == RET_ERR_CONNECTION_EXIST) { 1002 error.message_ += ", RET_ERR_CONNECTION_EXIST"; 1003 } else { 1004 error.message_ += ", RET_ERR_AAMS"; 1005 } 1006 return false; 1007 } 1008 const auto timeout = chrono::milliseconds(7000); 1009 if (condition->wait_for(uLock, timeout) == cv_status::timeout) { 1010 LOG_E("Wait connection to AccessibilityUITestAbility timed out"); 1011 error = ApiCallErr(ERR_INITIALIZE_FAILED, "Can not connect to AAMS, RET_TIMEOUT"); 1012 return false; 1013 } 1014 connected_ = true; 1015 return true; 1016 } 1017 RegisterUiEventListener(std::shared_ptr<UiEventListener> listener) const1018 void SysUiController::RegisterUiEventListener(std::shared_ptr<UiEventListener> listener) const 1019 { 1020 g_monitorInstance_->RegisterUiEventListener(listener); 1021 } 1022 WaitForUiSteady(uint32_t idleThresholdMs,uint32_t timeoutMs) const1023 bool SysUiController::WaitForUiSteady(uint32_t idleThresholdMs, uint32_t timeoutMs) const 1024 { 1025 return g_monitorInstance_->WaitEventIdle(idleThresholdMs, timeoutMs); 1026 } 1027 DisConnectFromSysAbility()1028 void SysUiController::DisConnectFromSysAbility() 1029 { 1030 if (!connected_ || g_monitorInstance_ == nullptr) { 1031 return; 1032 } 1033 connected_ = false; 1034 mutex mtx; 1035 unique_lock<mutex> uLock(mtx); 1036 condition_variable condition; 1037 auto onDisConnectCallback = [&condition]() { 1038 LOG_I("Success disconnect from AccessibilityUITestAbility"); 1039 condition.notify_all(); 1040 }; 1041 g_monitorInstance_->SetOnAbilityDisConnectCallback(onDisConnectCallback); 1042 auto ability = AccessibilityUITestAbility::GetInstance(); 1043 LOG_I("Start disconnect from AccessibilityUITestAbility"); 1044 if (ability->Disconnect() != RET_OK) { 1045 LOG_E("Failed to disconnect from AccessibilityUITestAbility"); 1046 return; 1047 } 1048 const auto timeout = chrono::milliseconds(200); 1049 if (condition.wait_for(uLock, timeout) == cv_status::timeout) { 1050 LOG_E("Wait disconnection from AccessibilityUITestAbility timed out"); 1051 return; 1052 } 1053 } 1054 SetDisplayRotation(DisplayRotation rotation) const1055 void SysUiController::SetDisplayRotation(DisplayRotation rotation) const 1056 { 1057 auto display = DisplayManager::GetInstance().GetDefaultDisplay(); 1058 if (display == nullptr) { 1059 LOG_E("DisplayManager init fail"); 1060 return; 1061 } 1062 auto screenId = display->GetScreenId(); 1063 ScreenManager &screenMgr = ScreenManager::GetInstance(); 1064 bool isLocked = false; 1065 screenMgr.IsScreenRotationLocked(isLocked); 1066 if (isLocked) { 1067 screenMgr.SetScreenRotationLocked(false); 1068 } 1069 auto screen = screenMgr.GetScreenById(screenId); 1070 if (screen == nullptr) { 1071 LOG_E("ScreenManager init fail"); 1072 return; 1073 } 1074 switch (rotation) { 1075 case ROTATION_0 : 1076 screen->SetOrientation(Orientation::VERTICAL); 1077 break; 1078 case ROTATION_90 : 1079 screen->SetOrientation(Orientation::HORIZONTAL); 1080 break; 1081 case ROTATION_180 : 1082 screen->SetOrientation(Orientation::REVERSE_VERTICAL); 1083 break; 1084 case ROTATION_270 : 1085 screen->SetOrientation(Orientation::REVERSE_HORIZONTAL); 1086 break; 1087 default : 1088 break; 1089 } 1090 } 1091 GetDisplayRotation(int32_t displayId) const1092 DisplayRotation SysUiController::GetDisplayRotation(int32_t displayId) const 1093 { 1094 DisplayManager &displayMgr = DisplayManager::GetInstance(); 1095 displayId = GetValidDisplayId(displayId); 1096 auto display = displayMgr.GetDisplayById(displayId); 1097 if (display == nullptr) { 1098 LOG_E("DisplayManager init fail"); 1099 return DisplayRotation::ROTATION_0; 1100 } 1101 auto rotation = (DisplayRotation)display->GetRotation(); 1102 return rotation; 1103 } 1104 SetDisplayRotationEnabled(bool enabled) const1105 void SysUiController::SetDisplayRotationEnabled(bool enabled) const 1106 { 1107 ScreenManager &screenMgr = ScreenManager::GetInstance(); 1108 screenMgr.SetScreenRotationLocked(!enabled); 1109 } 1110 GetDisplaySize(int32_t displayId) const1111 Point SysUiController::GetDisplaySize(int32_t displayId) const 1112 { 1113 DisplayManager &displayMgr = DisplayManager::GetInstance(); 1114 displayId = GetValidDisplayId(displayId); 1115 auto display = displayMgr.GetDisplayById(displayId); 1116 if (display == nullptr) { 1117 LOG_E("DisplayManager init fail"); 1118 return {0, 0}; 1119 } 1120 auto width = display->GetWidth(); 1121 auto height = display->GetHeight(); 1122 LOG_D("GetDisplaysize in display %{public}d, width: %{public}d, height: %{public}d", displayId, width, height); 1123 auto virtualDisplay = displayMgr.GetDisplayById(VIRTUAL_DISPLAY_ID); 1124 if (displayId == 0 && virtualDisplay != nullptr) { 1125 auto virtualwidth = virtualDisplay->GetWidth(); 1126 auto virtualheight = virtualDisplay->GetHeight(); 1127 auto foldArea = GetFoldArea(); 1128 auto foldAreaWidth = foldArea.right_ - foldArea.left_; 1129 auto foldAreaHeight = foldArea.bottom_ - foldArea.top_; 1130 LOG_D("GetDisplaysize in virtual display, width: %{public}d, height: %{public}d", 1131 virtualwidth, virtualheight); 1132 LOG_D("GetDisplaysize in foldArea, width: %{public}d, height: %{public}d", foldAreaWidth, foldAreaHeight); 1133 height = height + virtualheight + foldAreaHeight; 1134 } 1135 Point result(width, height, displayId); 1136 return result; 1137 } 1138 GetDisplayDensity(int32_t displayId) const1139 Point SysUiController::GetDisplayDensity(int32_t displayId) const 1140 { 1141 DisplayManager &displayMgr = DisplayManager::GetInstance(); 1142 displayId = GetValidDisplayId(displayId); 1143 auto display = displayMgr.GetDisplayById(displayId); 1144 if (display == nullptr) { 1145 LOG_E("DisplayManager init fail"); 1146 return {0, 0}; 1147 } 1148 auto rate = display->GetVirtualPixelRatio(); 1149 Point displaySize = GetDisplaySize(displayId); 1150 Point result(displaySize.px_ * rate, displaySize.py_ * rate); 1151 return result; 1152 } 1153 IsScreenOn() const1154 bool SysUiController::IsScreenOn() const 1155 { 1156 DisplayManager &displayMgr = DisplayManager::GetInstance(); 1157 auto displayId = displayMgr.GetDefaultDisplayId(); 1158 auto state = displayMgr.GetDisplayState(displayId); 1159 return (state != DisplayState::OFF); 1160 } 1161 CloseAamsEvent() const1162 void SysUiController::CloseAamsEvent() const 1163 { 1164 AccessibilityUITestAbility::GetInstance()->ConfigureEvents({ Accessibility::EventType::TYPE_VIEW_INVALID }); 1165 } 1166 OpenAamsEvent() const1167 void SysUiController::OpenAamsEvent() const 1168 { 1169 AccessibilityUITestAbility::GetInstance()->ConfigureEvents(EVENT_MASK); 1170 } 1171 1172 class OnSaLoadCallback : public SystemAbilityLoadCallbackStub { 1173 public: OnSaLoadCallback(mutex & mutex)1174 explicit OnSaLoadCallback(mutex &mutex): mutex_(mutex) {}; ~OnSaLoadCallback()1175 ~OnSaLoadCallback() {}; OnLoadSystemAbilitySuccess(int32_t systemAbilityId,const sptr<IRemoteObject> & remoteObject)1176 void OnLoadSystemAbilitySuccess(int32_t systemAbilityId, const sptr<IRemoteObject>& remoteObject) override 1177 { 1178 if (systemAbilityId == OHOS::DFX_HI_DUMPER_SERVICE_ABILITY_ID) { 1179 remoteObject_ = remoteObject; 1180 mutex_.unlock(); 1181 } 1182 } OnLoadSystemAbilityFail(int32_t systemAbilityId)1183 void OnLoadSystemAbilityFail(int32_t systemAbilityId) override 1184 { 1185 if (systemAbilityId == OHOS::DFX_HI_DUMPER_SERVICE_ABILITY_ID) { 1186 mutex_.unlock(); 1187 } 1188 } 1189 GetSaObject()1190 sptr<IRemoteObject> GetSaObject() 1191 { 1192 return remoteObject_; 1193 } 1194 1195 private: 1196 mutex &mutex_; 1197 sptr<IRemoteObject> remoteObject_ = nullptr; 1198 }; 1199 CreateHidumperCmd(const std::string & windowId,vector<u16string> & result)1200 static void CreateHidumperCmd(const std::string &windowId, vector<u16string> &result) 1201 { 1202 result.emplace_back(u"hidumper"); 1203 result.emplace_back(u"-s"); 1204 result.emplace_back(u"WindowManagerService"); 1205 result.emplace_back(u"-a"); 1206 auto winIdInUtf16 = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{}.from_bytes(windowId); 1207 auto arg = u16string(u"-w ").append(winIdInUtf16).append(u" -default -lastpage"); 1208 result.emplace_back(move(arg)); 1209 } 1210 GetHidumperInfo(std::string windowId,char ** buf,size_t & len)1211 void SysUiController::GetHidumperInfo(std::string windowId, char **buf, size_t &len) 1212 { 1213 #ifdef HIDUMPER_ENABLED 1214 auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 1215 // wati SA start 1216 constexpr auto delayMs = 2000; 1217 this_thread::sleep_for(chrono::milliseconds(delayMs)); 1218 if (sam == nullptr) { 1219 LOG_E("Get samgr failed"); 1220 return; 1221 } 1222 auto remoteObject = sam->CheckSystemAbility(OHOS::DFX_HI_DUMPER_SERVICE_ABILITY_ID); 1223 if (remoteObject == nullptr) { 1224 mutex lock; 1225 lock.lock(); 1226 sptr<OnSaLoadCallback> loadCallback = new OnSaLoadCallback(lock); 1227 if (sam->LoadSystemAbility(OHOS::DFX_HI_DUMPER_SERVICE_ABILITY_ID, loadCallback) != ERR_OK) { 1228 LOG_E("Schedule LoadSystemAbility failed"); 1229 lock.unlock(); 1230 return; 1231 } 1232 LOG_E("Schedule LoadSystemAbility succeed"); 1233 lock.unlock(); 1234 remoteObject = loadCallback->GetSaObject(); 1235 LOG_E("LoadSystemAbility callbacked, result = %{public}s", remoteObject == nullptr ? "FAIL" : "SUCCESS"); 1236 } 1237 if (remoteObject == nullptr) { 1238 LOG_E("remoteObject is null"); 1239 return; 1240 } 1241 // run dump command 1242 sptr<IDumpBroker> client = iface_cast<IDumpBroker>(remoteObject); 1243 if (client == nullptr) { 1244 LOG_E("IDumpBroker converts failed"); 1245 return; 1246 } 1247 auto fd = memfd_create("dummy_file", 2); 1248 ftruncate(fd, 0); 1249 vector<u16string> args; 1250 CreateHidumperCmd(windowId, args); 1251 client->Request(args, fd); 1252 auto size = lseek(fd, 0, SEEK_END); 1253 char *tempBuf = new char[size + 1]; 1254 lseek(fd, 0, SEEK_SET); 1255 read(fd, tempBuf, size); 1256 *buf = tempBuf; 1257 len = size; 1258 close(fd); 1259 #else 1260 *buf = nullptr; 1261 len = 0; 1262 #endif 1263 } 1264 } // namespace OHOS::uitest