Merge "Update Photos App Helper to improve dismiss initial dialog" into nyc-dev
diff --git a/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractStandardAppHelper.java b/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractStandardAppHelper.java
index f16aaac..93fd1fe 100644
--- a/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractStandardAppHelper.java
+++ b/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractStandardAppHelper.java
@@ -56,6 +56,7 @@
int maxBacks = 4;
while (!mDevice.hasObject(mLauncherStrategy.getWorkspaceSelector()) && maxBacks > 0) {
mDevice.pressBack();
+ mDevice.waitForIdle();
maxBacks--;
}
diff --git a/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractYouTubeHelper.java b/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractYouTubeHelper.java
index 0f7e7ed..aa0c641 100644
--- a/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractYouTubeHelper.java
+++ b/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractYouTubeHelper.java
@@ -45,13 +45,6 @@
}
/**
- * Setup expectations: YouTube is on the home page.
- *
- * This method selects the first video and blocks until the video is playing.
- */
- public abstract void playFirstVideo();
-
- /**
* Setup expectations: YouTube app is open.
*
* This method keeps pressing the back button until YouTube is on the home page.
@@ -66,6 +59,28 @@
public abstract void goToSearchPage();
/**
+ * Setup expectations: YouTube is on the non-fullscreen video player page.
+ *
+ * This method changes the video player to fullscreen mode. Has no effect if the video player
+ * is already in fullscreen mode.
+ */
+ public abstract void goToFullscreenMode();
+
+ /**
+ * Setup expectations: YouTube is on the home page.
+ *
+ * This method selects a video on the home page and blocks until the video is playing.
+ */
+ public abstract void playHomePageVideo();
+
+ /**
+ * Setup expectations: YouTube is on the search results page.
+ *
+ * This method selects a search result video and blocks until the video is playing.
+ */
+ public abstract void playSearchResultPageVideo();
+
+ /**
* Setup expectations: Recently opened a video in the YouTube app.
*
* This method blocks until the video has loaded.
@@ -96,17 +111,9 @@
public abstract void setVideoQuality(VideoQuality quality);
/**
- * Setup expectations: YouTube is on the non-fullscreen video player page.
- *
- * This method changes the video player to fullscreen mode. Has no effect if the video player
- * is already in fullscreen mode.
- */
- public abstract void goToFullscreenMode();
-
- /**
* Setup expectations: YouTube is on the video player page.
*
- * This method plays the video if it is paused.
+ * This method resumes the video if it is paused.
*/
- public abstract void playVideo();
+ public abstract void resumeVideo();
}
diff --git a/libraries/facebook-app-helper/src/android/platform/test/helpers/FacebookHelperImpl.java b/libraries/facebook-app-helper/src/android/platform/test/helpers/FacebookHelperImpl.java
index bd24f42..b7f39f6 100644
--- a/libraries/facebook-app-helper/src/android/platform/test/helpers/FacebookHelperImpl.java
+++ b/libraries/facebook-app-helper/src/android/platform/test/helpers/FacebookHelperImpl.java
@@ -31,18 +31,19 @@
public class FacebookHelperImpl extends AbstractFacebookHelper {
private static final String TAG = "android.platform.test.helpers.FacebookHelperImpl";
- private static final String UI_HOME_PAGE_CONTAINER_ID = "tab_content_viewpager";
+ private static final String UI_HOME_PAGE_CONTAINER_ID = "cs7";
private static final String UI_LOADING_VIEW_ID = "loading_view";
- private static final String UI_LOGIN_BUTTON_ID = "login_login";
- private static final String UI_LOGIN_PASSWORD_ID = "login_password";
- private static final String UI_LOGIN_ROOT_ID = "login_root";
- private static final String UI_LOGIN_USERNAME_ID = "login_username";
- private static final String UI_NEWS_FEED_TAB_ID = "news_feed_tab";
- private static final String UI_NEWS_FEED_TAB_SELECTED_DESC = "Selected";
+ private static final String UI_LOGIN_BUTTON_ID = "bjb";
+ private static final String UI_LOGIN_PASSWORD_ID = "bj_";
+ private static final String UI_LOGIN_ROOT_ID = "bj6";
+ private static final String UI_LOGIN_USERNAME_ID = "bj8";
+ private static final String UI_NEWS_FEED_TAB_ID = "a0";
+ private static final String UI_NEWS_FEED_TAB_SELECTED_DESC = "News";
private static final String UI_PACKAGE_NAME = "com.facebook.katana";
- private static final String UI_POST_BUTTON_ID = "primary_named_button";
- private static final String UI_STATUS_TEXT_ID = "status_text";
- private static final String UI_STATUS_UPDATE_BUTTON_ID = "feed_composer_status_button";
+ private static final String UI_POST_BUTTON_ID = "rk";
+ private static final String UI_STATUS_TEXT_ID = "cmk";
+ private static final String UI_STATUS_UPDATE_BUTTON_ID = "bmp";
+ private static final String UI_LOGIN_ONE_TAP = "sc";
private static final long UI_LOGIN_WAIT = 30000;
private static final long UI_NAVIGATION_WAIT = 10000;
@@ -174,6 +175,8 @@
statusUpdateButton.click();
mDevice.wait(Until.findObject(
By.res(UI_PACKAGE_NAME, UI_STATUS_TEXT_ID)), UI_NAVIGATION_WAIT);
+
+ getStatusTextField().click();
}
private UiObject2 getStatusTextField() {
@@ -266,6 +269,14 @@
usernameTextField.setText(username);
passwordTextField.setText(password);
loginButton.click();
+
+ // Check if one tap login screen is prompted and click on it
+ UiObject2 oneTapLogin = mDevice.wait(Until.findObject(
+ By.res(UI_PACKAGE_NAME, UI_LOGIN_ONE_TAP)), UI_NAVIGATION_WAIT);
+ if (oneTapLogin != null) {
+ oneTapLogin.click();
+ }
+
mDevice.wait(Until.findObject(
By.res(UI_PACKAGE_NAME, UI_HOME_PAGE_CONTAINER_ID)), UI_NAVIGATION_WAIT);
// Wait for user content to load after logging in
diff --git a/libraries/play-movies-app-helper/src/android/platform/test/helpers/PlayMoviesHelperImpl.java b/libraries/play-movies-app-helper/src/android/platform/test/helpers/PlayMoviesHelperImpl.java
index 263cc85..99830f5 100644
--- a/libraries/play-movies-app-helper/src/android/platform/test/helpers/PlayMoviesHelperImpl.java
+++ b/libraries/play-movies-app-helper/src/android/platform/test/helpers/PlayMoviesHelperImpl.java
@@ -19,6 +19,7 @@
import android.app.Instrumentation;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.SystemClock;
+import android.platform.test.helpers.exceptions.UnknownUiException;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.BySelector;
import android.support.test.uiautomator.Configurator;
@@ -31,12 +32,14 @@
import java.util.regex.Pattern;
-import junit.framework.Assert;
-
public class PlayMoviesHelperImpl extends AbstractPlayMoviesHelper {
private static final String LOG_TAG = PlayMoviesHelperImpl.class.getSimpleName();
- private static final String UI_PACKAGE = "com.google.android.videos";
+ private static final String UI_PACKAGE = "com.google.android.videos";
+ private static final String UI_NAV_DRAWER_ID = "play_drawer_list";
+ private static final String UI_MOVIE_LIST_ID = "play_header_listview";
+
+ private static final int SEARCH_MOVIES_SCROLL_RETRY = 4;
private static final long APP_INIT_WAIT = 5000;
private boolean mIsVersion3p8 = false;
@@ -69,7 +72,7 @@
*/
@Override
public String getPackage() {
- return "com.google.android.videos";
+ return UI_PACKAGE;
}
/**
@@ -126,12 +129,15 @@
public void openMoviesTab() {
// Navigate to the Movies tab through the Navigation drawer
openNavigationDrawer();
- UiObject2 libraryButton = mDevice.findObject(By.text("My Library").clickable(true));
+ Pattern myLibraryPattern = Pattern.compile("My Library", Pattern.CASE_INSENSITIVE);
+ UiObject2 libraryButton = mDevice.findObject(By.text(myLibraryPattern).clickable(true));
libraryButton.click();
waitForNavigationDrawerClose();
// Select the Movies tab if necessary
- UiObject2 moviesTab = mDevice.findObject(By.text("MY MOVIES"));
- Assert.assertNotNull("Unable to find movies tab", moviesTab);
+ UiObject2 moviesTab = getMoviesTab();
+ if (moviesTab == null) {
+ throw new UnknownUiException("Unable to find the movies tab.");
+ }
if (!moviesTab.isSelected()) {
moviesTab.click();
mDevice.waitForIdle();
@@ -143,16 +149,38 @@
*/
@Override
public void playMovie(String name) {
- UiObject2 title = mDevice.findObject(By.textContains(name));
- Assert.assertNotNull(String.format("Failed to find movie by name %s", name), title);
+ UiObject2 title = null;
+ for (int retry = 0; retry < SEARCH_MOVIES_SCROLL_RETRY; retry++) {
+ title = mDevice.findObject(By.textContains(name));
+ if (title == null) {
+ UiObject2 scroller = mDevice.findObject(By.res(UI_PACKAGE, UI_MOVIE_LIST_ID));
+ if (scroller != null) {
+ scroller.scroll(Direction.DOWN, 1.0f);
+ }
+ }
+ }
+ if (title == null) {
+ throw new IllegalArgumentException(
+ String.format("Failed to find movie by name %s", name));
+ }
title.click();
UiObject2 play = mDevice.wait(Until.findObject(By.res(UI_PACKAGE, "play")), 5000);
- Assert.assertNotNull("Failed to find play button", play);
+ if (play == null) {
+ throw new UnknownUiException("Failed to find the play button.");
+ }
play.click();
mDevice.waitForIdle();
}
+ private boolean isNavigationDrawerOpen () {
+ return mDevice.hasObject(By.res(UI_PACKAGE, UI_NAV_DRAWER_ID));
+ }
+
private void openNavigationDrawer() {
+ if (isNavigationDrawerOpen()) {
+ return;
+ }
+
UiObject2 backButton = mDevice.findObject(By.pkg(getPackage()).desc("Navigate up"));
if (backButton != null) {
backButton.click();
@@ -160,7 +188,9 @@
}
UiObject2 navButton = mDevice.findObject(By.desc("Show navigation drawer"));
- Assert.assertNotNull("Unable to find navigation drawer button", navButton);
+ if (navButton == null) {
+ throw new UnknownUiException("Unable to find the navigation drawer button.");
+ }
navButton.click();
waitForNavigationDrawerOpen();
}
@@ -172,4 +202,14 @@
private void waitForNavigationDrawerClose() {
mDevice.wait(Until.gone(By.text("Settings").clickable(true)), 2500);
}
+
+ private UiObject2 getMoviesTab() {
+ Pattern moviesText = Pattern.compile("MY MOVIES", Pattern.CASE_INSENSITIVE);
+ UiObject2 tab = mDevice.findObject(By.text(moviesText));
+ if (tab == null) {
+ moviesText = Pattern.compile("MOVIES", Pattern.CASE_INSENSITIVE);
+ tab = mDevice.findObject(By.text(moviesText));
+ }
+ return tab;
+ }
}
diff --git a/libraries/youtube-app-helper/src/android/platform/test/helpers/YouTubeHelperImpl.java b/libraries/youtube-app-helper/src/android/platform/test/helpers/YouTubeHelperImpl.java
index ff6ef7e..2750f47 100644
--- a/libraries/youtube-app-helper/src/android/platform/test/helpers/YouTubeHelperImpl.java
+++ b/libraries/youtube-app-helper/src/android/platform/test/helpers/YouTubeHelperImpl.java
@@ -21,6 +21,8 @@
import android.content.res.Configuration;
import android.graphics.Point;
import android.os.SystemClock;
+import android.platform.test.helpers.exceptions.UiTimeoutException;
+import android.platform.test.helpers.exceptions.UnknownUiException;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.BySelector;
import android.support.test.uiautomator.Direction;
@@ -29,7 +31,7 @@
import android.support.test.uiautomator.UiObject2;
import android.util.Log;
-import junit.framework.Assert;
+import java.util.regex.Pattern;
public class YouTubeHelperImpl extends AbstractYouTubeHelper {
private static final String TAG = AbstractYouTubeHelper.class.getSimpleName();
@@ -39,15 +41,17 @@
private static final String UI_FULLSCREEN_BUTTON_DESC = "Enter fullscreen";
private static final String UI_HELP_AND_FEEDBACK_TEXT = "Help & feedback";
private static final String UI_HOME_BUTTON_DESC = "Home";
- private static final String UI_VIDEO_PLAYER_ID = "watch_player";
+ private static final String UI_HOME_PAGE_VIDEO_ID = "event_item";
+ private static final String UI_VIDEO_INFO_VIEW_ID = "video_info_view";
private static final String UI_PACKAGE_NAME = "com.google.android.youtube";
private static final String UI_PLAY_VIDEO_DESC = "Play video";
private static final String UI_PROGRESS_ID = "load_progress";
+ private static final String UI_RESULT_FILTER_ID = "menu_filter_results";
private static final String UI_SEARCH_BUTTON_ID = "menu_search";
private static final String UI_SEARCH_EDIT_TEXT_ID = "search_edit_text";
private static final String UI_SELECT_DIALOG_LISTVIEW_ID = "select_dialog_listview";
private static final String UI_TRENDING_BUTTON_DESC = "Trending";
- private static final String UI_VIDEO_CARD_ID = "video_info_view";
+ private static final String UI_VIDEO_PLAYER_ID = "watch_player";
private static final String UI_VIDEO_PLAYER_OVERFLOW_BUTTON_ID = "player_overflow_button";
private static final String UI_VIDEO_PLAYER_PLAY_PAUSE_REPLAY_BUTTON_ID =
"player_control_play_pause_replay_button";
@@ -112,28 +116,64 @@
* {@inheritDoc}
*/
@Override
- public void playFirstVideo() {
+ public void playHomePageVideo() {
+ if (!isOnHomePage()) {
+ throw new IllegalStateException("YouTube is not on the home page.");
+ }
+
+ if (hasConnectionEstablishedMessage()) {
+ pressGoOnline();
+ }
+
for (int i = 0; i < 3; i++) {
- UiObject2 video = getFirstVideo();
+ UiObject2 video = getPlayableVideo();
if (video != null) {
video.click();
waitForVideoToLoad(UI_NAVIGATION_WAIT);
return;
+ } else {
+ scrollHomePage(Direction.DOWN);
}
}
if (isLoading()) {
- Assert.fail("Timed out waiting for video search result to load.");
- } else {
- Assert.fail("YouTube does not support playing videos from this page or an " +
- "unexpected automation failure occurred.");
+ throw new UiTimeoutException("Timed out waiting for video search results.");
}
+
+ throw new UnknownUiException("Unsuccessful attempt playing home page video.");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void playSearchResultPageVideo() {
+ if (!isOnSearchResultsPage()) {
+ throw new IllegalStateException("YouTube is not on the home page.");
+ }
+
+ for (int i = 0; i < 3; i++) {
+ UiObject2 video = getPlayableVideo();
+ if (video != null) {
+ video.click();
+ waitForVideoToLoad(UI_NAVIGATION_WAIT);
+ return;
+ } else {
+ scrollSearchResultsPage(Direction.DOWN);
+ }
+ }
+
+ throw new UnknownUiException("Unsuccessful attempt playing search result video.");
}
private UiObject2 getHomePageContainer() {
return mDevice.findObject(By.res(UI_PACKAGE_NAME, UI_HOME_CONTAINER_ID));
}
+ private UiObject2 getSearchResultsPageContainer() {
+ return getHomePageContainer();
+ }
+
private UiObject2 getHomeButton() {
return mDevice.findObject(By.pkg(UI_PACKAGE_NAME).desc(UI_HOME_BUTTON_DESC));
}
@@ -151,16 +191,35 @@
}
private void scrollHomePage(Direction dir) {
+ if (dir == Direction.RIGHT || dir == Direction.LEFT) {
+ throw new IllegalArgumentException("Can only scroll up and down.");
+ }
+
UiObject2 scrollContainer = getHomePageContainer();
if (scrollContainer != null) {
scrollContainer.scroll(dir, 1.0f);
mDevice.waitForIdle();
} else {
- Assert.fail("No valid scrolling mechanism found.");
+ throw new UnknownUiException("No scrolling mechanism found.");
+ }
+ }
+
+ private void scrollSearchResultsPage(Direction dir) {
+ if (dir == Direction.RIGHT || dir == Direction.LEFT) {
+ throw new IllegalArgumentException("Can only scroll up and down.");
+ }
+
+ UiObject2 scrollContainer = getSearchResultsPageContainer();
+ if (scrollContainer != null) {
+ scrollContainer.scroll(dir, 1.0f);
+ mDevice.waitForIdle();
+ } else {
+ throw new UnknownUiException("No scrolling mechanism found.");
}
}
private boolean isLoading() {
+ // TODO: Is loading what? Requires more documentation.
return mDevice.hasObject(By.res(UI_PACKAGE_NAME, UI_PROGRESS_ID));
}
@@ -179,8 +238,19 @@
return (accountButton != null && accountButton.isSelected());
}
- private UiObject2 getFirstVideo() {
- return mDevice.findObject(By.res(UI_PACKAGE_NAME, UI_VIDEO_CARD_ID));
+ private boolean isOnSearchResultsPage() {
+ // Simplest way to identify search result page is the result filter button.
+ UiObject2 resultFilterButton =
+ mDevice.findObject(By.res(UI_PACKAGE_NAME, UI_RESULT_FILTER_ID));
+ return (resultFilterButton != null);
+ }
+
+ private UiObject2 getPlayableVideo() {
+ UiObject2 video = mDevice.findObject(By.res(UI_PACKAGE_NAME, UI_HOME_PAGE_VIDEO_ID));
+ if (video == null) {
+ video = mDevice.findObject(By.res(UI_PACKAGE_NAME, UI_VIDEO_INFO_VIEW_ID));
+ }
+ return video;
}
/**
@@ -192,6 +262,7 @@
By.res(UI_PACKAGE_NAME, UI_VIDEO_PLAYER_ID)), timeout);
}
+
/**
* {@inheritDoc}
*/
@@ -202,13 +273,22 @@
mDevice.pressBack();
SystemClock.sleep(3000);
}
+ // Get and press the home button
UiObject2 homeButton = getHomeButton();
- Assert.assertNotNull("Could not find home button", homeButton);
-
- homeButton.click();
- Assert.assertTrue("Not on home page after pressing home button",
- mDevice.wait(Until.hasObject(By.pkg(UI_PACKAGE_NAME).desc(
- UI_HOME_BUTTON_DESC).selected(true)), UI_NAVIGATION_WAIT));
+ if (homeButton == null) {
+ throw new UnknownUiException("Could not find home button.");
+ } else if (!homeButton.isSelected()) {
+ homeButton.click();
+ // Validate the home button is selected
+ if (!mDevice.wait(Until.hasObject(
+ By.pkg(UI_PACKAGE_NAME).desc(UI_HOME_BUTTON_DESC).selected(true)),
+ UI_NAVIGATION_WAIT)) {
+ throw new UnknownUiException("Not on home page after pressing home button.");
+ } else {
+ // Make sure the transition is complete
+ mDevice.waitForIdle();
+ }
+ }
}
/**
@@ -216,20 +296,55 @@
*/
@Override
public void goToSearchPage() {
+ if (!isOnHomePage()) {
+ throw new IllegalStateException("YouTube is not on the home page.");
+ }
+
UiObject2 searchButton = getSearchButton();
if (searchButton == null) {
- UiObject2 homeButton = getHomeButton();
- Assert.assertNotNull("Could not find home button", homeButton);
-
- homeButton.click();
- searchButton = mDevice.wait(Until.findObject(
- By.res(UI_PACKAGE_NAME, UI_SEARCH_BUTTON_ID)), UI_NAVIGATION_WAIT);
+ throw new UnknownUiException("Could not find search button.");
+ } else {
+ searchButton.click();
+ if (!mDevice.wait(Until.hasObject(
+ By.res(UI_PACKAGE_NAME, UI_SEARCH_EDIT_TEXT_ID)), UI_NAVIGATION_WAIT)) {
+ throw new UnknownUiException("Not on search page after pressing search button.");
+ }
}
- Assert.assertNotNull("Could not find search button", searchButton);
- searchButton.click();
- Assert.assertTrue("Not on search page after pressing search button",
- mDevice.wait(Until.hasObject(By.res(UI_PACKAGE_NAME, UI_SEARCH_EDIT_TEXT_ID)),
- UI_NAVIGATION_WAIT));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void goToFullscreenMode() {
+ if (!isOnVideo()) {
+ throw new IllegalStateException("YouTube is not on a video page.");
+ }
+
+ if (getOrientation() == Configuration.ORIENTATION_LANDSCAPE) {
+ return;
+ }
+
+ UiObject2 fullscreenButton = null;
+ for (int retriesRemaining = 5; retriesRemaining > 0; --retriesRemaining) {
+ UiObject2 miniVideoPlayer = getVideoPlayer();
+ if (miniVideoPlayer == null) {
+ throw new UnknownUiException("Could not find mini video player.");
+ }
+
+ miniVideoPlayer.click();
+ SystemClock.sleep(1500);
+ fullscreenButton = getFullscreenButton();
+ if (fullscreenButton != null) {
+ fullscreenButton.click();
+ // TODO: Add a valid wait for fullscreen
+ break;
+ }
+ }
+
+ if (fullscreenButton == null) {
+ throw new UnknownUiException("Did not find a fullscreen button.");
+ }
}
private UiObject2 getVideoPlayer() {
@@ -260,7 +375,8 @@
*/
@Override
public boolean waitForSearchResults(long timeout) {
- return mDevice.wait(Until.hasObject(By.res(UI_PACKAGE_NAME, UI_VIDEO_CARD_ID)), timeout);
+ return mDevice.wait(Until.hasObject(
+ By.res(UI_PACKAGE_NAME, UI_VIDEO_INFO_VIEW_ID)), timeout);
}
/**
@@ -268,32 +384,46 @@
*/
@Override
public void setVideoQuality(VideoQuality quality) {
- Assert.assertTrue("Not on video player", isOnVideo());
+ if (!isOnVideo()) {
+ throw new IllegalStateException("YouTube is not on a video page.");
+ }
UiObject2 overflowButton = getVideoPlayerOverflowButton();
+ // Open the mini video player
if (overflowButton == null) {
UiObject2 miniVideoPlayer = getVideoPlayer();
- Assert.assertNotNull("Could not find video player", miniVideoPlayer);
+ if (miniVideoPlayer == null) {
+ throw new UnknownUiException("Could not find mini video player.");
+ }
miniVideoPlayer.click();
mDevice.wait(Until.findObject(By.res(
UI_PACKAGE_NAME, UI_VIDEO_PLAYER_OVERFLOW_BUTTON_ID)), UI_NAVIGATION_WAIT);
overflowButton = getVideoPlayerOverflowButton();
}
- Assert.assertNotNull("Could not find overflow button", overflowButton);
+
+ if (overflowButton == null) {
+ throw new UnknownUiException("Could not find overflow button.");
+ }
overflowButton.click();
UiObject2 qualityButton = mDevice.wait(Until.findObject(
By.res(UI_PACKAGE_NAME, UI_VIDEO_PLAYER_QUALITY_BUTTON_ID)), UI_NAVIGATION_WAIT);
- Assert.assertNotNull("Could not find video quality button", qualityButton);
+ if (qualityButton == null) {
+ throw new UnknownUiException("Could not find video quality button.");
+ }
qualityButton.click();
UiObject2 quality360pLabel = mDevice.wait(Until.findObject(By.text(
AbstractYouTubeHelper.VideoQuality.QUALITY_360p.getText())), UI_NAVIGATION_WAIT);
- Assert.assertNotNull("Could not find 360p quality label", quality360pLabel);
+ if (quality360pLabel == null) {
+ throw new UnknownUiException("Could not find 360p quality label.");
+ }
UiObject2 selectDialog = quality360pLabel.getParent();
- Assert.assertNotNull("Could not find video quality dialog", selectDialog);
+ if (selectDialog == null) {
+ throw new UnknownUiException("Could not find video quality dialog.");
+ }
UiObject2 qualityLabel = null;
for (int retriesRemaining = 5; retriesRemaining > 0; --retriesRemaining) {
@@ -304,63 +434,60 @@
selectDialog.scroll(Direction.DOWN, 1.0f);
mDevice.waitForIdle();
}
- Assert.assertNotNull(String.format("Could not find quality %s label", quality.getText()),
- qualityLabel);
+ if (qualityLabel == null) {
+ throw new UnknownUiException(
+ String.format("Could not find quality %s label", quality.getText()));
+ }
Log.v(TAG, String.format("Found quality %s label", quality.getText()));
qualityLabel.click();
- Assert.assertTrue("Could not find video player after selecting quality",
- mDevice.wait(Until.hasObject(By.res(UI_PACKAGE_NAME, UI_VIDEO_PLAYER_ID)),
- UI_NAVIGATION_WAIT));
+ if (!mDevice.wait(Until.hasObject(By.res(UI_PACKAGE_NAME, UI_VIDEO_PLAYER_ID)),
+ UI_NAVIGATION_WAIT)) {
+ throw new UnknownUiException("Did not find video player after selecting quality.");
+ }
}
private UiObject2 getFullscreenButton() {
return mDevice.findObject(By.desc(UI_FULLSCREEN_BUTTON_DESC));
}
- /**
- * {@inheritDoc}
- */
- @Override
- public void goToFullscreenMode() {
- Assert.assertTrue(isOnVideo());
-
- if (getOrientation() == Configuration.ORIENTATION_LANDSCAPE) {
- return;
- }
-
- UiObject2 fullscreenButton = null;
- for (int retriesRemaining = 5; retriesRemaining > 0; --retriesRemaining) {
- UiObject2 miniVideoPlayer = getVideoPlayer();
- Assert.assertNotNull("Could not find video player", miniVideoPlayer);
-
- miniVideoPlayer.click();
- SystemClock.sleep(1500);
- fullscreenButton = getFullscreenButton();
- if (fullscreenButton != null) {
- fullscreenButton.click();
- break;
- }
- }
- Assert.assertNotNull("Could not find fullscreen button", fullscreenButton);
- }
-
private UiObject2 getPlayPauseReplayButton() {
return mDevice.findObject(
By.res(UI_PACKAGE_NAME, UI_VIDEO_PLAYER_PLAY_PAUSE_REPLAY_BUTTON_ID));
}
- public void playVideo() {
+ public void resumeVideo() {
UiObject2 videoPlayer = getVideoPlayer();
- Assert.assertNotNull("Could not find video player", videoPlayer);
+ if (videoPlayer == null) {
+ throw new UnknownUiException("Could not find video player.");
+ }
videoPlayer.click();
UiObject2 playPauseReplayButton = mDevice.wait(Until.findObject(By.res(UI_PACKAGE_NAME,
UI_VIDEO_PLAYER_PLAY_PAUSE_REPLAY_BUTTON_ID)), UI_NAVIGATION_WAIT);
- Assert.assertNotNull("Could not find pause / play button", playPauseReplayButton);
+ if (playPauseReplayButton == null) {
+ throw new UnknownUiException("Could not find the pause/play button.");
+ }
if (UI_PLAY_VIDEO_DESC.equals(playPauseReplayButton.getContentDescription())) {
playPauseReplayButton.click();
}
}
+
+ private boolean hasConnectionEstablishedMessage() {
+ Pattern establishedMsg =
+ Pattern.compile("Connection established", Pattern.CASE_INSENSITIVE);
+ return mDevice.hasObject(By.res(UI_PACKAGE_NAME, "message").text(establishedMsg));
+ }
+
+ private void pressGoOnline() {
+ Pattern goOnlineMsg = Pattern.compile("Go online", Pattern.CASE_INSENSITIVE);
+ UiObject2 button = mDevice.findObject(By.res(UI_PACKAGE_NAME, "action").text(goOnlineMsg));
+ if (button != null) {
+ button.click();
+ mDevice.waitForIdle();
+ } else {
+ throw new UnknownUiException("Unable to find GO ONLINE button.");
+ }
+ }
}
diff --git a/tests/androidbvt/Android.mk b/tests/androidbvt/Android.mk
index 0461dec..970a3df 100644
--- a/tests/androidbvt/Android.mk
+++ b/tests/androidbvt/Android.mk
@@ -17,8 +17,8 @@
LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
-
+LOCAL_SDK_VERSION := system_current
+media_framework_app_base := frameworks/base/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_JAVA_LIBRARIES := android.test.runner
LOCAL_STATIC_JAVA_LIBRARIES := android-support-test ub-uiautomator launcher-helper-lib
@@ -26,4 +26,4 @@
LOCAL_PACKAGE_NAME := AndroidBvtTests
LOCAL_CERTIFICATE := platform
-include $(BUILD_PACKAGE)
\ No newline at end of file
+include $(BUILD_PACKAGE)
diff --git a/tests/androidbvt/AndroidManifest.xml b/tests/androidbvt/AndroidManifest.xml
index d5962a5..c38bc88 100644
--- a/tests/androidbvt/AndroidManifest.xml
+++ b/tests/androidbvt/AndroidManifest.xml
@@ -17,16 +17,39 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.androidbvt">
-
<uses-sdk android:minSdkVersion="19"
android:targetSdkVersion="24" />
- <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+ <uses-feature android:name="android.hardware.camera"
+ android:required="true" />
+
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT" />
+ <uses-permission android:name="android.permission.CALL_PHONE" />
+ <uses-permission android:name="android.permission.CAMERA" />
+ <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.GET_ACCOUNTS" />
+ <uses-permission android:name="android.permission.GET_DETAILED_TASKS" />
+ <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+ <uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.SET_WALLPAPER" />
+ <uses-permission android:name="android.permission.TETHER_PRIVILEGED" />
+ <uses-permission android:name="android.permission.WAKE_LOCK" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_SETTINGS" />
<application>
<uses-library android:name="android.test.runner" />
+ <activity android:label="MediaPlaybackTest"
+ android:name=".app.MediaPlaybackTestApp"
+ android:screenOrientation="landscape">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
</application>
<instrumentation
android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/tests/androidbvt/res/layout/surface_view.xml b/tests/androidbvt/res/layout/surface_view.xml
new file mode 100644
index 0000000..4999e5d
--- /dev/null
+++ b/tests/androidbvt/res/layout/surface_view.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <SurfaceView
+ android:id="@+id/surface_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_centerInParent="true"
+ />
+
+ <ImageView android:id="@+id/overlay_layer"
+ android:layout_width="0dip"
+ android:layout_height="392dip"/>
+
+ <VideoView
+ android:id="@+id/video_view"
+ android:layout_width="320px"
+ android:layout_height="240px"
+ />
+
+ </FrameLayout>
+
+</LinearLayout>
+
diff --git a/tests/androidbvt/res/raw/bbb.mkv b/tests/androidbvt/res/raw/bbb.mkv
new file mode 100644
index 0000000..e286e01
--- /dev/null
+++ b/tests/androidbvt/res/raw/bbb.mkv
Binary files differ
diff --git a/tests/androidbvt/src/com/android/androidbvt/ConnectivityWifiTests.java b/tests/androidbvt/src/com/android/androidbvt/ConnectivityWifiTests.java
index 834a705..c9bbd92 100644
--- a/tests/androidbvt/src/com/android/androidbvt/ConnectivityWifiTests.java
+++ b/tests/androidbvt/src/com/android/androidbvt/ConnectivityWifiTests.java
@@ -27,6 +27,7 @@
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.Until;
import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.Suppress;
import android.util.Log;
import junit.framework.TestCase;
@@ -37,6 +38,8 @@
public class ConnectivityWifiTests extends TestCase {
private final static String DEFAULT_PING_SITE = "www.google.com";
+ private final String NETWORK_ID = "AndroidAP";
+ private final String PASSWD = "androidwifi";
private UiDevice mDevice;
private WifiManager mWifiManager = null;
private Context mContext = null;
@@ -106,6 +109,68 @@
}
/**
+ * Verifies WifiAp is by default disabled Then enable adn disable it
+ */
+ @LargeTest
+ @Suppress
+ public void testWifiTetheringDisableEnable() throws InterruptedException {
+ WifiConfiguration config = new WifiConfiguration();
+ config.SSID = NETWORK_ID;
+ config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
+ config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
+ config.preSharedKey = PASSWD;
+ int counter;
+ try {
+ // disable wifiap
+ assertTrue("wifi hotspot not disabled by default",
+ mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_DISABLED);
+ // Enable wifiap
+ assertTrue("failed to disable wifi hotspot",
+ mWifiManager.setWifiApEnabled(config, true));
+ Log.d("MyTestTag", "Now checkign wifi ap");
+ counter = 10;
+ while (--counter > 0
+ && mWifiManager.getWifiApState() != WifiManager.WIFI_AP_STATE_ENABLED) {
+ Thread.sleep(mABvtHelper.SHORT_TIMEOUT);
+ }
+ assertTrue("wifi hotspot not enabled",
+ mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED);
+ // Navigate to Wireless Settings page and verify Wifi AP setting is on
+ Intent intent_as = new Intent(
+ android.provider.Settings.ACTION_WIRELESS_SETTINGS);
+ mContext.startActivity(intent_as);
+ Thread.sleep(mABvtHelper.LONG_TIMEOUT);
+ mDevice.wait(Until.findObject(By.text("Tethering & portable hotspot")),
+ mABvtHelper.LONG_TIMEOUT).click();
+ Thread.sleep(mABvtHelper.SHORT_TIMEOUT);
+ assertTrue("Settings UI for Wifi AP is not ON",
+ mDevice.wait(Until.hasObject(By.text("Portable hotspot AndroidAP active")),
+ mABvtHelper.LONG_TIMEOUT));
+
+ mDevice.wait(Until.findObject(By.text("Portable Wi‑Fi hotspot")),
+ mABvtHelper.LONG_TIMEOUT).click();
+ assertTrue("Wifi ap disable call fails", mWifiManager.setWifiApEnabled(config,
+ false));
+ counter = 5;
+ while (--counter > 0
+ && mWifiManager.getWifiApState() != WifiManager.WIFI_AP_STATE_DISABLED) {
+ Thread.sleep(mABvtHelper.LONG_TIMEOUT);
+ }
+ assertTrue("wifi hotspot not enabled",
+ mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_DISABLED);
+ Thread.sleep(mABvtHelper.LONG_TIMEOUT * 2);
+ } finally {
+ assertTrue("Wifi enable call fails", mWifiManager
+ .enableNetwork(mWifiManager.getConnectionInfo().getNetworkId(), false));
+ counter = 10;
+ while (--counter > 0 && !mWifiManager.isWifiEnabled()) {
+ Thread.sleep(mABvtHelper.LONG_TIMEOUT);
+ }
+ assertTrue("Wifi isn't enabled", mWifiManager.isWifiEnabled());
+ }
+ }
+
+ /**
* Checks if wifi connection is active by sending an HTTP request, check for HTTP_OK
*/
private boolean isWifiConnected() throws InterruptedException {
diff --git a/tests/androidbvt/src/com/android/androidbvt/MediaCaptureTests.java b/tests/androidbvt/src/com/android/androidbvt/MediaCaptureTests.java
new file mode 100644
index 0000000..518a49d
--- /dev/null
+++ b/tests/androidbvt/src/com/android/androidbvt/MediaCaptureTests.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.androidbvt;
+
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Environment;
+import android.provider.MediaStore;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import junit.framework.TestCase;
+import java.io.File;
+import java.util.regex.Pattern;
+
+/**
+ * Basic tests for the Camera app.
+ */
+public class MediaCaptureTests extends TestCase {
+ private static final int CAPTURE_TIMEOUT = 6000;
+ private static final String DESC_BTN_CAPTURE_PHOTO = "Capture photo";
+ private static final String DESC_BTN_CAPTURE_VIDEO = "Capture video";
+ private static final String DESC_BTN_DONE = "Done";
+ private static final String DESC_BTN_PHOTO_MODE = "Open photo mode";
+ private static final String DESC_BTN_VIDEO_MODE = "Open video mode";
+ private static final int FILE_CHECK_ATTEMPTS = 5;
+ private static final int VIDEO_LENGTH = 2000;
+
+ private UiDevice mDevice;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ mDevice.freezeRotation();
+ // if there are any dialogues that pop up, dismiss them
+ UiObject2 maybeOkButton = mDevice.wait(Until.findObject(By.res("android:id/ok_button")),
+ CAPTURE_TIMEOUT);
+ if (maybeOkButton != null) {
+ maybeOkButton.click();
+ }
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ mDevice.unfreezeRotation();
+ super.tearDown();
+ }
+
+ /**
+ * Test that the device can capture a photo.
+ */
+ @LargeTest
+ public void testPhotoCapture() {
+ runCaptureTest(new Intent(MediaStore.ACTION_IMAGE_CAPTURE), "smoke.jpg", false);
+ }
+
+ /**
+ * Test that the device can capture a video.
+ */
+ @LargeTest
+ public void testVideoCapture() {
+ runCaptureTest(new Intent(MediaStore.ACTION_VIDEO_CAPTURE), "smoke.avi", true);
+ }
+
+ private void runCaptureTest(Intent intent, String tmpName, boolean isVideo) {
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ if (intent.resolveActivity(
+ InstrumentationRegistry.getInstrumentation().getContext().getPackageManager()) != null) {
+ File outputFile = null;
+ try {
+ outputFile = new File(Environment
+ .getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), tmpName);
+ intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(outputFile));
+ InstrumentationRegistry.getInstrumentation().getContext().startActivity(intent);
+ switchCaptureMode(isVideo);
+ pressCaptureButton(isVideo);
+ if (isVideo) {
+ Thread.sleep(VIDEO_LENGTH);
+ pressCaptureButton(isVideo);
+ }
+ Thread.sleep(1000);
+ pushButton(DESC_BTN_DONE);
+ long fileLength = outputFile.length();
+ for (int i=0; i<FILE_CHECK_ATTEMPTS; i++) {
+ if ((fileLength = outputFile.length()) > 0) {
+ break;
+ }
+ Thread.sleep(1000);
+ }
+ assertTrue(fileLength > 0);
+ } catch (InterruptedException e) {
+ fail(e.getLocalizedMessage());
+ } finally {
+ if (outputFile != null) {
+ outputFile.delete();
+ }
+ }
+ }
+ }
+
+ private void switchCaptureMode(boolean isVideo) {
+ if (isVideo) {
+ pushButton(DESC_BTN_VIDEO_MODE);
+ } else {
+ pushButton(DESC_BTN_PHOTO_MODE);
+ }
+ }
+
+ private void pressCaptureButton(boolean isVideo) {
+ if (isVideo) {
+ pushButton(DESC_BTN_CAPTURE_VIDEO);
+ } else {
+ pushButton(DESC_BTN_CAPTURE_PHOTO);
+ }
+ }
+
+ private void pushButton(String desc) {
+ Pattern pattern = Pattern.compile(desc, Pattern.CASE_INSENSITIVE);
+ UiObject2 doneBtn = mDevice.wait(Until.findObject(By.desc(pattern)), CAPTURE_TIMEOUT);
+ if (null != doneBtn) {
+ doneBtn.clickAndWait(Until.newWindow(), 500);
+ }
+ }
+}
diff --git a/tests/androidbvt/src/com/android/androidbvt/MediaPlaybackTests.java b/tests/androidbvt/src/com/android/androidbvt/MediaPlaybackTests.java
new file mode 100644
index 0000000..474e820
--- /dev/null
+++ b/tests/androidbvt/src/com/android/androidbvt/MediaPlaybackTests.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.androidbvt;
+
+import android.media.MediaPlayer;
+import android.os.Looper;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+
+import com.android.androidbvt.app.MediaPlaybackTestApp;
+
+/**
+ * Basic tests for video playback
+ */
+public class MediaPlaybackTests extends ActivityInstrumentationTestCase2<MediaPlaybackTestApp> {
+
+ private static final String TAG = "MediaPlaybackTest";
+ private static final int LOOP_START_BUFFER_MS = 10000;
+ private static final int PLAY_BUFFER_MS = 2000;
+ private final Object mCompletionLock = new Object();
+ private final Object mLooperLock = new Object();
+ private boolean mPlaybackSucceeded = false;
+ private boolean mPlaybackError = false;
+ private Looper mLooper;
+ private MediaPlayer mPlayer;
+
+ public MediaPlaybackTests() {
+ super(MediaPlaybackTestApp.class);
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ // start activity
+ getActivity();
+ }
+
+ @LargeTest
+ public void testVideoPlayback() {
+ // start the MediaPlayer on a Looper thread, so it does not deadlock itself
+ new Thread() {
+ @Override
+ public void run() {
+ Looper.prepare();
+ mLooper = Looper.myLooper();
+ mPlayer = MediaPlayer.create(getInstrumentation().getContext(), R.raw.bbb);
+ mPlayer.setDisplay(getActivity().getSurfaceHolder());
+ synchronized (mLooperLock) {
+ mLooperLock.notify();
+ }
+ Looper.loop();
+ }
+ }.start();
+ // make sure the looper is really started before we proceed
+ synchronized (mLooperLock) {
+ try {
+ mLooperLock.wait(LOOP_START_BUFFER_MS);
+ } catch (InterruptedException e) {
+ fail("Loop thread start was interrupted");
+ }
+ }
+ mPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
+ @Override
+ public boolean onError(MediaPlayer mp, int what, int extra) {
+ mPlaybackError = true;
+ mp.reset();
+ return true;
+ }
+ });
+ mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+ @Override
+ public void onCompletion(MediaPlayer mp) {
+ synchronized (mCompletionLock) {
+ Log.w(TAG, "Hit onCompletion!");
+ mPlaybackSucceeded = true;
+ mCompletionLock.notifyAll();
+ }
+ }
+ });
+ mPlayer.start();
+ int duration = mPlayer.getDuration();
+ int currentPosition = mPlayer.getCurrentPosition();
+ synchronized (mCompletionLock) {
+ try {
+ mCompletionLock.wait(duration - currentPosition + PLAY_BUFFER_MS);
+ } catch (InterruptedException e) {
+ fail("Wait for playback was interrupted");
+ }
+ }
+ mLooper.quit();
+ mPlayer.release();
+ assertFalse(mPlaybackError);
+ assertTrue(mPlaybackSucceeded);
+ }
+}
diff --git a/tests/androidbvt/src/com/android/androidbvt/SysUIGSATests.java b/tests/androidbvt/src/com/android/androidbvt/SysUIGSATests.java
new file mode 100644
index 0000000..dd7a9cf
--- /dev/null
+++ b/tests/androidbvt/src/com/android/androidbvt/SysUIGSATests.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.androidbvt;
+
+import android.app.UiAutomation;
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.Direction;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.KeyEvent;
+
+import junit.framework.TestCase;
+
+import java.util.List;
+
+/**
+ * Contains tests for features that are loosely coupled with Android system for sanity
+ */
+public class SysUIGSATests extends TestCase {
+ private final String QSB_PKG = "com.google.android.googlequicksearchbox";
+ private UiAutomation mUiAutomation = null;
+ private UiDevice mDevice;
+ private Context mContext = null;
+ private AndroidBvtHelper mABvtHelper = null;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ mDevice.setOrientationNatural();
+ mContext = InstrumentationRegistry.getTargetContext();
+ mUiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ mABvtHelper = AndroidBvtHelper.getInstance(mDevice, mContext, mUiAutomation);
+ mDevice.pressMenu();
+ mDevice.pressHome();
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ mDevice.pressHome();
+ mDevice.unfreezeRotation();
+ super.tearDown();
+ }
+
+ /**
+ * Ensures search via QSB searches both web and device apps Suuggested texts starts with
+ * searched text Remembers searched item, suggests as top suggestion next time
+ */
+ @LargeTest
+ public void testGoogleQuickSearchBar() throws InterruptedException {
+ final String TextToSearch = "co";
+ UiObject2 searchBox = null;
+ int counter = 5;
+ while (--counter > 0
+ && ((searchBox = mDevice.wait(Until.findObject(By.res(QSB_PKG, "search_box")),
+ mABvtHelper.SHORT_TIMEOUT)) == null)) {
+ Thread.sleep(mABvtHelper.SHORT_TIMEOUT);
+ mDevice.pressHome();
+ mDevice.pressSearch();
+ }
+ mDevice.wait(Until.findObject(By.res(QSB_PKG, "search_box")),
+ mABvtHelper.LONG_TIMEOUT).setText(TextToSearch);
+ Thread.sleep(mABvtHelper.LONG_TIMEOUT);
+ // make the IME down
+ mDevice.pressKeyCode(KeyEvent.KEYCODE_BACK);
+ // searching for 'co' will result from web, as well as 'Contacts' app. So there should be
+ // more than 1 container
+ UiObject2 searchSuggestionsContainer = mDevice.wait(Until.findObject(By.res(
+ QSB_PKG, "search_suggestions_container")), mABvtHelper.LONG_TIMEOUT);
+ assertTrue("QS suggestion should have more than 1 container",
+ searchSuggestionsContainer.getChildCount() > 1);
+ UiObject2 searchSuggestions = mDevice.wait(Until.findObject(By.res(
+ QSB_PKG, "search_suggestions_web")), mABvtHelper.LONG_TIMEOUT);
+ assertNotNull(
+ "Web Search suggestions shouldn't be null & should have more than 1 suggestions",
+ searchSuggestions != null && searchSuggestions.getChildCount() > 1);
+ List<UiObject2> suggestions = mDevice.wait(Until.findObjects(By.res(QSB_PKG, "text_1")),
+ mABvtHelper.LONG_TIMEOUT);
+ assertNotNull("Contacts app should be found", mDevice.wait(Until.findObject(
+ By.res(QSB_PKG, "text_1").text("Contacts")), mABvtHelper.LONG_TIMEOUT));
+ String topSuggestedText = suggestions.get(0).getText();
+ suggestions.get(0).clickAndWait(Until.newWindow(), mABvtHelper.LONG_TIMEOUT);
+ Thread.sleep(mABvtHelper.LONG_TIMEOUT);
+ // Search again and ensure last searched item showed as top suggestion
+ mDevice.pressHome();
+ Thread.sleep(mABvtHelper.SHORT_TIMEOUT);
+ mDevice.pressSearch();
+ String currentTopSuggestion = mDevice.wait(Until.findObjects(By.res(QSB_PKG, "text_1")),
+ mABvtHelper.LONG_TIMEOUT).get(0).getText();
+ assertTrue("Previous searched item isn't top suggested word",
+ topSuggestedText.toLowerCase().equals(topSuggestedText.toLowerCase()));
+ }
+
+ /**
+ * Ensures if any account is opted in GoogleNow, Google-assist offers card on long home press
+ */
+ @LargeTest
+ public void testGoogleAssist() throws InterruptedException {
+ mDevice.wait(Until.findObject(By.res(QSB_PKG, "search_plate")),
+ mABvtHelper.SHORT_TIMEOUT).click();
+ Thread.sleep(mABvtHelper.SHORT_TIMEOUT);
+ UiObject2 getStarted = mDevice.wait(Until.findObject(By.text("GET STARTED")),
+ mABvtHelper.SHORT_TIMEOUT);
+ if (getStarted != null) {
+ getStarted.clickAndWait(Until.newWindow(), mABvtHelper.SHORT_TIMEOUT);
+ mDevice.wait(Until.findObject(By.res(QSB_PKG, "text_container")),
+ mABvtHelper.SHORT_TIMEOUT).swipe(Direction.UP, 1.0f);
+ mDevice.wait(Until.findObject(By.text("YES, I’M IN")),
+ mABvtHelper.SHORT_TIMEOUT)
+ .clickAndWait(Until.newWindow(), mABvtHelper.SHORT_TIMEOUT);
+ }
+ // Search for Paris and click on first suggested text
+ mDevice.wait(Until.findObject(By.res(QSB_PKG, "text_container")),
+ mABvtHelper.LONG_TIMEOUT).setText("Paris");
+ Thread.sleep(mABvtHelper.LONG_TIMEOUT);
+ List<UiObject2> suggestedTexts = null;
+ int counter = 5;
+ while (--counter > 0
+ && ((suggestedTexts = mDevice.wait(Until.findObjects(By.res(QSB_PKG, "text_1")),
+ mABvtHelper.LONG_TIMEOUT)) == null)) {
+ Thread.sleep(mABvtHelper.SHORT_TIMEOUT);
+ }
+ assertNotNull("Suggested text shouldn't be null", suggestedTexts);
+ UiObject2 itemToClick = suggestedTexts.get(0);
+ for (UiObject2 item : suggestedTexts) {
+ if (item.getText().toLowerCase().equals("paris")) {
+ itemToClick = item;
+ }
+ }
+ itemToClick.clickAndWait(Until.newWindow(), mABvtHelper.SHORT_TIMEOUT);
+ Thread.sleep(mABvtHelper.LONG_TIMEOUT);
+ // Now long press home to load assist layer
+ mDevice.pressKeyCode(KeyEvent.KEYCODE_ASSIST);
+ UiObject2 optInYes = mDevice.wait(
+ Until.findObject(By.res(QSB_PKG, "screen_assist_opt_in_yes")),
+ mABvtHelper.SHORT_TIMEOUT);
+ if (optInYes != null) {
+ optInYes.clickAndWait(Until.newWindow(), mABvtHelper.SHORT_TIMEOUT);
+ }
+ // Ensure some cards are loaded
+ // Note card's content isn't verified
+ counter = 5;
+ UiObject2 cardContainer = null;
+ while (--counter > 0 && ((cardContainer = mDevice.wait(
+ Until.findObject(By.res(QSB_PKG, "card_container")),
+ mABvtHelper.SHORT_TIMEOUT)) != null)) {
+ Thread.sleep(mABvtHelper.SHORT_TIMEOUT);
+ }
+ assertNotNull("Some cards should be loaded", cardContainer);
+ }
+}
diff --git a/tests/androidbvt/src/com/android/androidbvt/LauncherTests.java b/tests/androidbvt/src/com/android/androidbvt/SysUILauncherTests.java
similarity index 99%
rename from tests/androidbvt/src/com/android/androidbvt/LauncherTests.java
rename to tests/androidbvt/src/com/android/androidbvt/SysUILauncherTests.java
index b93ec7f..e209817 100644
--- a/tests/androidbvt/src/com/android/androidbvt/LauncherTests.java
+++ b/tests/androidbvt/src/com/android/androidbvt/SysUILauncherTests.java
@@ -37,7 +37,7 @@
import java.io.IOException;
import java.util.List;
-public class LauncherTests extends TestCase {
+public class SysUILauncherTests extends TestCase {
private static final int LONG_TIMEOUT = 5000;
private static final String APP_NAME = "Clock";
private static final String PKG_NAME = "com.google.android.deskclock";
diff --git a/tests/androidbvt/src/com/android/androidbvt/SysUILockScreenTests.java b/tests/androidbvt/src/com/android/androidbvt/SysUILockScreenTests.java
index 801f9cd..28192d6 100644
--- a/tests/androidbvt/src/com/android/androidbvt/SysUILockScreenTests.java
+++ b/tests/androidbvt/src/com/android/androidbvt/SysUILockScreenTests.java
@@ -22,22 +22,25 @@
import android.os.RemoteException;
import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.Direction;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
-import android.support.test.uiautomator.By;
import android.support.test.uiautomator.Until;
import android.test.suitebuilder.annotation.LargeTest;
-import android.widget.EditText;
import junit.framework.Assert;
import junit.framework.TestCase;
public class SysUILockScreenTests extends TestCase {
+ private static final String LAUNCHER_PACKAGE = "com.google.android.googlequicksearchbox";
+ private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
+ private static final String EDIT_TEXT_CLASS_NAME = "android.widget.EditText";
private static final int SHORT_TIMEOUT = 200;
private static final int LONG_TIMEOUT = 2000;
private static final int PIN = 1234;
private static final String PASSWORD = "aaaa";
- private static final String EDIT_TEXT_CLASS_NAME = "android.widget.EditText";
+ private AndroidBvtHelper mABvtHelper = null;
private UiDevice mDevice = null;
private Context mContext;
@@ -47,6 +50,8 @@
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
mDevice.freezeRotation();
mContext = InstrumentationRegistry.getTargetContext();
+ mABvtHelper = AndroidBvtHelper.getInstance(mDevice, mContext,
+ InstrumentationRegistry.getInstrumentation().getUiAutomation());
mDevice.wakeUp();
mDevice.pressHome();
}
@@ -69,7 +74,7 @@
sleepAndWakeUpDevice();
unlockScreen(Integer.toString(PIN));
removeScreenLock(Integer.toString(PIN));
- Thread.sleep(LONG_TIMEOUT);
+ Thread.sleep(mABvtHelper.LONG_TIMEOUT);
Assert.assertFalse("Lock Screen is still enabled", isLockScreenEnabled());
}
@@ -83,7 +88,7 @@
sleepAndWakeUpDevice();
unlockScreen(PASSWORD);
removeScreenLock(PASSWORD);
- Thread.sleep(LONG_TIMEOUT);
+ Thread.sleep(mABvtHelper.LONG_TIMEOUT);
Assert.assertFalse("Lock Screen is still enabled", isLockScreenEnabled());
}
@@ -99,28 +104,46 @@
checkCheckEmergencyCall();
unlockScreen(PASSWORD);
removeScreenLock(PASSWORD);
- Thread.sleep(LONG_TIMEOUT);
+ Thread.sleep(mABvtHelper.LONG_TIMEOUT);
Assert.assertFalse("Lock Screen is still enabled", isLockScreenEnabled());
}
/**
+ * Just lock the screen and slide up to unlock
+ */
+ @LargeTest
+ public void testSlideUnlock() throws Exception {
+ sleepAndWakeUpDevice();
+ mDevice.wait(Until.findObject(
+ By.res(SYSTEMUI_PACKAGE, "notification_stack_scroller")), 2000)
+ .swipe(Direction.UP, 1.0f);
+ int counter = 6;
+ UiObject2 workspace = mDevice.findObject(By.res(LAUNCHER_PACKAGE, "workspace"));
+ while (counter-- > 0 && workspace == null) {
+ workspace = mDevice.findObject(By.res(LAUNCHER_PACKAGE, "workspace"));
+ Thread.sleep(500);
+ }
+ assertNotNull("Workspace wasn't found", workspace);
+ }
+
+ /**
* Sets the screen lock pin or password
* @param pwd text of Password or Pin for lockscreen
* @param mode indicate if its password or PIN
*/
private void setScreenLock(String pwd, String mode) throws Exception {
navigateToScreenLock();
- mDevice.wait(Until.findObject(By.text(mode)), LONG_TIMEOUT).click();
+ mDevice.wait(Until.findObject(By.text(mode)), mABvtHelper.LONG_TIMEOUT).click();
// set up Secure start-up page
- mDevice.wait(Until.findObject(By.text("No thanks")), LONG_TIMEOUT).click();
+ mDevice.wait(Until.findObject(By.text("No thanks")), mABvtHelper.LONG_TIMEOUT).click();
UiObject2 pinField = mDevice.wait(Until.findObject(By.clazz(EDIT_TEXT_CLASS_NAME)),
- LONG_TIMEOUT);
+ mABvtHelper.LONG_TIMEOUT);
pinField.setText(pwd);
// enter and verify password
mDevice.pressEnter();
pinField.setText(pwd);
mDevice.pressEnter();
- mDevice.wait(Until.findObject(By.text("DONE")), LONG_TIMEOUT).click();
+ mDevice.wait(Until.findObject(By.text("DONE")), mABvtHelper.LONG_TIMEOUT).click();
}
/**
@@ -128,57 +151,58 @@
*/
private void checkCheckEmergencyCall() throws Exception {
mDevice.pressMenu();
- mDevice.wait(Until.findObject(By.text("EMERGENCY")), LONG_TIMEOUT).click();
- Thread.sleep(LONG_TIMEOUT);
- UiObject2 dialButton = mDevice.wait(Until.findObject(By.desc("dial")), LONG_TIMEOUT);
+ mDevice.wait(Until.findObject(By.text("EMERGENCY")), mABvtHelper.LONG_TIMEOUT).click();
+ Thread.sleep(mABvtHelper.LONG_TIMEOUT);
+ UiObject2 dialButton = mDevice.wait(Until.findObject(By.desc("dial")),
+ mABvtHelper.LONG_TIMEOUT);
Assert.assertNotNull("Can't reach emergency call page", dialButton);
mDevice.pressBack();
- Thread.sleep(LONG_TIMEOUT);
+ Thread.sleep(mABvtHelper.LONG_TIMEOUT);
}
private void removeScreenLock(String pwd) throws Exception {
navigateToScreenLock();
UiObject2 pinField = mDevice.wait(Until.findObject(By.clazz(EDIT_TEXT_CLASS_NAME)),
- LONG_TIMEOUT);
+ mABvtHelper.LONG_TIMEOUT);
pinField.setText(pwd);
mDevice.pressEnter();
- mDevice.wait(Until.findObject(By.text("Swipe")), LONG_TIMEOUT).click();
- mDevice.wait(Until.findObject(By.text("YES, REMOVE")), LONG_TIMEOUT).click();
+ mDevice.wait(Until.findObject(By.text("Swipe")), mABvtHelper.LONG_TIMEOUT).click();
+ mDevice.wait(Until.findObject(By.text("YES, REMOVE")), mABvtHelper.LONG_TIMEOUT).click();
}
private void unlockScreen(String pwd) throws Exception {
swipeUp();
- Thread.sleep(SHORT_TIMEOUT);
+ Thread.sleep(mABvtHelper.SHORT_TIMEOUT);
// enter password to unlock screen
String command = String.format(" %s %s %s", "input", "text", pwd);
mDevice.executeShellCommand(command);
mDevice.waitForIdle();
- Thread.sleep(SHORT_TIMEOUT);
+ Thread.sleep(mABvtHelper.SHORT_TIMEOUT);
mDevice.pressEnter();
}
private void navigateToScreenLock() throws Exception {
launchSettingsPage(mContext, Settings.ACTION_SECURITY_SETTINGS);
- mDevice.wait(Until.findObject(By.text("Screen lock")), LONG_TIMEOUT).click();
+ mDevice.wait(Until.findObject(By.text("Screen lock")), mABvtHelper.LONG_TIMEOUT).click();
}
private void launchSettingsPage(Context ctx, String pageName) throws Exception {
Intent intent = new Intent(pageName);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ctx.startActivity(intent);
- Thread.sleep(LONG_TIMEOUT * 2);
+ Thread.sleep(mABvtHelper.LONG_TIMEOUT * 2);
}
private void sleepAndWakeUpDevice() throws RemoteException, InterruptedException {
mDevice.sleep();
- Thread.sleep(LONG_TIMEOUT);
+ Thread.sleep(mABvtHelper.LONG_TIMEOUT);
mDevice.wakeUp();
}
private void swipeUp() throws Exception {
mDevice.swipe(mDevice.getDisplayWidth() / 2, mDevice.getDisplayHeight(),
mDevice.getDisplayWidth() / 2, 0, 30);
- Thread.sleep(SHORT_TIMEOUT);
+ Thread.sleep(mABvtHelper.SHORT_TIMEOUT);
}
private boolean isLockScreenEnabled() {
@@ -186,3 +210,4 @@
return km.isKeyguardSecure();
}
}
+
diff --git a/tests/androidbvt/src/com/android/androidbvt/app/MediaPlaybackTestApp.java b/tests/androidbvt/src/com/android/androidbvt/app/MediaPlaybackTestApp.java
new file mode 100644
index 0000000..bfb239b
--- /dev/null
+++ b/tests/androidbvt/src/com/android/androidbvt/app/MediaPlaybackTestApp.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.androidbvt.app;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+import com.android.androidbvt.R;
+
+public class MediaPlaybackTestApp extends Activity {
+
+ private SurfaceView mSurfaceView;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ setContentView(R.layout.surface_view);
+ mSurfaceView = (SurfaceView)findViewById(R.id.surface_view);
+ }
+
+ public SurfaceHolder getSurfaceHolder() {
+ return mSurfaceView.getHolder();
+ }
+}
diff --git a/tests/perf/PerformanceLaunch/res/values-v11/styles.xml b/tests/perf/PerformanceLaunch/res/values-v11/styles.xml
deleted file mode 100644
index 3c02242..0000000
--- a/tests/perf/PerformanceLaunch/res/values-v11/styles.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<resources>
-
- <!--
- Base application theme for API 11+. This theme completely replaces
- AppBaseTheme from res/values/styles.xml on API 11+ devices.
- -->
- <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
- <!-- API 11 theme customizations can go here. -->
- </style>
-
-</resources>
diff --git a/tests/perf/PerformanceLaunch/res/values-v14/styles.xml b/tests/perf/PerformanceLaunch/res/values-v14/styles.xml
deleted file mode 100644
index a91fd03..0000000
--- a/tests/perf/PerformanceLaunch/res/values-v14/styles.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<resources>
-
- <!--
- Base application theme for API 14+. This theme completely replaces
- AppBaseTheme from BOTH res/values/styles.xml and
- res/values-v11/styles.xml on API 14+ devices.
- -->
- <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
- <!-- API 14 theme customizations can go here. -->
- </style>
-
-</resources>
diff --git a/tests/perf/PerformanceLaunch/res/values-v21/styles.xml b/tests/perf/PerformanceLaunch/res/values-v21/styles.xml
new file mode 100644
index 0000000..ea65cee
--- /dev/null
+++ b/tests/perf/PerformanceLaunch/res/values-v21/styles.xml
@@ -0,0 +1,4 @@
+<resources>
+ <style name="AppBaseTheme" parent="android:Theme.Material.Light">
+ </style>
+</resources>