1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.platform.helpers; 18 19 import android.app.Instrumentation; 20 import android.content.res.Resources; 21 import android.platform.helpers.ScrollUtility.ScrollActions; 22 import android.platform.helpers.ScrollUtility.ScrollDirection; 23 import android.platform.spectatio.exceptions.MissingUiElementException; 24 25 import androidx.test.uiautomator.By; 26 import androidx.test.uiautomator.BySelector; 27 import androidx.test.uiautomator.UiObject2; 28 29 import java.text.SimpleDateFormat; 30 import java.time.Month; 31 import java.util.Date; 32 import java.util.List; 33 34 /** Helper class for functional tests of System settings */ 35 public class SettingsSystemHelperImpl extends AbstractStandardAppHelper 36 implements IAutoSystemSettingsHelper { 37 38 private ScrollUtility mScrollUtility; 39 private ScrollActions mScrollAction; 40 private BySelector mBackwardButtonSelector; 41 private BySelector mForwardButtonSelector; 42 private BySelector mScrollableElementSelector; 43 private ScrollDirection mScrollDirection; 44 SettingsSystemHelperImpl(Instrumentation instr)45 public SettingsSystemHelperImpl(Instrumentation instr) { 46 super(instr); 47 mScrollUtility = ScrollUtility.getInstance(getSpectatioUiUtil()); 48 mScrollAction = 49 ScrollActions.valueOf( 50 getActionFromConfig( 51 AutomotiveConfigConstants.SYSTEM_SETTINGS_SCROLL_ACTION)); 52 mBackwardButtonSelector = 53 getUiElementFromConfig( 54 AutomotiveConfigConstants.SYSTEM_SETTINGS_SCROLL_BACKWARD_BUTTON); 55 mForwardButtonSelector = 56 getUiElementFromConfig( 57 AutomotiveConfigConstants.SYSTEM_SETTINGS_SCROLL_FORWARD_BUTTON); 58 mScrollableElementSelector = 59 getUiElementFromConfig(AutomotiveConfigConstants.SYSTEM_SETTINGS_SCROLL_ELEMENT); 60 mScrollDirection = 61 ScrollDirection.valueOf( 62 getActionFromConfig( 63 AutomotiveConfigConstants.SYSTEM_SETTINGS_SCROLL_DIRECTION)); 64 mScrollUtility.setScrollValues( 65 Integer.valueOf( 66 getActionFromConfig( 67 AutomotiveConfigConstants.SYSTEM_SETTINGS_SCROLL_MARGIN)), 68 Integer.valueOf( 69 getActionFromConfig( 70 AutomotiveConfigConstants.SYSTEM_SETTINGS_SCROLL_WAIT_TIME))); 71 } 72 73 /** {@inheritDoc} */ 74 @Override getPackage()75 public String getPackage() { 76 return getPackageFromConfig(AutomotiveConfigConstants.SETTINGS_PACKAGE); 77 } 78 79 @Override dismissInitialDialogs()80 public void dismissInitialDialogs() { 81 // Nothing to dismiss 82 } 83 84 /** {@inheritDoc} */ 85 @Override getLauncherName()86 public String getLauncherName() { 87 throw new UnsupportedOperationException("Operation not supported."); 88 } 89 90 /** {@inheritDoc} */ 91 @Override setDisplayLanguage(String language)92 public void setDisplayLanguage(String language) { 93 openLanguageMenu(); 94 BySelector languageSelector = By.clickable(true).hasDescendant(By.textStartsWith(language)); 95 UiObject2 languageObject = getMenu(languageSelector); 96 getSpectatioUiUtil() 97 .validateUiObject( 98 languageObject, 99 String.format("Unable to find UI Element for language selector")); 100 getSpectatioUiUtil().clickAndWait(languageObject); 101 String systemLanguage = 102 Resources.getSystem().getConfiguration().getLocales().get(0).getDisplayLanguage(); 103 if (!language.toLowerCase().contains(systemLanguage.toLowerCase())) { 104 throw new RuntimeException("System language is different from selected language"); 105 } 106 } 107 108 /** {@inheritDoc} */ 109 @Override getCurrentLanguage()110 public String getCurrentLanguage() { 111 UiObject2 object = 112 getBtnByText( 113 AutomotiveConfigConstants.LANGUAGES_MENU, 114 AutomotiveConfigConstants.LANGUAGES_MENU_IN_SELECTED_LANGUAGE); 115 getSpectatioUiUtil() 116 .validateUiObject( 117 object, String.format("Unable to find UI Element for current language")); 118 String currentLanguage = getSummeryText(object); 119 return currentLanguage; 120 } 121 122 /** {@inheritDoc} */ 123 @Override getDeviceModel()124 public String getDeviceModel() { 125 openAboutMenu(); 126 UiObject2 object = getMenu(getUiElementFromConfig(AutomotiveConfigConstants.DEVICE_MODEL)); 127 getSpectatioUiUtil() 128 .validateUiObject( 129 object, String.format("Unable to find UI Element for device model")); 130 String modelName = getSummeryText(object); 131 return modelName; 132 } 133 134 /** {@inheritDoc} */ 135 @Override getAndroidVersion()136 public String getAndroidVersion() { 137 openAboutMenu(); 138 UiObject2 object = 139 getMenu(getUiElementFromConfig(AutomotiveConfigConstants.ANDROID_VERSION)); 140 getSpectatioUiUtil() 141 .validateUiObject( 142 object, String.format("Unable to find UI Element for current language")); 143 String androidVersion = getSummeryText(object); 144 return androidVersion; 145 } 146 147 /** {@inheritDoc} */ 148 @Override getAndroidSecurityPatchLevel()149 public Date getAndroidSecurityPatchLevel() { 150 openAboutMenu(); 151 UiObject2 object = 152 getMenu( 153 getUiElementFromConfig( 154 AutomotiveConfigConstants.ANDROID_SECURITY_PATCH_LEVEL)); 155 getSpectatioUiUtil() 156 .validateUiObject( 157 object, 158 String.format( 159 "Unable to find UI Element for android security patch level")); 160 String androidSecurityPatchLevel = getSummeryText(object); 161 Date patchDate = parseDate(androidSecurityPatchLevel, "MMMM dd, yyyy"); 162 if (patchDate == null) { 163 patchDate = parseDate(androidSecurityPatchLevel, "dd MMMM yyyy"); 164 } 165 if (patchDate == null) { 166 throw new RuntimeException("Cannot find date from UI"); 167 } 168 return formatDate(patchDate, "MMMM dd, yyyy"); // return locale independent date 169 } 170 formatDate(Date date, String format)171 private Date formatDate(Date date, String format) { 172 SimpleDateFormat dateFormatter = new SimpleDateFormat(format); 173 String dateString = dateFormatter.format(date); 174 String[] arr = dateString.split(" "); 175 int year = Integer.valueOf(arr[2]); 176 int month = Month.valueOf(arr[0].toUpperCase()).getValue() - 1; 177 int day = Integer.valueOf(arr[1].substring(0, arr[1].length() - 1)); 178 return new Date(year, month, day); 179 } 180 parseDate(String date, String format)181 private Date parseDate(String date, String format) { 182 Date parsedDate = null; 183 try { 184 SimpleDateFormat dateFormatter = new SimpleDateFormat(format); 185 parsedDate = dateFormatter.parse(date); 186 } catch (Exception e) { 187 // do nothing 188 } 189 return parsedDate; 190 } 191 192 /** {@inheritDoc} */ 193 @Override getKernelVersion()194 public String getKernelVersion() { 195 openAboutMenu(); 196 UiObject2 object = 197 getMenu(getUiElementFromConfig(AutomotiveConfigConstants.KERNEL_VERSION)); 198 getSpectatioUiUtil() 199 .validateUiObject( 200 object, String.format("Unable to find UI Element for kernel version")); 201 String kernelVersion = getSummeryText(object); 202 return kernelVersion; 203 } 204 205 /** {@inheritDoc} */ 206 @Override getBuildNumber()207 public String getBuildNumber() { 208 openAboutMenu(); 209 UiObject2 object = getMenu(getUiElementFromConfig(AutomotiveConfigConstants.BUILD_NUMBER)); 210 getSpectatioUiUtil() 211 .validateUiObject( 212 object, String.format("Unable to find UI Element for build number")); 213 String buildNumber = getSummeryText(object); 214 return buildNumber; 215 } 216 217 /** {@inheritDoc} */ 218 @Override resetNetwork()219 public void resetNetwork() { 220 openResetOptionsMenu(); 221 BySelector resetNetworkSelector = 222 By.clickable(true) 223 .hasDescendant( 224 getUiElementFromConfig(AutomotiveConfigConstants.RESET_NETWORK)); 225 UiObject2 resetNetworkMenu = getMenu(resetNetworkSelector); 226 getSpectatioUiUtil() 227 .validateUiObject(resetNetworkMenu, AutomotiveConfigConstants.RESET_NETWORK); 228 getSpectatioUiUtil().clickAndWait(resetNetworkMenu); 229 BySelector resetSettingsSelector = 230 getUiElementFromConfig(AutomotiveConfigConstants.RESET_SETTINGS); 231 232 UiObject2 resetSettingsButton1 = getMenu(resetSettingsSelector); 233 getSpectatioUiUtil() 234 .validateUiObject(resetSettingsButton1, AutomotiveConfigConstants.RESET_SETTINGS); 235 getSpectatioUiUtil().clickAndWait(resetSettingsButton1); 236 237 UiObject2 resetSettingsButton2 = 238 getMenu(getUiElementFromConfig(AutomotiveConfigConstants.RESET_SETTINGS)); 239 getSpectatioUiUtil() 240 .validateUiObject(resetSettingsButton2, AutomotiveConfigConstants.RESET_SETTINGS); 241 getSpectatioUiUtil().clickAndWait(resetSettingsButton2); 242 } 243 244 /** {@inheritDoc} */ 245 @Override resetAppPreferences()246 public void resetAppPreferences() { 247 openResetOptionsMenu(); 248 BySelector selector = 249 By.clickable(true) 250 .hasDescendant( 251 getUiElementFromConfig( 252 AutomotiveConfigConstants.RESET_APP_PREFERENCES)); 253 UiObject2 object = getMenu(selector); 254 getSpectatioUiUtil() 255 .validateUiObject(object, AutomotiveConfigConstants.RESET_APP_PREFERENCES); 256 getSpectatioUiUtil().clickAndWait(object); 257 BySelector reset_apps_selector = 258 getUiElementFromConfig(AutomotiveConfigConstants.RESET_APPS); 259 260 UiObject2 reset_apps_button = getMenu(reset_apps_selector); 261 getSpectatioUiUtil() 262 .validateUiObject(reset_apps_button, AutomotiveConfigConstants.RESET_APPS); 263 getSpectatioUiUtil().clickAndWait(reset_apps_button); 264 } 265 266 /** {@inheritDoc} */ 267 @Override openLanguagesInputMenu()268 public void openLanguagesInputMenu() { 269 UiObject2 languagesInputMenu = 270 getMenu(getUiElementFromConfig(AutomotiveConfigConstants.LANGUAGES_AND_INPUT_MENU)); 271 getSpectatioUiUtil() 272 .validateUiObject( 273 languagesInputMenu, 274 String.format("Unable to find UI Element for language input menu")); 275 getSpectatioUiUtil().clickAndWait(languagesInputMenu); 276 } 277 getSummeryText(UiObject2 object)278 private String getSummeryText(UiObject2 object) { 279 UiObject2 parent = object.getParent(); 280 if (parent.getChildren().size() < 2) { 281 BySelector swipeSelector = 282 getUiElementFromConfig( 283 AutomotiveConfigConstants.SYSTEM_SETTINGS_SCROLL_ELEMENT); 284 UiObject2 swipeObject = getSpectatioUiUtil().findUiObject(swipeSelector); 285 getSpectatioUiUtil() 286 .validateUiObject( 287 swipeObject, AutomotiveConfigConstants.SYSTEM_SETTINGS_SCROLL_ELEMENT); 288 getSpectatioUiUtil().swipeUp(swipeObject); 289 } 290 return object.getParent().getChildren().get(1).getText(); 291 } 292 openResetOptionsMenu()293 private void openResetOptionsMenu() { 294 UiObject2 resetOptionMenu = 295 getMenu(getUiElementFromConfig(AutomotiveConfigConstants.RESET_OPTIONS_MENU)); 296 getSpectatioUiUtil() 297 .validateUiObject( 298 resetOptionMenu, String.format("Unable to find UI Element for reset menu")); 299 getSpectatioUiUtil().clickAndWait(resetOptionMenu); 300 } 301 openAboutMenu()302 private void openAboutMenu() { 303 getSpectatioUiUtil().wait1Second(); 304 UiObject2 aboutMenu = getMenu(getUiElementFromConfig(AutomotiveConfigConstants.ABOUT_MENU)); 305 getSpectatioUiUtil() 306 .validateUiObject( 307 aboutMenu, String.format("Unable to find UI Element for about menu")); 308 getSpectatioUiUtil().clickAndWait(aboutMenu); 309 } 310 311 /** {@inheritDoc} */ 312 @Override openViewAll()313 public void openViewAll() { 314 getSpectatioUiUtil().wait1Second(); 315 UiObject2 viewAll = 316 getMenu( 317 getUiElementFromConfig( 318 AutomotiveConfigConstants.LOCATION_SETTINGS_VIEW_ALL)); 319 getSpectatioUiUtil() 320 .validateUiObject(viewAll, String.format("Unable to find UI Element for view all")); 321 getSpectatioUiUtil().clickAndWait(viewAll); 322 } 323 openLanguageMenu()324 private void openLanguageMenu() { 325 UiObject2 languageMenu = 326 getBtnByText( 327 AutomotiveConfigConstants.LANGUAGES_MENU, 328 AutomotiveConfigConstants.LANGUAGES_MENU_IN_SELECTED_LANGUAGE); 329 getSpectatioUiUtil() 330 .validateUiObject( 331 languageMenu, String.format("Unable to find UI Element for language menu")); 332 getSpectatioUiUtil().clickAndWait(languageMenu); 333 } 334 getBtnByText(String... texts)335 private UiObject2 getBtnByText(String... texts) { 336 for (String text : texts) { 337 BySelector btnSelector = By.text(text); 338 UiObject2 btn = getSpectatioUiUtil().findUiObject(btnSelector); 339 if (btn != null) { 340 return btn; 341 } 342 } 343 throw new RuntimeException("Cannot find button"); 344 } 345 346 /** {@inheritDoc} */ 347 @Override openStorageMenu()348 public void openStorageMenu() { 349 UiObject2 aboutMenu = 350 getMenu( 351 getUiElementFromConfig( 352 AutomotiveConfigConstants.STORAGE_SYSTEM_SUB_SETTINGS)); 353 getSpectatioUiUtil() 354 .validateUiObject( 355 aboutMenu, String.format("Unable to find UI Element for Storage menu")); 356 getSpectatioUiUtil().clickAndWait(aboutMenu); 357 getSpectatioUiUtil().wait5Seconds(); 358 } 359 360 /** {@inheritDoc} */ 361 @Override verifyUsageinGB(String option)362 public boolean verifyUsageinGB(String option) { 363 boolean isUsageinGB = false; 364 List<UiObject2> scrollElements = 365 getSpectatioUiUtil() 366 .findUiObjects( 367 getUiElementFromConfig( 368 AutomotiveConfigConstants 369 .SETTINGS_UI_SUB_SETTING_SCROLL_ELEMENT)); 370 for (UiObject2 element : scrollElements) { 371 UiObject2 foundObject = 372 getSpectatioUiUtil() 373 .findUiObjectInGivenElement(element, getUiElementFromConfig(option)); 374 if (foundObject != null) { 375 // there may be multiple matches the 'option' config on screen, such as 'System' 376 String targetText = getSummeryText(foundObject); 377 if (targetText != null && targetText.contains("GB")) { 378 isUsageinGB = true; 379 } 380 } 381 } 382 return isUsageinGB; 383 } 384 getMenu(BySelector selector)385 private UiObject2 getMenu(BySelector selector) { 386 UiObject2 object = 387 mScrollUtility.scrollAndFindUiObject( 388 mScrollAction, 389 mScrollDirection, 390 mForwardButtonSelector, 391 mBackwardButtonSelector, 392 mScrollableElementSelector, 393 selector, 394 String.format("Scroll on system setting to find %s", selector)); 395 396 getSpectatioUiUtil() 397 .validateUiObject( 398 object, 399 String.format("Unable to find UI Element %s.", selector.toString())); 400 return object; 401 } 402 403 /** {@inheritDoc} */ 404 @Override hasDeveloperOptions()405 public boolean hasDeveloperOptions() throws MissingUiElementException { 406 getSpectatioUiUtil().wait1Second(); 407 boolean hasDeveloperOptions = 408 getSpectatioUiUtil() 409 .scrollAndCheckIfUiElementExist( 410 mScrollableElementSelector, "Developer options", true); 411 return hasDeveloperOptions; 412 } 413 414 /** {@inheritDoc} */ 415 @Override openDeveloperOptions()416 public void openDeveloperOptions() { 417 getSpectatioUiUtil().wait1Second(); 418 UiObject2 developerOptions = 419 getMenu(getUiElementFromConfig(AutomotiveConfigConstants.DEVELOPER_OPTIONS)); 420 getSpectatioUiUtil() 421 .validateUiObject( 422 developerOptions, 423 String.format("Unable to find UI Element for Developer Options")); 424 getSpectatioUiUtil().clickAndWait(developerOptions); 425 } 426 427 /** {@inheritDoc} */ 428 @Override enterDeveloperMode()429 public void enterDeveloperMode() { 430 openAboutMenu(); 431 getSpectatioUiUtil().wait1Second(); 432 UiObject2 buildNumber = 433 getMenu(getUiElementFromConfig(AutomotiveConfigConstants.BUILD_NUMBER)); 434 getSpectatioUiUtil() 435 .validateUiObject( 436 buildNumber, String.format("Unable to find UI Element for build number")); 437 for (int i = 0; i <= 6; i++) { 438 getSpectatioUiUtil().clickAndWait(buildNumber); 439 getSpectatioUiUtil().wait1Second(); 440 } 441 pressSettingsBackNavIcon(); 442 getSpectatioUiUtil().waitForIdle(); 443 } 444 pressSettingsBackNavIcon()445 private void pressSettingsBackNavIcon() { 446 UiObject2 navIcon = 447 getSpectatioUiUtil() 448 .findUiObject( 449 getUiElementFromConfig( 450 AutomotiveConfigConstants.SETTINGS_BACK_NAV_ICON)); 451 getSpectatioUiUtil() 452 .validateUiObject( 453 navIcon, "Could not press back; unable to find settings back nav icon"); 454 getSpectatioUiUtil().clickAndWait(navIcon); 455 } 456 } 457