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 result = OHOS::ERR_NO_INIT;
311 }
312 }
313 DEBUG_LOG_STR("component random input result (%d)", result);
314 return result;
315 }
316
FocusInput(bool shouldScreenCap)317 ErrCode ComponentInput::FocusInput(bool shouldScreenCap)
318 {
319 auto treemanager = TreeManager::GetInstance();
320 ErrCode result = treemanager->UpdateComponentInfo();
321 auto componentManager = ComponentManager::GetInstance();
322 DEBUG_LOG_STR("update componentinfo result (%d)", result);
323 if (result == OHOS::ERR_OK) {
324 auto delegate = FocusSceneDelegate::GetInstance();
325 delegate->ChooseScene(true);
326 auto componentInfos = treemanager->GetActiveElementInfos();
327 auto wComponentInfos = treemanager->GetActiveComponentInfos();
328 DEBUG_LOG_STR("component list size (%d), back : (%d)", componentInfos.size(), delegate->IsBackToPrePage());
329 if (delegate->IsBackToPrePage()) {
330 result = componentManager->BackToPrePage();
331 } else if (componentInfos.size() > 0) {
332 uint32_t index = ChooseRightComponentIndex(componentInfos, wComponentInfos, shouldScreenCap);
333 DEBUG_LOG_STR("after ChooseRightComponentIndex (%d), comp cnt (%d)index (%d)",
334 componentInfos.size(), wComponentInfos.size(), index);
335 auto componentinfo = componentInfos[index];
336 DEBUG_LOG_STR("component input index (%d), NodeId (%d)", index,
337 wComponentInfos[index]->GetNodeId());
338 int actionType = JudgeComponentType(*(componentinfo.get()));
339 if (actionType == Accessibility::ACCESSIBILITY_ACTION_INVALID) {
340 actionType = OHOS::Accessibility::ACCESSIBILITY_ACTION_CLICK;
341 }
342
343 result = componentManager->ComponentEventInput(*(componentinfo.get()), actionType);
344 DEBUG_LOG_STR("after ChooseRightComponentIndex3 (%d), index (%d)", componentInfos.size(), index);
345 DEBUG_LOG_STR("action type: %d, sequence input: %d", actionType, result);
346 if (result == OHOS::ERR_OK) {
347 treemanager->SetInputcomponentIndex(actionType, index);
348 std::shared_ptr<ComponmentInputMsg> componentInputMsg = std::make_shared<ComponmentInputMsg>();
349 componentInputMsg->pageComponments = delegate->GetComponentTypeList();
350 componentInputMsg->componmentType_ = componentinfo->GetComponentType();
351 componentInputMsg->pagePath_ = componentinfo->GetPagePath();
352 componentInputMsg->startX_ = componentManager->GetStartX();
353 componentInputMsg->startY_ = componentManager->GetStartY();
354 componentInputMsg->endX_ = componentManager->GetEndX();
355 componentInputMsg->endY_ = componentManager->GetEndY();
356 componentInputMsg->content_ = componentinfo->GetContent();
357 componentInputMsg->pssTotal_ = WuKongUtil::GetInstance()->GetBundlePssTotal();
358 TreeManager::GetInstance()->SetComponentType(componentinfo->GetComponentType());
359 Report::GetInstance()->SyncInputInfo(componentInputMsg);
360 }
361 } else {
362 ERROR_LOG("component list is null");
363 result = OHOS::ERR_NO_INIT;
364 }
365 }
366 DEBUG_LOG_STR("component focus input result (%d)", result);
367 return result;
368 }
369
ChooseRightComponentIndex( std::vector<std::shared_ptr<OHOS::Accessibility::AccessibilityElementInfo>> &componentInfos, std::vector<std::shared_ptr<ComponentTree>> &wComponentInfos, bool shouldScreenCap)370 uint32_t ComponentInput::ChooseRightComponentIndex(
371 std::vector<std::shared_ptr<OHOS::Accessibility::AccessibilityElementInfo>> &componentInfos,
372 std::vector<std::shared_ptr<ComponentTree>> &wComponentInfos, bool shouldScreenCap)
373 {
374 auto treemanager = TreeManager::GetInstance();
375 uint32_t index;
376 if (treemanager->HasDialog()) {
377 DEBUG_LOG("Has dialog");
378 std::vector<uint32_t> indexList;
379 int count = wComponentInfos.size();
380 for (int i = 0; i < count; i++) {
381 auto it = wComponentInfos[i];
382 if (it->IsTopComponent()) {
383 indexList.push_back(i);
384 }
385 }
386 uint32_t randIndex = (std::uint32_t) rand() % indexList.size();
387 index = indexList[randIndex];
388 } else {
389 DEBUG_LOG("no dialog");
390 uint32_t randIndex = treemanager->FindInputComponentIndex(shouldScreenCap);
391 DEBUG_LOG_STR("ComponentInput::FocusInput START: randomIndex: %u", randIndex);
392 index = randIndex % componentInfos.size();
393 }
394 return index;
395 }
396
GetInputInfo()397 InputType ComponentInput::GetInputInfo()
398 {
399 return INPUTTYPE_ELEMENTINPUT;
400 }
401
JudgeComponentType(OHOS::Accessibility::AccessibilityElementInfo& elementInfo)402 int ComponentInput::JudgeComponentType(OHOS::Accessibility::AccessibilityElementInfo& elementInfo)
403 {
404 int actionType;
405 TRACK_LOG_STD();
406 // get action list of component
407 std::vector<OHOS::Accessibility::AccessibleAction> actionlist = elementInfo.GetActionList();
408 if (actionlist.empty()) {
409 std::string componentType = elementInfo.GetComponentType();
410 TRACK_LOG_STR("component type: %s", componentType.c_str());
411 if (componentType == "TextInput" || componentType == "TextArea" || componentType == "Text") {
412 actionType = Accessibility::ACCESSIBILITY_ACTION_SET_TEXT;
413 } else if (componentType == "GridContainer") {
414 actionType = Accessibility::ACCESSIBILITY_ACTION_SCROLL_FORWARD;
415 } else if (componentType == "Slider") {
416 actionType = COMPONENT_LEFT_SWAP;
417 } else {
418 actionType = Accessibility::ACCESSIBILITY_ACTION_CLICK;
419 }
420 } else {
421 TRACK_LOG_STR("action list size: %u", actionlist.size());
422 auto it = actionlist[(uint32_t)(rand()) % actionlist.size()];
423 actionType = (int)it.GetActionType();
424 }
425 TRACK_LOG_STR("action type: %d", actionType);
426 return actionType;
427 }
428 } // namespace WuKong
429 } // namespace OHOS
430