Add update_engine unittests to the native tests.
am: 381ef84902
Change-Id: I0017920562881c09bcb50600045d4706250fe85d
diff --git a/libraries/aupt-lib/src/android/support/test/aupt/AuptTestCase.java b/libraries/aupt-lib/src/android/support/test/aupt/AuptTestCase.java
index 5ec427c..7755fc7 100644
--- a/libraries/aupt-lib/src/android/support/test/aupt/AuptTestCase.java
+++ b/libraries/aupt-lib/src/android/support/test/aupt/AuptTestCase.java
@@ -71,6 +71,7 @@
private UiWatchers mWatchers;
private IProcessStatusTracker mProcessStatusTracker;
private DataCollector mDataCollector;
+ private List<String> mPaths;
// We want to periodically collect dumpheap output if the process grows to large to proactivelly
// help with catching memory leaks, but don't want to do it too often so it does not disturb the
@@ -805,6 +806,14 @@
mDataCollector = collector;
}
+ public void setDexedJarPaths(List<String> paths) {
+ mPaths = paths;
+ }
+
+ public List<String> getDexedJarPaths() {
+ return mPaths;
+ }
+
public String getPackageVersion(String packageName) throws NameNotFoundException {
if (null == packageName || packageName.isEmpty()) {
throw new RuntimeException("Package name can't be null or empty");
diff --git a/libraries/aupt-lib/src/android/support/test/aupt/AuptTestRunner.java b/libraries/aupt-lib/src/android/support/test/aupt/AuptTestRunner.java
index 643e681..a689a58 100644
--- a/libraries/aupt-lib/src/android/support/test/aupt/AuptTestRunner.java
+++ b/libraries/aupt-lib/src/android/support/test/aupt/AuptTestRunner.java
@@ -88,6 +88,7 @@
private boolean mTrackJank;
private GraphicsStatsMonitor mGraphicsStatsMonitor;
+ private List<String> mJars;
/**
* {@inheritDoc}
@@ -164,7 +165,8 @@
private void loadDexJars(String jars) {
// scan provided jar paths, translate relative to absolute paths, and check for existence
String[] jarsArray = jars.split(":");
- StringBuilder jarFiles = new StringBuilder();
+ StringBuilder classLoaderPath = new StringBuilder();
+ mJars = new ArrayList<String>();
for (int i = 0; i < jarsArray.length; i++) {
String jar = jarsArray[i];
if (!jar.startsWith("/")) {
@@ -176,9 +178,10 @@
+ jar);
}
if (i != 0) {
- jarFiles.append(File.pathSeparator);
+ classLoaderPath.append(File.pathSeparator);
}
- jarFiles.append(jarFile.getAbsolutePath());
+ classLoaderPath.append(jarFile.getAbsolutePath());
+ mJars.add(jarFile.getAbsolutePath());
}
// now load them
File optDir = new File(getContext().getCacheDir(), DEX_OPT_PATH);
@@ -186,7 +189,7 @@
throw new RuntimeException(
"Failed to create dex optimize directory: " + optDir.getAbsolutePath());
}
- mLoader = new BaseDexClassLoader(jarFiles.toString(), optDir, null,
+ mLoader = new BaseDexClassLoader(classLoaderPath.toString(), optDir, null,
super.getTargetContext().getClassLoader());
}
@@ -220,7 +223,7 @@
private void writeProgressMessage(String msg) {
writeMessage("progress.txt", msg);
}
-
+
private void writeGraphicsMessage(String msg) {
writeMessage("graphics.txt", msg);
}
@@ -440,6 +443,7 @@
((AuptTestCase)test).setProcessStatusTracker(mProcessTracker);
((AuptTestCase)test).setMemHealthRecords(mMemHealthRecords);
((AuptTestCase)test).setDataCollector(mDataCollector);
+ ((AuptTestCase)test).setDexedJarPaths(mJars);
}
}
diff --git a/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractAngryBirdsHelper.java b/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractAngryBirdsHelper.java
new file mode 100644
index 0000000..dc1f037
--- /dev/null
+++ b/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractAngryBirdsHelper.java
@@ -0,0 +1,48 @@
+/*
+ * 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 android.platform.test.helpers;
+
+import android.app.Instrumentation;
+
+public abstract class AbstractAngryBirdsHelper extends AbstractStandardAppHelper {
+
+ public AbstractAngryBirdsHelper(Instrumentation instr) {
+ super(instr);
+ }
+
+ /**
+ * Setup expectation: Angry Birds open and on main menu
+ *
+ * This method will set up game demo by going to level selection menu
+ */
+ public abstract void setUpDemo();
+
+ /**
+ * Setup expectation: Angry Birds open and on level selection menu
+ *
+ * This method plays a game demo for demoDurationInMinutes minutes
+ * @param demoDurationInMinutes: game demo duration in minutes
+ */
+ public abstract void playDemo(int demoDurationInMinutes);
+
+ /**
+ * Setup expectation: Angry Birds open and on level selection menu
+ *
+ * This method goes back to the main menu
+ */
+ public abstract void tearDownDemo();
+}
diff --git a/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractChromeHelper.java b/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractChromeHelper.java
index 050a1c9..7589d22 100644
--- a/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractChromeHelper.java
+++ b/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractChromeHelper.java
@@ -61,4 +61,12 @@
* is open on the original tab.
*/
public abstract void unmergeTabs();
+
+ /**
+ * Setup expectations: Chrome is open on a page.
+ *
+ * This method will reload the page by clicking the refresh button, and block until the page
+ * is reopened.
+ */
+ public abstract void reloadPage();
}
diff --git a/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractGoogleCameraHelper.java b/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractGoogleCameraHelper.java
index aa890c0..7b8e7a4 100644
--- a/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractGoogleCameraHelper.java
+++ b/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractGoogleCameraHelper.java
@@ -20,6 +20,26 @@
import android.support.test.uiautomator.Direction;
public abstract class AbstractGoogleCameraHelper extends AbstractStandardAppHelper {
+ public static final int HDR_MODE_AUTO = -1;
+ public static final int HDR_MODE_OFF = 0;
+ public static final int HDR_MODE_ON = 1;
+
+ public static final int VIDEO_SD_480 = -2;
+ public static final int VIDEO_HD_720 = -1;
+ public static final int VIDEO_HD_1080 = 0;
+ public static final int VIDEO_4K_MODE_ON = 1;
+
+ public static final int VIDEO_30FPS = 0;
+ public static final int VIDEO_60FPS = 1;
+
+ public static final int HFR_MODE_OFF = 0;
+ public static final int HFR_MODE_120_FPS = 1;
+ public static final int HFR_MODE_240_FPS = 2;
+
+ public static final int FLASH_AUTO = -1;
+ public static final int FLASH_OFF = 0;
+ public static final int FLASH_ON = 1;
+ public static final int NUM_FLASH_MODES = 3;
public AbstractGoogleCameraHelper(Instrumentation instr) {
super(instr);
@@ -158,6 +178,17 @@
public abstract void setFrameRate(int mode);
/**
+ * Setup expectation: GoogleCamera is open and idle in camera or video mode.
+ *
+ * This method will set flash to one of the following:
+ * - on (mode == FLASH_ON)
+ * - auto (mode == FLASH_AUTO)
+ * - off (mode == FLASH_OFF)
+ * @param mode the integer value of the mode denoted above.
+ */
+ public abstract void setFlashMode(int mode);
+
+ /**
* Setup expectation: in Camera mode with the capture button present.
*
* This method will block until the capture button is enabled for pressing.
diff --git a/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractGoogleFitHelper.java b/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractGoogleFitHelper.java
index 2ee1a58..df2e9a7 100644
--- a/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractGoogleFitHelper.java
+++ b/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractGoogleFitHelper.java
@@ -16,6 +16,8 @@
package android.platform.test.helpers;
+import java.io.IOException;
+
import android.app.Instrumentation;
import android.support.test.uiautomator.Direction;
@@ -65,15 +67,16 @@
* @param steps value of Steps
* @param distance value of Distance in mile
*/
- public abstract void addActivity(String activity, int duration,
- int calories, int steps, int distance);
+ public abstract void addActivity(String activity, int duration, int calories,
+ int steps, int distance);
/**
* Setup expectations: Google Fit is open and idle on the home page or timeline page.
*
* This method will select an activity type and start an activity session
* @param activity case-insensitive activity types, like: running, biking, walking
*/
- public abstract void startActivity(String activity);
+ public abstract void startActivity(String activity) throws IOException;
+
/**
* Setup expectations: An activity session is started.
*
@@ -94,4 +97,12 @@
* This method will terminate and save the current activity and end on the activity summary page
*/
public abstract void saveActivity();
+
+ /**
+ * Setup expectations: An activity session is started.
+ *
+ * This method will stop the current activity and end on the activity page.
+ */
+ public abstract void stopActivity() throws IOException;
+
}
diff --git a/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractSlackerHelper.java b/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractSlackerHelper.java
new file mode 100644
index 0000000..caceb0a
--- /dev/null
+++ b/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractSlackerHelper.java
@@ -0,0 +1,45 @@
+/*
+ * 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 android.platform.test.helpers;
+
+import android.app.Instrumentation;
+
+public abstract class AbstractSlackerHelper extends AbstractStandardAppHelper {
+
+ public AbstractSlackerHelper(Instrumentation instr) {
+ super(instr);
+ }
+
+ /**
+ * Setup expectation: Slacker is on page with playable radio channels
+ *
+ * This method starts playing one of the playable radio channels.
+ * If app is already on channel page, this function starts playing
+ * the radio on the current page. If it cannot start streaming a radio
+ * channel, it throws an exception.
+ */
+ public abstract void startAnyChannel();
+
+ /**
+ * Setup expectation: Slacker is on channel page
+ *
+ * This method pauses the audio streaming and returns to main page.
+ * If app is already on main page, this function does nothing. If it
+ * cannot stop streamming channel, it throws an exception.
+ */
+ public abstract void stopChannel();
+}
diff --git a/libraries/base-app-helpers/src/android/platform/test/helpers/HelperManager.java b/libraries/base-app-helpers/src/android/platform/test/helpers/HelperManager.java
index 3ac9246..533b0b2 100644
--- a/libraries/base-app-helpers/src/android/platform/test/helpers/HelperManager.java
+++ b/libraries/base-app-helpers/src/android/platform/test/helpers/HelperManager.java
@@ -30,6 +30,7 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
@@ -44,10 +45,9 @@
* <ol>
* <li> Static inclusion - if all the code is included in the final APK, the Context can be used to
* generate a HelperManager and to instantiate implementations.
- * <li> Dexed file inclusion - if this and the helper implementations are bundled into a dexed
- * file, such as a dexed JAR, that gets added after compilation, e.g. how the automated user
- * profile test suites are built, the path can be used to generate a HelperManager and to
- * instantiate implementations.
+ * <li> Dexed file inclusion - if this manager and the helper implementations are bundled into dex
+ * files and loaded from a single class loader, then the files can be used to generate a
+ * HelperManager and to instantiate implementations.
* </ol>
* <p>
* Including and using this strategy will prune the explicit dependency tree for the App Helper
@@ -76,33 +76,36 @@
String.format("Cannot pass in null instrumentation."));
}
// Instantiation
- sInstance = new HelperManager(context.getPackageCodePath(), instr);
+ List<String> paths = Arrays.asList(context.getPackageCodePath());
+ sInstance = new HelperManager(paths, instr);
}
return sInstance;
}
/**
- * Returns an instance of the HelperManager that searches the supplied location for classes to
+ * Returns an instance of the HelperManager that searches the supplied locations for classes to
* instantiate to helper implementations.
*
- * @param path the dexed file where the classes are included
+ * @param paths the dex files where the classes are included
* @param instr the active instrumentation
* @throws IllegalArgumentException if the path is not a valid file
* @return a new instance of the HelperManager class
*/
- public static HelperManager getInstance(String path, Instrumentation instr) {
+ public static HelperManager getInstance(List<String> paths, Instrumentation instr) {
if (sInstance == null) {
// Input checks
- if (!(new File(path)).exists()) {
- throw new IllegalArgumentException(
- String.format("No file found at path: %s.", path));
+ for (String path : paths) {
+ if (!(new File(path)).exists()) {
+ throw new IllegalArgumentException(
+ String.format("No file found at path: %s.", path));
+ }
}
if (instr == null) {
throw new NullPointerException(
String.format("Cannot pass in null instrumentation."));
}
// Instantiation
- sInstance = new HelperManager(path, instr);
+ sInstance = new HelperManager(paths, instr);
}
return sInstance;
}
@@ -110,12 +113,15 @@
private Instrumentation mInstrumentation;
private List<String> mClasses;
- private HelperManager(String path, Instrumentation instr) {
+ private HelperManager(List<String> paths, Instrumentation instr) {
mInstrumentation = instr;
// Collect all of the available classes
+ mClasses = new ArrayList<String>();
try {
- DexFile dex = new DexFile(path);
- mClasses = Collections.list(dex.entries());
+ for (String path : paths) {
+ DexFile dex = new DexFile(path);
+ mClasses.addAll(Collections.list(dex.entries()));
+ }
} catch (IOException e) {
throw new RuntimeException("Failed to retrieve the dex file.");
}
diff --git a/libraries/launcher-helper/src/android/support/test/launcherhelper/LauncherStrategyFactory.java b/libraries/launcher-helper/src/android/support/test/launcherhelper/LauncherStrategyFactory.java
index ce6bef4..cab96cd 100644
--- a/libraries/launcher-helper/src/android/support/test/launcherhelper/LauncherStrategyFactory.java
+++ b/libraries/launcher-helper/src/android/support/test/launcherhelper/LauncherStrategyFactory.java
@@ -43,7 +43,9 @@
registerLauncherStrategy(GoogleExperienceLauncherStrategy.class);
registerLauncherStrategy(Launcher3Strategy.class);
registerLauncherStrategy(NexusLauncherStrategy.class);
+ registerLauncherStrategy(PixelCLauncherStrategy.class);
registerLauncherStrategy(LeanbackLauncherStrategy.class);
+ registerLauncherStrategy(WearLauncherStrategy.class);
}
/**
diff --git a/libraries/launcher-helper/src/android/support/test/launcherhelper/PixelCLauncherStrategy.java b/libraries/launcher-helper/src/android/support/test/launcherhelper/PixelCLauncherStrategy.java
new file mode 100644
index 0000000..93b44ff
--- /dev/null
+++ b/libraries/launcher-helper/src/android/support/test/launcherhelper/PixelCLauncherStrategy.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2017 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 android.support.test.launcherhelper;
+
+/**
+ * Implementation of {@link ILauncherStrategy} to support Pixel C launcher
+ */
+public class PixelCLauncherStrategy extends NexusLauncherStrategy {
+
+ private static final String LAUNCHER_PKG = "com.google.android.apps.pixelclauncher";
+
+ @Override
+ public String getSupportedLauncherPackage() {
+ return LAUNCHER_PKG;
+ }
+}
diff --git a/libraries/launcher-helper/src/android/support/test/launcherhelper/WearLauncherStrategy.java b/libraries/launcher-helper/src/android/support/test/launcherhelper/WearLauncherStrategy.java
new file mode 100644
index 0000000..7f326ab
--- /dev/null
+++ b/libraries/launcher-helper/src/android/support/test/launcherhelper/WearLauncherStrategy.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2017 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 android.support.test.launcherhelper;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.Intent;
+import android.os.SystemClock;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.BySelector;
+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.widget.TextView;
+import android.util.Log;
+
+import junit.framework.Assert;
+
+public class WearLauncherStrategy implements ILauncherStrategy {
+
+ private static final String LAUNCHER_PKG = "com.google.android.wearable.app";
+ private static final String LOG_TAG = WearLauncherStrategy.class.getSimpleName();
+ protected UiDevice mDevice;
+ protected Context mContext;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getSupportedLauncherPackage() {
+ return LAUNCHER_PKG;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setUiDevice(UiDevice uiDevice) {
+ mDevice = uiDevice;
+ }
+
+ /**
+ * Shows the home screen of launcher
+ */
+ @Override
+ public void open() {
+ if (!mDevice.hasObject(getHotSeatSelector())) {
+ mDevice.pressBack();
+ if (!mDevice.wait(Until.hasObject(getHotSeatSelector()), 5000)) {
+ // HACK: dump hierarchy to logcat
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try {
+ mDevice.dumpWindowHierarchy(baos);
+ baos.flush();
+ baos.close();
+ String[] lines = baos.toString().split("\\r?\\n");
+ for (String line : lines) {
+ Log.d(LOG_TAG, line.trim());
+ }
+ } catch (IOException ioe) {
+ Log.e(LOG_TAG, "error dumping XML to logcat", ioe);
+ }
+ Assert.fail("Failed to open launcher");
+ }
+ mDevice.waitForIdle();
+ }
+ }
+
+ /**
+ * Opens the all apps drawer of launcher
+ * @param reset if the all apps drawer should be reset to the beginning
+ * @return {@link UiObject2} representation of the all apps drawer
+ */
+ @Override
+ public UiObject2 openAllApps(boolean reset) {
+ if (!mDevice.hasObject(getAllAppsSelector())) {
+ mDevice.pressBack();
+ }
+ UiObject2 allAppsContainer = mDevice.wait(Until.findObject(getAllAppsSelector()), 2000);
+ if (reset) {
+ CommonLauncherHelper.getInstance(mDevice).scrollBackToBeginning(
+ allAppsContainer, Direction.reverse(getAllAppsScrollDirection()));
+ }
+ return allAppsContainer;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public BySelector getHotSeatSelector() {
+ return By.res(getSupportedLauncherPackage(), "watchface_overlay");
+ }
+
+
+ /**
+ * Returns a {@link BySelector} describing the all apps drawer
+ * @return
+ */
+ @Override
+ public BySelector getAllAppsSelector() {
+ return By.res(getSupportedLauncherPackage(), "launcher_view");
+ }
+
+ /**
+ * Retrieves the all apps drawer forward scroll direction as implemented by the launcher
+ * @return
+ */
+ @Override
+ public Direction getAllAppsScrollDirection() {
+ return Direction.DOWN;
+ }
+
+ @Override
+ public BySelector getAllAppsButtonSelector() {
+ throw new UnsupportedOperationException(
+ "The 'All Apps' button is not available on Android Wear Launcher.");
+ }
+
+ @Override
+ public UiObject2 openAllWidgets(boolean reset) {
+ throw new UnsupportedOperationException(
+ "The 'All Widgets' button is not available on Android Wear Launcher.");
+ }
+
+ @Override
+ public BySelector getAllWidgetsSelector() {
+ throw new UnsupportedOperationException(
+ "The 'All Widgets' button is not available on Android Wear Launcher.");
+ }
+
+ @Override
+ public Direction getAllWidgetsScrollDirection() {
+ throw new UnsupportedOperationException(
+ "The 'All Widgets' button is not available on Android Wear Launcher.");
+ }
+
+ @Override
+ public BySelector getWorkspaceSelector() {
+ throw new UnsupportedOperationException(
+ "The 'Work space' is not available on Android Wear Launcher.");
+ }
+
+ @Override
+ public Direction getWorkspaceScrollDirection() {
+ throw new UnsupportedOperationException(
+ "The 'Work Space' is not available on Android Wear Launcher.");
+ }
+
+ /**
+ * Launch the named application
+ * @param appName the name of the application to launch as shown in launcher
+ * @param packageName the expected package name to verify that the application has been launched
+ * into foreground. If <code>null</code> is provided, no verification is
+ * performed.
+ * @return <code>true</code> if application is verified to be in foreground after launch, or the
+ * verification is skipped; <code>false</code> otherwise.
+ */
+ @Override
+ public long launch(String appName, String packageName) {
+ BySelector app = By.res(
+ getSupportedLauncherPackage(), "title").clazz(TextView.class).text(appName);
+ return CommonLauncherHelper.getInstance(mDevice).launchApp(this, app, packageName);
+ }
+}
diff --git a/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/CardsJankTest.java b/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/CardsJankTest.java
index 14507d3..5282f29 100644
--- a/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/CardsJankTest.java
+++ b/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/CardsJankTest.java
@@ -82,6 +82,20 @@
super.afterTest(metrics);
}
+ // Measure jank when dismissing on an expanded card
+ @JankTest(beforeLoop = "openSwipeExpandedCard", afterTest = "goBackHome",
+ expectedFrames = SysAppTestHelper.EXPECTED_FRAMES_DISMISS_EXPANDED_CARDS_TEST)
+ @GfxMonitor(processName = "com.google.android.wearable.app")
+ public void testSwipeExpandedCard() {
+ mHelper.swipeRight();
+ }
+
+ // Preparing the expanded card
+ public void openSwipeExpandedCard() throws Exception {
+ openSwipeCard();
+ mHelper.clickScreenCenter();
+ }
+
/*
* (non-Javadoc)
* @see android.test.InstrumentationTestCase#tearDown()
diff --git a/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/QuickSettingsJankTest.java b/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/QuickSettingsJankTest.java
index ed9c069..fa9e89f 100644
--- a/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/QuickSettingsJankTest.java
+++ b/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/QuickSettingsJankTest.java
@@ -40,7 +40,7 @@
private SysAppTestHelper mHelper;
private static final String WEARABLE_APP_PACKAGE = "com.google.android.wearable.app";
- private static final String QUICK_SETTINGS_LAUNCHED_INDICATOR = "settings_icon";
+ private static final String QUICK_SETTINGS_LAUNCHED_INDICATOR = "Quick settings";
/*
* (non-Javadoc)
@@ -55,9 +55,10 @@
}
private void isQuickSettingShadeLaunched() throws TimeoutException {
- SystemClock.sleep(SysAppTestHelper.SHORT_TIMEOUT + SysAppTestHelper.SHORT_TIMEOUT); //Wait until date & battery info transitions to page indicator
+ //Wait until date & battery info transitions to page indicator
+ SystemClock.sleep(SysAppTestHelper.SHORT_TIMEOUT + SysAppTestHelper.SHORT_TIMEOUT);
UiObject2 quickSettingsShade = mDevice.wait(
- Until.findObject(By.res(WEARABLE_APP_PACKAGE, QUICK_SETTINGS_LAUNCHED_INDICATOR)),
+ Until.findObject(By.desc(QUICK_SETTINGS_LAUNCHED_INDICATOR)),
SysAppTestHelper.SHORT_TIMEOUT);
Assert.assertNotNull("Quick settings shade not launched", quickSettingsShade);
diff --git a/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/SettingsFlingJankTest.java b/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/SettingsFlingJankTest.java
index 1da3683..97f574f 100644
--- a/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/SettingsFlingJankTest.java
+++ b/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/SettingsFlingJankTest.java
@@ -21,12 +21,12 @@
import android.support.test.jank.GfxMonitor;
import android.support.test.jank.JankTest;
import android.support.test.jank.JankTestBase;
+import android.support.test.jank.WindowAnimationFrameStatsMonitor;
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 java.util.concurrent.TimeoutException;
/**
@@ -34,15 +34,13 @@
*/
public class SettingsFlingJankTest extends JankTestBase {
- private UiDevice mDevice;
- private SysAppTestHelper mHelper;
-
// Settings app resources
private static final String CLOCK_SETTINGS_PACKAGE =
- "com.google.android.apps.wearable.settings";
-
+ "com.google.android.apps.wearable.settings";
private static final String CLOCK_SETTINGS_ACTIVITY =
- "com.google.android.clockwork.settings.MainSettingsActivity";
+ "com.google.android.clockwork.settings.MainSettingsActivity";
+ private UiDevice mDevice;
+ private SysAppTestHelper mHelper;
/*
* (non-Javadoc)
@@ -64,20 +62,25 @@
/**
* Test the jank by flinging in settings screen.
- * @throws TimeoutException
- *
*/
@JankTest(beforeTest = "openSettingsApp", afterTest = "goBackHome",
- expectedFrames = SysAppTestHelper.EXPECTED_FRAMES)
+ expectedFrames = SysAppTestHelper.EXPECTED_FRAMES)
@GfxMonitor(processName = CLOCK_SETTINGS_PACKAGE)
public void testSettingsApp() throws TimeoutException {
- UiObject2 listViewContents = mDevice.wait(Until.findObject(
- By.res("android", "list")),
- SysAppTestHelper.SHORT_TIMEOUT);
- for (int i = 0; i < 3; i++) {
- listViewContents.fling(Direction.DOWN, SysAppTestHelper.FLING_SPEED);
- listViewContents.fling(Direction.UP, SysAppTestHelper.FLING_SPEED);
- }
+ UiObject2 listViewContents = mDevice.wait(Until.findObject(
+ By.res("android", "list")),
+ SysAppTestHelper.SHORT_TIMEOUT);
+ for (int i = 0; i < 3; i++) {
+ listViewContents.fling(Direction.DOWN, SysAppTestHelper.FLING_SPEED);
+ listViewContents.fling(Direction.UP, SysAppTestHelper.FLING_SPEED);
+ }
+ }
+
+ @JankTest(beforeLoop = "openSettingsApp", afterTest = "goBackHome",
+ expectedFrames = SysAppTestHelper.EXPECTED_FRAMES_SWIPERIGHT_TO_DISMISS_TEST)
+ @WindowAnimationFrameStatsMonitor
+ public void testSwipeRightToDismissApp() {
+ mHelper.swipeRight();
}
// Ensuring that we head back to the first screen before launching the app again
diff --git a/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/SysAppTestHelper.java b/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/SysAppTestHelper.java
index 8e6ba1d..e78204e 100644
--- a/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/SysAppTestHelper.java
+++ b/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/SysAppTestHelper.java
@@ -37,7 +37,10 @@
public class SysAppTestHelper {
public static final int EXPECTED_FRAMES_CARDS_TEST = 20;
+ public static final int EXPECTED_FRAMES_DISMISS_EXPANDED_CARDS_TEST = 15;
public static final int EXPECTED_FRAMES_WATCHFACE_PICKER_TEST = 20;
+ public static final int EXPECTED_FRAMES_SWIPERIGHT_TO_DISMISS_TEST = 20;
+ public static final int EXPECTED_FRAMES_WATCHFACE_PICKER_TEST_ADD_FAVORITE = 5;
public static final int EXPECTED_FRAMES = 100;
public static final int LONG_TIMEOUT = 5000;
public static final int SHORT_TIMEOUT = 500;
@@ -47,10 +50,6 @@
private static final String RELOAD_NOTIFICATION_CARD_INTENT = "com.google.android.wearable."
+ "support.wearnotificationgenerator.SHOW_NOTIFICATION";
private static final String HOME_INDICATOR = "charging_icon";
- private static final String LAUNCHER_VIEW_NAME = "launcher_view";
- private static final String CARD_VIEW_NAME = "activity_view";
- private static final String QUICKSETTING_VIEW_NAME = "settings_icon";
- private static final String WATCHFACE_PREVIEW_NAME = "preview_image";
// Demo card selectors
private static final UiSelector CARD_SELECTOR = new UiSelector()
@@ -147,6 +146,11 @@
SystemClock.sleep(SHORT_TIMEOUT);
}
+ public void clickScreenCenter() {
+ mDevice.click(mDevice.getDisplayWidth() / 2, mDevice.getDisplayHeight() / 2);
+ SystemClock.sleep(SHORT_TIMEOUT);
+ }
+
// Helper method to go back to home screen
public void goBackHome() {
int count = 0;
@@ -159,23 +163,6 @@
count++;
} while (count < 5);
- // TODO (yuanlang@) Delete the following hacky codes after charging icon issue fixed
- // Make sure we're not in the launcher
- if (waitForSysAppUiObject2(LAUNCHER_VIEW_NAME) != null) {
- mDevice.pressBack();
- }
- // Make sure we're not in cards view
- if (waitForSysAppUiObject2(CARD_VIEW_NAME) != null) {
- mDevice.pressBack();
- }
- // Make sure we're not in the quick settings
- if (waitForSysAppUiObject2(QUICKSETTING_VIEW_NAME) != null) {
- mDevice.pressBack();
- }
- // Make sure we're not in watch face picker
- if (waitForSysAppUiObject2(WATCHFACE_PREVIEW_NAME) != null) {
- mDevice.pressBack();
- }
SystemClock.sleep(LONG_TIMEOUT);
}
diff --git a/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/WatchFacePickerJankTest.java b/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/WatchFacePickerJankTest.java
index 7ca40bc..4fd04f8 100644
--- a/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/WatchFacePickerJankTest.java
+++ b/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/WatchFacePickerJankTest.java
@@ -69,9 +69,8 @@
* Test the jank by adding watch face to favorites.
*/
@JankTest(beforeLoop = "startFromWatchFacePickerFull",
- afterLoop = "resetToWatchFacePickerFull",
afterTest = "removeAllButOneWatchFace",
- expectedFrames = SysAppTestHelper.EXPECTED_FRAMES_WATCHFACE_PICKER_TEST)
+ expectedFrames = SysAppTestHelper.EXPECTED_FRAMES_WATCHFACE_PICKER_TEST_ADD_FAVORITE)
@GfxMonitor(processName = WEARABLE_APP_PACKAGE)
public void testSelectWatchFaceFromFullList() {
selectWatchFaceFromFullList(0);
@@ -91,7 +90,7 @@
/**
* Test the jank on flinging watch face picker.
*/
- @JankTest(beforeLoop = "startWithFourWatchFaces", afterLoop = "resetToWatchFacePicker",
+ @JankTest(beforeTest = "startWithFourWatchFaces", beforeLoop = "resetToWatchFacePicker",
afterTest = "removeAllButOneWatchFace",
expectedFrames = SysAppTestHelper.EXPECTED_FRAMES_WATCHFACE_PICKER_TEST)
@GfxMonitor(processName = WEARABLE_APP_PACKAGE)
@@ -192,8 +191,14 @@
}
private void openPicker() {
- mHelper.swipeLeft();
- Assert.assertNotNull(mHelper.waitForSysAppUiObject2(WATCHFACE_PREVIEW_NAME));
+ // Try 5 times in case WFP is not ready
+ for (int i = 0; i < 5; i ++) {
+ mHelper.swipeLeft();
+ if (mHelper.waitForSysAppUiObject2(WATCHFACE_PREVIEW_NAME) != null) {
+ return;
+ }
+ }
+ Assert.fail("Still cannot open WFP after several attempts");
}
private void openPickerAllList() {
@@ -225,7 +230,10 @@
List<UiObject2> watchFaces = watchFacePickerAllList.getChildren();
Assert.assertNotNull(watchFaces);
int localIndex = index % 4;
- if (watchFaces.size() <= localIndex) return;
+ if (watchFaces.size() <= localIndex) {
+ mDevice.pressBack();
+ return;
+ }
Log.v(TAG, "Tapping the " + localIndex + " watchface on screen ...");
watchFaces.get(localIndex).click();
@@ -244,7 +252,9 @@
Assert.assertNotNull(watchFacePicker);
List<UiObject2> watchFaces = watchFacePicker.getChildren();
Assert.assertNotNull(watchFaces);
- if (isOnlyOneWatchFaceInFavorites()) return;
+ if (isOnlyOneWatchFaceInFavorites()) {
+ return;
+ }
Log.v(TAG, "Removing first watch face from favorites ...");
watchFaces.get(0).swipe(Direction.DOWN, 1.0f);
diff --git a/utils/wifistrengthscanner/Android.mk b/utils/wifistrengthscanner/Android.mk
new file mode 100644
index 0000000..d35afd4
--- /dev/null
+++ b/utils/wifistrengthscanner/Android.mk
@@ -0,0 +1,27 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_PACKAGE_NAME := WifiStrengthScannerUtil
+LOCAL_STATIC_JAVA_LIBRARIES := ub-uiautomator
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := 23
+
+include $(BUILD_PACKAGE)
diff --git a/utils/wifistrengthscanner/AndroidManifest.xml b/utils/wifistrengthscanner/AndroidManifest.xml
new file mode 100644
index 0000000..ddce7a2
--- /dev/null
+++ b/utils/wifistrengthscanner/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (c) 2016 Google Inc.
+ *
+ * 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.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.test.util.wifistrengthscanner">
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+ <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+ <uses-sdk android:minSdkVersion="23"
+ android:targetSdkVersion="23" />
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name=".WifiStrengthScannerInstrumentation"
+ android:targetPackage="com.android.test.util.wifistrengthscanner"
+ android:label="Dismiss Dialog Util">
+ </instrumentation>
+</manifest>
diff --git a/utils/wifistrengthscanner/src/com/android/test/util/wifistrengthscanner/WifiStrengthScannerInstrumentation.java b/utils/wifistrengthscanner/src/com/android/test/util/wifistrengthscanner/WifiStrengthScannerInstrumentation.java
new file mode 100644
index 0000000..39c49c1
--- /dev/null
+++ b/utils/wifistrengthscanner/src/com/android/test/util/wifistrengthscanner/WifiStrengthScannerInstrumentation.java
@@ -0,0 +1,195 @@
+/*
+ * 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.test.util.wifistrengthscanner;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class WifiStrengthScannerInstrumentation extends Instrumentation {
+ private static final String TAG = WifiStrengthScannerInstrumentation.class.getCanonicalName();
+ private final static String SD_CARD_PATH =
+ Environment.getExternalStorageDirectory().getAbsolutePath() + "/";
+ private final int NUMBER_OF_WIFI_LEVELS = 101;
+ private final int INVALID_RSSI = -127;
+ private Bundle mArguments;
+ private CountDownLatch mLatch;
+ private boolean scanReceived;
+
+ @Override
+ public void onCreate(Bundle arguments) {
+ super.onCreate(arguments);
+ mArguments = arguments;
+ start();
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ try {
+ mLatch = new CountDownLatch(1);
+ getContext().registerReceiver(new WifiScanReceiver(),
+ new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
+ WifiManager wifiManager =
+ (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
+ scanReceived = false;
+ wifiManager.startScan();
+ mLatch.await(10000, TimeUnit.MILLISECONDS);
+
+ if (!scanReceived) {
+ sendFailureStatus("no_scan_received");
+ finish(Activity.RESULT_CANCELED, new Bundle());
+ return;
+ }
+
+ WifiInfo wifiInfo = wifiManager.getConnectionInfo();
+ Bundle bundle = new Bundle();
+ bundle.putString("suplicant_state", wifiInfo.getSupplicantState().name());
+
+ String bssid = wifiInfo.getBSSID();
+ bundle.putString("bssid", bssid);
+ // zero counts as a level, so the max level is one less that the number of levels.
+ bundle.putInt("wifi_max_level", NUMBER_OF_WIFI_LEVELS - 1);
+
+ bundle.putInt("wifi_info_wifi_level",
+ WifiManager.calculateSignalLevel(wifiInfo.getRssi(), NUMBER_OF_WIFI_LEVELS));
+ bundle.putInt("wifi_info_rssi", wifiInfo.getRssi());
+ bundle.putInt("wifi_info_frequency", wifiInfo.getFrequency());
+
+ ScanResult result = getScanResult(wifiManager, bssid);
+ if (result != null) {
+ bundle.putInt("scan_result_wifi_level", wifiManager.calculateSignalLevel(result
+ .level, NUMBER_OF_WIFI_LEVELS));
+ bundle.putInt("scan_result_rssi", result.level);
+ bundle.putInt("scan_result_frequency", result.frequency);
+ }
+
+ int dumpsysRssi = getRssiFromDumpsys(bssid);
+ bundle.putInt("dumpsys_rssi", dumpsysRssi);
+ bundle.putInt("dumpsys_wifi_level",
+ WifiManager.calculateSignalLevel(dumpsysRssi, NUMBER_OF_WIFI_LEVELS));
+ sendStatus(Activity.RESULT_OK, bundle);
+ finish(Activity.RESULT_OK, new Bundle());
+ } catch (IOException e) {
+ Log.e(TAG, Log.getStackTraceString(e));
+ sendFailureStatus("io_exception");
+ finish(Activity.RESULT_CANCELED, new Bundle());
+ } catch (InterruptedException e) {
+ Log.e(TAG, Log.getStackTraceString(e));
+ sendFailureStatus("interrupted_exception");
+ finish(Activity.RESULT_CANCELED, new Bundle());
+ }
+ }
+
+ private ScanResult getScanResult(WifiManager wifiManager, String bssid) {
+ List<ScanResult> scanResults = wifiManager.getScanResults();
+ for (ScanResult scanResult : scanResults) {
+ if (scanResult.BSSID.equals(bssid)) {
+ return scanResult;
+ }
+ }
+
+ return null;
+ }
+
+ private void sendFailureStatus(String update) {
+ Bundle result = new Bundle();
+ result.putString("wifi_strength_scanner_failure", update);
+ sendStatus(Activity.RESULT_CANCELED, result);
+ }
+
+ private Integer getRssiFromDumpsys(String bssid) throws IOException, InterruptedException {
+ List<String> dumpsysLines = getDumpsysWifiLastScanResults();
+
+ for (int i = 2; i < dumpsysLines.size(); i++) {
+ String line = dumpsysLines.get(i);
+ if (line != null && line.contains(bssid)) {
+ String[] tokens = line.trim().split("\\s\\s+");
+ return Integer.parseInt(tokens[2]);
+ }
+ }
+
+ return INVALID_RSSI;
+ }
+
+ private List<String> getDumpsysWifiLastScanResults() throws IOException, InterruptedException {
+ String dumpsysWifi = executeCommand("dumpsys wifi");
+ String[] lines = dumpsysWifi.split("\n");
+ List<String> scanResults = new ArrayList<>();
+
+ boolean scansStarted = false;
+ for (String line : lines) {
+ if (line.startsWith("Latest scan results:")) {
+ scansStarted = true;
+ }
+
+ if (scansStarted) {
+ if ("".equals(line.trim())) {
+ break;
+ }
+
+ scanResults.add(line);
+ }
+ }
+
+ return scanResults;
+ }
+
+ private String executeCommand(String cmd) throws IOException, InterruptedException {
+ StringBuilder result = new StringBuilder();
+ try {
+ ParcelFileDescriptor pfd = getUiAutomation().executeShellCommand(cmd);
+ byte[] buf = new byte[1024];
+ int bytesRead;
+ FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
+ while ((bytesRead = fis.read(buf)) != -1) {
+ result.append(new String(buf, 0, bytesRead));
+ }
+ fis.close();
+ } catch (IOException e) {
+ throw new IOException(String.format("Fails to execute command: %s ", cmd), e);
+ }
+
+ return result.toString();
+ }
+
+ private class WifiScanReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.d(TAG, "scan results received.");
+ scanReceived = true;
+ mLatch.countDown();
+ }
+ }
+}