1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "component_manager.h" 17 18#include "accessibility_ui_test_ability.h" 19#include "multimode_manager.h" 20 21namespace OHOS { 22namespace WuKong { 23namespace { 24const std::string permissionBundleName = "com.ohos.permissionmanager"; 25const int DIV = 2; 26const int DOWNTIME = 10; 27const int ONESECOND = 1000000; 28const int TWOSECONDS = 2000000; 29const int OFFSET = 10; 30} // namespace 31 32class ComponentEventMonitor : public Accessibility::AccessibleAbilityListener { 33public: 34 virtual ~ComponentEventMonitor() = default; 35 36 void OnAbilityConnected() override; 37 38 void OnAbilityDisconnected() override; 39 40 void OnAccessibilityEvent(const Accessibility::AccessibilityEventInfo& eventInfo) override; 41 42 void SetOnAbilityConnectCallback(std::function<void()> onConnectCb); 43 44 void SetOnAbilityDisConnectCallback(std::function<void()> onDisConnectCb); 45 46 bool OnKeyPressEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent) override 47 { 48 return false; 49 } 50 51 uint64_t GetLastEventMillis(); 52 53 bool WaitEventIdle(uint32_t idleThresholdMs, uint32_t timeoutMs); 54 55private: 56 std::function<void()> onConnectCallback_ = nullptr; 57 std::function<void()> onDisConnectCallback_ = nullptr; 58 std::atomic<uint64_t> lastEventMillis_ = 0; 59}; 60 61void ComponentEventMonitor::SetOnAbilityConnectCallback(std::function<void()> onConnectCb) 62{ 63 onConnectCallback_ = std::move(onConnectCb); 64} 65 66void ComponentEventMonitor::SetOnAbilityDisConnectCallback(std::function<void()> onDisConnectCb) 67{ 68 onDisConnectCallback_ = std::move(onDisConnectCb); 69} 70 71void ComponentEventMonitor::OnAbilityConnected() 72{ 73 if (onConnectCallback_ != nullptr) { 74 onConnectCallback_(); 75 } 76} 77 78void ComponentEventMonitor::OnAbilityDisconnected() 79{ 80 if (onDisConnectCallback_ != nullptr) { 81 onDisConnectCallback_(); 82 } 83} 84 85void ComponentEventMonitor::OnAccessibilityEvent(const Accessibility::AccessibilityEventInfo& eventInfo) 86{ 87 TRACK_LOG_STR("OnAccessibilityEvent Start %u", eventInfo.GetEventType()); 88 TRACK_LOG_STR("current bundle: %s", eventInfo.GetBundleName().c_str()); 89 if (eventInfo.GetBundleName() == permissionBundleName) { 90 auto listenerlist = ComponentManager::GetInstance()->GetListenerList(); 91 for (auto it : listenerlist) { 92 it->OnPermissionScreenShown(); 93 } 94 } 95} 96 97uint64_t ComponentEventMonitor::GetLastEventMillis() 98{ 99 return 0; 100} 101 102bool ComponentEventMonitor::WaitEventIdle(uint32_t idleThresholdMs, uint32_t timeoutMs) 103{ 104 return true; 105} 106 107ComponentManager::ComponentManager() 108{ 109 componentMap_ = { 110 {Accessibility::ACCESSIBILITY_ACTION_CLICK, 111 [this] (Accessibility::AccessibilityElementInfo& elementInfo) -> ErrCode { 112 return ComponentManager::ComponentTouchInput(elementInfo); 113 }}, 114 {Accessibility::ACCESSIBILITY_ACTION_SCROLL_FORWARD, 115 [this] (Accessibility::AccessibilityElementInfo& elementInfo) -> ErrCode { 116 return ComponentManager::ComponentUpSwapInput(elementInfo); 117 }}, 118 {Accessibility::ACCESSIBILITY_ACTION_SCROLL_BACKWARD, 119 [this] (Accessibility::AccessibilityElementInfo& elementInfo) -> ErrCode { 120 return ComponentManager::ComponentDownSwapInput(elementInfo); 121 }}, 122 {Accessibility::ACCESSIBILITY_ACTION_SET_TEXT, 123 [this] (Accessibility::AccessibilityElementInfo& elementInfo) -> ErrCode { 124 return ComponentManager::ComponentMultikeyInput(elementInfo); 125 }}, 126 {COMPONENT_LEFT_SWAP, 127 [this] (Accessibility::AccessibilityElementInfo& elementInfo) -> ErrCode { 128 return ComponentManager::ComponentLeftSwapInput(elementInfo); 129 }}, 130 }; 131} 132ComponentManager::~ComponentManager() 133{ 134} 135 136bool ComponentManager::Connect() 137{ 138 if (connected_ == true) { 139 return true; 140 } 141 std::mutex mtx; 142 std::unique_lock<std::mutex> uLock(mtx); 143 std::shared_ptr<ComponentEventMonitor> g_monitorInstance_ = std::make_shared<ComponentEventMonitor>(); 144 std::condition_variable condition; 145 auto onConnectCallback = [&condition]() { 146 std::cout << "Success connect to AAMS" << std::endl; 147 condition.notify_all(); 148 }; 149 150 g_monitorInstance_->SetOnAbilityConnectCallback(onConnectCallback); 151 auto ability = Accessibility::AccessibilityUITestAbility::GetInstance(); 152 if (ability->RegisterAbilityListener(g_monitorInstance_) != Accessibility::RET_OK) { 153 std::cout << "Failed to register ComponentEventMonitor" << std::endl; 154 return false; 155 } 156 std::cout << "Start connect to AAMS" << std::endl; 157 if (ability->Connect() != Accessibility::RET_OK) { 158 std::cout << "Failed to connect to AAMS" << std::endl; 159 return false; 160 } 161 const auto timeout = std::chrono::milliseconds(1000); 162 if (condition.wait_for(uLock, timeout) == std::cv_status::timeout) { 163 std::cout << "Wait connection to AAMS timed out" << std::endl; 164 return false; 165 } 166 connected_ = true; 167 return true; 168} 169 170void ComponentManager::Disconnect() 171{ 172 auto auita = Accessibility::AccessibilityUITestAbility::GetInstance(); 173 if (auita != nullptr) { 174 auita->Disconnect(); 175 } 176 connected_ = false; 177} 178uint32_t ComponentManager::AddRegisterListener(std::shared_ptr<ComponentManagerListener> listener) 179{ 180 TRACK_LOG_STD(); 181 listenerList_.push_back(listener); 182 TRACK_LOG_STR("Add linstener count (%d)", listenerList_.size()); 183 return listenerList_.size() - 1; 184} 185 186void ComponentManager::DeleteRegisterListener(const uint32_t handle) 187{ 188 if (listenerList_.size() > handle) { 189 listenerList_.erase(listenerList_.begin() + handle); 190 } 191} 192 193std::vector<std::shared_ptr<ComponentManagerListener>> ComponentManager::GetListenerList() 194{ 195 return listenerList_; 196} 197 198ErrCode ComponentManager::GetReportInfo(std::string& info) 199{ 200 ErrCode result = OHOS::ERR_OK; 201 return result; 202} 203 204ErrCode ComponentManager::PermoissionInput() 205{ 206 DEBUG_LOG("handle permission window"); 207 return OHOS::ERR_OK; 208} 209 210ErrCode ComponentManager::CreateEventInputMap() 211{ 212 return OHOS::ERR_OK; 213} 214 215ErrCode ComponentManager::ComponentEventInput(OHOS::Accessibility::AccessibilityElementInfo& elementInfo, 216 const int actionType) 217{ 218 CreateEventInputMap(); 219 // get position of current component 220 GetComponentPosition(elementInfo); 221 auto componentRespond = componentMap_[actionType]; 222 if (componentRespond == nullptr) { 223 componentRespond = componentMap_[Accessibility::ACCESSIBILITY_ACTION_CLICK]; 224 } 225 ErrCode result = componentRespond(elementInfo); 226 return result; 227} 228 229ErrCode ComponentManager::ComponentTouchInput(Accessibility::AccessibilityElementInfo& elementInfo) 230{ 231 ErrCode result; 232 auto touchInput = MultimodeManager::GetInstance(); 233 // Calculate touch position 234 int32_t elementTouchX = startX_ + (endX_ - startX_) / DIV; 235 int32_t elementTouchY = startY_ + (endY_ - startY_) / DIV; 236 std::string type = elementInfo.GetContent(); 237 INFO_LOG_STR("component Content: Touch Position: (%d, %d)", elementTouchX, elementTouchY); 238 DEBUG_LOG_STR("component Content: (%s), Touch Position: (%d, %d)", type.c_str(), elementTouchX, elementTouchY); 239 result = touchInput->PointerInput(elementTouchX, elementTouchY, MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN, 240 MMI::PointerEvent::POINTER_ACTION_DOWN); 241 if (result == OHOS::ERR_OK) { 242 result = touchInput->PointerInput(elementTouchX, elementTouchY, MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN, 243 MMI::PointerEvent::POINTER_ACTION_UP); 244 } 245 return result; 246} 247 248ErrCode ComponentManager::BackToPrePage() 249{ 250 ErrCode result = ERR_OK; 251 int backKeyCode = OHOS::MMI::KeyEvent::KEYCODE_BACK; 252 result = MultimodeManager::GetInstance()->SingleKeyCodeInput(backKeyCode, DOWNTIME); 253 return result; 254} 255 256ErrCode ComponentManager::ComponentUpSwapInput(Accessibility::AccessibilityElementInfo& elementInfo) 257{ 258 // Calculate swap position 259 int32_t componentUpSwapStartX = startX_ + (endX_ - startX_) / DIV; 260 int32_t componentUpSwapStartY = endY_ - OFFSET; 261 int32_t componentUpSwapEndX = componentUpSwapStartX; 262 int32_t componentUpSwapEndY = startY_ + OFFSET; 263 INFO_LOG_STR("Component Up Swap: (%d, %d) -> (%d, %d)", componentUpSwapStartX, componentUpSwapStartY, 264 componentUpSwapEndX, componentUpSwapEndY); 265 ErrCode result = MultimodeManager::GetInstance()->IntervalSwap(componentUpSwapStartX, componentUpSwapStartY, 266 componentUpSwapEndX, componentUpSwapEndY); 267 usleep(TWOSECONDS); 268 return result; 269} 270 271ErrCode ComponentManager::ComponentDownSwapInput(Accessibility::AccessibilityElementInfo& elementInfo) 272{ 273 // Calculate swap position 274 int32_t componentDownSwapStartX = startX_ + (endX_ - startX_) / DIV; 275 int32_t componentDownSwapStartY = startY_ + OFFSET; 276 int32_t componentDownSwapEndX = componentDownSwapStartX; 277 int32_t componentDownSwapEndY = endY_ - OFFSET; 278 INFO_LOG_STR("Component Down Swap: (%d, %d) -> (%d, %d)", componentDownSwapStartX, componentDownSwapStartY, 279 componentDownSwapEndX, componentDownSwapEndY); 280 ErrCode result = MultimodeManager::GetInstance()->IntervalSwap(componentDownSwapStartX, componentDownSwapStartY, 281 componentDownSwapEndX, componentDownSwapEndY); 282 usleep(TWOSECONDS); 283 return result; 284} 285 286ErrCode ComponentManager::ComponentMultikeyInput(Accessibility::AccessibilityElementInfo& elementInfo) 287{ 288 ErrCode result = ComponentTouchInput(elementInfo); 289 if (result != OHOS::ERR_OK) { 290 return result; 291 } 292 usleep(ONESECOND); 293 result = MultimodeManager::GetInstance()->MultiKeyCodeInput(DOWNTIME); 294 return result; 295} 296 297ErrCode ComponentManager::ComponentLeftSwapInput(Accessibility::AccessibilityElementInfo& elementInfo) 298{ 299 ErrCode result; 300 // Calculate swap position 301 int32_t leftSwapStartX = startX_ + OFFSET; 302 int32_t leftSwapEndX = endX_ + OFFSET; 303 int32_t leftSwapStartY = startY_ + (endY_ - startY_) / DIV; 304 int32_t leftSwapEndY = leftSwapStartY; 305 INFO_LOG_STR("Component Left Swap: (%d, %d) -> (%d, %d)", leftSwapStartX, leftSwapStartY, leftSwapEndX, 306 leftSwapEndY); 307 result = MultimodeManager::GetInstance()->IntervalSwap(leftSwapStartX, leftSwapStartY, leftSwapEndX, leftSwapEndY); 308 return result; 309} 310 311void ComponentManager::GetComponentPosition(Accessibility::AccessibilityElementInfo& elementInfo) 312{ 313 Accessibility::Rect componentBounds = elementInfo.GetRectInScreen(); 314 startX_ = componentBounds.GetLeftTopXScreenPostion(); 315 startY_ = componentBounds.GetLeftTopYScreenPostion(); 316 endX_ = componentBounds.GetRightBottomXScreenPostion(); 317 endY_ = componentBounds.GetRightBottomYScreenPostion(); 318} 319} // namespace WuKong 320} // namespace OHOS 321