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_input.h"
17
18 #include "component_manager.h"
19 #include "input_factory.h"
20 #include "input_manager.h"
21 #include "input_msg_object.h"
22 #include "report.h"
23 #include "scene_delegate.h"
24 #include "focus_scene_delegate.h"
25 #include "tree_manager.h"
26 #include "wukong_define.h"
27
28 namespace OHOS {
29 namespace WuKong {
30 namespace {
31 const uint32_t PAGE_BACK_COUNT_MAX = 3;
32 const uint32_t LANUCH_APP_COUNT_MAX = 5;
33
PrepareApp()34 void PrepareApp()
35 {
36 // Wait for the App to be launched successfully
37 bool isFirstStartApp = WuKongUtil::GetInstance()->GetIsFirstStartAppFlag();
38 if (isFirstStartApp) {
39 usleep(THREE_SECOND);
40 WuKongUtil::GetInstance()->SetIsFirstStartAppFlag(false);
41 }
42 }
43
HandleAllBundleStatus(const std::shared_ptr<ComponentParam> & componentPtr)44 void HandleAllBundleStatus(const std::shared_ptr<ComponentParam>& componentPtr)
45 {
46 componentPtr->isAllFinished_ = true;
47 // confirm all bundle status.
48 std::vector<bool> bundleFinishList = componentPtr->bundleFinish_;
49 bool x = false;
50 if (std::any_of(bundleFinishList.begin(), bundleFinishList.end(), [x](int y) { return x == y; })) {
51 componentPtr->isAllFinished_ = false;
52 }
53 }
54
LauncherApp(const std::string & bundleName)55 ErrCode LauncherApp(const std::string& bundleName)
56 {
57 auto appInput = InputFactory::GetInputAction(INPUTTYPE_APPSWITCHINPUT);
58 if (appInput == nullptr) {
59 ERROR_LOG("InputFactory::GetInputAction INPUTTYPE_APPSWITCHINPUT is null");
60 return OHOS::ERR_INVALID_VALUE;
61 }
62
63 // launch app by AppSwitchInput function.
64 std::shared_ptr<AppSwitchParam> appSwitchParam = std::make_shared<AppSwitchParam>();
65 appSwitchParam->bundlename_ = bundleName;
66 std::shared_ptr<SpcialTestObject> sto = appSwitchParam;
67 auto result = appInput->OrderInput(sto);
68 if (result != OHOS::ERR_OK) {
69 ERROR_LOG("AppSwitchInput OrderInput failed");
70 }
71 return result;
72 }
73
CheckLauncherApp(const std::shared_ptr<ComponentParam> & param)74 uint32_t CheckLauncherApp(const std::shared_ptr<ComponentParam>& param)
75 {
76 TRACK_LOG_STD();
77 std::vector<std::string> tempAllowList;
78 for (uint32_t i = 0; i < param->bundleName_.size(); i++) {
79 // do not launch app when bundle is running.
80 if (param->bundleRunning_[i] == true && param->bundleFinish_[i] == false) {
81 return i;
82 }
83 // launch app when the bundle is stop and not finish.
84 if (param->bundleRunning_[i] == false && param->bundleFinish_[i] == false) {
85 tempAllowList.clear();
86 tempAllowList.push_back(param->bundleName_[i]);
87 WuKongUtil::GetInstance()->SetTempAllowList(tempAllowList);
88 // launch app by AppSwitchInput function.
89 if (LauncherApp(param->bundleName_[i]) != OHOS::ERR_OK) {
90 return param->bundleName_.size();
91 }
92 // init bundleRunning status to stop.
93 std::vector<bool> bundleRunning = param->bundleRunning_;
94 std::fill(bundleRunning.begin(), bundleRunning.end(), false);
95
96 // set current launched bundle is running.
97 param->bundleRunning_[i] = true;
98 TRACK_LOG_STR("%s", param->toString().c_str());
99 TEST_RUN_LOG(param->bundleName_[i].c_str());
100 return i;
101 }
102 }
103 // not found bundle can be run, and return failed.
104 return param->bundleName_.size();
105 }
106
CheckAbliltyFinished(const std::shared_ptr<AbilityTree> & abilityNode)107 bool CheckAbliltyFinished(const std::shared_ptr<AbilityTree>& abilityNode)
108 {
109 TRACK_LOG_STD();
110 bool abilityRunFinished = false;
111 if (abilityNode == nullptr) {
112 ERROR_LOG("abilityNode is nullptr");
113 return abilityRunFinished;
114 }
115 uint32_t allCount = abilityNode->GetAllComponentCount();
116 uint32_t inputCount = abilityNode->GetInputCount();
117 TRACK_LOG_STR("ability (%s) component count (%u), input count (%u)", abilityNode->GetBundleName().c_str(), allCount,
118 inputCount);
119 if (inputCount >= allCount) {
120 abilityRunFinished = true;
121 }
122 TRACK_LOG_END();
123 return abilityRunFinished;
124 }
125
CheckBundleFinished(const std::shared_ptr<WuKongTree> & parent)126 bool CheckBundleFinished(const std::shared_ptr<WuKongTree>& parent)
127 {
128 if (!CheckAbliltyFinished(std::static_pointer_cast<AbilityTree>(parent))) {
129 return false;
130 }
131 for (auto child : parent->GetChildren()) {
132 if (!CheckBundleFinished(std::static_pointer_cast<AbilityTree>(child))) {
133 return false;
134 }
135 }
136 return true;
137 }
138
CheckInputFinished(const std::shared_ptr<ComponentParam> & param)139 bool CheckInputFinished(const std::shared_ptr<ComponentParam>& param)
140 {
141 TRACK_LOG_STD();
142 bool isFinished = false;
143 auto currentAbilityPtr = TreeManager::GetInstance()->GetCurrentAbility();
144 if (currentAbilityPtr == nullptr) {
145 ERROR_LOG("GetCurrentAbility abilityNode is nullptr");
146 return isFinished;
147 }
148
149 // check app input event finished and set param is finished.
150 if (CheckBundleFinished(WuKongTree::GetRoot(currentAbilityPtr))) {
151 for (uint32_t i = 0; i < param->bundleRunning_.size(); i++) {
152 if (param->bundleRunning_[i] && param->bundleName_[i] == currentAbilityPtr->GetBundleName()) {
153 param->bundleFinish_[i] = true;
154 isFinished = true;
155 break;
156 }
157 }
158 }
159
160 TRACK_LOG_END();
161 return isFinished;
162 }
163
JudgeBackResult(const std::shared_ptr<ComponentParam> & param,uint32_t launchIndex)164 ErrCode JudgeBackResult(const std::shared_ptr<ComponentParam>& param, uint32_t launchIndex)
165 {
166 TRACK_LOG_STD();
167 ErrCode result;
168 param->pageBack_[launchIndex]++;
169 TRACK_LOG_STR("back count: %d", param->pageBack_[launchIndex]);
170 if (param->pageBack_[launchIndex] > PAGE_BACK_COUNT_MAX) {
171 result = LauncherApp(param->bundleName_[launchIndex]);
172 if (result != OHOS::ERR_OK) {
173 return result;
174 }
175 param->pageBack_[launchIndex] = 0;
176 param->lanuchCount_[launchIndex]++;
177 TRACK_LOG_STR("lanuchCount_[%d] = %d", launchIndex, param->lanuchCount_[launchIndex]);
178 if (param->lanuchCount_[launchIndex] > LANUCH_APP_COUNT_MAX) {
179 param->bundleFinish_[launchIndex] = true;
180 ERROR_LOG("Failed to launch the app five times in a row and exit");
181 param->lanuchCount_[launchIndex] = 0;
182 return OHOS::ERR_INVALID_VALUE;
183 }
184 } else {
185 result = ComponentManager::GetInstance()->BackToPrePage();
186 }
187 TRACK_LOG_END();
188 return result;
189 }
190 } // namespace
ComponentInput()191 ComponentInput::ComponentInput() : InputAction()
192 {
193 }
194
~ComponentInput()195 ComponentInput::~ComponentInput()
196 {
197 }
198
OrderInput(const std::shared_ptr<SpcialTestObject> & specialTestObject)199 ErrCode ComponentInput::OrderInput(const std::shared_ptr<SpcialTestObject>& specialTestObject)
200 {
201 auto componentPtr = std::static_pointer_cast<ComponentParam>(specialTestObject);
202 if (componentPtr == nullptr) {
203 ERROR_LOG("specialTestObject param is null");
204 return OHOS::ERR_INVALID_VALUE;
205 }
206 // launch app and check if app has been started
207 uint32_t launchIndex = CheckLauncherApp(componentPtr);
208 if (launchIndex >= componentPtr->bundleName_.size()) {
209 ERROR_LOG("launcher app failed, and stop run test");
210 componentPtr->isAllFinished_ = true;
211 ERROR_LOG(componentPtr->toString().c_str());
212 return OHOS::ERR_INVALID_VALUE;
213 }
214 auto treemanager = TreeManager::GetInstance();
215 auto delegate = SceneDelegate::GetInstance();
216 PrepareApp();
217 // update component information
218 ErrCode result = treemanager->UpdateComponentInfo();
219 DEBUG_LOG_STR("update componentinfo result (%d)", result);
220 if (result == OHOS::ERR_OK) {
221 // choose scene and set valid components
222 result = delegate->ChooseScene(false);
223 if (result != OHOS::ERR_OK) {
224 ERROR_LOG("choose scene failed");
225 return result;
226 }
227 // judge if is neccessnary to back to previous page
228 if (delegate->IsBackToPrePage()) {
229 result = JudgeBackResult(componentPtr, launchIndex);
230 if (result != OHOS::ERR_OK) {
231 return result;
232 }
233 } else {
234 // get the component from tree manager to input action
235 auto elementInfo = treemanager->GetElementInfoByOrder();
236 if (elementInfo == nullptr) {
237 ERROR_LOG("elementinfo is nullptr");
238 return OHOS::ERR_INVALID_VALUE;
239 }
240 // get the actions of component
241 int actionType = JudgeComponentType(*(elementInfo.get()));
242 if (actionType == Accessibility::ACCESSIBILITY_ACTION_INVALID) {
243 actionType = OHOS::Accessibility::ACCESSIBILITY_ACTION_CLICK;
244 }
245 // input action to component
246 result = ComponentManager::GetInstance()->ComponentEventInput(*(elementInfo.get()), actionType);
247 if (result == OHOS::ERR_OK) {
248 // record index of inputted component
249 treemanager->SetInputcomponentIndex(actionType);
250 componentPtr->pageBack_[launchIndex] = 0;
251 componentPtr->lanuchCount_[launchIndex] = 0;
252 std::shared_ptr<ComponmentInputMsg> componentInputMsg = std::make_shared<ComponmentInputMsg>();
253 componentInputMsg->pageComponments = delegate->GetComponentTypeList();
254 componentInputMsg->pageId_ = delegate->GetCurrentPageId();
255 componentInputMsg->componmentType_ = elementInfo->GetComponentType();
256 Report::GetInstance()->SyncInputInfo(componentInputMsg);
257 }
258 }
259 }
260 // check current bundle finished state.
261 if (CheckInputFinished(componentPtr)) {
262 HandleAllBundleStatus(componentPtr);
263 }
264 DEBUG_LOG_STR("component order input result (%d)", result);
265 return result;
266 }
267
RandomInput()268 ErrCode ComponentInput::RandomInput()
269 {
270 auto treemanager = TreeManager::GetInstance();
271 ErrCode result = treemanager->UpdateComponentInfo();
272 DEBUG_LOG_STR("update componentinfo result (%d)", result);
273 if (result == OHOS::ERR_OK) {
274 auto delegate = SceneDelegate::GetInstance();
275 delegate->ChooseScene(true);
276 auto componentInfos = treemanager->GetActiveElementInfos();
277 auto wComponentInfos = treemanager->GetActiveComponentInfos();
278 DEBUG_LOG_STR("component list size (%d)", componentInfos.size());
279 DEBUG_LOG_STR("back: %d", delegate->IsBackToPrePage());
280 if (delegate->IsBackToPrePage()) {
281 DEBUG_LOG("componentInputBranch1");
282 result = ComponentManager::GetInstance()->BackToPrePage();
283 DEBUG_LOG("componentInputBranch1 end");
284 } else if (componentInfos.size() > 0) {
285 DEBUG_LOG("componentInputBranch2");
286 uint32_t index = (uint32_t)(rand()) % componentInfos.size();
287 DEBUG_LOG_STR("component input index (%d), NodeId (%d)", index,
288 wComponentInfos[index]->GetNodeId());
289 int actionType = JudgeComponentType(*(componentInfos[index].get()));
290 if (actionType == Accessibility::ACCESSIBILITY_ACTION_INVALID) {
291 actionType = OHOS::Accessibility::ACCESSIBILITY_ACTION_CLICK;
292 }
293 DEBUG_LOG("componentInputBranch2 before input");
294 result = ComponentManager::GetInstance()->ComponentEventInput(*(componentInfos[index].get()), actionType);
295 DEBUG_LOG("componentInputBranch2 after input");
296 if (result == OHOS::ERR_OK) {
297 treemanager->SetInputcomponentIndex(actionType, index);
298 std::shared_ptr<ComponmentInputMsg> componentInputMsg = std::make_shared<ComponmentInputMsg>();
299 DEBUG_LOG("componentInputBranch2 after componentInputMsg");
300 componentInputMsg->pageComponments = delegate->GetComponentTypeList();
301 componentInputMsg->pageId_ = delegate->GetCurrentPageId();
302 componentInputMsg->componmentType_ = componentInfos[index]->GetComponentType();
303 DEBUG_LOG("componentInputBranch2 before SyncInputInfo");
304 Report::GetInstance()->SyncInputInfo(componentInputMsg);
305 DEBUG_LOG("componentInputBranch2 after SyncInputInfo");
306 }
307 DEBUG_LOG("componentInputBranch2 end");
308 } else {
309 DEBUG_LOG("componentInputBranch3");
310 ERROR_LOG("component list is null");
311 result = OHOS::ERR_NO_INIT;
312 }
313 }
314 DEBUG_LOG_STR("component random input result (%d)", result);
315 return result;
316 }
317
FocusInput(bool shouldScreenCap)318 ErrCode ComponentInput::FocusInput(bool shouldScreenCap)
319 {
320 auto treemanager = TreeManager::GetInstance();
321 ErrCode result = treemanager->UpdateComponentInfo();
322 auto componentManager = ComponentManager::GetInstance();
323 DEBUG_LOG_STR("update componentinfo result (%d)", result);
324 if (result == OHOS::ERR_OK) {
325 auto delegate = FocusSceneDelegate::GetInstance();
326 delegate->ChooseScene(true);
327 auto componentInfos = treemanager->GetActiveElementInfos();
328 auto wComponentInfos = treemanager->GetActiveComponentInfos();
329 DEBUG_LOG_STR("component list size (%d)", componentInfos.size());
330 DEBUG_LOG_STR("back: %d", delegate->IsBackToPrePage());
331 if (delegate->IsBackToPrePage()) {
332 result = componentManager->BackToPrePage();
333 } else if (componentInfos.size() > 0) {
334 uint32_t index = ChooseRightComponentIndex(componentInfos, wComponentInfos, shouldScreenCap);
335 DEBUG_LOG_STR("after ChooseRightComponentIndex (%d), comp cnt (%d)index (%d)",
336 componentInfos.size(), wComponentInfos.size(), index);
337 auto componentinfo = componentInfos[index];
338 DEBUG_LOG_STR("component input index (%d), NodeId (%d)", index,
339 wComponentInfos[index]->GetNodeId());
340 int actionType = JudgeComponentType(*(componentinfo.get()));
341 if (actionType == Accessibility::ACCESSIBILITY_ACTION_INVALID) {
342 actionType = OHOS::Accessibility::ACCESSIBILITY_ACTION_CLICK;
343 }
344
345 result = componentManager->ComponentEventInput(*(componentinfo.get()), actionType);
346 DEBUG_LOG_STR("after ChooseRightComponentIndex3 (%d), index (%d)", componentInfos.size(), index);
347 DEBUG_LOG_STR("action type: %d, sequence input: %d", actionType, result);
348 if (result == OHOS::ERR_OK) {
349 treemanager->SetInputcomponentIndex(actionType, index);
350 std::shared_ptr<ComponmentInputMsg> componentInputMsg = std::make_shared<ComponmentInputMsg>();
351 componentInputMsg->pageComponments = delegate->GetComponentTypeList();
352 componentInputMsg->componmentType_ = componentinfo->GetComponentType();
353 componentInputMsg->pagePath_ = componentinfo->GetPagePath();
354 componentInputMsg->startX_ = componentManager->GetStartX();
355 componentInputMsg->startY_ = componentManager->GetStartY();
356 componentInputMsg->endX_ = componentManager->GetEndX();
357 componentInputMsg->endY_ = componentManager->GetEndY();
358 componentInputMsg->content_ = componentinfo->GetContent();
359 TreeManager::GetInstance()->SetComponentType(componentinfo->GetComponentType());
360 Report::GetInstance()->SyncInputInfo(componentInputMsg);
361 }
362 } else {
363 ERROR_LOG("component list is null");
364 result = OHOS::ERR_NO_INIT;
365 }
366 }
367 DEBUG_LOG_STR("component focus input result (%d)", result);
368 return result;
369 }
370
ChooseRightComponentIndex(std::vector<std::shared_ptr<OHOS::Accessibility::AccessibilityElementInfo>> & componentInfos,std::vector<std::shared_ptr<ComponentTree>> & wComponentInfos,bool shouldScreenCap)371 uint32_t ComponentInput::ChooseRightComponentIndex(
372 std::vector<std::shared_ptr<OHOS::Accessibility::AccessibilityElementInfo>> &componentInfos,
373 std::vector<std::shared_ptr<ComponentTree>> &wComponentInfos, bool shouldScreenCap)
374 {
375 auto treemanager = TreeManager::GetInstance();
376 uint32_t index;
377 if (treemanager->HasDialog()) {
378 DEBUG_LOG("Has dialog");
379 std::vector<uint32_t> indexList;
380 int count = wComponentInfos.size();
381 for (int i = 0; i < count; i++) {
382 auto it = wComponentInfos[i];
383 if (it->IsTopComponent()) {
384 indexList.push_back(i);
385 }
386 }
387 uint32_t randIndex = (std::uint32_t) rand() % indexList.size();
388 index = indexList[randIndex];
389 } else {
390 DEBUG_LOG("no dialog");
391 uint32_t randIndex = treemanager->FindInputComponentIndex(shouldScreenCap);
392 DEBUG_LOG_STR("ComponentInput::FocusInput START: randomIndex: %u", randIndex);
393 index = randIndex % componentInfos.size();
394 }
395 return index;
396 }
397
GetInputInfo()398 ErrCode ComponentInput::GetInputInfo()
399 {
400 return OHOS::ERR_OK;
401 }
402
JudgeComponentType(OHOS::Accessibility::AccessibilityElementInfo & elementInfo)403 int ComponentInput::JudgeComponentType(OHOS::Accessibility::AccessibilityElementInfo& elementInfo)
404 {
405 int actionType;
406 TRACK_LOG_STD();
407 // get action list of component
408 std::vector<OHOS::Accessibility::AccessibleAction> actionlist = elementInfo.GetActionList();
409 if (actionlist.empty()) {
410 std::string componentType = elementInfo.GetComponentType();
411 TRACK_LOG_STR("component type: %s", componentType.c_str());
412 if (componentType == "TextInput" || componentType == "TextArea" || componentType == "Text") {
413 actionType = Accessibility::ACCESSIBILITY_ACTION_SET_TEXT;
414 } else if (componentType == "GridContainer") {
415 actionType = Accessibility::ACCESSIBILITY_ACTION_SCROLL_FORWARD;
416 } else if (componentType == "Slider") {
417 actionType = COMPONENT_LEFT_SWAP;
418 } else {
419 actionType = Accessibility::ACCESSIBILITY_ACTION_CLICK;
420 }
421 } else {
422 TRACK_LOG_STR("action list size: %u", actionlist.size());
423 auto it = actionlist[(uint32_t)(rand()) % actionlist.size()];
424 actionType = (int)it.GetActionType();
425 }
426 TRACK_LOG_STR("action type: %d", actionType);
427 return actionType;
428 }
429 } // namespace WuKong
430 } // namespace OHOS
431