Merge "CTS: Break out classloader tests from appsecurity"
diff --git a/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/Android.mk b/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/Android.mk
deleted file mode 100644
index 1adf0f8..0000000
--- a/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/Android.mk
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_EXPORT_PACKAGE_RESOURCES := true
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsClassloaderSplitApp
-
-# Tag this module as a cts test artifact
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
-
-include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_a/Android.mk b/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_a/Android.mk
deleted file mode 100644
index f37be44..0000000
--- a/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_a/Android.mk
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-LOCAL_MODULE_TAGS := tests
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_EXPORT_PACKAGE_RESOURCES := true
-LOCAL_PACKAGE_NAME := CtsClassloaderSplitAppFeatureA
-LOCAL_SDK_VERSION := current
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_APK_LIBRARIES := CtsClassloaderSplitApp
-LOCAL_RES_LIBRARIES := $(LOCAL_APK_LIBRARIES)
-
-LOCAL_AAPT_FLAGS += --custom-package com.android.cts.classloadersplitapp.feature_a
-LOCAL_AAPT_FLAGS += --package-id 0x80
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_b/Android.mk b/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_b/Android.mk
deleted file mode 100644
index 3262e15..0000000
--- a/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_b/Android.mk
+++ /dev/null
@@ -1,34 +0,0 @@
-#
-# 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-LOCAL_MODULE_TAGS := tests
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_PACKAGE_NAME := CtsClassloaderSplitAppFeatureB
-LOCAL_SDK_VERSION := current
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_APK_LIBRARIES := CtsClassloaderSplitApp CtsClassloaderSplitAppFeatureA
-LOCAL_RES_LIBRARIES := $(LOCAL_APK_LIBRARIES)
-
-LOCAL_AAPT_FLAGS := --custom-package com.android.cts.classloadersplitapp.feature_b
-LOCAL_AAPT_FLAGS += --package-id 0x81
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/UsesLibraryApp/Android.mk b/hostsidetests/appsecurity/test-apps/UsesLibraryApp/Android.mk
deleted file mode 100644
index df12f82..0000000
--- a/hostsidetests/appsecurity/test-apps/UsesLibraryApp/Android.mk
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# Copyright (C) 2015 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_SDK_VERSION := current
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test compatibility-device-util ctstestrunner ub-uiautomator
-
-LOCAL_JAVA_LIBRARIES := android.test.base.stubs
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src) \
- ../ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java
-
-LOCAL_PACKAGE_NAME := CtsUsesLibraryApp
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey2
-
-LOCAL_PROGUARD_ENABLED := disabled
-LOCAL_DEX_PREOPT := false
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/classloaders/splits/Android.bp b/hostsidetests/classloaders/splits/Android.bp
new file mode 100644
index 0000000..17f02a7
--- /dev/null
+++ b/hostsidetests/classloaders/splits/Android.bp
@@ -0,0 +1,34 @@
+// Copyright (C) 2019 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.
+
+java_test_host {
+ name: "CtsClassloaderSplitsHostTestCases",
+ defaults: [ "cts_defaults" ],
+ srcs: [ "src/**/*.java" ],
+ libs: [
+ "compatibility-host-util",
+ "cts-tradefed",
+ "tradefed",
+ ],
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ required: [
+ "CtsClassloaderSplitApp",
+ "CtsClassloaderSplitAppFeatureA",
+ "CtsClassloaderSplitAppFeatureB",
+ ],
+}
diff --git a/hostsidetests/classloaders/splits/AndroidTest.xml b/hostsidetests/classloaders/splits/AndroidTest.xml
new file mode 100644
index 0000000..77b5bce
--- /dev/null
+++ b/hostsidetests/classloaders/splits/AndroidTest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+<configuration description="Config for the CTS Classloader Splits host tests">
+ <option name="test-suite-tag" value="cts" />
+ <option name="config-descriptor:metadata" key="component" value="framework" />
+ <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+ <option name="jar" value="CtsClassloaderSplitsHostTestCases.jar" />
+ <option name="runtime-hint" value="1m" />
+ </test>
+</configuration>
diff --git a/hostsidetests/classloaders/splits/TEST_MAPPING b/hostsidetests/classloaders/splits/TEST_MAPPING
new file mode 100644
index 0000000..18f00dd
--- /dev/null
+++ b/hostsidetests/classloaders/splits/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsClassloaderSplitsHostTestCases"
+ }
+ ]
+}
diff --git a/hostsidetests/classloaders/splits/apps/Android.bp b/hostsidetests/classloaders/splits/apps/Android.bp
new file mode 100644
index 0000000..ebd9318
--- /dev/null
+++ b/hostsidetests/classloaders/splits/apps/Android.bp
@@ -0,0 +1,29 @@
+// Copyright (C) 2019 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.
+
+android_test {
+ name: "CtsClassloaderSplitApp",
+ defaults: [ "cts_support_defaults" ],
+ sdk_version: "current",
+ srcs: ["src/**/*.java"],
+ static_libs: [
+ "android-support-test",
+ "ctstestrunner",
+ ],
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/AndroidManifest.xml b/hostsidetests/classloaders/splits/apps/AndroidManifest.xml
similarity index 100%
rename from hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/AndroidManifest.xml
rename to hostsidetests/classloaders/splits/apps/AndroidManifest.xml
diff --git a/hostsidetests/classloaders/splits/apps/feature_a/Android.bp b/hostsidetests/classloaders/splits/apps/feature_a/Android.bp
new file mode 100644
index 0000000..0fd7091
--- /dev/null
+++ b/hostsidetests/classloaders/splits/apps/feature_a/Android.bp
@@ -0,0 +1,32 @@
+// Copyright (C) 2019 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.
+
+android_test_helper_app {
+ name: "CtsClassloaderSplitAppFeatureA",
+ defaults: [ "cts_support_defaults" ],
+ sdk_version: "current",
+ srcs: [ "src/**/*.java" ],
+ libs: [ "CtsClassloaderSplitApp" ],
+ aaptflags: [
+ "--custom-package",
+ "com.android.cts.classloadersplitapp.feature_a",
+ "--package-id",
+ "0x80",
+ ],
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_a/AndroidManifest.xml b/hostsidetests/classloaders/splits/apps/feature_a/AndroidManifest.xml
similarity index 100%
rename from hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_a/AndroidManifest.xml
rename to hostsidetests/classloaders/splits/apps/feature_a/AndroidManifest.xml
diff --git a/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_a/src/com/android/cts/classloadersplitapp/feature_a/FeatureAActivity.java b/hostsidetests/classloaders/splits/apps/feature_a/src/com/android/cts/classloadersplitapp/feature_a/FeatureAActivity.java
similarity index 100%
rename from hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_a/src/com/android/cts/classloadersplitapp/feature_a/FeatureAActivity.java
rename to hostsidetests/classloaders/splits/apps/feature_a/src/com/android/cts/classloadersplitapp/feature_a/FeatureAActivity.java
diff --git a/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_a/src/com/android/cts/classloadersplitapp/feature_a/FeatureAReceiver.java b/hostsidetests/classloaders/splits/apps/feature_a/src/com/android/cts/classloadersplitapp/feature_a/FeatureAReceiver.java
similarity index 100%
rename from hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_a/src/com/android/cts/classloadersplitapp/feature_a/FeatureAReceiver.java
rename to hostsidetests/classloaders/splits/apps/feature_a/src/com/android/cts/classloadersplitapp/feature_a/FeatureAReceiver.java
diff --git a/hostsidetests/classloaders/splits/apps/feature_b/Android.bp b/hostsidetests/classloaders/splits/apps/feature_b/Android.bp
new file mode 100644
index 0000000..2643840
--- /dev/null
+++ b/hostsidetests/classloaders/splits/apps/feature_b/Android.bp
@@ -0,0 +1,35 @@
+// Copyright (C) 2019 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.
+
+android_test_helper_app {
+ name: "CtsClassloaderSplitAppFeatureB",
+ defaults: [ "cts_support_defaults" ],
+ sdk_version: "current",
+ srcs: [ "src/**/*.java" ],
+ libs: [
+ "CtsClassloaderSplitApp",
+ "CtsClassloaderSplitAppFeatureA",
+ ],
+ aaptflags: [
+ "--custom-package",
+ "com.android.cts.classloadersplitapp.feature_a",
+ "--package-id",
+ "0x81",
+ ],
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_b/AndroidManifest.xml b/hostsidetests/classloaders/splits/apps/feature_b/AndroidManifest.xml
similarity index 100%
rename from hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_b/AndroidManifest.xml
rename to hostsidetests/classloaders/splits/apps/feature_b/AndroidManifest.xml
diff --git a/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_b/res/values-pl/values.xml b/hostsidetests/classloaders/splits/apps/feature_b/res/values-pl/values.xml
similarity index 100%
rename from hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_b/res/values-pl/values.xml
rename to hostsidetests/classloaders/splits/apps/feature_b/res/values-pl/values.xml
diff --git a/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_b/res/values/values.xml b/hostsidetests/classloaders/splits/apps/feature_b/res/values/values.xml
similarity index 100%
rename from hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_b/res/values/values.xml
rename to hostsidetests/classloaders/splits/apps/feature_b/res/values/values.xml
diff --git a/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_b/src/com/android/cts/classloadersplitapp/feature_b/FeatureBActivity.java b/hostsidetests/classloaders/splits/apps/feature_b/src/com/android/cts/classloadersplitapp/feature_b/FeatureBActivity.java
similarity index 100%
rename from hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_b/src/com/android/cts/classloadersplitapp/feature_b/FeatureBActivity.java
rename to hostsidetests/classloaders/splits/apps/feature_b/src/com/android/cts/classloadersplitapp/feature_b/FeatureBActivity.java
diff --git a/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_b/src/com/android/cts/classloadersplitapp/feature_b/FeatureBReceiver.java b/hostsidetests/classloaders/splits/apps/feature_b/src/com/android/cts/classloadersplitapp/feature_b/FeatureBReceiver.java
similarity index 100%
rename from hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_b/src/com/android/cts/classloadersplitapp/feature_b/FeatureBReceiver.java
rename to hostsidetests/classloaders/splits/apps/feature_b/src/com/android/cts/classloadersplitapp/feature_b/FeatureBReceiver.java
diff --git a/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/src/com/android/cts/classloadersplitapp/BaseActivity.java b/hostsidetests/classloaders/splits/apps/src/com/android/cts/classloadersplitapp/BaseActivity.java
similarity index 100%
rename from hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/src/com/android/cts/classloadersplitapp/BaseActivity.java
rename to hostsidetests/classloaders/splits/apps/src/com/android/cts/classloadersplitapp/BaseActivity.java
diff --git a/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/src/com/android/cts/classloadersplitapp/BaseReceiver.java b/hostsidetests/classloaders/splits/apps/src/com/android/cts/classloadersplitapp/BaseReceiver.java
similarity index 100%
rename from hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/src/com/android/cts/classloadersplitapp/BaseReceiver.java
rename to hostsidetests/classloaders/splits/apps/src/com/android/cts/classloadersplitapp/BaseReceiver.java
diff --git a/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/src/com/android/cts/classloadersplitapp/SplitAppTest.java b/hostsidetests/classloaders/splits/apps/src/com/android/cts/classloadersplitapp/SplitAppTest.java
similarity index 100%
rename from hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/src/com/android/cts/classloadersplitapp/SplitAppTest.java
rename to hostsidetests/classloaders/splits/apps/src/com/android/cts/classloadersplitapp/SplitAppTest.java
diff --git a/hostsidetests/classloaders/splits/src/android/classloaders/cts/BaseInstallMultiple.java b/hostsidetests/classloaders/splits/src/android/classloaders/cts/BaseInstallMultiple.java
new file mode 100644
index 0000000..f5170e9
--- /dev/null
+++ b/hostsidetests/classloaders/splits/src/android/classloaders/cts/BaseInstallMultiple.java
@@ -0,0 +1,187 @@
+/*
+ * 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.classloaders.cts;
+
+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.testtype.IAbi;
+import com.android.tradefed.util.AbiUtils;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Base class for invoking the install-multiple command via ADB. Subclass this for less typing:
+ *
+ * <code>
+ * private class InstallMultiple extends BaseInstallMultiple<InstallMultiple> {
+ * public InstallMultiple() {
+ * super(getDevice(), null, null);
+ * }
+ * }
+ * </code>
+ */
+public class BaseInstallMultiple<T extends BaseInstallMultiple<?>> {
+ private final ITestDevice mDevice;
+ private final IBuildInfo mBuild;
+ private final IAbi mAbi;
+
+ private final List<String> mArgs = new ArrayList<>();
+ private final List<File> mApks = new ArrayList<>();
+ private boolean mUseNaturalAbi;
+
+ public BaseInstallMultiple(ITestDevice device, IBuildInfo buildInfo, IAbi abi) {
+ mDevice = device;
+ mBuild = buildInfo;
+ mAbi = abi;
+ addArg("-g");
+ }
+
+ T addArg(String arg) {
+ mArgs.add(arg);
+ return (T) this;
+ }
+
+ T addApk(String apk) throws FileNotFoundException {
+ CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuild);
+ mApks.add(buildHelper.getTestFile(apk));
+ return (T) this;
+ }
+
+ T inheritFrom(String packageName) {
+ addArg("-r");
+ addArg("-p " + packageName);
+ return (T) this;
+ }
+
+ T useNaturalAbi() {
+ mUseNaturalAbi = true;
+ return (T) this;
+ }
+
+ T allowTest() {
+ addArg("-t");
+ return (T) this;
+ }
+
+ T locationAuto() {
+ addArg("--install-location 0");
+ return (T) this;
+ }
+
+ T locationInternalOnly() {
+ addArg("--install-location 1");
+ return (T) this;
+ }
+
+ T locationPreferExternal() {
+ addArg("--install-location 2");
+ return (T) this;
+ }
+
+ T forceUuid(String uuid) {
+ addArg("--force-uuid " + uuid);
+ return (T) this;
+ }
+
+ T forUser(int userId) {
+ addArg("--user " + userId);
+ return (T) this;
+ }
+
+ void run() throws DeviceNotAvailableException {
+ run(true, null);
+ }
+
+ void runExpectingFailure() throws DeviceNotAvailableException {
+ run(false, null);
+ }
+
+ void runExpectingFailure(String failure) throws DeviceNotAvailableException {
+ run(false, failure);
+ }
+
+ private void run(boolean expectingSuccess, String failure) throws DeviceNotAvailableException {
+ final ITestDevice device = mDevice;
+
+ // Create an install session
+ final StringBuilder cmd = new StringBuilder();
+ cmd.append("pm install-create");
+ for (String arg : mArgs) {
+ cmd.append(' ').append(arg);
+ }
+ if (!mUseNaturalAbi && mAbi != null) {
+ cmd.append(' ').append(AbiUtils.createAbiFlag(mAbi.getName()));
+ }
+
+ String result = device.executeShellCommand(cmd.toString());
+ TestCase.assertTrue(result, result.startsWith("Success"));
+
+ final int start = result.lastIndexOf("[");
+ final int end = result.lastIndexOf("]");
+ int sessionId = -1;
+ try {
+ if (start != -1 && end != -1 && start < end) {
+ sessionId = Integer.parseInt(result.substring(start + 1, end));
+ }
+ } catch (NumberFormatException e) {
+ }
+ if (sessionId == -1) {
+ throw new IllegalStateException("Failed to create install session: " + result);
+ }
+
+ // Push our files into session. Ideally we'd use stdin streaming,
+ // but ddmlib doesn't support it yet.
+ for (int i = 0; i < mApks.size(); i++) {
+ final File apk = mApks.get(i);
+ final String remotePath = "/data/local/tmp/" + i + "_" + apk.getName();
+ if (!device.pushFile(apk, remotePath)) {
+ throw new IllegalStateException("Failed to push " + apk);
+ }
+
+ cmd.setLength(0);
+ cmd.append("pm install-write");
+ cmd.append(' ').append(sessionId);
+ cmd.append(' ').append(i + "_" + apk.getName());
+ cmd.append(' ').append(remotePath);
+
+ result = device.executeShellCommand(cmd.toString());
+ TestCase.assertTrue(result, result.startsWith("Success"));
+ }
+
+ // Everything staged; let's pull trigger
+ cmd.setLength(0);
+ cmd.append("pm install-commit");
+ cmd.append(' ').append(sessionId);
+
+ result = device.executeShellCommand(cmd.toString()).trim();
+ if (failure == null) {
+ if (expectingSuccess) {
+ TestCase.assertTrue(result, result.startsWith("Success"));
+ } else {
+ TestCase.assertFalse(result, result.startsWith("Success"));
+ }
+ } else {
+ TestCase.assertTrue(result, result.contains(failure));
+ }
+ }
+}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ClassloaderSplitsTest.java b/hostsidetests/classloaders/splits/src/android/classloaders/cts/ClassloaderSplitsTest.java
similarity index 89%
rename from hostsidetests/appsecurity/src/android/appsecurity/cts/ClassloaderSplitsTest.java
rename to hostsidetests/classloaders/splits/src/android/classloaders/cts/ClassloaderSplitsTest.java
index 4e54bc4..1460bfc 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ClassloaderSplitsTest.java
+++ b/hostsidetests/classloaders/splits/src/android/classloaders/cts/ClassloaderSplitsTest.java
@@ -13,11 +13,12 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
-package android.appsecurity.cts;
+package android.classloaders.cts;
import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.AppModeInstant;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import org.junit.After;
import org.junit.Before;
@@ -25,7 +26,7 @@
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class ClassloaderSplitsTest extends BaseAppSecurityTest {
+public class ClassloaderSplitsTest extends BaseHostJUnit4Test {
private static final String PKG = "com.android.cts.classloadersplitapp";
private static final String TEST_CLASS = PKG + ".SplitAppTest";
@@ -47,7 +48,6 @@
@Before
public void setUp() throws Exception {
- Utils.prepareSingleUser(getDevice());
getDevice().uninstallPackage(PKG);
}
@@ -116,4 +116,14 @@
runDeviceTests(getDevice(), PKG, TEST_CLASS, "testBaseClassLoader");
runDeviceTests(getDevice(), PKG, TEST_CLASS, "testAllReceivers");
}
+
+ protected class InstallMultiple extends BaseInstallMultiple<InstallMultiple> {
+ public InstallMultiple() {
+ this(false);
+ }
+ public InstallMultiple(boolean instant) {
+ super(getDevice(), getBuild(), getAbi());
+ addArg(instant ? "--instant" : "");
+ }
+ }
}
diff --git a/hostsidetests/classloaders/useslibrary/Android.bp b/hostsidetests/classloaders/useslibrary/Android.bp
new file mode 100644
index 0000000..603b2ec
--- /dev/null
+++ b/hostsidetests/classloaders/useslibrary/Android.bp
@@ -0,0 +1,30 @@
+// Copyright (C) 2019 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.
+
+java_test_host {
+ name: "CtsUsesLibraryHostTestCases",
+ defaults: [ "cts_defaults" ],
+ srcs: [ "src/**/*.java" ],
+ libs: [
+ "compatibility-host-util",
+ "cts-tradefed",
+ "tradefed",
+ ],
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ required: [ "CtsUsesLibraryApp" ],
+}
diff --git a/hostsidetests/classloaders/useslibrary/AndroidTest.xml b/hostsidetests/classloaders/useslibrary/AndroidTest.xml
new file mode 100644
index 0000000..b7796d7
--- /dev/null
+++ b/hostsidetests/classloaders/useslibrary/AndroidTest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+<configuration description="Config for the CTS UsesLibrary host tests">
+ <option name="test-suite-tag" value="cts" />
+ <option name="config-descriptor:metadata" key="component" value="framework" />
+ <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+ <option name="jar" value="CtsUsesLibraryHostTestCases.jar" />
+ <option name="runtime-hint" value="1m" />
+ </test>
+</configuration>
diff --git a/hostsidetests/classloaders/useslibrary/TEST_MAPPING b/hostsidetests/classloaders/useslibrary/TEST_MAPPING
new file mode 100644
index 0000000..72ef61b
--- /dev/null
+++ b/hostsidetests/classloaders/useslibrary/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsUsesLibraryHostTestCases"
+ }
+ ]
+}
diff --git a/hostsidetests/classloaders/useslibrary/app/Android.bp b/hostsidetests/classloaders/useslibrary/app/Android.bp
new file mode 100644
index 0000000..faf7a22
--- /dev/null
+++ b/hostsidetests/classloaders/useslibrary/app/Android.bp
@@ -0,0 +1,32 @@
+// Copyright (C) 2019 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.
+
+android_test {
+ name: "CtsUsesLibraryApp",
+ defaults: [ "cts_support_defaults" ],
+ sdk_version: "current",
+ srcs: ["src/**/*.java"],
+ libs: [
+ "android.test.base.stubs",
+ ],
+ static_libs: [
+ "android-support-test",
+ "ctstestrunner",
+ ],
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/hostsidetests/appsecurity/test-apps/UsesLibraryApp/AndroidManifest.xml b/hostsidetests/classloaders/useslibrary/app/AndroidManifest.xml
similarity index 100%
rename from hostsidetests/appsecurity/test-apps/UsesLibraryApp/AndroidManifest.xml
rename to hostsidetests/classloaders/useslibrary/app/AndroidManifest.xml
diff --git a/hostsidetests/appsecurity/test-apps/UsesLibraryApp/src/com/android/cts/useslibrary/UsesLibraryTest.java b/hostsidetests/classloaders/useslibrary/app/src/com/android/cts/useslibrary/UsesLibraryTest.java
similarity index 95%
rename from hostsidetests/appsecurity/test-apps/UsesLibraryApp/src/com/android/cts/useslibrary/UsesLibraryTest.java
rename to hostsidetests/classloaders/useslibrary/app/src/com/android/cts/useslibrary/UsesLibraryTest.java
index 73b820d..7fa8b20 100644
--- a/hostsidetests/appsecurity/test-apps/UsesLibraryApp/src/com/android/cts/useslibrary/UsesLibraryTest.java
+++ b/hostsidetests/classloaders/useslibrary/app/src/com/android/cts/useslibrary/UsesLibraryTest.java
@@ -16,11 +16,6 @@
package com.android.cts.useslibrary;
-import android.content.pm.PackageManager;
-import android.os.Environment;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject;
-import android.support.test.uiautomator.UiSelector;
import android.test.InstrumentationTestCase;
import dalvik.system.BaseDexClassLoader;
diff --git a/hostsidetests/classloaders/useslibrary/src/android/classloaders/cts/BaseInstallMultiple.java b/hostsidetests/classloaders/useslibrary/src/android/classloaders/cts/BaseInstallMultiple.java
new file mode 100644
index 0000000..f5170e9
--- /dev/null
+++ b/hostsidetests/classloaders/useslibrary/src/android/classloaders/cts/BaseInstallMultiple.java
@@ -0,0 +1,187 @@
+/*
+ * 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.classloaders.cts;
+
+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.testtype.IAbi;
+import com.android.tradefed.util.AbiUtils;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Base class for invoking the install-multiple command via ADB. Subclass this for less typing:
+ *
+ * <code>
+ * private class InstallMultiple extends BaseInstallMultiple<InstallMultiple> {
+ * public InstallMultiple() {
+ * super(getDevice(), null, null);
+ * }
+ * }
+ * </code>
+ */
+public class BaseInstallMultiple<T extends BaseInstallMultiple<?>> {
+ private final ITestDevice mDevice;
+ private final IBuildInfo mBuild;
+ private final IAbi mAbi;
+
+ private final List<String> mArgs = new ArrayList<>();
+ private final List<File> mApks = new ArrayList<>();
+ private boolean mUseNaturalAbi;
+
+ public BaseInstallMultiple(ITestDevice device, IBuildInfo buildInfo, IAbi abi) {
+ mDevice = device;
+ mBuild = buildInfo;
+ mAbi = abi;
+ addArg("-g");
+ }
+
+ T addArg(String arg) {
+ mArgs.add(arg);
+ return (T) this;
+ }
+
+ T addApk(String apk) throws FileNotFoundException {
+ CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuild);
+ mApks.add(buildHelper.getTestFile(apk));
+ return (T) this;
+ }
+
+ T inheritFrom(String packageName) {
+ addArg("-r");
+ addArg("-p " + packageName);
+ return (T) this;
+ }
+
+ T useNaturalAbi() {
+ mUseNaturalAbi = true;
+ return (T) this;
+ }
+
+ T allowTest() {
+ addArg("-t");
+ return (T) this;
+ }
+
+ T locationAuto() {
+ addArg("--install-location 0");
+ return (T) this;
+ }
+
+ T locationInternalOnly() {
+ addArg("--install-location 1");
+ return (T) this;
+ }
+
+ T locationPreferExternal() {
+ addArg("--install-location 2");
+ return (T) this;
+ }
+
+ T forceUuid(String uuid) {
+ addArg("--force-uuid " + uuid);
+ return (T) this;
+ }
+
+ T forUser(int userId) {
+ addArg("--user " + userId);
+ return (T) this;
+ }
+
+ void run() throws DeviceNotAvailableException {
+ run(true, null);
+ }
+
+ void runExpectingFailure() throws DeviceNotAvailableException {
+ run(false, null);
+ }
+
+ void runExpectingFailure(String failure) throws DeviceNotAvailableException {
+ run(false, failure);
+ }
+
+ private void run(boolean expectingSuccess, String failure) throws DeviceNotAvailableException {
+ final ITestDevice device = mDevice;
+
+ // Create an install session
+ final StringBuilder cmd = new StringBuilder();
+ cmd.append("pm install-create");
+ for (String arg : mArgs) {
+ cmd.append(' ').append(arg);
+ }
+ if (!mUseNaturalAbi && mAbi != null) {
+ cmd.append(' ').append(AbiUtils.createAbiFlag(mAbi.getName()));
+ }
+
+ String result = device.executeShellCommand(cmd.toString());
+ TestCase.assertTrue(result, result.startsWith("Success"));
+
+ final int start = result.lastIndexOf("[");
+ final int end = result.lastIndexOf("]");
+ int sessionId = -1;
+ try {
+ if (start != -1 && end != -1 && start < end) {
+ sessionId = Integer.parseInt(result.substring(start + 1, end));
+ }
+ } catch (NumberFormatException e) {
+ }
+ if (sessionId == -1) {
+ throw new IllegalStateException("Failed to create install session: " + result);
+ }
+
+ // Push our files into session. Ideally we'd use stdin streaming,
+ // but ddmlib doesn't support it yet.
+ for (int i = 0; i < mApks.size(); i++) {
+ final File apk = mApks.get(i);
+ final String remotePath = "/data/local/tmp/" + i + "_" + apk.getName();
+ if (!device.pushFile(apk, remotePath)) {
+ throw new IllegalStateException("Failed to push " + apk);
+ }
+
+ cmd.setLength(0);
+ cmd.append("pm install-write");
+ cmd.append(' ').append(sessionId);
+ cmd.append(' ').append(i + "_" + apk.getName());
+ cmd.append(' ').append(remotePath);
+
+ result = device.executeShellCommand(cmd.toString());
+ TestCase.assertTrue(result, result.startsWith("Success"));
+ }
+
+ // Everything staged; let's pull trigger
+ cmd.setLength(0);
+ cmd.append("pm install-commit");
+ cmd.append(' ').append(sessionId);
+
+ result = device.executeShellCommand(cmd.toString()).trim();
+ if (failure == null) {
+ if (expectingSuccess) {
+ TestCase.assertTrue(result, result.startsWith("Success"));
+ } else {
+ TestCase.assertFalse(result, result.startsWith("Success"));
+ }
+ } else {
+ TestCase.assertTrue(result, result.contains(failure));
+ }
+ }
+}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/UsesLibraryHostTest.java b/hostsidetests/classloaders/useslibrary/src/android/classloaders/cts/UsesLibraryHostTest.java
similarity index 84%
rename from hostsidetests/appsecurity/src/android/appsecurity/cts/UsesLibraryHostTest.java
rename to hostsidetests/classloaders/useslibrary/src/android/classloaders/cts/UsesLibraryHostTest.java
index 41ce7a1..aecd87b 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/UsesLibraryHostTest.java
+++ b/hostsidetests/classloaders/useslibrary/src/android/classloaders/cts/UsesLibraryHostTest.java
@@ -14,12 +14,13 @@
* limitations under the License.
*/
-package android.appsecurity.cts;
+package android.classloaders.cts;
import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.AppModeInstant;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import org.junit.After;
import org.junit.Before;
@@ -32,7 +33,7 @@
*/
@AppModeFull(reason = "TODO verify whether or not these should run in instant mode")
@RunWith(DeviceJUnit4ClassRunner.class)
-public class UsesLibraryHostTest extends BaseAppSecurityTest {
+public class UsesLibraryHostTest extends BaseHostJUnit4Test {
private static final String PKG = "com.android.cts.useslibrary";
private static final String APK = "CtsUsesLibraryApp.apk";
@@ -79,4 +80,14 @@
new InstallMultiple(instant).addApk(APK).run();
Utils.runDeviceTests(getDevice(), PKG, ".UsesLibraryTest", "testDuplicateLibrary");
}
+
+ protected class InstallMultiple extends BaseInstallMultiple<InstallMultiple> {
+ public InstallMultiple() {
+ this(false);
+ }
+ public InstallMultiple(boolean instant) {
+ super(getDevice(), getBuild(), getAbi());
+ addArg(instant ? "--instant" : "");
+ }
+ }
}
diff --git a/hostsidetests/classloaders/useslibrary/src/android/classloaders/cts/Utils.java b/hostsidetests/classloaders/useslibrary/src/android/classloaders/cts/Utils.java
new file mode 100644
index 0000000..48497d8
--- /dev/null
+++ b/hostsidetests/classloaders/useslibrary/src/android/classloaders/cts/Utils.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2014 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.classloaders.cts;
+
+import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
+import com.android.ddmlib.testrunner.TestResult.TestStatus;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestDescription;
+import com.android.tradefed.result.TestResult;
+import com.android.tradefed.result.TestRunResult;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+public class Utils {
+ public static final int USER_SYSTEM = 0;
+
+ public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
+ String testMethodName) throws DeviceNotAvailableException {
+ runDeviceTests(device, packageName, testClassName, testMethodName, USER_SYSTEM, null);
+ }
+
+ public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
+ String testMethodName, Map<String, String> testArgs)
+ throws DeviceNotAvailableException {
+ runDeviceTests(device, packageName, testClassName, testMethodName, USER_SYSTEM, testArgs);
+ }
+
+ public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
+ String testMethodName, int userId) throws DeviceNotAvailableException {
+ runDeviceTests(device, packageName, testClassName, testMethodName, userId, null);
+ }
+
+ public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
+ String testMethodName, int userId, Map<String, String> testArgs)
+ throws DeviceNotAvailableException {
+ // 60 min timeout per test by default
+ runDeviceTests(device, packageName, testClassName, testMethodName, userId, testArgs,
+ 60L, TimeUnit.MINUTES);
+ }
+
+ public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
+ String testMethodName, int userId, Map<String, String> testArgs, long timeout,
+ TimeUnit unit)
+ throws DeviceNotAvailableException {
+ if (testClassName != null && testClassName.startsWith(".")) {
+ testClassName = packageName + testClassName;
+ }
+ RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(packageName,
+ "android.support.test.runner.AndroidJUnitRunner", device.getIDevice());
+ // timeout_msec is the timeout per test for instrumentation
+ testRunner.addInstrumentationArg("timeout_msec", Long.toString(unit.toMillis(timeout)));
+ if (testClassName != null && testMethodName != null) {
+ testRunner.setMethodName(testClassName, testMethodName);
+ } else if (testClassName != null) {
+ testRunner.setClassName(testClassName);
+ }
+
+ if (testArgs != null && testArgs.size() > 0) {
+ for (String name : testArgs.keySet()) {
+ final String value = testArgs.get(name);
+ testRunner.addInstrumentationArg(name, value);
+ }
+ }
+ final CollectingTestListener listener = new CollectingTestListener();
+ device.runInstrumentationTestsAsUser(testRunner, userId, listener);
+
+ final TestRunResult result = listener.getCurrentRunResults();
+ if (result.isRunFailure()) {
+ throw new AssertionError("Failed to successfully run device tests for "
+ + result.getName() + ": " + result.getRunFailureMessage());
+ }
+ if (result.getNumTests() == 0) {
+ throw new AssertionError("No tests were run on the device");
+ }
+ if (result.hasFailedTests()) {
+ // build a meaningful error message
+ StringBuilder errorBuilder = new StringBuilder("on-device tests failed:\n");
+ for (Map.Entry<TestDescription, TestResult> resultEntry :
+ result.getTestResults().entrySet()) {
+ if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
+ errorBuilder.append(resultEntry.getKey().toString());
+ errorBuilder.append(":\n");
+ errorBuilder.append(resultEntry.getValue().getStackTrace());
+ }
+ }
+ throw new AssertionError(errorBuilder.toString());
+ }
+ }
+
+ /**
+ * Prepare and return a single user relevant for testing.
+ */
+ public static int[] prepareSingleUser(ITestDevice device)
+ throws DeviceNotAvailableException {
+ return prepareMultipleUsers(device, 1);
+ }
+
+ /**
+ * Prepare and return two users relevant for testing.
+ */
+ public static int[] prepareMultipleUsers(ITestDevice device)
+ throws DeviceNotAvailableException {
+ return prepareMultipleUsers(device, 2);
+ }
+
+ /**
+ * Prepare and return multiple users relevant for testing.
+ */
+ public static int[] prepareMultipleUsers(ITestDevice device, int maxUsers)
+ throws DeviceNotAvailableException {
+ 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]);
+ }
+ }
+ if (userIds.length > maxUsers) {
+ return Arrays.copyOf(userIds, maxUsers);
+ } else {
+ return userIds;
+ }
+ }
+
+ public static int[] getAllUsers(ITestDevice device)
+ throws DeviceNotAvailableException {
+ 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;
+ }
+}