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 "tree_manager.h"
25 #include "wukong_define.h"
26
27 namespace OHOS {
28 namespace WuKong {
29 namespace {
30 const uint32_t PAGE_BACK_COUNT_MAX = 3;
31 const uint32_t LANUCH_APP_COUNT_MAX = 5;
32
LauncherApp(const std::string & bundleName)33 ErrCode LauncherApp(const std::string& bundleName)
34 {
35 auto appInput = InputFactory::GetInputAction(INPUTTYPE_APPSWITCHINPUT);
36 if (appInput == nullptr) {
37 ERROR_LOG("InputFactory::GetInputAction INPUTTYPE_APPSWITCHINPUT is null");
38 return OHOS::ERR_INVALID_VALUE;
39 }
40
41 // launch app by AppSwitchInput function.
42 std::shared_ptr<AppSwitchParam> appSwitchParam = std::make_shared<AppSwitchParam>();
43 appSwitchParam->bundlename_ = bundleName;
44 std::shared_ptr<SpcialTestObject> sto = appSwitchParam;
45 auto result = appInput->OrderInput(sto);
46 if (result != OHOS::ERR_OK) {
47 ERROR_LOG("AppSwitchInput OrderInput failed");
48 }
49 return result;
50 }
51
CheckLauncherApp(const std::shared_ptr<ComponentParam> & param)52 uint32_t CheckLauncherApp(const std::shared_ptr<ComponentParam>& param)
53 {
54 TRACK_LOG_STD();
55 std::vector<std::string> tempAllowList;
56 for (uint32_t i = 0; i < param->bundleName_.size(); i++) {
57 // do not launch app when bundle is running.
58 if (param->bundleRunning_[i] == true && param->bundleFinish_[i] == false) {
59 return i;
60 }
61 // launch app when the bundle is stop and not finish.
62 if (param->bundleRunning_[i] == false && param->bundleFinish_[i] == false) {
63 tempAllowList.clear();
64 tempAllowList.push_back(param->bundleName_[i]);
65 WuKongUtil::GetInstance()->SetTempAllowList(tempAllowList);
66 // launch app by AppSwitchInput function.
67 if (LauncherApp(param->bundleName_[i]) != OHOS::ERR_OK) {
68 return param->bundleName_.size();
69 }
70 // init bundleRunning status to stop.
71 std::vector<bool> bundleRunning = param->bundleRunning_;
72 std::fill(bundleRunning.begin(), bundleRunning.end(), false);
73
74 // set current launched bundle is running.
75 param->bundleRunning_[i] = true;
76 TRACK_LOG_STR("%s", param->toString().c_str());
77 TEST_RUN_LOG(param->bundleName_[i].c_str());
78 return i;
79 }
80 }
81 // not found bundle can be run, and return failed.
82 return param->bundleName_.size();
83 }
84
CheckAbliltyFinished(const std::shared_ptr<AbilityTree> & abilityNode)85 bool CheckAbliltyFinished(const std::shared_ptr<AbilityTree>& abilityNode)
86 {
87 TRACK_LOG_STD();
88 bool abilityRunFinished = false;
89 if (abilityNode == nullptr) {
90 ERROR_LOG("abilityNode is nullptr");
91 return abilityRunFinished;
92 }
93 uint32_t allCount = abilityNode->GetAllComponentCount();
94 uint32_t inputCount = abilityNode->GetInputCount();
95 TRACK_LOG_STR("ability (%s) component count (%u), input count (%u)", abilityNode->GetBundleName().c_str(), allCount,
96 inputCount);
97 if (inputCount >= allCount) {
98 abilityRunFinished = true;
99 }
100 TRACK_LOG_END();
101 return abilityRunFinished;
102 }
103
CheckBundleFinished(const std::shared_ptr<WuKongTree> & parent)104 bool CheckBundleFinished(const std::shared_ptr<WuKongTree>& parent)
105 {
106 if (!CheckAbliltyFinished(std::static_pointer_cast<AbilityTree>(parent))) {
107 return false;
108 }
109 for (auto child : parent->GetChildren()) {
110 if (!CheckBundleFinished(std::static_pointer_cast<AbilityTree>(child))) {
111 return false;
112 }
113 }
114 return true;
115 }
116
CheckInputFinished(const std::shared_ptr<ComponentParam> & param)117 bool CheckInputFinished(const std::shared_ptr<ComponentParam>& param)
118 {
119 TRACK_LOG_STD();
120 bool isFinished = false;
121 auto currentAbilityPtr = TreeManager::GetInstance()->GetCurrentAbility();
122 if (currentAbilityPtr == nullptr) {
123 ERROR_LOG("GetCurrentAbility abilityNode is nullptr");
124 return isFinished;
125 }
126
127 // check app input event finished and set param is finished.
128 if (CheckBundleFinished(WuKongTree::GetRoot(currentAbilityPtr))) {
129 for (uint32_t i = 0; i < param->bundleRunning_.size(); i++) {
130 if (param->bundleRunning_[i] && param->bundleName_[i] == currentAbilityPtr->GetBundleName()) {
131 param->bundleFinish_[i] = true;
132 isFinished = true;
133 break;
134 }
135 }
136 }
137
138 TRACK_LOG_END();
139 return isFinished;
140 }
141
JudgeBackResult(const std::shared_ptr<ComponentParam> & param,uint32_t launchIndex)142 ErrCode JudgeBackResult(const std::shared_ptr<ComponentParam>& param, uint32_t launchIndex)
143 {
144 TRACK_LOG_STD();
145 ErrCode result;
146 param->pageBack_[launchIndex]++;
147 TRACK_LOG_STR("back count: %d", param->pageBack_[launchIndex]);
148 if (param->pageBack_[launchIndex] > PAGE_BACK_COUNT_MAX) {
149 result = LauncherApp(param->bundleName_[launchIndex]);
150 if (result != OHOS::ERR_OK) {
151 return result;
152 }
153 param->pageBack_[launchIndex] = 0;
154 param->lanuchCount_[launchIndex]++;
155 TRACK_LOG_STR("lanuchCount_[%d] = %d", launchIndex, param->lanuchCount_[launchIndex]);
156 if (param->lanuchCount_[launchIndex] > LANUCH_APP_COUNT_MAX) {
157 param->bundleFinish_[launchIndex] = true;
158 ERROR_LOG("Failed to launch the app five times in a row and exit");
159 param->lanuchCount_[launchIndex] = 0;
160 return OHOS::ERR_INVALID_VALUE;
161 }
162 } else {
163 result = ComponentManager::GetInstance()->BackToPrePage();
164 }
165 TRACK_LOG_END();
166 return result;
167 }
168 } // namespace
ComponentInput()169 ComponentInput::ComponentInput() : InputAction()
170 {
171 }
172
~ComponentInput()173 ComponentInput::~ComponentInput()
174 {
175 }
176
OrderInput(const std::shared_ptr<SpcialTestObject> & specialTestObject)177 ErrCode ComponentInput::OrderInput(const std::shared_ptr<SpcialTestObject>& specialTestObject)
178 {
179 auto componentPtr = std::static_pointer_cast<ComponentParam>(specialTestObject);
180 if (componentPtr == nullptr) {
181 ERROR_LOG("specialTestObject param is null");
182 return OHOS::ERR_INVALID_VALUE;
183 }
184 // launch app and check if app has been started
185 uint32_t launchIndex = CheckLauncherApp(componentPtr);
186 if (launchIndex >= componentPtr->bundleName_.size()) {
187 ERROR_LOG("launcher app failed, and stop run test");
188 componentPtr->isAllFinished_ = true;
189 ERROR_LOG(componentPtr->toString().c_str());
190 return OHOS::ERR_INVALID_VALUE;
191 }
192 auto treemanager = TreeManager::GetInstance();
193 auto delegate = SceneDelegate::GetInstance();
194 // update component information
195 ErrCode result = treemanager->UpdateComponentInfo();
196 DEBUG_LOG_STR("update componentinfo result (%d)", result);
197 if (result == OHOS::ERR_OK) {
198 // choose scene and set valid components
199 result = delegate->ChooseScene(false);
200 if (result != OHOS::ERR_OK) {
201 ERROR_LOG("choose scene failed");
202 return result;
203 }
204 // judge if is neccessnary to back to previous page
205 if (delegate->IsBackToPrePage()) {
206 result = JudgeBackResult(componentPtr, launchIndex);
207 if (result != OHOS::ERR_OK) {
208 return result;
209 }
210 } else {
211 // get the component from tree manager to input action
212 auto elementInfo = treemanager->GetElementInfoByOrder();
213 if (elementInfo == nullptr) {
214 ERROR_LOG("elementinfo is nullptr");
215 return OHOS::ERR_INVALID_VALUE;
216 }
217 // get the actions of component
218 int actionType = JudgeComponentType(*(elementInfo.get()));
219 if (actionType == Accessibility::ACCESSIBILITY_ACTION_INVALID) {
220 actionType = OHOS::Accessibility::ACCESSIBILITY_ACTION_CLICK;
221 }
222 // input action to component
223 result = ComponentManager::GetInstance()->ComponentEventInput(*(elementInfo.get()), actionType);
224 if (result == OHOS::ERR_OK) {
225 // record index of inputted component
226 treemanager->SetInputcomponentIndex(actionType);
227 componentPtr->pageBack_[launchIndex] = 0;
228 componentPtr->lanuchCount_[launchIndex] = 0;
229 std::shared_ptr<ComponmentInputMsg> componentInputMsg = std::make_shared<ComponmentInputMsg>();
230 componentInputMsg->pageComponments = delegate->GetComponentTypeList();
231 componentInputMsg->pageId_ = delegate->GetCurrentPageId();
232 componentInputMsg->componmentType_ = elementInfo->GetComponentType();
233 Report::GetInstance()->SyncInputInfo(componentInputMsg);
234 }
235 }
236 }
237 // check current bundle finished state.
238 if (CheckInputFinished(componentPtr)) {
239 componentPtr->isAllFinished_ = true;
240 // confirm all bundle status.
241 std::vector<bool> bundleFinishList = componentPtr->bundleFinish_;
242 bool x = false;
243 if (std::any_of(bundleFinishList.begin(), bundleFinishList.end(), [x](int y) { return x == y; })) {
244 componentPtr->isAllFinished_ = false;
245 }
246 }
247 DEBUG_LOG_STR("component order input result (%d)", result);
248 return result;
249 }
250
RandomInput()251 ErrCode ComponentInput::RandomInput()
252 {
253 auto treemanager = TreeManager::GetInstance();
254 ErrCode result = treemanager->UpdateComponentInfo();
255 DEBUG_LOG_STR("update componentinfo result (%d)", result);
256 if (result == OHOS::ERR_OK) {
257 auto delegate = SceneDelegate::GetInstance();
258 delegate->ChooseScene(true);
259 auto componentInfos = treemanager->GetActiveElementInfos();
260 DEBUG_LOG_STR("component list size (%d)", componentInfos.size());
261 DEBUG_LOG_STR("back: %d", delegate->IsBackToPrePage());
262 if (delegate->IsBackToPrePage()) {
263 result = ComponentManager::GetInstance()->BackToPrePage();
264 } else if (componentInfos.size() > 0) {
265 uint32_t index = (uint32_t)(rand()) % componentInfos.size();
266 DEBUG_LOG_STR("component input index (%d)", index);
267 int actionType = JudgeComponentType(*(componentInfos[index].get()));
268 if (actionType == Accessibility::ACCESSIBILITY_ACTION_INVALID) {
269 actionType = OHOS::Accessibility::ACCESSIBILITY_ACTION_CLICK;
270 }
271 result = ComponentManager::GetInstance()->ComponentEventInput(*(componentInfos[index].get()), actionType);
272 if (result == OHOS::ERR_OK) {
273 treemanager->SetInputcomponentIndex(actionType, index);
274 std::shared_ptr<ComponmentInputMsg> componentInputMsg = std::make_shared<ComponmentInputMsg>();
275 componentInputMsg->pageComponments = delegate->GetComponentTypeList();
276 componentInputMsg->pageId_ = delegate->GetCurrentPageId();
277 componentInputMsg->componmentType_ = componentInfos[index]->GetComponentType();
278 Report::GetInstance()->SyncInputInfo(componentInputMsg);
279 }
280 } else {
281 ERROR_LOG("component list is null");
282 result = OHOS::ERR_NO_INIT;
283 }
284 }
285 DEBUG_LOG_STR("component random input result (%d)", result);
286 return result;
287 }
288
GetInputInfo()289 ErrCode ComponentInput::GetInputInfo()
290 {
291 return OHOS::ERR_OK;
292 }
293
JudgeComponentType(OHOS::Accessibility::AccessibilityElementInfo & elementInfo)294 int ComponentInput::JudgeComponentType(OHOS::Accessibility::AccessibilityElementInfo& elementInfo)
295 {
296 int actionType;
297 TRACK_LOG_STD();
298 // get action list of component
299 std::vector<OHOS::Accessibility::AccessibleAction> actionlist = elementInfo.GetActionList();
300 if (actionlist.empty()) {
301 std::string componentType = elementInfo.GetComponentType();
302 TRACK_LOG_STR("component type: %s", componentType.c_str());
303 if (componentType == "TextInput" || componentType == "TextArea" || componentType == "Text") {
304 actionType = Accessibility::ACCESSIBILITY_ACTION_SET_TEXT;
305 } else if (componentType == "GridContainer") {
306 actionType = Accessibility::ACCESSIBILITY_ACTION_SCROLL_FORWARD;
307 } else if (componentType == "Slider") {
308 actionType = COMPONENT_LEFT_SWAP;
309 } else {
310 actionType = Accessibility::ACCESSIBILITY_ACTION_CLICK;
311 }
312 } else {
313 TRACK_LOG_STR("action list size: %u", actionlist.size());
314 auto it = actionlist[(uint32_t)(rand()) % actionlist.size()];
315 actionType = (int)it.GetActionType();
316 }
317 TRACK_LOG_STR("action type: %d", actionType);
318 return actionType;
319 }
320 } // namespace WuKong
321 } // namespace OHOS
322