Make storage and StrictMode tests more robust.
Many of the AppSecurity tests verify cross-user interactions by
creating and starting temporary users on multi-user devices. Since
user creation adds significant overhead, this change creates a
secondary and tertiary user only once for the entire module, which
individual tests can then efficiently reuse.
Quietly skip testFullDisk() when we're unable to free up more than
90% of disk space, since that's a prerequisite for that test.
Rewrite StrictModeTest to use explicit listener for observing
violations, since reading back raw logcat data recently became
very flaky.
Test: cts-tradefed run commandAndExit cts-dev -m CtsOsTestCases -t android.os.cts.StrictModeTest
Test: cts-tradefed run commandAndExit cts-dev -m CtsAppSecurityHostTestCases
Test: cts-tradefed run commandAndExit cts-dev -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.StorageHostTest
Test: cts-tradefed run commandAndExit cts-dev -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.ExternalStorageHostTest
Bug: 38234598, 37486230, 37915178, 62018992
Change-Id: I97182aaa8c82cdc0a1169d5b4adac053c84a1b11
diff --git a/hostsidetests/appsecurity/AndroidTest.xml b/hostsidetests/appsecurity/AndroidTest.xml
index d1989e6..418d363 100644
--- a/hostsidetests/appsecurity/AndroidTest.xml
+++ b/hostsidetests/appsecurity/AndroidTest.xml
@@ -14,6 +14,7 @@
limitations under the License.
-->
<configuration description="Config for the CTS App Security host tests">
+ <target_preparer class="android.appsecurity.cts.AppSecurityPreparer" />
<test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
<option name="jar" value="CtsAppSecurityHostTestCases.jar" />
<option name="runtime-hint" value="20m" />
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
index 16e2765..a1bcc30 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
@@ -55,6 +55,7 @@
protected void setUp() throws Exception {
super.setUp();
+ Utils.prepareSingleUser(getDevice());
assertNotNull(mAbi);
assertNotNull(mCtsBuild);
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityPreparer.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityPreparer.java
new file mode 100644
index 0000000..b1ac744
--- /dev/null
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityPreparer.java
@@ -0,0 +1,64 @@
+/*
+ * 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.appsecurity.cts;
+
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.targetprep.BuildError;
+import com.android.tradefed.targetprep.ITargetCleaner;
+import com.android.tradefed.targetprep.ITargetPreparer;
+import com.android.tradefed.targetprep.TargetSetupError;
+
+/**
+ * Creates secondary and tertiary users for use during a test suite.
+ */
+public class AppSecurityPreparer implements ITargetPreparer, ITargetCleaner {
+ @Override
+ public void setUp(ITestDevice device, IBuildInfo buildInfo)
+ throws TargetSetupError, BuildError, DeviceNotAvailableException {
+ // Clean up any lingering users from other tests to ensure that we have
+ // best shot at creating the users we need below.
+ removeSecondaryUsers(device);
+
+ final int maxUsers = device.getMaxNumberOfUsersSupported();
+ if (maxUsers > 1) {
+ CLog.logAndDisplay(LogLevel.INFO,
+ "Created secondary user " + device.createUser("CTS_" + System.nanoTime()));
+ }
+ if (maxUsers > 2) {
+ CLog.logAndDisplay(LogLevel.INFO,
+ "Created secondary user " + device.createUser("CTS_" + System.nanoTime()));
+ }
+ }
+
+ @Override
+ public void tearDown(ITestDevice device, IBuildInfo buildInfo, Throwable throwable)
+ throws DeviceNotAvailableException {
+ removeSecondaryUsers(device);
+ }
+
+ private void removeSecondaryUsers(ITestDevice device) throws DeviceNotAvailableException {
+ final int[] userIds = Utils.getAllUsers(device);
+ for (int i = 1; i < userIds.length; i++) {
+ device.removeUser(userIds[i]);
+ CLog.logAndDisplay(LogLevel.INFO, "Destroyed secondary user " + userIds[i]);
+ }
+ }
+}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java
index 36b0921..390064d 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java
@@ -110,7 +110,8 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- // ensure build has been set before test is run
+
+ Utils.prepareSingleUser(getDevice());
assertNotNull(mCtsBuild);
}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseAppSecurityTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseAppSecurityTest.java
index 69ff55e..920e0a5 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseAppSecurityTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseAppSecurityTest.java
@@ -17,29 +17,17 @@
package android.appsecurity.cts;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.ddmlib.testrunner.TestResult;
-import com.android.ddmlib.testrunner.TestRunResult;
-import com.android.ddmlib.testrunner.TestResult.TestStatus;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.CollectingTestListener;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IBuildReceiver;
import java.util.ArrayList;
-import java.util.Map;
/**
* Base class.
*/
public class BaseAppSecurityTest extends DeviceTestCase implements IBuildReceiver {
- protected static final int USER_SYSTEM = 0; // From the UserHandle class.
-
- private static final String RUNNER = "android.support.test.runner.AndroidJUnitRunner";
-
protected IBuildInfo mBuildInfo;
/** Whether multi-user is supported. */
@@ -62,49 +50,12 @@
mSupportsMultiUser = getDevice().getMaxNumberOfUsersSupported() > 1;
mIsSplitSystemUser = checkIfSplitSystemUser();
mPrimaryUserId = getDevice().getPrimaryUserId();
- mFixedUsers = new ArrayList();
+ mFixedUsers = new ArrayList<>();
mFixedUsers.add(mPrimaryUserId);
- if (mPrimaryUserId != USER_SYSTEM) {
- mFixedUsers.add(USER_SYSTEM);
+ if (mPrimaryUserId != Utils.USER_SYSTEM) {
+ mFixedUsers.add(Utils.USER_SYSTEM);
}
getDevice().switchUser(mPrimaryUserId);
- removeTestUsers();
- }
-
- @Override
- protected void tearDown() throws Exception {
- removeTestUsers();
- super.tearDown();
- }
-
- /**
- * @return the userid of the created user
- */
- protected int createUser() throws DeviceNotAvailableException, IllegalStateException {
- final String command = "pm create-user "
- + "TestUser_" + System.currentTimeMillis();
- CLog.d("Starting command: " + command);
- final String output = getDevice().executeShellCommand(command);
- CLog.d("Output for command " + command + ": " + output);
-
- if (output.startsWith("Success")) {
- try {
- return Integer.parseInt(output.substring(output.lastIndexOf(" ")).trim());
- } catch (NumberFormatException e) {
- CLog.e("Failed to parse result: %s", output);
- }
- } else {
- CLog.e("Failed to create user: %s", output);
- }
- throw new IllegalStateException();
- }
-
- private void removeTestUsers() throws Exception {
- for (int userId : getDevice().listUsers()) {
- if (!mFixedUsers.contains(userId)) {
- getDevice().removeUser(userId);
- }
- }
}
private boolean checkIfSplitSystemUser() throws DeviceNotAvailableException {
@@ -131,37 +82,4 @@
String output = getDevice().executeShellCommand(command);
return output.contains(packageName);
}
-
- private void printTestResult(TestRunResult runResult) {
- for (Map.Entry<TestIdentifier, TestResult> testEntry :
- runResult.getTestResults().entrySet()) {
- TestResult testResult = testEntry.getValue();
- CLog.d("Test " + testEntry.getKey() + ": " + testResult.getStatus());
- if (testResult.getStatus() != TestStatus.PASSED) {
- CLog.d(testResult.getStackTrace());
- }
- }
- }
-
- protected boolean runDeviceTestsAsUser(String packageName,
- String testClassName, String testMethodName, int userId) throws Exception {
- if (testClassName != null && testClassName.startsWith(".")) {
- testClassName = packageName + testClassName;
- }
-
- RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(
- packageName, RUNNER, getDevice().getIDevice());
- if (testClassName != null && testMethodName != null) {
- testRunner.setMethodName(testClassName, testMethodName);
- } else if (testClassName != null) {
- testRunner.setClassName(testClassName);
- }
-
- CollectingTestListener listener = new CollectingTestListener();
- assertTrue(getDevice().runInstrumentationTestsAsUser(testRunner, userId, listener));
-
- TestRunResult runResult = listener.getCurrentRunResults();
- printTestResult(runResult);
- return !runResult.hasFailedTests() && runResult.getNumTestsInState(TestStatus.PASSED) > 0;
- }
-}
\ No newline at end of file
+}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
index 6a6c27d..2174fa0 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
@@ -54,6 +54,7 @@
private String mFeatureList = null;
+ private int[] mUsers;
private IAbi mAbi;
private IBuildInfo mCtsBuild;
@@ -71,6 +72,7 @@
protected void setUp() throws Exception {
super.setUp();
+ mUsers = Utils.prepareSingleUser(getDevice());
assertNotNull(mAbi);
assertNotNull(mCtsBuild);
@@ -148,11 +150,8 @@
}
public void doDirectBootTest(String mode) throws Exception {
- int[] users = {};
boolean doTest = true;
try {
- users = createUsersForTest();
-
// Set up test app and secure lock screens
new InstallMultiple().addApk(APK).run();
new InstallMultiple().addApk(OTHER_APK).run();
@@ -164,7 +163,7 @@
// Give enough time for PackageManager to persist stopped state
Thread.sleep(15000);
- runDeviceTests(PKG, CLASS, "testSetUp", users);
+ runDeviceTests(PKG, CLASS, "testSetUp", mUsers);
// Give enough time for vold to update keys
Thread.sleep(15000);
@@ -184,19 +183,18 @@
if (doTest) {
if (MODE_NONE.equals(mode)) {
- runDeviceTests(PKG, CLASS, "testVerifyUnlockedAndDismiss", users);
+ runDeviceTests(PKG, CLASS, "testVerifyUnlockedAndDismiss", mUsers);
} else {
- runDeviceTests(PKG, CLASS, "testVerifyLockedAndDismiss", users);
+ runDeviceTests(PKG, CLASS, "testVerifyLockedAndDismiss", mUsers);
}
}
} finally {
try {
// Remove secure lock screens and tear down test app
- runDeviceTests(PKG, CLASS, "testTearDown", users);
+ runDeviceTests(PKG, CLASS, "testTearDown", mUsers);
} finally {
getDevice().uninstallPackage(PKG);
- removeUsersForTest(users);
// Get ourselves back into a known-good state
if (MODE_EMULATED.equals(mode)) {
@@ -211,16 +209,6 @@
}
}
- private int[] createUsersForTest() throws DeviceNotAvailableException {
- // TODO: enable test for multiple users
- return new int[] { 0 };
-// return Utils.createUsersForTest(getDevice());
- }
-
- private void removeUsersForTest(int[] users) throws DeviceNotAvailableException {
- Utils.removeUsersForTest(getDevice(), users);
- }
-
private void runDeviceTests(String packageName, String testClassName, String testMethodName,
int... users) throws DeviceNotAvailableException {
for (int user : users) {
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java
index ceb7539..7bdd128 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java
@@ -48,6 +48,7 @@
protected void setUp() throws Exception {
super.setUp();
+ Utils.prepareSingleUser(getDevice());
assertNotNull(mAbi);
assertNotNull(mCtsBuild);
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
index 915f147..8397f54 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
@@ -70,6 +70,7 @@
public void setUp() throws Exception {
super.setUp();
+ Utils.prepareSingleUser(getDevice());
assertNotNull(mAbi);
assertNotNull(mBuildInfo);
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
index e8dca57..87d8bd6 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
@@ -52,6 +52,7 @@
private static final String MULTIUSER_PKG = "com.android.cts.multiuserstorageapp";
private static final String MULTIUSER_CLASS = ".MultiUserStorageTest";
+ private int[] mUsers;
private IAbi mAbi;
private IBuildInfo mCtsBuild;
@@ -74,6 +75,7 @@
protected void setUp() throws Exception {
super.setUp();
+ mUsers = Utils.prepareMultipleUsers(getDevice());
assertNotNull(mAbi);
assertNotNull(mCtsBuild);
}
@@ -87,7 +89,6 @@
* Verify that app with no external storage permissions works correctly.
*/
public void testExternalStorageNone() throws Exception {
- final int[] users = createUsersForTest();
try {
wipePrimaryExternalStorage();
@@ -95,13 +96,12 @@
String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
assertNull(getDevice().installPackage(getTestAppFile(NONE_APK), false, options));
- for (int user : users) {
+ for (int user : mUsers) {
runDeviceTests(NONE_PKG, COMMON_CLASS, user);
runDeviceTests(NONE_PKG, NONE_CLASS, user);
}
} finally {
getDevice().uninstallPackage(NONE_PKG);
- removeUsersForTest(users);
}
}
@@ -111,7 +111,6 @@
* correctly.
*/
public void testExternalStorageRead() throws Exception {
- final int[] users = createUsersForTest();
try {
wipePrimaryExternalStorage();
@@ -119,13 +118,12 @@
String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
assertNull(getDevice().installPackage(getTestAppFile(READ_APK), false, options));
- for (int user : users) {
+ for (int user : mUsers) {
runDeviceTests(READ_PKG, COMMON_CLASS, user);
runDeviceTests(READ_PKG, READ_CLASS, user);
}
} finally {
getDevice().uninstallPackage(READ_PKG);
- removeUsersForTest(users);
}
}
@@ -135,7 +133,6 @@
* correctly.
*/
public void testExternalStorageWrite() throws Exception {
- final int[] users = createUsersForTest();
try {
wipePrimaryExternalStorage();
@@ -143,13 +140,12 @@
String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options));
- for (int user : users) {
+ for (int user : mUsers) {
runDeviceTests(WRITE_PKG, COMMON_CLASS, user);
runDeviceTests(WRITE_PKG, WRITE_CLASS, user);
}
} finally {
getDevice().uninstallPackage(WRITE_PKG);
- removeUsersForTest(users);
}
}
@@ -158,7 +154,6 @@
* directories belonging to other apps, and those apps can read.
*/
public void testExternalStorageGifts() throws Exception {
- final int[] users = createUsersForTest();
try {
wipePrimaryExternalStorage();
@@ -170,13 +165,13 @@
// We purposefully delay the installation of the reading apps to
// verify that the daemon correctly invalidates any caches.
assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options));
- for (int user : users) {
+ for (int user : mUsers) {
runDeviceTests(WRITE_PKG, ".WriteGiftTest", user);
}
assertNull(getDevice().installPackage(getTestAppFile(NONE_APK), false, options));
assertNull(getDevice().installPackage(getTestAppFile(READ_APK), false, options));
- for (int user : users) {
+ for (int user : mUsers) {
runDeviceTests(READ_PKG, ".ReadGiftTest", user);
runDeviceTests(NONE_PKG, ".GiftTest", user);
}
@@ -184,7 +179,6 @@
getDevice().uninstallPackage(NONE_PKG);
getDevice().uninstallPackage(READ_PKG);
getDevice().uninstallPackage(WRITE_PKG);
- removeUsersForTest(users);
}
}
@@ -193,15 +187,14 @@
* isolated storage.
*/
public void testMultiUserStorageIsolated() throws Exception {
- final int[] users = createUsersForTest();
try {
- if (users.length == 1) {
+ if (mUsers.length == 1) {
Log.d(TAG, "Single user device; skipping isolated storage tests");
return;
}
- final int owner = users[0];
- final int secondary = users[1];
+ final int owner = mUsers[0];
+ final int secondary = mUsers[1];
// Install our test app
getDevice().uninstallPackage(MULTIUSER_PKG);
@@ -231,7 +224,6 @@
runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testMediaProviderUserIsolation", secondary);
} finally {
getDevice().uninstallPackage(MULTIUSER_PKG);
- removeUsersForTest(users);
}
}
@@ -240,7 +232,6 @@
* when apps with r/w permission levels move around their files.
*/
public void testMultiViewMoveConsistency() throws Exception {
- final int[] users = createUsersForTest();
try {
wipePrimaryExternalStorage();
@@ -252,37 +243,35 @@
assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options));
assertNull(getDevice().installPackage(getTestAppFile(READ_APK), false, options));
- for (int user : users) {
+ for (int user : mUsers) {
runDeviceTests(READ_PKG, ".ReadMultiViewTest", "testFolderSetup", user);
}
- for (int user : users) {
+ for (int user : mUsers) {
runDeviceTests(READ_PKG, ".ReadMultiViewTest", "testRWAccess", user);
}
- for (int user : users) {
+ for (int user : mUsers) {
runDeviceTests(WRITE_PKG, ".WriteMultiViewTest", "testMoveAway", user);
}
- for (int user : users) {
+ for (int user : mUsers) {
runDeviceTests(READ_PKG, ".ReadMultiViewTest", "testROAccess", user);
}
- for (int user : users) {
+ for (int user : mUsers) {
runDeviceTests(WRITE_PKG, ".WriteMultiViewTest", "testMoveBack", user);
}
- for (int user : users) {
+ for (int user : mUsers) {
runDeviceTests(READ_PKG, ".ReadMultiViewTest", "testRWAccess", user);
}
} finally {
getDevice().uninstallPackage(NONE_PKG);
getDevice().uninstallPackage(READ_PKG);
getDevice().uninstallPackage(WRITE_PKG);
- removeUsersForTest(users);
}
}
/** Verify that app without READ_EXTERNAL can play default URIs in external storage. */
public void testExternalStorageReadDefaultUris() throws Exception {
- final int[] users = createUsersForTest();
try {
wipePrimaryExternalStorage();
@@ -293,7 +282,7 @@
assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options));
assertNull(getDevice().installPackage(getTestAppFile(NONE_APK), false, options));
- for (int user : users) {
+ for (int user : mUsers) {
enableWriteSettings(WRITE_PKG, user);
runDeviceTests(
WRITE_PKG, WRITE_PKG + ".ChangeDefaultUris", "testChangeDefaultUris", user);
@@ -303,13 +292,12 @@
}
} finally {
// Make sure the provider and uris are reset on failure.
- for (int user : users) {
+ for (int user : mUsers) {
runDeviceTests(
WRITE_PKG, WRITE_PKG + ".ChangeDefaultUris", "testResetDefaultUris", user);
}
getDevice().uninstallPackage(NONE_PKG);
getDevice().uninstallPackage(WRITE_PKG);
- removeUsersForTest(users);
}
}
@@ -334,14 +322,6 @@
getDevice().executeShellCommand("rm -rf /sdcard/MUST_*");
}
- private int[] createUsersForTest() throws DeviceNotAvailableException {
- return Utils.createUsersForTest(getDevice());
- }
-
- private void removeUsersForTest(int[] users) throws DeviceNotAvailableException {
- Utils.removeUsersForTest(getDevice(), users);
- }
-
private void runDeviceTests(String packageName, String testClassName, int userId)
throws DeviceNotAvailableException {
Utils.runDeviceTests(getDevice(), packageName, testClassName, userId);
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantAppUserTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantAppUserTest.java
index fb5dffa..4609e8a 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantAppUserTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantAppUserTest.java
@@ -19,8 +19,6 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IAbi;
import com.android.tradefed.testtype.IAbiReceiver;
@@ -73,8 +71,9 @@
assertNotNull(mAbi);
assertNotNull(mBuildInfo);
- mSupportsMultiUser =
- getDevice().getMaxNumberOfUsersSupported() - getDevice().listUsers().size() >= 2;
+ // This test only runs when we have at least 3 users to work with
+ final int[] users = Utils.prepareMultipleUsers(getDevice(), 3);
+ mSupportsMultiUser = (users.length == 3);
if (mSupportsMultiUser) {
mPrimaryUserId = getDevice().getPrimaryUserId();
mFixedUsers = new ArrayList<>();
@@ -83,8 +82,9 @@
mFixedUsers.add(USER_SYSTEM);
}
getDevice().switchUser(mPrimaryUserId);
- removeTestUsers();
- createTestUsers();
+
+ mTestUser[0] = users[1];
+ mTestUser[1] = users[2];
uninstallTestPackages();
installTestPackages();
@@ -93,7 +93,6 @@
public void tearDown() throws Exception {
if (mSupportsMultiUser) {
- removeTestUsers();
uninstallTestPackages();
}
super.tearDown();
@@ -180,19 +179,6 @@
getDevice().uninstallPackage(USER_PKG);
}
- private void createTestUsers() throws Exception {
- mTestUser[0] = getDevice().createUser("TestUser_" + System.currentTimeMillis());
- mTestUser[1] = getDevice().createUser("TestUser_" + System.currentTimeMillis());
- }
-
- private void removeTestUsers() throws Exception {
- for (int userId : getDevice().listUsers()) {
- if (!mFixedUsers.contains(userId)) {
- getDevice().removeUser(userId);
- }
- }
- }
-
private void runDeviceTests(String packageName, String testClassName, String testMethodName)
throws DeviceNotAvailableException {
Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantCookieHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantCookieHostTest.java
index e5a483c..fd599ea 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantCookieHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantCookieHostTest.java
@@ -39,6 +39,8 @@
@Override
protected void setUp() throws Exception {
super.setUp();
+
+ Utils.prepareSingleUser(getDevice());
uninstallPackage(INSTANT_COOKIE_APP_PKG);
clearUserData(INSTANT_COOKIE_APP_PKG);
}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/IsolatedSplitsTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/IsolatedSplitsTests.java
index ed05837..8795fe8 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/IsolatedSplitsTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/IsolatedSplitsTests.java
@@ -43,6 +43,8 @@
@Override
protected void setUp() throws Exception {
super.setUp();
+
+ Utils.prepareSingleUser(getDevice());
getDevice().uninstallPackage(PKG);
}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java
index 1f7c6be..3574191 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java
@@ -236,10 +236,13 @@
}
@Override
- protected void setUp() throws Exception {
+ protected void setUp() throws Exception {
super.setUp();
- mDevice = getDevice();
+
+ Utils.prepareSingleUser(getDevice());
assertNotNull(mCtsBuild);
+
+ mDevice = getDevice();
}
/**
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageVisibilityTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageVisibilityTest.java
index 115ebf4..fde9f10 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageVisibilityTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageVisibilityTest.java
@@ -32,10 +32,13 @@
private static final boolean MATCH_UNINSTALLED = true;
private static final boolean MATCH_NORMAL = false;
+ private int[] mUsers;
private String mOldVerifierValue;
public void setUp() throws Exception {
super.setUp();
+
+ mUsers = Utils.prepareMultipleUsers(getDevice());
mOldVerifierValue =
getDevice().executeShellCommand("settings get global package_verifier_enable");
getDevice().executeShellCommand("settings put global package_verifier_enable 0");
@@ -54,7 +57,7 @@
return;
}
- int userId = createUser();
+ int userId = mUsers[1];
assertTrue(userId > 0);
getDevice().startUser(userId);
installTestAppForUser(TEST_APK, userId);
@@ -67,23 +70,23 @@
assertTrue(isAppVisibleForUser(TINY_PKG, mPrimaryUserId, MATCH_UNINSTALLED));
// Try the same from an app
- assertTrue(runDeviceTestsAsUser(TEST_PKG,
- ".PackageAccessTest", "testPackageAccess_inUser", mPrimaryUserId));
- assertTrue(runDeviceTestsAsUser(TEST_PKG,
- ".PackageAccessTest", "testPackageAccess_inUserUninstalled", mPrimaryUserId));
+ Utils.runDeviceTests(getDevice(), TEST_PKG,
+ ".PackageAccessTest", "testPackageAccess_inUser", mPrimaryUserId);
+ Utils.runDeviceTests(getDevice(), TEST_PKG,
+ ".PackageAccessTest", "testPackageAccess_inUserUninstalled", mPrimaryUserId);
// It is not visible for the other user using shell commands
assertFalse(isAppVisibleForUser(TINY_PKG, userId, MATCH_NORMAL));
assertFalse(isAppVisibleForUser(TINY_PKG, userId, MATCH_UNINSTALLED));
// Try the same from an app
- assertTrue(runDeviceTestsAsUser(TEST_PKG,
- ".PackageAccessTest", "testPackageAccess_notInOtherUser", userId));
- assertTrue(runDeviceTestsAsUser(TEST_PKG,
- ".PackageAccessTest", "testPackageAccess_notInOtherUserUninstalled", userId));
+ Utils.runDeviceTests(getDevice(), TEST_PKG,
+ ".PackageAccessTest", "testPackageAccess_notInOtherUser", userId);
+ Utils.runDeviceTests(getDevice(), TEST_PKG,
+ ".PackageAccessTest", "testPackageAccess_notInOtherUserUninstalled", userId);
- assertTrue(runDeviceTestsAsUser(TEST_PKG,
- ".PackageAccessTest", "testPackageAccess_getPackagesCantSeeTiny", userId));
+ Utils.runDeviceTests(getDevice(), TEST_PKG,
+ ".PackageAccessTest", "testPackageAccess_getPackagesCantSeeTiny", userId);
getDevice().uninstallPackage(TINY_PKG);
@@ -105,14 +108,14 @@
assertFalse(isAppVisibleForUser(TINY_PKG, userId, MATCH_NORMAL));
assertTrue(isAppVisibleForUser(TINY_PKG, userId, MATCH_UNINSTALLED));
- assertTrue(runDeviceTestsAsUser(TEST_PKG,
- ".PackageAccessTest", "testPackageAccess_getPackagesCanSeeTiny", userId));
+ Utils.runDeviceTests(getDevice(), TEST_PKG,
+ ".PackageAccessTest", "testPackageAccess_getPackagesCanSeeTiny", userId);
- assertTrue(runDeviceTestsAsUser(TEST_PKG,
+ Utils.runDeviceTests(getDevice(), TEST_PKG,
".PackageAccessTest", "testPackageAccess_notInOtherUserUninstalled",
- mPrimaryUserId));
- assertTrue(runDeviceTestsAsUser(TEST_PKG,
- ".PackageAccessTest", "testPackageAccess_getPackagesCantSeeTiny", mPrimaryUserId));
+ mPrimaryUserId);
+ Utils.runDeviceTests(getDevice(), TEST_PKG,
+ ".PackageAccessTest", "testPackageAccess_getPackagesCantSeeTiny", mPrimaryUserId);
getDevice().uninstallPackage(TINY_PKG);
getDevice().uninstallPackage(TEST_PKG);
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java
index b7f7f88..9ba3c82 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java
@@ -58,6 +58,7 @@
protected void setUp() throws Exception {
super.setUp();
+ Utils.prepareSingleUser(getDevice());
assertNotNull(mAbi);
assertNotNull(mBuildHelper);
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
index 93d683f..e87c390 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
@@ -16,6 +16,11 @@
package android.appsecurity.cts;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
@@ -24,12 +29,6 @@
import java.io.OutputStream;
import java.util.Locale;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.testtype.IBuildReceiver;
-
/**
* Tests for APK signature verification during installation.
*/
@@ -44,10 +43,6 @@
private static final String[] RSA_KEY_NAMES_2048_AND_LARGER =
{"2048", "3072", "4096", "8192", "16384"};
-
- /** Device under test. */
- private ITestDevice mDevice;
-
private IBuildInfo mCtsBuild;
@Override
@@ -58,7 +53,8 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- mDevice = getDevice();
+
+ Utils.prepareSingleUser(getDevice());
assertNotNull(mCtsBuild);
uninstallPackage();
}
@@ -582,9 +578,9 @@
}
}
if (ephemeral) {
- return mDevice.installPackage(apkFile, true, "--ephemeral");
+ return getDevice().installPackage(apkFile, true, "--ephemeral");
} else {
- return mDevice.installPackage(apkFile, true);
+ return getDevice().installPackage(apkFile, true);
}
} finally {
apkFile.delete();
@@ -602,6 +598,6 @@
}
private String uninstallPackage() throws DeviceNotAvailableException {
- return mDevice.uninstallPackage(TEST_PKG);
+ return getDevice().uninstallPackage(TEST_PKG);
}
}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PrivilegedUpdateTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PrivilegedUpdateTests.java
index ca218ef..630f351 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PrivilegedUpdateTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PrivilegedUpdateTests.java
@@ -63,6 +63,7 @@
protected void setUp() throws Exception {
super.setUp();
+ Utils.prepareSingleUser(getDevice());
assertNotNull(mAbi);
assertNotNull(mBuildHelper);
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/SplitTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/SplitTests.java
index 21bfca1..9474ba8 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/SplitTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/SplitTests.java
@@ -96,6 +96,7 @@
protected void setUp() throws Exception {
super.setUp();
+ Utils.prepareSingleUser(getDevice());
assertNotNull(mAbi);
assertNotNull(mCtsBuild);
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java
index f679e83..f08e4fe 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java
@@ -16,18 +16,22 @@
package android.appsecurity.cts;
-import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.tradefed.build.IBuildInfo;
+import com.android.compatibility.common.tradefed.testtype.CompatibilityHostTestBase;
import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.testtype.IAbi;
-import com.android.tradefed.testtype.IAbiReceiver;
-import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import junit.framework.AssertionFailedError;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
/**
* Tests that exercise various storage APIs.
*/
-public class StorageHostTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class StorageHostTest extends CompatibilityHostTestBase {
private static final String PKG_STATS = "com.android.cts.storagestatsapp";
private static final String PKG_A = "com.android.cts.storageapp_a";
private static final String PKG_B = "com.android.cts.storageapp_b";
@@ -37,49 +41,15 @@
private static final String CLASS_STATS = "com.android.cts.storagestatsapp.StorageStatsTest";
private static final String CLASS = "com.android.cts.storageapp.StorageTest";
- private IAbi mAbi;
- private IBuildInfo mCtsBuild;
-
private int[] mUsers;
- @Override
- public void setAbi(IAbi abi) {
- mAbi = abi;
- }
+ @Before
+ public void setUp() throws Exception {
+ mUsers = Utils.prepareMultipleUsers(getDevice());
- @Override
- public void setBuild(IBuildInfo buildInfo) {
- mCtsBuild = buildInfo;
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- mUsers = Utils.createUsersForTest(getDevice());
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
-
- getDevice().uninstallPackage(PKG_STATS);
- getDevice().uninstallPackage(PKG_A);
- getDevice().uninstallPackage(PKG_B);
-
- Utils.removeUsersForTest(getDevice(), mUsers);
- mUsers = null;
- }
-
- private void prepareTestApps() throws Exception {
- getDevice().uninstallPackage(PKG_STATS);
- getDevice().uninstallPackage(PKG_A);
- getDevice().uninstallPackage(PKG_B);
-
- CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild);
- assertNull(getDevice().installPackage(buildHelper.getTestFile(APK_STATS), false));
- assertNull(getDevice().installPackage(buildHelper.getTestFile(APK_A), false));
- assertNull(getDevice().installPackage(buildHelper.getTestFile(APK_B), false));
+ installPackage(APK_STATS);
+ installPackage(APK_A);
+ installPackage(APK_B);
for (int user : mUsers) {
getDevice().executeShellCommand("appops set --user " + user + " " + PKG_STATS
@@ -87,26 +57,20 @@
}
}
- public void testEverything() throws Exception {
- prepareTestApps(); doVerifyQuota();
- prepareTestApps(); doVerifyAppStats();
- prepareTestApps(); doVerifyAppQuota();
- prepareTestApps(); doVerifyAppAllocate();
- prepareTestApps(); doVerifySummary();
- prepareTestApps(); doVerifyStats();
- prepareTestApps(); doVerifyStatsMultiple();
- prepareTestApps(); doVerifyStatsExternal();
- prepareTestApps(); doVerifyStatsExternalConsistent();
- prepareTestApps(); doVerifyCategory();
- prepareTestApps(); doCache();
- prepareTestApps(); doFullDisk();
+ @After
+ public void tearDown() throws Exception {
+ getDevice().uninstallPackage(PKG_STATS);
+ getDevice().uninstallPackage(PKG_A);
+ getDevice().uninstallPackage(PKG_B);
}
- public void doVerifyQuota() throws Exception {
- runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifyQuota", Utils.USER_OWNER);
+ @Test
+ public void testVerifyQuota() throws Exception {
+ Utils.runDeviceTests(getDevice(), PKG_STATS, CLASS_STATS, "testVerifyQuota");
}
- public void doVerifyAppStats() throws Exception {
+ @Test
+ public void testVerifyAppStats() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_A, CLASS, "testAllocate", user);
}
@@ -120,31 +84,36 @@
}
}
- public void doVerifyAppQuota() throws Exception {
+ @Test
+ public void testVerifyAppQuota() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_A, CLASS, "testVerifyQuotaApi", user);
}
}
- public void doVerifyAppAllocate() throws Exception {
+ @Test
+ public void testVerifyAppAllocate() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_A, CLASS, "testVerifyAllocateApi", user);
}
}
- public void doVerifySummary() throws Exception {
+ @Test
+ public void testVerifySummary() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifySummary", user);
}
}
- public void doVerifyStats() throws Exception {
+ @Test
+ public void testVerifyStats() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifyStats", user);
}
}
- public void doVerifyStatsMultiple() throws Exception {
+ @Test
+ public void testVerifyStatsMultiple() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_A, CLASS, "testAllocate", user);
runDeviceTests(PKG_A, CLASS, "testAllocate", user);
@@ -157,25 +126,29 @@
}
}
- public void doVerifyStatsExternal() throws Exception {
+ @Test
+ public void testVerifyStatsExternal() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifyStatsExternal", user);
}
}
- public void doVerifyStatsExternalConsistent() throws Exception {
+ @Test
+ public void testVerifyStatsExternalConsistent() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifyStatsExternalConsistent", user);
}
}
- public void doVerifyCategory() throws Exception {
+ @Test
+ public void testVerifyCategory() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifyCategory", user);
}
}
- public void doCache() throws Exception {
+ @Test
+ public void testCache() throws Exception {
// To make the cache clearing logic easier to verify, ignore any cache
// and low space reserved space.
getDevice().executeShellCommand("settings put global sys_storage_threshold_max_bytes 0");
@@ -197,7 +170,8 @@
}
}
- public void doFullDisk() throws Exception {
+ @Test
+ public void testFullDisk() throws Exception {
waitForIdle();
// Clear all other cached and external storage data to give ourselves a
@@ -209,9 +183,18 @@
final String lastEvent = getDevice().executeShellCommand("logcat -d -b events -t 1");
final String sinceTime = lastEvent.trim().substring(0, 18);
- // Try our hardest to fill up the entire disk
- runDeviceTests(PKG_A, CLASS, "testFullDisk", Utils.USER_OWNER);
- runDeviceTests(PKG_A, CLASS, "testTweakComponent", Utils.USER_OWNER);
+ try {
+ // Try our hardest to fill up the entire disk
+ Utils.runDeviceTests(getDevice(), PKG_A, CLASS, "testFullDisk");
+ } catch (Throwable t) {
+ // If we had trouble filling the disk, don't bother going any
+ // further; we failed because we either don't have quota support, or
+ // because disk was more than 10% full.
+ return;
+ }
+
+ // Tweak something that causes PackageManager to persist data
+ Utils.runDeviceTests(getDevice(), PKG_A, CLASS, "testTweakComponent");
// Try poking around a couple of settings apps
getDevice().executeShellCommand("input keyevent KEY_HOME");
@@ -234,7 +217,7 @@
troubleLogs = troubleLogs.trim().replaceAll("\\-+ beginning of [a-z]+", "");
if (troubleLogs.length() > 4) {
- fail("Unexpected crashes while disk full: " + troubleLogs);
+ throw new AssertionFailedError("Unexpected crashes while disk full: " + troubleLogs);
}
}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/UsesLibraryHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/UsesLibraryHostTest.java
index cf8a354..4afeb9bf 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/UsesLibraryHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/UsesLibraryHostTest.java
@@ -51,6 +51,7 @@
protected void setUp() throws Exception {
super.setUp();
+ Utils.prepareSingleUser(getDevice());
assertNotNull(mAbi);
assertNotNull(mBuildHelper);
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java
index 37aaeaf..8e83c87 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java
@@ -16,7 +16,6 @@
package android.appsecurity.cts;
-import com.android.ddmlib.Log;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.ddmlib.testrunner.TestResult;
@@ -26,16 +25,15 @@
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.result.CollectingTestListener;
+import java.util.Arrays;
import java.util.Map;
public class Utils {
- private static final String TAG = "AppSecurity";
-
- public static final int USER_OWNER = 0;
+ public static final int USER_SYSTEM = 0;
public static void runDeviceTests(ITestDevice device, String packageName)
throws DeviceNotAvailableException {
- runDeviceTests(device, packageName, null, null, USER_OWNER);
+ runDeviceTests(device, packageName, null, null, USER_SYSTEM);
}
public static void runDeviceTests(ITestDevice device, String packageName, int userId)
@@ -45,7 +43,7 @@
public static void runDeviceTests(ITestDevice device, String packageName, String testClassName)
throws DeviceNotAvailableException {
- runDeviceTests(device, packageName, testClassName, null, USER_OWNER);
+ runDeviceTests(device, packageName, testClassName, null, USER_SYSTEM);
}
public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
@@ -55,7 +53,7 @@
public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
String testMethodName) throws DeviceNotAvailableException {
- runDeviceTests(device, packageName, testClassName, testMethodName, USER_OWNER);
+ runDeviceTests(device, packageName, testClassName, testMethodName, USER_SYSTEM);
}
public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
@@ -72,13 +70,8 @@
testRunner.setClassName(testClassName);
}
- if (userId != USER_OWNER) {
- // TODO: move this to RemoteAndroidTestRunner once it supports users
- testRunner.addInstrumentationArg("hack_key", "hack_value --user " + userId);
- }
-
final CollectingTestListener listener = new CollectingTestListener();
- device.runInstrumentationTests(testRunner, listener);
+ device.runInstrumentationTestsAsUser(testRunner, userId, listener);
final TestRunResult result = listener.getCurrentRunResults();
if (result.isRunFailure()) {
@@ -103,65 +96,55 @@
}
}
- private static boolean isMultiUserSupportedOnDevice(ITestDevice device)
+ /**
+ * Prepare and return a single user relevant for testing.
+ */
+ public static int[] prepareSingleUser(ITestDevice device)
throws DeviceNotAvailableException {
- // TODO: move this to ITestDevice once it supports users
- final String output = device.executeShellCommand("pm get-max-users");
- try {
- return Integer.parseInt(output.substring(output.lastIndexOf(" ")).trim()) > 1;
- } catch (NumberFormatException e) {
- throw new AssertionError("Failed to parse result: " + output);
- }
+ return prepareMultipleUsers(device, 1);
}
/**
- * Return set of users that test should be run for, creating a secondary
- * user if the device supports it. Always call
- * {@link #removeUsersForTest(ITestDevice, int[])} when finished.
+ * Prepare and return two users relevant for testing.
*/
- public static int[] createUsersForTest(ITestDevice device) throws DeviceNotAvailableException {
- if (isMultiUserSupportedOnDevice(device)) {
- return new int[] { USER_OWNER, createUserOnDevice(device) };
- } else {
- Log.d(TAG, "Single user device; skipping isolated storage tests");
- return new int[] { USER_OWNER };
- }
+ public static int[] prepareMultipleUsers(ITestDevice device)
+ throws DeviceNotAvailableException {
+ return prepareMultipleUsers(device, 2);
}
- public static void removeUsersForTest(ITestDevice device, int[] users)
+ /**
+ * Prepare and return multiple users relevant for testing.
+ */
+ public static int[] prepareMultipleUsers(ITestDevice device, int maxUsers)
throws DeviceNotAvailableException {
- for (int user : users) {
- if (user != USER_OWNER) {
- removeUserOnDevice(device, user);
+ final int[] userIds = getAllUsers(device);
+ for (int i = 1; i < userIds.length; i++) {
+ if (i < maxUsers) {
+ device.startUser(userIds[i]);
+ } else {
+ device.stopUser(userIds[i]);
}
}
- }
-
- private static int createUserOnDevice(ITestDevice device) throws DeviceNotAvailableException {
- // TODO: move this to ITestDevice once it supports users
- final String name = "CTS_" + System.currentTimeMillis();
- final String output = device.executeShellCommand("pm create-user " + name);
- if (output.startsWith("Success")) {
- try {
- final int userId = Integer.parseInt(
- output.substring(output.lastIndexOf(" ")).trim());
- device.executeShellCommand("am start-user " + userId);
- return userId;
- } catch (NumberFormatException e) {
- throw new AssertionError("Failed to parse result: " + output);
- }
+ if (userIds.length > maxUsers) {
+ return Arrays.copyOf(userIds, maxUsers);
} else {
- throw new AssertionError("Failed to create user: " + output);
+ return userIds;
}
}
- private static void removeUserOnDevice(ITestDevice device, int userId)
+ public static int[] getAllUsers(ITestDevice device)
throws DeviceNotAvailableException {
- // TODO: move this to ITestDevice once it supports users
- final String output = device.executeShellCommand("pm remove-user " + userId);
- if (output.startsWith("Error")) {
- throw new AssertionError("Failed to remove user: " + output);
+ Integer primary = device.getPrimaryUserId();
+ if (primary == null) {
+ primary = USER_SYSTEM;
}
+ int[] users = new int[] { primary };
+ for (Integer user : device.listUsers()) {
+ if ((user != USER_SYSTEM) && (user != primary)) {
+ users = Arrays.copyOf(users, users.length + 1);
+ users[users.length - 1] = user;
+ }
+ }
+ return users;
}
-
}
diff --git a/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/StorageTest.java b/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/StorageTest.java
index 4a4eef1..9d0dec6 100644
--- a/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/StorageTest.java
+++ b/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/StorageTest.java
@@ -23,7 +23,6 @@
import static com.android.cts.storageapp.Utils.DATA_INT;
import static com.android.cts.storageapp.Utils.MB_IN_BYTES;
import static com.android.cts.storageapp.Utils.PKG_B;
-import static com.android.cts.storageapp.Utils.TAG;
import static com.android.cts.storageapp.Utils.assertMostlyEquals;
import static com.android.cts.storageapp.Utils.getSizeManual;
import static com.android.cts.storageapp.Utils.makeUniqueFile;
@@ -42,7 +41,6 @@
import android.os.storage.StorageManager;
import android.system.Os;
import android.test.InstrumentationTestCase;
-import android.util.Log;
import java.io.File;
import java.io.IOException;
@@ -62,9 +60,19 @@
public void testFullDisk() throws Exception {
if (shouldHaveQuota(Os.uname())) {
- Hoarder.doBlocks(getContext().getDataDir(), true);
+ final File dataDir = getContext().getDataDir();
+
+ // Pre-flight to see if we have enough disk space to test with
+ final long total = dataDir.getTotalSpace();
+ final long free = dataDir.getFreeSpace();
+ final long required = ((total * 9) / 10) + MB_IN_BYTES;
+ if (free < required) {
+ fail("Skipping full disk test; only found " + free + " free out of " + total);
+ }
+
+ Hoarder.doBlocks(dataDir, true);
} else {
- Log.d(TAG, "Skipping full disk test due to missing quota support");
+ fail("Skipping full disk test due to missing quota support");
}
}
diff --git a/tests/tests/os/src/android/os/cts/StrictModeTest.java b/tests/tests/os/src/android/os/cts/StrictModeTest.java
index fecc067..21730c6 100644
--- a/tests/tests/os/src/android/os/cts/StrictModeTest.java
+++ b/tests/tests/os/src/android/os/cts/StrictModeTest.java
@@ -22,15 +22,12 @@
import android.net.TrafficStats;
import android.net.Uri;
import android.os.StrictMode;
-import android.os.SystemClock;
+import android.os.StrictMode.ViolationListener;
import android.system.Os;
import android.system.OsConstants;
import android.test.InstrumentationTestCase;
import android.util.Log;
-import libcore.io.Streams;
-
-import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
@@ -38,8 +35,8 @@
import java.net.HttpURLConnection;
import java.net.Socket;
import java.net.URL;
-import java.text.SimpleDateFormat;
-import java.util.Date;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
/**
* Tests for {@link StrictMode}
@@ -66,6 +63,10 @@
StrictMode.setVmPolicy(mVmPolicy);
}
+ public interface ThrowingRunnable {
+ public void run() throws Exception;
+ }
+
/**
* Insecure connection should be detected
*/
@@ -80,10 +81,10 @@
.penaltyLog()
.build());
- long mark = System.currentTimeMillis();
- ((HttpURLConnection) new URL("http://example.com/").openConnection()).getResponseCode();
- assertLogged("Detected cleartext network traffic from UID "
- + android.os.Process.myUid(), mark, 5000);
+ assertViolation("Detected cleartext network traffic from UID", () -> {
+ ((HttpURLConnection) new URL("http://example.com/").openConnection())
+ .getResponseCode();
+ });
}
/**
@@ -100,10 +101,10 @@
.penaltyLog()
.build());
- long mark = System.currentTimeMillis();
- ((HttpURLConnection) new URL("https://example.com/").openConnection()).getResponseCode();
- assertNotLogged("Detected cleartext network traffic from UID "
- + android.os.Process.myUid(), mark, 5000);
+ assertNoViolation(() -> {
+ ((HttpURLConnection) new URL("https://example.com/").openConnection())
+ .getResponseCode();
+ });
}
public void testFileUriExposure() throws Exception {
@@ -112,19 +113,21 @@
.penaltyLog()
.build());
- long mark = System.currentTimeMillis();
- Uri uri = Uri.fromFile(new File("/sdcard/meow.jpg"));
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setDataAndType(uri, "image/jpeg");
- getContext().startActivity(intent);
- assertLogged(uri + " exposed beyond app", mark);
+ final Uri badUri = Uri.fromFile(new File("/sdcard/meow.jpg"));
+ assertViolation(badUri + " exposed beyond app", () -> {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setDataAndType(badUri, "image/jpeg");
+ getContext().startActivity(intent);
+ });
- mark = System.currentTimeMillis();
- uri = Uri.parse("content://com.example/foobar");
- intent = new Intent(Intent.ACTION_VIEW);
- intent.setDataAndType(uri, "image/jpeg");
- getContext().startActivity(intent);
- assertNotLogged(uri + " exposed beyond app", mark);
+ final Uri goodUri = Uri.parse("content://com.example/foobar");
+ assertNoViolation(() -> {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setDataAndType(goodUri, "image/jpeg");
+ getContext().startActivity(intent);
+ });
}
public void testContentUriWithoutPermission() throws Exception {
@@ -133,19 +136,21 @@
.penaltyLog()
.build());
- long mark = System.currentTimeMillis();
final Uri uri = Uri.parse("content://com.example/foobar");
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setDataAndType(uri, "image/jpeg");
- getContext().startActivity(intent);
- assertLogged(uri + " exposed beyond app", mark);
+ assertViolation(uri + " exposed beyond app", () -> {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setDataAndType(uri, "image/jpeg");
+ getContext().startActivity(intent);
+ });
- mark = System.currentTimeMillis();
- intent = new Intent(Intent.ACTION_VIEW);
- intent.setDataAndType(uri, "image/jpeg");
- intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- getContext().startActivity(intent);
- assertNotLogged(uri + " exposed beyond app", mark);
+ assertNoViolation(() -> {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setDataAndType(uri, "image/jpeg");
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ getContext().startActivity(intent);
+ });
}
public void testUntaggedSocketsHttp() throws Exception {
@@ -159,18 +164,20 @@
.penaltyLog()
.build());
- long mark = System.currentTimeMillis();
- ((HttpURLConnection) new URL("http://example.com/").openConnection()).getResponseCode();
- assertLogged("Untagged socket detected", mark);
+ assertViolation("Untagged socket detected", () -> {
+ ((HttpURLConnection) new URL("http://example.com/").openConnection())
+ .getResponseCode();
+ });
- mark = System.currentTimeMillis();
- TrafficStats.setThreadStatsTag(0xDECAFBAD);
- try {
- ((HttpURLConnection) new URL("http://example.com/").openConnection()).getResponseCode();
- } finally {
- TrafficStats.clearThreadStatsTag();
- }
- assertNotLogged("Untagged socket detected", mark);
+ assertNoViolation(() -> {
+ TrafficStats.setThreadStatsTag(0xDECAFBAD);
+ try {
+ ((HttpURLConnection) new URL("http://example.com/").openConnection())
+ .getResponseCode();
+ } finally {
+ TrafficStats.clearThreadStatsTag();
+ }
+ });
}
public void testUntaggedSocketsRaw() throws Exception {
@@ -184,99 +191,95 @@
.penaltyLog()
.build());
- long mark = System.currentTimeMillis();
- TrafficStats.setThreadStatsTag(0xDECAFBAD);
- try (Socket socket = new Socket("example.com", 80)) {
- socket.getOutputStream().close();
- } finally {
- TrafficStats.clearThreadStatsTag();
- }
- assertNotLogged("Untagged socket detected", mark);
+ assertNoViolation(() -> {
+ TrafficStats.setThreadStatsTag(0xDECAFBAD);
+ try (Socket socket = new Socket("example.com", 80)) {
+ socket.getOutputStream().close();
+ } finally {
+ TrafficStats.clearThreadStatsTag();
+ }
+ });
- mark = System.currentTimeMillis();
- try (Socket socket = new Socket("example.com", 80)) {
- socket.getOutputStream().close();
- }
- assertLogged("Untagged socket detected", mark);
+ assertViolation("Untagged socket detected", () -> {
+ try (Socket socket = new Socket("example.com", 80)) {
+ socket.getOutputStream().close();
+ }
+ });
}
public void testRead() throws Exception {
final File test = File.createTempFile("foo", "bar");
final File dir = test.getParentFile();
- FileInputStream is = null;
- FileDescriptor fd = null;
+ final FileInputStream is = new FileInputStream(test);
+ final FileDescriptor fd = Os.open(test.getAbsolutePath(), OsConstants.O_RDONLY, 0600);
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.penaltyLog()
.build());
- SystemClock.sleep(1500);
-
- try (AssertDiskReadLogged l = new AssertDiskReadLogged()) {
+ assertViolation("StrictModeDiskReadViolation", () -> {
test.exists();
- }
- try (AssertDiskReadLogged l = new AssertDiskReadLogged()) {
+ });
+ assertViolation("StrictModeDiskReadViolation", () -> {
test.length();
- }
- try (AssertDiskReadLogged l = new AssertDiskReadLogged()) {
+ });
+ assertViolation("StrictModeDiskReadViolation", () -> {
dir.list();
- }
- try (AssertDiskReadLogged l = new AssertDiskReadLogged()) {
- is = new FileInputStream(test);
- }
- try (AssertDiskReadLogged l = new AssertDiskReadLogged()) {
+ });
+ assertViolation("StrictModeDiskReadViolation", () -> {
+ new FileInputStream(test);
+ });
+ assertViolation("StrictModeDiskReadViolation", () -> {
is.read();
- }
- try (AssertDiskReadLogged l = new AssertDiskReadLogged()) {
- fd = Os.open(test.getAbsolutePath(), OsConstants.O_RDONLY, 0600);
- }
- try (AssertDiskReadLogged l = new AssertDiskReadLogged()) {
+ });
+ assertViolation("StrictModeDiskReadViolation", () -> {
+ Os.open(test.getAbsolutePath(), OsConstants.O_RDONLY, 0600);
+ });
+ assertViolation("StrictModeDiskReadViolation", () -> {
Os.read(fd, new byte[10], 0, 1);
- }
+ });
}
public void testWrite() throws Exception {
- File file = null;
+ File file = File.createTempFile("foo", "bar");
- FileOutputStream os = null;
- FileDescriptor fd = null;
+ final FileOutputStream os = new FileOutputStream(file);
+ final FileDescriptor fd = Os.open(file.getAbsolutePath(), OsConstants.O_RDWR, 0600);
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskWrites()
.penaltyLog()
.build());
- SystemClock.sleep(1500);
-
- try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
- file = File.createTempFile("foo", "bar");
- }
- try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
+ assertViolation("StrictModeDiskWriteViolation", () -> {
+ File.createTempFile("foo", "bar");
+ });
+ assertViolation("StrictModeDiskWriteViolation", () -> {
file.delete();
- }
- try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
+ });
+ assertViolation("StrictModeDiskWriteViolation", () -> {
file.createNewFile();
- }
- try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
- os = new FileOutputStream(file);
- }
- try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
+ });
+ assertViolation("StrictModeDiskWriteViolation", () -> {
+ new FileOutputStream(file);
+ });
+ assertViolation("StrictModeDiskWriteViolation", () -> {
os.write(32);
- }
- try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
- fd = Os.open(file.getAbsolutePath(), OsConstants.O_RDWR, 0600);
- }
- try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
+ });
+ assertViolation("StrictModeDiskWriteViolation", () -> {
+ Os.open(file.getAbsolutePath(), OsConstants.O_RDWR, 0600);
+ });
+ assertViolation("StrictModeDiskWriteViolation", () -> {
Os.write(fd, new byte[10], 0, 1);
- }
- try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
+ });
+ assertViolation("StrictModeDiskWriteViolation", () -> {
Os.fsync(fd);
- }
- try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
+ });
+ assertViolation("StrictModeDiskWriteViolation", () -> {
file.renameTo(new File(file.getParent(), "foobar"));
- }
+ });
}
public void testNetwork() throws Exception {
@@ -290,75 +293,66 @@
.penaltyLog()
.build());
- long mark = System.currentTimeMillis();
- try (Socket socket = new Socket("example.com", 80)) {
- socket.getOutputStream().close();
- }
- assertLogged("StrictModeNetworkViolation", mark);
+ assertViolation("StrictModeNetworkViolation", () -> {
+ try (Socket socket = new Socket("example.com", 80)) {
+ socket.getOutputStream().close();
+ }
+ });
- mark = System.currentTimeMillis();
- ((HttpURLConnection) new URL("http://example.com/").openConnection()).getResponseCode();
- assertLogged("StrictModeNetworkViolation", mark);
+ assertViolation("StrictModeNetworkViolation", () -> {
+ ((HttpURLConnection) new URL("http://example.com/").openConnection())
+ .getResponseCode();
+ });
}
- private static class AssertLogged implements AutoCloseable {
- private final String mMessage;
- private final long mStart;
+ private static void assertViolation(String expected, ThrowingRunnable r) throws Exception {
+ final LinkedBlockingQueue<String> violations = new LinkedBlockingQueue<>();
+ StrictMode.setViolationListener(new ViolationListener() {
+ @Override
+ public void onViolation(String message) {
+ violations.add(message);
+ }
+ });
- public AssertLogged(String message) {
- mMessage = message;
- mStart = System.currentTimeMillis();
- }
-
- @Override
- public void close() throws Exception {
- assertLogged(mMessage, mStart);
+ try {
+ r.run();
+ while (true) {
+ final String violation = violations.poll(5, TimeUnit.SECONDS);
+ if (violation == null) {
+ fail("Expected violation not found: " + expected);
+ } else if (violation.contains(expected)) {
+ return;
+ }
+ }
+ } finally {
+ StrictMode.setViolationListener(null);
}
}
- private static class AssertDiskReadLogged extends AssertLogged {
- public AssertDiskReadLogged() {
- super("StrictModeDiskReadViolation");
+ private static void assertNoViolation(ThrowingRunnable r) throws Exception {
+ final LinkedBlockingQueue<String> violations = new LinkedBlockingQueue<>();
+ StrictMode.setViolationListener(new ViolationListener() {
+ @Override
+ public void onViolation(String message) {
+ violations.add(message);
+ }
+ });
+
+ try {
+ r.run();
+ while (true) {
+ final String violation = violations.poll(5, TimeUnit.SECONDS);
+ if (violation == null) {
+ return;
+ } else {
+ fail("Unexpected violation found: " + violation);
+ }
+ }
+ } finally {
+ StrictMode.setViolationListener(null);
}
}
- private static class AssertDiskWriteLogged extends AssertLogged {
- public AssertDiskWriteLogged() {
- super("StrictModeDiskWriteViolation");
- }
- }
-
- private static void assertLogged(String msg, long since) throws Exception {
- assertLogged(msg, since, 1100);
- }
-
- private static void assertLogged(String msg, long since, long wait) throws Exception {
- SystemClock.sleep(wait);
- assertTrue("Expected message not found: " + msg, readLogSince(since).contains(msg));
- }
-
- private static void assertNotLogged(String msg, long since) throws Exception {
- assertNotLogged(msg, since, 1100);
- }
-
- private static void assertNotLogged(String msg, long since, long wait) throws Exception {
- SystemClock.sleep(wait);
- assertFalse("Unexpected message found: " + msg, readLogSince(since).contains(msg));
- }
-
- private static String readLogSince(long millis) throws Exception {
- final SimpleDateFormat format = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
- final Process proc = new ProcessBuilder("logcat", "-t", format.format(new Date(millis)))
- .redirectErrorStream(true).start();
-
- final ByteArrayOutputStream buf = new ByteArrayOutputStream();
- Streams.copy(proc.getInputStream(), buf);
- final int res = proc.waitFor();
-
- Log.d(TAG, "Log output was " + buf.size() + " bytes, exit code " + res);
- return new String(buf.toByteArray());
- }
-
private boolean hasInternetConnection() {
final PackageManager pm = getContext().getPackageManager();
return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)