1 /* 2 * Copyright (C) 2021 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.app.UiAutomation; 21 import android.content.Context; 22 import android.media.session.MediaController; 23 import android.media.session.MediaSessionManager; 24 import android.media.session.PlaybackState; 25 import android.platform.helpers.ScrollUtility.ScrollActions; 26 import android.platform.helpers.ScrollUtility.ScrollDirection; 27 import android.platform.helpers.exceptions.UnknownUiException; 28 29 import androidx.test.uiautomator.By; 30 import androidx.test.uiautomator.BySelector; 31 import androidx.test.uiautomator.Direction; 32 import androidx.test.uiautomator.UiObject; 33 import androidx.test.uiautomator.UiObject2; 34 import androidx.test.uiautomator.UiObjectNotFoundException; 35 36 import java.util.List; 37 import java.util.regex.Pattern; 38 39 /** Helper class for functional test for Mediacenter test */ 40 public class MediaCenterHelperImpl extends AbstractStandardAppHelper implements IAutoMediaHelper { 41 42 private MediaSessionManager mMediaSessionManager; 43 private UiAutomation mUiAutomation; 44 45 private ScrollUtility mScrollUtility; 46 private ScrollActions mScrollAction; 47 private BySelector mBackwardButtonSelector; 48 private BySelector mForwardButtonSelector; 49 private BySelector mScrollableElementSelector; 50 private ScrollDirection mScrollDirection; 51 MediaCenterHelperImpl(Instrumentation instr)52 public MediaCenterHelperImpl(Instrumentation instr) { 53 super(instr); 54 mUiAutomation = instr.getUiAutomation(); 55 mUiAutomation.adoptShellPermissionIdentity("android.permission.MEDIA_CONTENT_CONTROL"); 56 mMediaSessionManager = 57 (MediaSessionManager) 58 instr.getContext().getSystemService(Context.MEDIA_SESSION_SERVICE); 59 mScrollUtility = ScrollUtility.getInstance(getSpectatioUiUtil()); 60 mScrollAction = 61 ScrollActions.valueOf( 62 getActionFromConfig(AutomotiveConfigConstants.MEDIA_APP_SCROLL_ACTION)); 63 mBackwardButtonSelector = 64 getUiElementFromConfig(AutomotiveConfigConstants.MEDIA_APP_SCROLL_FORWARD_BUTTON); 65 mForwardButtonSelector = 66 getUiElementFromConfig(AutomotiveConfigConstants.MEDIA_APP_SCROLL_BACKWARD_BUTTON); 67 mScrollableElementSelector = 68 getUiElementFromConfig(AutomotiveConfigConstants.MEDIA_APP_SCROLL_ELEMENT); 69 mScrollDirection = 70 ScrollDirection.valueOf( 71 getActionFromConfig(AutomotiveConfigConstants.MEDIA_APP_SCROLL_DIRECTION)); 72 } 73 74 /** {@inheritDoc} */ 75 @Override exit()76 public void exit() { 77 getSpectatioUiUtil().pressHome(); 78 getSpectatioUiUtil().wait1Second(); 79 } 80 81 /** {@inheritDoc} */ 82 @Override getLauncherName()83 public String getLauncherName() { 84 throw new UnsupportedOperationException("Operation not supported."); 85 } 86 87 /** {@inheritDoc} */ 88 @Override dismissInitialDialogs()89 public void dismissInitialDialogs() { 90 // Nothing to dismiss 91 } 92 93 /** {@inheritDoc} */ 94 @Override scrollUpOnePage()95 public boolean scrollUpOnePage() { 96 return false; 97 } 98 99 /** {@inheritDoc} */ 100 @Override scrollDownOnePage()101 public boolean scrollDownOnePage() { 102 return false; 103 } 104 105 /** {@inheritDoc} */ 106 @Override getPackage()107 public String getPackage() { 108 return getPackageFromConfig(AutomotiveConfigConstants.MEDIA_CENTER_PACKAGE); 109 } 110 111 /** {@inheritDoc} */ open()112 public void open() { 113 openMediaApp(); 114 } 115 openMediaApp()116 private void openMediaApp() { 117 getSpectatioUiUtil().pressHome(); 118 getSpectatioUiUtil().waitForIdle(); 119 getSpectatioUiUtil() 120 .executeShellCommand( 121 getCommandFromConfig(AutomotiveConfigConstants.MEDIA_LAUNCH_COMMAND)); 122 } 123 124 /** {@inheritDoc} */ playMedia()125 public void playMedia() { 126 if (!isPlaying()) { 127 BySelector playButtonSelector = 128 getUiElementFromConfig(AutomotiveConfigConstants.PLAY_PAUSE_BUTTON); 129 UiObject2 playButton = getSpectatioUiUtil().findUiObject(playButtonSelector); 130 getSpectatioUiUtil() 131 .validateUiObject(playButton, AutomotiveConfigConstants.PLAY_PAUSE_BUTTON); 132 getSpectatioUiUtil().clickAndWait(playButton); 133 getSpectatioUiUtil().wait5Seconds(); 134 } 135 } 136 137 /** {@inheritDoc} */ playPauseMediaFromHomeScreen()138 public void playPauseMediaFromHomeScreen() { 139 BySelector playButtonSelector = 140 getUiElementFromConfig(AutomotiveConfigConstants.PLAY_PAUSE_BUTTON_HOME_SCREEN); 141 UiObject2 playButtonHomeScreen = getSpectatioUiUtil().findUiObject(playButtonSelector); 142 getSpectatioUiUtil() 143 .validateUiObject( 144 playButtonHomeScreen, 145 AutomotiveConfigConstants.PLAY_PAUSE_BUTTON_HOME_SCREEN); 146 getSpectatioUiUtil().clickAndWait(playButtonHomeScreen); 147 getSpectatioUiUtil().wait5Seconds(); 148 } 149 150 /** {@inheritDoc} */ pauseMedia()151 public void pauseMedia() { 152 BySelector pauseButtonSelector = 153 getUiElementFromConfig(AutomotiveConfigConstants.PLAY_PAUSE_BUTTON); 154 UiObject2 pauseButton = getSpectatioUiUtil().findUiObject(pauseButtonSelector); 155 getSpectatioUiUtil() 156 .validateUiObject(pauseButton, AutomotiveConfigConstants.PLAY_PAUSE_BUTTON); 157 getSpectatioUiUtil().clickAndWait(pauseButton); 158 getSpectatioUiUtil().wait5Seconds(); 159 } 160 161 /** {@inheritDoc} */ clickNextTrack()162 public void clickNextTrack() { 163 BySelector nextTrackButtonSelector = 164 getUiElementFromConfig(AutomotiveConfigConstants.NEXT_BUTTON); 165 UiObject2 nextTrackButton = getSpectatioUiUtil().findUiObject(nextTrackButtonSelector); 166 getSpectatioUiUtil() 167 .validateUiObject(nextTrackButton, AutomotiveConfigConstants.NEXT_BUTTON); 168 getSpectatioUiUtil().clickAndWait(nextTrackButton); 169 getSpectatioUiUtil().wait5Seconds(); 170 } 171 172 /** {@inheritDoc} */ clickNextTrackFromHomeScreen()173 public void clickNextTrackFromHomeScreen() { 174 BySelector nextTrackButtonSelector = 175 getUiElementFromConfig(AutomotiveConfigConstants.NEXT_BUTTON_HOME_SCREEN); 176 UiObject2 nextTrackHomeScreenButton = 177 getSpectatioUiUtil().findUiObject(nextTrackButtonSelector); 178 getSpectatioUiUtil() 179 .validateUiObject( 180 nextTrackHomeScreenButton, 181 AutomotiveConfigConstants.NEXT_BUTTON_HOME_SCREEN); 182 getSpectatioUiUtil().clickAndWait(nextTrackHomeScreenButton); 183 getSpectatioUiUtil().wait5Seconds(); 184 } 185 186 /** {@inheritDoc} */ clickPreviousTrack()187 public void clickPreviousTrack() { 188 BySelector previousTrackButtonSelector = 189 getUiElementFromConfig(AutomotiveConfigConstants.PREVIOUS_BUTTON); 190 UiObject2 previousTrackMediaCenterButton = 191 getSpectatioUiUtil().findUiObject(previousTrackButtonSelector); 192 getSpectatioUiUtil() 193 .validateUiObject( 194 previousTrackMediaCenterButton, AutomotiveConfigConstants.PREVIOUS_BUTTON); 195 getSpectatioUiUtil().clickAndWait(previousTrackMediaCenterButton); 196 getSpectatioUiUtil().wait5Seconds(); 197 } 198 199 /** {@inheritDoc} */ clickPreviousTrackFromHomeScreen()200 public void clickPreviousTrackFromHomeScreen() { 201 BySelector previousTrackButtonSelector = 202 getUiElementFromConfig(AutomotiveConfigConstants.PREVIOUS_BUTTON_HOME_SCREEN); 203 UiObject2 previousTrackHomeScreenButton = 204 getSpectatioUiUtil().findUiObject(previousTrackButtonSelector); 205 getSpectatioUiUtil() 206 .validateUiObject( 207 previousTrackHomeScreenButton, AutomotiveConfigConstants.PREVIOUS_BUTTON); 208 getSpectatioUiUtil().clickAndWait(previousTrackHomeScreenButton); 209 getSpectatioUiUtil().wait5Seconds(); 210 } 211 212 /** {@inheritDoc} */ clickShuffleAll()213 public void clickShuffleAll() { 214 BySelector shufflePlaylistButtonSelector = 215 getUiElementFromConfig(AutomotiveConfigConstants.SHUFFLE_BUTTON); 216 UiObject2 shufflePlaylistButton = 217 getSpectatioUiUtil().findUiObject(shufflePlaylistButtonSelector); 218 getSpectatioUiUtil() 219 .validateUiObject(shufflePlaylistButton, AutomotiveConfigConstants.SHUFFLE_BUTTON); 220 getSpectatioUiUtil().clickAndWait(shufflePlaylistButton); 221 getSpectatioUiUtil().wait5Seconds(); 222 } 223 224 /** 225 * TODO - Keeping the empty functions for now, to avoid the compilation error in Vendor it will 226 * be removed after vendor clean up (b/266449779) 227 */ 228 229 /** Click the nth instance among the visible menu items */ clickMenuItem(int instance)230 public void clickMenuItem(int instance) {} 231 232 /** 233 * TODO - Keeping the empty functions for now, to avoid the compilation error in Vendor it will 234 * be removed after vendor clean up (b/266449779) 235 */ 236 237 /** {@inheritDoc} */ 238 @Override openMenuWith(String... menuOptions)239 public void openMenuWith(String... menuOptions) {} 240 241 /** 242 * TODO - Keeping the empty functions for now, to avoid the compilation error in Vendor it will 243 * be removed after vendor clean up (b/266449779) 244 */ 245 246 /** {@inheritDoc} */ 247 @Override openNowPlayingWith(String trackName)248 public void openNowPlayingWith(String trackName) {} 249 250 /** {@inheritDoc} */ getMediaTrackName()251 public String getMediaTrackName() { 252 String track; 253 BySelector mediaControlSelector = 254 getUiElementFromConfig(AutomotiveConfigConstants.MINIMIZED_MEDIA_CONTROLS); 255 UiObject2 mediaControl = getSpectatioUiUtil().findUiObject(mediaControlSelector); 256 257 if (mediaControl != null) { 258 track = getMediaTrackNameFromMinimizedControl(); 259 } else { 260 track = getMediaTrackNameFromPlayback(); 261 } 262 return track; 263 } 264 265 /** {@inheritDoc} */ getMediaTrackNameFromHomeScreen()266 public String getMediaTrackNameFromHomeScreen() { 267 String trackName; 268 BySelector trackNameSelector = 269 getUiElementFromConfig(AutomotiveConfigConstants.TRACK_NAME_HOME_SCREEN); 270 UiObject2 trackNamexTextHomeScreen = getSpectatioUiUtil().findUiObject(trackNameSelector); 271 getSpectatioUiUtil() 272 .validateUiObject( 273 trackNamexTextHomeScreen, AutomotiveConfigConstants.TRACK_NAME_HOME_SCREEN); 274 trackName = trackNamexTextHomeScreen.getText(); 275 return trackName; 276 } 277 getMediaTrackNameFromMinimizedControl()278 private String getMediaTrackNameFromMinimizedControl() { 279 String trackName; 280 BySelector trackNameSelector = 281 getUiElementFromConfig(AutomotiveConfigConstants.TRACK_NAME_MINIMIZED_CONTROL); 282 UiObject2 trackNameTextMinimizeControl = 283 getSpectatioUiUtil().findUiObject(trackNameSelector); 284 getSpectatioUiUtil() 285 .validateUiObject( 286 trackNameTextMinimizeControl, 287 AutomotiveConfigConstants.TRACK_NAME_MINIMIZED_CONTROL); 288 trackName = trackNameTextMinimizeControl.getText(); 289 return trackName; 290 } 291 getMediaTrackNameFromPlayback()292 private String getMediaTrackNameFromPlayback() { 293 String trackName; 294 BySelector trackNameSelector = getUiElementFromConfig(AutomotiveConfigConstants.TRACK_NAME); 295 UiObject2 trackNameTextPlayback = getSpectatioUiUtil().findUiObject(trackNameSelector); 296 getSpectatioUiUtil() 297 .validateUiObject(trackNameTextPlayback, AutomotiveConfigConstants.TRACK_NAME); 298 trackName = trackNameTextPlayback.getText(); 299 return trackName; 300 } 301 302 /** {@inheritDoc} */ goBackToMediaHomePage()303 public void goBackToMediaHomePage() { 304 minimizeNowPlaying(); 305 BySelector back_btnSelector = getUiElementFromConfig(AutomotiveConfigConstants.BACK_BUTTON); 306 UiObject2 back_btn = getSpectatioUiUtil().findUiObject(back_btnSelector); 307 getSpectatioUiUtil().validateUiObject(back_btn, AutomotiveConfigConstants.BACK_BUTTON); 308 while (back_btn != null) { 309 getSpectatioUiUtil().clickAndWait(back_btn); 310 getSpectatioUiUtil().wait5Seconds(); 311 back_btn = getSpectatioUiUtil().findUiObject(back_btnSelector); 312 } 313 } 314 315 /** Minimize the Now Playing window. */ 316 /** {@inheritDoc} */ 317 @Override minimizeNowPlaying()318 public void minimizeNowPlaying() { 319 BySelector trackNameSelector = getUiElementFromConfig(AutomotiveConfigConstants.TRACK_NAME); 320 UiObject2 trackNameText = getSpectatioUiUtil().findUiObject(trackNameSelector); 321 if (trackNameText != null) { 322 trackNameText.swipe(Direction.DOWN, 1.0f, 500); 323 } 324 } 325 326 /** Maximize the Now Playing window. */ 327 /** {@inheritDoc} */ 328 @Override maximizeNowPlaying()329 public void maximizeNowPlaying() { 330 BySelector trackNameSelector = 331 getUiElementFromConfig(AutomotiveConfigConstants.MINIMIZED_MEDIA_CONTROLS); 332 UiObject2 trackNameText = getSpectatioUiUtil().findUiObject(trackNameSelector); 333 if (trackNameText != null) { 334 trackNameText.click(); 335 } 336 } 337 338 /** 339 * Scrolls through the list in search of the provided menu 340 * 341 * @param menu : menu to search 342 * @return UiObject found for the menu searched 343 */ selectByName(String menu)344 private UiObject selectByName(String menu) throws UiObjectNotFoundException { 345 UiObject menuListItem = null; 346 347 /** 348 * TODO - Keeping the empty functions for now, to avoid the compilation error in Vendor it 349 * will be removed after vendor clean up (b/266449779) 350 */ 351 return menuListItem; 352 } 353 354 /** {@inheritDoc} */ 355 @Override isPlaying()356 public boolean isPlaying() { 357 List<MediaController> controllers = mMediaSessionManager.getActiveSessions(null); 358 if (controllers.size() == 0) { 359 throw new RuntimeException("Unable to find Media Controller"); 360 } 361 PlaybackState state = controllers.get(0).getPlaybackState(); 362 return state.getState() == PlaybackState.STATE_PLAYING; 363 } 364 365 /** {@inheritDoc} */ 366 @Override getMediaAppTitle()367 public String getMediaAppTitle() { 368 BySelector mediaAppTitleSelector = 369 getUiElementFromConfig(AutomotiveConfigConstants.MEDIA_APP_TITLE); 370 UiObject2 mediaAppTitle = getSpectatioUiUtil().findUiObject(mediaAppTitleSelector); 371 getSpectatioUiUtil() 372 .validateUiObject(mediaAppTitle, AutomotiveConfigConstants.MEDIA_APP_TITLE); 373 return mediaAppTitle.getText(); 374 } 375 376 /** {@inheritDoc} */ 377 @Override openMediaAppMenuItems()378 public void openMediaAppMenuItems() { 379 BySelector mediaDropDownMenuSelector = 380 getUiElementFromConfig(AutomotiveConfigConstants.MEDIA_APP_DROP_DOWN_MENU); 381 List<UiObject2> menuItemElements = 382 getSpectatioUiUtil().findUiObjects(mediaDropDownMenuSelector); 383 getSpectatioUiUtil() 384 .validateUiObjects( 385 menuItemElements, AutomotiveConfigConstants.MEDIA_APP_DROP_DOWN_MENU); 386 if (menuItemElements.size() == 0) { 387 throw new UnknownUiException("Unable to find Media drop down."); 388 } 389 // Media menu drop down is the last item in Media App Screen 390 int positionOfMenuItemDropDown = menuItemElements.size() - 1; 391 getSpectatioUiUtil().clickAndWait(menuItemElements.get(positionOfMenuItemDropDown)); 392 } 393 394 /** {@inheritDoc} */ 395 @Override areMediaAppsPresent(List<String> mediaAppsNames)396 public boolean areMediaAppsPresent(List<String> mediaAppsNames) { 397 BySelector mediaAppPageTitleSelector = 398 getUiElementFromConfig(AutomotiveConfigConstants.MEDIA_APPS_GRID_TITLE); 399 UiObject2 mediaAppPageTitle = getSpectatioUiUtil().findUiObject(mediaAppPageTitleSelector); 400 getSpectatioUiUtil() 401 .validateUiObject( 402 mediaAppPageTitle, AutomotiveConfigConstants.MEDIA_APPS_GRID_TITLE); 403 if (mediaAppsNames == null || mediaAppsNames.size() == 0) { 404 return false; 405 } 406 // Scroll and find media apps in Media App Grid 407 for (String expectedApp : mediaAppsNames) { 408 UiObject2 mediaApp = 409 scrollAndFindApp( 410 By.text(Pattern.compile(expectedApp, Pattern.CASE_INSENSITIVE))); 411 if (mediaApp == null || !mediaApp.getText().equals(expectedApp)) { 412 return false; 413 } 414 } 415 return true; 416 } 417 418 /** 419 * {@inheritDoc} 420 */ 421 @Override openApp(String appName)422 public void openApp(String appName) { 423 getSpectatioUiUtil().wait1Second(); // to avoid stale object error 424 UiObject2 app = scrollAndFindApp(By.text(appName)); 425 if (app != null) { 426 getSpectatioUiUtil().clickAndWait(app); 427 } else { 428 throw new IllegalStateException(String.format("App %s cannot be found", appName)); 429 } 430 } 431 432 /** 433 * {@inheritDoc} 434 */ 435 @Override openMediaAppSettingsPage()436 public void openMediaAppSettingsPage() { 437 BySelector menuItemElementSelector = 438 getUiElementFromConfig(AutomotiveConfigConstants.MEDIA_APP_DROP_DOWN_MENU); 439 List<UiObject2> menuItemElements = 440 getSpectatioUiUtil().findUiObjects(menuItemElementSelector); 441 getSpectatioUiUtil() 442 .validateUiObjects( 443 menuItemElements, AutomotiveConfigConstants.MEDIA_APP_DROP_DOWN_MENU); 444 int settingsItemPosition = menuItemElements.size() - 2; 445 getSpectatioUiUtil().clickAndWait(menuItemElements.get(settingsItemPosition)); 446 } 447 448 /** {@inheritDoc} */ 449 @Override getMediaAppUserNotLoggedInErrorMessage()450 public String getMediaAppUserNotLoggedInErrorMessage() { 451 BySelector noLoginMsgSelector = 452 getUiElementFromConfig(AutomotiveConfigConstants.MEDIA_APP_NO_LOGIN_MSG); 453 UiObject2 noLoginMsg = getSpectatioUiUtil().findUiObject(noLoginMsgSelector); 454 getSpectatioUiUtil() 455 .validateUiObject(noLoginMsg, AutomotiveConfigConstants.MEDIA_APP_NO_LOGIN_MSG); 456 return noLoginMsg.getText(); 457 } 458 459 /** {@inheritDoc} */ 460 @Override selectMediaTrack(String... menuOptions)461 public void selectMediaTrack(String... menuOptions) { 462 for (String option : menuOptions) { 463 UiObject2 mediaTrack = 464 scrollAndFindApp(By.text(Pattern.compile(option, Pattern.CASE_INSENSITIVE))); 465 getSpectatioUiUtil() 466 .validateUiObject(mediaTrack, String.format("media track: %s", option)); 467 mediaTrack.click(); 468 getSpectatioUiUtil().waitForIdle(); 469 } 470 } 471 472 /** {@inheritDoc} */ 473 @Override isBluetoothAudioDisconnectedLabelVisible()474 public boolean isBluetoothAudioDisconnectedLabelVisible() { 475 BySelector isBluetoothAudioDisconnectedLabel = 476 getUiElementFromConfig(AutomotiveConfigConstants.BLUETOOTH_DISCONNECTED_LABEL); 477 return getSpectatioUiUtil().hasUiElement(isBluetoothAudioDisconnectedLabel); 478 } 479 scrollAndFindApp(BySelector selector)480 private UiObject2 scrollAndFindApp(BySelector selector) { 481 482 UiObject2 object = 483 mScrollUtility.scrollAndFindUiObject( 484 mScrollAction, 485 mScrollDirection, 486 mForwardButtonSelector, 487 mBackwardButtonSelector, 488 mScrollableElementSelector, 489 selector, 490 String.format("Scroll through media app grid to find %s", selector)); 491 getSpectatioUiUtil() 492 .validateUiObject(object, String.format("Given media app %s", selector)); 493 return object; 494 } 495 496 } 497