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