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 
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     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 
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         [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 }
~ComponentManager()132 ComponentManager::~ComponentManager()
133 {
134 }
135 
Connect()136 bool 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 
Disconnect()170 void ComponentManager::Disconnect()
171 {
172     auto auita = Accessibility::AccessibilityUITestAbility::GetInstance();
173     if (auita != nullptr) {
174         auita->Disconnect();
175     }
176     connected_ = false;
177 }
AddRegisterListener(std::shared_ptr<ComponentManagerListener> listener)178 uint32_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 
DeleteRegisterListener(const uint32_t handle)186 void ComponentManager::DeleteRegisterListener(const uint32_t handle)
187 {
188     if (listenerList_.size() > handle) {
189         listenerList_.erase(listenerList_.begin() + handle);
190     }
191 }
192 
GetListenerList()193 std::vector<std::shared_ptr<ComponentManagerListener>> ComponentManager::GetListenerList()
194 {
195     return listenerList_;
196 }
197 
GetReportInfo(std::string& info)198 ErrCode ComponentManager::GetReportInfo(std::string& info)
199 {
200     ErrCode result = OHOS::ERR_OK;
201     return result;
202 }
203 
PermoissionInput()204 ErrCode ComponentManager::PermoissionInput()
205 {
206     DEBUG_LOG("handle permission window");
207     return OHOS::ERR_OK;
208 }
209 
CreateEventInputMap()210 ErrCode ComponentManager::CreateEventInputMap()
211 {
212     return OHOS::ERR_OK;
213 }
214 
ComponentEventInput(OHOS::Accessibility::AccessibilityElementInfo& elementInfo, const int actionType)215 ErrCode 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 
ComponentTouchInput(Accessibility::AccessibilityElementInfo& elementInfo)229 ErrCode 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 
BackToPrePage()248 ErrCode 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 
ComponentUpSwapInput(Accessibility::AccessibilityElementInfo& elementInfo)256 ErrCode 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 
ComponentDownSwapInput(Accessibility::AccessibilityElementInfo& elementInfo)271 ErrCode 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 
ComponentMultikeyInput(Accessibility::AccessibilityElementInfo& elementInfo)286 ErrCode 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 
ComponentLeftSwapInput(Accessibility::AccessibilityElementInfo& elementInfo)297 ErrCode 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 
GetComponentPosition(Accessibility::AccessibilityElementInfo& elementInfo)311 void 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