• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.os.SystemClock;
26 import android.platform.helpers.exceptions.UnknownUiException;
27 import android.support.test.uiautomator.By;
28 import android.support.test.uiautomator.Direction;
29 import android.support.test.uiautomator.UiObject;
30 import android.support.test.uiautomator.UiObject2;
31 import android.support.test.uiautomator.UiObjectNotFoundException;
32 import android.support.test.uiautomator.UiScrollable;
33 import android.support.test.uiautomator.UiSelector;
34 
35 import java.util.List;
36 import java.util.regex.Pattern;
37 
38 public class MediaCenterHelperImpl extends AbstractAutoStandardAppHelper
39         implements IAutoMediaHelper {
40     // Wait Time
41     private static final int UI_RESPONSE_WAIT_MS = 5000;
42     private static final int SHORT_RESPONSE_WAIT_MS = 1000;
43 
44     private static final String MEDIA_LAUNCH_COMMAND =
45             "am start -a android.car.intent.action.MEDIA_TEMPLATE -e "
46                     + "android.car.intent.extra.MEDIA_COMPONENT ";
47 
48     private MediaSessionManager mMediaSessionManager;
49     private UiAutomation mUiAutomation;
50 
MediaCenterHelperImpl(Instrumentation instr)51     public MediaCenterHelperImpl(Instrumentation instr) {
52         super(instr);
53         mUiAutomation = instr.getUiAutomation();
54         mUiAutomation.adoptShellPermissionIdentity("android.permission.MEDIA_CONTENT_CONTROL");
55         mMediaSessionManager =
56                 (MediaSessionManager)
57                         instr.getContext().getSystemService(Context.MEDIA_SESSION_SERVICE);
58     }
59 
60     /** {@inheritDoc} */
61     @Override
getPackage()62     public String getPackage() {
63         return getApplicationConfig(AutoConfigConstants.MEDIA_CENTER_PACKAGE);
64     }
65 
66     /** {@inheritDoc} */
open()67     public void open() {
68         openMediaApp(getApplicationConfig(AutoConfigConstants.MEDIA_ACTIVITY));
69     }
70 
openMediaApp(String packagename)71     private void openMediaApp(String packagename) {
72         pressHome();
73         waitForIdle();
74         executeShellCommand(MEDIA_LAUNCH_COMMAND + packagename);
75     }
76 
77     /** {@inheritDoc} */
playMedia()78     public void playMedia() {
79         if (!isPlaying()) {
80             UiObject2 playButton =
81                     findUiObject(
82                             getResourceFromConfig(
83                                     AutoConfigConstants.MEDIA_CENTER,
84                                     AutoConfigConstants.MEDIA_CENTER_SCREEN,
85                                     AutoConfigConstants.PLAY_PAUSE_BUTTON));
86             if (playButton == null) {
87                 throw new UnknownUiException("Unable to find play/pause button");
88             }
89             clickAndWaitForIdleScreen(playButton);
90             SystemClock.sleep(UI_RESPONSE_WAIT_MS);
91         }
92     }
93 
94     /** {@inheritDoc} */
playPauseMediaFromHomeScreen()95     public void playPauseMediaFromHomeScreen() {
96         UiObject2 playButton =
97                 findUiObject(
98                         getResourceFromConfig(
99                                 AutoConfigConstants.MEDIA_CENTER,
100                                 AutoConfigConstants.MEDIA_CENTER_ON_HOME_SCREEN,
101                                 AutoConfigConstants.PLAY_PAUSE_BUTTON));
102         if (playButton == null) {
103             throw new UnknownUiException("Unable to find play button from home screen");
104         }
105         clickAndWaitForIdleScreen(playButton);
106         SystemClock.sleep(UI_RESPONSE_WAIT_MS);
107     }
108 
109     /** {@inheritDoc} */
pauseMedia()110     public void pauseMedia() {
111         if (isPlaying()) {
112             UiObject2 pauseButton =
113                     findUiObject(
114                             getResourceFromConfig(
115                                     AutoConfigConstants.MEDIA_CENTER,
116                                     AutoConfigConstants.MEDIA_CENTER_SCREEN,
117                                     AutoConfigConstants.PLAY_PAUSE_BUTTON));
118             if (pauseButton == null) {
119                 throw new UnknownUiException("Unable to find pause button");
120             }
121             clickAndWaitForIdleScreen(pauseButton);
122             SystemClock.sleep(UI_RESPONSE_WAIT_MS);
123         }
124     }
125 
126     /** {@inheritDoc} */
clickNextTrack()127     public void clickNextTrack() {
128         UiObject2 nextTrackButton =
129                 findUiObject(
130                         getResourceFromConfig(
131                                 AutoConfigConstants.MEDIA_CENTER,
132                                 AutoConfigConstants.MEDIA_CENTER_SCREEN,
133                                 AutoConfigConstants.NEXT_BUTTON));
134         if (nextTrackButton == null) {
135             throw new UnknownUiException("Unable to find next track button");
136         }
137         clickAndWaitForIdleScreen(nextTrackButton);
138         SystemClock.sleep(UI_RESPONSE_WAIT_MS);
139     }
140 
141     /** {@inheritDoc} */
clickNextTrackFromHomeScreen()142     public void clickNextTrackFromHomeScreen() {
143         UiObject2 nextTrackButton =
144                 findUiObject(
145                         getResourceFromConfig(
146                                 AutoConfigConstants.MEDIA_CENTER,
147                                 AutoConfigConstants.MEDIA_CENTER_ON_HOME_SCREEN,
148                                 AutoConfigConstants.NEXT_BUTTON));
149         if (nextTrackButton == null) {
150             throw new UnknownUiException("Unable to find next track button from home screen");
151         }
152         clickAndWaitForIdleScreen(nextTrackButton);
153         SystemClock.sleep(UI_RESPONSE_WAIT_MS);
154     }
155 
156     /** {@inheritDoc} */
clickPreviousTrack()157     public void clickPreviousTrack() {
158         UiObject2 previousTrackButton =
159                 findUiObject(
160                         getResourceFromConfig(
161                                 AutoConfigConstants.MEDIA_CENTER,
162                                 AutoConfigConstants.MEDIA_CENTER_SCREEN,
163                                 AutoConfigConstants.PREVIOUS_BUTTON));
164         if (previousTrackButton == null) {
165             throw new UnknownUiException("Unable to find previous track button");
166         }
167         clickAndWaitForIdleScreen(previousTrackButton);
168         SystemClock.sleep(UI_RESPONSE_WAIT_MS);
169     }
170 
171     /** {@inheritDoc} */
clickPreviousTrackFromHomeScreen()172     public void clickPreviousTrackFromHomeScreen() {
173         UiObject2 previousTrackButton =
174                 findUiObject(
175                         getResourceFromConfig(
176                                 AutoConfigConstants.MEDIA_CENTER,
177                                 AutoConfigConstants.MEDIA_CENTER_ON_HOME_SCREEN,
178                                 AutoConfigConstants.PREVIOUS_BUTTON));
179         if (previousTrackButton == null) {
180             throw new UnknownUiException("Unable to find previous track button");
181         }
182         clickAndWaitForIdleScreen(previousTrackButton);
183         SystemClock.sleep(UI_RESPONSE_WAIT_MS);
184     }
185 
186     /** {@inheritDoc} */
clickShuffleAll()187     public void clickShuffleAll() {
188         UiObject2 shufflePlaylistButton =
189                 findUiObject(
190                         getResourceFromConfig(
191                                 AutoConfigConstants.MEDIA_CENTER,
192                                 AutoConfigConstants.MEDIA_CENTER_SCREEN,
193                                 AutoConfigConstants.SHUFFLE_BUTTON));
194         if (shufflePlaylistButton == null) {
195             throw new UnknownUiException("Unable to find shuffle playlist button");
196         }
197         clickAndWaitForIdleScreen(shufflePlaylistButton);
198     }
199 
200     /** Click the nth instance among the visible menu items */
clickMenuItem(int instance)201     public void clickMenuItem(int instance) {
202         if (!mDevice.hasObject(By.scrollable(true))) {
203             // Menu is not open
204             return;
205         }
206         UiScrollable menuList = new UiScrollable(new UiSelector().scrollable(true));
207         menuList.setAsVerticalList();
208         try {
209             UiObject menuListItem =
210                     menuList.getChildByInstance(new UiSelector().clickable(true), instance);
211             menuListItem.clickAndWaitForNewWindow(UI_RESPONSE_WAIT_MS);
212             waitForIdle();
213         } catch (UiObjectNotFoundException e) {
214             throw new UnknownUiException("Unable to find menu item", e);
215         }
216     }
217 
218     /** {@inheritDoc} */
openMenuWith(String... menuOptions)219     public void openMenuWith(String... menuOptions) {
220         for (String menu : menuOptions) {
221             UiObject2 menuButton = findUiObject(By.text(menu));
222             if (menuButton != null) {
223                 clickAndWaitForIdleScreen(menuButton);
224                 waitForGone(By.text(menu));
225             } else {
226                 try {
227                     UiObject menuItem_object = selectByName(menu);
228                     menuItem_object.clickAndWaitForNewWindow();
229                 } catch (UiObjectNotFoundException exception) {
230                     throw new UnknownUiException("Unable to find the menu item");
231                 }
232             }
233             SystemClock.sleep(SHORT_RESPONSE_WAIT_MS);
234         }
235     }
236 
237     /** {@inheritDoc} */
openNowPlayingWith(String trackName)238     public void openNowPlayingWith(String trackName) {
239         UiObject2 nowPlayingButton =
240                 findUiObject(
241                         getResourceFromConfig(
242                                 AutoConfigConstants.MEDIA_CENTER,
243                                 AutoConfigConstants.MEDIA_CENTER_SCREEN,
244                                 AutoConfigConstants.PLAY_QUEUE_BUTTON));
245         if (nowPlayingButton == null) {
246             throw new UnknownUiException("Unable to find Now playing button");
247         }
248         clickAndWaitForIdleScreen(nowPlayingButton);
249         waitForWindowUpdate(getApplicationConfig(AutoConfigConstants.MEDIA_CENTER_PACKAGE));
250         UiObject2 playTrackName = findUiObject(By.text(trackName));
251         if (playTrackName != null) {
252             clickAndWaitForIdleScreen(playTrackName);
253         } else {
254             try {
255                 UiObject menuItem_object = selectByName(trackName);
256                 menuItem_object.clickAndWaitForNewWindow();
257             } catch (UiObjectNotFoundException exception) {
258                 throw new UnknownUiException("Unable to find the trackname from Now playing list");
259             }
260         }
261     }
262 
263     /** {@inheritDoc} */
getMediaTrackName()264     public String getMediaTrackName() {
265         String track;
266         UiObject2 mediaControl =
267                 findUiObject(
268                         getResourceFromConfig(
269                                 AutoConfigConstants.MEDIA_CENTER,
270                                 AutoConfigConstants.MEDIA_CENTER_SCREEN,
271                                 AutoConfigConstants.MINIMIZED_MEDIA_CONTROLS));
272         if (mediaControl != null) {
273             track = getMediaTrackNameFromMinimizedControl();
274         } else {
275             track = getMediaTrackNameFromPlayback();
276         }
277         return track;
278     }
279 
280     /** {@inheritDoc} */
getMediaTrackNameFromHomeScreen()281     public String getMediaTrackNameFromHomeScreen() {
282         String trackName;
283         UiObject2 trackNameText =
284                 findUiObject(
285                         getResourceFromConfig(
286                                 AutoConfigConstants.MEDIA_CENTER,
287                                 AutoConfigConstants.MEDIA_CENTER_ON_HOME_SCREEN,
288                                 AutoConfigConstants.TRACK_NAME));
289         if (trackNameText == null) {
290             throw new UnknownUiException("Unable to find track name from Home Screen");
291         }
292         trackName = trackNameText.getText();
293         return trackName;
294     }
295 
getMediaTrackNameFromMinimizedControl()296     private String getMediaTrackNameFromMinimizedControl() {
297         String trackName;
298         UiObject2 trackNameText =
299                 findUiObject(
300                         getResourceFromConfig(
301                                 AutoConfigConstants.MEDIA_CENTER,
302                                 AutoConfigConstants.MEDIA_CENTER_SCREEN,
303                                 AutoConfigConstants.TRACK_NAME_MINIMIZED_CONTROL));
304         if (trackNameText == null) {
305             throw new UnknownUiException("Unable to find track name from minimized control");
306         }
307         trackName = trackNameText.getText();
308         return trackName;
309     }
310 
getMediaTrackNameFromPlayback()311     private String getMediaTrackNameFromPlayback() {
312         String trackName;
313         waitForIdle();
314         UiObject2 trackNameText =
315                 findUiObject(
316                         getResourceFromConfig(
317                                 AutoConfigConstants.MEDIA_CENTER,
318                                 AutoConfigConstants.MEDIA_CENTER_SCREEN,
319                                 AutoConfigConstants.TRACK_NAME));
320         if (trackNameText == null) {
321             throw new UnknownUiException("Unable to find track name from now playing");
322         }
323         trackName = trackNameText.getText();
324         return trackName;
325     }
326 
327     /** {@inheritDoc} */
goBackToMediaHomePage()328     public void goBackToMediaHomePage() {
329         minimizeNowPlaying();
330         UiObject2 back_btn =
331                 findUiObject(
332                         getResourceFromConfig(
333                                 AutoConfigConstants.MEDIA_CENTER,
334                                 AutoConfigConstants.MEDIA_CENTER_SCREEN,
335                                 AutoConfigConstants.BACK_BUTTON));
336         while (back_btn != null) {
337             clickAndWaitForIdleScreen(back_btn);
338             back_btn =
339                     findUiObject(
340                             getResourceFromConfig(
341                                     AutoConfigConstants.MEDIA_CENTER,
342                                     AutoConfigConstants.MEDIA_CENTER_SCREEN,
343                                     AutoConfigConstants.BACK_BUTTON));
344         }
345     }
346 
347     /**
348      * Minimize the Now Playing window.
349      */
minimizeNowPlaying()350     private void minimizeNowPlaying() {
351         UiObject2 trackNameText =
352                 findUiObject(
353                         getResourceFromConfig(
354                                 AutoConfigConstants.MEDIA_CENTER,
355                                 AutoConfigConstants.MEDIA_CENTER_SCREEN,
356                                 AutoConfigConstants.TRACK_NAME));
357         if (trackNameText != null) {
358             trackNameText.swipe(Direction.DOWN, 1.0f, 500);
359         }
360     }
361 
362     /**
363      * Scrolls through the list in search of the provided menu
364      *
365      * @param menu : menu to search
366      * @return UiObject found for the menu searched
367      */
selectByName(String menu)368     private UiObject selectByName(String menu) throws UiObjectNotFoundException {
369         UiObject menuListItem = null;
370         UiScrollable menuList = new UiScrollable(new UiSelector().scrollable(true));
371         menuList.setAsVerticalList();
372         menuListItem =
373                 menuList.getChildByText(
374                         new UiSelector().className(android.widget.TextView.class.getName()), menu);
375         mDevice.waitForIdle();
376         return menuListItem;
377     }
378 
379     /** {@inheritDoc} */
380     @Override
isPlaying()381     public boolean isPlaying() {
382         List<MediaController> controllers = mMediaSessionManager.getActiveSessions(null);
383         if (controllers.size() == 0) {
384             throw new RuntimeException("Unable to find Media Controller");
385         }
386         PlaybackState state = controllers.get(0).getPlaybackState();
387         return state.getState() == PlaybackState.STATE_PLAYING;
388     }
389 
390     /** {@inheritDoc} */
391     @Override
getMediaAppTitle()392     public String getMediaAppTitle() {
393         UiObject2 mediaAppTitle = findUiObject(getResourceFromConfig(
394                 AutoConfigConstants.MEDIA_CENTER,
395                 AutoConfigConstants.MEDIA_APP,
396                 AutoConfigConstants.MEDIA_APP_TITLE));
397         if (mediaAppTitle == null) {
398             throw new UnknownUiException("Unable to find Media app title text.");
399         }
400         return mediaAppTitle.getText();
401     }
402 
403     /** {@inheritDoc} */
404     @Override
openMediaAppMenuItems()405     public void openMediaAppMenuItems() {
406         List<UiObject2> menuItemElements = findUiObjects(getResourceFromConfig(
407                 AutoConfigConstants.MEDIA_CENTER,
408                 AutoConfigConstants.MEDIA_APP,
409                 AutoConfigConstants.MEDIA_APP_DROP_DOWN_MENU));
410         if (menuItemElements.size() == 0) {
411             throw new UnknownUiException("Unable to find Media drop down.");
412         }
413         // Media menu drop down is the last item in Media App Screen
414         int positionOfMenuItemDropDown = menuItemElements.size() - 1;
415         clickAndWaitForIdleScreen(menuItemElements.get(positionOfMenuItemDropDown));
416     }
417 
418     /** {@inheritDoc} */
419     @Override
areMediaAppsPresent(List<String> mediaAppsNames)420     public boolean areMediaAppsPresent(List<String> mediaAppsNames) {
421         UiObject2 mediaAppPageTitle =
422                 findUiObject(
423                         getResourceFromConfig(
424                                 AutoConfigConstants.MEDIA_CENTER,
425                                 AutoConfigConstants.MEDIA_APPS_GRID,
426                                 AutoConfigConstants.MEDIA_APPS_GRID_TITLE));
427         if (mediaAppPageTitle == null) {
428             throw new RuntimeException("Media apps grid activity not open.");
429         }
430         if (mediaAppsNames == null || mediaAppsNames.size() == 0) {
431             return false;
432         }
433         // Scroll and find media apps in Media App Grid
434         for (String expectedApp : mediaAppsNames) {
435             UiObject2 mediaApp =
436                     scrollAndFindUiObject(
437                             By.text(Pattern.compile(expectedApp, Pattern.CASE_INSENSITIVE)));
438             if (mediaApp == null || !mediaApp.getText().equals(expectedApp)) {
439                 return false;
440             }
441         }
442         return true;
443     }
444 
445     /**
446      * {@inheritDoc}
447      */
448     @Override
openApp(String appName)449     public void openApp(String appName) {
450         SystemClock.sleep(SHORT_RESPONSE_WAIT_MS); // to avoid stale object error
451         UiObject2 app = scrollAndFindUiObject(By.text(appName));
452         if (app != null) {
453             clickAndWaitForIdleScreen(app);
454         } else {
455             throw new IllegalStateException(String.format("App %s cannot be found", appName));
456         }
457     }
458 
459     /**
460      * {@inheritDoc}
461      */
462     @Override
openMediaAppSettingsPage()463     public void openMediaAppSettingsPage() {
464         List<UiObject2> mediaAppMenuItem = findUiObjects(getResourceFromConfig(
465                 AutoConfigConstants.MEDIA_CENTER,
466                 AutoConfigConstants.MEDIA_APP,
467                 AutoConfigConstants.MEDIA_APP_DROP_DOWN_MENU));
468         if (mediaAppMenuItem.size() == 0) {
469             throw new UnknownUiException("Unable to find Media App menu items.");
470         }
471         // settings page is 2nd last item in Menu Item list
472         int settingsItemPosition = mediaAppMenuItem.size() - 2;
473         clickAndWaitForIdleScreen(mediaAppMenuItem.get(settingsItemPosition));
474     }
475 
476     /** {@inheritDoc} */
477     @Override
getMediaAppUserNotLoggedInErrorMessage()478     public String getMediaAppUserNotLoggedInErrorMessage() {
479         UiObject2 noLoginMsg = findUiObject(getResourceFromConfig(
480                 AutoConfigConstants.MEDIA_CENTER,
481                 AutoConfigConstants.MEDIA_APP,
482                 AutoConfigConstants.MEDIA_APP_NO_LOGIN_MSG));
483         if (noLoginMsg == null) {
484             throw new UnknownUiException("Unable to find Media app error text.");
485         }
486         return noLoginMsg.getText();
487     }
488 }
489