Merge "Logging for linkify selections"
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index cc2aad9..3fdd96e 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -6,6 +6,7 @@
tests/tests/animation/
tests/tests/print/
tests/tests/text/
+ tests/tests/graphics/
tests/tests/transition/
tests/tests/view/
tests/tests/widget/
diff --git a/apps/CameraITS/build/envsetup.sh b/apps/CameraITS/build/envsetup.sh
index 13c907c..a21108e 100644
--- a/apps/CameraITS/build/envsetup.sh
+++ b/apps/CameraITS/build/envsetup.sh
@@ -31,12 +31,19 @@
python -V 2>&1 | grep -q "Python 2.7" || \
echo ">> Require python 2.7" >&2
-for M in numpy PIL Image matplotlib pylab scipy.stats scipy.spatial
+for M in numpy PIL matplotlib scipy.stats scipy.spatial
do
python -c "import $M" >/dev/null 2>&1 || \
echo ">> Require Python $M module" >&2
done
+for N in 'PIL Image' 'matplotlib pylab'
+do
+ IFS=' ' read module submodule <<< "$N"
+ python -c "from $module import $submodule" >/dev/null 2>&1 || \
+ echo ">> Require Python $module module $submodule submodule" >&2
+done
+
CV2_VER=$(python -c "\
try:
import cv2
diff --git a/apps/CameraITS/pymodules/its/device.py b/apps/CameraITS/pymodules/its/device.py
index 7a20877..4f35b7a 100644
--- a/apps/CameraITS/pymodules/its/device.py
+++ b/apps/CameraITS/pymodules/its/device.py
@@ -119,10 +119,10 @@
try:
socket_lock.bind((ItsSession.IPADDR, ItsSession.LOCK_PORT))
break
- except socket.error:
+ except socket.error or socket.timeout:
if i == NUM_RETRIES - 1:
raise its.error.Error(self.device_id,
- "acquiring socket lock timed out")
+ "socket lock returns error")
else:
time.sleep(RETRY_WAIT_TIME_SEC)
diff --git a/apps/CameraITS/tests/scene2/scene2_0.67_scaled.pdf b/apps/CameraITS/tests/scene2/scene2_0.67_scaled.pdf
index 5e7128b..7b64817 100644
--- a/apps/CameraITS/tests/scene2/scene2_0.67_scaled.pdf
+++ b/apps/CameraITS/tests/scene2/scene2_0.67_scaled.pdf
Binary files differ
diff --git a/apps/CameraITS/tools/run_all_tests.py b/apps/CameraITS/tools/run_all_tests.py
index 17d49ec..e4c20a8 100644
--- a/apps/CameraITS/tools/run_all_tests.py
+++ b/apps/CameraITS/tools/run_all_tests.py
@@ -65,6 +65,7 @@
with open(err_file_path, 'r') as ferr:
for line in ferr:
if (line.find('socket.error') != -1 or
+ line.find('socket.timeout') != -1 or
line.find('Problem with socket') != -1):
socket_fail = True
return socket_fail
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 6753d6c..c50c259 100755
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -999,7 +999,7 @@
<string name="usb_tapjacking_test_instructions">
1. Connect device via usb to computer.\n
2. Click \"Show overlay\" button. Settings may appear if the CTS Verifier app doesn\'t have display over apps permission. Enable this permission and then click back to navigate back to the app.\n
- 3. Trigger USB debugging dialog (from computer terminal): \"adb shell am start -e fingerprints placeholder -e key placeholder com.android.systemui/.UsbDebuggingActivityAlias\"\n
+ 3. Trigger USB debugging dialog (from computer terminal): \"adb shell am start -e fingerprints placeholder -e key placeholder com.android.systemui/.usb.UsbDebuggingActivity\"\n
4. USB debugging dialog should appear with the overlay on top saying \"This message covers the USB debugging RSA prompt\" to appear.\n
5. Try clicking OK. \n
Test pass if you cannot click OK when the text quoted above is on top of the USB debugging dialog. Toast should appear saying there is an overlay so Settings cannot verify your response. \n
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/VintfDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/VintfDeviceInfo.java
index 468bcc1..a5a949272 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/VintfDeviceInfo.java
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/VintfDeviceInfo.java
@@ -63,5 +63,13 @@
store.endGroup();
}
store.endArray();
+
+ // getTargetFrameworkCompatibilityMatrixVersion is available Android P onward.
+ // (Use O_MR1 until P is released.)
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O_MR1) {
+ return;
+ }
+ store.addResult("target_fcm_version",
+ VintfObject.getTargetFrameworkCompatibilityMatrixVersion());
}
}
diff --git a/common/device-side/device-info/src_stub/android/os/VintfObject.java b/common/device-side/device-info/src_stub/android/os/VintfObject.java
index 42f1be2..b8da52e 100644
--- a/common/device-side/device-info/src_stub/android/os/VintfObject.java
+++ b/common/device-side/device-info/src_stub/android/os/VintfObject.java
@@ -12,4 +12,5 @@
public static String getSepolicyVersion() { return null; }
public static String[] getHalNamesAndVersions() { return null; }
public static String[] report() { return null; }
+ public static Long getTargetFrameworkCompatibilityMatrixVersion() { return null; }
}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ConsoleReporter.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ConsoleReporter.java
index 4944da2..9c79abd 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ConsoleReporter.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ConsoleReporter.java
@@ -17,13 +17,13 @@
package com.android.compatibility.common.tradefed.result;
import com.android.ddmlib.Log.LogLevel;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.config.Option;
import com.android.tradefed.config.OptionCopier;
import com.android.tradefed.invoker.IInvocationContext;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.IShardableListener;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.util.TimeUtil;
import java.util.Map;
@@ -84,7 +84,7 @@
* {@inheritDoc}
*/
@Override
- public void testStarted(TestIdentifier test) {
+ public void testStarted(TestDescription test) {
mTestFailed = false;
mCurrentTestNum++;
}
@@ -93,7 +93,7 @@
* {@inheritDoc}
*/
@Override
- public void testFailed(TestIdentifier test, String trace) {
+ public void testFailed(TestDescription test, String trace) {
logProgress("%s fail: %s", test, trace);
mTestFailed = true;
mFailedTests++;
@@ -103,7 +103,7 @@
* {@inheritDoc}
*/
@Override
- public void testIgnored(TestIdentifier test) {
+ public void testIgnored(TestDescription test) {
mCurrentTestNum--;
logProgress("%s ignore", test);
}
@@ -112,7 +112,7 @@
* {@inheritDoc}
*/
@Override
- public void testAssumptionFailure(TestIdentifier test, String trace) {
+ public void testAssumptionFailure(TestDescription test, String trace) {
logProgress("%s skip", test);
}
@@ -120,7 +120,7 @@
* {@inheritDoc}
*/
@Override
- public void testEnded(TestIdentifier test, Map<String, String> testMetrics) {
+ public void testEnded(TestDescription test, Map<String, String> testMetrics) {
if (!mTestFailed) {
logProgress("%s pass", test);
mPassedTests++;
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/MetadataReporter.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/MetadataReporter.java
index 6894c2d..3f51cca 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/MetadataReporter.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/MetadataReporter.java
@@ -17,7 +17,6 @@
package com.android.compatibility.common.tradefed.result;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.json.stream.JsonWriter;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.config.Option;
@@ -25,6 +24,7 @@
import com.android.tradefed.invoker.IInvocationContext;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.IShardableListener;
+import com.android.tradefed.result.TestDescription;
import java.io.File;
import java.io.FileNotFoundException;
@@ -96,7 +96,7 @@
* {@inheritDoc}
*/
@Override
- public void testStarted(TestIdentifier test) {
+ public void testStarted(TestDescription test) {
mStartTime = System.currentTimeMillis();
mTestFailed = false;
}
@@ -105,7 +105,7 @@
* {@inheritDoc}
*/
@Override
- public void testFailed(TestIdentifier test, String trace) {
+ public void testFailed(TestDescription test, String trace) {
mTestFailed = true;
}
@@ -113,7 +113,7 @@
* {@inheritDoc}
*/
@Override
- public void testIgnored(TestIdentifier test) {
+ public void testIgnored(TestDescription test) {
mTestFailed = true;
}
@@ -121,7 +121,7 @@
* {@inheritDoc}
*/
@Override
- public void testAssumptionFailure(TestIdentifier test, String trace) {
+ public void testAssumptionFailure(TestDescription test, String trace) {
mTestFailed = true;
}
@@ -129,7 +129,7 @@
* {@inheritDoc}
*/
@Override
- public void testEnded(TestIdentifier test, Map<String, String> testMetrics) {
+ public void testEnded(TestDescription test, Map<String, String> testMetrics) {
long duration = System.currentTimeMillis() - mStartTime;
if (mTestFailed && !mIncludeFailures) {
return;
@@ -163,7 +163,7 @@
long seconds;
}
- private static String buildTestId(TestIdentifier test) {
+ private static String buildTestId(TestDescription test) {
return String.format("%s.%s", test.getClassName(), test.getTestName());
}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ModuleListener.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ModuleListener.java
index 8140887..878d0fd 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ModuleListener.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ModuleListener.java
@@ -16,12 +16,12 @@
package com.android.compatibility.common.tradefed.result;
import com.android.compatibility.common.tradefed.testtype.IModuleDef;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.invoker.IInvocationContext;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.result.InputStreamSource;
import com.android.tradefed.result.LogDataType;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.result.TestSummary;
import java.util.Map;
@@ -67,7 +67,7 @@
* {@inheritDoc}
*/
@Override
- public void testStarted(TestIdentifier test) {
+ public void testStarted(TestDescription test) {
CLog.d("ModuleListener.testStarted(%s)", test.toString());
mListener.testStarted(test);
}
@@ -76,7 +76,7 @@
* {@inheritDoc}
*/
@Override
- public void testEnded(TestIdentifier test, Map<String, String> metrics) {
+ public void testEnded(TestDescription test, Map<String, String> metrics) {
CLog.d("ModuleListener.testEnded(%s, %s)", test.toString(), metrics.toString());
mListener.testEnded(test, metrics);
}
@@ -85,7 +85,7 @@
* {@inheritDoc}
*/
@Override
- public void testIgnored(TestIdentifier test) {
+ public void testIgnored(TestDescription test) {
CLog.d("ModuleListener.testIgnored(%s)", test.toString());
mListener.testIgnored(test);
}
@@ -94,7 +94,7 @@
* {@inheritDoc}
*/
@Override
- public void testFailed(TestIdentifier test, String trace) {
+ public void testFailed(TestDescription test, String trace) {
CLog.d("ModuleListener.testFailed(%s, %s)", test.toString(), trace);
mListener.testFailed(test, trace);
}
@@ -103,7 +103,7 @@
* {@inheritDoc}
*/
@Override
- public void testAssumptionFailure(TestIdentifier test, String trace) {
+ public void testAssumptionFailure(TestDescription test, String trace) {
CLog.d("ModuleListener.testAssumptionFailure(%s, %s)", test.toString(), trace);
mListener.testAssumptionFailure(test, trace);
}
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 11a7466..1e0782d 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
@@ -32,7 +32,6 @@
import com.android.compatibility.common.util.ResultUploader;
import com.android.compatibility.common.util.TestStatus;
import com.android.ddmlib.Log.LogLevel;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.config.Option;
import com.android.tradefed.config.Option.Importance;
@@ -50,6 +49,7 @@
import com.android.tradefed.result.LogDataType;
import com.android.tradefed.result.LogFile;
import com.android.tradefed.result.LogFileSaver;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.result.TestSummary;
import com.android.tradefed.result.suite.SuiteResultReporter;
import com.android.tradefed.util.FileUtil;
@@ -327,7 +327,7 @@
* {@inheritDoc}
*/
@Override
- public void testStarted(TestIdentifier test) {
+ public void testStarted(TestDescription test) {
mCurrentCaseResult = mCurrentModuleResult.getOrCreateResult(test.getClassName());
mCurrentResult = mCurrentCaseResult.getOrCreateResult(test.getTestName().trim());
if (mCurrentResult.isRetry()) {
@@ -340,7 +340,7 @@
* {@inheritDoc}
*/
@Override
- public void testEnded(TestIdentifier test, Map<String, String> metrics) {
+ public void testEnded(TestDescription test, Map<String, String> metrics) {
if (mCurrentResult.getResultStatus() == TestStatus.FAIL) {
// Test has previously failed.
return;
@@ -370,7 +370,7 @@
* {@inheritDoc}
*/
@Override
- public void testIgnored(TestIdentifier test) {
+ public void testIgnored(TestDescription test) {
mCurrentResult.skipped();
}
@@ -378,7 +378,7 @@
* {@inheritDoc}
*/
@Override
- public void testFailed(TestIdentifier test, String trace) {
+ public void testFailed(TestDescription test, String trace) {
mCurrentResult.failed(trace);
}
@@ -386,7 +386,7 @@
* {@inheritDoc}
*/
@Override
- public void testAssumptionFailure(TestIdentifier test, String trace) {
+ public void testAssumptionFailure(TestDescription test, String trace) {
mCurrentResult.skipped();
}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ApkInstrumentationPreparer.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ApkInstrumentationPreparer.java
index 1673866..dbd202b 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ApkInstrumentationPreparer.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ApkInstrumentationPreparer.java
@@ -17,7 +17,6 @@
package com.android.compatibility.common.tradefed.targetprep;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.config.Option;
import com.android.tradefed.config.OptionClass;
@@ -25,6 +24,7 @@
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.targetprep.BuildError;
import com.android.tradefed.targetprep.ITargetCleaner;
import com.android.tradefed.targetprep.TargetSetupError;
@@ -57,9 +57,9 @@
@Option(name = "throw-error", description = "Whether to throw error for device test failure")
protected boolean mThrowError = true;
- protected ConcurrentHashMap<TestIdentifier, Map<String, String>> testMetrics =
+ protected ConcurrentHashMap<TestDescription, Map<String, String>> testMetrics =
new ConcurrentHashMap<>();
- private ConcurrentHashMap<TestIdentifier, String> testFailures = new ConcurrentHashMap<>();
+ private ConcurrentHashMap<TestDescription, String> testFailures = new ConcurrentHashMap<>();
/**
* {@inheritDoc}
@@ -126,7 +126,7 @@
instrTest.run(listener);
boolean success = true;
if (!testFailures.isEmpty()) {
- for (TestIdentifier test : testFailures.keySet()) {
+ for (TestDescription test : testFailures.keySet()) {
success = false;
String trace = testFailures.get(test);
if (mThrowError) {
@@ -143,12 +143,12 @@
private class TargetPreparerListener implements ITestInvocationListener {
@Override
- public void testEnded(TestIdentifier test, Map<String, String> metrics) {
+ public void testEnded(TestDescription test, Map<String, String> metrics) {
testMetrics.put(test, metrics);
}
@Override
- public void testFailed(TestIdentifier test, String trace) {
+ public void testFailed(TestDescription test, String trace) {
testFailures.put(test, trace);
}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DynamicConfigPusher.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DynamicConfigPusher.java
index 0e23165..6db5e78 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DynamicConfigPusher.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DynamicConfigPusher.java
@@ -58,6 +58,10 @@
"target after test completion.")
private boolean mCleanup = true;
+ @Option(name = "config-url", description = "The url path of the dynamic config. If set, " +
+ "will override the default config location defined in CompatibilityBuildProvider.")
+ private String mConfigUrl;
+
@Option(name="config-filename", description = "The module name for module-level " +
"configurations, or the suite name for suite-level configurations", mandatory = true)
private String mModuleName;
@@ -104,7 +108,7 @@
}
String apfeConfigInJson = null;
- String originUrl = buildHelper.getDynamicConfigUrl();
+ String originUrl = (mConfigUrl != null) ? mConfigUrl : buildHelper.getDynamicConfigUrl();
if (originUrl != null) {
String requestUrl = originUrl;
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/MediaPreparer.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/MediaPreparer.java
index 1bcc6f8..59216df 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/MediaPreparer.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/MediaPreparer.java
@@ -16,16 +16,15 @@
package com.android.compatibility.common.tradefed.targetprep;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.compatibility.common.tradefed.targetprep.PreconditionPreparer;
import com.android.compatibility.common.tradefed.util.DynamicConfigFileReader;
import com.android.ddmlib.IDevice;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.config.Option;
import com.android.tradefed.config.OptionClass;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.targetprep.BuildError;
import com.android.tradefed.targetprep.TargetSetupError;
import com.android.tradefed.testtype.AndroidJUnitTest;
@@ -380,7 +379,7 @@
private class MediaPreparerListener implements ITestInvocationListener {
@Override
- public void testEnded(TestIdentifier test, Map<String, String> metrics) {
+ public void testEnded(TestDescription test, Map<String, String> metrics) {
String resString = metrics.get(RESOLUTION_STRING_KEY);
if (resString != null) {
mMaxRes = new Resolution(resString);
@@ -388,7 +387,7 @@
}
@Override
- public void testFailed(TestIdentifier test, String trace) {
+ public void testFailed(TestDescription test, String trace) {
mFailureStackTrace = trace;
}
}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/FailureListener.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/FailureListener.java
index fbddb22..d21ef81 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/FailureListener.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/FailureListener.java
@@ -15,7 +15,6 @@
*/
package com.android.compatibility.common.tradefed.testtype;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.log.LogUtil.CLog;
@@ -23,6 +22,7 @@
import com.android.tradefed.result.InputStreamSource;
import com.android.tradefed.result.LogDataType;
import com.android.tradefed.result.ResultForwarder;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.util.RunUtil;
public class FailureListener extends ResultForwarder {
@@ -65,7 +65,7 @@
* {@inheritDoc}
*/
@Override
- public void testFailed(TestIdentifier test, String trace) {
+ public void testFailed(TestDescription test, String trace) {
super.testFailed(test, trace);
CLog.i("FailureListener.testFailed %s %b %b %b",
test.toString(), mBugReportOnFailure, mLogcatOnFailure, mScreenshotOnFailure);
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/IntegrationTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/IntegrationTest.java
index 4dbd3a9..a6e4090 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/IntegrationTest.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/IntegrationTest.java
@@ -24,7 +24,6 @@
import com.android.compatibility.common.tradefed.testtype.IModuleDef;
import com.android.compatibility.common.util.IInvocationResult;
import com.android.compatibility.common.util.TestStatus;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.config.ConfigurationFactory;
import com.android.tradefed.config.OptionSetter;
@@ -35,6 +34,7 @@
import com.android.tradefed.invoker.ShardListener;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.result.ResultForwarder;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.testtype.IBuildReceiver;
import com.android.tradefed.testtype.IDeviceTest;
import com.android.tradefed.testtype.IInvocationContextReceiver;
@@ -259,7 +259,7 @@
.getAttributes().get(IModuleDef.MODULE_ABI));
}
@Override
- public void testEnded(TestIdentifier test, long endTime,
+ public void testEnded(TestDescription test, long endTime,
Map<String, String> testMetrics) {
receivedComponentsTestEnded.addAll(myContext.getModuleInvocationContext()
.getConfigurationDescriptor().getMetaData("component"));
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ConsoleReporterTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ConsoleReporterTest.java
index 9102f1a..4f00387 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ConsoleReporterTest.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ConsoleReporterTest.java
@@ -16,9 +16,9 @@
package com.android.compatibility.common.tradefed.result;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.config.OptionSetter;
import com.android.tradefed.invoker.IInvocationContext;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.util.AbiUtils;
import junit.framework.TestCase;
@@ -94,24 +94,24 @@
/** Run 4 test, but one is ignored */
private void runTests() {
- TestIdentifier test1 = new TestIdentifier(CLASS, METHOD_1);
+ TestDescription test1 = new TestDescription(CLASS, METHOD_1);
mReporter.testStarted(test1);
mReporter.testEnded(test1, new HashMap<String, String>());
assertFalse(mReporter.getTestFailed());
- TestIdentifier test2 = new TestIdentifier(CLASS, METHOD_2);
+ TestDescription test2 = new TestDescription(CLASS, METHOD_2);
mReporter.testStarted(test2);
assertFalse(mReporter.getTestFailed());
mReporter.testFailed(test2, STACK_TRACE);
assertTrue(mReporter.getTestFailed());
- TestIdentifier test3 = new TestIdentifier(CLASS, METHOD_3);
+ TestDescription test3 = new TestDescription(CLASS, METHOD_3);
mReporter.testStarted(test3);
assertFalse(mReporter.getTestFailed());
mReporter.testFailed(test3, STACK_TRACE);
assertTrue(mReporter.getTestFailed());
- TestIdentifier test4 = new TestIdentifier(CLASS, METHOD_3);
+ TestDescription test4 = new TestDescription(CLASS, METHOD_3);
mReporter.testStarted(test4);
assertFalse(mReporter.getTestFailed());
mReporter.testIgnored(test4);
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/MetadataReporterTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/MetadataReporterTest.java
index 1f80dec..ba59ac1 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/MetadataReporterTest.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/MetadataReporterTest.java
@@ -18,12 +18,12 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.compatibility.common.util.AbiUtils;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.build.BuildInfo;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.config.OptionSetter;
import com.android.tradefed.invoker.IInvocationContext;
import com.android.tradefed.invoker.InvocationContext;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.util.FileUtil;
import com.android.tradefed.util.RunUtil;
@@ -115,23 +115,23 @@
/** Run 4 test. */
private void runTests(long waitTime) {
- TestIdentifier test1 = new TestIdentifier(CLASS, METHOD_1);
+ TestDescription test1 = new TestDescription(CLASS, METHOD_1);
mReporter.testStarted(test1);
RunUtil.getDefault().sleep(waitTime);
mReporter.testEnded(test1, new HashMap<String, String>());
- TestIdentifier test2 = new TestIdentifier(CLASS, METHOD_2);
+ TestDescription test2 = new TestDescription(CLASS, METHOD_2);
mReporter.testStarted(test2);
RunUtil.getDefault().sleep(waitTime);
mReporter.testEnded(test1, new HashMap<String, String>());
- TestIdentifier test3 = new TestIdentifier(CLASS, METHOD_3);
+ TestDescription test3 = new TestDescription(CLASS, METHOD_3);
mReporter.testStarted(test3);
RunUtil.getDefault().sleep(waitTime);
mReporter.testFailed(test3, STACK_TRACE);
mReporter.testEnded(test3, new HashMap<String, String>());
- TestIdentifier test4 = new TestIdentifier(CLASS, METHOD_3);
+ TestDescription test4 = new TestDescription(CLASS, METHOD_3);
mReporter.testStarted(test4);
RunUtil.getDefault().sleep(waitTime);
mReporter.testIgnored(test4);
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ResultReporterTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ResultReporterTest.java
index c24e9df..d5382b8 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ResultReporterTest.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ResultReporterTest.java
@@ -24,7 +24,6 @@
import com.android.compatibility.common.util.IModuleResult;
import com.android.compatibility.common.util.ITestResult;
import com.android.compatibility.common.util.TestStatus;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.config.OptionSetter;
import com.android.tradefed.invoker.IInvocationContext;
@@ -32,6 +31,7 @@
import com.android.tradefed.result.ByteArrayInputStreamSource;
import com.android.tradefed.result.InputStreamSource;
import com.android.tradefed.result.LogDataType;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.util.AbiUtils;
import com.android.tradefed.util.FileUtil;
@@ -144,13 +144,13 @@
public void testResultReporting() throws Exception {
mReporter.invocationStarted(mContext);
mReporter.testRunStarted(ID, 2);
- TestIdentifier test1 = new TestIdentifier(CLASS, METHOD_1);
+ TestDescription test1 = new TestDescription(CLASS, METHOD_1);
mReporter.testStarted(test1);
mReporter.testEnded(test1, new HashMap<String, String>());
- TestIdentifier test2 = new TestIdentifier(CLASS, METHOD_2);
+ TestDescription test2 = new TestDescription(CLASS, METHOD_2);
mReporter.testStarted(test2);
mReporter.testFailed(test2, STACK_TRACE);
- TestIdentifier test3 = new TestIdentifier(CLASS, METHOD_3);
+ TestDescription test3 = new TestDescription(CLASS, METHOD_3);
mReporter.testStarted(test3);
mReporter.testFailed(test3, STACK_TRACE);
mReporter.testEnded(test3, new HashMap<String, String>());
@@ -187,7 +187,7 @@
mReporter.testRunStarted(ID, methods.length);
for (int i = 0; i < methods.length; i++) {
- TestIdentifier test = new TestIdentifier(CLASS, methods[i]);
+ TestDescription test = new TestDescription(CLASS, methods[i]);
mReporter.testStarted(test);
if (!passes[i]) {
mReporter.testFailed(test, STACK_TRACE);
@@ -263,11 +263,11 @@
testResult2.setRetry(true);
// Flip results for the current session
- TestIdentifier test1 = new TestIdentifier(CLASS, METHOD_1);
+ TestDescription test1 = new TestDescription(CLASS, METHOD_1);
mReporter.testStarted(test1);
mReporter.testFailed(test1, STACK_TRACE);
mReporter.testEnded(test1, new HashMap<String, String>());
- TestIdentifier test2 = new TestIdentifier(CLASS, METHOD_2);
+ TestDescription test2 = new TestDescription(CLASS, METHOD_2);
mReporter.testStarted(test2);
mReporter.testEnded(test2, new HashMap<String, String>());
@@ -323,7 +323,7 @@
// been collected. Thus, module "done" value should switch.
mReporter.testRunStarted(ID, 1);
- TestIdentifier test2 = new TestIdentifier(CLASS, METHOD_2);
+ TestDescription test2 = new TestDescription(CLASS, METHOD_2);
mReporter.testStarted(test2);
mReporter.testEnded(test2, new HashMap<String, String>());
@@ -362,7 +362,7 @@
// and don't run any non-executed tests, so module "done" value should not switch.
mReporter.testRunStarted(ID, 1);
- TestIdentifier test2 = new TestIdentifier(CLASS, METHOD_2);
+ TestDescription test2 = new TestDescription(CLASS, METHOD_2);
mReporter.testStarted(test2);
mReporter.testEnded(test2, new HashMap<String, String>());
@@ -382,7 +382,7 @@
public void testResultReporting_moduleNotDone() throws Exception {
mReporter.invocationStarted(mContext);
mReporter.testRunStarted(ID, 2);
- TestIdentifier test1 = new TestIdentifier(CLASS, METHOD_1);
+ TestDescription test1 = new TestDescription(CLASS, METHOD_1);
mReporter.testStarted(test1);
mReporter.testEnded(test1, new HashMap<String, String>());
mReporter.testRunFailed("error");
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/JarHostTestTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/JarHostTestTest.java
index 1178a2f..fb361d2 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/JarHostTestTest.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/JarHostTestTest.java
@@ -282,7 +282,7 @@
OptionSetter setter = new OptionSetter(mTest);
setter.setOptionValue("jar", "thisjardoesnotexistatall.jar");
mListener.testRunStarted(EasyMock.anyObject(), EasyMock.eq(0));
- mListener.testRunEnded(EasyMock.anyLong(), EasyMock.anyObject());
+ mListener.testRunEnded(EasyMock.anyLong(), (Map<String, String>) EasyMock.anyObject());
EasyMock.replay(mListener);
try {
mTest.run(mListener);
@@ -308,7 +308,7 @@
Map<String, String> metrics = new HashMap<>();
metrics.put("key", "value");
mListener.testEnded(EasyMock.eq(tid), EasyMock.anyLong(), EasyMock.eq(metrics));
- mListener.testRunEnded(EasyMock.anyLong(), EasyMock.anyObject());
+ mListener.testRunEnded(EasyMock.anyLong(), (Map<String, String>) EasyMock.anyObject());
EasyMock.replay(mListener);
mTest.run(mListener);
EasyMock.verify(mListener);
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/SimpleTestStub.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/SimpleTestStub.java
index 331f978..aacda6a 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/SimpleTestStub.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/SimpleTestStub.java
@@ -15,10 +15,10 @@
*/
package com.android.compatibility.common.tradefed.testtype;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.config.Option;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.testtype.IAbi;
import com.android.tradefed.testtype.IAbiReceiver;
import com.android.tradefed.testtype.IRemoteTest;
@@ -52,7 +52,7 @@
public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
// We report 1 passing tes
listener.testRunStarted("module-run", 1);
- TestIdentifier tid = new TestIdentifier("TestStub", "test1");
+ TestDescription tid = new TestDescription("TestStub", "test1");
listener.testStarted(tid);
listener.testEnded(tid, Collections.emptyMap());
listener.testRunEnded(0, Collections.emptyMap());
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/TestStub.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/TestStub.java
index a154f31..a493d3f 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/TestStub.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/TestStub.java
@@ -15,10 +15,10 @@
*/
package com.android.compatibility.common.tradefed.testtype;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.config.Option;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.testtype.IAbi;
import com.android.tradefed.testtype.IAbiReceiver;
import com.android.tradefed.testtype.IRemoteTest;
@@ -51,7 +51,7 @@
@Option(name = "internal-retry")
protected boolean mRetry = false;
- protected List<TestIdentifier> mShardedTestToRun;
+ protected List<TestDescription> mShardedTestToRun;
protected Integer mShardIndex = null;
/**
@@ -60,18 +60,18 @@
private void testAttempt(ITestInvocationListener listener) {
// We report 3 tests: 2 pass, 1 failed
listener.testRunStarted("module-run", 3);
- TestIdentifier tid = new TestIdentifier("TestStub", "test1");
+ TestDescription tid = new TestDescription("TestStub", "test1");
listener.testStarted(tid);
listener.testEnded(tid, Collections.emptyMap());
if (mIsComplete) {
// possibly skip this one to create some not_executed case.
- TestIdentifier tid2 = new TestIdentifier("TestStub", "test2");
+ TestDescription tid2 = new TestDescription("TestStub", "test2");
listener.testStarted(tid2);
listener.testEnded(tid2, Collections.emptyMap());
}
- TestIdentifier tid3 = new TestIdentifier("TestStub", "test3");
+ TestDescription tid3 = new TestDescription("TestStub", "test3");
listener.testStarted(tid3);
if (mDoesOneTestFail) {
listener.testFailed(tid3, "ouch this is bad.");
@@ -105,18 +105,18 @@
}
if (mIsComplete) {
- for (TestIdentifier tid : mShardedTestToRun) {
+ for (TestDescription tid : mShardedTestToRun) {
listener.testStarted(tid);
listener.testEnded(tid, Collections.emptyMap());
}
} else {
- TestIdentifier tid = mShardedTestToRun.get(0);
+ TestDescription tid = mShardedTestToRun.get(0);
listener.testStarted(tid);
listener.testEnded(tid, Collections.emptyMap());
}
if (mDoesOneTestFail) {
- TestIdentifier tid = new TestIdentifier("TestStub", "failed" + mShardIndex);
+ TestDescription tid = new TestDescription("TestStub", "failed" + mShardIndex);
listener.testStarted(tid);
listener.testFailed(tid, "shard failed this one.");
listener.testEnded(tid, Collections.emptyMap());
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/TestStubShardable.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/TestStubShardable.java
index 2789b82..d3d7b41 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/TestStubShardable.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/TestStubShardable.java
@@ -15,8 +15,8 @@
*/
package com.android.compatibility.common.tradefed.testtype;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.config.OptionCopier;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.testtype.IRemoteTest;
import com.android.tradefed.testtype.IStrictShardableTest;
@@ -32,10 +32,10 @@
TestStubShardable test = new TestStubShardable();
OptionCopier.copyOptionsNoThrow(this, test);
test.mShardedTestToRun = new ArrayList<>();
- TestIdentifier tid = new TestIdentifier("TestStub", "test" + shardIndex);
+ TestDescription tid = new TestDescription("TestStub", "test" + shardIndex);
test.mShardedTestToRun.add(tid);
if (mIsComplete == false) {
- TestIdentifier tid2 = new TestIdentifier("TestStub", "test" + shardIndex + 100);
+ TestDescription tid2 = new TestDescription("TestStub", "test" + shardIndex + 100);
test.mShardedTestToRun.add(tid2);
test.mIsComplete = false;
}
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-1-permcli-companion.apk b/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-1-permcli-companion.apk
new file mode 100644
index 0000000..8eeac8c
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-1-permcli-companion.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-1-permdef.apk b/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-1-permdef.apk
new file mode 100644
index 0000000..9bb3d1f
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-1-permdef.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-2-permcli-companion.apk b/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-2-permcli-companion.apk
new file mode 100644
index 0000000..93b4a40
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-2-permcli-companion.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-2-permdef.apk b/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-2-permdef.apk
new file mode 100644
index 0000000..bd785d7
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-2-permdef.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps-permcli-companion.apk b/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps-permcli-companion.apk
new file mode 100644
index 0000000..916f1e4
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps-permcli-companion.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps-permdef.apk b/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps-permdef.apk
new file mode 100644
index 0000000..7db3423
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps-permdef.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-no-perm-cap-permcli-companion.apk b/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-no-perm-cap-permcli-companion.apk
new file mode 100644
index 0000000..043e97b
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-no-perm-cap-permcli-companion.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-no-perm-cap-permdef.apk b/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-no-perm-cap-permdef.apk
new file mode 100644
index 0000000..ce9901d
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-no-perm-cap-permdef.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-2-with_por_1_2-no-perm-cap-permdef-companion.apk b/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-2-with_por_1_2-no-perm-cap-permdef-companion.apk
new file mode 100644
index 0000000..8b08a79
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-2-with_por_1_2-no-perm-cap-permdef-companion.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-2-with_por_1_2-permdef-companion.apk b/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-2-with_por_1_2-permdef-companion.apk
new file mode 100644
index 0000000..773ae5e
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v3-rsa-pkcs1-sha256-2048-2-with_por_1_2-permdef-companion.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
index 38e4dc2..0822760 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
@@ -252,6 +252,8 @@
runDeviceTests(READ_PKG, READ_PKG + ".ReadMultiViewTest", "testROAccess", user);
}
+ // for fuse file system
+ Thread.sleep(10000);
for (int user : mUsers) {
runDeviceTests(WRITE_PKG, WRITE_PKG + ".WriteMultiViewTest", "testMoveBack", user);
}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java
index 02187fa..03a1189 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java
@@ -18,12 +18,12 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.result.TestResult;
import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.testtype.DeviceTestCase;
@@ -117,7 +117,7 @@
/* build a meaningful error message */
StringBuilder errorBuilder = new StringBuilder("on-device tests failed:\n");
- for (Map.Entry<TestIdentifier, TestResult> resultEntry :
+ for (Map.Entry<TestDescription, TestResult> resultEntry :
result.getTestResults().entrySet()) {
if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
errorBuilder.append(resultEntry.getKey().toString());
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/OverlayHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/OverlayHostTest.java
index b543fbd6ae..cf903db 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/OverlayHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/OverlayHostTest.java
@@ -17,7 +17,6 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.CollectingOutputReceiver;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IBuildReceiver;
@@ -44,13 +43,16 @@
}
public void testInstallingOverlayHasNoEffect() throws Exception {
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(APK), false, false));
- CollectingOutputReceiver receiver = new CollectingOutputReceiver();
- getDevice().getIDevice().executeShellCommand("cmd overlay list", receiver);
+ assertFalse(getDevice().getInstalledPackageNames().contains(PKG));
+
+ // Try to install the overlay, but expect an error.
+ assertNotNull(getDevice().installPackage(mBuildHelper.getTestFile(APK), false, false));
+
+ // The install should have failed.
+ assertFalse(getDevice().getInstalledPackageNames().contains(PKG));
// The package of the installed overlay should not appear in the overlay manager list.
- final String output = receiver.getOutput();
- assertFalse(output.contains(PKG));
+ assertFalse(getDevice().executeShellCommand("cmd overlay list").contains(PKG));
}
}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java
index b797b32..e4b0f09 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java
@@ -364,6 +364,25 @@
"testNoProtectionFlagsAddedToNonSignatureProtectionPermissions");
}
+ public void testNullPermissionRequest() throws Exception {
+ assertNull(getDevice().installPackage(mBuildHelper.getTestFile(APK_23), false, false));
+ runDeviceTests(USES_PERMISSION_PKG, "com.android.cts.usepermission.UsePermissionTest23",
+ "testNullPermissionRequest");
+ }
+
+ public void testNullAndRealPermission() throws Exception {
+ assertNull(getDevice().installPackage(mBuildHelper.getTestFile(APK_23), false, false));
+ runDeviceTests(USES_PERMISSION_PKG, "com.android.cts.usepermission.UsePermissionTest23",
+ "testNullAndRealPermission");
+ }
+
+ public void testInvalidPermission() throws Exception {
+ assertNull(getDevice().installPackage(mBuildHelper.getTestFile(APK_23), false, false));
+ runDeviceTests(USES_PERMISSION_PKG, "com.android.cts.usepermission.UsePermissionTest23",
+ "testInvalidPermission");
+ }
+
+
public void testSerialAccessPolicy() throws Exception {
// Verify legacy app behavior
assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
index a295736..4d8981f 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
@@ -16,14 +16,17 @@
package android.appsecurity.cts;
+import android.platform.test.annotations.SecurityTest;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IBuildReceiver;
-import android.platform.test.annotations.SecurityTest;
import java.io.BufferedOutputStream;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -37,6 +40,9 @@
private static final String TEST_PKG = "android.appsecurity.cts.tinyapp";
private static final String COMPANION_TEST_PKG = "android.appsecurity.cts.tinyapp_companion";
+ private static final String DEVICE_TESTS_APK = "CtsV3SigningSchemeRotationTest.apk";
+ private static final String DEVICE_TESTS_PKG = "android.appsecurity.cts.v3rotationtests";
+ private static final String DEVICE_TESTS_CLASS = DEVICE_TESTS_PKG + ".V3RotationTest";
private static final String TEST_APK_RESOURCE_PREFIX = "/pkgsigverify/";
private static final String[] DSA_KEY_NAMES = {"1024", "2048", "3072"};
@@ -59,13 +65,14 @@
Utils.prepareSingleUser(getDevice());
assertNotNull(mCtsBuild);
uninstallPackage();
+ uninstallCompanionPackage();
+ installDeviceTestPkg();
}
@Override
protected void tearDown() throws Exception {
try {
- uninstallPackage();
- uninstallCompanionPackage();
+ uninstallPackages();
} catch (DeviceNotAvailableException ignored) {
} finally {
super.tearDown();
@@ -582,6 +589,95 @@
assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-sharedUid.apk");
}
+ public void testInstallV3KeyRotationSigPerm() throws Exception {
+ // tests that a v3 signed APK can still get a signature permission from an app with its
+ // older signing certificate.
+ assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1-permdef.apk");
+ assertInstallSucceeds(
+ "v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps-permcli-companion.apk");
+ Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasPerm");
+ }
+
+ public void testInstallV3KeyRotationOlderSigPerm() throws Exception {
+ // tests that an apk with an older signing certificate than the one which defines a
+ // signature permission it wants gets the permission if the defining APK grants the
+ // capability
+ assertInstallSucceeds(
+ "v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-full-caps-permdef.apk");
+ assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1-permcli-companion.apk");
+ Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasPerm");
+ }
+
+ public void testInstallV3KeyRotationSigPermNoCap() throws Exception {
+ // tests that an APK signed by an older signing certificate is unable to get a requested
+ // signature permission when the defining APK has rotated to a newer signing certificiate
+ // and does not grant the permission capability to the older cert
+ assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-no-perm-cap-permdef.apk");
+ assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1-permcli-companion.apk");
+ Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasNoPerm");
+ }
+
+ public void testInstallV3KeyRotationOlderSigPermNoCap() throws Exception {
+ // tests that an APK signed by a newer signing certificate than the APK which defines a
+ // signature permission is able to get that permission, even if the newer APK does not
+ // grant the permission capability to the older signing certificate.
+ assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1-permdef.apk");
+ assertInstallSucceeds(
+ "v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-no-perm-cap-permcli-companion.apk");
+ Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasPerm");
+ }
+
+ public void testInstallV3NoRotationSigPerm() throws Exception {
+ // make sure that an APK, which wants to use a signature permission defined by an APK, which
+ // has not granted that capability to older signing certificates, can still install
+ assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with-por_1_2-no-perm-cap-permdef.apk");
+ assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-permcli-companion.apk");
+ Utils.runDeviceTests(getDevice(), DEVICE_TESTS_PKG, DEVICE_TESTS_CLASS, "testHasPerm");
+ }
+
+ public void testInstallV3SigPermDoubleDefNewerSucceeds() throws Exception {
+ // make sure that if an app defines a signature permission already defined by another app,
+ // it successfully installs if the other app's signing cert is in its past signing certs and
+ // the signature permission capability is granted
+ assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1-permdef.apk");
+ assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with_por_1_2-permdef-companion.apk");
+ }
+
+ public void testInstallV3SigPermDoubleDefOlderSucceeds() throws Exception {
+ // make sure that if an app defines a signature permission already defined by another app,
+ // it successfully installs if it is in the other app's past signing certs and the signature
+ // permission capability is granted
+ assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-with_por_1_2-permdef-companion.apk");
+ assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1-permdef.apk");
+ }
+
+ public void testInstallV3SigPermDoubleDefNewerNoCapFails() throws Exception {
+ // make sure that if an app defines a signature permission already defined by another app,
+ // it fails to install if the other app's signing cert is in its past signing certs but the
+ // signature permission capability is not granted
+ assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-1-permdef.apk");
+ assertInstallFails(
+ "v3-rsa-pkcs1-sha256-2048-2-with_por_1_2-no-perm-cap-permdef-companion.apk");
+ }
+
+ public void testInstallV3SigPermDoubleDefOlderNoCapFails() throws Exception {
+ // make sure that if an app defines a signature permission already defined by another app,
+ // it fails to install if it is in the other app's past signing certs but the signature
+ // permission capability is not granted
+ assertInstallSucceeds(
+ "v3-rsa-pkcs1-sha256-2048-2-with_por_1_2-no-perm-cap-permdef-companion.apk");
+ assertInstallFails("v3-rsa-pkcs1-sha256-2048-1-permdef.apk");
+ }
+
+ public void testInstallV3SigPermDoubleDefSameNoCapSucceeds() throws Exception {
+ // make sure that if an app defines a signature permission already defined by another app,
+ // it installs successfully when signed by the same certificate, even if the original app
+ // does not grant signature capabilities to its past certs
+ assertInstallSucceeds(
+ "v3-rsa-pkcs1-sha256-2048-2-with_por_1_2-no-perm-cap-permdef-companion.apk");
+ assertInstallSucceeds("v3-rsa-pkcs1-sha256-2048-2-permdef.apk");
+ }
+
private void assertInstallSucceeds(String apkFilenameInResources) throws Exception {
String installResult = installPackageFromResource(apkFilenameInResources);
if (installResult != null) {
@@ -658,6 +754,13 @@
}
}
+ private void installDeviceTestPkg() throws Exception {
+ CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild);
+ File apk = buildHelper.getTestFile(DEVICE_TESTS_APK);
+ String result = getDevice().installPackage(apk, true);
+ assertNull("failed to install " + DEVICE_TESTS_APK + ", Reason: " + result, result);
+ }
+
private String installPackageFromResource(String apkFilenameInResources, boolean ephemeral)
throws IOException, DeviceNotAvailableException {
// ITestDevice.installPackage API requires the APK to be install to be a File. We thus
@@ -705,4 +808,14 @@
private String uninstallCompanionPackage() throws DeviceNotAvailableException {
return getDevice().uninstallPackage(COMPANION_TEST_PKG);
}
+
+ private String uninstallDeviceTestPackage() throws DeviceNotAvailableException {
+ return getDevice().uninstallPackage(DEVICE_TESTS_PKG);
+ }
+
+ private void uninstallPackages() throws DeviceNotAvailableException {
+ uninstallPackage();
+ uninstallCompanionPackage();
+ uninstallDeviceTestPackage();
+ }
}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java
index 6c0efd5..38f7347 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java
@@ -16,9 +16,9 @@
package android.appsecurity.cts;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.result.TestResult;
import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -83,6 +83,9 @@
runDeviceTests(PKG_A, CLASS, "testAllocate", user);
}
+ // for fuse file system
+ Thread.sleep(10000);
+
// TODO: remove this once 34723223 is fixed
getDevice().executeShellCommand("sync");
@@ -244,7 +247,7 @@
TestRunResult res = getLastDeviceRunResults();
if (res != null) {
StringBuilder errorBuilder = new StringBuilder("on-device tests failed:\n");
- for (Map.Entry<TestIdentifier, TestResult> resultEntry :
+ for (Map.Entry<TestDescription, TestResult> resultEntry :
res.getTestResults().entrySet()) {
if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
errorBuilder.append(resultEntry.getKey().toString());
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java
index 3cde96f..c63720f 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java
@@ -17,11 +17,11 @@
package android.appsecurity.cts;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.result.TestResult;
import com.android.tradefed.result.TestRunResult;
@@ -93,7 +93,7 @@
if (result.hasFailedTests()) {
// build a meaningful error message
StringBuilder errorBuilder = new StringBuilder("on-device tests failed:\n");
- for (Map.Entry<TestIdentifier, TestResult> resultEntry :
+ for (Map.Entry<TestDescription, TestResult> resultEntry :
result.getTestResults().entrySet()) {
if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
errorBuilder.append(resultEntry.getKey().toString());
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/EphemeralActivity.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/EphemeralActivity.java
index bc29af9..270df87 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/EphemeralActivity.java
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/EphemeralActivity.java
@@ -37,6 +37,7 @@
TestResult.getBuilder()
.setPackageName("com.android.cts.ephemeralapp1")
.setComponentName("EphemeralActivity")
+ .setIntent(getIntent())
.setStatus("PASS")
.build()
.broadcast(this);
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/EphemeralActivity2.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/EphemeralActivity2.java
index 952b2f66..a0a170d 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/EphemeralActivity2.java
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/EphemeralActivity2.java
@@ -35,6 +35,7 @@
TestResult.getBuilder()
.setPackageName("com.android.cts.ephemeralapp1")
.setComponentName("EphemeralActivity2")
+ .setIntent(getIntent())
.setStatus("PASS")
.build()
.broadcast(this);
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/EphemeralActivity3.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/EphemeralActivity3.java
index 28734dd..1267577 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/EphemeralActivity3.java
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/EphemeralActivity3.java
@@ -35,6 +35,7 @@
TestResult.getBuilder()
.setPackageName("com.android.cts.ephemeralapp1")
.setComponentName("EphemeralActivity3")
+ .setIntent(getIntent())
.setStatus("PASS")
.build()
.broadcast(this);
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/EphemeralService.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/EphemeralService.java
index d649994..86dedc6 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/EphemeralService.java
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/EphemeralService.java
@@ -41,6 +41,7 @@
.setPackageName("com.android.cts.ephemeralapp1")
.setComponentName("EphemeralService")
.setMethodName("onBind")
+ .setIntent(intent)
.setStatus("PASS")
.build()
.broadcast(this);
@@ -53,6 +54,7 @@
.setPackageName("com.android.cts.ephemeralapp1")
.setComponentName("EphemeralService")
.setMethodName("onStartCommand")
+ .setIntent(intent)
.setStatus("PASS")
.build()
.broadcast(this);
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/AndroidManifest.xml
index 4c27dba..54ab0d7 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/AndroidManifest.xml
@@ -19,6 +19,7 @@
<uses-sdk
android:minSdkVersion="24" />
+ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
<application
android:label="@string/app_name">
<uses-library android:name="android.test.runner" />
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ClientTest.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ClientTest.java
index c5f36f3..616a5e9 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ClientTest.java
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ClientTest.java
@@ -16,6 +16,7 @@
package com.android.cts.normalapp;
+import static org.hamcrest.CoreMatchers.hasItems;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
@@ -25,16 +26,16 @@
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.net.Uri;
+import android.provider.Settings.Secure;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
-import android.test.InstrumentationTestCase;
-import android.util.Log;
import com.android.cts.util.TestResult;
@@ -376,6 +377,7 @@
startEphemeralIntent, null /*options*/);
final TestResult testResult = getResult();
assertThat("com.android.cts.ephemeralapp1", is(testResult.getPackageName()));
+ assertThat(ACTION_START_EPHEMERAL_ACTIVITY, is(testResult.getIntent().getAction()));
}
@@ -400,6 +402,7 @@
startEphemeralIntent, null /*options*/);
final TestResult testResult = getResult();
assertThat("com.android.cts.ephemeralapp1", is(testResult.getPackageName()));
+ assertThat(ACTION_START_EPHEMERAL_ACTIVITY, is(testResult.getIntent().getAction()));
}
// start the ephemeral activity; directed component
@@ -442,13 +445,51 @@
final TestResult testResult = getResult();
assertThat("com.android.cts.ephemeralapp1", is(testResult.getPackageName()));
assertThat("EphemeralActivity", is(testResult.getComponentName()));
+ assertThat(Intent.ACTION_VIEW, is(testResult.getIntent().getAction()));
+ assertThat(testResult.getIntent().getCategories(), hasItems(Intent.CATEGORY_BROWSABLE));
+ assertThat("https://cts.google.com/ephemeral",
+ is(testResult.getIntent().getData().toString()));
+ }
+
+ final ContentResolver contentResolver =
+ InstrumentationRegistry.getContext().getContentResolver();
+ final int originalSetting = Secure.getInt(contentResolver, Secure.INSTANT_APPS_ENABLED);
+ Secure.putInt(contentResolver, Secure.INSTANT_APPS_ENABLED, 0);
+ try {
+ // start the ephemeral activity; using VIEW/BROWSABLE with setting disabled
+ try {
+ final Intent startViewIntent = new Intent(Intent.ACTION_VIEW)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startViewIntent.addCategory(Intent.CATEGORY_BROWSABLE);
+ startViewIntent.setData(Uri.parse("https://cts.google.com/ephemeral"));
+ InstrumentationRegistry.getContext().startActivity(
+ startViewIntent, null /*options*/);
+ final TestResult testResult = getResult();
+ fail();
+ } catch (TestResultNotFoundException expected) {
+ // we shouldn't resolve to our instant app
+ }
+
+ // start the ephemeral activity; EXTERNAL flag with setting disabled
+ {
+ final Intent startEphemeralIntent = new Intent(ACTION_START_EPHEMERAL_ACTIVITY)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_MATCH_EXTERNAL);
+ InstrumentationRegistry.getContext().startActivity(
+ startEphemeralIntent, null /*options*/);
+ final TestResult testResult = getResult();
+ assertThat("com.android.cts.ephemeralapp1", is(testResult.getPackageName()));
+ assertThat(ACTION_START_EPHEMERAL_ACTIVITY, is(testResult.getIntent().getAction()));
+ }
+
+ } finally {
+ Secure.putInt(contentResolver, Secure.INSTANT_APPS_ENABLED, originalSetting);
}
// connect to the instant app provider
{
final String provider = "content://com.android.cts.ephemeralapp1.provider/table";
- final Cursor testCursor = InstrumentationRegistry
- .getContext().getContentResolver().query(
+ final Cursor testCursor = contentResolver.query(
Uri.parse(provider),
null /*projection*/,
null /*selection*/,
@@ -466,11 +507,18 @@
throw new RuntimeException(e);
}
if (result == null) {
- throw new IllegalStateException("Activity didn't receive a Result in 5 seconds");
+ throw new TestResultNotFoundException(
+ "Activity didn't receive a Result in 5 seconds");
}
return result;
}
+ private static class TestResultNotFoundException extends IllegalStateException {
+ public TestResultNotFoundException(String description) {
+ super(description);
+ }
+ }
+
private static class ActivityBroadcastReceiver extends BroadcastReceiver {
private final SynchronousQueue<TestResult> mQueue;
public ActivityBroadcastReceiver(SynchronousQueue<TestResult> queue) {
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/util/src/com/android/cts/util/TestResult.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/util/src/com/android/cts/util/TestResult.java
index dd326d0..9664823 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/util/src/com/android/cts/util/TestResult.java
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/util/src/com/android/cts/util/TestResult.java
@@ -20,9 +20,6 @@
import android.content.Intent;
import android.os.Parcel;
import android.os.Parcelable;
-import android.os.Parcelable.Creator;
-
-import java.util.ArrayList;
public class TestResult implements Parcelable {
public static final String EXTRA_TEST_RESULT =
@@ -35,6 +32,7 @@
private final String mMethodName;
private final String mStatus;
private final String mException;
+ private final Intent mIntent;
private final boolean mInstantAppPackageInfoExposed;
public String getPackageName() {
@@ -61,6 +59,10 @@
return mInstantAppPackageInfoExposed;
}
+ public Intent getIntent() {
+ return mIntent;
+ }
+
public static Builder getBuilder() {
return new Builder();
}
@@ -74,12 +76,14 @@
}
private TestResult(String packageName, String componentName, String methodName,
- String status, String exception, boolean ephemeralPackageInfoExposed) {
+ String status, String exception, Intent intent,
+ boolean ephemeralPackageInfoExposed) {
mPackageName = packageName;
mComponentName = componentName;
mMethodName = methodName;
mStatus = status;
mException = exception;
+ mIntent = intent;
mInstantAppPackageInfoExposed = ephemeralPackageInfoExposed;
}
@@ -95,7 +99,8 @@
dest.writeString(mMethodName);
dest.writeString(mStatus);
dest.writeString(mException);
- dest.writeBoolean(mInstantAppPackageInfoExposed);
+ dest.writeParcelable(mIntent, 0 /* flags */);
+ dest.writeInt(mInstantAppPackageInfoExposed ? 1 : 0);
}
public static final Creator<TestResult> CREATOR = new Creator<TestResult>() {
@@ -113,6 +118,7 @@
mMethodName = source.readString();
mStatus = source.readString();
mException = source.readString();
+ mIntent = source.readParcelable(Object.class.getClassLoader());
mInstantAppPackageInfoExposed = source.readBoolean();
}
@@ -122,6 +128,7 @@
private String methodName;
private String status;
private String exception;
+ private Intent intent;
private boolean instantAppPackageInfoExposed;
private Builder() {
@@ -150,9 +157,13 @@
instantAppPackageInfoExposed = _instantAppPackageInfoExposed;
return this;
}
+ public Builder setIntent(Intent _intent) {
+ intent = _intent;
+ return this;
+ }
public TestResult build() {
return new TestResult(packageName, componentName, methodName,
- status, exception, instantAppPackageInfoExposed);
+ status, exception, intent, instantAppPackageInfoExposed);
}
}
}
diff --git a/hostsidetests/appsecurity/test-apps/StorageStatsApp/src/com/android/cts/storagestatsapp/StorageStatsTest.java b/hostsidetests/appsecurity/test-apps/StorageStatsApp/src/com/android/cts/storagestatsapp/StorageStatsTest.java
index 351c493..7b1abec 100644
--- a/hostsidetests/appsecurity/test-apps/StorageStatsApp/src/com/android/cts/storagestatsapp/StorageStatsTest.java
+++ b/hostsidetests/appsecurity/test-apps/StorageStatsApp/src/com/android/cts/storagestatsapp/StorageStatsTest.java
@@ -224,6 +224,9 @@
useWrite(makeUniqueFile(pics), 5 * MB_IN_BYTES);
useWrite(makeUniqueFile(pics), 5 * MB_IN_BYTES);
+ // for fuse file system
+ Thread.sleep(10000);
+
// TODO: remove this once 34723223 is fixed
logCommand("sync");
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java
index 23bf004..b9b652a 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java
@@ -17,6 +17,8 @@
package com.android.cts.usepermission;
import static junit.framework.Assert.assertEquals;
+
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertDirNoAccess;
@@ -551,6 +553,76 @@
assertAllPermissionsGrantState(PackageManager.PERMISSION_GRANTED);
}
+ @Test
+ public void testNullPermissionRequest() throws Exception {
+ String[] permissions = new String[] {null};
+
+ // Go through normal grant flow
+ BasePermissionActivity.Result result = requestPermissions(permissions,
+ REQUEST_CODE_PERMISSIONS,
+ BasePermissionActivity.class,
+ () -> { /* empty */ });
+
+ assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS,
+ permissions, new boolean[] {false});
+ }
+
+ @Test
+ public void testNullAndRealPermission() throws Exception {
+ // Make sure we don't have the permissions
+ assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
+ .checkSelfPermission(Manifest.permission.WRITE_CONTACTS));
+ assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
+ .checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE));
+
+ String[] permissions = new String[] {
+ null,
+ Manifest.permission.WRITE_CONTACTS,
+ null,
+ Manifest.permission.WRITE_EXTERNAL_STORAGE
+ };
+
+ // Request the permission and allow it
+ BasePermissionActivity.Result result = requestPermissions(permissions,
+ REQUEST_CODE_PERMISSIONS, BasePermissionActivity.class, () -> {
+ try {
+ clickAllowButton();
+ getUiDevice().waitForIdle();
+ clickAllowButton();
+ getUiDevice().waitForIdle();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ });
+
+ // Expect the permission are reported as granted
+ assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS,
+ permissions, new boolean[] {false, true, false, true});
+
+ // The permissions are granted
+ assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+ .checkSelfPermission(Manifest.permission.WRITE_CONTACTS));
+ assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+ .checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE));
+ }
+
+ @Test
+ public void testInvalidPermission() throws Exception {
+ String[] permissions = new String[] {
+ getInstrumentation().getContext().getPackageName() + ".abadname"
+ };
+
+ // Request the permission and allow it
+ BasePermissionActivity.Result result = requestPermissions(permissions,
+ REQUEST_CODE_PERMISSIONS,
+ BasePermissionActivity.class,
+ () -> { /* empty */ });
+
+ // Expect the permissions is not granted
+ assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS,
+ permissions, new boolean[] {false});
+ }
+
private void assertAllPermissionsRevoked() {
assertAllPermissionsGrantState(PackageManager.PERMISSION_DENIED);
}
diff --git a/hostsidetests/appsecurity/test-apps/V3SigningSchemeRotation/Android.mk b/hostsidetests/appsecurity/test-apps/V3SigningSchemeRotation/Android.mk
new file mode 100644
index 0000000..235a955
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/V3SigningSchemeRotation/Android.mk
@@ -0,0 +1,30 @@
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_JAVA_LIBRARIES := android.test.base.stubs
+LOCAL_PACKAGE_NAME := CtsV3SigningSchemeRotationTest
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/V3SigningSchemeRotation/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/V3SigningSchemeRotation/AndroidManifest.xml
new file mode 100644
index 0000000..677757f
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/V3SigningSchemeRotation/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.appsecurity.cts.v3rotationtests">
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:targetPackage="android.appsecurity.cts.v3rotationtests"
+ android:name="android.support.test.runner.AndroidJUnitRunner" />
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/V3SigningSchemeRotation/src/android/appsecurity/cts/v3rotationtests/V3RotationTest.java b/hostsidetests/appsecurity/test-apps/V3SigningSchemeRotation/src/android/appsecurity/cts/v3rotationtests/V3RotationTest.java
new file mode 100644
index 0000000..2459752
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/V3SigningSchemeRotation/src/android/appsecurity/cts/v3rotationtests/V3RotationTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.appsecurity.cts.v3rotationtests;
+
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.util.Log;
+import android.test.AndroidTestCase;
+
+import java.lang.Override;
+
+/**
+ * On-device tests for APK Signature Scheme v3 based signing certificate rotation
+ */
+public class V3RotationTest extends AndroidTestCase {
+
+ private static final String COMPANION_PKG = "android.appsecurity.cts.tinyapp_companion";
+ private static final String PERMISSION_NAME = "android.appsecurity.cts.tinyapp.perm";
+
+ public void testHasPerm() throws Exception {
+ PackageManager pm = getContext().getPackageManager();
+ assertTrue(PERMISSION_NAME + " not granted to " + COMPANION_PKG,
+ pm.checkPermission(PERMISSION_NAME, COMPANION_PKG)
+ == PackageManager.PERMISSION_GRANTED);
+ }
+
+ public void testHasNoPerm() throws Exception {
+ PackageManager pm = getContext().getPackageManager();
+ assertFalse(PERMISSION_NAME + " granted to " + COMPANION_PKG,
+ pm.checkPermission(PERMISSION_NAME, COMPANION_PKG)
+ == PackageManager.PERMISSION_GRANTED);
+ }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AssistScreenCaptureDisabledTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AssistScreenCaptureDisabledTest.java
index db54ac3..d076920 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AssistScreenCaptureDisabledTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AssistScreenCaptureDisabledTest.java
@@ -87,7 +87,11 @@
Intent showSessionIntent = new Intent(ACTION_SHOW_SESSION);
showSessionIntent.setPackage(ASSIST_PACKAGE);
mContext.sendBroadcast(showSessionIntent);
- Intent screenShotIntent = receiver.awaitForBroadcast();
+ Intent screenShotIntent = null;
+ for (int i = 0; i < MAX_ATTEMPTS_COUNT && (screenShotIntent == null); ++ i) {
+ Log.d(TAG, "has not received intent yet: wait for intent, attempt " + i);
+ screenShotIntent = receiver.awaitForBroadcast();
+ }
Assert.assertNotNull(screenShotIntent);
Assert.assertTrue(screenShotIntent.hasExtra(KEY_HAS_SCREENSHOT));
assertEquals(possible, screenShotIntent.getBooleanExtra(KEY_HAS_SCREENSHOT, false));
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PrintingPolicyTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PrintingPolicyTest.java
index 21503dd..29f6376 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PrintingPolicyTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PrintingPolicyTest.java
@@ -17,7 +17,7 @@
package com.android.cts.deviceandprofileowner;
import android.app.admin.DevicePolicyManager;
-import android.content.ComponentName;
+import android.os.UserManager;
/**
* Validates that Device Owner or Profile Owner can disable printing.
@@ -25,9 +25,8 @@
public class PrintingPolicyTest extends BaseDeviceAdminTest {
public void testPrintingPolicy() throws Exception {
- DevicePolicyManager.class
- .getDeclaredMethod("setPrintingEnabled", ComponentName.class, boolean.class)
- .invoke(mDevicePolicyManager, ADMIN_RECEIVER_COMPONENT, false);
+ mDevicePolicyManager.addUserRestriction(ADMIN_RECEIVER_COMPONENT,
+ UserManager.DISALLOW_PRINTING);
final PrintActivity activity = launchActivity("com.android.cts.deviceandprofileowner",
PrintActivity.class, null);
final String errorMessage = activity.getErrorMessage();
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CreateAndManageUserTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CreateAndManageUserTest.java
index cb2f9b2..b037092 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CreateAndManageUserTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CreateAndManageUserTest.java
@@ -73,7 +73,6 @@
private volatile boolean mReceived;
private volatile boolean mTestProfileOwnerWasUsed;
private volatile boolean mSetupComplete;
- private UserHandle mUserHandle;
@Override
protected void setUp() throws Exception {
@@ -86,11 +85,6 @@
protected void tearDown() throws Exception {
mDevicePolicyManager.clearUserRestriction(getWho(), UserManager.DISALLOW_ADD_USER);
mDevicePolicyManager.clearUserRestriction(getWho(), UserManager.DISALLOW_REMOVE_USER);
- // Remove user in case of failed test.
- if (mUserHandle != null) {
- mDevicePolicyManager.removeUser(getWho(), mUserHandle);
- mUserHandle = null;
- }
super.tearDown();
}
@@ -183,11 +177,11 @@
mContext.registerReceiver(receiver, filter);
synchronized (this) {
- mUserHandle = mDevicePolicyManager.createAndManageUser(getWho(), testUserName,
+ UserHandle userHandle = mDevicePolicyManager.createAndManageUser(getWho(), testUserName,
TestProfileOwner.getComponentName(), bundle, flags);
- assertNotNull(mUserHandle);
+ assertNotNull(userHandle);
- mDevicePolicyManager.switchUser(getWho(), mUserHandle);
+ mDevicePolicyManager.switchUser(getWho(), userHandle);
try {
wait(USER_SWITCH_DELAY);
} catch (InterruptedException e) {
@@ -201,9 +195,9 @@
assertTrue(mTestProfileOwnerWasUsed);
assertEquals(expectedSetupComplete, mSetupComplete);
- assertTrue(mDevicePolicyManager.removeUser(getWho(), mUserHandle));
+ assertTrue(mDevicePolicyManager.removeUser(getWho(), userHandle));
- mUserHandle = null;
+ userHandle = null;
}
mContext.unregisterReceiver(receiver);
@@ -212,17 +206,17 @@
public void testCreateAndManageUser_GetSecondaryUsers() throws Exception {
String testUserName = "TestUser_" + System.currentTimeMillis();
- mUserHandle = mDevicePolicyManager.createAndManageUser(
+ UserHandle userHandle = mDevicePolicyManager.createAndManageUser(
getWho(),
testUserName,
getWho(),
null,
/* flags */ 0);
- Log.d(TAG, "User create: " + mUserHandle);
+ Log.d(TAG, "User create: " + userHandle);
List<UserHandle> secondaryUsers = mDevicePolicyManager.getSecondaryUsers(getWho());
assertEquals(1, secondaryUsers.size());
- assertEquals(mUserHandle, secondaryUsers.get(0));
+ assertEquals(userHandle, secondaryUsers.get(0));
}
public void testCreateAndManageUser_SwitchUser() throws Exception {
@@ -231,20 +225,20 @@
String testUserName = "TestUser_" + System.currentTimeMillis();
- mUserHandle = mDevicePolicyManager.createAndManageUser(
+ UserHandle userHandle = mDevicePolicyManager.createAndManageUser(
getWho(),
testUserName,
getWho(),
null,
/* flags */ 0);
- Log.d(TAG, "User create: " + mUserHandle);
+ Log.d(TAG, "User create: " + userHandle);
LocalBroadcastReceiver broadcastReceiver = new LocalBroadcastReceiver();
localBroadcastManager.registerReceiver(broadcastReceiver,
new IntentFilter(BasicAdminReceiver.ACTION_USER_SWITCHED));
try {
- assertTrue(mDevicePolicyManager.switchUser(getWho(), mUserHandle));
- assertEquals(mUserHandle, broadcastReceiver.waitForBroadcastReceived());
+ assertTrue(mDevicePolicyManager.switchUser(getWho(), userHandle));
+ assertEquals(userHandle, broadcastReceiver.waitForBroadcastReceived());
} finally {
localBroadcastManager.unregisterReceiver(broadcastReceiver);
}
@@ -256,22 +250,22 @@
String testUserName = "TestUser_" + System.currentTimeMillis();
- mUserHandle = mDevicePolicyManager.createAndManageUser(
+ UserHandle userHandle = mDevicePolicyManager.createAndManageUser(
getWho(),
testUserName,
getWho(),
null,
/* flags */ 0);
- Log.d(TAG, "User create: " + mUserHandle);
+ Log.d(TAG, "User create: " + userHandle);
LocalBroadcastReceiver broadcastReceiver = new LocalBroadcastReceiver();
localBroadcastManager.registerReceiver(broadcastReceiver,
new IntentFilter(BasicAdminReceiver.ACTION_USER_SWITCHED));
try {
- assertTrue(mDevicePolicyManager.switchUser(getWho(), mUserHandle));
- assertEquals(mUserHandle, broadcastReceiver.waitForBroadcastReceived());
+ assertTrue(mDevicePolicyManager.switchUser(getWho(), userHandle));
+ assertEquals(userHandle, broadcastReceiver.waitForBroadcastReceived());
assertEquals(DevicePolicyManager.USER_OPERATION_ERROR_CURRENT_USER,
- mDevicePolicyManager.stopUser(getWho(), mUserHandle));
+ mDevicePolicyManager.stopUser(getWho(), userHandle));
} finally {
localBroadcastManager.unregisterReceiver(broadcastReceiver);
}
@@ -283,7 +277,6 @@
String testUserName = "TestUser_" + System.currentTimeMillis();
- // Do not assign return value to mUserHandle, so it is not removed in tearDown.
UserHandle userHandle = mDevicePolicyManager.createAndManageUser(
getWho(),
testUserName,
@@ -309,17 +302,17 @@
public void testCreateAndManageUser_StartInBackground_MaxRunningUsers() throws Exception {
String testUserName = "TestUser_" + System.currentTimeMillis();
- mUserHandle = mDevicePolicyManager.createAndManageUser(
+ UserHandle userHandle = mDevicePolicyManager.createAndManageUser(
getWho(),
testUserName,
getWho(),
null,
/* flags */ 0);
- Log.d(TAG, "User create: " + mUserHandle);
+ Log.d(TAG, "User create: " + userHandle);
// Start user in background and should receive max running users error
assertEquals(DevicePolicyManager.USER_OPERATION_ERROR_MAX_RUNNING_USERS,
- mDevicePolicyManager.startUserInBackground(getWho(), mUserHandle));
+ mDevicePolicyManager.startUserInBackground(getWho(), userHandle));
}
public void testCreateAndManageUser_StopUser() throws Exception {
@@ -328,7 +321,6 @@
String testUserName = "TestUser_" + System.currentTimeMillis();
- // Do not assign return value to mUserHandle, so it is not removed in tearDown.
UserHandle userHandle = mDevicePolicyManager.createAndManageUser(
getWho(),
testUserName,
@@ -352,6 +344,40 @@
}
}
+ public void testCreateAndManageUser_StopEphemeralUser_DisallowRemoveUser() throws Exception {
+ LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(
+ getContext());
+
+ String testUserName = "TestUser_" + System.currentTimeMillis();
+
+ // Set DISALLOW_REMOVE_USER restriction
+ mDevicePolicyManager.addUserRestriction(getWho(), UserManager.DISALLOW_REMOVE_USER);
+
+ UserHandle userHandle = mDevicePolicyManager.createAndManageUser(
+ getWho(),
+ testUserName,
+ getWho(),
+ null,
+ DevicePolicyManager.MAKE_USER_EPHEMERAL);
+ Log.d(TAG, "User create: " + userHandle);
+ assertEquals(DevicePolicyManager.USER_OPERATION_SUCCESS,
+ mDevicePolicyManager.startUserInBackground(getWho(), userHandle));
+
+ LocalBroadcastReceiver broadcastReceiver = new LocalBroadcastReceiver();
+ localBroadcastManager.registerReceiver(broadcastReceiver,
+ new IntentFilter(BasicAdminReceiver.ACTION_USER_REMOVED));
+
+ try {
+ assertEquals(DevicePolicyManager.USER_OPERATION_SUCCESS,
+ mDevicePolicyManager.stopUser(getWho(), userHandle));
+ assertEquals(userHandle, broadcastReceiver.waitForBroadcastReceived());
+ } finally {
+ localBroadcastManager.unregisterReceiver(broadcastReceiver);
+ // Clear DISALLOW_REMOVE_USER restriction
+ mDevicePolicyManager.clearUserRestriction(getWho(), UserManager.DISALLOW_REMOVE_USER);
+ }
+ }
+
@SuppressWarnings("unused")
private static void logoutUser(Context context, DevicePolicyManager devicePolicyManager,
ComponentName componentName) {
@@ -438,7 +464,6 @@
bundle.putString(EXTRA_AFFILIATION_ID, AFFILIATION_ID);
bundle.putString(EXTRA_METHOD_NAME, methodName);
- // Do not assign return value to mUserHandle, so it is not removed in tearDown.
UserHandle userHandle = mDevicePolicyManager.createAndManageUser(
getWho(),
testUserName,
@@ -468,19 +493,19 @@
public void testCreateAndManageUser_AddRestrictionSet() {
mDevicePolicyManager.addUserRestriction(getWho(), UserManager.DISALLOW_ADD_USER);
- mUserHandle = mDevicePolicyManager.createAndManageUser(getWho(), "Test User", getWho(),
- null, 0);
- assertNotNull(mUserHandle);
+ UserHandle userHandle = mDevicePolicyManager.createAndManageUser(getWho(), "Test User",
+ getWho(), null, 0);
+ assertNotNull(userHandle);
}
public void testCreateAndManageUser_RemoveRestrictionSet() {
mDevicePolicyManager.addUserRestriction(getWho(), UserManager.DISALLOW_REMOVE_USER);
- mUserHandle = mDevicePolicyManager.createAndManageUser(getWho(), "Test User", getWho(),
- null, 0);
- assertNotNull(mUserHandle);
+ UserHandle userHandle = mDevicePolicyManager.createAndManageUser(getWho(), "Test User",
+ getWho(), null, 0);
+ assertNotNull(userHandle);
- boolean removed = mDevicePolicyManager.removeUser(getWho(), mUserHandle);
+ boolean removed = mDevicePolicyManager.removeUser(getWho(), userHandle);
// When the device owner itself has set the user restriction, it should still be allowed
// to remove a user.
assertTrue(removed);
@@ -492,20 +517,20 @@
getContext());
localBroadcastManager.registerReceiver(receiver,
new IntentFilter(BasicAdminReceiver.ACTION_USER_ADDED));
+ UserHandle userHandle;
try {
- mUserHandle = mDevicePolicyManager.createAndManageUser(getWho(), "Test User", getWho(),
+ userHandle = mDevicePolicyManager.createAndManageUser(getWho(), "Test User", getWho(),
null, 0);
- assertNotNull(mUserHandle);
- assertEquals(mUserHandle, receiver.waitForBroadcastReceived());
+ assertNotNull(userHandle);
+ assertEquals(userHandle, receiver.waitForBroadcastReceived());
} finally {
localBroadcastManager.unregisterReceiver(receiver);
}
localBroadcastManager.registerReceiver(receiver,
new IntentFilter(BasicAdminReceiver.ACTION_USER_REMOVED));
try {
- assertTrue(mDevicePolicyManager.removeUser(getWho(), mUserHandle));
- assertEquals(mUserHandle, receiver.waitForBroadcastReceived());
- mUserHandle = null;
+ assertTrue(mDevicePolicyManager.removeUser(getWho(), userHandle));
+ assertEquals(userHandle, receiver.waitForBroadcastReceived());
} finally {
localBroadcastManager.unregisterReceiver(receiver);
}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SecurityLoggingTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SecurityLoggingTest.java
index bc4fe8d..7fd3e7e 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SecurityLoggingTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SecurityLoggingTest.java
@@ -15,16 +15,99 @@
*/
package com.android.cts.deviceowner;
+import static android.app.admin.SecurityLog.TAG_ADB_SHELL_CMD;
+import static android.app.admin.SecurityLog.TAG_ADB_SHELL_INTERACTIVE;
+import static android.app.admin.SecurityLog.TAG_APP_PROCESS_START;
+import static android.app.admin.SecurityLog.TAG_CERT_AUTHORITY_INSTALLED;
+import static android.app.admin.SecurityLog.TAG_CERT_AUTHORITY_REMOVED;
+import static android.app.admin.SecurityLog.TAG_CRYPTO_SELF_TEST_COMPLETED;
+import static android.app.admin.SecurityLog.TAG_KEYGUARD_DISABLED_FEATURES_SET;
+import static android.app.admin.SecurityLog.TAG_KEYGUARD_DISMISSED;
+import static android.app.admin.SecurityLog.TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT;
+import static android.app.admin.SecurityLog.TAG_KEYGUARD_SECURED;
+import static android.app.admin.SecurityLog.TAG_KEY_DESTRUCTION;
+import static android.app.admin.SecurityLog.TAG_KEY_GENERATED;
+import static android.app.admin.SecurityLog.TAG_KEY_IMPORT;
+import static android.app.admin.SecurityLog.TAG_LOGGING_STARTED;
+import static android.app.admin.SecurityLog.TAG_LOGGING_STOPPED;
+import static android.app.admin.SecurityLog.TAG_LOG_BUFFER_SIZE_CRITICAL;
+import static android.app.admin.SecurityLog.TAG_MAX_PASSWORD_ATTEMPTS_SET;
+import static android.app.admin.SecurityLog.TAG_MAX_SCREEN_LOCK_TIMEOUT_SET;
+import static android.app.admin.SecurityLog.TAG_MEDIA_MOUNT;
+import static android.app.admin.SecurityLog.TAG_MEDIA_UNMOUNT;
+import static android.app.admin.SecurityLog.TAG_OS_SHUTDOWN;
+import static android.app.admin.SecurityLog.TAG_OS_STARTUP;
+import static android.app.admin.SecurityLog.TAG_PASSWORD_COMPLEXITY_SET;
+import static android.app.admin.SecurityLog.TAG_PASSWORD_EXPIRATION_SET;
+import static android.app.admin.SecurityLog.TAG_PASSWORD_HISTORY_LENGTH_SET;
+import static android.app.admin.SecurityLog.TAG_REMOTE_LOCK;
+import static android.app.admin.SecurityLog.TAG_SYNC_RECV_FILE;
+import static android.app.admin.SecurityLog.TAG_SYNC_SEND_FILE;
+import static android.app.admin.SecurityLog.TAG_USER_RESTRICTION_ADDED;
+import static android.app.admin.SecurityLog.TAG_USER_RESTRICTION_REMOVED;
+import static android.app.admin.SecurityLog.TAG_WIPE_FAILURE;
+
+import static com.google.common.collect.ImmutableList.of;
+
import android.app.admin.SecurityLog.SecurityEvent;
+import android.content.Context;
+import android.content.SharedPreferences;
import android.os.Parcel;
import android.support.test.InstrumentationRegistry;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
import java.util.Arrays;
import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
public class SecurityLoggingTest extends BaseDeviceOwnerTest {
private static final String ARG_BATCH_NUMBER = "batchNumber";
- private static final int BUFFER_ENTRIES_NOTIFICATION_LEVEL = 1024;
+ private static final String PREF_KEY_PREFIX = "batch-last-id-";
+ private static final String PREF_NAME = "batchIds";
+
+ // For brevity.
+ private static final Class<String> S = String.class;
+ private static final Class<Long> L = Long.class;
+ private static final Class<Integer> I = Integer.class;
+
+ private static final Map<Integer, List<Class>> PAYLOAD_TYPES_MAP =
+ new ImmutableMap.Builder<Integer, List<Class>>()
+ .put(TAG_ADB_SHELL_INTERACTIVE, of())
+ .put(TAG_ADB_SHELL_CMD, of(S))
+ .put(TAG_SYNC_RECV_FILE, of(S))
+ .put(TAG_SYNC_SEND_FILE, of(S))
+ .put(TAG_APP_PROCESS_START, of(S, L, I, I, S, S))
+ .put(TAG_KEYGUARD_DISMISSED, of())
+ .put(TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT, of(I, I))
+ .put(TAG_KEYGUARD_SECURED, of())
+ .put(TAG_OS_STARTUP, of(S, S))
+ .put(TAG_OS_SHUTDOWN, of())
+ .put(TAG_LOGGING_STARTED, of())
+ .put(TAG_LOGGING_STOPPED, of())
+ .put(TAG_MEDIA_MOUNT, of(S, S))
+ .put(TAG_MEDIA_UNMOUNT, of(S, S))
+ .put(TAG_LOG_BUFFER_SIZE_CRITICAL, of())
+ .put(TAG_PASSWORD_EXPIRATION_SET, of(S, I, I, L))
+ .put(TAG_PASSWORD_COMPLEXITY_SET, of(S, I, I, I, I, I, I, I, I, I, I))
+ .put(TAG_PASSWORD_HISTORY_LENGTH_SET, of(S, I, I, I))
+ .put(TAG_MAX_SCREEN_LOCK_TIMEOUT_SET, of(S, I, I, L))
+ .put(TAG_MAX_PASSWORD_ATTEMPTS_SET, of(S, I, I, I))
+ .put(TAG_KEYGUARD_DISABLED_FEATURES_SET, of(S, I, I, I))
+ .put(TAG_REMOTE_LOCK, of(S, I))
+ .put(TAG_WIPE_FAILURE, of())
+ .put(TAG_KEY_GENERATED, of(I, S, I))
+ .put(TAG_KEY_IMPORT, of(I, S, I))
+ .put(TAG_KEY_DESTRUCTION, of(I, S, I))
+ .put(TAG_CERT_AUTHORITY_INSTALLED, of(I, S))
+ .put(TAG_CERT_AUTHORITY_REMOVED, of(I, S))
+ .put(TAG_USER_RESTRICTION_ADDED, of(S, I, S))
+ .put(TAG_USER_RESTRICTION_REMOVED, of(S, I, S))
+ .put(TAG_CRYPTO_SELF_TEST_COMPLETED, of(I))
+ .build();
/**
* Test: retrieving security logs can only be done if there's one user on the device or all
@@ -52,25 +135,36 @@
/**
* Test: retrieving security logs. This test has should be called when security logging is
- * enabled and directly after reboot with device owner installed so that security logging
- * actually takes place and fetching the logs isn't subject to rate limiting.
+ * enabled and a batch of events is available.
*/
- public void testGetSecurityLogs() {
- List<SecurityEvent> events = mDevicePolicyManager.retrieveSecurityLogs(getWho());
- String param = InstrumentationRegistry.getArguments().getString(ARG_BATCH_NUMBER);
- int batchNumber = param == null ? 0 : Integer.parseInt(param);
+ public void testGetSecurityLogs() throws Exception {
+ List<SecurityEvent> events = null;
+ // Retry once after seeping for 1 second, in case "dpm force-security-logs" hasn't taken
+ // effect just yet.
+ for (int i = 0; i < 2 && events == null; i++) {
+ events = mDevicePolicyManager.retrieveSecurityLogs(getWho());
+ if (events == null) Thread.sleep(1000);
+ }
+
+ final String param = InstrumentationRegistry.getArguments().getString(ARG_BATCH_NUMBER);
+ final int batchNumber = param == null ? 0 : Integer.parseInt(param);
verifySecurityLogs(batchNumber, events);
}
- private static void verifySecurityLogs(int batchNumber, List<SecurityEvent> events) {
+ private void verifySecurityLogs(int batchNumber, List<SecurityEvent> events) {
assertTrue("Unable to get events", events != null && events.size() > 0);
- assertTrue(
- "First id in batch " + events.get(0).getId() + " is too small for the batch number "
- + batchNumber,
- events.get(0).getId() >= (BUFFER_ENTRIES_NOTIFICATION_LEVEL * batchNumber));
+
+ verifyContinuousIdsBetweenBatches(batchNumber, events);
+
+ if (batchNumber == 0) {
+ verifyAutomaticEvents(events);
+ }
+
// We don't know much about the events, so just call public API methods.
for (int i = 0; i < events.size(); i++) {
- SecurityEvent event = events.get(i);
+ final SecurityEvent event = events.get(i);
+
+ verifyPayloadTypes(event);
// Test id for monotonically increasing.
if (i > 0) {
@@ -84,7 +178,7 @@
p.setDataPosition(0);
// Restore from parcel and check contents.
- SecurityEvent restored = SecurityEvent.CREATOR.createFromParcel(p);
+ final SecurityEvent restored = SecurityEvent.CREATOR.createFromParcel(p);
p.recycle();
// For some events data is encapsulated into Object array.
@@ -106,6 +200,103 @@
}
}
+ private void verifyPayloadTypes(SecurityEvent event) {
+ final List<Class> payloadTypes = PAYLOAD_TYPES_MAP.get(event.getTag());
+ assertNotNull("event type unknown: " + event.getTag(), payloadTypes);
+
+ if (payloadTypes.size() == 0) {
+ // No payload.
+ assertNull("non-null payload", event.getData());
+ } else if (payloadTypes.size() == 1) {
+ // Singleton payload.
+ assertTrue(payloadTypes.get(0).isInstance(event.getData()));
+ } else {
+ // Payload is incapsulated into Object[]
+ assertTrue(event.getData() instanceof Object[]);
+ final Object[] dataArray = (Object[]) event.getData();
+ assertEquals(payloadTypes.size(), dataArray.length);
+ for (int i = 0; i < payloadTypes.size(); i++) {
+ assertTrue(payloadTypes.get(i).isInstance(dataArray[i]));
+ }
+ }
+ }
+
+ private void verifyAutomaticEvents(List<SecurityEvent> events) {
+ verifyOsStartup(events);
+ verifyLoggingStarted(events);
+ verifyCryptoSelfTest(events);
+ }
+
+ private void verifyOsStartup(List<SecurityEvent> events) {
+ final SecurityEvent event = findEvent("os startup", events, TAG_OS_STARTUP);
+ // Verified boot state
+ assertTrue(ImmutableSet.of("green", "yellow", "orange").contains(getString(event, 0)));
+ // dm-verity mode
+ assertTrue(ImmutableSet.of("enforcing", "eio").contains(getString(event, 1)));
+ }
+
+ private void verifyCryptoSelfTest(List<SecurityEvent> events) {
+ final SecurityEvent event = findEvent("crypto self test complete",
+ events, TAG_CRYPTO_SELF_TEST_COMPLETED);
+ // Success code.
+ assertEquals(1, getInt(event));
+ }
+
+ private void verifyLoggingStarted(List<SecurityEvent> events) {
+ findEvent("logging started", events, TAG_LOGGING_STARTED);
+ }
+
+ private SecurityEvent findEvent(String description, List<SecurityEvent> events, int tag) {
+ return findEvent(description, events, e -> e.getTag() == tag);
+ }
+
+ private SecurityEvent findEvent(String description, List<SecurityEvent> events,
+ Predicate<SecurityEvent> predicate) {
+ final List<SecurityEvent> matches =
+ events.stream().filter(predicate).collect(Collectors.toList());
+ assertEquals("Invalid number of events: " + description, 1, matches.size());
+ return matches.get(0);
+ }
+
+ private static Object getDatum(SecurityEvent event, int pos) {
+ final Object[] dataArray = (Object[]) event.getData();
+ return dataArray[pos];
+ }
+
+ private static String getString(SecurityEvent event, int pos) {
+ return (String) getDatum(event, pos);
+ }
+
+ private static int getInt(SecurityEvent event) {
+ assertTrue(event.getData() instanceof Integer);
+ return (Integer) event.getData();
+ }
+
+ /**
+ * Check that there are no gaps between ids in two consecutive batches. Shared preference is
+ * used to store these numbers between invocations.
+ */
+ private void verifyContinuousIdsBetweenBatches(int batchNumber, List<SecurityEvent> events) {
+ final SharedPreferences prefs =
+ mContext.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
+
+ final long firstId = events.get(0).getId();
+ if (batchNumber == 0) {
+ assertEquals("Event id wasn't reset.", 0L, firstId);
+ } else {
+ final String prevBatchLastIdKey = PREF_KEY_PREFIX + (batchNumber - 1);
+ assertTrue("Last event id from previous batch not found in shared prefs",
+ prefs.contains(prevBatchLastIdKey));
+ final long prevBatchLastId = prefs.getLong(prevBatchLastIdKey, 0);
+ assertEquals("Event ids aren't consecutive between batches",
+ firstId, prevBatchLastId + 1);
+ }
+
+ final String currBatchLastIdKey = PREF_KEY_PREFIX + batchNumber;
+ final long lastId = events.get(events.size() - 1).getId();
+ prefs.edit().putLong(currBatchLastIdKey, lastId).commit();
+ }
+
/**
* Test: Test enabling security logging. This test should be executed after installing a device
* owner so that we check that logging is not enabled by default. This test has a side effect:
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/SanityTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/SanityTest.java
index 28c7e25..683d465 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/SanityTest.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/SanityTest.java
@@ -62,6 +62,7 @@
intent.setComponent(SIMPLE_APP_ACTIVITY);
// Finish the activity after that.
intent.putExtra("finish", true);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
Intent receivedBroadcast = receiver.awaitForBroadcast();
assertNotNull(receivedBroadcast);
diff --git a/hostsidetests/devicepolicy/app/TransferOwnerIncomingApp/src/com/android/cts/transferowner/DeviceAndProfileOwnerTransferIncomingTest.java b/hostsidetests/devicepolicy/app/TransferOwnerIncomingApp/src/com/android/cts/transferowner/DeviceAndProfileOwnerTransferIncomingTest.java
index cc2fb86..7a598d9 100644
--- a/hostsidetests/devicepolicy/app/TransferOwnerIncomingApp/src/com/android/cts/transferowner/DeviceAndProfileOwnerTransferIncomingTest.java
+++ b/hostsidetests/devicepolicy/app/TransferOwnerIncomingApp/src/com/android/cts/transferowner/DeviceAndProfileOwnerTransferIncomingTest.java
@@ -25,7 +25,6 @@
import android.content.Context;
import android.content.SharedPreferences;
import android.os.PersistableBundle;
-import android.os.UserHandle;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
@@ -43,11 +42,6 @@
public void onTransferOwnershipComplete(Context context, PersistableBundle bundle) {
putBooleanPref(context, KEY_TRANSFER_COMPLETED_CALLED, true);
}
-
- @Override
- public void onTransferAffiliatedProfileOwnershipComplete(Context context, UserHandle user) {
- putBooleanPref(context, KEY_TRANSFER_AFFILIATED_PROFILE_COMPLETED_CALLED, true);
- }
}
public static class BasicAdminReceiverNoMetadata extends DeviceAdminReceiver {
@@ -57,8 +51,6 @@
private final static String SHARED_PREFERENCE_NAME = "shared-preference-name";
private final static String KEY_TRANSFER_COMPLETED_CALLED = "key-transfer-completed-called";
private final static String ARE_PARAMETERS_SAVED = "ARE_PARAMETERS_SAVED";
- final static String KEY_TRANSFER_AFFILIATED_PROFILE_COMPLETED_CALLED =
- "key-transfer-affiliated-completed-called";
protected Context mContext;
protected ComponentName mIncomingComponentName;
@@ -91,6 +83,7 @@
return affiliationIds.iterator().next();
}
+ @Test
public void testTransferOwnershipBundleLoaded() throws Throwable {
PersistableBundle bundle = mDevicePolicyManager.getTransferOwnershipBundle();
assertNotNull(bundle);
diff --git a/hostsidetests/devicepolicy/app/TransferOwnerIncomingApp/src/com/android/cts/transferowner/TransferDeviceOwnerIncomingTest.java b/hostsidetests/devicepolicy/app/TransferOwnerIncomingApp/src/com/android/cts/transferowner/TransferDeviceOwnerIncomingTest.java
index 7054d07..b33da04 100644
--- a/hostsidetests/devicepolicy/app/TransferOwnerIncomingApp/src/com/android/cts/transferowner/TransferDeviceOwnerIncomingTest.java
+++ b/hostsidetests/devicepolicy/app/TransferOwnerIncomingApp/src/com/android/cts/transferowner/TransferDeviceOwnerIncomingTest.java
@@ -49,9 +49,4 @@
&& policy1.getInstallWindowStart() == policy2.getInstallWindowStart()
&& policy1.getInstallWindowEnd() == policy2.getInstallWindowEnd());
}
-
- @Test
- public void testTransferAffiliatedProfileOwnershipCompleteCallbackIsCalled() {
- assertTrue(getBooleanPref(mContext, KEY_TRANSFER_AFFILIATED_PROFILE_COMPLETED_CALLED));
- }
}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index b41eac3..ed2b193 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -18,7 +18,6 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.CollectingOutputReceiver;
@@ -27,6 +26,7 @@
import com.android.tradefed.result.CollectingTestListener;
import com.android.tradefed.result.FileInputStreamSource;
import com.android.tradefed.result.LogDataType;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.result.TestResult;
import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.testtype.DeviceTestCase;
@@ -405,7 +405,7 @@
if (result.hasFailedTests()) {
// build a meaningful error message
StringBuilder errorBuilder = new StringBuilder("On-device tests failed:\n");
- for (Map.Entry<TestIdentifier, TestResult> resultEntry :
+ for (Map.Entry<TestDescription, TestResult> resultEntry :
result.getTestResults().entrySet()) {
if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
errorBuilder.append(resultEntry.getKey().toString());
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index 519c195..f4db369 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -56,10 +56,13 @@
private static final String TEST_APP_LOCATION = "/data/local/tmp/cts/packageinstaller/";
private static final String ARG_SECURITY_LOGGING_BATCH_NUMBER = "batchNumber";
- private static final int BUFFER_SECURITY_ENTRIES_NOTIFICATION_LEVEL = 1024;
+ private static final int SECURITY_EVENTS_BATCH_SIZE = 100;
private static final String ARG_NETWORK_LOGGING_BATCH_COUNT = "batchCount";
+ /** CreateAndManageUser is available and an additional user can be created. */
+ private boolean mHasCreateAndManageUserFeature;
+
/** Forcing ephemeral users is implemented and supported on the device. */
private boolean mHasForceEphemeralUserFeature;
@@ -69,9 +72,6 @@
*/
private boolean mHasDisabledForceEphemeralUserFeature;
- /** CreateAndManageUser is available and an additional user can be created. */
- private boolean mHasCreateAndManageUserFeature;
-
@Override
protected void setUp() throws Exception {
super.setUp();
@@ -84,11 +84,12 @@
fail("Failed to set device owner");
}
}
- mHasForceEphemeralUserFeature = mHasFeature && canCreateAdditionalUsers(1)
+ mHasCreateAndManageUserFeature = mHasFeature && canCreateAdditionalUsers(1)
+ && hasDeviceFeature("android.software.managed_users");
+ mHasForceEphemeralUserFeature = mHasCreateAndManageUserFeature
&& hasUserSplit();
- mHasDisabledForceEphemeralUserFeature = mHasFeature && canCreateAdditionalUsers(1)
+ mHasDisabledForceEphemeralUserFeature = mHasCreateAndManageUserFeature
&& !hasUserSplit();
- mHasCreateAndManageUserFeature = mHasFeature && canCreateAdditionalUsers(1);
}
@Override
@@ -241,7 +242,7 @@
* {@link android.app.admin.DevicePolicyManager#getSecondaryUsers} is tested.
*/
public void testCreateAndManageUser_GetSecondaryUsers() throws Exception {
- if (!mHasFeature || !canCreateAdditionalUsers(1)) {
+ if (!mHasCreateAndManageUserFeature) {
return;
}
@@ -255,7 +256,7 @@
* {@link android.app.admin.DevicePolicyManager#switchUser} is tested.
*/
public void testCreateAndManageUser_SwitchUser() throws Exception {
- if (!mHasFeature || !canCreateAdditionalUsers(1) || !canStartAdditionalUsers(1)) {
+ if (!mHasCreateAndManageUserFeature || !canStartAdditionalUsers(1)) {
return;
}
@@ -269,7 +270,7 @@
* {@link android.app.admin.DevicePolicyManager#stopUser} is tested.
*/
public void testCreateAndManageUser_CannotStopCurrentUser() throws Exception {
- if (!mHasFeature || !canCreateAdditionalUsers(1) || !canStartAdditionalUsers(1)) {
+ if (!mHasCreateAndManageUserFeature || !canStartAdditionalUsers(1)) {
return;
}
@@ -283,7 +284,7 @@
* {@link android.app.admin.DevicePolicyManager#startUserInBackground} is tested.
*/
public void testCreateAndManageUser_StartInBackground() throws Exception {
- if (!mHasFeature || !canCreateAdditionalUsers(1) || !canStartAdditionalUsers(1)) {
+ if (!mHasCreateAndManageUserFeature || !canStartAdditionalUsers(1)) {
return;
}
@@ -297,7 +298,7 @@
* {@link android.app.admin.DevicePolicyManager#startUserInBackground} is tested.
*/
public void testCreateAndManageUser_StartInBackground_MaxRunningUsers() throws Exception {
- if (!mHasFeature || !canCreateAdditionalUsers(1)) {
+ if (!mHasCreateAndManageUserFeature) {
return;
}
@@ -318,7 +319,7 @@
* {@link android.app.admin.DevicePolicyManager#stopUser} is tested.
*/
public void testCreateAndManageUser_StopUser() throws Exception {
- if (!mHasFeature || !canCreateAdditionalUsers(1) || !canStartAdditionalUsers(1)) {
+ if (!mHasCreateAndManageUserFeature || !canStartAdditionalUsers(1)) {
return;
}
@@ -328,12 +329,27 @@
}
/**
+ * Test creating an ephemeral user using the DevicePolicyManager's createAndManageUser method
+ * and start the user in background, user is then stopped. The user should be removed
+ * automatically even when DISALLOW_REMOVE_USER is set.
+ */
+ public void testCreateAndManageUser_StopEphemeralUser_DisallowRemoveUser() throws Exception {
+ if (!mHasCreateAndManageUserFeature || !canStartAdditionalUsers(1)) {
+ return;
+ }
+
+ executeDeviceTestMethod(".CreateAndManageUserTest",
+ "testCreateAndManageUser_StopEphemeralUser_DisallowRemoveUser");
+ assertEquals(0, getUsersCreatedByTests().size());
+ }
+
+ /**
* Test creating an user using the DevicePolicyManager's createAndManageUser method, affiliate
* the user and start the user in background to test APIs on that user.
* {@link android.app.admin.DevicePolicyManager#logoutUser} is tested.
*/
public void testCreateAndManageUser_LogoutUser() throws Exception {
- if (!mHasFeature || !canCreateAdditionalUsers(1) || !canStartAdditionalUsers(1)) {
+ if (!mHasCreateAndManageUserFeature || !canStartAdditionalUsers(1)) {
return;
}
@@ -348,7 +364,7 @@
* {@link android.app.admin.DevicePolicyManager#isAffiliatedUser} is tested.
*/
public void testCreateAndManageUser_Affiliated() throws Exception {
- if (!mHasFeature || !canCreateAdditionalUsers(1) || !canStartAdditionalUsers(1)) {
+ if (!mHasCreateAndManageUserFeature || !canStartAdditionalUsers(1)) {
return;
}
@@ -362,7 +378,7 @@
* {@link android.app.admin.DevicePolicyManager#isEphemeralUser} is tested.
*/
public void testCreateAndManageUser_Ephemeral() throws Exception {
- if (!mHasFeature || !canCreateAdditionalUsers(1) || !canStartAdditionalUsers(1)) {
+ if (!mHasCreateAndManageUserFeature || !canStartAdditionalUsers(1)) {
return;
}
@@ -384,7 +400,7 @@
* {@link android.app.admin.DevicePolicyManager#LEAVE_ALL_SYSTEM_APPS_ENABLED} is tested.
*/
public void testCreateAndManageUser_LeaveAllSystemApps() throws Exception {
- if (!mHasFeature || !canCreateAdditionalUsers(1) || !canStartAdditionalUsers(1)) {
+ if (!mHasCreateAndManageUserFeature || !canStartAdditionalUsers(1)) {
return;
}
@@ -408,21 +424,21 @@
}
public void testCreateAndManageUser_AddRestrictionSet() throws Exception {
- if (mHasFeature && canCreateAdditionalUsers(1)) {
+ if (mHasCreateAndManageUserFeature) {
executeDeviceTestMethod(".CreateAndManageUserTest",
"testCreateAndManageUser_AddRestrictionSet");
}
}
public void testCreateAndManageUser_RemoveRestrictionSet() throws Exception {
- if (mHasFeature && canCreateAdditionalUsers(1)) {
+ if (mHasCreateAndManageUserFeature) {
executeDeviceTestMethod(".CreateAndManageUserTest",
"testCreateAndManageUser_RemoveRestrictionSet");
}
}
public void testUserAddedOrRemovedBroadcasts() throws Exception {
- if (mHasFeature && canCreateAdditionalUsers(1)) {
+ if (mHasCreateAndManageUserFeature) {
executeDeviceTestMethod(".CreateAndManageUserTest",
"testUserAddedOrRemovedBroadcasts");
}
@@ -455,23 +471,22 @@
executeDeviceTestMethod(".SecurityLoggingTest", "testDisablingSecurityLogging");
// Generate more than enough events for a batch of security events.
- int batchSize = BUFFER_SECURITY_ENTRIES_NOTIFICATION_LEVEL + 100;
try {
executeDeviceTestMethod(".SecurityLoggingTest", "testEnablingSecurityLogging");
// Reboot to ensure ro.device_owner is set to true in logd.
rebootAndWaitUntilReady();
// First batch: retrieve and verify the events.
- runBatch(0, batchSize);
+ runBatch(0);
// Verify event ids are consistent across a consecutive batch.
- runBatch(1, batchSize);
+ runBatch(1);
// Reboot the device, so the security event ids are reset.
rebootAndWaitUntilReady();
// First batch after reboot: retrieve and verify the events.
- runBatch(0 /* batch number */, batchSize);
+ runBatch(0 /* batch number */);
// Immediately attempting to fetch events again should fail.
executeDeviceTestMethod(".SecurityLoggingTest",
@@ -482,16 +497,14 @@
}
}
- private void runBatch(int batchNumber, int batchSize) throws Exception {
+ private void runBatch(int batchNumber) throws Exception {
// Trigger security events of type TAG_ADB_SHELL_CMD.
- for (int i = 0; i < batchSize; i++) {
- getDevice().executeShellCommand("adb shell echo just_testing_" + i);
+ for (int i = 0; i < SECURITY_EVENTS_BATCH_SIZE; i++) {
+ getDevice().executeShellCommand("echo just_testing_" + i);
}
- // Sleep for ~1 minute so that SecurityLogMonitor fetches the security events. This is
- // an implementation detail we shouldn't rely on but there is no other way to do it
- // currently.
- Thread.sleep(TimeUnit.SECONDS.toMillis(70));
+ // Force log batch.
+ getDevice().executeShellCommand("dpm force-security-logs");
// Verify the contents of the batch.
executeDeviceTestMethod(".SecurityLoggingTest", "testGetSecurityLogs",
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerHostSideTransferTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerHostSideTransferTest.java
index 3fca7d9..c18d8c3e 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerHostSideTransferTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerHostSideTransferTest.java
@@ -83,17 +83,18 @@
runDeviceTestsAsUser(TRANSFER_OWNER_OUTGOING_PKG,
mOutgoingTestClassName,
- "testTransferOwner", mUserId);
+ "testTransferOwner", profileUserId);
+ waitForBroadcastIdle();
+
runDeviceTestsAsUser(TRANSFER_OWNER_OUTGOING_PKG,
mOutgoingTestClassName,
- "testTransferOwner", profileUserId);
+ "testTransferOwner", mUserId);
+ waitForBroadcastIdle();
assertAffiliationIdsAreIntact(profileUserId, mIncomingTestClassName);
- waitForBroadcastIdle();
-
- runDeviceTestsAsUser(TRANSFER_OWNER_INCOMING_PKG,
- mIncomingTestClassName,
+ runDeviceTestsAsUser(TRANSFER_OWNER_OUTGOING_PKG,
+ mOutgoingTestClassName,
"testTransferAffiliatedProfileOwnershipCompleteCallbackIsCalled",
mUserId);
}
diff --git a/hostsidetests/dumpsys/src/android/dumpsys/cts/BaseDumpsysTest.java b/hostsidetests/dumpsys/src/android/dumpsys/cts/BaseDumpsysTest.java
index 54c0dfb..ca548c8 100644
--- a/hostsidetests/dumpsys/src/android/dumpsys/cts/BaseDumpsysTest.java
+++ b/hostsidetests/dumpsys/src/android/dumpsys/cts/BaseDumpsysTest.java
@@ -18,7 +18,6 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.CollectingOutputReceiver;
@@ -26,6 +25,7 @@
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.result.TestResult;
import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.testtype.DeviceTestCase;
@@ -188,7 +188,7 @@
if (result.hasFailedTests()) {
// build a meaningful error message
StringBuilder errorBuilder = new StringBuilder("On-device tests failed:\n");
- for (Map.Entry<TestIdentifier, TestResult> resultEntry :
+ for (Map.Entry<TestDescription, TestResult> resultEntry :
result.getTestResults().entrySet()) {
if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
errorBuilder.append(resultEntry.getKey().toString());
diff --git a/hostsidetests/dumpsys/src/android/dumpsys/cts/StoragedDumpsysTest.java b/hostsidetests/dumpsys/src/android/dumpsys/cts/StoragedDumpsysTest.java
index c8981c5..34da3b6 100644
--- a/hostsidetests/dumpsys/src/android/dumpsys/cts/StoragedDumpsysTest.java
+++ b/hostsidetests/dumpsys/src/android/dumpsys/cts/StoragedDumpsysTest.java
@@ -17,17 +17,9 @@
package android.dumpsys.cts;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.ddmlib.testrunner.TestResult;
-import com.android.ddmlib.testrunner.TestResult.TestStatus;
-import com.android.ddmlib.testrunner.TestRunResult;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.result.CollectingTestListener;
import java.io.BufferedReader;
import java.io.StringReader;
-import java.util.Map;
/**
* Test to check the format of the dumps of the processstats test.
diff --git a/hostsidetests/incident/src/com/android/server/cts/AlarmManagerIncidentTest.java b/hostsidetests/incident/src/com/android/server/cts/AlarmManagerIncidentTest.java
index 59396dc..9bcce64 100644
--- a/hostsidetests/incident/src/com/android/server/cts/AlarmManagerIncidentTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/AlarmManagerIncidentTest.java
@@ -37,6 +37,10 @@
final AlarmManagerServiceProto dump =
getDump(AlarmManagerServiceProto.parser(), "dumpsys alarm --proto");
+ verifyAlarmManagerServiceProto(dump, PRIVACY_NONE);
+ }
+
+ static void verifyAlarmManagerServiceProto(AlarmManagerServiceProto dump, final int filterLevel) throws Exception {
// Times should be positive.
assertTrue(0 < dump.getCurrentTime());
assertTrue(0 < dump.getElapsedRealtime());
@@ -98,18 +102,18 @@
assertTrue("Batch end time (" + end + ") is negative", 0 <= end);
assertTrue("Batch start time (" + start + ") is after its end time (" + end + ")",
start <= end);
- testAlarmProtoList(b.getAlarmsList());
+ testAlarmProtoList(b.getAlarmsList(), filterLevel);
}
- testAlarmProtoList(dump.getPendingUserBlockedBackgroundAlarmsList());
+ testAlarmProtoList(dump.getPendingUserBlockedBackgroundAlarmsList(), filterLevel);
- testAlarmProto(dump.getPendingIdleUntil());
+ testAlarmProto(dump.getPendingIdleUntil(), filterLevel);
- testAlarmProtoList(dump.getPendingWhileIdleAlarmsList());
+ testAlarmProtoList(dump.getPendingWhileIdleAlarmsList(), filterLevel);
- testAlarmProto(dump.getNextWakeFromIdle());
+ testAlarmProto(dump.getNextWakeFromIdle(), filterLevel);
- testAlarmProtoList(dump.getPastDueNonWakeupAlarmsList());
+ testAlarmProtoList(dump.getPastDueNonWakeupAlarmsList(), filterLevel);
assertTrue(0 <= dump.getDelayedAlarmCount());
assertTrue(0 <= dump.getTotalDelayTimeMs());
@@ -126,13 +130,12 @@
assertTrue(0 <= f.getUid());
assertTrue(0 < f.getWhenElapsedMs());
testBroadcastStatsProto(f.getBroadcastStats());
- testFilterStatsProto(f.getFilterStats());
+ testFilterStatsProto(f.getFilterStats(), filterLevel);
+ if (filterLevel == PRIVACY_AUTO) {
+ assertTrue(f.getTag().isEmpty());
+ }
}
- long awimds = dump.getAllowWhileIdleMinDurationMs();
- assertTrue(awimds == settings.getAllowWhileIdleShortDurationMs()
- || awimds == settings.getAllowWhileIdleLongDurationMs());
-
for (AlarmManagerServiceProto.LastAllowWhileIdleDispatch l : dump.getLastAllowWhileIdleDispatchTimesList()) {
assertTrue(0 <= l.getUid());
assertTrue(0 < l.getTimeMs());
@@ -140,13 +143,13 @@
for (AlarmManagerServiceProto.TopAlarm ta : dump.getTopAlarmsList()) {
assertTrue(0 <= ta.getUid());
- testFilterStatsProto(ta.getFilter());
+ testFilterStatsProto(ta.getFilter(), filterLevel);
}
for (AlarmManagerServiceProto.AlarmStat as : dump.getAlarmStatsList()) {
testBroadcastStatsProto(as.getBroadcast());
for (FilterStatsProto f : as.getFiltersList()) {
- testFilterStatsProto(f);
+ testFilterStatsProto(f, filterLevel);
}
}
@@ -154,6 +157,9 @@
assertTrue(0 <= id.getUid());
assertTrue(0 <= id.getEntryCreationRealtime());
assertTrue(0 <= id.getArgRealtime());
+ if (filterLevel == PRIVACY_AUTO) {
+ assertTrue(id.getTag().isEmpty());
+ }
}
for (WakeupEventProto we : dump.getRecentWakeupHistoryList()) {
@@ -162,22 +168,26 @@
}
}
- private void testAlarmProtoList(List<AlarmProto> alarms) throws Exception {
+ private static void testAlarmProtoList(List<AlarmProto> alarms, final int filterLevel) throws Exception {
for (AlarmProto a : alarms) {
- testAlarmProto(a);
+ testAlarmProto(a, filterLevel);
}
}
- private void testAlarmProto(AlarmProto alarm) throws Exception {
+ private static void testAlarmProto(AlarmProto alarm, final int filterLevel) throws Exception {
assertNotNull(alarm);
+ if (filterLevel == PRIVACY_AUTO) {
+ assertTrue(alarm.getTag().isEmpty());
+ assertTrue(alarm.getListener().isEmpty());
+ }
// alarm.time_until_when_elapsed_ms can be negative if 'when' is in the past.
assertTrue(0 <= alarm.getWindowLengthMs());
assertTrue(0 <= alarm.getRepeatIntervalMs());
assertTrue(0 <= alarm.getCount());
}
- private void testBroadcastStatsProto(BroadcastStatsProto broadcast) throws Exception {
+ private static void testBroadcastStatsProto(BroadcastStatsProto broadcast) throws Exception {
assertNotNull(broadcast);
assertTrue(0 <= broadcast.getUid());
@@ -189,9 +199,12 @@
assertTrue(0 <= broadcast.getNesting());
}
- private void testFilterStatsProto(FilterStatsProto filter) throws Exception {
+ private static void testFilterStatsProto(FilterStatsProto filter, final int filterLevel) throws Exception {
assertNotNull(filter);
+ if (filterLevel == PRIVACY_AUTO) {
+ assertTrue(filter.getTag().isEmpty());
+ }
assertTrue(0 <= filter.getLastFlightTimeRealtime());
assertTrue(0 <= filter.getTotalFlightDurationMs());
assertTrue(0 <= filter.getCount());
diff --git a/hostsidetests/incident/src/com/android/server/cts/BatteryIncidentTest.java b/hostsidetests/incident/src/com/android/server/cts/BatteryIncidentTest.java
index 51ca3c2..368b574 100644
--- a/hostsidetests/incident/src/com/android/server/cts/BatteryIncidentTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/BatteryIncidentTest.java
@@ -21,22 +21,26 @@
import android.os.BatteryStatusEnum;
import android.service.battery.BatteryServiceDumpProto;
import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
/** Test to check that the battery manager properly outputs its dump state. */
public class BatteryIncidentTest extends ProtoDumpTestCase {
- private final String LEANBACK_FEATURE = "android.software.leanback";
+ private static final String LEANBACK_FEATURE = "android.software.leanback";
public void testBatteryServiceDump() throws Exception {
- final BatteryServiceDumpProto dump =
- getDump(BatteryServiceDumpProto.parser(), "dumpsys battery --proto");
-
- if (!dump.getIsPresent()) {
- /* If the battery isn't present, no need to run this test. */
+ if (hasBattery(getDevice())) {
return;
}
- if (isLeanback()) {
- /* Android TV reports that it has a battery, but it doesn't really. */
+ final BatteryServiceDumpProto dump =
+ getDump(BatteryServiceDumpProto.parser(), "dumpsys battery --proto");
+
+ verifyBatteryServiceDumpProto(dump, PRIVACY_NONE);
+ }
+
+ static void verifyBatteryServiceDumpProto(BatteryServiceDumpProto dump, final int filterLevel) {
+ if (!dump.getIsPresent()) {
+ /* If the battery isn't present, no need to run this test. */
return;
}
@@ -56,8 +60,13 @@
assertTrue(dump.getTemperature() > 0);
}
- private boolean isLeanback() throws DeviceNotAvailableException {
- final String commandOutput = getDevice().executeShellCommand("pm list features");
+ static boolean hasBattery(ITestDevice device) throws DeviceNotAvailableException {
+ /* Android TV reports that it has a battery, but it doesn't really. */
+ return !isLeanback(device);
+ }
+
+ private static boolean isLeanback(ITestDevice device) throws DeviceNotAvailableException {
+ final String commandOutput = device.executeShellCommand("pm list features");
return commandOutput.contains(LEANBACK_FEATURE);
}
}
diff --git a/hostsidetests/incident/src/com/android/server/cts/BatteryStatsIncidentTest.java b/hostsidetests/incident/src/com/android/server/cts/BatteryStatsIncidentTest.java
index fb971de..6a9168e 100644
--- a/hostsidetests/incident/src/com/android/server/cts/BatteryStatsIncidentTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/BatteryStatsIncidentTest.java
@@ -53,6 +53,13 @@
final BatteryStatsServiceDumpProto dump = getDump(BatteryStatsServiceDumpProto.parser(),
"dumpsys batterystats --proto");
+
+ verifyBatteryStatsServiceDumpProto(dump, PRIVACY_NONE);
+
+ batteryOffScreenOn();
+ }
+
+ static void verifyBatteryStatsServiceDumpProto(BatteryStatsServiceDumpProto dump, final int filterLevel) throws Exception {
final BatteryStatsProto bs = dump.getBatterystats();
assertNotNull(bs);
@@ -66,15 +73,13 @@
assertFalse(bs.getEndPlatformVersion().isEmpty());
for (UidProto u : bs.getUidsList()) {
- testUidProto(u);
+ testUidProto(u, filterLevel);
}
testSystemProto(bs.getSystem());
-
- batteryOffScreenOn();
}
- private void testControllerActivityProto(ControllerActivityProto ca) throws Exception {
+ private static void testControllerActivityProto(ControllerActivityProto ca) throws Exception {
assertNotNull(ca);
assertTrue(0 <= ca.getIdleDurationMs());
@@ -85,7 +90,7 @@
}
}
- private void testBatteryLevelStep(SystemProto.BatteryLevelStep bls) throws Exception {
+ private static void testBatteryLevelStep(SystemProto.BatteryLevelStep bls) throws Exception {
assertNotNull(bls);
assertTrue(0 < bls.getDurationMs());
@@ -100,7 +105,8 @@
.contains(bls.getIdleMode().getValueDescriptor()));
}
- private void testSystemProto(SystemProto s) throws Exception {
+ private static void testSystemProto(SystemProto s) throws Exception {
+ final long epsilon = 500; // Allow ~500 ms of error when comparing times.
assertNotNull(s);
SystemProto.Battery b = s.getBattery();
@@ -109,22 +115,23 @@
long totalRealtimeMs = b.getTotalRealtimeMs();
long totalUptimeMs = b.getTotalUptimeMs();
assertTrue(0 <= totalUptimeMs);
- assertTrue(totalUptimeMs <= totalRealtimeMs);
+ assertTrue(totalUptimeMs <= totalRealtimeMs + epsilon);
long batteryRealtimeMs = b.getBatteryRealtimeMs();
long batteryUptimeMs = b.getBatteryUptimeMs();
assertTrue(0 <= batteryUptimeMs);
- assertTrue(batteryUptimeMs <= batteryRealtimeMs);
- assertTrue(batteryRealtimeMs <= totalRealtimeMs);
- assertTrue(batteryUptimeMs <= totalUptimeMs);
+ assertTrue(batteryUptimeMs <= batteryRealtimeMs + epsilon);
+ assertTrue("Battery realtime (" + batteryRealtimeMs + ") is greater than total realtime (" + totalRealtimeMs + ")",
+ batteryRealtimeMs <= totalRealtimeMs + epsilon);
+ assertTrue(batteryUptimeMs <= totalUptimeMs + epsilon);
long screenOffRealtimeMs = b.getScreenOffRealtimeMs();
long screenOffUptimeMs = b.getScreenOffUptimeMs();
assertTrue(0 <= screenOffUptimeMs);
- assertTrue(screenOffUptimeMs <= screenOffRealtimeMs);
- assertTrue(screenOffRealtimeMs <= totalRealtimeMs);
- assertTrue(screenOffUptimeMs <= totalUptimeMs);
+ assertTrue(screenOffUptimeMs <= screenOffRealtimeMs + epsilon);
+ assertTrue(screenOffRealtimeMs <= totalRealtimeMs + epsilon);
+ assertTrue(screenOffUptimeMs <= totalUptimeMs + epsilon);
long screenDozeDurationMs = b.getScreenDozeDurationMs();
assertTrue(0 <= screenDozeDurationMs);
- assertTrue(screenDozeDurationMs <= screenOffRealtimeMs);
+ assertTrue(screenDozeDurationMs <= screenOffRealtimeMs + epsilon);
assertTrue(0 < b.getEstimatedBatteryCapacityMah());
long minLearnedCapacityUah = b.getMinLearnedBatteryCapacityUah();
long maxLearnedCapacityUah = b.getMaxLearnedBatteryCapacityUah();
@@ -276,7 +283,7 @@
}
}
- private void testTimerProto(TimerProto t) throws Exception {
+ private static void testTimerProto(TimerProto t) throws Exception {
assertNotNull(t);
long duration = t.getDurationMs();
@@ -300,7 +307,7 @@
}
}
- private void testByFrequency(UidProto.Cpu.ByFrequency bf) throws Exception {
+ private static void testByFrequency(UidProto.Cpu.ByFrequency bf) throws Exception {
assertNotNull(bf);
assertTrue(1 <= bf.getFrequencyIndex());
@@ -310,7 +317,7 @@
assertTrue(screenOff <= total);
}
- private void testUidProto(UidProto u) throws Exception {
+ private static void testUidProto(UidProto u, final int filterLevel) throws Exception {
assertNotNull(u);
assertTrue(0 <= u.getUid());
@@ -363,15 +370,23 @@
testTimerProto(u.getVideo());
for (UidProto.Job j : u.getJobsList()) {
- assertNotNull(j.getName());
- assertFalse(j.getName().isEmpty());
+ if (filterLevel >= PRIVACY_EXPLICIT) {
+ assertNotNull(j.getName());
+ assertFalse(j.getName().isEmpty());
+ } else {
+ assertTrue(j.getName().isEmpty());
+ }
testTimerProto(j.getTotal());
testTimerProto(j.getBackground());
}
for (UidProto.JobCompletion jc : u.getJobCompletionList()) {
- assertNotNull(jc.getName());
- assertFalse(jc.getName().isEmpty());
+ if (filterLevel >= PRIVACY_EXPLICIT) {
+ assertNotNull(jc.getName());
+ assertFalse(jc.getName().isEmpty());
+ } else {
+ assertTrue(jc.getName().isEmpty());
+ }
for (UidProto.JobCompletion.ReasonCount rc : jc.getReasonCountList()) {
assertTrue(0 <= rc.getCount());
}
@@ -429,6 +444,11 @@
}
for (UidProto.Sync s : u.getSyncsList()) {
+ if (filterLevel >= PRIVACY_EXPLICIT) {
+ assertFalse(s.getName().isEmpty());
+ } else {
+ assertTrue(s.getName().isEmpty());
+ }
testTimerProto(s.getTotal());
testTimerProto(s.getBackground());
}
@@ -444,6 +464,11 @@
assertTrue(awBgPartial <= awPartial);
for (UidProto.Wakelock w : u.getWakelocksList()) {
+ // Unfortunately, apps can legitimately pass an empty string as the wakelock name, so we
+ // can't guarantee that wakelock names will be non-empty for EXPLICIT+.
+ if (filterLevel == PRIVACY_AUTO) {
+ assertTrue(w.getName().isEmpty());
+ }
testTimerProto(w.getFull());
testTimerProto(w.getPartial());
testTimerProto(w.getBackgroundPartial());
@@ -451,6 +476,9 @@
}
for (UidProto.WakeupAlarm wa : u.getWakeupAlarmList()) {
+ if (filterLevel == PRIVACY_AUTO) {
+ assertTrue(wa.getName().isEmpty());
+ }
assertTrue(0 <= wa.getCount());
}
diff --git a/hostsidetests/incident/src/com/android/server/cts/FingerprintIncidentTest.java b/hostsidetests/incident/src/com/android/server/cts/FingerprintIncidentTest.java
index ed87f11..3c26066 100644
--- a/hostsidetests/incident/src/com/android/server/cts/FingerprintIncidentTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/FingerprintIncidentTest.java
@@ -20,6 +20,8 @@
import com.android.server.fingerprint.FingerprintUserStatsProto;
import com.android.server.fingerprint.PerformanceStatsProto;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.log.LogUtil.CLog;
@@ -29,14 +31,17 @@
public class FingerprintIncidentTest extends ProtoDumpTestCase {
public void testFingerprintServiceDump() throws Exception {
// If the device doesn't support fingerprints, then pass.
- if (!getDevice().hasFeature("android.hardware.fingerprint")) {
- CLog.d("Bypass as android.hardware.fingerprint is not supported.");
+ if (!supportsFingerprint(getDevice())) {
return;
}
final FingerprintServiceDumpProto dump =
getDump(FingerprintServiceDumpProto.parser(), "dumpsys fingerprint --proto");
+ verifyFingerprintServiceDumpProto(dump, PRIVACY_NONE);
+ }
+
+ static void verifyFingerprintServiceDumpProto(FingerprintServiceDumpProto dump, int filterLevel) {
// There should be at least one user.
assertTrue(1 <= dump.getUsersCount());
@@ -60,5 +65,13 @@
assertTrue(0 <= crypto.getPermanentLockout());
}
}
+
+ static boolean supportsFingerprint(ITestDevice device) throws DeviceNotAvailableException {
+ if (!device.hasFeature("android.hardware.fingerprint")) {
+ CLog.d("Bypass as android.hardware.fingerprint is not supported.");
+ return false;
+ }
+ return true;
+ }
}
diff --git a/hostsidetests/incident/src/com/android/server/cts/IncidentdIsolatedTest.java b/hostsidetests/incident/src/com/android/server/cts/IncidentdIsolatedTest.java
new file mode 100644
index 0000000..4161c2ff
--- /dev/null
+++ b/hostsidetests/incident/src/com/android/server/cts/IncidentdIsolatedTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2018 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.server.cts;
+
+import android.os.IncidentProto;
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.log.LogUtil.CLog;
+
+/**
+ * Tests incidentd works when system_server is crashed.
+ */
+public class IncidentdIsolatedTest extends ProtoDumpTestCase {
+ private static final String TAG = "IncidentdIsolatedTest";
+
+ private static final String SYSTEM_SERVER = "system_server";
+ private static final String CMD_TOP = "top -b -n 1 -o cmd";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ if (execCommandAndFind(CMD_TOP, SYSTEM_SERVER) != null) {
+ CLog.logAndDisplay(LogLevel.INFO, "stop server");
+ getDevice().executeShellCommand("stop");
+ Thread.sleep(3000); // wait for 3 seconds to stop.
+ assertTrue("system_server failed to stop",
+ !execCommandAndGet(CMD_TOP).contains(SYSTEM_SERVER));
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ if (!execCommandAndGet(CMD_TOP).contains(SYSTEM_SERVER)) {
+ CLog.logAndDisplay(LogLevel.INFO, "start server");
+ getDevice().executeShellCommand("start");
+ Thread.sleep(10000); // wait for 10 seconds to boot.
+ execCommandAndFind(CMD_TOP, SYSTEM_SERVER);
+ }
+ }
+
+ public void testFullReportParsable() throws Exception {
+ final IncidentProto dump = getDump(IncidentProto.parser(), "incident 2>/dev/null");
+ assertTrue(dump.toByteArray().length > 0);
+ assertTrue(dump.hasSystemProperties());
+ assertTrue(dump.hasEventLogTagMap());
+ assertTrue(dump.hasPageTypeInfo());
+ assertTrue(dump.hasKernelWakeSources());
+ assertTrue(dump.hasCpuInfo());
+ assertTrue(dump.hasCpuFreq());
+ assertTrue(dump.hasProcessesAndThreads());
+ assertTrue(dump.hasBatteryType());
+ }
+
+ public void testReportInPrivateDirectory() throws Exception {
+ assertTrue(execCommandAndGet("ls /data/misc/incidents").isEmpty());
+ assertTrue(execCommandAndGet("incident -d 1000 2>/dev/null").isEmpty());
+ Thread.sleep(5000); // wait for report to finish.
+ execCommandAndFind("ls /data/misc/incidents", "incident-");
+ }
+}
diff --git a/hostsidetests/incident/src/com/android/server/cts/IncidentdTest.java b/hostsidetests/incident/src/com/android/server/cts/IncidentdTest.java
index abb9b9b..fe8b876 100644
--- a/hostsidetests/incident/src/com/android/server/cts/IncidentdTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/IncidentdTest.java
@@ -19,6 +19,7 @@
import android.os.IncidentProto;
import android.os.SystemPropertiesProto;
+import com.android.tradefed.log.LogUtil.CLog;
/**
* Tests incidentd reports filters fields correctly based on its privacy tags.
@@ -26,10 +27,49 @@
public class IncidentdTest extends ProtoDumpTestCase {
private static final String TAG = "IncidentdTest";
- public void testIncidentReportDump() throws Exception {
- final IncidentProto dump = getDump(IncidentProto.parser(), "incident 3000 2>/dev/null");
- FingerprintServiceDumpProto fingerprint = dump.getFingerprint();
- assertTrue(1 <= fingerprint.getUsersCount());
+ public void testIncidentReportDump(final int filterLevel, final String dest) throws Exception {
+ final String destArg = dest == null || dest.isEmpty() ? "" : "-p " + dest;
+ final IncidentProto dump = getDump(IncidentProto.parser(), "incident " + destArg + " 2>/dev/null");
+
+ if (FingerprintIncidentTest.supportsFingerprint(getDevice())) {
+ FingerprintIncidentTest.verifyFingerprintServiceDumpProto(dump.getFingerprint(), filterLevel);
+ }
+
+ SettingsIncidentTest.verifySettingsServiceDumpProto(dump.getSettings(), filterLevel);
+
+ BatteryStatsIncidentTest.verifyBatteryStatsServiceDumpProto(dump.getBatterystats(), filterLevel);
+
+ if (BatteryIncidentTest.hasBattery(getDevice())) {
+ BatteryIncidentTest.verifyBatteryServiceDumpProto(dump.getBattery(), filterLevel);
+ }
+
+ PackageIncidentTest.verifyPackageServiceDumpProto(dump.getPackage(), filterLevel);
+
+ PowerIncidentTest.verifyPowerManagerServiceDumpProto(dump.getPower(), filterLevel);
+
+ AlarmManagerIncidentTest.verifyAlarmManagerServiceProto(dump.getAlarm(), filterLevel);
+
+ MemInfoIncidentTest.verifyMemInfoProto(dump.getMeminfo(), filterLevel);
+
+ JobSchedulerIncidentTest.verifyJobSchedulerServiceDumpProto(dump.getJobscheduler(), filterLevel);
+ }
+
+ // Splitting these into separate methods to make debugging easier.
+
+ public void testIncidentReportDumpAuto() throws Exception {
+ testIncidentReportDump(PRIVACY_AUTO, "A");
+ testIncidentReportDump(PRIVACY_AUTO, "AUTO");
+ testIncidentReportDump(PRIVACY_AUTO, "AUTOMATIC");
+ }
+
+ public void testIncidentReportDumpExplicit() throws Exception {
+ testIncidentReportDump(PRIVACY_EXPLICIT, "E" );
+ testIncidentReportDump(PRIVACY_EXPLICIT, "EXPLICIT");
+ }
+
+ public void testIncidentReportDumpLocal() throws Exception {
+ testIncidentReportDump(PRIVACY_LOCAL, "L" );
+ testIncidentReportDump(PRIVACY_LOCAL, "LOCAL");
}
public void testSystemPropertiesLocal() throws Exception {
@@ -56,6 +96,8 @@
// check explicit tagged data show up
assertFalse(properties.getDalvikVm().getHeapmaxfree().isEmpty());
// check automatic tagged data show up
+ CLog.i(mCtsBuild.getBuildId());
+ CLog.i(properties.getRo().getBuild().getVersion().getIncremental());
assertTrue(properties.getRo().getBuild().getVersion().getIncremental()
.equals(mCtsBuild.getBuildId()));
}
diff --git a/hostsidetests/incident/src/com/android/server/cts/JobSchedulerIncidentTest.java b/hostsidetests/incident/src/com/android/server/cts/JobSchedulerIncidentTest.java
index fa23d9a..e6465f8 100644
--- a/hostsidetests/incident/src/com/android/server/cts/JobSchedulerIncidentTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/JobSchedulerIncidentTest.java
@@ -34,6 +34,10 @@
final JobSchedulerServiceDumpProto dump =
getDump(JobSchedulerServiceDumpProto.parser(), "dumpsys jobscheduler --proto");
+ verifyJobSchedulerServiceDumpProto(dump, PRIVACY_NONE);
+ }
+
+ static void verifyJobSchedulerServiceDumpProto(JobSchedulerServiceDumpProto dump, final int filterLevel) throws Exception {
testConstantsProto(dump.getSettings());
for (int u : dump.getStartedUsersList()) {
@@ -41,12 +45,12 @@
}
for (JobSchedulerServiceDumpProto.RegisteredJob rj : dump.getRegisteredJobsList()) {
- testJobStatusShortInfoProto(rj.getInfo());
+ testJobStatusShortInfoProto(rj.getInfo(), filterLevel);
testJobStatusDumpProto(rj.getDump());
}
for (StateControllerProto c : dump.getControllersList()) {
- testStateControllerProto(c);
+ testStateControllerProto(c, filterLevel);
}
for (JobSchedulerServiceDumpProto.PriorityOverride po : dump.getPriorityOverridesList()) {
@@ -57,12 +61,12 @@
assertTrue(0 <= buu);
}
- testJobPackageHistoryProto(dump.getHistory());
+ testJobPackageHistoryProto(dump.getHistory(), filterLevel);
testJobPackageTrackerDumpProto(dump.getPackageTracker());
for (JobSchedulerServiceDumpProto.PendingJob pj : dump.getPendingJobsList()) {
- testJobStatusShortInfoProto(pj.getInfo());
+ testJobStatusShortInfoProto(pj.getInfo(), filterLevel);
testJobStatusDumpProto(pj.getDump());
assertTrue(0 <= pj.getEnqueuedDurationMs());
}
@@ -72,7 +76,7 @@
assertTrue(0 <= ajIj.getTimeSinceStoppedMs());
JobSchedulerServiceDumpProto.ActiveJob.RunningJob ajRj = aj.getRunning();
- testJobStatusShortInfoProto(ajRj.getInfo());
+ testJobStatusShortInfoProto(ajRj.getInfo(), filterLevel);
assertTrue(0 <= ajRj.getRunningDurationMs());
assertTrue(0 <= ajRj.getTimeUntilTimeoutMs());
testJobStatusDumpProto(ajRj.getDump());
@@ -83,7 +87,7 @@
assertTrue(0 <= dump.getMaxActiveJobs());
}
- private void testConstantsProto(ConstantsProto c) throws Exception {
+ private static void testConstantsProto(ConstantsProto c) throws Exception {
assertNotNull(c);
assertTrue(0 <= c.getMinIdleCount());
@@ -110,7 +114,7 @@
}
}
- private void testDataSetProto(DataSetProto ds) throws Exception {
+ private static void testDataSetProto(DataSetProto ds) throws Exception {
assertNotNull(ds);
assertTrue(0 <= ds.getStartClockTimeMs());
@@ -137,7 +141,7 @@
assertTrue(0 <= ds.getMaxForegroundConcurrency());
}
- private void testJobPackageHistoryProto(JobPackageHistoryProto jph) throws Exception {
+ private static void testJobPackageHistoryProto(JobPackageHistoryProto jph, int filterLevel) throws Exception {
assertNotNull(jph);
for (JobPackageHistoryProto.HistoryEvent he : jph.getHistoryEventList()) {
@@ -147,10 +151,13 @@
assertTrue(0 <= he.getUid());
assertTrue(JobParametersProto.CancelReason.getDescriptor().getValues()
.contains(he.getStopReason().getValueDescriptor()));
+ if (filterLevel == PRIVACY_AUTO) {
+ assertTrue(he.getTag().isEmpty());
+ }
}
}
- private void testJobPackageTrackerDumpProto(JobPackageTrackerDumpProto jptd) throws Exception {
+ private static void testJobPackageTrackerDumpProto(JobPackageTrackerDumpProto jptd) throws Exception {
assertNotNull(jptd);
for (DataSetProto ds : jptd.getHistoricalStatsList()) {
@@ -159,13 +166,16 @@
testDataSetProto(jptd.getCurrentStats());
}
- private void testJobStatusShortInfoProto(JobStatusShortInfoProto jssi) throws Exception {
+ private static void testJobStatusShortInfoProto(JobStatusShortInfoProto jssi, final int filterLevel) throws Exception {
assertNotNull(jssi);
assertTrue(0 <= jssi.getCallingUid());
+ if (filterLevel == PRIVACY_AUTO) {
+ assertTrue(jssi.getBatteryName().isEmpty());
+ }
}
- private void testJobStatusDumpProto(JobStatusDumpProto jsd) throws Exception {
+ private static void testJobStatusDumpProto(JobStatusDumpProto jsd) throws Exception {
assertNotNull(jsd);
assertTrue(0 <= jsd.getCallingUid());
@@ -224,7 +234,7 @@
assertTrue(0 <= jsd.getLastFailedRunTime());
}
- private void testNetworkRequestProto(NetworkRequestProto nr) throws Exception {
+ private static void testNetworkRequestProto(NetworkRequestProto nr) throws Exception {
assertNotNull(nr);
assertTrue(NetworkRequestProto.Type.getDescriptor().getValues()
@@ -232,7 +242,7 @@
testNetworkCapabilitesProto(nr.getNetworkCapabilities());
}
- private void testNetworkCapabilitesProto(NetworkCapabilitiesProto nc) throws Exception {
+ private static void testNetworkCapabilitesProto(NetworkCapabilitiesProto nc) throws Exception {
assertNotNull(nc);
for (NetworkCapabilitiesProto.Transport t : nc.getTransportsList()) {
@@ -248,61 +258,73 @@
assertTrue(0 <= nc.getLinkDownBandwidthKbps());
}
- private void testStateControllerProto(StateControllerProto sc) throws Exception {
+ private static void testStateControllerProto(StateControllerProto sc, int filterLevel) throws Exception {
assertNotNull(sc);
StateControllerProto.AppIdleController aic = sc.getAppIdle();
for (StateControllerProto.AppIdleController.TrackedJob tj : aic.getTrackedJobsList()) {
- testJobStatusShortInfoProto(tj.getInfo());
+ testJobStatusShortInfoProto(tj.getInfo(), filterLevel);
assertTrue(0 <= tj.getSourceUid());
}
StateControllerProto.BackgroundJobsController bjc = sc.getBackground();
for (StateControllerProto.BackgroundJobsController.TrackedJob tj : bjc.getTrackedJobsList()) {
- testJobStatusShortInfoProto(tj.getInfo());
+ testJobStatusShortInfoProto(tj.getInfo(), filterLevel);
assertTrue(0 <= tj.getSourceUid());
}
StateControllerProto.BatteryController bc = sc.getBattery();
for (StateControllerProto.BatteryController.TrackedJob tj : bc.getTrackedJobsList()) {
- testJobStatusShortInfoProto(tj.getInfo());
+ testJobStatusShortInfoProto(tj.getInfo(), filterLevel);
assertTrue(0 <= tj.getSourceUid());
}
StateControllerProto.ConnectivityController cc = sc.getConnectivity();
for (StateControllerProto.ConnectivityController.TrackedJob tj : cc.getTrackedJobsList()) {
- testJobStatusShortInfoProto(tj.getInfo());
+ testJobStatusShortInfoProto(tj.getInfo(), filterLevel);
assertTrue(0 <= tj.getSourceUid());
testNetworkRequestProto(tj.getRequiredNetwork());
}
StateControllerProto.ContentObserverController coc = sc.getContentObserver();
for (StateControllerProto.ContentObserverController.TrackedJob tj : coc.getTrackedJobsList()) {
- testJobStatusShortInfoProto(tj.getInfo());
+ testJobStatusShortInfoProto(tj.getInfo(), filterLevel);
assertTrue(0 <= tj.getSourceUid());
}
for (StateControllerProto.ContentObserverController.Observer o : coc.getObserversList()) {
assertTrue(0 <= o.getUserId());
for (StateControllerProto.ContentObserverController.Observer.TriggerContentData tcd : o.getTriggersList()) {
+ if (filterLevel == PRIVACY_AUTO) {
+ assertTrue(tcd.getUri().isEmpty());
+ }
for (StateControllerProto.ContentObserverController.Observer.TriggerContentData.JobInstance ji : tcd.getJobsList()) {
- testJobStatusShortInfoProto(ji.getInfo());
+ testJobStatusShortInfoProto(ji.getInfo(), filterLevel);
assertTrue(0 <= ji.getSourceUid());
assertTrue(0 <= ji.getTriggerContentUpdateDelayMs());
assertTrue(0 <= ji.getTriggerContentMaxDelayMs());
+
+ if (filterLevel == PRIVACY_AUTO) {
+ for (String ca : ji.getChangedAuthoritiesList()) {
+ assertTrue(ca.isEmpty());
+ }
+ for (String ca : ji.getChangedUrisList()) {
+ assertTrue(ca.isEmpty());
+ }
+ }
}
}
}
StateControllerProto.DeviceIdleJobsController dijc = sc.getDeviceIdle();
for (StateControllerProto.DeviceIdleJobsController.TrackedJob tj : dijc.getTrackedJobsList()) {
- testJobStatusShortInfoProto(tj.getInfo());
+ testJobStatusShortInfoProto(tj.getInfo(), filterLevel);
assertTrue(0 <= tj.getSourceUid());
}
StateControllerProto.IdleController ic = sc.getIdle();
for (StateControllerProto.IdleController.TrackedJob tj : ic.getTrackedJobsList()) {
- testJobStatusShortInfoProto(tj.getInfo());
+ testJobStatusShortInfoProto(tj.getInfo(), filterLevel);
assertTrue(0 <= tj.getSourceUid());
}
StateControllerProto.StorageController scr = sc.getStorage();
for (StateControllerProto.StorageController.TrackedJob tj : scr.getTrackedJobsList()) {
- testJobStatusShortInfoProto(tj.getInfo());
+ testJobStatusShortInfoProto(tj.getInfo(), filterLevel);
assertTrue(0 <= tj.getSourceUid());
}
StateControllerProto.TimeController tc = sc.getTime();
@@ -310,7 +332,7 @@
assertTrue(0 <= tc.getTimeUntilNextDelayAlarmMs());
assertTrue(0 <= tc.getTimeUntilNextDeadlineAlarmMs());
for (StateControllerProto.TimeController.TrackedJob tj : tc.getTrackedJobsList()) {
- testJobStatusShortInfoProto(tj.getInfo());
+ testJobStatusShortInfoProto(tj.getInfo(), filterLevel);
assertTrue(0 <= tj.getSourceUid());
}
}
diff --git a/hostsidetests/incident/src/com/android/server/cts/MemInfoIncidentTest.java b/hostsidetests/incident/src/com/android/server/cts/MemInfoIncidentTest.java
index 69fe2ac..3798319 100644
--- a/hostsidetests/incident/src/com/android/server/cts/MemInfoIncidentTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/MemInfoIncidentTest.java
@@ -24,11 +24,15 @@
/** Test to check that ActivityManager properly outputs meminfo data. */
public class MemInfoIncidentTest extends ProtoDumpTestCase {
- public void testBatteryServiceDump() throws Exception {
+ public void testMemInfoDump() throws Exception {
final MemInfoProto dump =
getDump(MemInfoProto.parser(), "dumpsys meminfo -a --proto");
- assertTrue(dump.getUptimeDurationMs() > 0);
+ verifyMemInfoProto(dump, PRIVACY_NONE);
+ }
+
+ static void verifyMemInfoProto(MemInfoProto dump, final int filterLevel) throws Exception {
+ assertTrue(dump.getUptimeDurationMs() >= 0);
assertTrue(dump.getElapsedRealtimeMs() >= 0);
for (ProcessMemory pm : dump.getNativeProcessesList()) {
@@ -67,7 +71,7 @@
assertTrue(0 <= dump.getKsmUnsharedKb());
assertTrue(0 <= dump.getKsmVolatileKb());
- assertTrue(0 < dump.getTuningMb());
+ assertTrue("Tuning_mb (" + dump.getTuningMb() + ") is not positive", 0 < dump.getTuningMb());
assertTrue(0 < dump.getTuningLargeMb());
assertTrue(0 <= dump.getOomKb());
@@ -75,7 +79,7 @@
assertTrue(0 < dump.getRestoreLimitKb());
}
- private void testProcessMemory(ProcessMemory pm) throws Exception {
+ private static void testProcessMemory(ProcessMemory pm) throws Exception {
assertNotNull(pm);
assertTrue(0 < pm.getPid());
@@ -108,7 +112,7 @@
assertTrue(0 <= as.getTotalSwapKb());
}
- private void testMemoryInfo(ProcessMemory.MemoryInfo mi) throws Exception {
+ private static void testMemoryInfo(ProcessMemory.MemoryInfo mi) throws Exception {
assertNotNull(mi);
assertTrue(0 <= mi.getTotalPssKb());
@@ -121,7 +125,7 @@
assertTrue(0 <= mi.getDirtySwapPssKb());
}
- private void testHeapInfo(ProcessMemory.HeapInfo hi) throws Exception {
+ private static void testHeapInfo(ProcessMemory.HeapInfo hi) throws Exception {
assertNotNull(hi);
testMemoryInfo(hi.getMemInfo());
@@ -130,7 +134,7 @@
assertTrue(0 <= hi.getHeapFreeKb());
}
- private void testAppData(AppData ad) throws Exception {
+ private static void testAppData(AppData ad) throws Exception {
assertNotNull(ad);
testProcessMemory(ad.getProcessMemory());
@@ -161,7 +165,7 @@
}
}
- private void testMemItem(MemItem mi) throws Exception {
+ private static void testMemItem(MemItem mi) throws Exception {
assertNotNull(mi);
assertTrue(0 <= mi.getPssKb());
diff --git a/hostsidetests/incident/src/com/android/server/cts/PackageIncidentTest.java b/hostsidetests/incident/src/com/android/server/cts/PackageIncidentTest.java
index 18efcb0..a9ae705 100644
--- a/hostsidetests/incident/src/com/android/server/cts/PackageIncidentTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/PackageIncidentTest.java
@@ -34,12 +34,12 @@
super.tearDown();
}
- private void assertPositive(String name, long value) {
+ private static void assertPositive(String name, long value) {
if (value > 0) return;
fail(name + " expected to be positive, but was: " + value);
}
- private void assertNotNegative(String name, long value) {
+ private static void assertNotNegative(String name, long value) {
if (value >= 0) return;
fail(name + " expected to be zero or positive, but was: " + value);
}
@@ -63,15 +63,6 @@
final PackageServiceDumpProto dump =
getDump(PackageServiceDumpProto.parser(), "dumpsys package --proto");
- assertNotNull(dump.getVerifierPackage().getName());
- assertPositive("verifier_package uid", dump.getVerifierPackage().getUid());
- assertNotNull(dump.getSharedLibraries(0).getName());
- if (dump.getSharedLibraries(0).getIsJar()) {
- assertNotNull(dump.getSharedLibraries(0).getPath());
- } else {
- assertNotNull(dump.getSharedLibraries(0).getApk());
- }
- assertNotNull(dump.getFeatures(0).getName());
PackageProto testPackage = null;
for (PackageProto pkg : dump.getPackagesList()) {
if (pkg.getName().equals(DEVICE_SIDE_TEST_PACKAGE)) {
@@ -99,6 +90,19 @@
== PackageProto.UserInfoProto.EnabledState
.COMPONENT_ENABLED_STATE_DISABLED_USER);
+ verifyPackageServiceDumpProto(dump, PRIVACY_NONE);
+ }
+
+ static void verifyPackageServiceDumpProto(PackageServiceDumpProto dump, final int filterLevel) throws Exception {
+ assertNotNull(dump.getVerifierPackage().getName());
+ assertNotNull(dump.getSharedLibraries(0).getName());
+ if (dump.getSharedLibraries(0).getIsJar()) {
+ assertNotNull(dump.getSharedLibraries(0).getPath());
+ } else {
+ assertNotNull(dump.getSharedLibraries(0).getApk());
+ }
+ assertNotNull(dump.getFeatures(0).getName());
+
PackageServiceDumpProto.SharedUserProto systemUser = null;
for (PackageServiceDumpProto.SharedUserProto user : dump.getSharedUsersList()) {
if (user.getUserId() == 1000) {
@@ -107,6 +111,12 @@
}
}
assertNotNull(systemUser);
- assertEquals(systemUser.getName(), "android.uid.system");
+ assertEquals("android.uid.system", systemUser.getName());
+
+ if (filterLevel == PRIVACY_AUTO) {
+ for (String msg : dump.getMessagesList()) {
+ assertTrue(msg.isEmpty());
+ }
+ }
}
}
diff --git a/hostsidetests/incident/src/com/android/server/cts/PowerIncidentTest.java b/hostsidetests/incident/src/com/android/server/cts/PowerIncidentTest.java
index 27e2704f..03ba7b5 100644
--- a/hostsidetests/incident/src/com/android/server/cts/PowerIncidentTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/PowerIncidentTest.java
@@ -34,6 +34,10 @@
final PowerManagerServiceDumpProto dump =
getDump(PowerManagerServiceDumpProto.parser(), "dumpsys power --proto");
+ verifyPowerManagerServiceDumpProto(dump, PRIVACY_NONE);
+ }
+
+ static void verifyPowerManagerServiceDumpProto(PowerManagerServiceDumpProto dump, int filterLevel) {
assertTrue(dump.getBatteryLevel() >= 0);
assertTrue(dump.getBatteryLevel() <= 100);
@@ -67,9 +71,9 @@
int settingMin = brightnessLimits.getSettingMinimum();
assertTrue(settingMin >= 0);
assertTrue(settingMax > 0);
- assertTrue(settingMax >= settingMin);
+ assertTrue("Brightness limit max setting (" + settingMax + ") is less than min setting (" + settingMin + ")",
+ settingMax >= settingMin);
assertTrue(brightnessLimits.getSettingDefault() > 0);
- assertTrue(brightnessLimits.getSettingForVrDefault() > 0);
final PowerManagerServiceDumpProto.UidStateProto uid = dump.getUidStates(0);
assertEquals(uid.getUid(), SYSTEM_UID);
@@ -107,6 +111,10 @@
assertTrue(dump.getScreenDimDurationMs() >= 0);
for (WakeLockProto wl : dump.getWakeLocksList()) {
+ if (filterLevel == PRIVACY_AUTO) {
+ // Tag may or may not be empty, but for AUTO, it should always be empty.
+ assertTrue(wl.getTag().isEmpty());
+ }
assertTrue(0 <= wl.getAcqMs());
assertTrue(0 <= wl.getUid());
assertTrue(0 <= wl.getPid());
diff --git a/hostsidetests/incident/src/com/android/server/cts/ProtoDumpTestCase.java b/hostsidetests/incident/src/com/android/server/cts/ProtoDumpTestCase.java
index dbb7e07..4acf5ba 100644
--- a/hostsidetests/incident/src/com/android/server/cts/ProtoDumpTestCase.java
+++ b/hostsidetests/incident/src/com/android/server/cts/ProtoDumpTestCase.java
@@ -19,7 +19,6 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.ddmlib.IShellOutputReceiver;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.CollectingByteOutputReceiver;
@@ -27,6 +26,7 @@
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.result.TestResult;
import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.testtype.DeviceTestCase;
@@ -48,6 +48,11 @@
import javax.annotation.Nullable;
public class ProtoDumpTestCase extends DeviceTestCase implements IBuildReceiver {
+ protected static final int PRIVACY_AUTO = 0;
+ protected static final int PRIVACY_EXPLICIT = 1;
+ protected static final int PRIVACY_LOCAL = 2;
+ /** No privacy filtering has been done. All fields should be present. */
+ protected static final int PRIVACY_NONE = 3;
protected IBuildInfo mCtsBuild;
@@ -137,7 +142,7 @@
if (result.hasFailedTests()) {
// build a meaningful error message
StringBuilder errorBuilder = new StringBuilder("On-device tests failed:\n");
- for (Map.Entry<TestIdentifier, TestResult> resultEntry :
+ for (Map.Entry<TestDescription, TestResult> resultEntry :
result.getTestResults().entrySet()) {
if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
errorBuilder.append(resultEntry.getKey().toString());
@@ -150,14 +155,21 @@
}
/**
+ * Execute the given command, and returns the output.
+ */
+ protected String execCommandAndGet(String command) throws Exception {
+ final CollectingOutputReceiver receiver = new CollectingOutputReceiver();
+ getDevice().executeShellCommand(command, receiver);
+ return receiver.getOutput();
+ }
+
+ /**
* Execute the given command, and find the given pattern with given flags and return the
* resulting {@link Matcher}.
*/
protected Matcher execCommandAndFind(String command, String pattern, int patternFlags)
throws Exception {
- final CollectingOutputReceiver receiver = new CollectingOutputReceiver();
- getDevice().executeShellCommand(command, receiver);
- final String output = receiver.getOutput();
+ final String output = execCommandAndGet(command);
final Matcher matcher = Pattern.compile(pattern, patternFlags).matcher(output);
assertTrue("Pattern '" + pattern + "' didn't match. Output=\n" + output, matcher.find());
return matcher;
diff --git a/hostsidetests/incident/src/com/android/server/cts/SettingsIncidentTest.java b/hostsidetests/incident/src/com/android/server/cts/SettingsIncidentTest.java
index d9ee469..4c465a9 100644
--- a/hostsidetests/incident/src/com/android/server/cts/SettingsIncidentTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/SettingsIncidentTest.java
@@ -44,6 +44,10 @@
SettingsServiceDumpProto dump = getDump(SettingsServiceDumpProto.parser(),
"dumpsys settings --proto");
+ verifySettingsServiceDumpProto(dump, PRIVACY_NONE);
+ }
+
+ static void verifySettingsServiceDumpProto(SettingsServiceDumpProto dump, final int filterLevel) throws Exception {
assertTrue(dump.getUserSettingsCount() > 0);
UserSettingsProto userSettings = dump.getUserSettings(0);
@@ -55,7 +59,7 @@
verifySettings(dump.getGlobalSettings());
}
- private void verifySettings(GeneratedMessage settings) throws Exception {
+ private static void verifySettings(GeneratedMessage settings) throws Exception {
verifySettings(getSettingProtos(settings));
final List<SettingsOperationProto> ops = invoke(settings, "getHistoricalOperationsList");
@@ -101,7 +105,7 @@
return c == Integer.class ? int.class : c;
}
- private void verifySettings(List<SettingProto> settings) throws Exception {
+ private static void verifySettings(List<SettingProto> settings) throws Exception {
assertFalse(settings.isEmpty());
for (SettingProto setting : settings) {
diff --git a/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/ImeCommandConstants.java b/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/ImeCommandConstants.java
index 61d5fc9..31368b0 100644
--- a/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/ImeCommandConstants.java
+++ b/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/ImeCommandConstants.java
@@ -52,6 +52,24 @@
public static final String COMMAND_SWITCH_INPUT_METHOD = "switchInputMethod";
/**
+ * This command has the mock IME call {@link android.inputmethodservice.InputMethodService#setInputMethodAndSubtype(String, InputMethodSubtype)} InputMethodService#setInputMethodAndSubtype(String imeId, InputMethodSubtype subtype)}.
+ * <ul>
+ * <li>argument {@code imeId} needs to be specified by {@link #EXTRA_ARG_STRING1}.</li>
+ * </ul>
+ */
+ public static final String COMMAND_SET_INPUT_METHOD_AND_SUBTYPE = "setInputMethodAndSubtype";
+
+ /**
+ * This command has the mock IME call {@link android.inputmethodservice.InputMethodService#switchToNextInputMethod(boolean)} InputMethodService#switchToNextInputMethod(boolean onlyCurrentIme)}.
+ */
+ public static final String COMMAND_SWITCH_TO_NEXT_INPUT = "switchToNextInput";
+
+ /**
+ * This command has the mock IME call {@link android.inputmethodservice.InputMethodService#switchToLastInputMethod()} InputMethodService#switchToLastInputMethod()}.
+ */
+ public static final String COMMAND_SWITCH_TO_LAST_INPUT = "switchToLastInput";
+
+ /**
* This command has the mock IME call {@link android.inputmethodservice.InputMethodService#requestHideSelf(int)} InputMethodService#requestHideSelf(int flags)}.
* <ul>
* <li>argument {@code flags} needs to be specified by {@link #EXTRA_ARG_INT1}.</li>
diff --git a/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/test/DeviceTestConstants.java b/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/test/DeviceTestConstants.java
index 4502325..049f32e 100644
--- a/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/test/DeviceTestConstants.java
+++ b/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/test/DeviceTestConstants.java
@@ -42,4 +42,7 @@
"android.inputmethodservice.cts.devicetest.InputMethodServiceDeviceTest";
public static final String TEST_CREATE_IME1 = "testCreateIme1";
public static final String TEST_SWITCH_IME1_TO_IME2 = "testSwitchIme1ToIme2";
+ public static final String TEST_SET_INPUTMETHOD_AND_SUBTYPE = "testSetInputMethodAndSubtype";
+ public static final String TEST_SWITCH_NEXT_INPUT = "testSwitchToNextInputMethod";
+ public static final String TEST_SWITCH_LAST_INPUT = "testSwitchToLastInputMethod";
}
diff --git a/hostsidetests/inputmethodservice/deviceside/devicetest/src/android/inputmethodservice/cts/devicetest/InputMethodServiceDeviceTest.java b/hostsidetests/inputmethodservice/deviceside/devicetest/src/android/inputmethodservice/cts/devicetest/InputMethodServiceDeviceTest.java
index 5245612..0b43dd6 100644
--- a/hostsidetests/inputmethodservice/deviceside/devicetest/src/android/inputmethodservice/cts/devicetest/InputMethodServiceDeviceTest.java
+++ b/hostsidetests/inputmethodservice/deviceside/devicetest/src/android/inputmethodservice/cts/devicetest/InputMethodServiceDeviceTest.java
@@ -23,7 +23,13 @@
import static android.inputmethodservice.cts.common.DeviceEventConstants.DeviceEventType.ON_DESTROY;
import static android.inputmethodservice.cts.common.DeviceEventConstants.DeviceEventType.ON_START_INPUT;
import static android.inputmethodservice.cts.common.ImeCommandConstants.ACTION_IME_COMMAND;
+import static android.inputmethodservice.cts.common.ImeCommandConstants
+ .COMMAND_SET_INPUT_METHOD_AND_SUBTYPE;
import static android.inputmethodservice.cts.common.ImeCommandConstants.COMMAND_SWITCH_INPUT_METHOD;
+import static android.inputmethodservice.cts.common.ImeCommandConstants
+ .COMMAND_SWITCH_TO_LAST_INPUT;
+import static android.inputmethodservice.cts.common.ImeCommandConstants
+ .COMMAND_SWITCH_TO_NEXT_INPUT;
import static android.inputmethodservice.cts.common.ImeCommandConstants.EXTRA_ARG_STRING1;
import static android.inputmethodservice.cts.common.ImeCommandConstants.EXTRA_COMMAND;
import static android.inputmethodservice.cts.devicetest.BusyWaitUtils.pollingCheck;
@@ -114,6 +120,78 @@
"CtsInputMethod2.onCreate and onStartInput are called in sequence");
}
+ @Test
+ public void testSetInputMethodAndSubtype() throws Throwable {
+ final TestHelper helper = new TestHelper(
+ getClass(), DeviceTestConstants.TEST_SET_INPUTMETHOD_AND_SUBTYPE);
+ final long startActivityTime = SystemClock.uptimeMillis();
+ helper.launchActivity(DeviceTestConstants.PACKAGE, DeviceTestConstants.TEST_ACTIVITY_CLASS);
+ pollingCheck(() -> helper.queryAllEvents()
+ .filter(isNewerThan(startActivityTime))
+ .anyMatch(isFrom(Ime1Constants.CLASS).and(isType(ON_START_INPUT))),
+ TIMEOUT, "CtsInputMethod1.onStartInput is called");
+ helper.findUiObject(R.id.text_entry).click();
+
+ final long setImeTime = SystemClock.uptimeMillis();
+ // call setInputMethodAndSubtype(IME2, null)
+ helper.shell(ShellCommandUtils.broadcastIntent(
+ ACTION_IME_COMMAND, Ime1Constants.PACKAGE,
+ "-e", EXTRA_COMMAND, COMMAND_SET_INPUT_METHOD_AND_SUBTYPE,
+ "-e", EXTRA_ARG_STRING1, Ime2Constants.IME_ID));
+ pollingCheck(() -> helper.shell(ShellCommandUtils.getCurrentIme())
+ .equals(Ime2Constants.IME_ID),
+ TIMEOUT, "CtsInputMethod2 is current IME");
+ pollingCheck(() -> helper.queryAllEvents()
+ .filter(isNewerThan(setImeTime))
+ .anyMatch(isFrom(Ime1Constants.CLASS).and(isType(ON_DESTROY))),
+ TIMEOUT, "CtsInputMethod1.onDestroy is called");
+ }
+
+ @Test
+ public void testSwitchToNextInputMethod() throws Throwable {
+ final TestHelper helper = new TestHelper(
+ getClass(), DeviceTestConstants.TEST_SWITCH_NEXT_INPUT);
+ final long startActivityTime = SystemClock.uptimeMillis();
+ helper.launchActivity(DeviceTestConstants.PACKAGE, DeviceTestConstants.TEST_ACTIVITY_CLASS);
+ pollingCheck(() -> helper.queryAllEvents()
+ .filter(isNewerThan(startActivityTime))
+ .anyMatch(isFrom(Ime1Constants.CLASS).and(isType(ON_START_INPUT))),
+ TIMEOUT, "CtsInputMethod1.onStartInput is called");
+ helper.findUiObject(R.id.text_entry).click();
+
+ pollingCheck(() -> helper.shell(ShellCommandUtils.getCurrentIme())
+ .equals(Ime1Constants.IME_ID),
+ TIMEOUT, "CtsInputMethod1 is current IME");
+ helper.shell(ShellCommandUtils.broadcastIntent(
+ ACTION_IME_COMMAND, Ime1Constants.PACKAGE,
+ "-e", EXTRA_COMMAND, COMMAND_SWITCH_TO_NEXT_INPUT));
+ pollingCheck(() -> !helper.shell(ShellCommandUtils.getCurrentIme())
+ .equals(Ime1Constants.IME_ID),
+ TIMEOUT, "CtsInputMethod1 shouldn't be current IME");
+ }
+
+ @Test
+ public void testSwitchToLastInputMethod() throws Throwable {
+ final TestHelper helper = new TestHelper(
+ getClass(), DeviceTestConstants.TEST_SWITCH_LAST_INPUT);
+ final long startActivityTime = SystemClock.uptimeMillis();
+ helper.launchActivity(DeviceTestConstants.PACKAGE, DeviceTestConstants.TEST_ACTIVITY_CLASS);
+ helper.findUiObject(R.id.text_entry).click();
+
+ final String initialIme = helper.shell(ShellCommandUtils.getCurrentIme());
+ helper.shell(ShellCommandUtils.setCurrentIme(Ime2Constants.IME_ID));
+ pollingCheck(() -> helper.queryAllEvents()
+ .filter(isNewerThan(startActivityTime))
+ .anyMatch(isFrom(Ime2Constants.CLASS).and(isType(ON_START_INPUT))),
+ TIMEOUT, "CtsInputMethod2.onStartInput is called");
+ helper.shell(ShellCommandUtils.broadcastIntent(
+ ACTION_IME_COMMAND, Ime2Constants.PACKAGE,
+ "-e", EXTRA_COMMAND, COMMAND_SWITCH_TO_LAST_INPUT));
+ pollingCheck(() -> helper.shell(ShellCommandUtils.getCurrentIme())
+ .equals(initialIme),
+ TIMEOUT, initialIme + " is current IME");
+ }
+
/**
* Build stream collector of {@link DeviceEvent} collecting sequence that elements have
* specified types.
diff --git a/hostsidetests/inputmethodservice/deviceside/lib/src/android/inputmethodservice/cts/ime/ImeCommandReceiver.java b/hostsidetests/inputmethodservice/deviceside/lib/src/android/inputmethodservice/cts/ime/ImeCommandReceiver.java
index 23e5555..c926b3c 100644
--- a/hostsidetests/inputmethodservice/deviceside/lib/src/android/inputmethodservice/cts/ime/ImeCommandReceiver.java
+++ b/hostsidetests/inputmethodservice/deviceside/lib/src/android/inputmethodservice/cts/ime/ImeCommandReceiver.java
@@ -86,6 +86,19 @@
mIme.commandRequestHideSelf(flags);
return;
}
+ case ImeCommandConstants.COMMAND_SET_INPUT_METHOD_AND_SUBTYPE: {
+ final String imeId = getString1(intent);
+ mIme.setInputMethodAndSubtype(imeId, null);
+ return;
+ }
+ case ImeCommandConstants.COMMAND_SWITCH_TO_NEXT_INPUT: {
+ mIme.switchToNextInputMethod(false);
+ return;
+ }
+ case ImeCommandConstants.COMMAND_SWITCH_TO_LAST_INPUT: {
+ mIme.switchToLastInputMethod();
+ return;
+ }
default: {
throw new UnsupportedOperationException("Unknown IME command: " + command);
}
diff --git a/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/InputMethodServiceLifecycleTest.java b/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/InputMethodServiceLifecycleTest.java
index bdf0983..2e8a8b0 100644
--- a/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/InputMethodServiceLifecycleTest.java
+++ b/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/InputMethodServiceLifecycleTest.java
@@ -104,6 +104,53 @@
assertImeNotSelectedInSecureSettings(Ime1Constants.IME_ID, TIMEOUT);
}
+ @Test
+ public void testSetInputMethodAndSubtype() throws Exception {
+ final TestInfo testSetInputMethod = new TestInfo(
+ DeviceTestConstants.PACKAGE, DeviceTestConstants.TEST_CLASS,
+ DeviceTestConstants.TEST_SET_INPUTMETHOD_AND_SUBTYPE);
+ sendTestStartEvent(testSetInputMethod);
+ installPackage(Ime1Constants.APK, "-r");
+ installPackage(Ime2Constants.APK, "-r");
+ shell(ShellCommandUtils.enableIme(Ime1Constants.IME_ID));
+ shell(ShellCommandUtils.enableIme(Ime2Constants.IME_ID));
+ shell(ShellCommandUtils.setCurrentIme(Ime1Constants.IME_ID));
+
+ assertTrue(runDeviceTestMethod(testSetInputMethod));
+ }
+
+ @Test
+ public void testSwitchToNextInput() throws Exception {
+ final TestInfo testSwitchInputs = new TestInfo(
+ DeviceTestConstants.PACKAGE, DeviceTestConstants.TEST_CLASS,
+ DeviceTestConstants.TEST_SWITCH_NEXT_INPUT);
+ sendTestStartEvent(testSwitchInputs);
+ installPackage(Ime1Constants.APK, "-r");
+ installPackage(Ime2Constants.APK, "-r");
+ shell(ShellCommandUtils.enableIme(Ime1Constants.IME_ID));
+ // Make sure that there is at least one more IME that specifies
+ // supportsSwitchingToNextInputMethod="true"
+ shell(ShellCommandUtils.enableIme(Ime2Constants.IME_ID));
+ shell(ShellCommandUtils.setCurrentIme(Ime1Constants.IME_ID));
+
+ assertTrue(runDeviceTestMethod(testSwitchInputs));
+ }
+
+ @Test
+ public void testSwitchToLastInput() throws Exception {
+ final TestInfo testSwitchInputs = new TestInfo(
+ DeviceTestConstants.PACKAGE, DeviceTestConstants.TEST_CLASS,
+ DeviceTestConstants.TEST_SWITCH_LAST_INPUT);
+ sendTestStartEvent(testSwitchInputs);
+ installPackage(Ime1Constants.APK, "-r");
+ installPackage(Ime2Constants.APK, "-r");
+ shell(ShellCommandUtils.enableIme(Ime1Constants.IME_ID));
+ shell(ShellCommandUtils.enableIme(Ime2Constants.IME_ID));
+ shell(ShellCommandUtils.setCurrentIme(Ime1Constants.IME_ID));
+
+ assertTrue(runDeviceTestMethod(testSwitchInputs));
+ }
+
private void sendTestStartEvent(final TestInfo deviceTest) throws Exception {
final String sender = deviceTest.getTestName();
// {@link EventType#EXTRA_EVENT_TIME} will be recorded at device side.
diff --git a/hostsidetests/jvmti/base/host/src/android/jvmti/cts/JvmtiHostTest.java b/hostsidetests/jvmti/base/host/src/android/jvmti/cts/JvmtiHostTest.java
index 2e060fc..f80492c 100644
--- a/hostsidetests/jvmti/base/host/src/android/jvmti/cts/JvmtiHostTest.java
+++ b/hostsidetests/jvmti/base/host/src/android/jvmti/cts/JvmtiHostTest.java
@@ -16,12 +16,12 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.config.Option;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.ITestLifeCycleReceiver;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IAbi;
import com.android.tradefed.testtype.IAbiReceiver;
@@ -217,22 +217,22 @@
}
@Override
- public void testAssumptionFailure(TestIdentifier arg0, String arg1) {
+ public void testAssumptionFailure(TestDescription arg0, String arg1) {
mFailed = true;
mErrors.add(arg0.toString() + " " + arg1);
}
@Override
- public void testEnded(TestIdentifier arg0, Map<String, String> arg1) {}
+ public void testEnded(TestDescription arg0, Map<String, String> arg1) {}
@Override
- public void testFailed(TestIdentifier arg0, String arg1) {
+ public void testFailed(TestDescription arg0, String arg1) {
mFailed = true;
mErrors.add(arg0.toString() + " " + arg1);
}
@Override
- public void testIgnored(TestIdentifier arg0) {}
+ public void testIgnored(TestDescription arg0) {}
@Override
public void testRunEnded(long arg0, Map<String, String> arg1) {}
@@ -254,7 +254,7 @@
public void testRunStopped(long arg0) {}
@Override
- public void testStarted(TestIdentifier arg0) {
+ public void testStarted(TestDescription arg0) {
mStarted = true;
}
}
diff --git a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/ReportProcessor.java b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/ReportProcessor.java
index e7be900..07b496c 100644
--- a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/ReportProcessor.java
+++ b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/ReportProcessor.java
@@ -16,13 +16,14 @@
package android.media.cts.bitstreams;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.testtype.AndroidJUnitTest;
import com.android.tradefed.util.FileUtil;
+
import java.io.File;
import java.io.IOException;
import java.util.Collections;
@@ -117,12 +118,12 @@
private class MediaBitstreamsListener implements ITestInvocationListener {
@Override
- public void testEnded(TestIdentifier test, Map<String, String> metrics) {
+ public void testEnded(TestDescription test, Map<String, String> metrics) {
mMetrics.putAll(metrics);
}
@Override
- public void testFailed(TestIdentifier test, String trace) {
+ public void testFailed(TestDescription test, String trace) {
mFailureStackTrace = trace;
}
diff --git a/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java b/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java
index dcb1e5a..d505394 100644
--- a/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java
+++ b/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java
@@ -18,12 +18,12 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.result.TestResult;
import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.testtype.DeviceTestCase;
@@ -275,7 +275,7 @@
if (result.hasFailedTests()) {
// Build a meaningful error message
StringBuilder errorBuilder = new StringBuilder("On-device tests failed:\n");
- for (Map.Entry<TestIdentifier, TestResult> resultEntry :
+ for (Map.Entry<TestDescription, TestResult> resultEntry :
result.getTestResults().entrySet()) {
if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
errorBuilder.append(resultEntry.getKey().toString());
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java
index 133a43b..0e141c05 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java
@@ -34,7 +34,7 @@
removePowerSaveModeWhitelist(TEST_APP2_PKG);
removePowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG);
setAppIdle(false);
- turnBatteryOff();
+ turnBatteryOn();
registerBroadcastReceiver();
}
@@ -48,7 +48,7 @@
try {
tearDownMeteredNetwork();
} finally {
- turnBatteryOn();
+ turnBatteryOff();
setAppIdle(false);
}
}
@@ -155,9 +155,9 @@
// Check that app is paroled when charging
setAppIdle(true);
assertBackgroundNetworkAccess(false);
- turnBatteryOn();
- assertBackgroundNetworkAccess(true);
turnBatteryOff();
+ assertBackgroundNetworkAccess(true);
+ turnBatteryOn();
assertBackgroundNetworkAccess(false);
// Check that app is restricted when not idle but power-save is on
@@ -167,11 +167,11 @@
assertBackgroundNetworkAccess(false);
// Use setBatterySaverMode API to leave power-save mode instead of plugging in charger
setBatterySaverMode(false);
- turnBatteryOn();
+ turnBatteryOff();
assertBackgroundNetworkAccess(true);
// And when no longer charging, it still has network access, since it's not idle
- turnBatteryOff();
+ turnBatteryOn();
assertBackgroundNetworkAccess(true);
}
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
index 47ab9fa..406b1d8 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
@@ -49,8 +49,6 @@
import android.text.TextUtils;
import android.util.Log;
-import com.android.cts.net.hostside.INetworkStateObserver;
-
/**
* Superclass for tests related to background network restrictions.
*/
@@ -150,6 +148,7 @@
@Override
protected void tearDown() throws Exception {
+ batteryReset();
if (!mIsLocationOn) {
disableLocation();
}
@@ -809,15 +808,18 @@
assertPowerSaveModeExceptIdleWhitelist(packageName, false); // Sanity check
}
- protected void turnBatteryOff() throws Exception {
+ protected void turnBatteryOn() throws Exception {
executeSilentShellCommand("cmd battery unplug");
assertBatteryState(false);
}
- protected void turnBatteryOn() throws Exception {
- executeSilentShellCommand("cmd battery reset");
+ protected void turnBatteryOff() throws Exception {
+ executeSilentShellCommand("cmd battery set ac " + BatteryManager.BATTERY_PLUGGED_AC);
assertBatteryState(true);
+ }
+ private void batteryReset() throws Exception {
+ executeSilentShellCommand("cmd battery reset");
}
private void assertBatteryState(boolean pluggedIn) throws Exception {
@@ -848,11 +850,11 @@
protected void setBatterySaverMode(boolean enabled) throws Exception {
Log.i(TAG, "Setting Battery Saver Mode to " + enabled);
if (enabled) {
- turnBatteryOff();
+ turnBatteryOn();
executeSilentShellCommand("cmd power set-mode 1");
} else {
executeSilentShellCommand("cmd power set-mode 0");
- turnBatteryOn();
+ turnBatteryOff();
}
}
@@ -862,12 +864,12 @@
Log.i(TAG, "Setting Doze Mode to " + enabled);
if (enabled) {
- turnBatteryOff();
+ turnBatteryOn();
turnScreenOff();
executeShellCommand("dumpsys deviceidle force-idle deep");
} else {
turnScreenOn();
- turnBatteryOn();
+ turnBatteryOff();
executeShellCommand("dumpsys deviceidle unforce");
}
// Sanity check.
diff --git a/hostsidetests/net/src/com/android/cts/net/HostsideNetworkTestCase.java b/hostsidetests/net/src/com/android/cts/net/HostsideNetworkTestCase.java
index efc405f..7c9ce8f 100644
--- a/hostsidetests/net/src/com/android/cts/net/HostsideNetworkTestCase.java
+++ b/hostsidetests/net/src/com/android/cts/net/HostsideNetworkTestCase.java
@@ -19,11 +19,11 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.ddmlib.Log;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.result.TestResult;
import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.testtype.DeviceTestCase;
@@ -150,7 +150,7 @@
if (result.hasFailedTests()) {
// build a meaningful error message
StringBuilder errorBuilder = new StringBuilder("on-device tests failed:\n");
- for (Map.Entry<TestIdentifier, TestResult> resultEntry :
+ for (Map.Entry<TestDescription, TestResult> resultEntry :
result.getTestResults().entrySet()) {
if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
errorBuilder.append(resultEntry.getKey().toString());
diff --git a/hostsidetests/os/src/android/os/cts/StaticSharedLibsHostTests.java b/hostsidetests/os/src/android/os/cts/StaticSharedLibsHostTests.java
index 3a27c78..5097df6 100644
--- a/hostsidetests/os/src/android/os/cts/StaticSharedLibsHostTests.java
+++ b/hostsidetests/os/src/android/os/cts/StaticSharedLibsHostTests.java
@@ -18,11 +18,11 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.result.TestResult;
import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.testtype.DeviceTestCase;
@@ -495,7 +495,7 @@
if (result.hasFailedTests()) {
// build a meaningful error message
StringBuilder errorBuilder = new StringBuilder("on-device tests failed:\n");
- for (Map.Entry<TestIdentifier, TestResult> resultEntry :
+ for (Map.Entry<TestDescription, TestResult> resultEntry :
result.getTestResults().entrySet()) {
if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
errorBuilder.append(resultEntry.getKey().toString());
diff --git a/hostsidetests/shortcuts/hostside/src/android/content/pm/cts/shortcuthost/BaseShortcutManagerHostTest.java b/hostsidetests/shortcuts/hostside/src/android/content/pm/cts/shortcuthost/BaseShortcutManagerHostTest.java
index c5d4f7f..bc33abf 100644
--- a/hostsidetests/shortcuts/hostside/src/android/content/pm/cts/shortcuthost/BaseShortcutManagerHostTest.java
+++ b/hostsidetests/shortcuts/hostside/src/android/content/pm/cts/shortcuthost/BaseShortcutManagerHostTest.java
@@ -17,12 +17,12 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.result.TestResult;
import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.testtype.DeviceTestCase;
@@ -165,7 +165,7 @@
}
private void printTestResult(TestRunResult runResult) {
- for (Map.Entry<TestIdentifier, TestResult> testEntry :
+ for (Map.Entry<TestDescription, TestResult> testEntry :
runResult.getTestResults().entrySet()) {
TestResult testResult = testEntry.getValue();
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AlertTests.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AlertTests.java
index c303ad8..b8e61f5 100644
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AlertTests.java
+++ b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AlertTests.java
@@ -132,7 +132,7 @@
sLatch1 = new CountDownLatch(1);
sLatch2 = new CountDownLatch(1);
mStatsManager.removeConfiguration(CONFIG_ID);
- mStatsManager.addConfiguration(CONFIG_ID, CONFIG.toByteArray(), "", "");
+ mStatsManager.addConfiguration(CONFIG_ID, CONFIG.toByteArray());
mStatsManager.setBroadcastSubscriber(CONFIG_ID, SUBSCRIBER_ID_1, mPendingIntent1);
mStatsManager.setBroadcastSubscriber(CONFIG_ID, SUBSCRIBER_ID_2, mPendingIntent2);
@@ -156,7 +156,7 @@
sLatch1 = new CountDownLatch(2);
sLatch2 = new CountDownLatch(2);
mStatsManager.removeConfiguration(CONFIG_ID);
- mStatsManager.addConfiguration(CONFIG_ID, CONFIG.toByteArray(), "", "");
+ mStatsManager.addConfiguration(CONFIG_ID, CONFIG.toByteArray());
mStatsManager.setBroadcastSubscriber(CONFIG_ID, SUBSCRIBER_ID_1, mPendingIntent1);
mStatsManager.setBroadcastSubscriber(CONFIG_ID, SUBSCRIBER_ID_2, mPendingIntent2);
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java b/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java
index 06f1f49..4e78042 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java
@@ -169,6 +169,15 @@
return data;
}
+ protected StatsLogReport getStatsLogReport() throws Exception {
+ ConfigMetricsReportList reportList = getReportList();
+ assertTrue(reportList.getReportsCount() == 1);
+ ConfigMetricsReport report = reportList.getReports(0);
+ assertTrue(report.hasUidMap());
+ assertEquals(1, report.getMetricsCount());
+ return report.getMetrics(0);
+ }
+
protected ConfigMetricsReportList getReportList() throws Exception {
ConfigMetricsReportList reportList = getDump(ConfigMetricsReportList.parser(),
String.join(" ", DUMP_REPORT_CMD, CONFIG_UID, String.valueOf(CONFIG_ID), "--proto"));
@@ -526,4 +535,4 @@
return hasIt;
}
-}
\ No newline at end of file
+}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/BaseTestCase.java b/hostsidetests/statsd/src/android/cts/statsd/atom/BaseTestCase.java
index 2db4438..654861f 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/BaseTestCase.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/BaseTestCase.java
@@ -18,13 +18,13 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.CollectingByteOutputReceiver;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.result.TestResult;
import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.testtype.DeviceTestCase;
@@ -130,7 +130,7 @@
if (result.hasFailedTests()) {
// build a meaningful error message
StringBuilder errorBuilder = new StringBuilder("On-device tests failed:\n");
- for (Map.Entry<TestIdentifier, TestResult> resultEntry :
+ for (Map.Entry<TestDescription, TestResult> resultEntry :
result.getTestResults().entrySet()) {
if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
errorBuilder.append(resultEntry.getKey().toString());
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/HostAtomTests.java b/hostsidetests/statsd/src/android/cts/statsd/atom/HostAtomTests.java
index 934c5ba..8bac2db 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/HostAtomTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/HostAtomTests.java
@@ -82,7 +82,7 @@
// Setup, make sure the screen is off.
turnScreenOff();
- Thread.sleep(WAIT_TIME_SHORT);
+ Thread.sleep(WAIT_TIME_LONG);
final int atomTag = Atom.SCREEN_STATE_CHANGED_FIELD_NUMBER;
@@ -701,7 +701,7 @@
FieldMatcher.Builder dimension = FieldMatcher.newBuilder()
.setField(Atom.SUBSYSTEM_SLEEP_STATE_FIELD_NUMBER)
.addChild(FieldMatcher.newBuilder()
- .setField(SubsystemSleepState.NAME_FIELD_NUMBER));
+ .setField(SubsystemSleepState.SUBSYSTEM_NAME_FIELD_NUMBER));
addGaugeAtom(config, Atom.SUBSYSTEM_SLEEP_STATE_FIELD_NUMBER, dimension);
turnScreenOff();
@@ -715,7 +715,7 @@
List<Atom> dataList = getGaugeMetricDataList();
for (Atom atom: dataList) {
- assertTrue(!atom.getSubsystemSleepState().getName().equals(""));
+ assertTrue(!atom.getSubsystemSleepState().getSubsystemName().equals(""));
assertTrue(atom.getSubsystemSleepState().getCount() >= 0);
assertTrue(atom.getSubsystemSleepState().getTimeMs() >= 0);
}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/metric/DurationMetricsTests.java b/hostsidetests/statsd/src/android/cts/statsd/metric/DurationMetricsTests.java
new file mode 100644
index 0000000..0183fdf
--- /dev/null
+++ b/hostsidetests/statsd/src/android/cts/statsd/metric/DurationMetricsTests.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2018 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.cts.statsd.metric;
+
+import android.cts.statsd.atom.DeviceAtomTestCase;
+
+import com.android.internal.os.StatsdConfigProto;
+import com.android.internal.os.StatsdConfigProto.AtomMatcher;
+import com.android.internal.os.StatsdConfigProto.FieldMatcher;
+import com.android.internal.os.StatsdConfigProto.FieldValueMatcher;
+import com.android.internal.os.StatsdConfigProto.Position;
+import com.android.internal.os.StatsdConfigProto.Predicate;
+import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
+import com.android.internal.os.StatsdConfigProto.SimplePredicate;
+import com.android.os.AtomsProto.AppHook;
+import com.android.os.AtomsProto.Atom;
+import com.android.os.StatsLog.ConfigMetricsReport;
+import com.android.os.StatsLog.ConfigMetricsReportList;
+import com.android.os.StatsLog.DurationBucketInfo;
+import com.android.os.StatsLog.StatsLogReport;
+import com.android.tradefed.device.DeviceNotAvailableException;
+
+import java.util.List;
+
+public class DurationMetricsTests extends DeviceAtomTestCase {
+
+ private static final int APP_HOOK_A_MATCH_START_ID = 0;
+ private static final int APP_HOOK_A_MATCH_STOP_ID = 1;
+ private static final int APP_HOOK_B_MATCH_START_ID = 2;
+ private static final int APP_HOOK_B_MATCH_STOP_ID = 3;
+
+ public void testDurationMetric() throws Exception {
+ // Add AtomMatcher's.
+ AtomMatcher startAtomMatcher = startAtomMatcher(APP_HOOK_A_MATCH_START_ID);
+ AtomMatcher stopAtomMatcher = stopAtomMatcher(APP_HOOK_A_MATCH_STOP_ID);
+
+ StatsdConfigProto.StatsdConfig.Builder builder = MetricsUtils.getEmptyConfig();
+ builder.addAtomMatcher(startAtomMatcher);
+ builder.addAtomMatcher(stopAtomMatcher);
+
+ // Add Predicate's.
+ SimplePredicate simplePredicate = SimplePredicate.newBuilder()
+ .setStart(APP_HOOK_A_MATCH_START_ID)
+ .setStop(APP_HOOK_A_MATCH_STOP_ID)
+ .build();
+ Predicate predicate = Predicate.newBuilder()
+ .setId(StringToId("Predicate"))
+ .setSimplePredicate(simplePredicate)
+ .build();
+ builder.addPredicate(predicate);
+
+ // Add DurationMetric.
+ builder.addDurationMetric(StatsdConfigProto.DurationMetric.newBuilder()
+ .setId(MetricsUtils.DURATION_METRIC_ID)
+ .setWhat(StringToId("Predicate"))
+ .setAggregationType(StatsdConfigProto.DurationMetric.AggregationType.SUM)
+ .setBucket(StatsdConfigProto.TimeUnit.CTS));
+
+ // Upload config.
+ uploadConfig(builder);
+
+ // Create AppHook Start/Stop events.
+ doAppHookStart(1);
+ Thread.sleep(2000);
+ doAppHookStop(1);
+
+ // Wait for the metrics to propagate to statsd.
+ Thread.sleep(2000);
+
+ StatsLogReport metricReport = getStatsLogReport();
+ assertEquals(MetricsUtils.DURATION_METRIC_ID, metricReport.getMetricId());
+ assertTrue(metricReport.hasDurationMetrics());
+ StatsLogReport.DurationMetricDataWrapper durationData
+ = metricReport.getDurationMetrics();
+ assertTrue(durationData.getDataCount() == 1);
+ assertTrue(durationData.getData(0).getBucketInfo(0).getDurationNanos() > 0);
+ assertTrue(durationData.getData(0).getBucketInfo(0).getDurationNanos() < 1e10);
+ }
+
+ public void testDurationMetricWithDimension() throws Exception {
+ // Add AtomMatcher's.
+ AtomMatcher startAtomMatcherA = startAtomMatcher(APP_HOOK_A_MATCH_START_ID);
+ AtomMatcher stopAtomMatcherA = stopAtomMatcher(APP_HOOK_A_MATCH_STOP_ID);
+ AtomMatcher startAtomMatcherB = startAtomMatcher(APP_HOOK_B_MATCH_START_ID);
+ AtomMatcher stopAtomMatcherB = stopAtomMatcher(APP_HOOK_B_MATCH_STOP_ID);
+
+ StatsdConfigProto.StatsdConfig.Builder builder = MetricsUtils.getEmptyConfig();
+ builder.addAtomMatcher(startAtomMatcherA);
+ builder.addAtomMatcher(stopAtomMatcherA);
+ builder.addAtomMatcher(startAtomMatcherB);
+ builder.addAtomMatcher(stopAtomMatcherB);
+
+ // Add Predicate's.
+ SimplePredicate simplePredicateA = SimplePredicate.newBuilder()
+ .setStart(APP_HOOK_A_MATCH_START_ID)
+ .setStop(APP_HOOK_A_MATCH_STOP_ID)
+ .build();
+ Predicate predicateA = Predicate.newBuilder()
+ .setId(StringToId("Predicate_A"))
+ .setSimplePredicate(simplePredicateA)
+ .build();
+ builder.addPredicate(predicateA);
+
+ FieldMatcher.Builder dimensionsBuilder = FieldMatcher.newBuilder()
+ .setField(AppHook.STATE_FIELD_NUMBER);
+ dimensionsBuilder.addChild(FieldMatcher.newBuilder()
+ .setField(AppHook.LABEL_FIELD_NUMBER)
+ .setPosition(Position.FIRST)
+ .addChild(FieldMatcher.newBuilder().setField(AppHook.LABEL_FIELD_NUMBER)));
+ Predicate predicateB = Predicate.newBuilder()
+ .setId(StringToId("Predicate_B"))
+ .setSimplePredicate(SimplePredicate.newBuilder()
+ .setStart(APP_HOOK_B_MATCH_START_ID)
+ .setStop(APP_HOOK_B_MATCH_STOP_ID)
+ .setDimensions(dimensionsBuilder.build())
+ .build())
+ .build();
+ builder.addPredicate(predicateB);
+
+ // Add DurationMetric.
+ builder.addDurationMetric(StatsdConfigProto.DurationMetric.newBuilder()
+ .setId(MetricsUtils.DURATION_METRIC_ID)
+ .setWhat(StringToId("Predicate_B"))
+ .setCondition(StringToId("Predicate_A"))
+ .setAggregationType(StatsdConfigProto.DurationMetric.AggregationType.SUM)
+ .setBucket(StatsdConfigProto.TimeUnit.CTS)
+ .setDimensionsInWhat(FieldMatcher.newBuilder()
+ .setField(Atom.BATTERY_SAVER_MODE_STATE_CHANGED_FIELD_NUMBER)
+ .addChild(FieldMatcher.newBuilder()
+ .setField(AppHook.STATE_FIELD_NUMBER)
+ .setPosition(Position.FIRST)
+ .addChild(FieldMatcher.newBuilder().setField(AppHook.LABEL_FIELD_NUMBER)))));
+
+ // Upload config.
+ uploadConfig(builder);
+
+ // Trigger events.
+ doAppHookStart(1);
+ Thread.sleep(2000);
+ doAppHookStart(2);
+ Thread.sleep(2000);
+ doAppHookStop(1);
+ Thread.sleep(2000);
+ doAppHookStop(2);
+
+ // Wait for the metrics to propagate to statsd.
+ Thread.sleep(2000);
+
+ StatsLogReport metricReport = getStatsLogReport();
+ assertEquals(MetricsUtils.DURATION_METRIC_ID, metricReport.getMetricId());
+ assertTrue(metricReport.hasDurationMetrics());
+ StatsLogReport.DurationMetricDataWrapper durationData
+ = metricReport.getDurationMetrics();
+ assertTrue(durationData.getDataCount() == 1);
+ assertTrue(durationData.getData(0).getBucketInfoList().size() > 1);
+ for (DurationBucketInfo bucketInfo : durationData.getData(0).getBucketInfoList()) {
+ assertTrue(bucketInfo.getDurationNanos() > 0);
+ assertTrue(bucketInfo.getDurationNanos() < 1e10);
+ }
+ }
+
+ private void doAppHookStart(int label) throws Exception {
+ doAppHook(label, AppHook.State.START.ordinal());
+ }
+
+ private void doAppHookStop(int label) throws Exception {
+ doAppHook(label, AppHook.State.STOP.ordinal());
+ }
+
+ private void doAppHook(int label, int state) throws Exception {
+ getDevice().executeShellCommand(String.format(
+ "cmd stats log-app-hook %d %d", label, state));
+ }
+
+ private AtomMatcher startAtomMatcher(int id) {
+ return AtomMatcher.newBuilder()
+ .setId(id)
+ .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
+ .setAtomId(Atom.APP_HOOK_FIELD_NUMBER)
+ .addFieldValueMatcher(FieldValueMatcher.newBuilder()
+ .setField(AppHook.STATE_FIELD_NUMBER)
+ .setEqInt(AppHook.State.START.ordinal())))
+ .build();
+ }
+
+ private AtomMatcher stopAtomMatcher(int id) {
+ return AtomMatcher.newBuilder()
+ .setId(id)
+ .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
+ .setAtomId(Atom.APP_HOOK_FIELD_NUMBER)
+ .addFieldValueMatcher(FieldValueMatcher.newBuilder()
+ .setField(AppHook.STATE_FIELD_NUMBER)
+ .setEqInt(AppHook.State.STOP.ordinal())))
+ .build();
+ }
+
+ private long StringToId(String str) {
+ return str.hashCode();
+ }
+}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/metric/MetricsTestCase.java b/hostsidetests/statsd/src/android/cts/statsd/metric/MetricsTestCase.java
index bb1d599..35f1026 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/metric/MetricsTestCase.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/metric/MetricsTestCase.java
@@ -25,18 +25,6 @@
import java.util.List;
public class MetricsTestCase extends DeviceAtomTestCase {
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- getDevice().uninstallPackage(DEVICE_SIDE_TEST_PACKAGE);
- installTestApp();
- }
-
- @Override
- protected void tearDown() throws Exception {
- getDevice().uninstallPackage(DEVICE_SIDE_TEST_PACKAGE);
- super.tearDown();
- }
private static abstract class TestCase {
private final StatsdConfigProto.StatsdConfig mConfig;
diff --git a/hostsidetests/statsd/src/android/cts/statsd/metric/MetricsUtils.java b/hostsidetests/statsd/src/android/cts/statsd/metric/MetricsUtils.java
index 596ff8a..e7b21a6 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/metric/MetricsUtils.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/metric/MetricsUtils.java
@@ -16,22 +16,26 @@
package android.cts.statsd.metric;
import com.android.internal.os.StatsdConfigProto;
+import com.android.internal.os.StatsdConfigProto.AtomMatcher;
+import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
public class MetricsUtils {
public static final long COUNT_METRIC_ID = 3333;
+ public static final long DURATION_METRIC_ID = 4444;
public static StatsdConfigProto.StatsdConfig.Builder getEmptyConfig() {
StatsdConfigProto.StatsdConfig.Builder builder =
StatsdConfigProto.StatsdConfig.newBuilder();
- // only accept the log events from this cts to avoid noise.
+ // Only accept the log events from this cts and android system (1000) to avoid noise.
builder.addAllowedLogSource("com.android.server.cts.device.statsd");
+ builder.addAllowedLogSource("android");
return builder;
}
- public static StatsdConfigProto.AtomMatcher.Builder getAtomMatcher(int atomTag) {
- StatsdConfigProto.AtomMatcher.Builder builder = StatsdConfigProto.AtomMatcher.newBuilder();
- builder.setSimpleAtomMatcher(StatsdConfigProto.SimpleAtomMatcher.newBuilder()
- .setAtomId(atomTag).build());
+ public static AtomMatcher.Builder getAtomMatcher(int atomId) {
+ AtomMatcher.Builder builder = AtomMatcher.newBuilder();
+ builder.setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
+ .setAtomId(atomId).build());
return builder;
}
}
diff --git a/hostsidetests/theme/assets/P/260dpi.zip b/hostsidetests/theme/assets/P/260dpi.zip
index ee51862..cd938f9 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 35684df..c75ab35 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 85ca77e..dae6771 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 5b04c23..c33be5c 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 26af132..e49c3c6 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 431efd6..d6fa8d1 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 81ddaa6..882cd2e 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 d8d6159..3d25327 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 ddec4a1..3bd0217 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 0b0fe66..390613a 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 abeaa1b..656fab1 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 a9911d7..61d2df1 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 c1e068c..7304c22 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 de491eb..6f2aab8 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 cc9382a..8a714bd 100644
--- a/hostsidetests/theme/assets/P/xxxhdpi.zip
+++ b/hostsidetests/theme/assets/P/xxxhdpi.zip
Binary files differ
diff --git a/hostsidetests/ui/src/android/ui/cts/TaskSwitchingTest.java b/hostsidetests/ui/src/android/ui/cts/TaskSwitchingTest.java
index acf9972..814d4e1 100644
--- a/hostsidetests/ui/src/android/ui/cts/TaskSwitchingTest.java
+++ b/hostsidetests/ui/src/android/ui/cts/TaskSwitchingTest.java
@@ -20,10 +20,10 @@
import com.android.compatibility.common.util.MetricsStore;
import com.android.compatibility.common.util.ReportLog;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.result.TestRunResult;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IAbi;
@@ -111,7 +111,7 @@
public class LocalListener extends CollectingTestListener {
@Override
- public void testEnded(TestIdentifier test, Map<String, String> testMetrics) {
+ public void testEnded(TestDescription test, Map<String, String> testMetrics) {
// necessary as testMetrics passed from CollectingTestListerner is empty
if (testMetrics.containsKey(RESULT_KEY)) {
try {
diff --git a/tests/AlarmManager/src/android/alarmmanager/cts/AppStandbyTests.java b/tests/AlarmManager/src/android/alarmmanager/cts/AppStandbyTests.java
index c4b5a0d..d9d621b 100644
--- a/tests/AlarmManager/src/android/alarmmanager/cts/AppStandbyTests.java
+++ b/tests/AlarmManager/src/android/alarmmanager/cts/AppStandbyTests.java
@@ -16,12 +16,13 @@
package android.alarmmanager.cts;
+import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
+
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.alarmmanager.alarmtestapp.cts.TestAlarmReceiver;
import android.alarmmanager.alarmtestapp.cts.TestAlarmScheduler;
-import android.app.AlarmManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -57,6 +58,7 @@
private static final long POLL_INTERVAL = 200;
// Tweaked alarm manager constants to facilitate testing
+ private static final long ALLOW_WHILE_IDLE_SHORT_TIME = 15_000;
private static final long MIN_FUTURITY = 2_000;
private static final long[] APP_STANDBY_DELAYS = {0, 10_000, 20_000, 30_000, 600_000};
private static final String[] APP_BUCKET_TAGS = {
@@ -102,17 +104,18 @@
intentFilter.addAction(TestAlarmReceiver.ACTION_REPORT_ALARM_EXPIRED);
mContext.registerReceiver(mAlarmStateReceiver, intentFilter);
setAppStandbyBucket("active");
- scheduleAlarm(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), 0);
+ scheduleAlarm(SystemClock.elapsedRealtime(), false, 0);
Thread.sleep(MIN_FUTURITY);
assertTrue("Alarm not sent when app in active", waitForAlarms(1));
}
- private void scheduleAlarm(int type, long triggerMillis, long interval) {
+ private void scheduleAlarm(long triggerMillis, boolean allowWhileIdle, long interval) {
final Intent setAlarmIntent = new Intent(TestAlarmScheduler.ACTION_SET_ALARM);
setAlarmIntent.setComponent(mAlarmScheduler);
- setAlarmIntent.putExtra(TestAlarmScheduler.EXTRA_TYPE, type);
+ setAlarmIntent.putExtra(TestAlarmScheduler.EXTRA_TYPE, ELAPSED_REALTIME_WAKEUP);
setAlarmIntent.putExtra(TestAlarmScheduler.EXTRA_TRIGGER_TIME, triggerMillis);
setAlarmIntent.putExtra(TestAlarmScheduler.EXTRA_REPEAT_INTERVAL, interval);
+ setAlarmIntent.putExtra(TestAlarmScheduler.EXTRA_ALLOW_WHILE_IDLE, allowWhileIdle);
mContext.sendBroadcast(setAlarmIntent);
}
@@ -120,7 +123,7 @@
setAppStandbyBucket(APP_BUCKET_TAGS[bucketIndex]);
final long triggerTime = SystemClock.elapsedRealtime() + MIN_FUTURITY;
final long minTriggerTime = mLastAlarmTime + APP_STANDBY_DELAYS[bucketIndex];
- scheduleAlarm(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerTime, 0);
+ scheduleAlarm(triggerTime, false, 0);
Thread.sleep(MIN_FUTURITY);
if (triggerTime + DEFAULT_WAIT < minTriggerTime) {
assertFalse("Alarm went off before " + APP_BUCKET_TAGS[bucketIndex] + " delay",
@@ -151,7 +154,7 @@
setAppStandbyBucket(APP_BUCKET_TAGS[2]);
final long triggerTime = SystemClock.elapsedRealtime() + MIN_FUTURITY;
final long workingSetExpectedTrigger = mLastAlarmTime + APP_STANDBY_DELAYS[1];
- scheduleAlarm(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerTime, 0);
+ scheduleAlarm(triggerTime, false, 0);
Thread.sleep(workingSetExpectedTrigger - SystemClock.elapsedRealtime());
assertFalse("The alarm went off before frequent delay", waitForAlarms(1));
setAppStandbyBucket(APP_BUCKET_TAGS[1]);
@@ -170,7 +173,7 @@
public void testBucketUpgradeToNoDelay() throws Exception {
setAppStandbyBucket(APP_BUCKET_TAGS[3]);
final long triggerTime1 = mLastAlarmTime + APP_STANDBY_DELAYS[2];
- scheduleAlarm(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerTime1, 0);
+ scheduleAlarm(triggerTime1, false, 0);
Thread.sleep(triggerTime1 - SystemClock.elapsedRealtime());
assertFalse("The alarm went off after frequent delay when app in rare bucket",
waitForAlarms(1));
@@ -181,15 +184,54 @@
// Once more
setAppStandbyBucket(APP_BUCKET_TAGS[3]);
final long triggerTime2 = mLastAlarmTime + APP_STANDBY_DELAYS[2];
- scheduleAlarm(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerTime2, 0);
+ scheduleAlarm(triggerTime2, false, 0);
setAppStandbyBucket(APP_BUCKET_TAGS[0]);
Thread.sleep(triggerTime2 - SystemClock.elapsedRealtime());
assertTrue("The alarm did not go off as scheduled when the app was in active",
waitForAlarms(1));
}
+ @Test
+ public void testAllowWhileIdleAlarms() throws Exception {
+ final long firstTrigger = SystemClock.elapsedRealtime() + MIN_FUTURITY;
+ scheduleAlarm(firstTrigger, true, 0);
+ Thread.sleep(MIN_FUTURITY);
+ assertTrue("first allow_while_idle alarm did not go off as scheduled", waitForAlarms(1));
+ scheduleAlarm(mLastAlarmTime + 9_000, true, 0);
+ // First check for the case where allow_while_idle delay should supersede app standby
+ setAppStandbyBucket(APP_BUCKET_TAGS[1]);
+ Thread.sleep(APP_STANDBY_DELAYS[1]);
+ assertFalse("allow_while_idle alarm went off before short time", waitForAlarms(1));
+ long expectedTriggerTime = mLastAlarmTime + ALLOW_WHILE_IDLE_SHORT_TIME;
+ Thread.sleep(expectedTriggerTime - SystemClock.elapsedRealtime());
+ assertTrue("allow_while_idle alarm did not go off after short time", waitForAlarms(1));
+
+ // Now the other case, app standby delay supersedes the allow_while_idle delay
+ scheduleAlarm(mLastAlarmTime + 12_000, true, 0);
+ setAppStandbyBucket(APP_BUCKET_TAGS[2]);
+ Thread.sleep(ALLOW_WHILE_IDLE_SHORT_TIME);
+ assertFalse("allow_while_idle alarm went off before " + APP_STANDBY_DELAYS[2]
+ + "ms, when in bucket " + APP_BUCKET_TAGS[2], waitForAlarms(1));
+ expectedTriggerTime = mLastAlarmTime + APP_STANDBY_DELAYS[2];
+ Thread.sleep(expectedTriggerTime - SystemClock.elapsedRealtime());
+ assertTrue("allow_while_idle alarm did not go off even after " + APP_STANDBY_DELAYS[2]
+ + "ms, when in bucket " + APP_BUCKET_TAGS[2], waitForAlarms(1));
+ }
+
+ @Test
+ public void testPowerWhitelistedAlarmNotBlocked() throws Exception {
+ setAppStandbyBucket(APP_BUCKET_TAGS[3]);
+ setPowerWhitelisted(true);
+ final long triggerTime = SystemClock.elapsedRealtime() + MIN_FUTURITY;
+ scheduleAlarm(triggerTime, false, 0);
+ Thread.sleep(MIN_FUTURITY);
+ assertTrue("Alarm did not go off for whitelisted app in rare bucket", waitForAlarms(1));
+ setPowerWhitelisted(false);
+ }
+
@After
public void tearDown() throws Exception {
+ setPowerWhitelisted(false);
setBatteryCharging(true);
deleteAlarmManagerConstants();
final Intent cancelAlarmsIntent = new Intent(TestAlarmScheduler.ACTION_CANCEL_ALL_ALARMS);
@@ -203,6 +245,7 @@
private void updateAlarmManagerConstants() throws IOException {
final StringBuffer cmd = new StringBuffer("settings put global alarm_manager_constants ");
cmd.append("min_futurity="); cmd.append(MIN_FUTURITY);
+ cmd.append(",allow_while_idle_short_time="); cmd.append(ALLOW_WHILE_IDLE_SHORT_TIME);
for (int i = 0; i < APP_STANDBY_DELAYS.length; i++) {
cmd.append(",");
cmd.append(APP_BUCKET_KEYS[i]); cmd.append("="); cmd.append(APP_STANDBY_DELAYS[i]);
@@ -210,6 +253,13 @@
executeAndLog(cmd.toString());
}
+ private void setPowerWhitelisted(boolean whitelist) throws IOException {
+ final StringBuffer cmd = new StringBuffer("cmd deviceidle whitelist ");
+ cmd.append(whitelist ? "+" : "-");
+ cmd.append(TEST_APP_PACKAGE);
+ executeAndLog(cmd.toString());
+ }
+
private void deleteAlarmManagerConstants() throws IOException {
executeAndLog("settings delete global alarm_manager_constants");
}
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java
index e9902f8..2b5f6ae 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java
@@ -56,7 +56,7 @@
// marshal and unmarshal the node info
Parcel parcel = Parcel.obtain();
- sentInfo.writeToParcel(parcel, 0);
+ sentInfo.writeToParcelNoRecycle(parcel, 0);
parcel.setDataPosition(0);
AccessibilityNodeInfo receivedInfo = AccessibilityNodeInfo.CREATOR.createFromParcel(parcel);
diff --git a/tests/accessibilityservice/AndroidManifest.xml b/tests/accessibilityservice/AndroidManifest.xml
index fe5e18a..e709c6f 100644
--- a/tests/accessibilityservice/AndroidManifest.xml
+++ b/tests/accessibilityservice/AndroidManifest.xml
@@ -53,7 +53,8 @@
<activity
android:label="Full screen activity for gesture dispatch testing"
- android:name=".AccessibilityGestureDispatchTest$GestureDispatchActivity" />
+ android:name=".AccessibilityGestureDispatchTest$GestureDispatchActivity"
+ android:screenOrientation="portrait" />
<service
android:name=".StubGestureAccessibilityService"
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFingerprintGestureTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFingerprintGestureTest.java
index 3eebff9..c9b0027 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFingerprintGestureTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFingerprintGestureTest.java
@@ -16,13 +16,16 @@
import android.accessibilityservice.FingerprintGestureController;
import android.accessibilityservice.FingerprintGestureController.FingerprintGestureCallback;
+import android.accessibilityservice.cts.activities.AccessibilityEndToEndActivity;
import android.app.Instrumentation;
import android.hardware.fingerprint.FingerprintManager;
import android.os.CancellationSignal;
import android.support.test.InstrumentationRegistry;
+import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -53,6 +56,11 @@
FingerprintGestureController mFingerprintGestureController;
CancellationSignal mCancellationSignal = new CancellationSignal();
+ @Rule
+ public ActivityTestRule<AccessibilityEndToEndActivity> mActivityRule =
+ new ActivityTestRule<>(AccessibilityEndToEndActivity.class, false, false);
+
+
@Mock FingerprintManager.AuthenticationCallback mMockAuthenticationCallback;
@Mock FingerprintGestureCallback mMockFingerprintGestureCallback;
@@ -86,6 +94,8 @@
if (!mIsHardwareAvailable) {
return;
}
+ // Launch an activity to make sure we're in the foreground
+ mActivityRule.launchActivity(null);
mFingerprintGestureController.registerFingerprintGestureCallback(
mMockFingerprintGestureCallback, null);
try {
diff --git a/tests/app/src/android/app/cts/ApplicationTest.java b/tests/app/src/android/app/cts/ApplicationTest.java
index 664d3ee..ee1758d 100644
--- a/tests/app/src/android/app/cts/ApplicationTest.java
+++ b/tests/app/src/android/app/cts/ApplicationTest.java
@@ -21,16 +21,25 @@
import android.app.Instrumentation;
import android.app.stubs.MockApplication;
import android.app.stubs.MockApplicationActivity;
-import android.app.stubs.OrientationTestUtils;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.PackageManager;
import android.test.InstrumentationTestCase;
+import com.android.compatibility.common.util.SystemUtil;
+
/**
* Test {@link Application}.
*/
public class ApplicationTest extends InstrumentationTestCase {
+ private static final String ERASE_FONT_SCALE_CMD = "settings delete system font_scale";
+ // 2 is an arbitrary value.
+ private static final String PUT_FONT_SCALE_CMD = "settings put system font_scale 2";
+
+ @Override
+ public void tearDown() throws Exception {
+ SystemUtil.runShellCommand(getInstrumentation(), ERASE_FONT_SCALE_CMD);
+ }
+
public void testApplication() throws Throwable {
final Instrumentation instrumentation = getInstrumentation();
@@ -43,27 +52,30 @@
final MockApplication mockApp = (MockApplication) activity.getApplication();
assertTrue(mockApp.isConstructorCalled);
assertTrue(mockApp.isOnCreateCalled);
+ toggleFontScale();
+ assertTrue(waitForOnConfigurationChange(mockApp));
+ }
- //skip if the device doesn't support both of portrait and landscape orientation screens.
- final PackageManager pm = targetContext.getPackageManager();
- if(!(pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE)
- && pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_PORTRAIT))){
- return;
- }
+ // Font scale is a global configuration.
+ // This function will delete any previous font scale changes, apply one, and remove it.
+ private void toggleFontScale() throws Throwable {
+ SystemUtil.runShellCommand(getInstrumentation(), ERASE_FONT_SCALE_CMD);
+ getInstrumentation().waitForIdleSync();
+ SystemUtil.runShellCommand(getInstrumentation(), PUT_FONT_SCALE_CMD);
+ getInstrumentation().waitForIdleSync();
+ SystemUtil.runShellCommand(getInstrumentation(), ERASE_FONT_SCALE_CMD);
+ }
- runTestOnUiThread(new Runnable() {
- public void run() {
- OrientationTestUtils.toggleOrientation(activity);
+ // Wait for a maximum of 5 seconds for global config change to occur.
+ private boolean waitForOnConfigurationChange(MockApplication mockApp) throws Throwable {
+ int retriesLeft = 5;
+ while(retriesLeft-- > 0) {
+ if (mockApp.isOnConfigurationChangedCalled) {
+ return true;
}
- });
- instrumentation.waitForIdleSync();
- final boolean isInMultiwindowMode = activity.isInMultiWindowMode();
- if (activity.isInMultiWindowMode()) {
- assertFalse("Orientation change should not trigger global configuration change when "
- + " in multi-window mode.", mockApp.isOnConfigurationChangedCalled);
- } else {
- assertTrue(mockApp.isOnConfigurationChangedCalled);
+ Thread.sleep(1000);
}
+ return false;
}
}
diff --git a/tests/app/src/android/app/cts/DialogTest.java b/tests/app/src/android/app/cts/DialogTest.java
index 453fd44..3673803 100755
--- a/tests/app/src/android/app/cts/DialogTest.java
+++ b/tests/app/src/android/app/cts/DialogTest.java
@@ -124,6 +124,20 @@
assertFalse(mActivity.onCancelListenerCalled);
}
+ public void testConstructor_protectedCancellableEsc() {
+ startDialogActivity(DialogStubActivity.TEST_PROTECTED_CANCELABLE);
+ mActivity.onCancelListenerCalled = false;
+ sendKeys(KeyEvent.KEYCODE_ESCAPE);
+ assertTrue(mActivity.onCancelListenerCalled);
+ }
+
+ public void testConstructor_protectedNotCancellableEsc() {
+ startDialogActivity(DialogStubActivity.TEST_PROTECTED_NOT_CANCELABLE);
+ mActivity.onCancelListenerCalled = false;
+ sendKeys(KeyEvent.KEYCODE_ESCAPE);
+ assertFalse(mActivity.onCancelListenerCalled);
+ }
+
private void assertTextAppearanceStyle(TypedArray ta) {
final int defValue = -1;
// get Theme and assert
@@ -158,6 +172,18 @@
assertTrue(d.isOnStopCalled);
}
+ public void testOnStartCreateStopEsc(){
+ startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
+ final TestDialog d = (TestDialog) mActivity.getDialog();
+
+ assertTrue(d.isOnStartCalled);
+ assertTrue(d.isOnCreateCalled);
+
+ assertFalse(d.isOnStopCalled);
+ sendKeys(KeyEvent.KEYCODE_ESCAPE);
+ assertTrue(d.isOnStopCalled);
+ }
+
public void testAccessOwnerActivity() throws Throwable {
startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
Dialog d = mActivity.getDialog();
@@ -755,7 +781,7 @@
assertEquals(d.getWindow().getLayoutInflater(), d.getLayoutInflater());
}
- public void testSetCancelable_true() {
+ public void testSetCancellable_true() {
startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
final Dialog d = mActivity.getDialog();
@@ -775,6 +801,26 @@
assertTrue(d.isShowing());
}
+ public void testSetCancellableEsc_true() {
+ startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
+ final Dialog d = mActivity.getDialog();
+
+ d.setCancelable(true);
+ assertTrue(d.isShowing());
+ sendKeys(KeyEvent.KEYCODE_ESCAPE);
+ assertFalse(d.isShowing());
+ }
+
+ public void testSetCancellableEsc_false() {
+ startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
+ final Dialog d = mActivity.getDialog();
+
+ d.setCancelable(false);
+ assertTrue(d.isShowing());
+ sendKeys(KeyEvent.KEYCODE_ESCAPE);
+ assertTrue(d.isShowing());
+ }
+
/*
* Test point
* 1. Cancel the dialog.
@@ -786,6 +832,7 @@
assertTrue(d.isShowing());
mOnCancelListenerCalled = false;
+
d.setOnCancelListener(new OnCancelListener() {
public void onCancel(DialogInterface dialog) {
mOnCancelListenerCalled = true;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java
index 695f7f0..9ff2325 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java
@@ -27,19 +27,19 @@
import static android.autofillservice.cts.VirtualContainerView.LABEL_CLASS;
import static android.autofillservice.cts.VirtualContainerView.TEXT_CLASS;
import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_PASSWORD;
-
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import android.app.assist.AssistStructure.ViewNode;
import android.autofillservice.cts.CannedFillResponse.CannedDataset;
import android.autofillservice.cts.InstrumentedAutoFillService.FillRequest;
+import android.autofillservice.cts.InstrumentedAutoFillService.SaveRequest;
import android.autofillservice.cts.VirtualContainerView.Line;
import android.content.ComponentName;
import android.graphics.Rect;
-import android.os.SystemClock;
import android.service.autofill.SaveInfo;
import android.support.test.uiautomator.UiObject2;
+import android.view.ViewGroup;
import android.view.autofill.AutofillManager;
import org.junit.Before;
@@ -380,35 +380,74 @@
}
@Test
- public void testSaveDialogShownWhenAllVirtualViewsNotVisible() throws Throwable {
+ public void testSave_childViewsGone() throws Throwable {
+ saveTest(CommitType.CHILDREN_VIEWS_GONE);
+ }
+
+ @Test
+ public void testSave_parentViewGone() throws Throwable {
+ saveTest(CommitType.PARENT_VIEW_GONE);
+ }
+
+ @Test
+ public void testSave_appCallsCommit() throws Throwable {
+ saveTest(CommitType.EXPLICIT_COMMIT);
+ }
+
+ enum CommitType {
+ CHILDREN_VIEWS_GONE,
+ PARENT_VIEW_GONE,
+ EXPLICIT_COMMIT
+ }
+
+ private void saveTest(CommitType commitType) throws Throwable {
// Set service.
enableService();
// Set expectations.
- sReplier.addResponse(new CannedFillResponse.Builder()
- .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
- .setSaveInfoFlags(SaveInfo.FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE)
- .build());
+ final CannedFillResponse.Builder response = new CannedFillResponse.Builder()
+ .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD);
+ if (commitType == CommitType.CHILDREN_VIEWS_GONE
+ || commitType == CommitType.PARENT_VIEW_GONE) {
+ response.setSaveInfoFlags(SaveInfo.FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE);
+ }
+ sReplier.addResponse(response.build());
// Trigger auto-fill.
focusToUsernameExpectNoWindowEvent();
sReplier.getNextFillRequest();
- // TODO: 63602573 Should be removed once this bug is fixed
- SystemClock.sleep(1000);
-
mActivity.runOnUiThread(() -> {
// Fill in some stuff
mActivity.mUsername.setText("foo");
mActivity.mPassword.setText("bar");
-
- // Hide all virtual views
- mActivity.mUsername.changeVisibility(false);
- mActivity.mPassword.changeVisibility(false);
+ switch (commitType) {
+ case CHILDREN_VIEWS_GONE:
+ mActivity.mUsername.changeVisibility(false);
+ mActivity.mPassword.changeVisibility(false);
+ break;
+ case PARENT_VIEW_GONE:
+ final ViewGroup parent = (ViewGroup) mActivity.mCustomView.getParent();
+ parent.removeView(mActivity.mCustomView);
+ break;
+ case EXPLICIT_COMMIT:
+ mActivity.getAutofillManager().commit();
+ break;
+ default:
+ throw new IllegalArgumentException("unknown type: " + commitType);
+ }
});
- // Make sure save is shown
- mUiBot.assertSaveShowing(SAVE_DATA_TYPE_PASSWORD);
+ // Trigger save.
+ mUiBot.saveForAutofill(true, SAVE_DATA_TYPE_PASSWORD);
+
+ // Assert results
+ final SaveRequest saveRequest = sReplier.getNextSaveRequest();
+ final ViewNode username = findNodeByResourceId(saveRequest.structure, ID_USERNAME);
+ final ViewNode password = findNodeByResourceId(saveRequest.structure, ID_PASSWORD);
+
+ assertTextAndValue(username, "foo");
+ assertTextAndValue(password, "bar");
}
@Test
diff --git a/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java b/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java
index f3b4942..c537c04 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java
@@ -43,6 +43,7 @@
import android.hardware.camera2.params.SessionConfiguration;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.ImageReader;
+import android.os.ConditionVariable;
import android.os.Handler;
import android.os.SystemClock;
import android.util.Log;
@@ -51,6 +52,7 @@
import com.android.ex.camera2.blocking.BlockingSessionCallback;
import com.android.ex.camera2.blocking.BlockingStateCallback;
+import com.android.ex.camera2.exceptions.TimeoutRuntimeException;
import com.android.ex.camera2.utils.StateWaiter;
import java.util.ArrayList;
@@ -896,6 +898,174 @@
}
/**
+ * Check for any state leakage in case of internal re-configure
+ */
+ public void testSessionParametersStateLeak() throws Exception {
+ for (int i = 0; i < mCameraIds.length; i++) {
+ try {
+ openDevice(mCameraIds[i], mCameraMockListener);
+ waitForDeviceState(STATE_OPENED, CAMERA_OPEN_TIMEOUT_MS);
+ if (!mStaticInfo.isColorOutputSupported()) {
+ Log.i(TAG, "Camera " + mCameraIds[i] +
+ " does not support color outputs, skipping");
+ continue;
+ }
+ testSessionParametersStateLeakByCamera(mCameraIds[i]);
+ }
+ finally {
+ closeDevice(mCameraIds[i], mCameraMockListener);
+ }
+ }
+ }
+
+ /**
+ * Check for any state leakage in case of internal re-configure
+ */
+ private void testSessionParametersStateLeakByCamera(String cameraId)
+ throws Exception {
+ int outputFormat = ImageFormat.YUV_420_888;
+ Size outputSize = mOrderedPreviewSizes.get(0);
+
+ CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(cameraId);
+ StreamConfigurationMap config = characteristics.get(
+ CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+ List <CaptureRequest.Key<?>> sessionKeys = characteristics.getAvailableSessionKeys();
+ if (sessionKeys == null) {
+ return;
+ }
+
+ if (config.isOutputSupportedFor(outputFormat)) {
+ outputSize = config.getOutputSizes(outputFormat)[0];
+ } else {
+ return;
+ }
+
+ ImageReader imageReader = ImageReader.newInstance(outputSize.getWidth(),
+ outputSize.getHeight(), outputFormat, /*maxImages*/3);
+
+ class OnReadyCaptureStateCallback extends CameraCaptureSession.StateCallback {
+ private ConditionVariable onReadyTriggeredCond = new ConditionVariable();
+ private boolean onReadyTriggered = false;
+
+ @Override
+ public void onConfigured(CameraCaptureSession session) {
+ }
+
+ @Override
+ public void onConfigureFailed(CameraCaptureSession session) {
+ }
+
+ @Override
+ public synchronized void onReady(CameraCaptureSession session) {
+ onReadyTriggered = true;
+ onReadyTriggeredCond.open();
+ }
+
+ public void waitForOnReady(long timeout) {
+ synchronized (this) {
+ if (onReadyTriggered) {
+ onReadyTriggered = false;
+ onReadyTriggeredCond.close();
+ return;
+ }
+ }
+
+ if (onReadyTriggeredCond.block(timeout)) {
+ synchronized (this) {
+ onReadyTriggered = false;
+ onReadyTriggeredCond.close();
+ }
+ } else {
+ throw new TimeoutRuntimeException("Unable to receive onReady after "
+ + timeout + "ms");
+ }
+ }
+ }
+
+ OnReadyCaptureStateCallback sessionListener = new OnReadyCaptureStateCallback();
+
+ try {
+ mSessionMockListener = spy(new BlockingSessionCallback(sessionListener));
+ mSessionWaiter = mSessionMockListener.getStateWaiter();
+ List<OutputConfiguration> outputs = new ArrayList<>();
+ outputs.add(new OutputConfiguration(imageReader.getSurface()));
+ SessionConfiguration sessionConfig = new SessionConfiguration(
+ SessionConfiguration.SESSION_REGULAR, outputs, mSessionMockListener, mHandler);
+
+ CaptureRequest.Builder builder =
+ mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
+ builder.addTarget(imageReader.getSurface());
+ CaptureRequest request = builder.build();
+
+ sessionConfig.setSessionParameters(request);
+ mCamera.createCaptureSession(sessionConfig);
+
+ mSession = mSessionMockListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
+ sessionListener.waitForOnReady(SESSION_CONFIGURE_TIMEOUT_MS);
+
+ SimpleCaptureCallback captureListener = new SimpleCaptureCallback();
+ ImageDropperListener imageListener = new ImageDropperListener();
+ imageReader.setOnImageAvailableListener(imageListener, mHandler);
+
+ // To check the state leak condition, we need a capture request that has
+ // at least one session pararameter value difference from the initial session
+ // parameters configured above. Scan all available template types for the
+ // required delta.
+ CaptureRequest.Builder requestBuilder = null;
+ ArrayList<CaptureRequest.Builder> builders = new ArrayList<CaptureRequest.Builder> ();
+ if (mStaticInfo.isCapabilitySupported(
+ CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
+ builders.add(mCamera.createCaptureRequest(CameraDevice.TEMPLATE_MANUAL));
+ }
+ if (mStaticInfo.isCapabilitySupported(
+ CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING)
+ || mStaticInfo.isCapabilitySupported(
+ CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING)) {
+ builders.add(mCamera.createCaptureRequest(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG));
+ }
+ builders.add(mCamera.createCaptureRequest(CameraDevice.TEMPLATE_VIDEO_SNAPSHOT));
+ builders.add(mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW));
+ builders.add(mCamera.createCaptureRequest(CameraDevice.TEMPLATE_RECORD));
+ for (CaptureRequest.Key<?> key : sessionKeys) {
+ Object sessionValue = builder.get(key);
+ for (CaptureRequest.Builder newBuilder : builders) {
+ Object currentValue = newBuilder.get(key);
+ if ((sessionValue == null) && (currentValue == null)) {
+ continue;
+ }
+
+ if (((sessionValue == null) && (currentValue != null)) ||
+ ((sessionValue != null) && (currentValue == null)) ||
+ (!sessionValue.equals(currentValue))) {
+ requestBuilder = newBuilder;
+ break;
+ }
+ }
+
+ if (requestBuilder != null) {
+ break;
+ }
+ }
+
+ if (requestBuilder != null) {
+ requestBuilder.addTarget(imageReader.getSurface());
+ request = requestBuilder.build();
+ mSession.setRepeatingRequest(request, captureListener, mHandler);
+ try {
+ sessionListener.waitForOnReady(SESSION_CONFIGURE_TIMEOUT_MS);
+ fail("Camera shouldn't switch to ready state when session parameters are " +
+ "modified");
+ } catch (TimeoutRuntimeException e) {
+ //expected
+ }
+ }
+ } finally {
+ imageReader.close();
+ mSession.close();
+ }
+ }
+
+ /**
* Verify creating a session with additional parameters.
*/
public void testCreateSessionWithParameters() throws Exception {
diff --git a/tests/framework/base/activitymanager/app/src/android/server/am/VirtualDisplayActivity.java b/tests/framework/base/activitymanager/app/src/android/server/am/VirtualDisplayActivity.java
index 3301b6a..8947a15 100644
--- a/tests/framework/base/activitymanager/app/src/android/server/am/VirtualDisplayActivity.java
+++ b/tests/framework/base/activitymanager/app/src/android/server/am/VirtualDisplayActivity.java
@@ -185,7 +185,7 @@
+ ", publicDisplay=" + publicDisplay);
try {
VirtualDisplay virtualDisplay = mDisplayManager.createVirtualDisplay(
- "VirtualDisplay" + mVirtualDisplays.size(), width,
+ "HostedVirtualDisplay" + mVirtualDisplays.size(), width,
height, densityDpi, surface, flags);
mVirtualDisplays.put(surface,
new VirtualDisplayEntry(virtualDisplay, entry.surfaceView, densityDpi,
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 71f71f8..18bdf7d 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerActivityVisibilityTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerActivityVisibilityTests.java
@@ -34,6 +34,8 @@
import android.support.test.filters.FlakyTest;
import android.platform.test.annotations.Presubmit;
+import org.junit.After;
+import org.junit.Before;
import org.junit.Test;
/**
@@ -58,6 +60,18 @@
private static final String TURN_SCREEN_ON_WITH_RELAYOUT_ACTIVITY =
"TurnScreenOnWithRelayoutActivity";
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ disableDozeStates();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ resetDozeStates();
+ }
+
@Presubmit
@Test
public void testTranslucentActivityOnTopOfPinnedStack() throws Exception {
@@ -387,7 +401,6 @@
@Test
@Presubmit
- @FlakyTest(bugId = 71868306)
public void testTurnScreenOnSingleTask() throws Exception {
try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
lockScreenSession.sleepDevice();
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmProfileTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmProfileTests.java
index ea2e2b3..74af4f7 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmProfileTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmProfileTests.java
@@ -16,6 +16,8 @@
package android.server.am;
+import static android.server.am.ComponentNameUtils.getActivityName;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -135,7 +137,7 @@
builder.append(" profile start");
} else {
builder.append(String.format(" start -n %s -W -S --start-profiler %s",
- activityName.flattenToShortString(), OUTPUT_FILE_PATH));
+ getActivityName(activityName), OUTPUT_FILE_PATH));
}
if (sampling) {
builder.append(" --sampling 1000");
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmStartOptionsTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmStartOptionsTests.java
index 6c37afb..03baab5 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmStartOptionsTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmStartOptionsTests.java
@@ -36,8 +36,7 @@
@Test
public void testDashD() throws Exception {
- final String activityComponentName =
- ActivityManagerTestBase.getActivityComponentName(TEST_ACTIVITY_NAME);
+ final String activityComponentName = getActivityComponentName(TEST_ACTIVITY_NAME);
final String[] waitForActivityRecords = new String[] {activityComponentName};
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 b7fa177..a69ad07 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAppConfigurationTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAppConfigurationTests.java
@@ -377,8 +377,7 @@
launchActivity(PORTRAIT_ACTIVITY_NAME);
assertFalse("target SDK > 26 non-fullscreen activity should not reach onResume",
- mAmWmState.getAmState().containsActivity(
- TRANSLUCENT_LANDSCAPE_ACTIVITY.flattenToShortString()));
+ mAmWmState.getAmState().containsActivity(TRANSLUCENT_LANDSCAPE_ACTIVITY));
}
@Test
@@ -517,7 +516,7 @@
// Launch to docked stack and record size.
String logSeparator = clearLogcat();
- launchActivity(activityName, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+ launchActivityInSplitScreenWithRecents(activityName);
final ReportedSizes initialDockedSizes = getActivityDisplaySize(activityName, logSeparator);
// Make sure docked stack is focused. This way when we dismiss it later fullscreen stack
// will come up.
@@ -607,7 +606,7 @@
private Rect getDisplayRect(String activityName)
throws Exception {
- final String windowName = getWindowName(activityName);
+ final String windowName = getActivityWindowName(activityName);
mAmWmState.computeState(new String[] {activityName});
mAmWmState.assertFocusedWindow("Test window must be the front window.", windowName);
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTestBase.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTestBase.java
index bc75e3c..7ef58c1 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTestBase.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTestBase.java
@@ -353,6 +353,33 @@
+ " -f 0x20000000"
+ " --es command destroy_display";
executeShellCommand(destroyVirtualDisplayCommand);
+ waitForDisplaysDestroyed();
+ }
+
+ private void waitForDisplaysDestroyed() throws Exception {
+ int tries = 0;
+ boolean done;
+ do {
+ done = !isHostedVirtualDisplayPresent();
+ if (!done && tries > 0) {
+ log("Waiting for hosted displays destruction");
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ // Oh well
+ }
+ }
+
+ tries++;
+ } while (tries < 10 && !done);
+
+ assertTrue(done);
+ }
+
+ private boolean isHostedVirtualDisplayPresent() throws Exception {
+ mAmWmState.computeState();
+ return mAmWmState.getWmState().getDisplays().stream().anyMatch(
+ d -> d.getName() != null && d.getName().contains("HostedVirtualDisplay"));
}
/**
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerManifestLayoutTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerManifestLayoutTests.java
index cb9be66..2929d90 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerManifestLayoutTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerManifestLayoutTests.java
@@ -147,7 +147,7 @@
private void getDisplayAndWindowState(String activityName, boolean checkFocus)
throws Exception {
- final String windowName = getWindowName(activityName);
+ final String windowName = getActivityWindowName(activityName);
mAmWmState.computeState(new WaitForValidActivityState.Builder(activityName).build());
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerMultiDisplayTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerMultiDisplayTests.java
index 7d8f9fc..f42f32c 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerMultiDisplayTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerMultiDisplayTests.java
@@ -24,6 +24,7 @@
.getDisplayMetrics;
import static android.server.am.ActivityManagerState.STATE_RESUMED;
import static android.server.am.ActivityManagerState.STATE_STOPPED;
+import static android.server.am.ComponentNameUtils.getActivityName;
import static android.server.am.StateLogger.logE;
import static org.junit.Assert.assertEquals;
@@ -332,7 +333,8 @@
mAmWmState.computeState(new WaitForValidActivityState(TEST_ACTIVITY_NAME));
assertFalse("Restricted activity must not be launched",
- mAmWmState.getAmState().containsActivity(TEST_ACTIVITY_NAME));
+ mAmWmState.getAmState().containsActivity(
+ getActivityComponentName(TEST_ACTIVITY_NAME)));
}
}
@@ -505,7 +507,7 @@
ActivityManagerState.ActivityStack frontStack =
mAmWmState.getAmState().getStackById(frontStackId);
assertEquals("Launched activity must be resumed in front stack",
- SECOND_ACTIVITY.flattenToShortString(), frontStack.mResumedActivity);
+ getActivityName(SECOND_ACTIVITY), frontStack.mResumedActivity);
// Launch other activity with different uid and check if it has launched successfully.
getLaunchActivityBuilder()
@@ -521,7 +523,7 @@
frontStackId = mAmWmState.getAmState().getFrontStackId(newDisplay.mId);
frontStack = mAmWmState.getAmState().getStackById(frontStackId);
assertEquals("Launched activity must be resumed in front stack",
- THIRD_ACTIVITY.flattenToShortString(), frontStack.mResumedActivity);
+ getActivityName(THIRD_ACTIVITY), frontStack.mResumedActivity);
}
}
@@ -845,7 +847,7 @@
// Launch other activity with different uid and check it is launched on dynamic stack on
// secondary display.
- final String startCmd = "am start -n " + SECOND_ACTIVITY.flattenToShortString()
+ final String startCmd = "am start -n " + getActivityName(SECOND_ACTIVITY)
+ " --display " + newDisplay.mId;
executeShellCommand(startCmd);
@@ -866,7 +868,7 @@
.createDisplay();
// Launch activity with different uid on secondary display.
- final String startCmd = "am start -n " + SECOND_ACTIVITY.flattenToShortString()
+ final String startCmd = "am start -n " + getActivityName(SECOND_ACTIVITY)
+ " --display " + newDisplay.mId;
executeShellCommand(startCmd);
@@ -944,7 +946,7 @@
focusedStack.mDisplayId);
// Launch other activity with different uid on secondary display.
- final String startCmd = "am start -n " + SECOND_ACTIVITY.flattenToShortString()
+ final String startCmd = "am start -n " + getActivityName(SECOND_ACTIVITY)
+ " --display " + newDisplay.mId;
executeShellCommand(startCmd);
@@ -1087,12 +1089,10 @@
logSeparator = clearLogcat();
}
- final String activityName1 = ActivityManagerTestBase.getActivityComponentName(
- TEST_ACTIVITY_NAME);
- final String activityName2 = ActivityManagerTestBase.getActivityComponentName(
- RESIZEABLE_ACTIVITY_NAME);
- final String windowName1 = ActivityManagerTestBase.getWindowName(TEST_ACTIVITY_NAME);
- final String windowName2 = ActivityManagerTestBase.getWindowName(RESIZEABLE_ACTIVITY_NAME);
+ final String activityName1 = getActivityComponentName(TEST_ACTIVITY_NAME);
+ final String activityName2 = getActivityComponentName(RESIZEABLE_ACTIVITY_NAME);
+ final String windowName1 = getActivityWindowName(TEST_ACTIVITY_NAME);
+ final String windowName2 = getActivityWindowName(RESIZEABLE_ACTIVITY_NAME);
mAmWmState.waitForWithAmState(
(state) -> !state.containsActivity(activityName1)
&& !state.containsActivity(activityName2),
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 5601f79..623d655 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerPinnedStackTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerPinnedStackTests.java
@@ -1022,7 +1022,8 @@
executeShellCommand("am stack resize-animated 4 20 20 500 500");
executeShellCommand("am broadcast -a " + TEST_ACTIVITY_ACTION_FINISH);
mAmWmState.waitFor((amState, wmState) -> !amState.containsActivity(
- TRANSLUCENT_TEST_ACTIVITY), "Waiting for test activity to finish...");
+ getActivityComponentName(TRANSLUCENT_TEST_ACTIVITY)),
+ "Waiting for test activity to finish...");
final ActivityLifecycleCounts lifecycleCounts = new ActivityLifecycleCounts(PIP_ACTIVITY,
logSeparator);
assertTrue(lifecycleCounts.mResumeCount == 0);
@@ -1431,7 +1432,7 @@
* @return the window state for the given {@param activity}'s window.
*/
private WindowManagerState.WindowState getWindowState(String activity) throws Exception {
- String windowName = getWindowName(activity);
+ String windowName = getActivityWindowName(activity);
mAmWmState.computeState(new WaitForValidActivityState.Builder(activity).build());
final List<WindowManagerState.WindowState> tempWindowList = new ArrayList<>();
mAmWmState.getWmState().getMatchingVisibleWindowState(windowName, tempWindowList);
@@ -1521,7 +1522,7 @@
mAmWmState.computeState();
if (supportsPip()) {
- final String windowName = getWindowName(topActivityName);
+ final String windowName = getActivityWindowName(topActivityName);
assertPinnedStackExists();
mAmWmState.assertFrontStack("Pinned stack must be the front stack.",
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerReplaceWindowTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerReplaceWindowTests.java
index faa72a9..233bad6 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerReplaceWindowTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerReplaceWindowTests.java
@@ -61,7 +61,7 @@
private void testReplaceWindow_Dock(boolean relaunch) throws Exception {
final String activityName =
relaunch ? SLOW_CREATE_ACTIVITY_NAME : NO_RELAUNCH_ACTIVITY_NAME;
- final String windowName = getWindowName(activityName);
+ final String windowName = getActivityWindowName(activityName);
final String amStartCmd = getAmStartCmd(activityName);
executeShellCommand(amStartCmd);
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java
index 83e77ff..6bad450 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java
@@ -148,6 +148,7 @@
@Test
@Presubmit
+ @FlakyTest(bugId = 72956284)
public void testNoUserLeaveHintOnMultiWindowModeChanged() throws Exception {
launchActivity(TEST_ACTIVITY_NAME, WINDOWING_MODE_FULLSCREEN);
diff --git a/tests/framework/base/activitymanager/src/android/server/am/DisplaySizeTest.java b/tests/framework/base/activitymanager/src/android/server/am/DisplaySizeTest.java
index 478c0b6..fd825cf 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/DisplaySizeTest.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/DisplaySizeTest.java
@@ -17,6 +17,8 @@
package android.server.am;
import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
+import static android.server.am.ComponentNameUtils.getActivityName;
+import static android.server.am.ComponentNameUtils.getWindowName;
import static org.junit.Assert.assertTrue;
@@ -91,7 +93,7 @@
// Launch another activity.
final String startActivityOnTop = String.format("%s -f 0x%x --es %s %s",
getAmStartCmd(SMALLEST_WIDTH_ACTIVITY), FLAG_ACTIVITY_SINGLE_TOP,
- EXTRA_LAUNCH_ANOTHER_ACTIVITY, TEST_ACTIVITY.flattenToShortString());
+ EXTRA_LAUNCH_ANOTHER_ACTIVITY, getActivityName(TEST_ACTIVITY));
executeShellCommand(startActivityOnTop);
assertActivityDisplayed(TEST_ACTIVITY);
@@ -137,7 +139,7 @@
}
private void assertActivityDisplayed(final ComponentName activityName) throws Exception {
- assertWindowDisplayed(activityName.flattenToString());
+ assertWindowDisplayed(getWindowName(activityName));
}
private void assertWindowDisplayed(final String windowName) throws Exception {
diff --git a/tests/framework/base/activitymanager/src/android/server/am/KeyguardTests.java b/tests/framework/base/activitymanager/src/android/server/am/KeyguardTests.java
index 612619c..03fb69a 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/KeyguardTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/KeyguardTests.java
@@ -88,7 +88,7 @@
mAmWmState.computeState();
mAmWmState.assertVisibility("ShowWhenLockedWithDialogActivity", true);
assertTrue(mAmWmState.getWmState().allWindowsVisible(
- getWindowName("ShowWhenLockedWithDialogActivity")));
+ getActivityWindowName("ShowWhenLockedWithDialogActivity")));
mAmWmState.assertKeyguardShowingAndOccluded();
}
}
diff --git a/tests/framework/base/activitymanager/src/android/server/am/StartActivityTests.java b/tests/framework/base/activitymanager/src/android/server/am/StartActivityTests.java
index 1f68aa3..4c3d021 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/StartActivityTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/StartActivityTests.java
@@ -67,7 +67,7 @@
mAmWmState.computeState(new WaitForValidActivityState(TEST_ACTIVITY_2));
// Verify Activity was not started.
- assertFalse(mAmWmState.getAmState().containsActivity(TEST_ACTIVITY.flattenToShortString()));
+ assertFalse(mAmWmState.getAmState().containsActivity(TEST_ACTIVITY));
mAmWmState.assertResumedActivity(
"Activity launched from activity context should be present", TEST_ACTIVITY_2);
}
diff --git a/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleTests.java b/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleTests.java
index 4ec99fa..b785b6b 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleTests.java
@@ -24,6 +24,7 @@
@Presubmit
public class ActivityLifecycleTests extends ActivityLifecycleClientTestBase {
+ @FlakyTest(bugId = 72956507)
@Test
public void testSingleLaunch() throws Exception {
final Activity activity = mFirstActivityTestRule.launchActivity(new Intent());
@@ -57,6 +58,7 @@
LifecycleVerifier.assertLaunchAndDestroySequence(FirstActivity.class, getLifecycleLog());
}
+ @FlakyTest(bugId = 72956507)
@Test
public void testRelaunch() throws Exception {
final Activity activity = mFirstActivityTestRule.launchActivity(new Intent());
diff --git a/tests/framework/base/activitymanager/util/Android.mk b/tests/framework/base/activitymanager/util/Android.mk
index 6fa0331..72c7058 100644
--- a/tests/framework/base/activitymanager/util/Android.mk
+++ b/tests/framework/base/activitymanager/util/Android.mk
@@ -25,8 +25,6 @@
compatibility-device-util \
android-support-test
-LOCAL_JAVA_LIBRARIES := core-oj core-libart
-
LOCAL_MODULE := cts-amwm-util
LOCAL_SDK_VERSION := test_current
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 ef2c1aa..a5b954f 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
@@ -23,7 +23,10 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
-import static android.server.am.ActivityManagerTestBase.componentName;
+import static android.server.am.ActivityManagerTestBase.getActivityComponentName;
+import static android.server.am.ActivityManagerTestBase.getActivityWindowName;
+import static android.server.am.ComponentNameUtils.getActivityName;
+import static android.server.am.ComponentNameUtils.getWindowName;
import static android.server.am.StateLogger.log;
import static android.server.am.StateLogger.logE;
@@ -45,6 +48,7 @@
import android.server.am.WindowManagerState.WindowTask;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.function.BiPredicate;
@@ -211,7 +215,8 @@
*/
private void waitForValidState(boolean compareTaskAndStackBounds,
WaitForValidActivityState... waitForActivitiesVisible) throws Exception {
- waitForValidState(compareTaskAndStackBounds, componentName, waitForActivitiesVisible);
+ waitForValidState(compareTaskAndStackBounds, ActivityManagerTestBase.componentName,
+ waitForActivitiesVisible);
}
/**
@@ -224,8 +229,7 @@
*/
void waitForValidState(boolean compareTaskAndStackBounds, String packageName,
WaitForValidActivityState... waitForActivitiesVisible) throws Exception {
- int retriesLeft = 5;
- do {
+ for (int retry = 1; retry <= 5; retry++) {
// TODO: Get state of AM and WM at the same time to avoid mismatches caused by
// requesting dump in some intermediate state.
mAmState.computeState();
@@ -234,7 +238,7 @@
|| shouldWaitForValidStacks(compareTaskAndStackBounds)
|| shouldWaitForActivities(packageName, waitForActivitiesVisible)
|| shouldWaitForWindows()) {
- log("***Waiting for valid stacks and activities states...");
+ log("***Waiting for valid stacks and activities states... retry=" + retry);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
@@ -242,9 +246,10 @@
// Well I guess we are not waiting...
}
} else {
- break;
+ return;
}
- } while (retriesLeft-- > 0);
+ }
+ logE("***Waiting for states failed: " + Arrays.toString(waitForActivitiesVisible));
}
/**
@@ -470,12 +475,12 @@
} else {
final String activityName = state.activityName;
activityComponentName = (activityName != null)
- ? ActivityManagerTestBase.getActivityComponentName(packageName, activityName)
+ ? getActivityComponentName(packageName, activityName)
: null;
// Check if window is visible - it should be represented as one of the window
// states.
windowName = (state.windowName != null) ? state.windowName
- : ActivityManagerTestBase.getWindowName(packageName, activityName);
+ : ActivityManagerTestBase.getActivityWindowName(packageName, activityName);
}
final int stackId = state.stackId;
final int windowingMode = state.windowingMode;
@@ -657,21 +662,20 @@
}
void assertFocusedActivity(final String msg, final ComponentName activityName) {
- final String activityComponentName = activityName.flattenToShortString();
+ final String activityComponentName = getActivityName(activityName);
assertEquals(msg, activityComponentName, mAmState.getFocusedActivity());
assertEquals(msg, activityComponentName, mWmState.getFocusedApp());
}
@Deprecated
void assertFocusedActivity(final String msg, final String activityName) {
- final String activityComponentName =
- ActivityManagerTestBase.getActivityComponentName(activityName);
+ final String activityComponentName = getActivityComponentName(activityName);
assertEquals(msg, activityComponentName, mAmState.getFocusedActivity());
assertEquals(msg, activityComponentName, mWmState.getFocusedApp());
}
void assertNotFocusedActivity(String msg, String activityName) throws Exception {
- final String componentName = ActivityManagerTestBase.getActivityComponentName(activityName);
+ final String componentName = getActivityComponentName(activityName);
if (mAmState.getFocusedActivity().equals(componentName)) {
assertNotEquals(msg, mAmState.getFocusedActivity(), componentName);
}
@@ -681,17 +685,17 @@
}
void assertResumedActivity(final String msg, final ComponentName activityName) {
- assertEquals(msg, activityName.flattenToShortString(), mAmState.getResumedActivity());
+ assertEquals(msg, getActivityName(activityName), mAmState.getResumedActivity());
}
@Deprecated
void assertResumedActivity(String msg, String activityName) throws Exception {
- final String componentName = ActivityManagerTestBase.getActivityComponentName(activityName);
+ final String componentName = getActivityComponentName(activityName);
assertEquals(msg, componentName, mAmState.getResumedActivity());
}
void assertNotResumedActivity(String msg, String activityName) throws Exception {
- final String componentName = ActivityManagerTestBase.getActivityComponentName(activityName);
+ final String componentName = getActivityComponentName(activityName);
if (mAmState.getResumedActivity().equals(componentName)) {
assertNotEquals(msg, mAmState.getResumedActivity(), componentName);
}
@@ -713,17 +717,13 @@
@Deprecated
public void assertVisibility(String activityName, boolean visible) {
- final String activityComponentName =
- ActivityManagerTestBase.getActivityComponentName(activityName);
- final String windowName =
- ActivityManagerTestBase.getWindowName(activityName);
+ final String activityComponentName = getActivityComponentName(activityName);
+ final String windowName = getActivityWindowName(activityName);
assertVisibility(activityComponentName, windowName, visible);
}
public void assertVisibility(final ComponentName activityName, final boolean visible) {
- final String activityComponentName = activityName.flattenToShortString();
- final String windowName = activityName.flattenToString();
- assertVisibility(activityComponentName, windowName, visible);
+ assertVisibility(getActivityName(activityName), getWindowName(activityName), visible);
}
private void assertVisibility(String activityComponentName, String windowName,
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 7be53c7..792b195 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
@@ -22,6 +22,8 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.server.am.ActivityManagerTestBase.getActivityComponentName;
+import static android.server.am.ComponentNameUtils.getActivityName;
import static android.server.am.ProtoExtractors.extract;
import static android.server.am.StateLogger.log;
import static android.server.am.StateLogger.logE;
@@ -299,7 +301,7 @@
/** Get the stack position on its display. */
int getStackIndexByActivityName(String activityName) {
- final String fullName = ActivityManagerTestBase.getActivityComponentName(activityName);
+ final String fullName = getActivityComponentName(activityName);
for (ActivityDisplay display : mDisplays) {
for (int i = display.mStacks.size() - 1; i >= 0; --i) {
@@ -328,11 +330,16 @@
return mStacks.size();
}
- boolean containsActivity(String activityName) {
+ boolean containsActivity(ComponentName activityName) {
+ return containsActivity(getActivityName(activityName));
+ }
+
+ @Deprecated
+ boolean containsActivity(String fullActivityName) {
for (ActivityStack stack : mStacks) {
for (ActivityTask task : stack.mTasks) {
for (Activity activity : task.mActivities) {
- if (activity.name.equals(activityName)) {
+ if (activity.name.equals(fullActivityName)) {
return true;
}
}
@@ -342,7 +349,7 @@
}
boolean containsActivityInWindowingMode(String activityName, int windowingMode) {
- final String fullName = ActivityManagerTestBase.getActivityComponentName(activityName);
+ final String fullName = getActivityComponentName(activityName);
for (ActivityStack stack : mStacks) {
for (ActivityTask task : stack.mTasks) {
for (Activity activity : task.mActivities) {
@@ -356,11 +363,11 @@
return false;
}
- boolean isActivityVisible(String activityName) {
+ boolean isActivityVisible(String fullActivityName) {
for (ActivityStack stack : mStacks) {
for (ActivityTask task : stack.mTasks) {
for (Activity activity : task.mActivities) {
- if (activity.name.equals(activityName)) {
+ if (activity.name.equals(fullActivityName)) {
return activity.visible;
}
}
@@ -384,7 +391,7 @@
}
boolean hasActivityState(String activityName, String activityState) {
- String fullName = ActivityManagerTestBase.getActivityComponentName(activityName);
+ String fullName = getActivityComponentName(activityName);
for (ActivityStack stack : mStacks) {
for (ActivityTask task : stack.mTasks) {
for (Activity activity : task.mActivities) {
@@ -397,11 +404,11 @@
return false;
}
- int getActivityProcId(String activityName) {
+ int getActivityProcId(String fullActivityName) {
for (ActivityStack stack : mStacks) {
for (ActivityTask task : stack.mTasks) {
for (Activity activity : task.mActivities) {
- if (activity.name.equals(activityName)) {
+ if (activity.name.equals(fullActivityName)) {
return activity.procId;
}
}
@@ -465,7 +472,7 @@
}
ActivityTask getTaskByActivityName(String activityName, int windowingMode) {
- String fullName = ActivityManagerTestBase.getActivityComponentName(activityName);
+ String fullName = getActivityComponentName(activityName);
for (ActivityStack stack : mStacks) {
if (windowingMode == WINDOWING_MODE_UNDEFINED
|| windowingMode == stack.getWindowingMode()) {
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 70d4888..d232dc3 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
@@ -31,6 +31,8 @@
import static android.content.pm.PackageManager.FEATURE_SCREEN_PORTRAIT;
import static android.content.pm.PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE;
import static android.content.pm.PackageManager.FEATURE_WATCH;
+import static android.server.am.ComponentNameUtils.getActivityName;
+import static android.server.am.ComponentNameUtils.getWindowName;
import static android.server.am.StateLogger.log;
import static android.server.am.StateLogger.logAlways;
import static android.server.am.StateLogger.logE;
@@ -135,6 +137,15 @@
protected ActivityManager mAm;
protected UiDevice mDevice;
+ /**
+ * The variables below are to store the doze states so they can be restored at the end.
+ */
+ private String mIsDozeAlwaysOn;
+ private String mIsDozeEnabled;
+ private String mIsDozePulseOnPickUp;
+ private String mIsDozePulseOnLongPress;
+ private String mIsDozePulseOnDoubleTap;
+
@Deprecated
protected static String getAmStartCmd(final String activityName) {
return "am start -n " + getActivityComponentName(activityName);
@@ -147,7 +158,7 @@
// TODO: Make this more generic, for instance accepting flags or extras of other types.
protected static String getAmStartCmd(final ComponentName activityName,
final String... keyValuePairs) {
- return getAmStartCmdInternal(activityName.flattenToShortString(), keyValuePairs);
+ return getAmStartCmdInternal(getActivityName(activityName), keyValuePairs);
}
@Deprecated
@@ -229,24 +240,16 @@
setComponentName(DEFAULT_COMPONENT_NAME);
}
- protected static String getBaseWindowName() {
- return getBaseWindowName(componentName);
- }
-
- static String getBaseWindowName(final String packageName) {
- return getBaseWindowName(packageName, true /*prependPackageName*/);
- }
-
- static String getBaseWindowName(final String packageName, boolean prependPackageName) {
+ private static String getBaseWindowName(final String packageName, boolean prependPackageName) {
return packageName + "/" + (prependPackageName ? packageName + "." : "");
}
// TODO: Remove this when all activity name are specified by {@link ComponentName}.
- static String getWindowName(final String activityName) {
- return getWindowName(componentName, activityName);
+ static String getActivityWindowName(final String activityName) {
+ return getActivityWindowName(componentName, activityName);
}
- static String getWindowName(final String packageName, final String activityName) {
+ static String getActivityWindowName(final String packageName, final String activityName) {
return getBaseWindowName(packageName, !isFullyQualifiedActivityName(activityName))
+ activityName;
}
@@ -607,12 +610,12 @@
@Deprecated
protected int getActivityTaskId(final ComponentName activityName) {
- return getWindowTaskId(activityName.flattenToString());
+ return getWindowTaskId(getWindowName(activityName));
}
@Deprecated
protected int getActivityTaskId(final String activityName) {
- return getWindowTaskId(getWindowName(activityName));
+ return getWindowTaskId(getActivityWindowName(activityName));
}
@Deprecated
@@ -726,6 +729,33 @@
return false;
}
+ protected void disableDozeStates() {
+ mIsDozeAlwaysOn = executeShellCommand("settings get secure doze_always_on").trim();
+ mIsDozeEnabled = executeShellCommand("settings get secure doze_enabled").trim();
+ mIsDozePulseOnPickUp = executeShellCommand(
+ "settings get secure doze_pulse_on_pick_up").trim();
+ mIsDozePulseOnLongPress = executeShellCommand(
+ "settings get secure doze_pulse_on_long_press").trim();
+ mIsDozePulseOnDoubleTap = executeShellCommand(
+ "settings get secure doze_pulse_on_double_tap").trim();
+
+ executeShellCommand("settings put secure doze_always_on 0");
+ executeShellCommand("settings put secure doze_enabled 0");
+ executeShellCommand("settings put secure doze_pulse_on_pick_up 0");
+ executeShellCommand("settings put secure doze_pulse_on_long_press 0");
+ executeShellCommand("settings put secure doze_pulse_on_double_tap 0");
+ }
+
+ protected void resetDozeStates() {
+ executeShellCommand("settings put secure doze_always_on " + mIsDozeAlwaysOn);
+ executeShellCommand("settings put secure doze_enabled " + mIsDozeEnabled);
+ executeShellCommand("settings put secure doze_pulse_on_pick_up " + mIsDozePulseOnPickUp);
+ executeShellCommand(
+ "settings put secure doze_pulse_on_long_press " + mIsDozePulseOnLongPress);
+ executeShellCommand(
+ "settings put secure doze_pulse_on_double_tap " + mIsDozePulseOnDoubleTap);
+ }
+
protected class LockScreenSession implements AutoCloseable {
private static final boolean DEBUG = false;
@@ -1571,8 +1601,10 @@
}
if (mComponent != null) {
+ // {@link ActivityLauncher} parses this extra string by
+ // {@link ComponentName#unflattenFromString(String)}.
commandBuilder.append(" --es target_component ")
- .append(mComponent.flattenToString());
+ .append(getActivityName(mComponent));
}
if (mSuppressExceptions) {
diff --git a/tests/framework/base/activitymanager/util/src/android/server/am/ComponentNameUtils.java b/tests/framework/base/activitymanager/util/src/android/server/am/ComponentNameUtils.java
new file mode 100644
index 0000000..daf654c
--- /dev/null
+++ b/tests/framework/base/activitymanager/util/src/android/server/am/ComponentNameUtils.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2018 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.server.am;
+
+import android.content.ComponentName;
+
+public class ComponentNameUtils {
+
+ /**
+ * Get component's activity name.
+ *
+ * @return the activity name of {@code componentName}, such as "contextPackage/.SimpleClassName"
+ * or "contextPackage/FullyClassName".
+ */
+ public static String getActivityName(ComponentName componentName) {
+ return componentName.flattenToShortString();
+ }
+
+ /**
+ * Get component's window mane.
+ *
+ * @return the window name of {@code componentName}, such that "contextPackage/FullyClassName".
+ */
+ public static String getWindowName(ComponentName componentName) {
+ return componentName.flattenToString();
+ }
+
+ /**
+ * Get component's simple class name suitable for logging tag.
+ *
+ * @return the simple class name of {@code componentName} that has no '.'.
+ */
+ public static String getLogTag(ComponentName componentName) {
+ final String className = componentName.getClassName();
+ final int pos = className.lastIndexOf('.');
+ return pos >= 0 ? className.substring(pos + 1) : className;
+ }
+
+}
diff --git a/tests/framework/base/activitymanager/util/src/android/server/am/WaitForValidActivityState.java b/tests/framework/base/activitymanager/util/src/android/server/am/WaitForValidActivityState.java
index 5d5366a0..057b90c 100644
--- a/tests/framework/base/activitymanager/util/src/android/server/am/WaitForValidActivityState.java
+++ b/tests/framework/base/activitymanager/util/src/android/server/am/WaitForValidActivityState.java
@@ -17,8 +17,19 @@
package android.server.am;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.server.am.ComponentNameUtils.getActivityName;
+import static android.server.am.ComponentNameUtils.getWindowName;
import android.content.ComponentName;
import android.support.annotation.Nullable;
@@ -41,8 +52,8 @@
}
public WaitForValidActivityState(final ComponentName activityName) {
- this.componentName = activityName.flattenToShortString();
- this.windowName = activityName.flattenToString();
+ this.componentName = getActivityName(activityName);
+ this.windowName = getWindowName(activityName);
this.activityName = getSimpleClassName(activityName);
this.stackId = INVALID_STACK_ID;
this.windowingMode = WINDOWING_MODE_UNDEFINED;
@@ -69,21 +80,64 @@
this.activityType = builder.mActivityType;
}
- /**
- * @return the class name of <code>componentName</code>, either fully qualified class name or in
- * a shortened form (WITHOUT a leading '.') if it is a suffix of the package.
- * @see ComponentName#getShortClassName()
- */
- private static String getSimpleClassName(final ComponentName componentName) {
- final String packageName = componentName.getPackageName();
- final String className = componentName.getClassName();
- if (className.startsWith(packageName)) {
- final int packageNameLen = packageName.length();
- if (className.length() > packageNameLen && className.charAt(packageNameLen) == '.') {
- return className.substring(packageNameLen + 1);
- }
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("wait:");
+ if (componentName != null) {
+ sb.append(" activity=").append(componentName);
+ } else if (activityName != null) {
+ sb.append(" activity=").append(activityName);
}
- return className;
+ if (activityType != ACTIVITY_TYPE_UNDEFINED) {
+ sb.append(" type=").append(activityTypeName(activityType));
+ }
+ if (windowName != null) {
+ sb.append(" window=").append(windowName);
+ }
+ if (windowingMode != WINDOWING_MODE_UNDEFINED) {
+ sb.append(" mode=").append(windowingModeName(windowingMode));
+ }
+ if (stackId != INVALID_STACK_ID) {
+ sb.append(" stack=").append(stackId);
+ }
+ return sb.toString();
+ }
+
+ private static String windowingModeName(int windowingMode) {
+ switch (windowingMode) {
+ case WINDOWING_MODE_UNDEFINED: return "UNDEFINED";
+ case WINDOWING_MODE_FULLSCREEN: return "FULLSCREEN";
+ case WINDOWING_MODE_PINNED: return "PINNED";
+ case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY: return "SPLIT_SCREEN_PRIMARY";
+ case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY: return "SPLIT_SCREEN_SECONDARY";
+ case WINDOWING_MODE_FREEFORM: return "FREEFORM";
+ default:
+ throw new IllegalArgumentException("Unknown WINDOWING_MODE_: " + windowingMode);
+ }
+ }
+
+ private static String activityTypeName(int activityType) {
+ switch (activityType) {
+ case ACTIVITY_TYPE_UNDEFINED: return "UNDEFINED";
+ case ACTIVITY_TYPE_STANDARD: return "STANDARD";
+ case ACTIVITY_TYPE_HOME: return "HOME";
+ case ACTIVITY_TYPE_RECENTS: return "RECENTS";
+ case ACTIVITY_TYPE_ASSISTANT: return "ASSISTANT";
+ default:
+ throw new IllegalArgumentException("Unknown ACTIVITY_TYPE_: " + activityType);
+ }
+ }
+
+ /**
+ * Get component's simple class name.
+ *
+ * @return the class name of {@code componentName}, either fully qualified class name or in
+ * a shortened form (WITHOUT a leading '.') if it is a suffix of the package.
+ * @see ComponentNameUtils#getLogTag(ComponentName)
+ */
+ public static String getSimpleClassName(final ComponentName componentName) {
+ final String shortClassName = componentName.getShortClassName();
+ return shortClassName.startsWith(".") ? shortClassName.substring(1) : shortClassName;
}
public static class Builder {
@@ -100,8 +154,8 @@
private Builder() {}
public Builder(final ComponentName activityName) {
- mComponentName = activityName.flattenToShortString();
- mWindowName = activityName.flattenToString();
+ mComponentName = getActivityName(activityName);
+ mWindowName = getWindowName(activityName);
mActivityName = getSimpleClassName(activityName);
}
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 1eb855e..6b613b1 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
@@ -390,6 +390,10 @@
return null;
}
+ List<Display> getDisplays() {
+ return mDisplays;
+ }
+
String getFrontWindow() {
if (mWindowStates == null || mWindowStates.isEmpty()) {
return null;
@@ -704,6 +708,7 @@
private Rect mAppRect = new Rect();
private int mDpi;
private Rect mStableBounds;
+ private String mName;
public Display(DisplayProto proto) {
super(proto.windowContainer);
@@ -722,6 +727,7 @@
if (infoProto != null) {
mDisplayRect.set(0, 0, infoProto.logicalWidth, infoProto.logicalHeight);
mAppRect.set(0, 0, infoProto.appWidth, infoProto.appHeight);
+ mName = infoProto.name;
}
final DisplayFramesProto displayFramesProto = proto.displayFrames;
if (displayFramesProto != null) {
@@ -754,9 +760,13 @@
return mAppRect;
}
+ String getName() {
+ return mName;
+ }
+
@Override
public String toString() {
- return "Display #" + mDisplayId + ": mDisplayRect=" + mDisplayRect
+ return "Display #" + mDisplayId + ": name=" + mName + " mDisplayRect=" + mDisplayRect
+ " mAppRect=" + mAppRect;
}
}
@@ -891,7 +901,7 @@
return mCrop;
}
- boolean isShown() {
+ public boolean isShown() {
return mShown;
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/AlertWindowsTests.java b/tests/framework/base/windowmanager/src/android/server/wm/AlertWindowsTests.java
index 418abc8..b79600d 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/AlertWindowsTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/AlertWindowsTests.java
@@ -131,6 +131,15 @@
assertAlertWindows(activityName, hasAlertWindowPermission, atLeastO);
}
+ private boolean allWindowsHidden(ArrayList<WindowManagerState.WindowState> windows) {
+ for (WindowManagerState.WindowState ws : windows) {
+ if (ws.isShown()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
private void assertAlertWindows(final ComponentName activityName,
final boolean hasAlertWindowPermission, final boolean atLeastO) throws Exception {
final String packageName = activityName.getPackageName();
@@ -140,9 +149,21 @@
wMState.getWindowsByPackageName(packageName, mAlertWindowTypes, alertWindows);
if (!hasAlertWindowPermission) {
- assertTrue("Should be empty alertWindows=" + alertWindows, alertWindows.isEmpty());
- assertTrue(AppOpsUtils.rejectedOperationLogged(packageName, OPSTR_SYSTEM_ALERT_WINDOW));
- return;
+ // When running in VR Mode, an App Op restriction is
+ // in place for SYSTEM_ALERT_WINDOW, which allows the window
+ // to be created, but will be hidden instead.
+ if (isUiModeLockedToVrHeadset()) {
+ assertTrue("Should not be empty alertWindows=" + alertWindows,
+ !alertWindows.isEmpty());
+ assertTrue("All alert windows should be hidden",
+ allWindowsHidden(alertWindows));
+ } else {
+ assertTrue("Should be empty alertWindows=" + alertWindows,
+ alertWindows.isEmpty());
+ assertTrue(AppOpsUtils.rejectedOperationLogged(packageName,
+ OPSTR_SYSTEM_ALERT_WINDOW));
+ return;
+ }
}
if (atLeastO) {
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/ChildMovementTests.java b/tests/framework/base/windowmanager/src/android/server/wm/ChildMovementTests.java
index 41f620d..8edffdc 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/ChildMovementTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/ChildMovementTests.java
@@ -16,6 +16,7 @@
package android.server.wm;
+import static android.server.am.ComponentNameUtils.getWindowName;
import static android.server.am.StateLogger.logE;
import static org.junit.Assert.assertTrue;
@@ -62,7 +63,7 @@
mAmWmState.computeState(waitForVisible);
WindowState popup = getSingleWindow(POPUP_WINDOW_NAME);
- WindowState parent = getSingleWindow(activityName().flattenToString());
+ WindowState parent = getSingleWindow(getWindowName(activityName()));
t.doTest(parent, popup);
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/DialogFrameTests.java b/tests/framework/base/windowmanager/src/android/server/wm/DialogFrameTests.java
index a5e5b4bb..79150e5 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/DialogFrameTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/DialogFrameTests.java
@@ -16,6 +16,7 @@
package android.server.wm;
+import static android.server.am.ComponentNameUtils.getWindowName;
import static android.server.am.StateLogger.logE;
import static org.junit.Assert.assertEquals;
@@ -64,7 +65,7 @@
mAmWmState.computeState(waitForVisible);
WindowState dialog = getSingleWindow(DIALOG_WINDOW_NAME);
- WindowState parent = getSingleWindow(activityName().flattenToString());
+ WindowState parent = getSingleWindow(getWindowName(activityName()));
t.doTest(parent, dialog);
}
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerTest.java
index 2587ed5..4c58b65 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerTest.java
@@ -30,9 +30,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.ResultReceiver;
import android.support.annotation.NonNull;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
@@ -114,23 +111,6 @@
// application should have no effect.
assertFalse(mImManager.isFullscreenMode());
- mActivityRule.runOnUiThread(() -> {
- IBinder token = view.getWindowToken();
-
- // Show and hide input method.
- assertTrue(mImManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT));
- assertTrue(mImManager.hideSoftInputFromWindow(token, 0));
-
- Handler handler = new Handler();
- ResultReceiver receiver = new ResultReceiver(handler);
- assertTrue(mImManager.showSoftInput(view, 0, receiver));
- receiver = new ResultReceiver(handler);
- assertTrue(mImManager.hideSoftInputFromWindow(token, 0, receiver));
-
- // status: hide to show to hide
- mImManager.toggleSoftInputFromWindow(token, 0, InputMethodManager.HIDE_NOT_ALWAYS);
- mImManager.toggleSoftInputFromWindow(token, 0, InputMethodManager.HIDE_NOT_ALWAYS);
- });
mInstrumentation.waitForIdleSync();
}
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java
new file mode 100644
index 0000000..c791f6ed
--- /dev/null
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2018 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.view.inputmethod.cts;
+
+import static android.view.inputmethod.cts.util.TestUtils.getOnMainSync;
+import static android.view.inputmethod.cts.util.TestUtils.runOnMainSync;
+
+import static com.android.cts.mockime.ImeEventStreamTestUtils.expectEvent;
+import static com.android.cts.mockime.ImeEventStreamTestUtils.notExpectEvent;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.os.SystemClock;
+import android.support.annotation.NonNull;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.text.TextUtils;
+import android.util.Pair;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethod;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.cts.util.EndToEndImeTestBase;
+import android.view.inputmethod.cts.util.TestActivity;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+
+import com.android.cts.mockime.ImeEvent;
+import com.android.cts.mockime.ImeEventStream;
+import com.android.cts.mockime.ImeSettings;
+import com.android.cts.mockime.MockImeSession;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Predicate;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class KeyboardVisibilityControlTest extends EndToEndImeTestBase {
+ private static final long TIMEOUT = TimeUnit.SECONDS.toMillis(5);
+
+ private static final String TEST_MARKER_PREFIX =
+ "android.view.inputmethod.cts.KeyboardVisibilityControlTest";
+
+ private static String getTestMarker() {
+ return TEST_MARKER_PREFIX + "/" + SystemClock.elapsedRealtimeNanos();
+ }
+
+ private static Predicate<ImeEvent> editorMatcher(
+ @NonNull String eventName, @NonNull String marker) {
+ return event -> {
+ if (!TextUtils.equals(eventName, event.getEventName())) {
+ return false;
+ }
+ final EditorInfo editorInfo = event.getArguments().getParcelable("editorInfo");
+ return TextUtils.equals(marker, editorInfo.privateImeOptions);
+ };
+ }
+
+ private static Predicate<ImeEvent> showSoftInputMatcher(int requiredFlags) {
+ return event -> {
+ if (!TextUtils.equals("showSoftInput", event.getEventName())) {
+ return false;
+ }
+ final int flags = event.getArguments().getInt("flags");
+ return (flags & requiredFlags) == requiredFlags;
+ };
+ }
+
+ private static Predicate<ImeEvent> hideSoftInputMatcher() {
+ return event -> TextUtils.equals("hideSoftInput", event.getEventName());
+ }
+
+ private static Predicate<ImeEvent> onFinishInputViewMatcher(boolean expectedFinishingInput) {
+ return event -> {
+ if (!TextUtils.equals("onFinishInputView", event.getEventName())) {
+ return false;
+ }
+ final boolean finishingInput = event.getArguments().getBoolean("finishingInput");
+ return finishingInput == expectedFinishingInput;
+ };
+ }
+
+ private Pair<EditText, EditText> launchTestActivity(@NonNull String focusedMarker,
+ @NonNull String nonFocusedMarker) {
+ final AtomicReference<EditText> focusedEditTextRef = new AtomicReference<>();
+ final AtomicReference<EditText> nonFocusedEditTextRef = new AtomicReference<>();
+ TestActivity.startSync(activity -> {
+ final LinearLayout layout = new LinearLayout(activity);
+ layout.setOrientation(LinearLayout.VERTICAL);
+
+ final EditText focusedEditText = new EditText(activity);
+ focusedEditText.setHint("focused editText");
+ focusedEditText.setPrivateImeOptions(focusedMarker);
+ focusedEditText.requestFocus();
+ focusedEditTextRef.set(focusedEditText);
+ layout.addView(focusedEditText);
+
+ final EditText nonFocusedEditText = new EditText(activity);
+ nonFocusedEditText.setPrivateImeOptions(nonFocusedMarker);
+ nonFocusedEditText.setHint("target editText");
+ nonFocusedEditTextRef.set(nonFocusedEditText);
+ layout.addView(nonFocusedEditText);
+ return layout;
+ });
+ return new Pair<>(focusedEditTextRef.get(), nonFocusedEditTextRef.get());
+ }
+
+ private EditText launchTestActivity(@NonNull String marker) {
+ return launchTestActivity(marker, getTestMarker()).first;
+ }
+
+ @Test
+ public void testBasicShowHideSoftInput() throws Exception {
+ final InputMethodManager imm = InstrumentationRegistry.getInstrumentation()
+ .getTargetContext().getSystemService(InputMethodManager.class);
+
+ try (MockImeSession imeSession = MockImeSession.create(
+ InstrumentationRegistry.getContext(),
+ InstrumentationRegistry.getInstrumentation().getUiAutomation(),
+ new ImeSettings.Builder())) {
+ final ImeEventStream stream = imeSession.openEventStream();
+
+ final String marker = getTestMarker();
+ final EditText editText = launchTestActivity(marker);
+
+ expectEvent(stream, editorMatcher("onStartInput", marker), TIMEOUT);
+ notExpectEvent(stream, editorMatcher("onStartInputView", marker), TIMEOUT);
+
+ assertTrue("isActive() must return true if the View has IME focus",
+ getOnMainSync(() -> imm.isActive(editText)));
+
+ // Test showSoftInput() flow
+ assertTrue("showSoftInput must success if the View has IME focus",
+ getOnMainSync(() -> imm.showSoftInput(editText, 0)));
+
+ // Nested events: "showSoftInput" internally triggers "onStartInputView" hence the
+ // event order is reversed. For now we just make sure that both get called, by passing
+ // stream.copy() because we are not sure if having a strong requirements regarding
+ // nested callback is a good idea or not.
+ // TODO(Bug 73077694): Change the event order.
+ expectEvent(stream.copy(), showSoftInputMatcher(InputMethod.SHOW_EXPLICIT), TIMEOUT);
+ expectEvent(stream.copy(), editorMatcher("onStartInputView", marker), TIMEOUT);
+ stream.skipAll();
+
+ // Test hideSoftInputFromWindow() flow
+ assertTrue("hideSoftInputFromWindow must success if the View has IME focus",
+ getOnMainSync(() -> imm.hideSoftInputFromWindow(editText.getWindowToken(), 0)));
+
+ // Nested events: "hideSoftInput" internally triggers "onFinishInputView" hence the
+ // event order is reversed. For now we just make sure that both get called, by passing
+ // stream.copy() because we are not sure if having a strong requirements regarding
+ // nested callback is a good idea or not.
+ // TODO(Bug 73077694): Change the event order.
+ expectEvent(stream.copy(), hideSoftInputMatcher(), TIMEOUT);
+ expectEvent(stream.copy(), onFinishInputViewMatcher(false), TIMEOUT);
+ stream.skipAll();
+ }
+ }
+
+ @Test
+ public void testShowHideSoftInputShouldBeIgnoredOnNonFocusedView() throws Exception {
+ final InputMethodManager imm = InstrumentationRegistry.getInstrumentation()
+ .getTargetContext().getSystemService(InputMethodManager.class);
+
+ try (MockImeSession imeSession = MockImeSession.create(
+ InstrumentationRegistry.getContext(),
+ InstrumentationRegistry.getInstrumentation().getUiAutomation(),
+ new ImeSettings.Builder())) {
+ final ImeEventStream stream = imeSession.openEventStream();
+
+ final String focusedMarker = getTestMarker();
+ final String nonFocusedMarker = getTestMarker();
+ final Pair<EditText, EditText> editTextPair =
+ launchTestActivity(focusedMarker, nonFocusedMarker);
+ final EditText nonFocusedEditText = editTextPair.second;
+
+ expectEvent(stream, editorMatcher("onStartInput", focusedMarker), TIMEOUT);
+
+ assertFalse("isActive() must return false if the View does not have IME focus",
+ getOnMainSync(() -> imm.isActive(nonFocusedEditText)));
+ assertFalse("showSoftInput must fail if the View does not have IME focus",
+ getOnMainSync(() -> imm.showSoftInput(nonFocusedEditText, 0)));
+ notExpectEvent(stream, showSoftInputMatcher(InputMethod.SHOW_EXPLICIT), TIMEOUT);
+
+ assertFalse("hideSoftInputFromWindow must fail if the View does not have IME focus",
+ getOnMainSync(() -> imm.hideSoftInputFromWindow(
+ nonFocusedEditText.getWindowToken(), 0)));
+ notExpectEvent(stream, hideSoftInputMatcher(), TIMEOUT);
+ }
+ }
+
+ @Test
+ public void testToggleSoftInput() throws Exception {
+ final InputMethodManager imm = InstrumentationRegistry.getInstrumentation()
+ .getTargetContext().getSystemService(InputMethodManager.class);
+
+ try (MockImeSession imeSession = MockImeSession.create(
+ InstrumentationRegistry.getContext(),
+ InstrumentationRegistry.getInstrumentation().getUiAutomation(),
+ new ImeSettings.Builder())) {
+ final ImeEventStream stream = imeSession.openEventStream();
+
+ final String marker = getTestMarker();
+ final EditText editText = launchTestActivity(marker);
+
+ expectEvent(stream, editorMatcher("onStartInput", marker), TIMEOUT);
+ notExpectEvent(stream, editorMatcher("onStartInputView", marker), TIMEOUT);
+
+ // Test toggleSoftInputFromWindow() flow
+ runOnMainSync(() -> imm.toggleSoftInputFromWindow(editText.getWindowToken(), 0, 0));
+
+ // Nested events: "showSoftInput" internally triggers "onStartInputView" hence the
+ // event order is reversed. For now we just make sure that both get called, by passing
+ // stream.copy() because we are not sure if having a strong requirements regarding
+ // nested callback is a good idea or not.
+ // TODO(Bug 73077694): Change the event order.
+ expectEvent(stream.copy(), showSoftInputMatcher(InputMethod.SHOW_EXPLICIT), TIMEOUT);
+ expectEvent(stream.copy(), editorMatcher("onStartInputView", marker), TIMEOUT);
+ stream.skipAll();
+
+ // Calling toggleSoftInputFromWindow() must hide the IME.
+ runOnMainSync(() -> imm.toggleSoftInputFromWindow(editText.getWindowToken(), 0, 0));
+
+ // Nested events: "hideSoftInput" internally triggers "onFinishInputView" hence the
+ // event order is reversed. For now we just make sure that both get called, by passing
+ // stream.copy() because we are not sure if having a strong requirements regarding
+ // nested callback is a good idea or not.
+ // TODO(Bug 73077694): Change the event order.
+ expectEvent(stream.copy(), hideSoftInputMatcher(), TIMEOUT);
+ expectEvent(stream.copy(), onFinishInputViewMatcher(false), TIMEOUT);
+ stream.skipAll();
+ }
+ }
+}
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/TestUtils.java b/tests/inputmethod/src/android/view/inputmethod/cts/util/TestUtils.java
index 04f52f6..63d9fe9 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/util/TestUtils.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/util/TestUtils.java
@@ -30,6 +30,17 @@
private static final long TIME_SLICE = 100; // msec
/**
+ * Executes a call on the application's main thread, blocking until it is complete.
+ *
+ * <p>A simple wrapper for {@link Instrumentation#runOnMainSync(Runnable)}.</p>
+ *
+ * @param task task to be called on the UI thread
+ */
+ public static void runOnMainSync(@NonNull Runnable task) {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(task);
+ }
+
+ /**
* Retrieves a value that needs to be obtained on the main thread.
*
* <p>A simple utility method that helps to return an object from the UI thread.</p>
diff --git a/tests/jdwp/runner/host-side/src/com/android/compatibility/testtype/DalvikTest.java b/tests/jdwp/runner/host-side/src/com/android/compatibility/testtype/DalvikTest.java
index 6abc6d7..e9d6d51 100644
--- a/tests/jdwp/runner/host-side/src/com/android/compatibility/testtype/DalvikTest.java
+++ b/tests/jdwp/runner/host-side/src/com/android/compatibility/testtype/DalvikTest.java
@@ -21,13 +21,13 @@
import com.android.ddmlib.Log;
import com.android.ddmlib.Log.LogLevel;
import com.android.ddmlib.MultiLineReceiver;
-import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.config.Option;
import com.android.tradefed.config.OptionCopier;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.result.TestDescription;
import com.android.tradefed.testtype.IAbi;
import com.android.tradefed.testtype.IAbiReceiver;
import com.android.tradefed.testtype.IBuildReceiver;
@@ -41,20 +41,16 @@
import com.android.tradefed.util.AbiUtils;
import com.android.tradefed.util.ArrayUtil;
import com.android.tradefed.util.FileUtil;
-import com.android.tradefed.util.TimeVal;
-import com.google.common.base.Splitter;
-import vogar.ExpectationStore;
-import vogar.ModeId;
+import com.google.common.base.Splitter;
import java.io.BufferedReader;
import java.io.File;
-import java.io.FilenameFilter;
import java.io.FileReader;
+import java.io.FilenameFilter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
@@ -62,6 +58,9 @@
import java.util.Set;
import java.util.concurrent.TimeUnit;
+import vogar.ExpectationStore;
+import vogar.ModeId;
+
/**
* A wrapper to run tests against Dalvik.
*/
@@ -339,7 +338,7 @@
dalvikArgs, abiName, runnerArgs,
includeFilters, excludeFilters, includeFile, excludeFile, collectTestsOnlyString);
IShellOutputReceiver receiver = new MultiLineReceiver() {
- private TestIdentifier test;
+ private TestDescription test;
@Override
public boolean isCancelled() {
@@ -360,12 +359,12 @@
Collections.<String, String>emptyMap());
Log.logAndDisplay(LogLevel.INFO, TAG, line);
} else if (tag.equals(START_TEST)) {
- test = getTestIdentifier(parts[1]);
+ test = getTestDescription(parts[1]);
listener.testStarted(test);
} else if (tag.equals(FAILURE)) {
listener.testFailed(test, parts[1]);
} else if (tag.equals(END_TEST)) {
- listener.testEnded(getTestIdentifier(parts[1]),
+ listener.testEnded(getTestDescription(parts[1]),
Collections.<String, String>emptyMap());
} else {
Log.logAndDisplay(LogLevel.INFO, TAG, line);
@@ -373,14 +372,14 @@
}
}
- private TestIdentifier getTestIdentifier(String name) {
+ private TestDescription getTestDescription(String name) {
String[] parts = name.split("#");
String className = parts[0];
String testName = "";
if (parts.length > 1) {
testName = parts[1];
}
- return new TestIdentifier(className, testName);
+ return new TestDescription(className, testName);
}
};
diff --git a/tests/perfetto/AndroidTest.xml b/tests/perfetto/AndroidTest.xml
index 6fada38..625af6a 100644
--- a/tests/perfetto/AndroidTest.xml
+++ b/tests/perfetto/AndroidTest.xml
@@ -15,6 +15,7 @@
-->
<!-- The Android.mk file that defines these target lives in /external/perfetto/cts -->
<configuration description="Config for CTS Perfetto test cases">
+ <option name="test-suite-tag" value="cts" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsPerfettoProducerApp.apk" />
@@ -30,4 +31,4 @@
<!-- test-timeout unit is ms, value = 10 seconds -->
<option name="native-test-timeout" value="10000" />
</test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/tests/tests/animation/src/android/animation/cts/InterpolatorTest.java b/tests/tests/animation/src/android/animation/cts/InterpolatorTest.java
new file mode 100644
index 0000000..bcb9bec
--- /dev/null
+++ b/tests/tests/animation/src/android/animation/cts/InterpolatorTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2018 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.animation.cts;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class InterpolatorTest {
+ private static final float EPSILON = 0.00001f;
+ private AnimationActivity mActivity;
+
+ @Rule
+ public ActivityTestRule<AnimationActivity> mActivityRule =
+ new ActivityTestRule<>(AnimationActivity.class);
+
+ @Before
+ public void setup() {
+ InstrumentationRegistry.getInstrumentation().setInTouchMode(false);
+ mActivity = mActivityRule.getActivity();
+ }
+
+ @Test
+ public void testFastOutExtraSlowIn() {
+ Interpolator interpolator = AnimationUtils.loadInterpolator(mActivity,
+ android.R.interpolator.fast_out_extra_slow_in);
+ float turningPointX = 0.166666f;
+ float turningPointY = 0.4f;
+
+ // Test that the interpolator starts at (0, 0) and ends at (1, 1)
+ assertEquals(0f, interpolator.getInterpolation(0), EPSILON);
+ assertEquals(1f, interpolator.getInterpolation(1), EPSILON);
+
+ // Test that when duration is at 1/6 of the total duration, the interpolation is 0.4, per
+ // interpolator spec.
+ assertEquals(turningPointY, interpolator.getInterpolation(turningPointX), EPSILON);
+
+ // Test that the first segment of the curve (i.e. fraction in (0, 0.166666)) is below the
+ // line formed with point (0, 0) and (0.166666, 0.4)
+ for (float fraction = EPSILON; fraction < turningPointX; fraction += 0.05f) {
+ assertTrue(interpolator.getInterpolation(fraction)
+ < fraction / turningPointX * turningPointY);
+ }
+
+ // Test that the second segment of the curve (i.e. fraction in (0.166666, 1)) is above
+ // the line formed with point (0.166666, 0.4) and (1, 1)
+ for (float fraction = turningPointX + EPSILON; fraction < 1f; fraction += 0.05f) {
+ float value = interpolator.getInterpolation(fraction);
+ assertTrue((value - turningPointY) / (fraction - turningPointX)
+ > (1f - turningPointY) / (1f - turningPointX));
+ }
+ // The curve needs to pass the turning point.
+ assertEquals(turningPointY, interpolator.getInterpolation(turningPointX), EPSILON);
+ }
+
+}
diff --git a/tests/tests/app.usage/res/drawable/ic_notification.png b/tests/tests/app.usage/res/drawable/ic_notification.png
new file mode 100644
index 0000000..6ae570b
--- /dev/null
+++ b/tests/tests/app.usage/res/drawable/ic_notification.png
Binary files differ
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
index 5dbc75e..110534f 100644
--- a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
+++ b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
@@ -20,13 +20,19 @@
import android.app.Activity;
import android.app.AppOpsManager;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
import android.app.usage.UsageEvents;
+import android.app.usage.UsageEvents.Event;
import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
import android.content.Context;
import android.content.Intent;
import android.os.Parcel;
import android.os.SystemClock;
+import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.By;
@@ -72,6 +78,8 @@
private static final long MONTH = 30 * DAY;
private static final long YEAR = 365 * DAY;
private static final long TIME_DIFF_THRESHOLD = 200;
+ private static final String CHANNEL_ID = "my_channel";
+
private UiDevice mUiDevice;
private UsageStatsManager mUsageStatsManager;
@@ -327,8 +335,8 @@
public void testNoAccessSilentlyFails() throws Exception {
final long startTime = System.currentTimeMillis() - MINUTE;
- launchSubActivity(Activities.ActivityOne.class);
- launchSubActivity(Activities.ActivityThree.class);
+ launchSubActivity(android.app.usage.cts.Activities.ActivityOne.class);
+ launchSubActivity(android.app.usage.cts.Activities.ActivityThree.class);
final long endTime = System.currentTimeMillis();
List<UsageStats> stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_BEST,
@@ -343,4 +351,57 @@
startTime, endTime);
assertTrue(stats.isEmpty());
}
+
+ @Test
+ public void testNotificationSeen() throws Exception {
+ final long startTime = System.currentTimeMillis();
+ Context context = InstrumentationRegistry.getContext();
+ NotificationManager mNotificationManager =
+ (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ int importance = NotificationManager.IMPORTANCE_DEFAULT;
+ NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, "Channel",
+ importance);
+ // Configure the notification channel.
+ mChannel.setDescription("Test channel");
+ mNotificationManager.createNotificationChannel(mChannel);
+ Notification.Builder mBuilder =
+ new Notification.Builder(context, CHANNEL_ID)
+ .setSmallIcon(R.drawable.ic_notification)
+ .setContentTitle("My notification")
+ .setContentText("Hello World!");
+ PendingIntent pi = PendingIntent.getActivity(context, 1,
+ new Intent(Settings.ACTION_SETTINGS), 0);
+ mBuilder.setContentIntent(pi);
+ mNotificationManager.notify(1, mBuilder.build());
+ Thread.sleep(500);
+ long endTime = System.currentTimeMillis();
+ UsageEvents events = mUsageStatsManager.queryEvents(startTime, endTime);
+ boolean found = false;
+ Event event = new Event();
+ while (events.hasNextEvent()) {
+ events.getNextEvent(event);
+ if (event.mEventType == Event.NOTIFICATION_SEEN) {
+ found = true;
+ }
+ }
+ assertFalse(found);
+ // Pull down shade
+ mUiDevice.openNotification();
+ outer:
+ for (int i = 0; i < 5; i++) {
+ Thread.sleep(500);
+ endTime = System.currentTimeMillis();
+ events = mUsageStatsManager.queryEvents(startTime, endTime);
+ found = false;
+ while (events.hasNextEvent()) {
+ events.getNextEvent(event);
+ if (event.mEventType == Event.NOTIFICATION_SEEN) {
+ found = true;
+ break outer;
+ }
+ }
+ }
+ assertTrue(found);
+ mUiDevice.pressBack();
+ }
}
diff --git a/tests/tests/assist/AndroidManifest.xml b/tests/tests/assist/AndroidManifest.xml
index a81ced2..0114ef5 100644
--- a/tests/tests/assist/AndroidManifest.xml
+++ b/tests/tests/assist/AndroidManifest.xml
@@ -24,8 +24,11 @@
<application>
<uses-library android:name="android.test.runner" />
+ <!-- resizeableActivity makes the TestStartActivity run on Primary display to accommodate
+ stack behavior assumptions in this test. See b/70032125 -->
<activity android:name="android.assist.cts.TestStartActivity"
- android:label="Assist Test Start Activity">
+ android:label="Assist Test Start Activity"
+ android:resizeableActivity="false">
<intent-filter>
<action android:name="android.intent.action.TEST_START_ACTIVITY_ASSIST_STRUCTURE" />
<action android:name="android.intent.action.TEST_START_ACTIVITY_DISABLE_CONTEXT" />
diff --git a/tests/tests/assist/testapp/AndroidManifest.xml b/tests/tests/assist/testapp/AndroidManifest.xml
index fa08f55..ee4c68f 100644
--- a/tests/tests/assist/testapp/AndroidManifest.xml
+++ b/tests/tests/assist/testapp/AndroidManifest.xml
@@ -55,8 +55,12 @@
<category android:name="android.intent.category.VOICE" />
</intent-filter>
</activity>
+ <!-- resizeableActivity makes the ScreenshotActivity run on Primary display to accommodate
+ assumptions about screenshot display vs TestStartActivity display in this test.
+ See b/70032125 -->
<activity android:name=".ScreenshotActivity"
- android:label="Screenshot Test Activity">
+ android:label="Screenshot Test Activity"
+ android:resizeableActivity="false">
<intent-filter>
<action android:name="android.intent.action.TEST_APP_SCREENSHOT" />
<category android:name="android.intent.category.DEFAULT" />
diff --git a/tests/tests/batterysaving/AndroidTest.xml b/tests/tests/batterysaving/AndroidTest.xml
index 066076b..d14c61f 100644
--- a/tests/tests/batterysaving/AndroidTest.xml
+++ b/tests/tests/batterysaving/AndroidTest.xml
@@ -24,12 +24,17 @@
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
- <option name="cleanup-apks" value="true" /> <!-- DO NOT SUBMIT WITH TRUE -->
+ <option name="cleanup-apks" value="true" /> <!-- DO NOT SUBMIT WITH FALSE -->
<option name="test-file-name" value="CtsBatterySavingTestCases.apk" />
<option name="test-file-name" value="CtsBatterySavingAppTargetApiCurrent.apk" />
<option name="test-file-name" value="CtsBatterySavingAppTargetApi25.apk" />
</target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="am set-standby-bucket android.os.cts.batterysaving.app_target_api_25 10" />
+ <option name="run-command" value="am set-standby-bucket android.os.cts.batterysaving.app_target_api_current 10" />
+ </target_preparer>
+
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.os.cts.batterysaving" />
<option name="runtime-hint" value="10m00s" />
diff --git a/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySaverLocationTest.java b/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySaverLocationTest.java
index 73c4e8d..9873bb2 100644
--- a/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySaverLocationTest.java
+++ b/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySaverLocationTest.java
@@ -51,7 +51,7 @@
/**
* Tests related to battery saver:
*
- * atest $ANDROID_BUILD_TOP/cts/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySaverLocationTest.java
+ atest $ANDROID_BUILD_TOP/cts/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySaverLocationTest.java
*/
@MediumTest
@RunWith(AndroidJUnit4.class)
@@ -78,6 +78,7 @@
// Make sure GPS is enabled.
putSecureSetting(LOCATION_PROVIDERS_ALLOWED, "+gps");
assertNotEquals(LOCATION_MODE_OFF, getLocationMode());
+ assertTrue(getLocationManager().isLocationEnabled());
// Unplug the charger and activate battery saver.
runDumpsysBatteryUnplug();
@@ -98,12 +99,14 @@
// Make sure location is still enabled.
assertNotEquals(LOCATION_MODE_OFF, getLocationMode());
+ assertTrue(getLocationManager().isLocationEnabled());
// Turn screen off.
runWithExpectingLocationCallback(() -> {
turnOnScreen(false);
waitUntil("Kill switch still off", () -> getLocationGlobalKillSwitch() == 1);
assertEquals(LOCATION_MODE_OFF, getLocationMode());
+ assertFalse(getLocationManager().isLocationEnabled());
});
// On again.
@@ -111,6 +114,7 @@
turnOnScreen(true);
waitUntil("Kill switch still off", () -> getLocationGlobalKillSwitch() == 0);
assertNotEquals(LOCATION_MODE_OFF, getLocationMode());
+ assertTrue(getLocationManager().isLocationEnabled());
});
// Off again.
@@ -118,6 +122,7 @@
turnOnScreen(false);
waitUntil("Kill switch still off", () -> getLocationGlobalKillSwitch() == 1);
assertEquals(LOCATION_MODE_OFF, getLocationMode());
+ assertFalse(getLocationManager().isLocationEnabled());
});
// Disable battery saver and make sure the kill swtich is off.
@@ -125,6 +130,7 @@
enableBatterySaver(false);
waitUntil("Kill switch still on", () -> getLocationGlobalKillSwitch() == 0);
assertNotEquals(LOCATION_MODE_OFF, getLocationMode());
+ assertTrue(getLocationManager().isLocationEnabled());
});
}
diff --git a/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySavingTestBase.java b/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySavingTestBase.java
index 81483c4..4ea3198 100644
--- a/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySavingTestBase.java
+++ b/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySavingTestBase.java
@@ -22,6 +22,7 @@
import android.content.Context;
import android.content.pm.PackageManager;
+import android.location.LocationManager;
import android.os.BatteryManager;
import android.os.PowerManager;
import android.support.test.InstrumentationRegistry;
@@ -92,4 +93,8 @@
public BatteryManager getBatteryManager() {
return getContext().getSystemService(BatteryManager.class);
}
+
+ public LocationManager getLocationManager() {
+ return getContext().getSystemService(LocationManager.class);
+ }
}
diff --git a/tests/tests/content/Android.mk b/tests/tests/content/Android.mk
index 3e8e783..0bbbb02 100644
--- a/tests/tests/content/Android.mk
+++ b/tests/tests/content/Android.mk
@@ -43,6 +43,18 @@
# Resource unit tests use a private locale and some densities
LOCAL_AAPT_INCLUDE_ALL_RESOURCES := true
+LOCAL_AAPT_FLAGS := \
+ -c cs \
+ -c fil,fil-rPH,fil-rSA \
+ -c fr,fr-rFR \
+ -c iw,iw-rIL \
+ -c kok,b+kok+419,b+kok+419+variant,b+kok+IN,b+kok+Knda,b+kok+Knda+419,b+kok+Knda+419+variant \
+ -c b+kok+variant \
+ -c mk,mk-rMK \
+ -c tl,tl-rPH \
+ -c tgl,tgl-rPH \
+ -c tlh \
+ -c xx,xx-rYY
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_MULTILIB := both
diff --git a/tests/tests/content/assets/subdir/subdir_text.txt b/tests/tests/content/assets/subdir/subdir_text.txt
new file mode 100644
index 0000000..80034a1
--- /dev/null
+++ b/tests/tests/content/assets/subdir/subdir_text.txt
@@ -0,0 +1 @@
+subdir
diff --git a/tests/tests/content/res/drawable/fake_image_will_not_decode.jpg b/tests/tests/content/res/drawable/fake_image_will_not_decode.jpg
new file mode 100644
index 0000000..32f7531
--- /dev/null
+++ b/tests/tests/content/res/drawable/fake_image_will_not_decode.jpg
@@ -0,0 +1 @@
+lol not a jpg
\ No newline at end of file
diff --git a/tests/tests/content/src/android/content/res/cts/AssetManagerTest.java b/tests/tests/content/src/android/content/res/cts/AssetManagerTest.java
index 1387be0..a1845d7 100644
--- a/tests/tests/content/src/android/content/res/cts/AssetManagerTest.java
+++ b/tests/tests/content/src/android/content/res/cts/AssetManagerTest.java
@@ -15,8 +15,16 @@
*/
package android.content.res.cts;
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.fail;
+
+import android.content.Context;
import android.content.cts.R;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -25,67 +33,84 @@
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import android.util.TypedValue;
import java.io.BufferedReader;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashSet;
-
-public class AssetManagerTest extends AndroidTestCase{
+@RunWith(AndroidJUnit4.class)
+public class AssetManagerTest {
private AssetManager mAssets;
+ private Context mContext;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
+ private Context getContext() {
+ return mContext;
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getContext();
mAssets = mContext.getAssets();
}
@SmallTest
- public void testAssetOperations() throws IOException, XmlPullParserException {
- final Resources res = getContext().getResources();
- final TypedValue value = new TypedValue();
- res.getValue(R.raw.text, value, true);
+ @Test
+ public void testAssetOperations() throws Exception {
final String fileName = "text.txt";
- InputStream inputStream = mAssets.open(fileName);
- assertNotNull(inputStream);
final String expect = "OneTwoThreeFourFiveSixSevenEightNineTen";
+
+ final TypedValue value = new TypedValue();
+ final Resources res = getContext().getResources();
+ res.getValue(R.raw.text, value, true);
+
+ InputStream inputStream = mAssets.open(fileName);
+ assertThat(inputStream).isNotNull();
assertContextEquals(expect, inputStream);
+
inputStream = mAssets.open(fileName, AssetManager.ACCESS_BUFFER);
- assertNotNull(inputStream);
+ assertThat(inputStream).isNotNull();
assertContextEquals(expect, inputStream);
AssetFileDescriptor assetFileDes = mAssets.openFd(fileName);
- assertNotNull(assetFileDes);
+ assertThat(assetFileDes).isNotNull();
assertContextEquals(expect, assetFileDes.createInputStream());
+
assetFileDes = mAssets.openNonAssetFd(value.string.toString());
- assertNotNull(assetFileDes);
+ assertThat(assetFileDes).isNotNull();
assertContextEquals(expect, assetFileDes.createInputStream());
+
assetFileDes = mAssets.openNonAssetFd(value.assetCookie, value.string.toString());
- assertNotNull(assetFileDes);
+ assertThat(assetFileDes).isNotNull();
assertContextEquals(expect, assetFileDes.createInputStream());
XmlResourceParser parser = mAssets.openXmlResourceParser("AndroidManifest.xml");
- assertNotNull(parser);
+ assertThat(parser).isNotNull();
XmlUtils.beginDocument(parser, "manifest");
parser = mAssets.openXmlResourceParser(0, "AndroidManifest.xml");
- assertNotNull(parser);
+ assertThat(parser).isNotNull();
beginDocument(parser, "manifest");
String[] files = mAssets.list("");
- boolean result = false;
- for (int i = 0; i < files.length; i++) {
- if (files[i].equals(fileName)) {
- result = true;
- break;
- }
- }
- assertTrue(result);
+ assertThat(files).isNotNull();
+
+ // We don't do an exact match because the framework can add asset files and this test
+ // would be too brittle.
+ assertThat(files).asList().containsAllOf(fileName, "subdir");
+
+ files = mAssets.list("subdir");
+ assertThat(files).isNotNull();
+ assertThat(files).asList().contains("subdir_text.txt");
+
+ // This directory doesn't exist.
+ assertThat(mAssets.list("__foo__bar__dir__")).asList().isEmpty();
try {
mAssets.open("notExistFile.txt", AssetManager.ACCESS_BUFFER);
@@ -115,12 +140,12 @@
// expected
}
- assertNotNull(mAssets.getLocales());
-
+ assertThat(mAssets.getLocales()).isNotNull();
}
@SmallTest
- public void testClose() throws IOException, XmlPullParserException {
+ @Test
+ public void testClose() throws Exception {
final AssetManager assets = new AssetManager();
assets.close();
@@ -136,6 +161,7 @@
}
@SmallTest
+ @Test
public void testGetNonSystemLocales() {
// This is the list of locales built into this test package. It is basically the locales
// specified in the Android.mk files (assuming they have corresponding resources), plus the
@@ -166,9 +192,6 @@
"xx-YY"
};
- final HashSet<String> KNOWN_LOCALES_SET =
- new HashSet<String>(Arrays.asList(KNOWN_LOCALES));
-
final String PSEUDO_OR_EMPTY_LOCALES[] = {
"",
"en-XA",
@@ -177,31 +200,26 @@
String locales[] = mAssets.getNonSystemLocales();
HashSet<String> localesSet = new HashSet<String>(Arrays.asList(locales));
- for (String l : PSEUDO_OR_EMPTY_LOCALES) {
- localesSet.remove(l);
- }
-
- assertEquals(KNOWN_LOCALES_SET, localesSet);
+ localesSet.removeAll(Arrays.asList(PSEUDO_OR_EMPTY_LOCALES));
+ assertThat(localesSet).containsExactlyElementsIn(Arrays.asList(KNOWN_LOCALES));
}
private void assertContextEquals(final String expect, final InputStream inputStream)
throws IOException {
- final BufferedReader bf = new BufferedReader(new InputStreamReader(inputStream));
- final String result = bf.readLine();
- inputStream.close();
- assertNotNull(result);
- assertEquals(expect, result);
+ try (final BufferedReader bf = new BufferedReader(new InputStreamReader(inputStream))) {
+ assertThat(bf.readLine()).isEqualTo(expect);
+ }
}
- private void beginDocument(final XmlPullParser parser,final String firstElementName)
+ private void beginDocument(final XmlPullParser parser, final String firstElementName)
throws XmlPullParserException, IOException {
int type;
while ((type = parser.next()) != XmlPullParser.START_TAG) {
}
+
if (type != XmlPullParser.START_TAG) {
fail("No start tag found");
}
- assertEquals(firstElementName, parser.getName());
+ assertThat(firstElementName).isEqualTo(parser.getName());
}
-
}
diff --git a/tests/tests/content/src/android/content/res/cts/ResourcesTest.java b/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
index 6c02845..75c9bf4 100644
--- a/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
+++ b/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
@@ -314,6 +314,13 @@
assertNotNull(draw);
assertEquals(212 * targetDensity / defaultDensity, draw.getIntrinsicWidth(), 1);
assertEquals(142 * targetDensity / defaultDensity, draw.getIntrinsicHeight(), 1);
+
+ try {
+ mResources.getDrawable(R.drawable.fake_image_will_not_decode);
+ fail("Expected decode failure as exception");
+ } catch (NotFoundException e) {
+ //expected
+ }
}
public void testGetDrawable_StackOverflowErrorDrawable() {
diff --git a/tests/tests/display/src/android/display/cts/DisplayTest.java b/tests/tests/display/src/android/display/cts/DisplayTest.java
index 6d7d38b..c7ea939 100644
--- a/tests/tests/display/src/android/display/cts/DisplayTest.java
+++ b/tests/tests/display/src/android/display/cts/DisplayTest.java
@@ -22,8 +22,10 @@
import android.app.Instrumentation;
import android.app.Presentation;
import android.app.UiAutomation;
+import android.app.UiModeManager;
import android.content.Context;
import android.content.Intent;
+import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.Point;
@@ -78,6 +80,7 @@
private DisplayManager mDisplayManager;
private WindowManager mWindowManager;
+ private UiModeManager mUiModeManager;
private Context mContext;
// To test display mode switches.
@@ -96,6 +99,7 @@
mContext = InstrumentationRegistry.getInstrumentation().getContext();
mDisplayManager = (DisplayManager)mContext.getSystemService(Context.DISPLAY_SERVICE);
mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
+ mUiModeManager = (UiModeManager)mContext.getSystemService(Context.UI_MODE_SERVICE);
}
@After
@@ -309,6 +313,12 @@
*/
@Test
public void testModeSwitch() throws Exception {
+ // Standalone VR devices globally ignore SYSTEM_ALERT_WINDOW via AppOps.
+ // Skip this test, which depends on a Presentation SYSTEM_ALERT_WINDOW to pass.
+ if (mUiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_VR_HEADSET) {
+ return;
+ }
+
enableAppOps();
final Display display = getSecondaryDisplay(mDisplayManager.getDisplays());
Display.Mode[] modes = display.getSupportedModes();
diff --git a/tests/tests/graphics/jni/android_graphics_cts_ANativeWindowTest.cpp b/tests/tests/graphics/jni/android_graphics_cts_ANativeWindowTest.cpp
index 788c66e..74f33cd 100644
--- a/tests/tests/graphics/jni/android_graphics_cts_ANativeWindowTest.cpp
+++ b/tests/tests/graphics/jni/android_graphics_cts_ANativeWindowTest.cpp
@@ -18,9 +18,10 @@
#define LOG_TAG "ANativeWindowTest"
#include <array>
-#include <jni.h>
+
#include <android/native_window.h>
#include <android/native_window_jni.h>
+#include <jni.h>
namespace {
@@ -33,8 +34,34 @@
ANativeWindow_release(window);
}
-const std::array<JNINativeMethod, 1> JNI_METHODS = {{
+jint setBuffersDataSpace(JNIEnv* env, jclass, jobject jSurface, jint dataSpace) {
+ ANativeWindow* window = nullptr;
+ if (jSurface) {
+ window = ANativeWindow_fromSurface(env, jSurface);
+ }
+ int error = ANativeWindow_setBuffersDataSpace(window, dataSpace);
+ if (error != 0) {
+ return error;
+ }
+ ANativeWindow_Buffer mappedBuffer;
+ ANativeWindow_lock(window, &mappedBuffer, nullptr);
+ ANativeWindow_unlockAndPost(window);
+ ANativeWindow_release(window);
+ return error;
+}
+
+jint getBuffersDataSpace(JNIEnv* env, jclass, jobject jSurface) {
+ ANativeWindow* window = nullptr;
+ if (jSurface) {
+ window = ANativeWindow_fromSurface(env, jSurface);
+ }
+ return ANativeWindow_getBuffersDataSpace(window);
+}
+
+const std::array<JNINativeMethod, 3> JNI_METHODS = {{
{ "nPushBufferWithTransform", "(Landroid/view/Surface;I)V", (void*)pushBufferWithTransform },
+ { "nSetBuffersDataSpace", "(Landroid/view/Surface;I)I", (void*)setBuffersDataSpace },
+ { "nGetBuffersDataSpace", "(Landroid/view/Surface;)I", (void*)getBuffersDataSpace },
}};
}
diff --git a/tests/tests/graphics/res/drawable/animatedimagedrawable.xml b/tests/tests/graphics/res/drawable/animatedimagedrawable.xml
new file mode 100644
index 0000000..b4133c4
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/animatedimagedrawable.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<android.graphics.drawable.AnimatedImageDrawable
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/animated" />
+
diff --git a/tests/tests/graphics/res/drawable/animatedimagedrawable_class.xml b/tests/tests/graphics/res/drawable/animatedimagedrawable_class.xml
new file mode 100644
index 0000000..0adc48e
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/animatedimagedrawable_class.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 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.
+ -->
+
+<drawable xmlns:android="http://schemas.android.com/apk/res/android"
+ class="android.graphics.drawable.AnimatedImageDrawable"
+ android:src="@drawable/animated" />
diff --git a/tests/tests/graphics/res/drawable/animatedimagedrawable_tag.xml b/tests/tests/graphics/res/drawable/animatedimagedrawable_tag.xml
new file mode 100644
index 0000000..4b66d64
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/animatedimagedrawable_tag.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 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.
+ -->
+
+<animated-image xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/animated" />
+
diff --git a/tests/tests/graphics/res/layout/animated_image_layout.xml b/tests/tests/graphics/res/layout/animated_image_layout.xml
new file mode 100644
index 0000000..73db92a
--- /dev/null
+++ b/tests/tests/graphics/res/layout/animated_image_layout.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ >
+ <ImageView
+ android:id="@+id/animated_image"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scaleType="fitCenter"
+ android:adjustViewBounds="true"
+ />
+</LinearLayout>
diff --git a/tests/tests/graphics/src/android/graphics/cts/ANativeWindowTest.java b/tests/tests/graphics/src/android/graphics/cts/ANativeWindowTest.java
index e67b5a4..f7cf694 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ANativeWindowTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ANativeWindowTest.java
@@ -192,6 +192,32 @@
}
}
+ @Test
+ public void testSetBuffersDataSpace() {
+ final int DATASPACE_SRGB = 142671872;
+ final int DATASPACE_UNKNOWN = 123;
+
+ int[] texId = new int[1];
+ GLES20.glGenTextures(1, texId, 0);
+
+ SurfaceTexture consumer = new SurfaceTexture(texId[0]);
+ consumer.setDefaultBufferSize(16, 16);
+ Surface surface = new Surface(consumer);
+
+ assertEquals(nGetBuffersDataSpace(surface), 0);
+ assertEquals(nSetBuffersDataSpace(surface, DATASPACE_SRGB), 0);
+ assertEquals(nGetBuffersDataSpace(surface), DATASPACE_SRGB);
+
+ assertEquals(nSetBuffersDataSpace(null, DATASPACE_SRGB), -22);
+ assertEquals(nGetBuffersDataSpace(null), -22);
+ assertEquals(nGetBuffersDataSpace(surface), DATASPACE_SRGB);
+
+ // set an unsupported data space should return a error code,
+ // the original data space shouldn't change.
+ assertEquals(nSetBuffersDataSpace(surface, DATASPACE_UNKNOWN), -22);
+ assertEquals(nGetBuffersDataSpace(surface), DATASPACE_SRGB);
+ }
+
// Multiply 4x4 matrices result = a*b. result can be the same as either a or b,
// allowing for result *= b. Another 4x4 matrix tmp must be provided as scratch space.
private void matrixMultiply(float[] result, float[] a, float[] b, float[] tmp) {
@@ -219,5 +245,6 @@
}
private static native void nPushBufferWithTransform(Surface surface, int transform);
-
+ private static native int nSetBuffersDataSpace(Surface surface, int dataSpace);
+ private static native int nGetBuffersDataSpace(Surface surface);
}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/Animatable2Callback.java b/tests/tests/graphics/src/android/graphics/drawable/cts/Animatable2Callback.java
new file mode 100644
index 0000000..5659ac2
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/Animatable2Callback.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2018 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.graphics.drawable.cts;
+
+import static junit.framework.TestCase.assertTrue;
+
+import static org.junit.Assert.assertEquals;
+
+import android.graphics.drawable.Animatable2;
+import android.graphics.drawable.Drawable;
+
+// Now this class can not only listen to the events, but also synchronize the key events,
+// logging the event timestamp, and centralize some assertions.
+public class Animatable2Callback extends Animatable2.AnimationCallback {
+ private static final long MAX_START_TIMEOUT_MS = 5000;
+
+ private boolean mStarted = false;
+ private boolean mEnded = false;
+
+ private long mStartNs = Long.MAX_VALUE;
+ private long mEndNs = Long.MIN_VALUE;
+
+ // Use this lock to make sure the onAnimationEnd() has been called.
+ // Each sub test should have its own lock.
+ private final Object mEndLock = new Object();
+
+ // Use this lock to make sure the test thread know when the AVD.start() has been called.
+ // Each sub test should have its own lock.
+ private final Object mStartLock = new Object();
+
+ public boolean waitForEnd(long timeoutMs) throws InterruptedException {
+ synchronized (mEndLock) {
+ if (!mEnded) {
+ // Return immediately if the AVD has already ended.
+ mEndLock.wait(timeoutMs);
+ }
+ return mEnded;
+ }
+ }
+
+ public boolean waitForStart() throws InterruptedException {
+ synchronized(mStartLock) {
+ if (!mStarted) {
+ // Return immediately if the AVD has already started.
+ mStartLock.wait(MAX_START_TIMEOUT_MS);
+ }
+ return mStarted;
+ }
+ }
+
+ @Override
+ public void onAnimationStart(Drawable drawable) {
+ mStartNs = System.nanoTime();
+ synchronized(mStartLock) {
+ mStarted = true;
+ mStartLock.notify();
+ }
+ }
+
+ @Override
+ public void onAnimationEnd(Drawable drawable) {
+ mEndNs = System.nanoTime();
+ synchronized (mEndLock) {
+ mEnded = true;
+ mEndLock.notify();
+ }
+ }
+
+ public boolean endIsCalled() {
+ synchronized (mEndLock) {
+ return mEnded;
+ }
+ }
+
+ public void assertStarted(boolean started) {
+ assertEquals(started, mStarted);
+ }
+
+ public void assertEnded(boolean ended) {
+ assertEquals(ended, mEnded);
+ }
+
+ public void assertAVDRuntime(long min, long max) {
+ assertTrue(mStartNs != Long.MAX_VALUE);
+ assertTrue(mEndNs != Long.MIN_VALUE);
+ long durationNs = mEndNs - mStartNs;
+ assertTrue("current duration " + durationNs + " should be within " +
+ min + "," + max, durationNs <= max && durationNs >= min);
+ }
+}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedImageDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedImageDrawableTest.java
new file mode 100644
index 0000000..cdc056f
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedImageDrawableTest.java
@@ -0,0 +1,356 @@
+/*
+ * Copyright (C) 2018 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.graphics.drawable.cts;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.ImageDecoder;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.AnimatedImageDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.cts.R;
+import android.net.Uri;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.rule.ActivityTestRule;
+import android.widget.ImageView;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+@RunWith(AndroidJUnit4.class)
+public class AnimatedImageDrawableTest {
+ private Resources mRes;
+ private ContentResolver mContentResolver;
+
+ private static final int RES_ID = R.drawable.animated;
+ private static final int WIDTH = 278;
+ private static final int HEIGHT = 183;
+ private static final int DURATION = 1000; // in milliseconds
+ private static final int LAYOUT = R.layout.animated_image_layout;
+ private static final int IMAGE_ID = R.id.animated_image;
+ @Rule
+ public ActivityTestRule<DrawableStubActivity> mActivityRule =
+ new ActivityTestRule<DrawableStubActivity>(DrawableStubActivity.class);
+ private Activity mActivity;
+
+ private Uri getAsResourceUri(int resId) {
+ return new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
+ .authority(mRes.getResourcePackageName(resId))
+ .appendPath(mRes.getResourceTypeName(resId))
+ .appendPath(mRes.getResourceEntryName(resId))
+ .build();
+ }
+
+ @Before
+ public void setup() {
+ mRes = InstrumentationRegistry.getTargetContext().getResources();
+ mContentResolver = InstrumentationRegistry.getTargetContext().getContentResolver();
+ mActivity = mActivityRule.getActivity();
+ }
+
+ private AnimatedImageDrawable createFromImageDecoder(int resId) {
+ Uri uri = null;
+ try {
+ uri = getAsResourceUri(resId);
+ ImageDecoder.Source source = ImageDecoder.createSource(mContentResolver, uri);
+ Drawable drawable = ImageDecoder.decodeDrawable(source);
+ assertTrue(drawable instanceof AnimatedImageDrawable);
+ return (AnimatedImageDrawable) drawable;
+ } catch (IOException e) {
+ fail("failed to create image from " + uri);
+ return null;
+ }
+ }
+
+ @Test
+ public void testDecodeAnimatedImageDrawable() {
+ Drawable drawable = createFromImageDecoder(RES_ID);
+ assertEquals(WIDTH, drawable.getIntrinsicWidth());
+ assertEquals(HEIGHT, drawable.getIntrinsicHeight());
+ }
+
+ private static class Callback extends Animatable2Callback {
+ private final Drawable mDrawable;
+
+ public Callback(Drawable d) {
+ mDrawable = d;
+ }
+
+ @Override
+ public void onAnimationStart(Drawable drawable) {
+ assertNotNull(drawable);
+ assertEquals(mDrawable, drawable);
+ super.onAnimationStart(drawable);
+ }
+
+ @Override
+ public void onAnimationEnd(Drawable drawable) {
+ assertNotNull(drawable);
+ assertEquals(mDrawable, drawable);
+ super.onAnimationEnd(drawable);
+ }
+ };
+
+ @Test(expected=IllegalStateException.class)
+ public void testRegisterWithoutLooper() {
+ AnimatedImageDrawable drawable = createFromImageDecoder(R.drawable.animated);
+
+ // registerAnimationCallback must be run on a thread with a Looper,
+ // which the test thread does not have.
+ Callback cb = new Callback(drawable);
+ drawable.registerAnimationCallback(cb);
+ }
+
+ @Test
+ public void testRegisterCallback() throws Throwable {
+ AnimatedImageDrawable drawable = createFromImageDecoder(R.drawable.animated);
+
+ mActivityRule.runOnUiThread(() -> {
+ // Register a callback.
+ Callback cb = new Callback(drawable);
+ drawable.registerAnimationCallback(cb);
+ assertTrue(drawable.unregisterAnimationCallback(cb));
+
+ // Now that it has been removed, it cannot be removed again.
+ assertFalse(drawable.unregisterAnimationCallback(cb));
+ });
+ }
+
+ @Test
+ public void testClearCallbacks() throws Throwable {
+ AnimatedImageDrawable drawable = createFromImageDecoder(R.drawable.animated);
+
+ Callback[] callbacks = new Callback[] {
+ new Callback(drawable),
+ new Callback(drawable),
+ new Callback(drawable),
+ new Callback(drawable),
+ new Callback(drawable),
+ new Callback(drawable),
+ new Callback(drawable),
+ new Callback(drawable),
+ };
+
+ mActivityRule.runOnUiThread(() -> {
+ for (Callback cb : callbacks) {
+ drawable.registerAnimationCallback(cb);
+ }
+ });
+
+ drawable.clearAnimationCallbacks();
+
+ for (Callback cb : callbacks) {
+ // It has already been removed.
+ assertFalse(drawable.unregisterAnimationCallback(cb));
+ }
+ }
+
+ /**
+ * Helper for attaching drawable to the view system.
+ *
+ * Necessary for the drawable to animate.
+ *
+ * Must be called from UI thread.
+ */
+ private void setContentView(AnimatedImageDrawable drawable) {
+ mActivity.setContentView(LAYOUT);
+ ImageView imageView = (ImageView) mActivity.findViewById(IMAGE_ID);
+ imageView.setImageDrawable(drawable);
+ }
+
+ @Test
+ public void testUnregisterCallback() throws Throwable {
+ AnimatedImageDrawable drawable = createFromImageDecoder(R.drawable.animated);
+
+ Callback cb = new Callback(drawable);
+ mActivityRule.runOnUiThread(() -> {
+ setContentView(drawable);
+
+ drawable.registerAnimationCallback(cb);
+ assertTrue(drawable.unregisterAnimationCallback(cb));
+ drawable.setLoopCount(0);
+ drawable.start();
+ });
+
+ cb.waitForStart();
+ cb.assertStarted(false);
+
+ cb.waitForEnd(DURATION * 2);
+ cb.assertEnded(false);
+ }
+
+ @Test
+ public void testLifeCycle() throws Throwable {
+ AnimatedImageDrawable drawable = createFromImageDecoder(RES_ID);
+
+ Callback cb = new Callback(drawable);
+ mActivityRule.runOnUiThread(() -> {
+ setContentView(drawable);
+
+ drawable.registerAnimationCallback(cb);
+ });
+
+ assertFalse(drawable.isRunning());
+ cb.assertStarted(false);
+ cb.assertEnded(false);
+
+
+ mActivityRule.runOnUiThread(() -> {
+ drawable.start();
+ assertTrue(drawable.isRunning());
+ });
+ cb.waitForStart();
+ cb.assertStarted(true);
+
+ // Only run the animation one time.
+ drawable.setLoopCount(0);
+
+ // Extra time, to wait for the message to post.
+ cb.waitForEnd(DURATION * 2);
+ cb.assertEnded(true);
+ assertFalse(drawable.isRunning());
+ }
+
+ @Test
+ public void testAddCallbackAfterStart() throws Throwable {
+ AnimatedImageDrawable drawable = createFromImageDecoder(RES_ID);
+ Callback cb = new Callback(drawable);
+ mActivityRule.runOnUiThread(() -> {
+ setContentView(drawable);
+
+ drawable.setLoopCount(0);
+ drawable.start();
+ drawable.registerAnimationCallback(cb);
+ });
+
+ cb.waitForEnd(DURATION * 2);
+ cb.assertEnded(true);
+ }
+
+ @Test
+ public void testStop() throws Throwable {
+ AnimatedImageDrawable drawable = createFromImageDecoder(RES_ID);
+ Callback cb = new Callback(drawable);
+ mActivityRule.runOnUiThread(() -> {
+ setContentView(drawable);
+
+ drawable.registerAnimationCallback(cb);
+
+ drawable.start();
+ assertTrue(drawable.isRunning());
+
+ drawable.stop();
+ assertFalse(drawable.isRunning());
+ });
+
+ // Duration may be overkill, but we need to wait for the message
+ // to post.
+ cb.waitForEnd(DURATION);
+ cb.assertStarted(true);
+ cb.assertEnded(true);
+ }
+
+ @Test
+ public void testLoopCounts() throws Throwable {
+ for (int loopCount : new int[] { 3, 5, 7, 16 }) {
+ AnimatedImageDrawable drawable = createFromImageDecoder(RES_ID);
+ Callback cb = new Callback(drawable);
+ mActivityRule.runOnUiThread(() -> {
+ setContentView(drawable);
+
+ drawable.registerAnimationCallback(cb);
+ drawable.setLoopCount(loopCount);
+ drawable.start();
+ });
+
+ // The animation runs loopCount + 1 total times.
+ cb.waitForEnd(DURATION * loopCount);
+ cb.assertEnded(false);
+
+ cb.waitForEnd(DURATION * 2);
+ cb.assertEnded(true);
+ }
+ }
+
+ @Test
+ public void testLoopCountInfinite() throws Throwable {
+ AnimatedImageDrawable drawable = createFromImageDecoder(RES_ID);
+ Callback cb = new Callback(drawable);
+ mActivityRule.runOnUiThread(() -> {
+ setContentView(drawable);
+
+ drawable.registerAnimationCallback(cb);
+ drawable.setLoopCount(AnimatedImageDrawable.LOOP_INFINITE);
+ drawable.start();
+ });
+
+ // There is no way to truly test infinite, but let it run for a long
+ // time and verify that it's still running.
+ cb.waitForEnd(DURATION * 30);
+ cb.assertEnded(false);
+ assertTrue(drawable.isRunning());
+ }
+
+ @Test
+ public void testGetOpacity() {
+ AnimatedImageDrawable drawable = createFromImageDecoder(RES_ID);
+ assertEquals(PixelFormat.TRANSLUCENT, drawable.getOpacity());
+ }
+
+ @Test
+ public void testCreateFromXml() throws XmlPullParserException, IOException {
+ XmlPullParser parser = mRes.getXml(R.drawable.animatedimagedrawable_tag);
+ Drawable drawable = Drawable.createFromXml(mRes, parser);
+ assertNotNull(drawable);
+ assertTrue(drawable instanceof AnimatedImageDrawable);
+ }
+
+ @Test
+ public void testCreateFromXmlClass() throws XmlPullParserException, IOException {
+ XmlPullParser parser = mRes.getXml(R.drawable.animatedimagedrawable);
+ Drawable drawable = Drawable.createFromXml(mRes, parser);
+ assertNotNull(drawable);
+ assertTrue(drawable instanceof AnimatedImageDrawable);
+ }
+
+ @Test
+ public void testCreateFromXmlClassAttribute() throws XmlPullParserException, IOException {
+ XmlPullParser parser = mRes.getXml(R.drawable.animatedimagedrawable_class);
+ Drawable drawable = Drawable.createFromXml(mRes, parser);
+ assertNotNull(drawable);
+ assertTrue(drawable instanceof AnimatedImageDrawable);
+ }
+}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableParameterizedTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableParameterizedTest.java
index 17edc3f..6ef16a3 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableParameterizedTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableParameterizedTest.java
@@ -118,8 +118,7 @@
@Test
public void testAnimationOnLayer() throws Throwable {
- final AnimatedVectorDrawableTest.MyCallback callback
- = new AnimatedVectorDrawableTest.MyCallback();
+ final Animatable2Callback callback = new Animatable2Callback();
// Can't simply use final here, b/c it needs to be initialized and referred later in UI
// thread.
final ImageView[] imageView = new ImageView[1];
@@ -231,8 +230,7 @@
@Test
public void testEmptyAnimatorSet() throws Throwable {
int resId = R.drawable.avd_empty_animator;
- final AnimatedVectorDrawableTest.MyCallback callback =
- new AnimatedVectorDrawableTest.MyCallback();
+ final Animatable2Callback callback = new Animatable2Callback();
final AnimatedVectorDrawable d1 =
(AnimatedVectorDrawable) mResources.getDrawable(resId);
d1.registerAnimationCallback(callback);
@@ -284,8 +282,7 @@
@Test
public void testInfiniteAVD() throws Throwable {
- final AnimatedVectorDrawableTest.MyCallback callback
- = new AnimatedVectorDrawableTest.MyCallback();
+ final Animatable2Callback callback = new Animatable2Callback();
// Can't simply use final here, b/c it needs to be initialized and referred later in UI
// thread.
final ImageView[] imageView = new ImageView[1];
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
index 990a8fb..f399cf6 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
@@ -57,7 +57,6 @@
private static final int IMAGE_WIDTH = 64;
private static final int IMAGE_HEIGHT = 64;
private static final long MAX_TIMEOUT_MS = 1000;
- private static final long MAX_START_TIMEOUT_MS = 5000;
private static final int MS_TO_NS = 1000000;
@Rule
@@ -202,7 +201,7 @@
@Test
public void testReset() throws Throwable {
- final MyCallback callback = new MyCallback();
+ final Animatable2Callback callback = new Animatable2Callback();
final AnimatedVectorDrawable d1 = (AnimatedVectorDrawable) mResources.getDrawable(mResId);
// The AVD has a duration as 100ms.
mActivityRule.runOnUiThread(() -> {
@@ -217,7 +216,7 @@
@Test
public void testStop() throws Throwable {
- final MyCallback callback = new MyCallback();
+ final Animatable2Callback callback = new Animatable2Callback();
final AnimatedVectorDrawable d1 = (AnimatedVectorDrawable) mResources.getDrawable(mResId);
// The AVD has a duration as 100ms.
mActivityRule.runOnUiThread(() -> {
@@ -231,7 +230,7 @@
@Test
public void testAddCallbackBeforeStart() throws Throwable {
- final MyCallback callback = new MyCallback();
+ final Animatable2Callback callback = new Animatable2Callback();
// The AVD has a duration as 100ms.
mActivityRule.runOnUiThread(() -> {
mActivity.setContentView(mLayoutId);
@@ -248,7 +247,7 @@
@Test
public void testAddCallbackAfterTrigger() throws Throwable {
- final MyCallback callback = new MyCallback();
+ final Animatable2Callback callback = new Animatable2Callback();
// The AVD has a duration as 100ms.
mActivityRule.runOnUiThread(() -> {
mActivity.setContentView(mLayoutId);
@@ -269,7 +268,7 @@
@Test
public void testAddCallbackAfterStart() throws Throwable {
- final MyCallback callback = new MyCallback();
+ final Animatable2Callback callback = new Animatable2Callback();
// The AVD has a duration as 100ms.
mActivityRule.runOnUiThread(() -> {
mActivity.setContentView(mLayoutId);
@@ -289,7 +288,7 @@
@Test
public void testRemoveCallback() throws Throwable {
- final MyCallback callback = new MyCallback();
+ final Animatable2Callback callback = new Animatable2Callback();
// The AVD has a duration as 100ms.
mActivityRule.runOnUiThread(() -> {
mActivity.setContentView(mLayoutId);
@@ -308,7 +307,7 @@
@Test
public void testClearCallback() throws Throwable {
- final MyCallback callback = new MyCallback();
+ final Animatable2Callback callback = new Animatable2Callback();
// The AVD has a duration as 100ms.
mActivityRule.runOnUiThread(() -> {
@@ -328,7 +327,7 @@
// The time out is expected when the listener is removed successfully.
// Such that we don't get the end event.
- static void waitForAVDStop(MyCallback callback, long timeout) {
+ static void waitForAVDStop(Animatable2Callback callback, long timeout) {
try {
callback.waitForEnd(timeout);
} catch (InterruptedException e) {
@@ -336,82 +335,4 @@
fail("We should not see the AVD run this long time!");
}
}
-
- // Now this class can not only listen to the events, but also synchronize the key events,
- // logging the event timestamp, and centralize some assertions.
- static class MyCallback extends Animatable2.AnimationCallback {
- private boolean mStarted = false;
- private boolean mEnded = false;
-
- private long mStartNs = Long.MAX_VALUE;
- private long mEndNs = Long.MIN_VALUE;
-
- // Use this lock to make sure the onAnimationEnd() has been called.
- // Each sub test should have its own lock.
- private final Object mEndLock = new Object();
-
- // Use this lock to make sure the test thread know when the AVD.start() has been called.
- // Each sub test should have its own lock.
- private final Object mStartLock = new Object();
-
- public boolean waitForEnd(long timeoutMs) throws InterruptedException {
- synchronized (mEndLock) {
- if (!mEnded) {
- // Return immediately if the AVD has already ended.
- mEndLock.wait(timeoutMs);
- }
- return mEnded;
- }
- }
-
- public boolean waitForStart() throws InterruptedException {
- synchronized(mStartLock) {
- if (!mStarted) {
- // Return immediately if the AVD has already started.
- mStartLock.wait(MAX_START_TIMEOUT_MS);
- }
- return mStarted;
- }
- }
-
- @Override
- public void onAnimationStart(Drawable drawable) {
- mStartNs = System.nanoTime();
- synchronized(mStartLock) {
- mStarted = true;
- mStartLock.notify();
- }
- }
-
- @Override
- public void onAnimationEnd(Drawable drawable) {
- mEndNs = System.nanoTime();
- synchronized (mEndLock) {
- mEnded = true;
- mEndLock.notify();
- }
- }
-
- public boolean endIsCalled() {
- synchronized (mEndLock) {
- return mEnded;
- }
- }
-
- public void assertStarted(boolean started) {
- assertEquals(started, mStarted);
- }
-
- public void assertEnded(boolean ended) {
- assertEquals(ended, mEnded);
- }
-
- public void assertAVDRuntime(long min, long max) {
- assertTrue(mStartNs != Long.MAX_VALUE);
- assertTrue(mEndNs != Long.MIN_VALUE);
- long durationNs = mEndNs - mStartNs;
- assertTrue("current duration " + durationNs + " should be within " +
- min + "," + max, durationNs <= max && durationNs >= min);
- }
- }
}
diff --git a/tests/tests/media/assets/video_decode_with_cropping-h264_520x360_30fps.mp4 b/tests/tests/media/assets/video_decode_with_cropping-h264_520x360_30fps.mp4
new file mode 100644
index 0000000..9a899b2
--- /dev/null
+++ b/tests/tests/media/assets/video_decode_with_cropping-h264_520x360_30fps.mp4
Binary files differ
diff --git a/tests/tests/media/assets/video_decode_with_cropping-h264_520x360_60fps.mp4 b/tests/tests/media/assets/video_decode_with_cropping-h264_520x360_60fps.mp4
deleted file mode 100644
index 362568c..0000000
--- a/tests/tests/media/assets/video_decode_with_cropping-h264_520x360_60fps.mp4
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/assets/video_decode_with_cropping-vp9_520x360_30fps.webm b/tests/tests/media/assets/video_decode_with_cropping-vp9_520x360_30fps.webm
new file mode 100644
index 0000000..df2723c
--- /dev/null
+++ b/tests/tests/media/assets/video_decode_with_cropping-vp9_520x360_30fps.webm
Binary files differ
diff --git a/tests/tests/media/assets/video_decode_with_cropping-vp9_520x360_60fps.webm b/tests/tests/media/assets/video_decode_with_cropping-vp9_520x360_60fps.webm
deleted file mode 100644
index 2ad27ed..0000000
--- a/tests/tests/media/assets/video_decode_with_cropping-vp9_520x360_60fps.webm
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/libmediandkjni/CtsMediaDrmJniOnLoad.cpp b/tests/tests/media/libmediandkjni/CtsMediaDrmJniOnLoad.cpp
index 24714a39..167763165 100644
--- a/tests/tests/media/libmediandkjni/CtsMediaDrmJniOnLoad.cpp
+++ b/tests/tests/media/libmediandkjni/CtsMediaDrmJniOnLoad.cpp
@@ -17,7 +17,7 @@
#include <jni.h>
#include <stdio.h>
-extern int register_android_media_cts_NativeClearKeySystemTest(JNIEnv*);
+extern int register_android_media_cts_NativeMediaDrmClearkeyTest(JNIEnv*);
jint JNI_OnLoad(JavaVM *vm, void */*reserved*/) {
JNIEnv *env = NULL;
@@ -26,7 +26,7 @@
return JNI_ERR;
}
- if (register_android_media_cts_NativeClearKeySystemTest(env)) {
+ if (register_android_media_cts_NativeMediaDrmClearkeyTest(env)) {
return JNI_ERR;
}
diff --git a/tests/tests/media/libmediandkjni/native-media-jni.cpp b/tests/tests/media/libmediandkjni/native-media-jni.cpp
index 68c7e9a..4779d51 100644
--- a/tests/tests/media/libmediandkjni/native-media-jni.cpp
+++ b/tests/tests/media/libmediandkjni/native-media-jni.cpp
@@ -103,6 +103,10 @@
return mSize;
}
+ void close() {
+ ::close(mFd);
+ }
+
private:
int mFd;
@@ -121,6 +125,10 @@
return src->getSize();
}
+static void FdSourceClose(void *userdata) {
+ FdDataSource *src = (FdDataSource*) userdata;
+ src->close();
+}
jobject testExtractor(AMediaExtractor *ex, JNIEnv *env) {
@@ -322,6 +330,7 @@
AMediaDataSource_setUserdata(ndkSrc, &fdSrc);
AMediaDataSource_setReadAt(ndkSrc, FdSourceReadAt);
AMediaDataSource_setGetSize(ndkSrc, FdSourceGetSize);
+ AMediaDataSource_setClose(ndkSrc, FdSourceClose);
err = AMediaExtractor_setDataSourceCustom(ex, ndkSrc);
} else {
err = AMediaExtractor_setDataSourceFd(ex, fd, offset, size);
diff --git a/tests/tests/media/libmediandkjni/native-mediadrm-jni.cpp b/tests/tests/media/libmediandkjni/native-mediadrm-jni.cpp
index d1e63ec..cc4387b 100644
--- a/tests/tests/media/libmediandkjni/native-mediadrm-jni.cpp
+++ b/tests/tests/media/libmediandkjni/native-mediadrm-jni.cpp
@@ -128,7 +128,7 @@
return juuid;
}
-extern "C" jboolean Java_android_media_cts_NativeClearKeySystemTest_isCryptoSchemeSupportedNative(
+extern "C" jboolean Java_android_media_cts_NativeMediaDrmClearkeyTest_isCryptoSchemeSupportedNative(
JNIEnv* env, jclass /*clazz*/, jbyteArray uuid) {
if (NULL == uuid) {
@@ -160,7 +160,7 @@
playbackParams, gFieldIds.videoUrl));
}
-extern "C" jboolean Java_android_media_cts_NativeClearKeySystemTest_testGetPropertyStringNative(
+extern "C" jboolean Java_android_media_cts_NativeMediaDrmClearkeyTest_testGetPropertyStringNative(
JNIEnv* env, jclass clazz, jbyteArray uuid,
jstring name, jobject outValue) {
@@ -205,7 +205,7 @@
return JNI_TRUE;
}
-extern "C" jboolean Java_android_media_cts_NativeClearKeySystemTest__testPsshNative(
+extern "C" jboolean Java_android_media_cts_NativeMediaDrmClearkeyTest__testPsshNative(
JNIEnv* env, jclass /*clazz*/, jbyteArray uuid, jstring videoUrl) {
if (NULL == uuid || NULL == videoUrl) {
@@ -543,7 +543,7 @@
jniThrowExceptionFmt(env, "java/lang/RuntimeException", errorMessage.c_str(), status);
}
-extern "C" jboolean Java_android_media_cts_NativeClearKeySystemTest_testClearKeyPlaybackNative(
+extern "C" jboolean Java_android_media_cts_NativeMediaDrmClearkeyTest_testClearKeyPlaybackNative(
JNIEnv* env, jclass /*clazz*/, jbyteArray uuid, jobject playbackParams) {
if (NULL == uuid || NULL == playbackParams) {
jniThrowException(env, "java/lang/NullPointerException",
@@ -648,7 +648,7 @@
return JNI_TRUE;
}
-extern "C" jboolean Java_android_media_cts_NativeClearKeySystemTest_testQueryKeyStatusNative(
+extern "C" jboolean Java_android_media_cts_NativeMediaDrmClearkeyTest_testQueryKeyStatusNative(
JNIEnv* env, jclass /*clazz*/, jbyteArray uuid) {
if (NULL == uuid) {
@@ -743,30 +743,30 @@
static JNINativeMethod gMethods[] = {
{ "isCryptoSchemeSupportedNative", "([B)Z",
- (void *)Java_android_media_cts_NativeClearKeySystemTest_isCryptoSchemeSupportedNative },
+ (void *)Java_android_media_cts_NativeMediaDrmClearkeyTest_isCryptoSchemeSupportedNative },
{ "testClearKeyPlaybackNative",
- "([BLandroid/media/cts/NativeClearKeySystemTest$PlaybackParams;)Z",
- (void *)Java_android_media_cts_NativeClearKeySystemTest_testClearKeyPlaybackNative },
+ "([BLandroid/media/cts/NativeMediaDrmClearkeyTest$PlaybackParams;)Z",
+ (void *)Java_android_media_cts_NativeMediaDrmClearkeyTest_testClearKeyPlaybackNative },
{ "testGetPropertyStringNative",
"([BLjava/lang/String;Ljava/lang/StringBuffer;)Z",
- (void *)Java_android_media_cts_NativeClearKeySystemTest_testGetPropertyStringNative },
+ (void *)Java_android_media_cts_NativeMediaDrmClearkeyTest_testGetPropertyStringNative },
{ "testPsshNative", "([BLjava/lang/String;)Z",
- (void *)Java_android_media_cts_NativeClearKeySystemTest__testPsshNative },
+ (void *)Java_android_media_cts_NativeMediaDrmClearkeyTest__testPsshNative },
{ "testQueryKeyStatusNative", "([B)Z",
- (void *)Java_android_media_cts_NativeClearKeySystemTest_testQueryKeyStatusNative },
+ (void *)Java_android_media_cts_NativeMediaDrmClearkeyTest_testQueryKeyStatusNative },
};
-int register_android_media_cts_NativeClearKeySystemTest(JNIEnv* env) {
+int register_android_media_cts_NativeMediaDrmClearkeyTest(JNIEnv* env) {
jint result = JNI_ERR;
jclass testClass =
- env->FindClass("android/media/cts/NativeClearKeySystemTest");
+ env->FindClass("android/media/cts/NativeMediaDrmClearkeyTest");
if (testClass) {
jclass playbackParamsClass = env->FindClass(
- "android/media/cts/NativeClearKeySystemTest$PlaybackParams");
+ "android/media/cts/NativeMediaDrmClearkeyTest$PlaybackParams");
if (playbackParamsClass) {
jclass surfaceClass =
env->FindClass("android/view/Surface");
@@ -787,7 +787,7 @@
}
} else {
- ALOGE("NativeClearKeySystemTest class not found");
+ ALOGE("NativeMediaDrmClearkeyTest class not found");
}
result = env->RegisterNatives(testClass, gMethods,
diff --git a/tests/tests/media/libndkaudio/Android.mk b/tests/tests/media/libndkaudio/Android.mk
index 29e2118..b547589 100644
--- a/tests/tests/media/libndkaudio/Android.mk
+++ b/tests/tests/media/libndkaudio/Android.mk
@@ -56,4 +56,6 @@
LOCAL_CERTIFICATE := platform
+LOCAL_SDK_VERSION := current
+
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tests/tests/media/src/android/media/cts/DecodeAccuracyTest.java b/tests/tests/media/src/android/media/cts/DecodeAccuracyTest.java
index 2840b16..7042213 100644
--- a/tests/tests/media/src/android/media/cts/DecodeAccuracyTest.java
+++ b/tests/tests/media/src/android/media/cts/DecodeAccuracyTest.java
@@ -129,8 +129,8 @@
"video_decode_accuracy_and_capability-vp9_2880x2160_30fps.webm",
"video_decode_accuracy_and_capability-vp9_1216x2160_30fps.webm",
// cropped
- "video_decode_with_cropping-h264_520x360_60fps.mp4",
- "video_decode_with_cropping-vp9_520x360_60fps.webm"
+ "video_decode_with_cropping-h264_520x360_30fps.mp4",
+ "video_decode_with_cropping-vp9_520x360_30fps.webm"
};
private View videoView;
diff --git a/tests/tests/media/src/android/media/cts/ClearKeySystemTest.java b/tests/tests/media/src/android/media/cts/MediaDrmClearkeyTest.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/ClearKeySystemTest.java
rename to tests/tests/media/src/android/media/cts/MediaDrmClearkeyTest.java
index 5afb71d..b07073e 100644
--- a/tests/tests/media/src/android/media/cts/ClearKeySystemTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaDrmClearkeyTest.java
@@ -58,8 +58,8 @@
/**
* Tests of MediaPlayer streaming capabilities.
*/
-public class ClearKeySystemTest extends MediaPlayerTestBase {
- private static final String TAG = ClearKeySystemTest.class.getSimpleName();
+public class MediaDrmClearkeyTest extends MediaPlayerTestBase {
+ private static final String TAG = MediaDrmClearkeyTest.class.getSimpleName();
// Add additional keys here if the content has more keys.
private static final byte[] CLEAR_KEY_CENC = {
diff --git a/tests/tests/media/src/android/media/cts/NativeClearKeySystemTest.java b/tests/tests/media/src/android/media/cts/NativeMediaDrmClearkeyTest.java
similarity index 96%
rename from tests/tests/media/src/android/media/cts/NativeClearKeySystemTest.java
rename to tests/tests/media/src/android/media/cts/NativeMediaDrmClearkeyTest.java
index d29cfed..1858da0 100644
--- a/tests/tests/media/src/android/media/cts/NativeClearKeySystemTest.java
+++ b/tests/tests/media/src/android/media/cts/NativeMediaDrmClearkeyTest.java
@@ -36,8 +36,8 @@
* Tests MediaDrm NDK APIs. ClearKey system uses a subset of NDK APIs,
* this test only tests the APIs that are supported by ClearKey system.
*/
-public class NativeClearKeySystemTest extends MediaPlayerTestBase {
- private static final String TAG = NativeClearKeySystemTest.class.getSimpleName();
+public class NativeMediaDrmClearkeyTest extends MediaPlayerTestBase {
+ private static final String TAG = NativeMediaDrmClearkeyTest.class.getSimpleName();
private static final int CONNECTION_RETRIES = 10;
private static final int VIDEO_WIDTH_CENC = 1280;
@@ -65,13 +65,13 @@
try {
System.loadLibrary("ctsmediadrm_jni");
} catch (UnsatisfiedLinkError e) {
- Log.e(TAG, "NativeClearKeySystemTest: Error loading JNI library");
+ Log.e(TAG, "NativeMediaDrmClearkeyTest: Error loading JNI library");
e.printStackTrace();
}
try {
System.loadLibrary("mediandk");
} catch (UnsatisfiedLinkError e) {
- Log.e(TAG, "NativeClearKeySystemTest: Error loading JNI library");
+ Log.e(TAG, "NativeMediaDrmClearkeyTest: Error loading JNI library");
e.printStackTrace();
}
}
diff --git a/tests/tests/security/res/raw/b70897454_avc.mp4 b/tests/tests/security/res/raw/b70897454_avc.mp4
new file mode 100644
index 0000000..cb86056
--- /dev/null
+++ b/tests/tests/security/res/raw/b70897454_avc.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_36725407.xmf b/tests/tests/security/res/raw/bug_36725407.xmf
new file mode 100644
index 0000000..30e90b1
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_36725407.xmf
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_37093318.xmf b/tests/tests/security/res/raw/bug_37093318.xmf
new file mode 100644
index 0000000..e42c863
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_37093318.xmf
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_38115076.mp4 b/tests/tests/security/res/raw/bug_38115076.mp4
new file mode 100644
index 0000000..2f3c34c
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_38115076.mp4
Binary files differ
diff --git a/tests/tests/security/src/android/security/cts/CertificateData.java b/tests/tests/security/src/android/security/cts/CertificateData.java
index 68ec092..76f86d5 100644
--- a/tests/tests/security/src/android/security/cts/CertificateData.java
+++ b/tests/tests/security/src/android/security/cts/CertificateData.java
@@ -165,4 +165,10 @@
"8D:A7:F9:65:EC:5E:FC:37:91:0F:1C:6E:59:FD:C1:CC:6A:6E:DE:16",
"B1:2E:13:63:45:86:A4:6F:1A:B2:60:68:37:58:2D:C4:AC:FD:94:97",
};
+
+ static final String[] WFA_CERTIFICATE_DATA = {
+ "BB:49:24:83:18:47:95:2B:DB:1A:12:B0:38:EC:51:54:AD:CB:DE:43",
+ "38:D6:63:9F:51:D7:24:21:AD:75:3C:C6:07:54:99:B7:1F:EC:F7:FC",
+ "51:50:1F:BF:CE:69:18:9D:60:9C:FA:F1:40:C5:76:75:5D:CC:1F:DF",
+ };
}
diff --git a/tests/tests/security/src/android/security/cts/CertificateTest.java b/tests/tests/security/src/android/security/cts/CertificateTest.java
index 2b8f351..2588f4d 100644
--- a/tests/tests/security/src/android/security/cts/CertificateTest.java
+++ b/tests/tests/security/src/android/security/cts/CertificateTest.java
@@ -16,14 +16,20 @@
package android.security.cts;
+import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
+import android.content.pm.PackageManager;
import android.platform.test.annotations.SecurityTest;
+import android.test.AndroidTestCase;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
+import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Collections;
@@ -31,10 +37,10 @@
import java.util.List;
import java.util.Set;
-import junit.framework.TestCase;
-
@SecurityTest
-public class CertificateTest extends TestCase {
+public class CertificateTest extends AndroidTestCase {
+ // The directory for CA root certificates trusted by WFA (WiFi Alliance)
+ static final String DIR_OF_CACERTS_FOR_WFA = "/etc/security/cacerts_wfa";
public void testNoRemovedCertificates() throws Exception {
Set<String> expectedCertificates = new HashSet<String>(
@@ -79,6 +85,89 @@
assertEquals("Blocked CA certificates", Collections.EMPTY_SET, deviceCertificates);
}
+ /**
+ * This test exists because adding new ca certificate or removing the ca certificates trusted by
+ * WFA (WiFi Alliance) is not allowed.
+ *
+ * For questions, comments, and code reviews please contact security@android.com.
+ */
+ public void testNoRemovedWfaCertificates() throws Exception {
+ if (!supportPasspoint()) {
+ return;
+ }
+ Set<String> expectedCertificates = new HashSet<>(
+ Arrays.asList(CertificateData.WFA_CERTIFICATE_DATA));
+ Set<String> deviceWfaCertificates = getDeviceWfaCertificates();
+ expectedCertificates.removeAll(deviceWfaCertificates);
+ assertEquals("Missing WFA CA certificates", Collections.EMPTY_SET, expectedCertificates);
+ }
+
+ public void testNoAddedWfaCertificates() throws Exception {
+ if (!supportPasspoint()) {
+ return;
+ }
+ Set<String> expectedCertificates = new HashSet<String>(
+ Arrays.asList(CertificateData.WFA_CERTIFICATE_DATA));
+ Set<String> deviceWfaCertificates = getDeviceWfaCertificates();
+ deviceWfaCertificates.removeAll(expectedCertificates);
+ assertEquals("Unknown WFA CA certificates", Collections.EMPTY_SET, deviceWfaCertificates);
+ }
+
+ private boolean supportPasspoint() {
+ return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_PASSPOINT);
+ }
+
+ private KeyStore createWfaKeyStore(String dirPath) throws CertificateException, IOException,
+ KeyStoreException, NoSuchAlgorithmException {
+ KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ keyStore.load(null, null);
+ String wfaCertsDir = System.getenv("ANDROID_ROOT") + dirPath;
+ int index = 0;
+ for (X509Certificate cert : loadCertsFromDisk(wfaCertsDir)) {
+ keyStore.setCertificateEntry(String.format("%d", index++), cert);
+ }
+ return keyStore;
+ }
+
+ private Set<X509Certificate> loadCertsFromDisk(String directory) throws CertificateException,
+ IOException {
+ Set<X509Certificate> certs = new HashSet<>();
+ File certDir = new File(directory);
+ File[] certFiles = certDir.listFiles();
+ if (certFiles == null || certFiles.length <= 0) {
+ return certs;
+ }
+ CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+ for (File certFile : certFiles) {
+ FileInputStream fis = new FileInputStream(certFile);
+ Certificate cert = certFactory.generateCertificate(fis);
+ if (cert instanceof X509Certificate) {
+ certs.add((X509Certificate) cert);
+ }
+ fis.close();
+ }
+ return certs;
+ }
+
+ private Set<String> getDeviceWfaCertificates() throws KeyStoreException,
+ NoSuchAlgorithmException, CertificateException, IOException {
+ KeyStore wfaKeyStore = createWfaKeyStore(DIR_OF_CACERTS_FOR_WFA);
+ List<String> aliases = Collections.list(wfaKeyStore.aliases());
+ assertFalse(aliases.isEmpty());
+
+ Set<String> certificates = new HashSet<>();
+ for (String alias : aliases) {
+ assertTrue(wfaKeyStore.isCertificateEntry(alias));
+ X509Certificate certificate = (X509Certificate) wfaKeyStore.getCertificate(alias);
+ assertEquals(certificate.getSubjectUniqueID(), certificate.getIssuerUniqueID());
+ assertNotNull(certificate.getSubjectDN());
+ assertNotNull(certificate.getIssuerDN());
+ String fingerprint = getFingerprint(certificate);
+ certificates.add(fingerprint);
+ }
+ return certificates;
+ }
+
private Set<String> getDeviceCertificates() throws KeyStoreException,
NoSuchAlgorithmException, CertificateException, IOException {
KeyStore keyStore = KeyStore.getInstance("AndroidCAStore");
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index a0f4e6c..5ac4307 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -78,6 +78,11 @@
***********************************************************/
@SecurityTest
+ public void testStagefright_bug_36725407() throws Exception {
+ doStagefrightTest(R.raw.bug_36725407);
+ }
+
+ @SecurityTest
public void testStagefright_bug_64710074() throws Exception {
doStagefrightTest(R.raw.bug_64710074);
}
@@ -271,6 +276,16 @@
***********************************************************/
@SecurityTest
+ public void testStagefright_bug_70897454() throws Exception {
+ doStagefrightTestRawBlob(R.raw.b70897454_avc, "video/avc", 320, 420);
+ }
+
+ @SecurityTest
+ public void testStagefright_bug_38115076() throws Exception {
+ doStagefrightTest(R.raw.bug_38115076);
+ }
+
+ @SecurityTest
public void testStagefright_bug_69478425() throws Exception {
doStagefrightTest(R.raw.bug_69478425);
}
@@ -448,6 +463,10 @@
doStagefrightTest(R.raw.bug_67737022);
}
+ @SecurityTest
+ public void testStagefright_bug_37093318() throws Exception {
+ doStagefrightTest(R.raw.bug_37093318, (4 * 60 * 1000));
+ }
private void doStagefrightTest(final int rid) throws Exception {
doStagefrightTestMediaPlayer(rid);
@@ -490,6 +509,19 @@
in2.close();
Log.i(TAG, "checked server");
}
+
+ private void doStagefrightTest(final int rid, int timeout) throws Exception {
+ runWithTimeout(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ doStagefrightTest(rid);
+ } catch (Exception e) {
+ //unhandled exception
+ }
+ }
+ }, timeout);
+ }
private void doStagefrightTestANR(final int rid) throws Exception {
doStagefrightTestMediaPlayerANR(rid, null);
diff --git a/tests/tests/telecom/src/android/telecom/cts/ConnectionServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/ConnectionServiceTest.java
index 0b70f1b..2fc401b 100644
--- a/tests/tests/telecom/src/android/telecom/cts/ConnectionServiceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/ConnectionServiceTest.java
@@ -21,6 +21,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.media.AudioManager;
+import android.net.Uri;
import android.telecom.Call;
import android.telecom.Connection;
import android.telecom.ConnectionService;
@@ -34,12 +35,16 @@
*/
public class ConnectionServiceTest extends BaseTelecomTestWithMockServices {
+ private static final Uri SELF_MANAGED_TEST_ADDRESS =
+ Uri.fromParts("sip", "call1@test.com", null);
+
@Override
protected void setUp() throws Exception {
super.setUp();
mContext = getInstrumentation().getContext();
if (mShouldTestTelecom) {
setupConnectionService(null, FLAG_REGISTER | FLAG_ENABLE);
+ mTelecomManager.registerPhoneAccount(TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_1);
}
}
@@ -124,6 +129,86 @@
assertEquals(AudioManager.MODE_IN_CALL, audioManager.getMode());
}
+ public void testConnectionServiceFocusGainedWithNoConnectionService() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
+ // WHEN place a managed call
+ placeAndVerifyCall();
+
+ // THEN managed connection service has gained the focus
+ assertTrue(connectionService.waitForEvent(
+ MockConnectionService.EVENT_CONNECTION_SERVICE_FOCUS_GAINED));
+ }
+
+ public void testConnectionServiceFocusGainedWithSameConnectionService() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
+ // GIVEN a managed call
+ placeAndVerifyCall();
+ verifyConnectionForOutgoingCall().setActive();
+ assertTrue(connectionService.waitForEvent(
+ MockConnectionService.EVENT_CONNECTION_SERVICE_FOCUS_GAINED));
+
+ // WHEN place another call has the same ConnectionService as the existing call
+ placeAndVerifyCall();
+ verifyConnectionForOutgoingCall();
+
+ // THEN the ConnectionService has not gained the focus again
+ assertFalse(connectionService.waitForEvent(
+ MockConnectionService.EVENT_CONNECTION_SERVICE_FOCUS_GAINED));
+ // and the ConnectionService didn't lose the focus
+ assertFalse(connectionService.waitForEvent(
+ MockConnectionService.EVENT_CONNECTION_SERVICE_FOCUS_LOST));
+ }
+
+ public void testConnectionServiceFocusGainedWithDifferentConnectionService() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
+ // GIVEN an existing managed call
+ placeAndVerifyCall();
+ verifyConnectionForOutgoingCall().setActive();
+ assertTrue(connectionService.waitForEvent(
+ MockConnectionService.EVENT_CONNECTION_SERVICE_FOCUS_GAINED));
+
+ // WHEN a self-managed call is coming
+ SelfManagedConnection selfManagedConnection =
+ addIncomingSelfManagedCall(TEST_SELF_MANAGED_HANDLE_1, SELF_MANAGED_TEST_ADDRESS);
+
+ // THEN the managed ConnectionService has lost the focus
+ assertTrue(connectionService.waitForEvent(
+ MockConnectionService.EVENT_CONNECTION_SERVICE_FOCUS_LOST));
+ // and the self-managed ConnectionService has gained the focus
+ assertTrue(CtsSelfManagedConnectionService.getConnectionService().waitForUpdate(
+ CtsSelfManagedConnectionService.FOCUS_GAINED_LOCK));
+
+ // Disconnected the self-managed call
+ selfManagedConnection.disconnectAndDestroy();
+ }
+
+ private SelfManagedConnection addIncomingSelfManagedCall(
+ PhoneAccountHandle pah, Uri address) {
+
+ TestUtils.addIncomingCall(getInstrumentation(), mTelecomManager, pah, address);
+
+ // Ensure Telecom bound to the self managed CS
+ if (!CtsSelfManagedConnectionService.waitForBinding()) {
+ fail("Could not bind to Self-Managed ConnectionService");
+ }
+
+ SelfManagedConnection connection = TestUtils.waitForAndGetConnection(address);
+
+ // Active the call
+ connection.setActive();
+
+ return connection;
+ }
+
public void testGetAllConnections() {
if (!mShouldTestTelecom) {
return;
diff --git a/tests/tests/telecom/src/android/telecom/cts/CtsConnectionService.java b/tests/tests/telecom/src/android/telecom/cts/CtsConnectionService.java
index 329031a..d93d431 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CtsConnectionService.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CtsConnectionService.java
@@ -176,6 +176,24 @@
}
@Override
+ public void onConnectionServiceFocusGained() {
+ synchronized (sLock) {
+ if (sConnectionService != null) {
+ sConnectionService.onConnectionServiceFocusGained();
+ }
+ }
+ }
+
+ @Override
+ public void onConnectionServiceFocusLost() {
+ synchronized (sLock) {
+ if (sConnectionService != null) {
+ sConnectionService.onConnectionServiceFocusLost();
+ }
+ }
+ }
+
+ @Override
public boolean onUnbind(Intent intent) {
Log.i(LOG_TAG, "Service has been unbound");
sServiceUnBoundLatch.countDown();
diff --git a/tests/tests/telecom/src/android/telecom/cts/CtsSelfManagedConnectionService.java b/tests/tests/telecom/src/android/telecom/cts/CtsSelfManagedConnectionService.java
index 6610705..b057648 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CtsSelfManagedConnectionService.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CtsSelfManagedConnectionService.java
@@ -43,7 +43,10 @@
public static int CREATE_INCOMING_CONNECTION_FAILED_LOCK = 1;
public static int CREATE_OUTGOING_CONNECTION_FAILED_LOCK = 2;
public static int HANDOVER_FAILED_LOCK = 3;
- private static int NUM_LOCKS = HANDOVER_FAILED_LOCK + 1;
+ public static int FOCUS_GAINED_LOCK = 4;
+ public static int FOCUS_LOST_LOCK = 5;
+
+ private static int NUM_LOCKS = FOCUS_LOST_LOCK + 1;
private static CtsSelfManagedConnectionService sConnectionService;
@@ -132,6 +135,16 @@
}
+ @Override
+ public void onConnectionServiceFocusGained() {
+ mLocks[FOCUS_GAINED_LOCK].countDown();
+ }
+
+ @Override
+ public void onConnectionServiceFocusLost() {
+ mLocks[FOCUS_LOST_LOCK].countDown();
+ }
+
public void tearDown() {
synchronized(mLock) {
if (mConnections != null && mConnections.size() > 0) {
@@ -150,6 +163,8 @@
SelfManagedConnection connection = new SelfManagedConnection(isIncoming,
mConnectionListener);
connection.setConnectionProperties(Connection.PROPERTY_SELF_MANAGED);
+ connection.setConnectionCapabilities(
+ Connection.CAPABILITY_HOLD | Connection.CAPABILITY_SUPPORT_HOLD);
connection.setAddress(request.getAddress(), TelecomManager.PRESENTATION_ALLOWED);
connection.setExtras(request.getExtras());
diff --git a/tests/tests/telecom/src/android/telecom/cts/MockConnectionService.java b/tests/tests/telecom/src/android/telecom/cts/MockConnectionService.java
index 6e022e6..6523bac 100644
--- a/tests/tests/telecom/src/android/telecom/cts/MockConnectionService.java
+++ b/tests/tests/telecom/src/android/telecom/cts/MockConnectionService.java
@@ -27,6 +27,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
/**
* Default implementation of a {@link CtsConnectionService}. This is used for the majority
@@ -36,6 +37,16 @@
public class MockConnectionService extends ConnectionService {
public static final int CONNECTION_PRESENTATION = TelecomManager.PRESENTATION_ALLOWED;
+ public static final int EVENT_CONNECTION_SERVICE_FOCUS_GAINED = 0;
+ public static final int EVENT_CONNECTION_SERVICE_FOCUS_LOST = 1;
+
+ // Next event id is 2
+ private static final int TOTAL_EVENT = EVENT_CONNECTION_SERVICE_FOCUS_LOST + 1;
+
+ private static final int DEFAULT_EVENT_TIMEOUT_MS = 2000;
+
+ private final Semaphore[] mEventLock = initializeSemaphore(TOTAL_EVENT);
+
/**
* Used to control whether the {@link MockVideoProvider} will be created when connections are
* created. Used by {@link VideoCallTest#testVideoCallDelayProvider()} to test scenario where
@@ -131,7 +142,39 @@
remoteConferences.add(conference);
}
+ @Override
+ public void onConnectionServiceFocusGained() {
+ mEventLock[EVENT_CONNECTION_SERVICE_FOCUS_GAINED].release();
+ }
+
+ @Override
+ public void onConnectionServiceFocusLost() {
+ mEventLock[EVENT_CONNECTION_SERVICE_FOCUS_LOST].release();
+ }
+
public void setCreateVideoProvider(boolean createVideoProvider) {
mCreateVideoProvider = createVideoProvider;
}
+
+ /** Returns true if the given {@code event} is happened before the default timeout. */
+ public boolean waitForEvent(int event) {
+ if (event < 0 || event >= mEventLock.length) {
+ return false;
+ }
+
+ try {
+ return mEventLock[event].tryAcquire(DEFAULT_EVENT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ // No interaction for the given event within the given timeout.
+ return false;
+ }
+ }
+
+ private static final Semaphore[] initializeSemaphore(int total) {
+ Semaphore[] locks = new Semaphore[total];
+ for (int i = 0; i < total; i++) {
+ locks[i] = new Semaphore(0);
+ }
+ return locks;
+ }
}
diff --git a/tests/tests/telecom/src/android/telecom/cts/SelfManagedConnectionServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/SelfManagedConnectionServiceTest.java
index 41bf986..2b67f95 100644
--- a/tests/tests/telecom/src/android/telecom/cts/SelfManagedConnectionServiceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/SelfManagedConnectionServiceTest.java
@@ -19,6 +19,7 @@
import android.net.Uri;
import android.os.Bundle;
import android.telecom.CallAudioState;
+import android.telecom.Connection;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
@@ -52,7 +53,6 @@
mTelecomManager.registerPhoneAccount(TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_1);
mTelecomManager.registerPhoneAccount(TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_2);
}
-
}
@Override
@@ -107,7 +107,7 @@
// enabled, and the one we get back after registration is.
assertPhoneAccountEquals(TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_1, registeredAccount);
- // An important asumption is that self-managed PhoneAccounts are automatically
+ // An important assumption is that self-managed PhoneAccounts are automatically
// enabled by default.
assertTrue("Self-managed PhoneAccounts must be enabled by default.",
registeredAccount.isEnabled());
@@ -219,6 +219,32 @@
}
/**
+ * Tests ensures that Telecom disallow to place outgoing self-managed call when the ongoing
+ * managed call can not be held.
+ */
+ public void testDisallowOutgoingCallWhileOngoingManagedCallCanNotBeHeld() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
+ // GIVEN an ongoing managed call that can not be held
+ addAndVerifyNewIncomingCall(createTestNumber(), null);
+ Connection connection = verifyConnectionForIncomingCall();
+ int capabilities = connection.getConnectionCapabilities();
+ capabilities &= ~Connection.CAPABILITY_HOLD;
+ connection.setConnectionCapabilities(capabilities);
+ connection.setActive();
+
+ // WHEN place a self-managed outgoing call
+ TestUtils.placeOutgoingCall(getInstrumentation(), mTelecomManager,
+ TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_1);
+
+ // THEN the new outgoing call is failed.
+ assertTrue(CtsSelfManagedConnectionService.getConnectionService().waitForUpdate(
+ CtsSelfManagedConnectionService.CREATE_OUTGOING_CONNECTION_FAILED_LOCK));
+ }
+
+ /**
* Tests ability to add a new self-managed outgoing connection.
*/
public void testAddSelfManagedOutgoingConnection() throws Exception {
@@ -296,11 +322,11 @@
}
/**
- * Tests that Telecom will disallow an outgoing call when there is already an ongoing call in
- * another third-party app.
+ * Tests that Telecom will allow the incoming call while the number of self-managed call is not
+ * exceed the limit.
* @throws Exception
*/
- public void testDisallowOutgoingCall() throws Exception {
+ public void testIncomingWhileOngoingWithinLimit() throws Exception {
if (!mShouldTestTelecom) {
return;
}
@@ -311,33 +337,7 @@
SelfManagedConnection connection = TestUtils.waitForAndGetConnection(TEST_ADDRESS_1);
setActiveAndVerify(connection);
- // Attempt to create a new outgoing call for the other PhoneAccount; it should fail.
- TestUtils.placeOutgoingCall(getInstrumentation(), mTelecomManager,
- TestUtils.TEST_SELF_MANAGED_HANDLE_2, TEST_ADDRESS_2);
- assertTrue("Expected onCreateOutgoingConnectionFailed callback",
- CtsSelfManagedConnectionService.getConnectionService().waitForUpdate(
- CtsSelfManagedConnectionService.CREATE_OUTGOING_CONNECTION_FAILED_LOCK));
-
- setDisconnectedAndVerify(connection);
- }
-
- /**
- * Tests that Telecom will disallow an outgoing call when there is already an ongoing call in
- * another third-party app.
- * @throws Exception
- */
- public void testIncomingWhileOngoing() throws Exception {
- if (!mShouldTestTelecom) {
- return;
- }
-
- // Create an ongoing call in the first self-managed PhoneAccount.
- TestUtils.placeOutgoingCall(getInstrumentation(), mTelecomManager,
- TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_1);
- SelfManagedConnection connection = TestUtils.waitForAndGetConnection(TEST_ADDRESS_1);
- setActiveAndVerify(connection);
-
- // Attempt to create a new outgoing call for the other PhoneAccount; it should succeed.
+ // Attempt to create a new incoming call for the other PhoneAccount; it should succeed.
TestUtils.addIncomingCall(getInstrumentation(), mTelecomManager,
TestUtils.TEST_SELF_MANAGED_HANDLE_2, TEST_ADDRESS_2);
SelfManagedConnection connection2 = TestUtils.waitForAndGetConnection(TEST_ADDRESS_2);
@@ -347,6 +347,76 @@
}
/**
+ * Tests the self-managed ConnectionService has gained the focus when it become active.
+ */
+ public void testSelfManagedConnectionServiceGainedFocus() throws Exception {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
+ // Attempt to create a new Incoming self-managed call
+ TestUtils.addIncomingCall(getInstrumentation(), mTelecomManager,
+ TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_1);
+ SelfManagedConnection connection = TestUtils.waitForAndGetConnection(TEST_ADDRESS_1);
+ setActiveAndVerify(connection);
+
+ // The ConnectionService has gained the focus
+ assertTrue(CtsSelfManagedConnectionService.getConnectionService().waitForUpdate(
+ CtsSelfManagedConnectionService.FOCUS_GAINED_LOCK));
+
+ setDisconnectedAndVerify(connection);
+ }
+
+ public void testSelfManagedConnectionServiceLostFocus() throws Exception {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
+ // GIVEN an ongoing self-managed call
+ TestUtils.addIncomingCall(getInstrumentation(), mTelecomManager,
+ TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_1);
+ SelfManagedConnection connection = TestUtils.waitForAndGetConnection(TEST_ADDRESS_1);
+ setActiveAndVerify(connection);
+ assertTrue(CtsSelfManagedConnectionService.getConnectionService().waitForUpdate(
+ CtsSelfManagedConnectionService.FOCUS_GAINED_LOCK));
+
+ // WHEN place a managed call
+ placeAndVerifyCall();
+ verifyConnectionForOutgoingCall().setActive();
+ assertTrue(connectionService.waitForEvent(
+ MockConnectionService.EVENT_CONNECTION_SERVICE_FOCUS_GAINED));
+
+ // THEN the self-managed ConnectionService lost the focus
+
+ connection.disconnectAndDestroy();
+ assertTrue(CtsSelfManagedConnectionService.getConnectionService().waitForUpdate(
+ CtsSelfManagedConnectionService.FOCUS_LOST_LOCK));
+ }
+
+ /**
+ * Tests that Telecom will disallow the incoming call while the ringing call is existed.
+ */
+ public void testRingCallLimitForOnePhoneAccount() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
+ // GIVEN a self-managed call which state is ringing
+ TestUtils.addIncomingCall(getInstrumentation(), mTelecomManager,
+ TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_1);
+ SelfManagedConnection connection = TestUtils.waitForAndGetConnection(TEST_ADDRESS_1);
+ connection.setRinging();
+
+ // WHEN create a new incoming call for the the same PhoneAccount
+ TestUtils.addIncomingCall(getInstrumentation(), mTelecomManager,
+ TestUtils.TEST_SELF_MANAGED_HANDLE_1, TEST_ADDRESS_1);
+
+ // THEN the new incoming call is denied
+ assertTrue(CtsSelfManagedConnectionService.getConnectionService().waitForUpdate(
+ CtsSelfManagedConnectionService.CREATE_INCOMING_CONNECTION_FAILED_LOCK));
+ }
+
+ /**
* Tests that Telecom enforces a maximum number of calls for a self-managed ConnectionService.
*
* @throws Exception
diff --git a/tests/tests/telephony/AndroidManifest.xml b/tests/tests/telephony/AndroidManifest.xml
index a50329a..b6840a3 100644
--- a/tests/tests/telephony/AndroidManifest.xml
+++ b/tests/tests/telephony/AndroidManifest.xml
@@ -129,6 +129,10 @@
</intent-filter>
</activity>
+ <activity android:name="android.telephony.euicc.cts.EuiccTestResolutionActivity"/>
+
+ <activity android:name="android.telephony.euicc.cts.EuiccResolutionActivity"/>
+
<uses-library android:name="android.test.runner" />
diff --git a/tests/tests/telephony/src/android/telephony/euicc/cts/EuiccManagerTest.java b/tests/tests/telephony/src/android/telephony/euicc/cts/EuiccManagerTest.java
new file mode 100644
index 0000000..17db4b1
--- /dev/null
+++ b/tests/tests/telephony/src/android/telephony/euicc/cts/EuiccManagerTest.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2018 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.telephony.euicc.cts;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.telephony.euicc.DownloadableSubscription;
+import android.telephony.euicc.EuiccInfo;
+import android.telephony.euicc.EuiccManager;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public class EuiccManagerTest {
+
+ private static final int REQUEST_CODE = 0;
+ private static final int CALLBACK_TIMEOUT_MILLIS = 2000;
+ // starting activities might take extra time
+ private static final int ACTIVITY_CALLBACK_TIMEOUT_MILLIS = 5000;
+ private static final String ACTION_DOWNLOAD_SUBSCRIPTION = "cts_download_subscription";
+ private static final String ACTION_DELETE_SUBSCRIPTION = "cts_delete_subscription";
+ private static final String ACTION_SWITCH_TO_SUBSCRIPTION = "cts_switch_to_subscription";
+ private static final String ACTION_START_TEST_RESOLUTION_ACTIVITY =
+ "cts_start_test_resolution_activity";
+ private static final String ACTIVATION_CODE = "1$LOCALHOST$04386-AGYFT-A74Y8-3F815";
+
+ private static final String[] sCallbackActions =
+ new String[] {
+ ACTION_DOWNLOAD_SUBSCRIPTION,
+ ACTION_DELETE_SUBSCRIPTION,
+ ACTION_SWITCH_TO_SUBSCRIPTION,
+ ACTION_START_TEST_RESOLUTION_ACTIVITY,
+ };
+
+ private MockEuiccManager mMockEuiccManager;
+ private CallbackReceiver mCallbackReceiver;
+
+ @Before
+ public void setUp() throws Exception {
+ mMockEuiccManager = new MockEuiccManager(getContext());
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (mCallbackReceiver != null) {
+ getContext().unregisterReceiver(mCallbackReceiver);
+ }
+ }
+
+ @Test
+ public void testGetEid() {
+ // test disabled state only for now
+ mMockEuiccManager.setEnabled(false /* enabled */);
+
+ // call getEid()
+ String eid = mMockEuiccManager.getEid();
+
+ // verify result is null
+ assertNull(eid);
+ }
+
+ @Test
+ public void testDownloadSubscription() {
+ // test disabled state only for now
+ mMockEuiccManager.setEnabled(false /* enabled */);
+
+ // set up CountDownLatch and receiver
+ CountDownLatch countDownLatch = new CountDownLatch(1);
+ mCallbackReceiver = new CallbackReceiver(countDownLatch);
+ getContext()
+ .registerReceiver(
+ mCallbackReceiver, new IntentFilter(ACTION_DOWNLOAD_SUBSCRIPTION));
+
+ // call downloadSubscription()
+ DownloadableSubscription subscription = createDownloadableSubscription();
+ PendingIntent callbackIntent = createCallbackIntent(ACTION_DOWNLOAD_SUBSCRIPTION);
+ mMockEuiccManager.downloadSubscription(
+ subscription, false /* switchAfterDownload */, callbackIntent);
+
+ // wait for callback
+ try {
+ countDownLatch.await(CALLBACK_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ fail(e.toString());
+ }
+
+ // verify correct result code is received
+ assertEquals(
+ EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_ERROR, mCallbackReceiver.getResultCode());
+ }
+
+ @Test
+ public void testGetEuiccInfo() {
+ // test disabled state only for now
+ mMockEuiccManager.setEnabled(false /* enabled */);
+
+ // call getEuiccInfo()
+ EuiccInfo euiccInfo = mMockEuiccManager.getEuiccInfo();
+
+ // verify result is null
+ assertNull(euiccInfo);
+ }
+
+ @Test
+ public void testDeleteSubscription() {
+ // test disabled state only for now
+ mMockEuiccManager.setEnabled(false /* enabled */);
+
+ // set up CountDownLatch and receiver
+ CountDownLatch countDownLatch = new CountDownLatch(1);
+ mCallbackReceiver = new CallbackReceiver(countDownLatch);
+ getContext()
+ .registerReceiver(mCallbackReceiver, new IntentFilter(ACTION_DELETE_SUBSCRIPTION));
+
+ // call deleteSubscription()
+ PendingIntent callbackIntent = createCallbackIntent(ACTION_DELETE_SUBSCRIPTION);
+ mMockEuiccManager.deleteSubscription(3, callbackIntent);
+
+ // wait for callback
+ try {
+ countDownLatch.await(CALLBACK_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ fail(e.toString());
+ }
+
+ // verify correct result code is received
+ assertEquals(
+ EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_ERROR, mCallbackReceiver.getResultCode());
+ }
+
+ @Test
+ public void testSwitchToSubscription() {
+ // test disabled state only for now
+ mMockEuiccManager.setEnabled(false /* enabled */);
+
+ // set up CountDownLatch and receiver
+ CountDownLatch countDownLatch = new CountDownLatch(1);
+ mCallbackReceiver = new CallbackReceiver(countDownLatch);
+ getContext()
+ .registerReceiver(
+ mCallbackReceiver, new IntentFilter(ACTION_SWITCH_TO_SUBSCRIPTION));
+
+ // call deleteSubscription()
+ PendingIntent callbackIntent = createCallbackIntent(ACTION_SWITCH_TO_SUBSCRIPTION);
+ mMockEuiccManager.switchToSubscription(4, callbackIntent);
+
+ // wait for callback
+ try {
+ countDownLatch.await(CALLBACK_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ fail(e.toString());
+ }
+
+ // verify correct result code is received
+ assertEquals(
+ EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_ERROR, mCallbackReceiver.getResultCode());
+ }
+
+ @Test
+ public void testStartResolutionActivity() {
+ // set up CountDownLatch and receiver
+ CountDownLatch countDownLatch = new CountDownLatch(1);
+ mCallbackReceiver = new CallbackReceiver(countDownLatch);
+ getContext()
+ .registerReceiver(
+ mCallbackReceiver, new IntentFilter(ACTION_START_TEST_RESOLUTION_ACTIVITY));
+
+ /*
+ * Start EuiccTestResolutionActivity to test EuiccManager#startResolutionActivity(), since
+ * it requires a foreground activity. EuiccTestResolutionActivity will report the test
+ * result to the callback receiver.
+ */
+ Intent testResolutionActivityIntent =
+ new Intent(getContext(), EuiccTestResolutionActivity.class);
+ PendingIntent callbackIntent = createCallbackIntent(ACTION_START_TEST_RESOLUTION_ACTIVITY);
+ testResolutionActivityIntent.putExtra(
+ EuiccTestResolutionActivity.EXTRA_ACTIVITY_CALLBACK_INTENT, callbackIntent);
+ testResolutionActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ getContext().startActivity(testResolutionActivityIntent);
+
+ // wait for callback
+ try {
+ countDownLatch.await(ACTIVITY_CALLBACK_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ fail(e.toString());
+ }
+
+ // verify test result reported by EuiccTestResolutionActivity
+ assertEquals(
+ EuiccTestResolutionActivity.RESULT_CODE_TEST_PASSED,
+ mCallbackReceiver.getResultCode());
+ }
+
+ private Context getContext() {
+ return InstrumentationRegistry.getContext();
+ }
+
+ private DownloadableSubscription createDownloadableSubscription() {
+ return DownloadableSubscription.forActivationCode(ACTIVATION_CODE);
+ }
+
+ private PendingIntent createCallbackIntent(String action) {
+ Intent intent = new Intent(action);
+ return PendingIntent.getBroadcast(
+ getContext(), REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ }
+
+ /** Mock version of {@link EuiccManager} that overrides {@link EuiccManager#isEnabled()}. */
+ private class MockEuiccManager extends EuiccManager {
+
+ private boolean mEnabled = false;
+
+ public MockEuiccManager(Context context) {
+ super(context);
+ }
+
+ public void setEnabled(boolean enabled) {
+ mEnabled = enabled;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return mEnabled;
+ }
+ }
+
+ private static class CallbackReceiver extends BroadcastReceiver {
+
+ private CountDownLatch mCountDownLatch;
+
+ public CallbackReceiver(CountDownLatch latch) {
+ mCountDownLatch = latch;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ for (String callbackAction : sCallbackActions) {
+ if (callbackAction.equals(intent.getAction())) {
+ int resultCode = getResultCode();
+ mCountDownLatch.countDown();
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/tests/tests/telephony/src/android/telephony/euicc/cts/EuiccResolutionActivity.java b/tests/tests/telephony/src/android/telephony/euicc/cts/EuiccResolutionActivity.java
new file mode 100644
index 0000000..7a4ca2a
--- /dev/null
+++ b/tests/tests/telephony/src/android/telephony/euicc/cts/EuiccResolutionActivity.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 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.telephony.euicc.cts;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.telephony.euicc.EuiccManager;
+
+/**
+ * A dummy activity which simulates a resolution activity. Returns {@link Activity#RESULT_OK} to
+ * caller if 1) {@link Activity#onResume()} is called (as proof that the activity has been
+ * successfully started), and 2) the callback intent is verified.
+ */
+public class EuiccResolutionActivity extends Activity {
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ // verify callback intent
+ // TODO: verify callback intent's action matches
+ // EuiccTestResolutionActivity.ACTION_START_RESOLUTION_ACTIVITY
+ PendingIntent callbackIntent =
+ getIntent()
+ .getParcelableExtra(
+ EuiccManager
+ .EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_CALLBACK_INTENT);
+ if (callbackIntent != null) {
+ setResult(RESULT_OK);
+ } else {
+ setResult(RESULT_CANCELED);
+ }
+
+ // Resolution activity has successfully started, return result & finish
+ finish();
+ }
+}
diff --git a/tests/tests/telephony/src/android/telephony/euicc/cts/EuiccTestResolutionActivity.java b/tests/tests/telephony/src/android/telephony/euicc/cts/EuiccTestResolutionActivity.java
new file mode 100644
index 0000000..b15ab22
--- /dev/null
+++ b/tests/tests/telephony/src/android/telephony/euicc/cts/EuiccTestResolutionActivity.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2018 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.telephony.euicc.cts;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentSender;
+import android.os.Bundle;
+import android.telephony.euicc.EuiccManager;
+
+/**
+ * A dummy activity started by {@link EuiccManagerTest#testStartResolutionActivity()} for testing
+ * {@link android.telephony.euicc.EuiccManager#startResolutionActivity(Activity, int, Intent,
+ * PendingIntent)}. Sends {@link EuiccTestResolutionActivity#RESULT_CODE_TEST_PASSED} if the
+ * resolution activity is successfully started, {@link
+ * EuiccTestResolutionActivity#RESULT_CODE_TEST_FAILED} otherwise.
+ */
+public class EuiccTestResolutionActivity extends Activity {
+
+ public static final String EXTRA_ACTIVITY_CALLBACK_INTENT = "extra_activity_callback_intent";
+ public static final int RESULT_CODE_TEST_PASSED = 101;
+ public static final int RESULT_CODE_TEST_FAILED = 102;
+
+ private static final int REQUEST_CODE = 100;
+ private static final String ACTION_START_RESOLUTION_ACTIVITY = "cts_start_resolution_activity";
+
+ private PendingIntent mCallbackIntent;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mCallbackIntent = getIntent().getParcelableExtra(EXTRA_ACTIVITY_CALLBACK_INTENT);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ testStartResolutionActivity();
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (requestCode == REQUEST_CODE) {
+ sendCallbackAndFinish(
+ resultCode == RESULT_OK ? RESULT_CODE_TEST_PASSED : RESULT_CODE_TEST_FAILED);
+ }
+ }
+
+ private void testStartResolutionActivity() {
+ EuiccManager euiccManager = (EuiccManager) getSystemService(Context.EUICC_SERVICE);
+
+ // specify activity to start
+ Intent resolutionActivityIntent =
+ new Intent(getApplicationContext(), EuiccResolutionActivity.class);
+ PendingIntent resolutionIntent =
+ PendingIntent.getActivity(
+ getApplicationContext(),
+ 0 /* requestCode */,
+ resolutionActivityIntent,
+ PendingIntent.FLAG_ONE_SHOT);
+
+ // add pending intent to extra
+ Intent resultIntent = new Intent();
+ resultIntent.putExtra(
+ EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT, resolutionIntent);
+
+ // call startResolutionActivity()
+ PendingIntent callbackIntent = createCallbackIntent(ACTION_START_RESOLUTION_ACTIVITY);
+ try {
+ euiccManager.startResolutionActivity(this, REQUEST_CODE, resultIntent, callbackIntent);
+ } catch (IntentSender.SendIntentException e) {
+ sendCallbackAndFinish(RESULT_CODE_TEST_FAILED);
+ }
+ }
+
+ private PendingIntent createCallbackIntent(String action) {
+ Intent intent = new Intent(action);
+ return PendingIntent.getBroadcast(
+ getApplicationContext(), REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ }
+
+ private void sendCallbackAndFinish(int resultCode) {
+ if (mCallbackIntent != null) {
+ try {
+ mCallbackIntent.send(resultCode);
+ } catch (PendingIntent.CanceledException e) {
+ // Caller canceled the callback; do nothing.
+ }
+ }
+ finish();
+ }
+}
diff --git a/tests/tests/text/OWNERS b/tests/tests/text/OWNERS
index 0f85e1f..9f2182e 100644
--- a/tests/tests/text/OWNERS
+++ b/tests/tests/text/OWNERS
@@ -1,4 +1,3 @@
siyamed@google.com
nona@google.com
clarabayarri@google.com
-toki@google.com
diff --git a/tests/tests/transition/src/android/transition/cts/ArcMotionTest.java b/tests/tests/transition/src/android/transition/cts/ArcMotionTest.java
index 370155d..db88bde 100644
--- a/tests/tests/transition/src/android/transition/cts/ArcMotionTest.java
+++ b/tests/tests/transition/src/android/transition/cts/ArcMotionTest.java
@@ -196,7 +196,38 @@
expected = arcWithPoint(100, 50, 0, 0, ex, ey);
path = arcMotion.getPath(100, 50, 0, 0);
assertPathMatches(expected, path);
+ }
+ @Test
+ public void horizontalAndVerticalMotion() {
+ ArcMotion arcMotion = new ArcMotion();
+ arcMotion.setMinimumHorizontalAngle(80);
+ arcMotion.setMaximumAngle(90);
+
+ float ex = 50;
+ float ey = (float) (50 * Math.tan(Math.toRadians(40)));
+ Path expected = arcWithPoint(0, 0, 100, 0, ex, ey);
+ Path path = arcMotion.getPath(0, 0, 100, 0);
+ assertPathMatches(expected, path);
+
+ // Now move it in the opposite direction
+ expected = arcWithPoint(100, 0, 0, 0, ex, ey);
+ path = arcMotion.getPath(100, 0, 0, 0);
+ assertPathMatches(expected, path);
+
+ // Now try vertical path
+ arcMotion.setMinimumVerticalAngle(45);
+ ex = (float) (50 * Math.tan(Math.toRadians(22.5)));
+ ey = 50f;
+ expected = arcWithPoint(0, 0, 0, 100f, ex, ey);
+ path = arcMotion.getPath(0, 0, 0, 100f);
+ assertPathMatches(expected, path);
+
+ // Now move it in the opposite direction
+ arcMotion.setMinimumVerticalAngle(45);
+ expected = arcWithPoint(0, 100, 0, 0f, ex, ey);
+ path = arcMotion.getPath(0, 100, 0, 0f);
+ assertPathMatches(expected, path);
}
}
diff --git a/tests/tests/view/src/android/view/cts/DragDropTest.java b/tests/tests/view/src/android/view/cts/DragDropTest.java
index d74acef..2ae12f0 100644
--- a/tests/tests/view/src/android/view/cts/DragDropTest.java
+++ b/tests/tests/view/src/android/view/cts/DragDropTest.java
@@ -65,6 +65,8 @@
private CountDownLatch mStartReceived;
private CountDownLatch mEndReceived;
+ private AssertionError mMainThreadAssertionError;
+
/**
* Check whether two objects have the same binary data when dumped into Parcels
* @return True if the objects are equal
@@ -340,8 +342,18 @@
}
}
- private void runOnMain(Runnable runner) {
- mInstrumentation.runOnMainSync(runner);
+ private void runOnMain(Runnable runner) throws AssertionError {
+ mMainThreadAssertionError = null;
+ mInstrumentation.runOnMainSync(() -> {
+ try {
+ runner.run();
+ } catch (AssertionError error) {
+ mMainThreadAssertionError = error;
+ }
+ });
+ if (mMainThreadAssertionError != null) {
+ throw mMainThreadAssertionError;
+ }
}
private void startDrag() {
diff --git a/tests/tests/view/src/android/view/cts/TextureViewTest.java b/tests/tests/view/src/android/view/cts/TextureViewTest.java
index d9b84a4..f66e137 100644
--- a/tests/tests/view/src/android/view/cts/TextureViewTest.java
+++ b/tests/tests/view/src/android/view/cts/TextureViewTest.java
@@ -20,16 +20,17 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
-import android.app.Instrumentation;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Point;
-import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
+import android.view.PixelCopy;
import android.view.View;
+import android.view.Window;
+import com.android.compatibility.common.util.SynchronousPixelCopy;
import com.android.compatibility.common.util.WidgetTestUtils;
import org.junit.Before;
@@ -42,8 +43,9 @@
@MediumTest
@RunWith(AndroidJUnit4.class)
public class TextureViewTest {
- private Instrumentation mInstrumentation;
private TextureViewCtsActivity mActivity;
+ private SynchronousPixelCopy mPixelCopy;
+ private Window mWindow;
@Rule
public ActivityTestRule<TextureViewCtsActivity> mActivityRule =
@@ -51,10 +53,9 @@
@Before
public void setup() {
- mInstrumentation = InstrumentationRegistry.getInstrumentation();
mActivity = mActivityRule.getActivity();
+ mPixelCopy = new SynchronousPixelCopy();
assertNotNull(mActivity);
- assertNotNull(mInstrumentation);
}
@Test
@@ -68,6 +69,7 @@
content.getLocationOnScreen(outLocation);
center.x = outLocation[0] + (content.getWidth() / 2);
center.y = outLocation[1] + (content.getHeight() / 2);
+ mWindow = mActivity.getWindow();
});
assertTrue(center.x > 0);
assertTrue(center.y > 0);
@@ -94,7 +96,10 @@
}
private int getPixel(Point point) {
- Bitmap screenshot = mInstrumentation.getUiAutomation().takeScreenshot();
+ Bitmap screenshot = Bitmap.createBitmap(mWindow.getDecorView().getWidth(),
+ mWindow.getDecorView().getHeight(), Bitmap.Config.ARGB_8888);
+ int result = mPixelCopy.request(mWindow, screenshot);
+ assertEquals("Copy request failed", PixelCopy.SUCCESS, result);
int pixel = screenshot.getPixel(point.x, point.y);
screenshot.recycle();
return pixel;
diff --git a/tests/tests/webkit/AndroidManifest.xml b/tests/tests/webkit/AndroidManifest.xml
index 5168cda..e7b81b9 100644
--- a/tests/tests/webkit/AndroidManifest.xml
+++ b/tests/tests/webkit/AndroidManifest.xml
@@ -66,6 +66,11 @@
<meta-data android:name="android.webkit.WebView.EnableSafeBrowsing" android:value="false" />
+ <!-- Specify a preloaded font list to ensure that this doesn't interfere
+ with the operation of the renderer process (as in b/70968451)
+ -->
+ <meta-data android:name="preloaded_fonts" android:resource="@array/preloaded_fonts" />
+
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/webkit/res/values/preloaded_fonts.xml b/tests/tests/webkit/res/values/preloaded_fonts.xml
new file mode 100644
index 0000000..f771982
--- /dev/null
+++ b/tests/tests/webkit/res/values/preloaded_fonts.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2018 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.
+-->
+<resources>
+ <!-- Specify a preloaded font list to ensure that this doesn't interfere
+ with the operation of the renderer process (as in b/70968451).
+ The list is intentionally empty, only the resource lookup for the list
+ itself needs to be covered.
+ -->
+ <array name="preloaded_fonts" translatable="false" />
+ <!-- Give the preloaded font list resource an ID that's unlikely to be
+ present in the APK implementing WebView to ensure it will crash if
+ actually looked up in the renderer process.
+ -->
+ <public type="array" name="preloaded_fonts" id="0x7f424242" />
+</resources>
diff --git a/tests/tests/widget/res/layout/magnifier_layout.xml b/tests/tests/widget/res/layout/magnifier_activity_basic_layout.xml
similarity index 93%
rename from tests/tests/widget/res/layout/magnifier_layout.xml
rename to tests/tests/widget/res/layout/magnifier_activity_basic_layout.xml
index 989d33d..f736e48 100644
--- a/tests/tests/widget/res/layout/magnifier_layout.xml
+++ b/tests/tests/widget/res/layout/magnifier_activity_basic_layout.xml
@@ -17,7 +17,7 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/magnifier_layout"
+ android:id="@+id/magnifier_activity_basic_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</LinearLayout>
diff --git a/tests/tests/widget/res/layout/magnifier_activity_four_quadrants_layout.xml b/tests/tests/widget/res/layout/magnifier_activity_four_quadrants_layout.xml
new file mode 100644
index 0000000..0240498
--- /dev/null
+++ b/tests/tests/widget/res/layout/magnifier_activity_four_quadrants_layout.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 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:id="@+id/magnifier_activity_four_quadrants_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1.0"
+ android:orientation="horizontal" >
+ <FrameLayout
+ android:id="@+id/magnifier_activity_four_quadrants_layout_quadrant_1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1.0"
+ android:background="@android:color/holo_blue_bright" />
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1.0"
+ android:background="@android:color/holo_green_light" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1.0"
+ android:orientation="horizontal" >
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1.0"
+ android:background="@android:color/holo_orange_light" />
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1.0"
+ android:background="@android:color/holo_red_light" />
+ </LinearLayout>
+</LinearLayout>
diff --git a/tests/tests/widget/src/android/widget/cts/MagnifierCtsActivity.java b/tests/tests/widget/src/android/widget/cts/MagnifierCtsActivity.java
index a828c3d..55d9f81 100644
--- a/tests/tests/widget/src/android/widget/cts/MagnifierCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/MagnifierCtsActivity.java
@@ -26,6 +26,6 @@
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.magnifier_layout);
+ setContentView(R.layout.magnifier_activity_basic_layout);
}
}
diff --git a/tests/tests/widget/src/android/widget/cts/MagnifierTest.java b/tests/tests/widget/src/android/widget/cts/MagnifierTest.java
index fde1848..fc54362 100644
--- a/tests/tests/widget/src/android/widget/cts/MagnifierTest.java
+++ b/tests/tests/widget/src/android/widget/cts/MagnifierTest.java
@@ -16,11 +16,22 @@
package android.widget.cts;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
import android.app.Activity;
+import android.app.Instrumentation;
+import android.graphics.Bitmap;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.support.test.InstrumentationRegistry;
import android.support.test.annotation.UiThreadTest;
import android.support.test.filters.SmallTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
+import android.util.DisplayMetrics;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
@@ -33,14 +44,19 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.HashMap;
+import java.util.Map;
+
/**
* Tests for {@link Magnifier}.
*/
@SmallTest
@RunWith(AndroidJUnit4.class)
public class MagnifierTest {
+ private Instrumentation mInstrumentation;
private Activity mActivity;
- private LinearLayout mMagnifierLayout;
+ private LinearLayout mLayout;
+ private Magnifier mMagnifier;
@Rule
public ActivityTestRule<MagnifierCtsActivity> mActivityRule =
@@ -48,9 +64,24 @@
@Before
public void setup() {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
mActivity = mActivityRule.getActivity();
PollingCheck.waitFor(mActivity::hasWindowFocus);
- mMagnifierLayout = mActivity.findViewById(R.id.magnifier_layout);
+ mLayout = mActivity.findViewById(R.id.magnifier_activity_basic_layout);
+
+ // Do not run the tests, unless the device screen is big enough to fit the magnifier.
+ assumeTrue(isScreenBigEnough());
+ }
+
+ private boolean isScreenBigEnough() {
+ // Get the size of the screen in dp.
+ final DisplayMetrics displayMetrics = mActivity.getResources().getDisplayMetrics();
+ final float dpScreenWidth = displayMetrics.widthPixels / displayMetrics.density;
+ final float dpScreenHeight = displayMetrics.heightPixels / displayMetrics.density;
+ // Get the size of the magnifier window in dp.
+ final PointF dpMagnifier = Magnifier.getMagnifierDefaultSize();
+
+ return dpScreenWidth >= dpMagnifier.x * 1.1 && dpScreenHeight >= dpMagnifier.y * 1.1;
}
@Test
@@ -66,46 +97,138 @@
@Test
@UiThreadTest
public void testShow() {
- View view = new View(mActivity);
- mMagnifierLayout.addView(view, new LayoutParams(200, 200));
- Magnifier magnifier = new Magnifier(view);
+ final View view = new View(mActivity);
+ mLayout.addView(view, new LayoutParams(200, 200));
+ mMagnifier = new Magnifier(view);
// Valid coordinates.
- magnifier.show(0, 0);
+ mMagnifier.show(0, 0);
// Invalid coordinates, should both be clamped to 0.
- magnifier.show(-1, -1);
+ mMagnifier.show(-1, -1);
// Valid coordinates.
- magnifier.show(10, 10);
+ mMagnifier.show(10, 10);
// Same valid coordinate as above, should skip making another copy request.
- magnifier.show(10, 10);
+ mMagnifier.show(10, 10);
}
@Test
@UiThreadTest
public void testDismiss() {
- View view = new View(mActivity);
- mMagnifierLayout.addView(view, new LayoutParams(200, 200));
- Magnifier magnifier = new Magnifier(view);
+ final View view = new View(mActivity);
+ mLayout.addView(view, new LayoutParams(200, 200));
+ mMagnifier = new Magnifier(view);
// Valid coordinates.
- magnifier.show(10, 10);
- magnifier.dismiss();
+ mMagnifier.show(10, 10);
+ mMagnifier.dismiss();
// Should be no-op.
- magnifier.dismiss();
+ mMagnifier.dismiss();
}
@Test
@UiThreadTest
public void testUpdate() {
- View view = new View(mActivity);
- mMagnifierLayout.addView(view, new LayoutParams(200, 200));
- Magnifier magnifier = new Magnifier(view);
+ final View view = new View(mActivity);
+ mLayout.addView(view, new LayoutParams(200, 200));
+ mMagnifier = new Magnifier(view);
// Should be no-op.
- magnifier.update();
+ mMagnifier.update();
// Valid coordinates.
- magnifier.show(10, 10);
+ mMagnifier.show(10, 10);
// Should not crash.
- magnifier.update();
- magnifier.dismiss();
+ mMagnifier.update();
+ mMagnifier.dismiss();
// Should be no-op.
- magnifier.update();
+ mMagnifier.update();
+ }
+
+ @Test
+ public void testWindowContent() {
+ prepareFourQuadrantsScenario();
+ // Show the magnifier at the center of the activity.
+ mInstrumentation.runOnMainSync(() -> {
+ mMagnifier.show(mLayout.getWidth() / 2, mLayout.getHeight() / 2);
+ });
+ mInstrumentation.waitForIdleSync();
+
+ assertFourQuadrants(mMagnifier.getContent());
+ }
+
+ @Test
+ public void testWindowPosition() {
+ prepareFourQuadrantsScenario();
+ // Show the magnifier at the center of the activity.
+ mInstrumentation.runOnMainSync(() -> {
+ mMagnifier.show(mLayout.getWidth() / 2, mLayout.getHeight() / 2);
+ });
+ mInstrumentation.waitForIdleSync();
+
+ // Assert that the magnifier position represents a valid rectangle on screen.
+ final Rect position = mMagnifier.getWindowPositionOnScreen();
+ assertFalse(position.isEmpty());
+ assertTrue(0 <= position.left && position.right <= mLayout.getWidth());
+ assertTrue(0 <= position.top && position.bottom <= mLayout.getHeight());
+ }
+
+ @Test
+ public void testWindowContent_modifiesAfterUpdate() {
+ prepareFourQuadrantsScenario();
+ // Show the magnifier at the center of the activity.
+ mInstrumentation.runOnMainSync(() -> {
+ mMagnifier.show(mLayout.getWidth() / 2, mLayout.getHeight() / 2);
+ });
+ mInstrumentation.waitForIdleSync();
+
+ final Bitmap initialBitmap = mMagnifier.getContent()
+ .copy(mMagnifier.getContent().getConfig(), true);
+ assertFourQuadrants(initialBitmap);
+
+ // Make the one quadrant white.
+ mInstrumentation.runOnMainSync(() -> {
+ mActivity.findViewById(R.id.magnifier_activity_four_quadrants_layout_quadrant_1)
+ .setBackground(null);
+ });
+ mInstrumentation.waitForIdleSync();
+ // Update the magnifier.
+ mInstrumentation.runOnMainSync(mMagnifier::update);
+ mInstrumentation.waitForIdleSync();
+
+ final Bitmap newBitmap = mMagnifier.getContent();
+ assertFourQuadrants(newBitmap);
+ assertFalse(newBitmap.sameAs(initialBitmap));
+ }
+
+ /**
+ * Sets the activity to contain four equal quadrants coloured differently and
+ * instantiates a magnifier. This method should not be called on the UI thread.
+ */
+ private void prepareFourQuadrantsScenario() {
+ mInstrumentation.runOnMainSync(() -> {
+ mActivity.setContentView(R.layout.magnifier_activity_four_quadrants_layout);
+ mLayout = mActivity.findViewById(R.id.magnifier_activity_four_quadrants_layout);
+ mMagnifier = new Magnifier(mLayout);
+ });
+ mInstrumentation.waitForIdleSync();
+ }
+
+ /**
+ * Asserts that the current bitmap contains exactly four different colors,
+ * and that they are (almost) equally distributed.
+ *
+ * @param bitmap the bitmap to be checked
+ */
+ private void assertFourQuadrants(final Bitmap bitmap) {
+ final int totalPixels = bitmap.getWidth() * bitmap.getHeight();
+ final Map<Integer, Integer> colorCount = new HashMap<>();
+ for (int x = 0; x < bitmap.getWidth(); ++x) {
+ for (int y = 0; y < bitmap.getHeight(); ++y) {
+ final int currentColor = bitmap.getPixel(x, y);
+ colorCount.put(currentColor, colorCount.getOrDefault(currentColor, 0) + 1);
+ }
+ }
+ assertEquals(4, colorCount.size());
+ for (Integer color : colorCount.keySet()) {
+ final int currentCount = colorCount.get(color);
+ final float proportion = 1.0f * Math.abs(4 * currentCount - totalPixels) / totalPixels;
+ assertTrue(proportion <= 0.2f);
+ }
}
}
diff --git a/tests/tests/widget/src/android/widget/cts/OWNERS b/tests/tests/widget/src/android/widget/cts/OWNERS
index 84f2ef0..462812a 100644
--- a/tests/tests/widget/src/android/widget/cts/OWNERS
+++ b/tests/tests/widget/src/android/widget/cts/OWNERS
@@ -1,8 +1,6 @@
per-file TextView*.java = siyamed@google.com
per-file TextView*.java = nona@google.com
per-file TextView*.java = clarabayarri@google.com
-per-file TextView*.java = toki@google.com
per-file EditText*.java = siyamed@google.com
per-file EditText*.java = nona@google.com
per-file EditText*.java = clarabayarri@google.com
-per-file EditText*.java = toki@google.com
diff --git a/tests/vr/jni/VrExtensionsJni.cpp b/tests/vr/jni/VrExtensionsJni.cpp
index 6f304b8..c93ca62 100644
--- a/tests/vr/jni/VrExtensionsJni.cpp
+++ b/tests/vr/jni/VrExtensionsJni.cpp
@@ -22,7 +22,9 @@
#include <stdlib.h>
#include <android/hardware_buffer.h>
#include <android/log.h>
+#include <cmath>
#include <string>
+#include <sstream>
#define LOG_TAG "VrExtensionsJni"
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE,LOG_TAG,__VA_ARGS__)
@@ -62,6 +64,9 @@
#define GL_MAP_PERSISTENT_BIT_EXT 0x0040
#define GL_MAP_COHERENT_BIT_EXT 0x0080
+// Declare tokens added as a part of EGL_EXT_image_gl_colorspace.
+#define EGL_GL_COLORSPACE_DEFAULT_EXT 0x314D
+
#define LOAD_PROC(NAME, TYPE) \
NAME = reinterpret_cast<TYPE>(eglGetProcAddress(# NAME))
@@ -81,6 +86,9 @@
ASSERT((a) != (b), "assert failed on (" #a ") at " __FILE__ ":%d", __LINE__)
#define ASSERT_GT(a, b) \
ASSERT((a) > (b), "assert failed on (" #a ") at " __FILE__ ":%d", __LINE__)
+#define ASSERT_NEAR(a, b, delta) \
+ ASSERT((a - delta) <= (b) && (b) <= (a + delta), \
+ "assert failed on (" #a ") at " __FILE__ ":%d", __LINE__)
void fail(JNIEnv* env, const char* format, ...) {
va_list args;
@@ -266,3 +274,403 @@
testExternalBuffer(env, usage, false, test_string);
testExternalBuffer(env, usage, true, test_string);
}
+
+const GLchar* const kSrgbVertexCode = R"(
+ // vertex position in clip space (-1..1)
+ attribute vec4 position;
+ varying mediump vec2 uv;
+ void main() {
+ gl_Position = position;
+ uv = vec2(0.5 * (position.x + 1.0), 0.5);
+ })";
+
+const GLchar* const kSrgbFragmentCode = R"(
+ varying mediump vec2 uv;
+ uniform sampler2D tex;
+ void main() {
+ gl_FragColor = texture2D(tex, uv);
+ })";
+
+static inline float SrgbChannelToLinear(float cs) {
+ if (cs <= 0.04045)
+ return cs / 12.92f;
+ else
+ return std::pow((cs + 0.055f) / 1.055f, 2.4f);
+}
+
+static inline float LinearChannelToSrgb(float cs) {
+ if (cs <= 0.0f)
+ return 0.0f;
+ else if (cs < 0.0031308f)
+ return 12.92f * cs;
+ else if (cs < 1.0f)
+ return 1.055f * std::pow(cs, 0.41666f) - 0.055f;
+ else
+ return 1.0f;
+}
+
+static uint32_t SrgbColorToLinear(uint32_t color) {
+ float r = SrgbChannelToLinear((color & 0xff) / 255.0f);
+ float g = SrgbChannelToLinear(((color >> 8) & 0xff) / 255.0f);
+ float b = SrgbChannelToLinear(((color >> 16) & 0xff) / 255.0f);
+ uint32_t r8 = r * 255.0f;
+ uint32_t g8 = g * 255.0f;
+ uint32_t b8 = b * 255.0f;
+ uint32_t a8 = color >> 24;
+ return (a8 << 24) | (b8 << 16) | (g8 << 8) | r8;
+}
+
+static uint32_t LinearColorToSrgb(uint32_t color) {
+ float r = LinearChannelToSrgb((color & 0xff) / 255.0f);
+ float g = LinearChannelToSrgb(((color >> 8) & 0xff) / 255.0f);
+ float b = LinearChannelToSrgb(((color >> 16) & 0xff) / 255.0f);
+ uint32_t r8 = r * 255.0f;
+ uint32_t g8 = g * 255.0f;
+ uint32_t b8 = b * 255.0f;
+ uint32_t a8 = color >> 24;
+ return (a8 << 24) | (b8 << 16) | (g8 << 8) | r8;
+}
+
+static uint32_t LerpColor(uint32_t color0, uint32_t color1, float t) {
+ float r0 = (color0 & 0xff) / 255.0f;
+ float g0 = ((color0 >> 8) & 0xff) / 255.0f;
+ float b0 = ((color0 >> 16) & 0xff) / 255.0f;
+ float a0 = ((color0 >> 24) & 0xff) / 255.0f;
+ float r1 = (color1 & 0xff) / 255.0f;
+ float g1 = ((color1 >> 8) & 0xff) / 255.0f;
+ float b1 = ((color1 >> 16) & 0xff) / 255.0f;
+ float a1 = ((color1 >> 24) & 0xff) / 255.0f;
+ uint32_t r8 = (r0 * (1.0f - t) + r1 * t) * 255.0f;
+ uint32_t g8 = (g0 * (1.0f - t) + g1 * t) * 255.0f;
+ uint32_t b8 = (b0 * (1.0f - t) + b1 * t) * 255.0f;
+ uint32_t a8 = (a0 * (1.0f - t) + a1 * t) * 255.0f;
+ return (a8 << 24) | (b8 << 16) | (g8 << 8) | r8;
+}
+
+// Choose an odd-numbered framebuffer width so that we can
+// extract the middle pixel of a gradient.
+constexpr uint32_t kFramebufferWidth = 31;
+
+// Declare the pixel data for the 2x1 texture.
+// Color components are ordered like this: AABBGGRR
+constexpr uint32_t kTextureData[] = {
+ 0xff800000, // Half-Blue
+ 0xff000080, // Half-Red
+};
+constexpr uint32_t kTextureWidth = sizeof(kTextureData) / sizeof(kTextureData[0]);
+
+// Declare expected values for the middle pixel for various sampling behaviors.
+const uint32_t kExpectedMiddlePixel_NoSrgb = LerpColor(kTextureData[0], kTextureData[1], 0.5f);
+const uint32_t kExpectedMiddlePixel_LinearizeAfterFiltering =
+ SrgbColorToLinear(kExpectedMiddlePixel_NoSrgb);
+const uint32_t kExpectedMiddlePixel_LinearizeBeforeFiltering =
+ LerpColor(SrgbColorToLinear(kTextureData[0]), SrgbColorToLinear(kTextureData[1]), 0.5f);
+
+// Declare expected values for the final pixel color for various blending behaviors.
+constexpr uint32_t kBlendDestColor = 0xff000080;
+constexpr uint32_t kBlendSourceColor = 0x80800000;
+const uint32_t kExpectedBlendedPixel_NoSrgb = LerpColor(kBlendSourceColor, kBlendDestColor, 0.5f);
+const uint32_t kExpectedBlendedPixel_Srgb =
+ LinearColorToSrgb(LerpColor(kBlendSourceColor, SrgbColorToLinear(kBlendDestColor), 0.5f));
+
+// Define a set of test flags. Not using an enum to avoid lots of casts.
+namespace SrgbFlag {
+constexpr uint32_t kHardwareBuffer = 1 << 0;
+constexpr uint32_t kSrgbFormat = 1 << 1;
+constexpr uint32_t kEglColorspaceDefault = 1 << 2;
+constexpr uint32_t kEglColorspaceLinear = 1 << 3;
+constexpr uint32_t kEglColorspaceSrgb = 1 << 4;
+} // namespace SrgbFlag
+
+static void configureEglColorspace(EGLint attrs[4], uint32_t srgb_flags) {
+ if (srgb_flags & SrgbFlag::kEglColorspaceDefault) {
+ attrs[0] = EGL_GL_COLORSPACE_KHR;
+ attrs[1] = EGL_GL_COLORSPACE_DEFAULT_EXT;
+ } else if (srgb_flags & SrgbFlag::kEglColorspaceLinear) {
+ attrs[0] = EGL_GL_COLORSPACE_KHR;
+ attrs[1] = EGL_GL_COLORSPACE_LINEAR_KHR;
+ } else if (srgb_flags & SrgbFlag::kEglColorspaceSrgb) {
+ attrs[0] = EGL_GL_COLORSPACE_KHR;
+ attrs[1] = EGL_GL_COLORSPACE_SRGB_KHR;
+ } else {
+ attrs[0] = EGL_NONE;
+ attrs[1] = EGL_NONE;
+ }
+ attrs[2] = EGL_NONE;
+ attrs[3] = EGL_NONE;
+}
+
+static void printSrgbFlags(std::ostream& out, uint32_t srgb_flags) {
+ if (srgb_flags & SrgbFlag::kHardwareBuffer) {
+ out << " AHardwareBuffer";
+ }
+ if (srgb_flags & SrgbFlag::kSrgbFormat) {
+ out << " GL_SRGB_ALPHA";
+ }
+ if (srgb_flags & SrgbFlag::kEglColorspaceDefault) {
+ out << " EGL_GL_COLORSPACE_DEFAULT_KHR";
+ }
+ if (srgb_flags & SrgbFlag::kEglColorspaceLinear) {
+ out << " EGL_GL_COLORSPACE_LINEAR_KHR";
+ }
+ if (srgb_flags & SrgbFlag::kEglColorspaceSrgb) {
+ out << " EGL_GL_COLORSPACE_SRGB_KHR";
+ }
+}
+
+// Draws a gradient and extracts the middle pixel. Returns void to allow ASSERT to work.
+static void testLinearMagnification(JNIEnv* env, uint32_t flags, uint32_t* middle_pixel) {
+ const bool use_hwbuffer = flags & SrgbFlag::kHardwareBuffer;
+ const bool use_srgb_format = flags & SrgbFlag::kSrgbFormat;
+ GLuint srgbtex;
+ glGenTextures(1, &srgbtex);
+ glBindTexture(GL_TEXTURE_2D, srgbtex);
+ if (use_hwbuffer) {
+ // Create a one-dimensional AHardwareBuffer.
+ AHardwareBuffer_Desc desc = {};
+ desc.width = kTextureWidth;
+ desc.height = 1;
+ desc.layers = 1;
+ desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
+ desc.usage =
+ AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
+ AHardwareBuffer* hwbuffer = nullptr;
+ int error = AHardwareBuffer_allocate(&desc, &hwbuffer);
+ ASSERT_EQ(error, NO_ERROR);
+ // Populate the pixels.
+ uint32_t* pixels = nullptr;
+ error = AHardwareBuffer_lock(hwbuffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, -1, nullptr,
+ reinterpret_cast<void**>(&pixels));
+ ASSERT_EQ(error, NO_ERROR);
+ ASSERT_TRUE(pixels);
+ memcpy(pixels, kTextureData, sizeof(kTextureData));
+ error = AHardwareBuffer_unlock(hwbuffer, nullptr);
+ ASSERT_EQ(error, NO_ERROR);
+ // Create EGLClientBuffer from the AHardwareBuffer.
+ EGLClientBuffer native_buffer = eglGetNativeClientBufferANDROID(hwbuffer);
+ ASSERT_TRUE(native_buffer);
+ // Create EGLImage from EGLClientBuffer.
+ EGLint attrs[4];
+ configureEglColorspace(attrs, flags);
+ EGLImageKHR image = eglCreateImageKHR(eglGetCurrentDisplay(), EGL_NO_CONTEXT,
+ EGL_NATIVE_BUFFER_ANDROID, native_buffer, attrs);
+ ASSERT_TRUE(image);
+ // Allocate the OpenGL texture using the EGLImage.
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
+ } else {
+ GLenum internal_format = use_srgb_format ? GL_SRGB8_ALPHA8_EXT : GL_RGBA8_OES;
+ GLenum format = use_srgb_format ? GL_SRGB_ALPHA_EXT : GL_RGBA;
+ glTexImage2D(GL_TEXTURE_2D, 0, internal_format, kTextureWidth, 1, 0, format,
+ GL_UNSIGNED_BYTE, kTextureData);
+ }
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ ASSERT_EQ(glGetError(), GL_NO_ERROR);
+ // Clear to an interesting constant color to make it easier to spot bugs.
+ glClearColor(1.0, 0.0, 0.5, 0.25);
+ glClear(GL_COLOR_BUFFER_BIT);
+ // Draw the texture.
+ const float kTriangleCoords[] = {-1, -1, -1, 1, 1, -1, 1, 1};
+ glBindTexture(GL_TEXTURE_2D, srgbtex);
+ const int kPositionSlot = 0;
+ glVertexAttribPointer(kPositionSlot, 2, GL_FLOAT, false, 0, kTriangleCoords);
+ glEnableVertexAttribArray(kPositionSlot);
+ glViewport(0, 0, kFramebufferWidth, 1);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ // Read back the framebuffer.
+ glReadPixels(kFramebufferWidth / 2, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, middle_pixel);
+ std::ostringstream flag_string;
+ printSrgbFlags(flag_string, flags);
+ LOGV("Filtered Result: %8.8X Flags =%s", *middle_pixel, flag_string.str().c_str());
+ ASSERT_EQ(glGetError(), GL_NO_ERROR);
+}
+
+// Blends a color into an (optionally) sRGB-encoded framebuffer and extracts the final color.
+// Returns void to allow ASSERT to work.
+static void testFramebufferBlending(JNIEnv* env, uint32_t flags, uint32_t* final_color) {
+ const bool use_hwbuffer = flags & SrgbFlag::kHardwareBuffer;
+ const bool use_srgb_format = flags & SrgbFlag::kSrgbFormat;
+ const bool override_egl_colorspace = use_hwbuffer && (flags & SrgbFlag::kEglColorspaceSrgb);
+ GLuint tex;
+ glGenTextures(1, &tex);
+ glBindTexture(GL_TEXTURE_2D, tex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ // Create a 1x1 half-blue, half-opaque texture.
+ const uint32_t kTextureData[] = {
+ kBlendSourceColor,
+ };
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, kTextureData);
+ // Create 1x1 framebuffer object.
+ GLuint fbo;
+ glGenFramebuffers(1, &fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ GLuint fbotex;
+ glGenTextures(1, &fbotex);
+ glBindTexture(GL_TEXTURE_2D, fbotex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ if (use_hwbuffer) {
+ AHardwareBuffer_Desc desc = {};
+ desc.width = 1;
+ desc.height = 1;
+ desc.layers = 1;
+ desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
+ desc.usage =
+ AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
+ AHardwareBuffer* hwbuffer = nullptr;
+ int error = AHardwareBuffer_allocate(&desc, &hwbuffer);
+ ASSERT_EQ(error, NO_ERROR);
+ // Create EGLClientBuffer from the AHardwareBuffer.
+ EGLClientBuffer native_buffer = eglGetNativeClientBufferANDROID(hwbuffer);
+ ASSERT_TRUE(native_buffer);
+ // Create EGLImage from EGLClientBuffer.
+ EGLint attrs[4];
+ configureEglColorspace(attrs, flags);
+ EGLImageKHR image = eglCreateImageKHR(eglGetCurrentDisplay(), EGL_NO_CONTEXT,
+ EGL_NATIVE_BUFFER_ANDROID, native_buffer, attrs);
+ ASSERT_TRUE(image);
+ // Allocate the OpenGL texture using the EGLImage.
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
+ } else {
+ GLenum internal_format = use_srgb_format ? GL_SRGB8_ALPHA8_EXT : GL_RGBA8_OES;
+ GLenum format = use_srgb_format ? GL_SRGB_ALPHA_EXT : GL_RGBA;
+ glTexImage2D(GL_TEXTURE_2D, 0, internal_format, 1, 1, 0, format,
+ GL_UNSIGNED_BYTE, nullptr);
+ }
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, fbotex, 0);
+ ASSERT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE);
+ ASSERT_EQ(glGetError(), GL_NO_ERROR);
+ // Clear to half-red.
+ if (use_srgb_format || override_egl_colorspace) {
+ glClearColor(SrgbChannelToLinear(0.5), 0.0, 0.0, 1.0);
+ } else {
+ glClearColor(0.5, 0.0, 0.0, 1.0);
+ }
+ glClear(GL_COLOR_BUFFER_BIT);
+ // Sanity check the cleared color.
+ uint32_t cleared_color = 0;
+ glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &cleared_color);
+ LOGV(" Cleared Color: %8.8X", cleared_color);
+ ASSERT_EQ(cleared_color, kBlendDestColor);
+ // Draw the texture.
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ const float kTriangleCoords[] = {-1, -1, -1, 1, 1, -1, 1, 1};
+ glBindTexture(GL_TEXTURE_2D, tex);
+ const int kPositionSlot = 0;
+ glVertexAttribPointer(kPositionSlot, 2, GL_FLOAT, false, 0, kTriangleCoords);
+ glEnableVertexAttribArray(kPositionSlot);
+ glViewport(0, 0, 1, 1);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ // Read back the framebuffer.
+ glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, final_color);
+ std::ostringstream flag_string;
+ printSrgbFlags(flag_string, flags);
+ LOGV("Blending Result: %8.8X Flags =%s", *final_color, flag_string.str().c_str());
+ ASSERT_EQ(glGetError(), GL_NO_ERROR);
+}
+
+extern "C" JNIEXPORT void JNICALL
+Java_android_vr_cts_VrExtensionBehaviorTest_nativeTestSrgbBuffer(
+ JNIEnv* env, jclass /* unused */) {
+ // First, check the published extension strings against expectations.
+ const char *egl_exts =
+ eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS);
+ LOGV("EGL Extensions: %s", egl_exts);
+ ASSERT_TRUE(egl_exts);
+ bool egl_colorspace_supported = strstr(egl_exts, "EGL_EXT_image_gl_colorspace");
+ auto gl_exts = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
+ LOGV("OpenGL Extensions: %s", gl_exts);
+ ASSERT_TRUE(gl_exts);
+ // Load ancillary entry points provided by extensions.
+ LOAD_PROC(eglGetNativeClientBufferANDROID,
+ PFNEGLGETNATIVECLIENTBUFFERANDROID);
+ ASSERT_NE(eglGetNativeClientBufferANDROID, nullptr);
+ LOAD_PROC(eglCreateImageKHR, PFNEGLCREATEIMAGEKHRPROC);
+ ASSERT_NE(eglCreateImageKHR, nullptr);
+ LOAD_PROC(glEGLImageTargetTexture2DOES,
+ PFNGLEGLIMAGETARGETTEXTURE2DOESPROC);
+ ASSERT_NE(glEGLImageTargetTexture2DOES, nullptr);
+ // Create a plain old one-dimensional FBO to render to.
+ GLuint fbo;
+ glGenFramebuffers(1, &fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ GLuint fbotex;
+ glGenTextures(1, &fbotex);
+ glBindTexture(GL_TEXTURE_2D, fbotex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kFramebufferWidth, 1, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, nullptr);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, fbotex, 0);
+ ASSERT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE);
+ ASSERT_EQ(glGetError(), GL_NO_ERROR);
+ // Compile and link shaders.
+ int program = glCreateProgram();
+ int vshader = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vshader, 1, &kSrgbVertexCode, nullptr);
+ glCompileShader(vshader);
+ glAttachShader(program, vshader);
+ int fshader = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fshader, 1, &kSrgbFragmentCode, nullptr);
+ glCompileShader(fshader);
+ glAttachShader(program, fshader);
+ glLinkProgram(program);
+ int status;
+ glGetProgramiv(program, GL_LINK_STATUS, &status);
+ ASSERT_EQ(status, GL_TRUE);
+ glUseProgram(program);
+ ASSERT_EQ(glGetError(), GL_NO_ERROR);
+
+ // Filtering test.
+ LOGV("Expected value for NoSrgb = %8.8X", kExpectedMiddlePixel_NoSrgb);
+ LOGV("Expected value for Srgb = %8.8X", kExpectedMiddlePixel_LinearizeBeforeFiltering);
+ uint32_t middle_pixel;
+ // First do a sanity check with plain old pre-linearized textures.
+ testLinearMagnification(env, 0, &middle_pixel);
+ ASSERT_NEAR(middle_pixel, kExpectedMiddlePixel_NoSrgb, 1);
+ testLinearMagnification(env, SrgbFlag::kHardwareBuffer, &middle_pixel);
+ ASSERT_NEAR(middle_pixel, kExpectedMiddlePixel_NoSrgb, 1);
+ // Try a "normally allocated" OpenGL texture with an sRGB source format.
+ testLinearMagnification(env, SrgbFlag::kSrgbFormat, &middle_pixel);
+ ASSERT_NEAR(middle_pixel, kExpectedMiddlePixel_LinearizeBeforeFiltering, 1);
+ // Try EGL_EXT_image_gl_colorspace.
+ if (egl_colorspace_supported) {
+ testLinearMagnification(env, SrgbFlag::kHardwareBuffer | SrgbFlag::kEglColorspaceDefault, &middle_pixel);
+ ASSERT_NEAR(middle_pixel, kExpectedMiddlePixel_NoSrgb, 1);
+ testLinearMagnification(env, SrgbFlag::kHardwareBuffer | SrgbFlag::kEglColorspaceLinear, &middle_pixel);
+ ASSERT_NEAR(middle_pixel, kExpectedMiddlePixel_NoSrgb, 1);
+ testLinearMagnification(env, SrgbFlag::kHardwareBuffer | SrgbFlag::kEglColorspaceSrgb, &middle_pixel);
+ ASSERT_NEAR(middle_pixel, kExpectedMiddlePixel_LinearizeBeforeFiltering, 1);
+ }
+
+ // Blending test.
+ LOGV("Expected value for NoSrgb = %8.8X", kExpectedBlendedPixel_NoSrgb);
+ LOGV("Expected value for Srgb = %8.8X", kExpectedBlendedPixel_Srgb);
+ uint32_t final_color;
+ // First do a sanity check with plain old pre-linearized textures.
+ testFramebufferBlending(env, 0, &final_color);
+ ASSERT_NEAR(final_color, kExpectedBlendedPixel_NoSrgb, 1);
+ testFramebufferBlending(env, SrgbFlag::kHardwareBuffer, &final_color);
+ ASSERT_NEAR(final_color, kExpectedBlendedPixel_NoSrgb, 1);
+ // Try a "normally allocated" OpenGL texture with an sRGB source format.
+ testFramebufferBlending(env, SrgbFlag::kSrgbFormat, &final_color);
+ ASSERT_NEAR(final_color, kExpectedBlendedPixel_Srgb, 1);
+ // Try EGL_EXT_image_gl_colorspace.
+ if (egl_colorspace_supported) {
+ testFramebufferBlending(env, SrgbFlag::kHardwareBuffer | SrgbFlag::kEglColorspaceDefault, &final_color);
+ ASSERT_NEAR(final_color, kExpectedBlendedPixel_NoSrgb, 1);
+ testFramebufferBlending(env, SrgbFlag::kHardwareBuffer | SrgbFlag::kEglColorspaceLinear, &final_color);
+ ASSERT_NEAR(final_color, kExpectedBlendedPixel_NoSrgb, 1);
+ testFramebufferBlending(env, SrgbFlag::kHardwareBuffer | SrgbFlag::kEglColorspaceSrgb, &final_color);
+ ASSERT_NEAR(final_color, kExpectedBlendedPixel_Srgb, 1);
+ }
+}
diff --git a/tests/vr/src/android/vr/cts/VrExtensionBehaviorTest.java b/tests/vr/src/android/vr/cts/VrExtensionBehaviorTest.java
index a27633a..5230eda 100644
--- a/tests/vr/src/android/vr/cts/VrExtensionBehaviorTest.java
+++ b/tests/vr/src/android/vr/cts/VrExtensionBehaviorTest.java
@@ -193,6 +193,20 @@
});
}
+ public void testSrgbBuffer() throws Throwable {
+ mActivity = getGlEsActivity(OpenGLESActivity.RENDERER_BASIC, 0, 0, 0);
+ if (!mActivity.supportsVrHighPerformance())
+ return;
+
+ assertEquals(GLES32.GL_NO_ERROR, mActivity.glGetError());
+
+ mActivity.runOnGlThread(new Runnable() {
+ public void run() {
+ nativeTestSrgbBuffer();
+ }
+ });
+ }
+
/**
* Runs a context priority test.
*/
@@ -223,4 +237,5 @@
private static native boolean nativeTestEglImageArray();
private static native boolean nativeTestExternalBuffer();
+ private static native boolean nativeTestSrgbBuffer();
}
diff --git a/tools/utils/java-cert-list-generator.sh b/tools/utils/java-cert-list-generator.sh
index 3b09f86..1f33c4a 100755
--- a/tools/utils/java-cert-list-generator.sh
+++ b/tools/utils/java-cert-list-generator.sh
@@ -60,5 +60,20 @@
cat <<-ENDCLASS
};
+ENDCLASS
+
+cat <<-STARTCLASS
+
+ static final String[] WFA_CERTIFICATE_DATA = {
+STARTCLASS
+
+CERT_DIRECTORY=$ANDROID_BUILD_TOP/system/ca-certificates/wfa_certs/files/
+for FILE in `ls $CERT_DIRECTORY`; do
+ FINGERPRINT=`cat $CERT_DIRECTORY/$FILE | grep "SHA1 Fingerprint=" | cut -d '=' -f 2`
+ echo " \"${FINGERPRINT}\","
+done
+
+cat <<-ENDCLASS
+ };
}
ENDCLASS