1886da342Sopenharmony_ci/* 2886da342Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3886da342Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4886da342Sopenharmony_ci * you may not use this file except in compliance with the License. 5886da342Sopenharmony_ci * You may obtain a copy of the License at 6886da342Sopenharmony_ci * 7886da342Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8886da342Sopenharmony_ci * 9886da342Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10886da342Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11886da342Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12886da342Sopenharmony_ci * See the License for the specific language governing permissions and 13886da342Sopenharmony_ci * limitations under the License. 14886da342Sopenharmony_ci */ 15886da342Sopenharmony_ci 16886da342Sopenharmony_ci#include <atomic> 17886da342Sopenharmony_ci#include <chrono> 18886da342Sopenharmony_ci#include <fstream> 19886da342Sopenharmony_ci#include <memory> 20886da342Sopenharmony_ci#include <iostream> 21886da342Sopenharmony_ci#include <thread> 22886da342Sopenharmony_ci#include <utility> 23886da342Sopenharmony_ci#include <condition_variable> 24886da342Sopenharmony_ci#include <sys/mman.h> 25886da342Sopenharmony_ci#ifdef HIDUMPER_ENABLED 26886da342Sopenharmony_ci#include <iservice_registry.h> 27886da342Sopenharmony_ci#include <system_ability_load_callback_stub.h> 28886da342Sopenharmony_ci#include "idump_broker.h" 29886da342Sopenharmony_ci#include "dump_broker_proxy.h" 30886da342Sopenharmony_ci#include "system_ability_definition.h" 31886da342Sopenharmony_ci#endif 32886da342Sopenharmony_ci#include "accessibility_event_info.h" 33886da342Sopenharmony_ci#include "accessibility_ui_test_ability.h" 34886da342Sopenharmony_ci#include "ability_manager_client.h" 35886da342Sopenharmony_ci#include "display_manager.h" 36886da342Sopenharmony_ci#include "screen_manager.h" 37886da342Sopenharmony_ci#include "input_manager.h" 38886da342Sopenharmony_ci#include "png.h" 39886da342Sopenharmony_ci#include "wm_common.h" 40886da342Sopenharmony_ci#include "element_node_iterator_impl.h" 41886da342Sopenharmony_ci#include "system_ui_controller.h" 42886da342Sopenharmony_ci#include "test_server_client.h" 43886da342Sopenharmony_ci 44886da342Sopenharmony_ciusing namespace std; 45886da342Sopenharmony_ciusing namespace chrono; 46886da342Sopenharmony_ci 47886da342Sopenharmony_cinamespace OHOS::uitest { 48886da342Sopenharmony_ci using namespace std; 49886da342Sopenharmony_ci using namespace nlohmann; 50886da342Sopenharmony_ci using namespace OHOS::MMI; 51886da342Sopenharmony_ci using namespace OHOS::Accessibility; 52886da342Sopenharmony_ci using namespace OHOS::Rosen; 53886da342Sopenharmony_ci using namespace OHOS::Media; 54886da342Sopenharmony_ci using namespace OHOS::HiviewDFX; 55886da342Sopenharmony_ci using namespace OHOS; 56886da342Sopenharmony_ci 57886da342Sopenharmony_ci class UiEventMonitor final : public AccessibleAbilityListener { 58886da342Sopenharmony_ci public: 59886da342Sopenharmony_ci virtual ~UiEventMonitor() override = default; 60886da342Sopenharmony_ci 61886da342Sopenharmony_ci void OnAbilityConnected() override; 62886da342Sopenharmony_ci 63886da342Sopenharmony_ci void OnAbilityDisconnected() override; 64886da342Sopenharmony_ci 65886da342Sopenharmony_ci void OnAccessibilityEvent(const AccessibilityEventInfo &eventInfo) override; 66886da342Sopenharmony_ci 67886da342Sopenharmony_ci void SetOnAbilityConnectCallback(function<void()> onConnectCb); 68886da342Sopenharmony_ci 69886da342Sopenharmony_ci void SetOnAbilityDisConnectCallback(function<void()> onDisConnectCb); 70886da342Sopenharmony_ci 71886da342Sopenharmony_ci bool OnKeyPressEvent(const shared_ptr<MMI::KeyEvent> &keyEvent) override 72886da342Sopenharmony_ci { 73886da342Sopenharmony_ci return false; 74886da342Sopenharmony_ci } 75886da342Sopenharmony_ci 76886da342Sopenharmony_ci uint64_t GetLastEventMillis(); 77886da342Sopenharmony_ci 78886da342Sopenharmony_ci bool WaitEventIdle(uint32_t idleThresholdMs, uint32_t timeoutMs); 79886da342Sopenharmony_ci 80886da342Sopenharmony_ci void WaitScrollCompelete(); 81886da342Sopenharmony_ci 82886da342Sopenharmony_ci void RegisterUiEventListener(shared_ptr<UiEventListener> listerner); 83886da342Sopenharmony_ci 84886da342Sopenharmony_ci private: 85886da342Sopenharmony_ci function<void()> onConnectCallback_ = nullptr; 86886da342Sopenharmony_ci function<void()> onDisConnectCallback_ = nullptr; 87886da342Sopenharmony_ci atomic<uint64_t> lastEventMillis_ = 0; 88886da342Sopenharmony_ci atomic<uint64_t> lastScrollBeginEventMillis_ = 0; 89886da342Sopenharmony_ci atomic<bool> scrollCompelete_ = true; 90886da342Sopenharmony_ci vector<shared_ptr<UiEventListener>> listeners_; 91886da342Sopenharmony_ci }; 92886da342Sopenharmony_ci 93886da342Sopenharmony_ci struct EventSpec { 94886da342Sopenharmony_ci std::string_view componentTyep; 95886da342Sopenharmony_ci int32_t eventType; 96886da342Sopenharmony_ci std::string_view event; 97886da342Sopenharmony_ci }; 98886da342Sopenharmony_ci 99886da342Sopenharmony_ci const std::map<char, int32_t> SingleKeySymbalMap = { 100886da342Sopenharmony_ci {' ', OHOS::MMI::KeyEvent::KEYCODE_SPACE}, 101886da342Sopenharmony_ci {'`', OHOS::MMI::KeyEvent::KEYCODE_GRAVE}, 102886da342Sopenharmony_ci {'[', OHOS::MMI::KeyEvent::KEYCODE_LEFT_BRACKET}, 103886da342Sopenharmony_ci {']', OHOS::MMI::KeyEvent::KEYCODE_RIGHT_BRACKET}, 104886da342Sopenharmony_ci {'\\', OHOS::MMI::KeyEvent::KEYCODE_BACKSLASH}, 105886da342Sopenharmony_ci {',', OHOS::MMI::KeyEvent::KEYCODE_COMMA}, 106886da342Sopenharmony_ci {';', OHOS::MMI::KeyEvent::KEYCODE_SEMICOLON}, 107886da342Sopenharmony_ci {'\'', OHOS::MMI::KeyEvent::KEYCODE_APOSTROPHE}, 108886da342Sopenharmony_ci {'/', OHOS::MMI::KeyEvent::KEYCODE_SLASH}, 109886da342Sopenharmony_ci {'*', OHOS::MMI::KeyEvent::KEYCODE_NUMPAD_MULTIPLY}, 110886da342Sopenharmony_ci {'-', OHOS::MMI::KeyEvent::KEYCODE_MINUS}, 111886da342Sopenharmony_ci {'.', OHOS::MMI::KeyEvent::KEYCODE_PERIOD}, 112886da342Sopenharmony_ci {'=', OHOS::MMI::KeyEvent::KEYCODE_EQUALS} 113886da342Sopenharmony_ci }; 114886da342Sopenharmony_ci 115886da342Sopenharmony_ci const std::map<char, int32_t> MultiKeySymbalMap = { 116886da342Sopenharmony_ci {'~', OHOS::MMI::KeyEvent::KEYCODE_GRAVE}, 117886da342Sopenharmony_ci {'!', OHOS::MMI::KeyEvent::KEYCODE_1}, 118886da342Sopenharmony_ci {'@', OHOS::MMI::KeyEvent::KEYCODE_2}, 119886da342Sopenharmony_ci {'#', OHOS::MMI::KeyEvent::KEYCODE_3}, 120886da342Sopenharmony_ci {'$', OHOS::MMI::KeyEvent::KEYCODE_4}, 121886da342Sopenharmony_ci {'%', OHOS::MMI::KeyEvent::KEYCODE_5}, 122886da342Sopenharmony_ci {'^', OHOS::MMI::KeyEvent::KEYCODE_6}, 123886da342Sopenharmony_ci {'&', OHOS::MMI::KeyEvent::KEYCODE_7}, 124886da342Sopenharmony_ci {'(', OHOS::MMI::KeyEvent::KEYCODE_9}, 125886da342Sopenharmony_ci {')', OHOS::MMI::KeyEvent::KEYCODE_0}, 126886da342Sopenharmony_ci {'+', OHOS::MMI::KeyEvent::KEYCODE_EQUALS}, 127886da342Sopenharmony_ci {'_', OHOS::MMI::KeyEvent::KEYCODE_MINUS}, 128886da342Sopenharmony_ci {':', OHOS::MMI::KeyEvent::KEYCODE_SEMICOLON}, 129886da342Sopenharmony_ci {'"', OHOS::MMI::KeyEvent::KEYCODE_APOSTROPHE}, 130886da342Sopenharmony_ci {'<', OHOS::MMI::KeyEvent::KEYCODE_COMMA}, 131886da342Sopenharmony_ci {'>', OHOS::MMI::KeyEvent::KEYCODE_PERIOD}, 132886da342Sopenharmony_ci {'?', OHOS::MMI::KeyEvent::KEYCODE_SLASH}, 133886da342Sopenharmony_ci {'{', OHOS::MMI::KeyEvent::KEYCODE_LEFT_BRACKET}, 134886da342Sopenharmony_ci {'}', OHOS::MMI::KeyEvent::KEYCODE_RIGHT_BRACKET}, 135886da342Sopenharmony_ci {'|', OHOS::MMI::KeyEvent::KEYCODE_BACKSLASH} 136886da342Sopenharmony_ci }; 137886da342Sopenharmony_ci 138886da342Sopenharmony_ci static constexpr EventSpec WATCHED_EVENTS[] = { 139886da342Sopenharmony_ci {"Toast", WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE, "toastShow"}, 140886da342Sopenharmony_ci {"AlertDialog", WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE, "dialogShow"} 141886da342Sopenharmony_ci }; 142886da342Sopenharmony_ci 143886da342Sopenharmony_ci static std::string GetWatchedEvent(const AccessibilityEventInfo &eventInfo) 144886da342Sopenharmony_ci { 145886da342Sopenharmony_ci auto eventCounts = sizeof(WATCHED_EVENTS) / sizeof(EventSpec); 146886da342Sopenharmony_ci for (unsigned long index = 0; index < eventCounts; index++) { 147886da342Sopenharmony_ci if (WATCHED_EVENTS[index].componentTyep == eventInfo.GetComponentType() && 148886da342Sopenharmony_ci WATCHED_EVENTS[index].eventType == eventInfo.GetWindowContentChangeTypes()) { 149886da342Sopenharmony_ci LOG_W("Capture event: %{public}s", WATCHED_EVENTS[index].event.data()); 150886da342Sopenharmony_ci return string(WATCHED_EVENTS[index].event); 151886da342Sopenharmony_ci } 152886da342Sopenharmony_ci } 153886da342Sopenharmony_ci return "undefine"; 154886da342Sopenharmony_ci } 155886da342Sopenharmony_ci 156886da342Sopenharmony_ci // UiEventMonitor instance. 157886da342Sopenharmony_ci static shared_ptr<UiEventMonitor> g_monitorInstance_ = make_shared<UiEventMonitor>(); 158886da342Sopenharmony_ci 159886da342Sopenharmony_ci void UiEventMonitor::SetOnAbilityConnectCallback(function<void()> onConnectCb) 160886da342Sopenharmony_ci { 161886da342Sopenharmony_ci onConnectCallback_ = std::move(onConnectCb); 162886da342Sopenharmony_ci } 163886da342Sopenharmony_ci 164886da342Sopenharmony_ci void UiEventMonitor::SetOnAbilityDisConnectCallback(function<void()> onDisConnectCb) 165886da342Sopenharmony_ci { 166886da342Sopenharmony_ci onDisConnectCallback_ = std::move(onDisConnectCb); 167886da342Sopenharmony_ci } 168886da342Sopenharmony_ci 169886da342Sopenharmony_ci void UiEventMonitor::OnAbilityConnected() 170886da342Sopenharmony_ci { 171886da342Sopenharmony_ci if (onConnectCallback_ != nullptr) { 172886da342Sopenharmony_ci onConnectCallback_(); 173886da342Sopenharmony_ci } 174886da342Sopenharmony_ci } 175886da342Sopenharmony_ci 176886da342Sopenharmony_ci void UiEventMonitor::OnAbilityDisconnected() 177886da342Sopenharmony_ci { 178886da342Sopenharmony_ci if (onDisConnectCallback_ != nullptr) { 179886da342Sopenharmony_ci onDisConnectCallback_(); 180886da342Sopenharmony_ci } 181886da342Sopenharmony_ci } 182886da342Sopenharmony_ci 183886da342Sopenharmony_ci // the monitored events 184886da342Sopenharmony_ci static constexpr uint32_t EVENT_MASK = EventType::TYPE_VIEW_TEXT_UPDATE_EVENT | 185886da342Sopenharmony_ci EventType::TYPE_PAGE_STATE_UPDATE | 186886da342Sopenharmony_ci EventType::TYPE_PAGE_CONTENT_UPDATE | 187886da342Sopenharmony_ci EventType::TYPE_VIEW_SCROLLED_EVENT | 188886da342Sopenharmony_ci EventType::TYPE_WINDOW_UPDATE; 189886da342Sopenharmony_ci 190886da342Sopenharmony_ci void UiEventMonitor::RegisterUiEventListener(std::shared_ptr<UiEventListener> listerner) 191886da342Sopenharmony_ci { 192886da342Sopenharmony_ci listeners_.emplace_back(listerner); 193886da342Sopenharmony_ci } 194886da342Sopenharmony_ci 195886da342Sopenharmony_ci void UiEventMonitor::OnAccessibilityEvent(const AccessibilityEventInfo &eventInfo) 196886da342Sopenharmony_ci { 197886da342Sopenharmony_ci auto eventType = eventInfo.GetEventType(); 198886da342Sopenharmony_ci LOG_D("OnEvent:0x%{public}x", eventType); 199886da342Sopenharmony_ci auto capturedEvent = GetWatchedEvent(eventInfo); 200886da342Sopenharmony_ci if (eventType == Accessibility::EventType::TYPE_VIEW_SCROLLED_START) { 201886da342Sopenharmony_ci LOG_I("Capture scroll begin"); 202886da342Sopenharmony_ci scrollCompelete_.store(false); 203886da342Sopenharmony_ci lastScrollBeginEventMillis_.store(GetCurrentMillisecond()); 204886da342Sopenharmony_ci } 205886da342Sopenharmony_ci if (eventType == Accessibility::EventType::TYPE_VIEW_SCROLLED_EVENT) { 206886da342Sopenharmony_ci LOG_I("Capture scroll end"); 207886da342Sopenharmony_ci scrollCompelete_.store(true); 208886da342Sopenharmony_ci } 209886da342Sopenharmony_ci if (capturedEvent != "undefine") { 210886da342Sopenharmony_ci auto bundleName = eventInfo.GetBundleName(); 211886da342Sopenharmony_ci auto contentList = eventInfo.GetContentList(); 212886da342Sopenharmony_ci auto text = !contentList.empty() ? contentList[0] : ""; 213886da342Sopenharmony_ci auto type = eventInfo.GetComponentType(); 214886da342Sopenharmony_ci UiEventSourceInfo uiEventSourceInfo = {bundleName, text, type}; 215886da342Sopenharmony_ci for (auto &listener : listeners_) { 216886da342Sopenharmony_ci listener->OnEvent(capturedEvent, uiEventSourceInfo); 217886da342Sopenharmony_ci } 218886da342Sopenharmony_ci } 219886da342Sopenharmony_ci if ((eventInfo.GetEventType() & EVENT_MASK) > 0) { 220886da342Sopenharmony_ci lastEventMillis_.store(GetCurrentMillisecond()); 221886da342Sopenharmony_ci } 222886da342Sopenharmony_ci } 223886da342Sopenharmony_ci 224886da342Sopenharmony_ci uint64_t UiEventMonitor::GetLastEventMillis() 225886da342Sopenharmony_ci { 226886da342Sopenharmony_ci if (lastEventMillis_.load() <= 0) { 227886da342Sopenharmony_ci lastEventMillis_.store(GetCurrentMillisecond()); 228886da342Sopenharmony_ci } 229886da342Sopenharmony_ci return lastEventMillis_.load(); 230886da342Sopenharmony_ci } 231886da342Sopenharmony_ci 232886da342Sopenharmony_ci void UiEventMonitor::WaitScrollCompelete() 233886da342Sopenharmony_ci { 234886da342Sopenharmony_ci if (scrollCompelete_.load()) { 235886da342Sopenharmony_ci return; 236886da342Sopenharmony_ci } 237886da342Sopenharmony_ci auto currentMs = GetCurrentMillisecond(); 238886da342Sopenharmony_ci if (lastScrollBeginEventMillis_.load() <= 0) { 239886da342Sopenharmony_ci lastScrollBeginEventMillis_.store(currentMs); 240886da342Sopenharmony_ci } 241886da342Sopenharmony_ci const auto idleThresholdMs = 10000; 242886da342Sopenharmony_ci static constexpr auto sliceMs = 10; 243886da342Sopenharmony_ci while (currentMs - lastScrollBeginEventMillis_.load() < idleThresholdMs) { 244886da342Sopenharmony_ci if (scrollCompelete_.load()) { 245886da342Sopenharmony_ci return; 246886da342Sopenharmony_ci } 247886da342Sopenharmony_ci this_thread::sleep_for(chrono::milliseconds(sliceMs)); 248886da342Sopenharmony_ci currentMs = GetCurrentMillisecond(); 249886da342Sopenharmony_ci } 250886da342Sopenharmony_ci LOG_E("wait for scrollEnd event timeout."); 251886da342Sopenharmony_ci scrollCompelete_.store(true); 252886da342Sopenharmony_ci return; 253886da342Sopenharmony_ci } 254886da342Sopenharmony_ci 255886da342Sopenharmony_ci bool UiEventMonitor::WaitEventIdle(uint32_t idleThresholdMs, uint32_t timeoutMs) 256886da342Sopenharmony_ci { 257886da342Sopenharmony_ci const auto currentMs = GetCurrentMillisecond(); 258886da342Sopenharmony_ci if (lastEventMillis_.load() <= 0) { 259886da342Sopenharmony_ci lastEventMillis_.store(currentMs); 260886da342Sopenharmony_ci } 261886da342Sopenharmony_ci if (currentMs - lastEventMillis_.load() >= idleThresholdMs) { 262886da342Sopenharmony_ci return true; 263886da342Sopenharmony_ci } 264886da342Sopenharmony_ci static constexpr auto sliceMs = 10; 265886da342Sopenharmony_ci this_thread::sleep_for(chrono::milliseconds(sliceMs)); 266886da342Sopenharmony_ci if (timeoutMs <= sliceMs) { 267886da342Sopenharmony_ci return false; 268886da342Sopenharmony_ci } 269886da342Sopenharmony_ci return WaitEventIdle(idleThresholdMs, timeoutMs - sliceMs); 270886da342Sopenharmony_ci } 271886da342Sopenharmony_ci 272886da342Sopenharmony_ci SysUiController::SysUiController() : UiController() {} 273886da342Sopenharmony_ci 274886da342Sopenharmony_ci SysUiController::~SysUiController() 275886da342Sopenharmony_ci { 276886da342Sopenharmony_ci DisConnectFromSysAbility(); 277886da342Sopenharmony_ci } 278886da342Sopenharmony_ci 279886da342Sopenharmony_ci bool SysUiController::Initialize(ApiCallErr &error) 280886da342Sopenharmony_ci { 281886da342Sopenharmony_ci return this->ConnectToSysAbility(error); 282886da342Sopenharmony_ci } 283886da342Sopenharmony_ci 284886da342Sopenharmony_ci static Rect GetVisibleRect(Rect windowBounds, Accessibility::Rect nodeBounds) 285886da342Sopenharmony_ci { 286886da342Sopenharmony_ci auto leftX = nodeBounds.GetLeftTopXScreenPostion(); 287886da342Sopenharmony_ci auto topY = nodeBounds.GetLeftTopYScreenPostion(); 288886da342Sopenharmony_ci auto rightX = nodeBounds.GetRightBottomXScreenPostion(); 289886da342Sopenharmony_ci auto bottomY = nodeBounds.GetRightBottomYScreenPostion(); 290886da342Sopenharmony_ci Rect newBounds((leftX < windowBounds.left_) ? windowBounds.left_ : leftX, 291886da342Sopenharmony_ci (rightX > windowBounds.right_) ? windowBounds.right_ : rightX, 292886da342Sopenharmony_ci (topY < windowBounds.top_) ? windowBounds.top_ : topY, 293886da342Sopenharmony_ci (bottomY > windowBounds.bottom_) ? windowBounds.bottom_ : bottomY); 294886da342Sopenharmony_ci return newBounds; 295886da342Sopenharmony_ci } 296886da342Sopenharmony_ci 297886da342Sopenharmony_ci static void InflateWindowInfo(AccessibilityWindowInfo& node, Window& info) 298886da342Sopenharmony_ci { 299886da342Sopenharmony_ci info.focused_ = node.IsFocused(); 300886da342Sopenharmony_ci info.actived_ = node.IsActive(); 301886da342Sopenharmony_ci info.decoratorEnabled_ = node.IsDecorEnable(); 302886da342Sopenharmony_ci // get bundle name by root node 303886da342Sopenharmony_ci AccessibilityElementInfo element; 304886da342Sopenharmony_ci LOG_D("Start Get Bundle Name by WindowId %{public}d", node.GetWindowId()); 305886da342Sopenharmony_ci if (AccessibilityUITestAbility::GetInstance()->GetRootByWindow(node, element) != RET_OK) { 306886da342Sopenharmony_ci LOG_E("Failed Get Bundle Name by WindowId %{public}d", node.GetWindowId()); 307886da342Sopenharmony_ci } else { 308886da342Sopenharmony_ci std::string app = element.GetBundleName(); 309886da342Sopenharmony_ci LOG_I("End Get Bundle Name by WindowId %{public}d, app is %{public}s", node.GetWindowId(), app.data()); 310886da342Sopenharmony_ci info.bundleName_ = app; 311886da342Sopenharmony_ci const auto foreAbility = AAFwk::AbilityManagerClient::GetInstance()->GetTopAbility(); 312886da342Sopenharmony_ci info.abilityName_ = (app == foreAbility.GetBundleName()) ? foreAbility.GetAbilityName() : ""; 313886da342Sopenharmony_ci info.pagePath_ = (app == foreAbility.GetBundleName()) ? element.GetPagePath() : ""; 314886da342Sopenharmony_ci } 315886da342Sopenharmony_ci info.mode_ = WindowMode::UNKNOWN; 316886da342Sopenharmony_ci const auto origMode = static_cast<OHOS::Rosen::WindowMode>(node.GetWindowMode()); 317886da342Sopenharmony_ci switch (origMode) { 318886da342Sopenharmony_ci case OHOS::Rosen::WindowMode::WINDOW_MODE_FULLSCREEN: 319886da342Sopenharmony_ci info.mode_ = WindowMode::FULLSCREEN; 320886da342Sopenharmony_ci break; 321886da342Sopenharmony_ci case OHOS::Rosen::WindowMode::WINDOW_MODE_SPLIT_PRIMARY: 322886da342Sopenharmony_ci info.mode_ = WindowMode::SPLIT_PRIMARY; 323886da342Sopenharmony_ci break; 324886da342Sopenharmony_ci case OHOS::Rosen::WindowMode::WINDOW_MODE_SPLIT_SECONDARY: 325886da342Sopenharmony_ci info.mode_ = WindowMode::SPLIT_SECONDARY; 326886da342Sopenharmony_ci break; 327886da342Sopenharmony_ci case OHOS::Rosen::WindowMode::WINDOW_MODE_FLOATING: 328886da342Sopenharmony_ci info.mode_ = WindowMode::FLOATING; 329886da342Sopenharmony_ci break; 330886da342Sopenharmony_ci case OHOS::Rosen::WindowMode::WINDOW_MODE_PIP: 331886da342Sopenharmony_ci info.mode_ = WindowMode::PIP; 332886da342Sopenharmony_ci break; 333886da342Sopenharmony_ci default: 334886da342Sopenharmony_ci info.mode_ = WindowMode::UNKNOWN; 335886da342Sopenharmony_ci break; 336886da342Sopenharmony_ci } 337886da342Sopenharmony_ci } 338886da342Sopenharmony_ci 339886da342Sopenharmony_ci static bool GetAamsWindowInfos(vector<AccessibilityWindowInfo> &windows) 340886da342Sopenharmony_ci { 341886da342Sopenharmony_ci auto ability = AccessibilityUITestAbility::GetInstance(); 342886da342Sopenharmony_ci g_monitorInstance_->WaitScrollCompelete(); 343886da342Sopenharmony_ci if (ability->GetWindows(windows) != RET_OK) { 344886da342Sopenharmony_ci LOG_W("GetWindows from AccessibilityUITestAbility failed"); 345886da342Sopenharmony_ci return false; 346886da342Sopenharmony_ci } 347886da342Sopenharmony_ci sort(windows.begin(), windows.end(), [](auto &w1, auto &w2) -> bool { 348886da342Sopenharmony_ci return w1.GetWindowLayer() > w2.GetWindowLayer(); 349886da342Sopenharmony_ci }); 350886da342Sopenharmony_ci return true; 351886da342Sopenharmony_ci } 352886da342Sopenharmony_ci 353886da342Sopenharmony_ci void SysUiController::GetUiWindows(std::vector<Window> &out) 354886da342Sopenharmony_ci { 355886da342Sopenharmony_ci std::lock_guard<std::mutex> dumpLocker(dumpMtx); // disallow concurrent dumpUi 356886da342Sopenharmony_ci ApiCallErr error = ApiCallErr(NO_ERROR); 357886da342Sopenharmony_ci if (!connected_ && !ConnectToSysAbility(error)) { 358886da342Sopenharmony_ci LOG_E("%{public}s", error.message_.c_str()); 359886da342Sopenharmony_ci return; 360886da342Sopenharmony_ci } 361886da342Sopenharmony_ci vector<AccessibilityWindowInfo> windows; 362886da342Sopenharmony_ci LOG_D("Get Window root info"); 363886da342Sopenharmony_ci if (!GetAamsWindowInfos(windows)) { 364886da342Sopenharmony_ci return; 365886da342Sopenharmony_ci } 366886da342Sopenharmony_ci LOG_D("End Get Window root info"); 367886da342Sopenharmony_ci auto screenSize = GetDisplaySize(); 368886da342Sopenharmony_ci auto screenRect = Rect(0, screenSize.px_, 0, screenSize.py_); 369886da342Sopenharmony_ci std::vector<Rect> overplays; 370886da342Sopenharmony_ci // window wrapper 371886da342Sopenharmony_ci for (auto &win : windows) { 372886da342Sopenharmony_ci Rect winRectInScreen = GetVisibleRect(screenRect, win.GetRectInScreen()); 373886da342Sopenharmony_ci Rect visibleArea = winRectInScreen; 374886da342Sopenharmony_ci if (!RectAlgorithm::ComputeMaxVisibleRegion(winRectInScreen, overplays, visibleArea)) { 375886da342Sopenharmony_ci LOG_I("window is covered, windowId : %{public}d, layer is %{public}d", win.GetWindowId(), 376886da342Sopenharmony_ci win.GetWindowLayer()); 377886da342Sopenharmony_ci continue; 378886da342Sopenharmony_ci } 379886da342Sopenharmony_ci LOG_I("window is visible, windowId: %{public}d, active: %{public}d, focus: %{public}d, layer: %{public}d", 380886da342Sopenharmony_ci win.GetWindowId(), win.IsActive(), win.IsFocused(), win.GetWindowLayer()); 381886da342Sopenharmony_ci Window winWrapper{win.GetWindowId()}; 382886da342Sopenharmony_ci InflateWindowInfo(win, winWrapper); 383886da342Sopenharmony_ci winWrapper.bounds_ = winRectInScreen; 384886da342Sopenharmony_ci for (const auto &overWin : overplays) { 385886da342Sopenharmony_ci Rect intersectionRect{0, 0, 0, 0}; 386886da342Sopenharmony_ci if (RectAlgorithm::ComputeIntersection(winRectInScreen, overWin, intersectionRect)) { 387886da342Sopenharmony_ci winWrapper.invisibleBoundsVec_.emplace_back(overWin); 388886da342Sopenharmony_ci } 389886da342Sopenharmony_ci } 390886da342Sopenharmony_ci RectAlgorithm::ComputeMaxVisibleRegion(winWrapper.bounds_, overplays, winWrapper.visibleBounds_); 391886da342Sopenharmony_ci overplays.emplace_back(winRectInScreen); 392886da342Sopenharmony_ci out.emplace_back(std::move(winWrapper)); 393886da342Sopenharmony_ci } 394886da342Sopenharmony_ci } 395886da342Sopenharmony_ci 396886da342Sopenharmony_ci bool SysUiController::GetWidgetsInWindow(const Window &winInfo, unique_ptr<ElementNodeIterator> &elementIterator) 397886da342Sopenharmony_ci { 398886da342Sopenharmony_ci std::lock_guard<std::mutex> dumpLocker(dumpMtx); // disallow concurrent dumpUi 399886da342Sopenharmony_ci if (!connected_) { 400886da342Sopenharmony_ci LOG_W("Connect to AccessibilityUITestAbility failed"); 401886da342Sopenharmony_ci return false; 402886da342Sopenharmony_ci } 403886da342Sopenharmony_ci std::vector<AccessibilityElementInfo> elementInfos; 404886da342Sopenharmony_ci AccessibilityWindowInfo window; 405886da342Sopenharmony_ci LOG_D("Get Window by WindowId %{public}d", winInfo.id_); 406886da342Sopenharmony_ci if (AccessibilityUITestAbility::GetInstance()->GetWindow(winInfo.id_, window) != RET_OK) { 407886da342Sopenharmony_ci LOG_E("GetWindowInfo failed, windowId: %{public}d", winInfo.id_); 408886da342Sopenharmony_ci return false; 409886da342Sopenharmony_ci } 410886da342Sopenharmony_ci LOG_D("Start Get nodes from window by WindowId %{public}d", winInfo.id_); 411886da342Sopenharmony_ci if (AccessibilityUITestAbility::GetInstance()->GetRootByWindowBatch(window, elementInfos) != RET_OK) { 412886da342Sopenharmony_ci LOG_E("GetRootByWindowBatch failed, windowId: %{public}d", winInfo.id_); 413886da342Sopenharmony_ci return false; 414886da342Sopenharmony_ci } else { 415886da342Sopenharmony_ci LOG_I("End Get nodes from window by WindowId %{public}d, node size is %{public}zu, appId: %{public}s", 416886da342Sopenharmony_ci winInfo.id_, elementInfos.size(), winInfo.bundleName_.data()); 417886da342Sopenharmony_ci elementIterator = std::make_unique<ElementNodeIteratorImpl>(elementInfos); 418886da342Sopenharmony_ci } 419886da342Sopenharmony_ci return true; 420886da342Sopenharmony_ci } 421886da342Sopenharmony_ci 422886da342Sopenharmony_ci static void AddPinterItems(PointerEvent &event, const vector<pair<bool, Point>> &fingerStatus, 423886da342Sopenharmony_ci uint32_t currentFinger) 424886da342Sopenharmony_ci { 425886da342Sopenharmony_ci PointerEvent::PointerItem pinterItem1; 426886da342Sopenharmony_ci pinterItem1.SetPointerId(currentFinger); 427886da342Sopenharmony_ci pinterItem1.SetOriginPointerId(currentFinger); 428886da342Sopenharmony_ci pinterItem1.SetDisplayX(fingerStatus[currentFinger].second.px_); 429886da342Sopenharmony_ci pinterItem1.SetDisplayY(fingerStatus[currentFinger].second.py_); 430886da342Sopenharmony_ci pinterItem1.SetPressed(fingerStatus[currentFinger].first); 431886da342Sopenharmony_ci event.UpdatePointerItem(currentFinger, pinterItem1); 432886da342Sopenharmony_ci LOG_D("Add touchItem, finger:%{public}d, pressed:%{public}d, location:%{public}d, %{public}d", 433886da342Sopenharmony_ci currentFinger, fingerStatus[currentFinger].first, fingerStatus[currentFinger].second.px_, 434886da342Sopenharmony_ci fingerStatus[currentFinger].second.py_); 435886da342Sopenharmony_ci // update pinterItem of other fingers which in pressed state. 436886da342Sopenharmony_ci for (uint32_t index = 0; index < fingerStatus.size(); index++) { 437886da342Sopenharmony_ci if (index == currentFinger) { 438886da342Sopenharmony_ci continue; 439886da342Sopenharmony_ci } 440886da342Sopenharmony_ci if (fingerStatus[index].first) { 441886da342Sopenharmony_ci PointerEvent::PointerItem pinterItem; 442886da342Sopenharmony_ci pinterItem.SetPointerId(index); 443886da342Sopenharmony_ci pinterItem.SetOriginPointerId(index); 444886da342Sopenharmony_ci pinterItem.SetDisplayX(fingerStatus[index].second.px_); 445886da342Sopenharmony_ci pinterItem.SetDisplayY(fingerStatus[index].second.py_); 446886da342Sopenharmony_ci pinterItem.SetPressed(true); 447886da342Sopenharmony_ci event.UpdatePointerItem(index, pinterItem); 448886da342Sopenharmony_ci LOG_D("Add touchItem, finger:%{public}d, pressed:%{public}d, location:%{public}d, %{public}d", 449886da342Sopenharmony_ci index, fingerStatus[index].first, fingerStatus[index].second.px_, 450886da342Sopenharmony_ci fingerStatus[index].second.py_); 451886da342Sopenharmony_ci } 452886da342Sopenharmony_ci } 453886da342Sopenharmony_ci } 454886da342Sopenharmony_ci 455886da342Sopenharmony_ci void SysUiController::InjectTouchEventSequence(const PointerMatrix &events) const 456886da342Sopenharmony_ci { 457886da342Sopenharmony_ci // fingerStatus stores the press status and coordinates of each finger. 458886da342Sopenharmony_ci vector<pair<bool, Point>> fingerStatus(events.GetFingers(), make_pair(false, Point(0,0))); 459886da342Sopenharmony_ci for (uint32_t step = 0; step < events.GetSteps(); step++) { 460886da342Sopenharmony_ci for (uint32_t finger = 0; finger < events.GetFingers(); finger++) { 461886da342Sopenharmony_ci auto pointerEvent = PointerEvent::Create(); 462886da342Sopenharmony_ci if (pointerEvent == nullptr) { 463886da342Sopenharmony_ci LOG_E("Creat PointerEvent failed."); 464886da342Sopenharmony_ci return; 465886da342Sopenharmony_ci } 466886da342Sopenharmony_ci bool isPressed = events.At(finger, step).stage_ != ActionStage::UP; 467886da342Sopenharmony_ci fingerStatus[finger] = make_pair(isPressed, events.At(finger, step).point_); 468886da342Sopenharmony_ci pointerEvent->SetPointerId(finger); 469886da342Sopenharmony_ci switch (events.At(finger, step).stage_) { 470886da342Sopenharmony_ci case ActionStage::DOWN: 471886da342Sopenharmony_ci pointerEvent->SetPointerAction(PointerEvent::POINTER_ACTION_DOWN); 472886da342Sopenharmony_ci break; 473886da342Sopenharmony_ci case ActionStage::MOVE: 474886da342Sopenharmony_ci pointerEvent->SetPointerAction(PointerEvent::POINTER_ACTION_MOVE); 475886da342Sopenharmony_ci break; 476886da342Sopenharmony_ci case ActionStage::UP: 477886da342Sopenharmony_ci pointerEvent->SetPointerAction(PointerEvent::POINTER_ACTION_UP); 478886da342Sopenharmony_ci break; 479886da342Sopenharmony_ci default: 480886da342Sopenharmony_ci break; 481886da342Sopenharmony_ci } 482886da342Sopenharmony_ci AddPinterItems(*pointerEvent, fingerStatus, finger); 483886da342Sopenharmony_ci pointerEvent->SetSourceType(PointerEvent::SOURCE_TYPE_TOUCHSCREEN); 484886da342Sopenharmony_ci DisplayManager &displayMgr = DisplayManager::GetInstance(); 485886da342Sopenharmony_ci pointerEvent->SetTargetDisplayId(displayMgr.GetDefaultDisplayId()); 486886da342Sopenharmony_ci InputManager::GetInstance()->SimulateInputEvent(pointerEvent); 487886da342Sopenharmony_ci LOG_D("Inject touchEvent"); 488886da342Sopenharmony_ci if (events.At(finger, step).holdMs_ > 0) { 489886da342Sopenharmony_ci this_thread::sleep_for(chrono::milliseconds(events.At(finger, step).holdMs_)); 490886da342Sopenharmony_ci } 491886da342Sopenharmony_ci } 492886da342Sopenharmony_ci } 493886da342Sopenharmony_ci } 494886da342Sopenharmony_ci 495886da342Sopenharmony_ci static void SetMousePointerItemAttr(const MouseEvent &event, PointerEvent::PointerItem &item) 496886da342Sopenharmony_ci { 497886da342Sopenharmony_ci item.SetPointerId(0); 498886da342Sopenharmony_ci item.SetOriginPointerId(0); 499886da342Sopenharmony_ci item.SetToolType(PointerEvent::TOOL_TYPE_MOUSE); 500886da342Sopenharmony_ci item.SetDisplayX(event.point_.px_); 501886da342Sopenharmony_ci item.SetDisplayY(event.point_.py_); 502886da342Sopenharmony_ci item.SetPressed(false); 503886da342Sopenharmony_ci item.SetDownTime(0); 504886da342Sopenharmony_ci LOG_D("Inject mouseEvent, pressed:%{public}d, location:%{public}d, %{public}d", 505886da342Sopenharmony_ci event.stage_ == ActionStage::DOWN, event.point_.px_, event.point_.py_); 506886da342Sopenharmony_ci } 507886da342Sopenharmony_ci 508886da342Sopenharmony_ci void SysUiController::InjectMouseEvent(const MouseEvent &event) const 509886da342Sopenharmony_ci { 510886da342Sopenharmony_ci auto pointerEvent = PointerEvent::Create(); 511886da342Sopenharmony_ci if (pointerEvent == nullptr) { 512886da342Sopenharmony_ci return; 513886da342Sopenharmony_ci } 514886da342Sopenharmony_ci PointerEvent::PointerItem item; 515886da342Sopenharmony_ci pointerEvent->SetSourceType(PointerEvent::SOURCE_TYPE_MOUSE); 516886da342Sopenharmony_ci pointerEvent->SetPointerId(0); 517886da342Sopenharmony_ci pointerEvent->SetButtonId(event.button_); 518886da342Sopenharmony_ci SetMousePointerItemAttr(event, item); 519886da342Sopenharmony_ci constexpr double axialValue = 15; 520886da342Sopenharmony_ci static bool flag = true; 521886da342Sopenharmony_ci auto injectAxialValue = axialValue; 522886da342Sopenharmony_ci switch (event.stage_) { 523886da342Sopenharmony_ci case ActionStage::DOWN: 524886da342Sopenharmony_ci pointerEvent->SetPointerAction(OHOS::MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN); 525886da342Sopenharmony_ci pointerEvent->SetButtonId(event.button_); 526886da342Sopenharmony_ci pointerEvent->SetButtonPressed(event.button_); 527886da342Sopenharmony_ci item.SetPressed(true); 528886da342Sopenharmony_ci break; 529886da342Sopenharmony_ci case ActionStage::MOVE: 530886da342Sopenharmony_ci pointerEvent->SetPointerAction(OHOS::MMI::PointerEvent::POINTER_ACTION_MOVE); 531886da342Sopenharmony_ci break; 532886da342Sopenharmony_ci case ActionStage::UP: 533886da342Sopenharmony_ci pointerEvent->SetPointerAction(OHOS::MMI::PointerEvent::POINTER_ACTION_BUTTON_UP); 534886da342Sopenharmony_ci pointerEvent->SetButtonId(event.button_); 535886da342Sopenharmony_ci pointerEvent->SetButtonPressed(event.button_); 536886da342Sopenharmony_ci break; 537886da342Sopenharmony_ci case ActionStage::AXIS_UP: 538886da342Sopenharmony_ci pointerEvent->SetPointerAction(OHOS::MMI::PointerEvent::POINTER_ACTION_AXIS_BEGIN); 539886da342Sopenharmony_ci pointerEvent->SetAxisValue(OHOS::MMI::PointerEvent::AXIS_TYPE_SCROLL_VERTICAL, -axialValue); 540886da342Sopenharmony_ci flag = false; 541886da342Sopenharmony_ci break; 542886da342Sopenharmony_ci case ActionStage::AXIS_DOWN: 543886da342Sopenharmony_ci pointerEvent->SetPointerAction(OHOS::MMI::PointerEvent::POINTER_ACTION_AXIS_BEGIN); 544886da342Sopenharmony_ci pointerEvent->SetAxisValue(OHOS::MMI::PointerEvent::AXIS_TYPE_SCROLL_VERTICAL, axialValue); 545886da342Sopenharmony_ci flag = true; 546886da342Sopenharmony_ci break; 547886da342Sopenharmony_ci case ActionStage::AXIS_STOP: 548886da342Sopenharmony_ci pointerEvent->SetPointerAction(OHOS::MMI::PointerEvent::POINTER_ACTION_AXIS_END); 549886da342Sopenharmony_ci injectAxialValue = flag ? axialValue : -axialValue; 550886da342Sopenharmony_ci pointerEvent->SetAxisValue(OHOS::MMI::PointerEvent::AXIS_TYPE_SCROLL_VERTICAL, injectAxialValue); 551886da342Sopenharmony_ci break; 552886da342Sopenharmony_ci default: 553886da342Sopenharmony_ci break; 554886da342Sopenharmony_ci } 555886da342Sopenharmony_ci pointerEvent->AddPointerItem(item); 556886da342Sopenharmony_ci InputManager::GetInstance()->SimulateInputEvent(pointerEvent); 557886da342Sopenharmony_ci this_thread::sleep_for(chrono::milliseconds(event.holdMs_)); 558886da342Sopenharmony_ci } 559886da342Sopenharmony_ci 560886da342Sopenharmony_ci void SysUiController::InjectMouseEventSequence(const vector<MouseEvent> &events) const 561886da342Sopenharmony_ci { 562886da342Sopenharmony_ci for (auto &event : events) { 563886da342Sopenharmony_ci auto keyEvents = event.keyEvents_; 564886da342Sopenharmony_ci if (!keyEvents.empty() && keyEvents.front().stage_ == ActionStage::DOWN) { 565886da342Sopenharmony_ci InjectKeyEventSequence(keyEvents); 566886da342Sopenharmony_ci InjectMouseEvent(event); 567886da342Sopenharmony_ci } else { 568886da342Sopenharmony_ci InjectMouseEvent(event); 569886da342Sopenharmony_ci InjectKeyEventSequence(keyEvents); 570886da342Sopenharmony_ci } 571886da342Sopenharmony_ci } 572886da342Sopenharmony_ci } 573886da342Sopenharmony_ci 574886da342Sopenharmony_ci void SysUiController::InjectKeyEventSequence(const vector<KeyEvent> &events) const 575886da342Sopenharmony_ci { 576886da342Sopenharmony_ci static vector<int32_t> downKeys; 577886da342Sopenharmony_ci for (auto &event : events) { 578886da342Sopenharmony_ci if (event.code_ == KEYCODE_NONE) { 579886da342Sopenharmony_ci continue; 580886da342Sopenharmony_ci } 581886da342Sopenharmony_ci auto keyEvent = OHOS::MMI::KeyEvent::Create(); 582886da342Sopenharmony_ci if (keyEvent == nullptr) { 583886da342Sopenharmony_ci LOG_E("Creat KeyEvent failed."); 584886da342Sopenharmony_ci return; 585886da342Sopenharmony_ci } 586886da342Sopenharmony_ci if (event.stage_ == ActionStage::UP) { 587886da342Sopenharmony_ci auto iter = std::find(downKeys.begin(), downKeys.end(), event.code_); 588886da342Sopenharmony_ci if (iter == downKeys.end()) { 589886da342Sopenharmony_ci LOG_W("Cannot release a not-pressed key: %{public}d", event.code_); 590886da342Sopenharmony_ci continue; 591886da342Sopenharmony_ci } 592886da342Sopenharmony_ci downKeys.erase(iter); 593886da342Sopenharmony_ci keyEvent->SetKeyCode(event.code_); 594886da342Sopenharmony_ci keyEvent->SetKeyAction(OHOS::MMI::KeyEvent::KEY_ACTION_UP); 595886da342Sopenharmony_ci OHOS::MMI::KeyEvent::KeyItem keyItem; 596886da342Sopenharmony_ci keyItem.SetKeyCode(event.code_); 597886da342Sopenharmony_ci keyItem.SetPressed(true); 598886da342Sopenharmony_ci keyEvent->AddKeyItem(keyItem); 599886da342Sopenharmony_ci InputManager::GetInstance()->SimulateInputEvent(keyEvent); 600886da342Sopenharmony_ci LOG_D("Inject keyEvent up, keycode:%{public}d", event.code_); 601886da342Sopenharmony_ci } else { 602886da342Sopenharmony_ci downKeys.push_back(event.code_); 603886da342Sopenharmony_ci for (auto downKey : downKeys) { 604886da342Sopenharmony_ci keyEvent->SetKeyCode(downKey); 605886da342Sopenharmony_ci keyEvent->SetKeyAction(OHOS::MMI::KeyEvent::KEY_ACTION_DOWN); 606886da342Sopenharmony_ci OHOS::MMI::KeyEvent::KeyItem keyItem; 607886da342Sopenharmony_ci keyItem.SetKeyCode(downKey); 608886da342Sopenharmony_ci keyItem.SetPressed(true); 609886da342Sopenharmony_ci keyEvent->AddKeyItem(keyItem); 610886da342Sopenharmony_ci } 611886da342Sopenharmony_ci InputManager::GetInstance()->SimulateInputEvent(keyEvent); 612886da342Sopenharmony_ci LOG_D("Inject keyEvent down, keycode:%{public}d", event.code_); 613886da342Sopenharmony_ci if (event.holdMs_ > 0) { 614886da342Sopenharmony_ci this_thread::sleep_for(chrono::milliseconds(event.holdMs_)); 615886da342Sopenharmony_ci } 616886da342Sopenharmony_ci } 617886da342Sopenharmony_ci } 618886da342Sopenharmony_ci // check not released keys 619886da342Sopenharmony_ci for (auto downKey : downKeys) { 620886da342Sopenharmony_ci LOG_W("Key event sequence injections done with not-released key: %{public}d", downKey); 621886da342Sopenharmony_ci } 622886da342Sopenharmony_ci } 623886da342Sopenharmony_ci 624886da342Sopenharmony_ci void SysUiController::PutTextToClipboard(string_view text) const 625886da342Sopenharmony_ci { 626886da342Sopenharmony_ci OHOS::testserver::TestServerClient::GetInstance().SetPasteData(string(text)); 627886da342Sopenharmony_ci } 628886da342Sopenharmony_ci 629886da342Sopenharmony_ci bool SysUiController::IsWorkable() const 630886da342Sopenharmony_ci { 631886da342Sopenharmony_ci return connected_; 632886da342Sopenharmony_ci } 633886da342Sopenharmony_ci 634886da342Sopenharmony_ci bool SysUiController::GetCharKeyCode(char ch, int32_t &code, int32_t &ctrlCode) const 635886da342Sopenharmony_ci { 636886da342Sopenharmony_ci ctrlCode = KEYCODE_NONE; 637886da342Sopenharmony_ci if (ch >= 'a' && ch <= 'z') { 638886da342Sopenharmony_ci code = OHOS::MMI::KeyEvent::KEYCODE_A + static_cast<int32_t>(ch - 'a'); 639886da342Sopenharmony_ci } else if (ch >= 'A' && ch <= 'Z') { 640886da342Sopenharmony_ci ctrlCode = OHOS::MMI::KeyEvent::KEYCODE_SHIFT_LEFT; 641886da342Sopenharmony_ci code = OHOS::MMI::KeyEvent::KEYCODE_A + static_cast<int32_t>(ch - 'A'); 642886da342Sopenharmony_ci } else if (ch >= '0' && ch <= '9') { 643886da342Sopenharmony_ci code = OHOS::MMI::KeyEvent::KEYCODE_0 + static_cast<int32_t>(ch - '0'); 644886da342Sopenharmony_ci } else if (SingleKeySymbalMap.find(ch) != SingleKeySymbalMap.end()) { 645886da342Sopenharmony_ci code = SingleKeySymbalMap.find(ch)->second; 646886da342Sopenharmony_ci } else if (MultiKeySymbalMap.find(ch) != MultiKeySymbalMap.end()) { 647886da342Sopenharmony_ci ctrlCode = OHOS::MMI::KeyEvent::KEYCODE_SHIFT_LEFT; 648886da342Sopenharmony_ci code = MultiKeySymbalMap.find(ch)->second; 649886da342Sopenharmony_ci } else { 650886da342Sopenharmony_ci return false; 651886da342Sopenharmony_ci } 652886da342Sopenharmony_ci return true; 653886da342Sopenharmony_ci } 654886da342Sopenharmony_ci 655886da342Sopenharmony_ci bool SysUiController::TakeScreenCap(int32_t fd, std::stringstream &errReceiver, Rect rect) const 656886da342Sopenharmony_ci { 657886da342Sopenharmony_ci DisplayManager &displayMgr = DisplayManager::GetInstance(); 658886da342Sopenharmony_ci // get PixelMap from DisplayManager API 659886da342Sopenharmony_ci shared_ptr<PixelMap> pixelMap; 660886da342Sopenharmony_ci if (rect.GetWidth() == 0) { 661886da342Sopenharmony_ci pixelMap = displayMgr.GetScreenshot(displayMgr.GetDefaultDisplayId()); 662886da342Sopenharmony_ci } else { 663886da342Sopenharmony_ci Media::Rect region = {.left = rect.left_, .top = rect.top_, 664886da342Sopenharmony_ci .width = rect.right_ - rect.left_, .height = rect.bottom_ - rect.top_}; 665886da342Sopenharmony_ci Media::Size size = {.width = rect.right_ - rect.left_, .height = rect.bottom_ - rect.top_}; 666886da342Sopenharmony_ci pixelMap = displayMgr.GetScreenshot(displayMgr.GetDefaultDisplayId(), region, size, 0); 667886da342Sopenharmony_ci } 668886da342Sopenharmony_ci if (pixelMap == nullptr) { 669886da342Sopenharmony_ci errReceiver << "Failed to get display pixelMap"; 670886da342Sopenharmony_ci return false; 671886da342Sopenharmony_ci } 672886da342Sopenharmony_ci FILE *fp = fdopen(fd, "wb"); 673886da342Sopenharmony_ci if (fp == nullptr) { 674886da342Sopenharmony_ci perror("File opening failed"); 675886da342Sopenharmony_ci errReceiver << "File opening failed"; 676886da342Sopenharmony_ci return false; 677886da342Sopenharmony_ci } 678886da342Sopenharmony_ci png_structp pngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); 679886da342Sopenharmony_ci if (pngStruct == nullptr) { 680886da342Sopenharmony_ci fclose(fp); 681886da342Sopenharmony_ci return false; 682886da342Sopenharmony_ci } 683886da342Sopenharmony_ci png_infop pngInfo = png_create_info_struct(pngStruct); 684886da342Sopenharmony_ci if (pngInfo == nullptr) { 685886da342Sopenharmony_ci fclose(fp); 686886da342Sopenharmony_ci png_destroy_write_struct(&pngStruct, nullptr); 687886da342Sopenharmony_ci return false; 688886da342Sopenharmony_ci } 689886da342Sopenharmony_ci png_init_io(pngStruct, fp); 690886da342Sopenharmony_ci auto width = static_cast<uint32_t>(pixelMap->GetWidth()); 691886da342Sopenharmony_ci auto height = static_cast<uint32_t>(pixelMap->GetHeight()); 692886da342Sopenharmony_ci auto data = pixelMap->GetPixels(); 693886da342Sopenharmony_ci auto stride = static_cast<uint32_t>(pixelMap->GetRowBytes()); 694886da342Sopenharmony_ci // set png header 695886da342Sopenharmony_ci static constexpr int bitmapDepth = 8; 696886da342Sopenharmony_ci png_set_IHDR(pngStruct, pngInfo, width, height, bitmapDepth, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, 697886da342Sopenharmony_ci PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); 698886da342Sopenharmony_ci png_set_packing(pngStruct); // set packing info 699886da342Sopenharmony_ci png_write_info(pngStruct, pngInfo); // write to header 700886da342Sopenharmony_ci for (uint32_t column = 0; column < height; column++) { 701886da342Sopenharmony_ci png_write_row(pngStruct, data + (column * stride)); 702886da342Sopenharmony_ci } 703886da342Sopenharmony_ci // free/close 704886da342Sopenharmony_ci png_write_end(pngStruct, pngInfo); 705886da342Sopenharmony_ci png_destroy_write_struct(&pngStruct, &pngInfo); 706886da342Sopenharmony_ci (void)fclose(fp); 707886da342Sopenharmony_ci return true; 708886da342Sopenharmony_ci } 709886da342Sopenharmony_ci 710886da342Sopenharmony_ci bool SysUiController::ConnectToSysAbility(ApiCallErr &error) 711886da342Sopenharmony_ci { 712886da342Sopenharmony_ci if (connected_) { 713886da342Sopenharmony_ci return true; 714886da342Sopenharmony_ci } 715886da342Sopenharmony_ci mutex mtx; 716886da342Sopenharmony_ci unique_lock<mutex> uLock(mtx); 717886da342Sopenharmony_ci std::shared_ptr<condition_variable> condition = make_shared<condition_variable>(); 718886da342Sopenharmony_ci auto onConnectCallback = [condition]() { 719886da342Sopenharmony_ci LOG_I("Success connect to AccessibilityUITestAbility"); 720886da342Sopenharmony_ci condition->notify_all(); 721886da342Sopenharmony_ci }; 722886da342Sopenharmony_ci auto onDisConnectCallback = [this]() { this->connected_ = false; }; 723886da342Sopenharmony_ci if (g_monitorInstance_ == nullptr) { 724886da342Sopenharmony_ci g_monitorInstance_ = make_shared<UiEventMonitor>(); 725886da342Sopenharmony_ci } 726886da342Sopenharmony_ci g_monitorInstance_->SetOnAbilityConnectCallback(onConnectCallback); 727886da342Sopenharmony_ci g_monitorInstance_->SetOnAbilityDisConnectCallback(onDisConnectCallback); 728886da342Sopenharmony_ci auto ability = AccessibilityUITestAbility::GetInstance(); 729886da342Sopenharmony_ci if (ability->RegisterAbilityListener(g_monitorInstance_) != RET_OK) { 730886da342Sopenharmony_ci error = ApiCallErr(ERR_INITIALIZE_FAILED, "Can not connect to AAMS, REGISTER_LISTENER_FAILED"); 731886da342Sopenharmony_ci return false; 732886da342Sopenharmony_ci } 733886da342Sopenharmony_ci auto ret = ability->Connect(); 734886da342Sopenharmony_ci LOG_I("Connect to AAMS, result: %{public}d", ret); 735886da342Sopenharmony_ci if (ret != RET_OK) { 736886da342Sopenharmony_ci error = ApiCallErr(ERR_INITIALIZE_FAILED, "Can not connect to AAMS"); 737886da342Sopenharmony_ci if (ret == RET_ERR_CONNECTION_EXIST) { 738886da342Sopenharmony_ci error.message_ += ", RET_ERR_CONNECTION_EXIST"; 739886da342Sopenharmony_ci } else { 740886da342Sopenharmony_ci error.message_ += ", RET_ERR_AAMS"; 741886da342Sopenharmony_ci } 742886da342Sopenharmony_ci return false; 743886da342Sopenharmony_ci } 744886da342Sopenharmony_ci const auto timeout = chrono::milliseconds(7000); 745886da342Sopenharmony_ci if (condition->wait_for(uLock, timeout) == cv_status::timeout) { 746886da342Sopenharmony_ci LOG_E("Wait connection to AccessibilityUITestAbility timed out"); 747886da342Sopenharmony_ci error = ApiCallErr(ERR_INITIALIZE_FAILED, "Can not connect to AAMS, RET_TIMEOUT"); 748886da342Sopenharmony_ci return false; 749886da342Sopenharmony_ci } 750886da342Sopenharmony_ci connected_ = true; 751886da342Sopenharmony_ci return true; 752886da342Sopenharmony_ci } 753886da342Sopenharmony_ci 754886da342Sopenharmony_ci void SysUiController::RegisterUiEventListener(std::shared_ptr<UiEventListener> listener) const 755886da342Sopenharmony_ci { 756886da342Sopenharmony_ci g_monitorInstance_->RegisterUiEventListener(listener); 757886da342Sopenharmony_ci } 758886da342Sopenharmony_ci 759886da342Sopenharmony_ci bool SysUiController::WaitForUiSteady(uint32_t idleThresholdMs, uint32_t timeoutMs) const 760886da342Sopenharmony_ci { 761886da342Sopenharmony_ci return g_monitorInstance_->WaitEventIdle(idleThresholdMs, timeoutMs); 762886da342Sopenharmony_ci } 763886da342Sopenharmony_ci 764886da342Sopenharmony_ci void SysUiController::DisConnectFromSysAbility() 765886da342Sopenharmony_ci { 766886da342Sopenharmony_ci if (!connected_ || g_monitorInstance_ == nullptr) { 767886da342Sopenharmony_ci return; 768886da342Sopenharmony_ci } 769886da342Sopenharmony_ci connected_ = false; 770886da342Sopenharmony_ci mutex mtx; 771886da342Sopenharmony_ci unique_lock<mutex> uLock(mtx); 772886da342Sopenharmony_ci condition_variable condition; 773886da342Sopenharmony_ci auto onDisConnectCallback = [&condition]() { 774886da342Sopenharmony_ci LOG_I("Success disconnect from AccessibilityUITestAbility"); 775886da342Sopenharmony_ci condition.notify_all(); 776886da342Sopenharmony_ci }; 777886da342Sopenharmony_ci g_monitorInstance_->SetOnAbilityDisConnectCallback(onDisConnectCallback); 778886da342Sopenharmony_ci auto ability = AccessibilityUITestAbility::GetInstance(); 779886da342Sopenharmony_ci LOG_I("Start disconnect from AccessibilityUITestAbility"); 780886da342Sopenharmony_ci if (ability->Disconnect() != RET_OK) { 781886da342Sopenharmony_ci LOG_E("Failed to disconnect from AccessibilityUITestAbility"); 782886da342Sopenharmony_ci return; 783886da342Sopenharmony_ci } 784886da342Sopenharmony_ci const auto timeout = chrono::milliseconds(200); 785886da342Sopenharmony_ci if (condition.wait_for(uLock, timeout) == cv_status::timeout) { 786886da342Sopenharmony_ci LOG_E("Wait disconnection from AccessibilityUITestAbility timed out"); 787886da342Sopenharmony_ci return; 788886da342Sopenharmony_ci } 789886da342Sopenharmony_ci } 790886da342Sopenharmony_ci 791886da342Sopenharmony_ci void SysUiController::SetDisplayRotation(DisplayRotation rotation) const 792886da342Sopenharmony_ci { 793886da342Sopenharmony_ci auto display = DisplayManager::GetInstance().GetDefaultDisplay(); 794886da342Sopenharmony_ci if (display == nullptr) { 795886da342Sopenharmony_ci LOG_E("DisplayManager init fail"); 796886da342Sopenharmony_ci return; 797886da342Sopenharmony_ci } 798886da342Sopenharmony_ci auto screenId = display->GetScreenId(); 799886da342Sopenharmony_ci ScreenManager &screenMgr = ScreenManager::GetInstance(); 800886da342Sopenharmony_ci bool isLocked = false; 801886da342Sopenharmony_ci screenMgr.IsScreenRotationLocked(isLocked); 802886da342Sopenharmony_ci if (isLocked) { 803886da342Sopenharmony_ci screenMgr.SetScreenRotationLocked(false); 804886da342Sopenharmony_ci } 805886da342Sopenharmony_ci auto screen = screenMgr.GetScreenById(screenId); 806886da342Sopenharmony_ci if (screen == nullptr) { 807886da342Sopenharmony_ci LOG_E("ScreenManager init fail"); 808886da342Sopenharmony_ci return; 809886da342Sopenharmony_ci } 810886da342Sopenharmony_ci switch (rotation) { 811886da342Sopenharmony_ci case ROTATION_0 : 812886da342Sopenharmony_ci screen->SetOrientation(Orientation::VERTICAL); 813886da342Sopenharmony_ci break; 814886da342Sopenharmony_ci case ROTATION_90 : 815886da342Sopenharmony_ci screen->SetOrientation(Orientation::HORIZONTAL); 816886da342Sopenharmony_ci break; 817886da342Sopenharmony_ci case ROTATION_180 : 818886da342Sopenharmony_ci screen->SetOrientation(Orientation::REVERSE_VERTICAL); 819886da342Sopenharmony_ci break; 820886da342Sopenharmony_ci case ROTATION_270 : 821886da342Sopenharmony_ci screen->SetOrientation(Orientation::REVERSE_HORIZONTAL); 822886da342Sopenharmony_ci break; 823886da342Sopenharmony_ci default : 824886da342Sopenharmony_ci break; 825886da342Sopenharmony_ci } 826886da342Sopenharmony_ci } 827886da342Sopenharmony_ci 828886da342Sopenharmony_ci DisplayRotation SysUiController::GetDisplayRotation() const 829886da342Sopenharmony_ci { 830886da342Sopenharmony_ci auto display = DisplayManager::GetInstance().GetDefaultDisplay(); 831886da342Sopenharmony_ci if (display == nullptr) { 832886da342Sopenharmony_ci LOG_E("DisplayManager init fail"); 833886da342Sopenharmony_ci return DisplayRotation::ROTATION_0; 834886da342Sopenharmony_ci } 835886da342Sopenharmony_ci auto rotation = (DisplayRotation)display->GetRotation(); 836886da342Sopenharmony_ci return rotation; 837886da342Sopenharmony_ci } 838886da342Sopenharmony_ci 839886da342Sopenharmony_ci void SysUiController::SetDisplayRotationEnabled(bool enabled) const 840886da342Sopenharmony_ci { 841886da342Sopenharmony_ci ScreenManager &screenMgr = ScreenManager::GetInstance(); 842886da342Sopenharmony_ci screenMgr.SetScreenRotationLocked(!enabled); 843886da342Sopenharmony_ci } 844886da342Sopenharmony_ci 845886da342Sopenharmony_ci Point SysUiController::GetDisplaySize() const 846886da342Sopenharmony_ci { 847886da342Sopenharmony_ci auto display = DisplayManager::GetInstance().GetDefaultDisplay(); 848886da342Sopenharmony_ci if (display == nullptr) { 849886da342Sopenharmony_ci LOG_E("DisplayManager init fail"); 850886da342Sopenharmony_ci return {0, 0}; 851886da342Sopenharmony_ci } 852886da342Sopenharmony_ci auto width = display->GetWidth(); 853886da342Sopenharmony_ci auto height = display->GetHeight(); 854886da342Sopenharmony_ci LOG_D("GetDisplaysize, width: %{public}d, height: %{public}d", width, height); 855886da342Sopenharmony_ci Point result(width, height); 856886da342Sopenharmony_ci return result; 857886da342Sopenharmony_ci } 858886da342Sopenharmony_ci 859886da342Sopenharmony_ci Point SysUiController::GetDisplayDensity() const 860886da342Sopenharmony_ci { 861886da342Sopenharmony_ci auto display = DisplayManager::GetInstance().GetDefaultDisplay(); 862886da342Sopenharmony_ci if (display == nullptr) { 863886da342Sopenharmony_ci LOG_E("DisplayManager init fail"); 864886da342Sopenharmony_ci return {0, 0}; 865886da342Sopenharmony_ci } 866886da342Sopenharmony_ci auto rate = display->GetVirtualPixelRatio(); 867886da342Sopenharmony_ci Point displaySize = GetDisplaySize(); 868886da342Sopenharmony_ci Point result(displaySize.px_ * rate, displaySize.py_ * rate); 869886da342Sopenharmony_ci return result; 870886da342Sopenharmony_ci } 871886da342Sopenharmony_ci 872886da342Sopenharmony_ci bool SysUiController::IsScreenOn() const 873886da342Sopenharmony_ci { 874886da342Sopenharmony_ci DisplayManager &displayMgr = DisplayManager::GetInstance(); 875886da342Sopenharmony_ci auto displayId = displayMgr.GetDefaultDisplayId(); 876886da342Sopenharmony_ci auto state = displayMgr.GetDisplayState(displayId); 877886da342Sopenharmony_ci return (state != DisplayState::OFF); 878886da342Sopenharmony_ci } 879886da342Sopenharmony_ci 880886da342Sopenharmony_ci class OnSaLoadCallback : public SystemAbilityLoadCallbackStub { 881886da342Sopenharmony_ci public: 882886da342Sopenharmony_ci explicit OnSaLoadCallback(mutex &mutex): mutex_(mutex) {}; 883886da342Sopenharmony_ci ~OnSaLoadCallback() {}; 884886da342Sopenharmony_ci void OnLoadSystemAbilitySuccess(int32_t systemAbilityId, const sptr<IRemoteObject>& remoteObject) override 885886da342Sopenharmony_ci { 886886da342Sopenharmony_ci if (systemAbilityId == OHOS::DFX_HI_DUMPER_SERVICE_ABILITY_ID) { 887886da342Sopenharmony_ci remoteObject_ = remoteObject; 888886da342Sopenharmony_ci mutex_.unlock(); 889886da342Sopenharmony_ci } 890886da342Sopenharmony_ci } 891886da342Sopenharmony_ci void OnLoadSystemAbilityFail(int32_t systemAbilityId) override 892886da342Sopenharmony_ci { 893886da342Sopenharmony_ci if (systemAbilityId == OHOS::DFX_HI_DUMPER_SERVICE_ABILITY_ID) { 894886da342Sopenharmony_ci mutex_.unlock(); 895886da342Sopenharmony_ci } 896886da342Sopenharmony_ci } 897886da342Sopenharmony_ci 898886da342Sopenharmony_ci sptr<IRemoteObject> GetSaObject() 899886da342Sopenharmony_ci { 900886da342Sopenharmony_ci return remoteObject_; 901886da342Sopenharmony_ci } 902886da342Sopenharmony_ci 903886da342Sopenharmony_ci private: 904886da342Sopenharmony_ci mutex &mutex_; 905886da342Sopenharmony_ci sptr<IRemoteObject> remoteObject_ = nullptr; 906886da342Sopenharmony_ci }; 907886da342Sopenharmony_ci 908886da342Sopenharmony_ci static void CreateHidumperCmd(const std::string &windowId, vector<u16string> &result) 909886da342Sopenharmony_ci { 910886da342Sopenharmony_ci result.emplace_back(u"hidumper"); 911886da342Sopenharmony_ci result.emplace_back(u"-s"); 912886da342Sopenharmony_ci result.emplace_back(u"WindowManagerService"); 913886da342Sopenharmony_ci result.emplace_back(u"-a"); 914886da342Sopenharmony_ci auto winIdInUtf16 = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{}.from_bytes(windowId); 915886da342Sopenharmony_ci auto arg = u16string(u"-w ").append(winIdInUtf16).append(u" -default -lastpage"); 916886da342Sopenharmony_ci result.emplace_back(move(arg)); 917886da342Sopenharmony_ci } 918886da342Sopenharmony_ci 919886da342Sopenharmony_ci void SysUiController::GetHidumperInfo(std::string windowId, char **buf, size_t &len) 920886da342Sopenharmony_ci { 921886da342Sopenharmony_ci#ifdef HIDUMPER_ENABLED 922886da342Sopenharmony_ci auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 923886da342Sopenharmony_ci // wati SA start 924886da342Sopenharmony_ci constexpr auto delayMs = 2000; 925886da342Sopenharmony_ci this_thread::sleep_for(chrono::milliseconds(delayMs)); 926886da342Sopenharmony_ci if (sam == nullptr) { 927886da342Sopenharmony_ci LOG_E("Get samgr failed"); 928886da342Sopenharmony_ci return; 929886da342Sopenharmony_ci } 930886da342Sopenharmony_ci auto remoteObject = sam->CheckSystemAbility(OHOS::DFX_HI_DUMPER_SERVICE_ABILITY_ID); 931886da342Sopenharmony_ci if (remoteObject == nullptr) { 932886da342Sopenharmony_ci mutex lock; 933886da342Sopenharmony_ci lock.lock(); 934886da342Sopenharmony_ci sptr<OnSaLoadCallback> loadCallback = new OnSaLoadCallback(lock); 935886da342Sopenharmony_ci if (sam->LoadSystemAbility(OHOS::DFX_HI_DUMPER_SERVICE_ABILITY_ID, loadCallback) != ERR_OK) { 936886da342Sopenharmony_ci LOG_E("Schedule LoadSystemAbility failed"); 937886da342Sopenharmony_ci lock.unlock(); 938886da342Sopenharmony_ci return; 939886da342Sopenharmony_ci } 940886da342Sopenharmony_ci LOG_E("Schedule LoadSystemAbility succeed"); 941886da342Sopenharmony_ci lock.unlock(); 942886da342Sopenharmony_ci remoteObject = loadCallback->GetSaObject(); 943886da342Sopenharmony_ci LOG_E("LoadSystemAbility callbacked, result = %{public}s", remoteObject == nullptr ? "FAIL" : "SUCCESS"); 944886da342Sopenharmony_ci } 945886da342Sopenharmony_ci if (remoteObject == nullptr) { 946886da342Sopenharmony_ci LOG_E("remoteObject is null"); 947886da342Sopenharmony_ci return; 948886da342Sopenharmony_ci } 949886da342Sopenharmony_ci // run dump command 950886da342Sopenharmony_ci sptr<IDumpBroker> client = iface_cast<IDumpBroker>(remoteObject); 951886da342Sopenharmony_ci if (client == nullptr) { 952886da342Sopenharmony_ci LOG_E("IDumpBroker converts failed"); 953886da342Sopenharmony_ci return; 954886da342Sopenharmony_ci } 955886da342Sopenharmony_ci auto fd = memfd_create("dummy_file", 2); 956886da342Sopenharmony_ci ftruncate(fd, 0); 957886da342Sopenharmony_ci vector<u16string> args; 958886da342Sopenharmony_ci CreateHidumperCmd(windowId, args); 959886da342Sopenharmony_ci client->Request(args, fd); 960886da342Sopenharmony_ci auto size = lseek(fd, 0, SEEK_END); 961886da342Sopenharmony_ci char *tempBuf = new char[size + 1]; 962886da342Sopenharmony_ci lseek(fd, 0, SEEK_SET); 963886da342Sopenharmony_ci read(fd, tempBuf, size); 964886da342Sopenharmony_ci *buf = tempBuf; 965886da342Sopenharmony_ci len = size; 966886da342Sopenharmony_ci close(fd); 967886da342Sopenharmony_ci#else 968886da342Sopenharmony_ci *buf = nullptr; 969886da342Sopenharmony_ci len = 0; 970886da342Sopenharmony_ci#endif 971886da342Sopenharmony_ci } 972886da342Sopenharmony_ci} // namespace OHOS::uitest