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