Merge "Use exclude filters for cts retry runs" into nyc-dev
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 157b54f..5d3914f 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -23,6 +23,7 @@
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="24"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index e14e2d9..50e1bdf 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -2462,6 +2462,13 @@
Do you see the programs named \"Dummy Program\" and their descriptions
"Dummy Program Description" in the EPG?
</string>
+ <string name="tv_input_discover_test_trigger_setup">
+ Select the \"Launch setup\" button and verify if the bundled TV app shows the list of installed
+ TV inputs for setup.
+ </string>
+ <string name="tv_input_discover_test_verify_trigger_setup">
+ Do you see the \"CTS Verifier\" input in the list?
+ </string>
<string name="tv_parental_control_test">TV app parental controls test</string>
<string name="tv_parental_control_test_info">
@@ -2489,6 +2496,7 @@
<string name="tv_launch_tv_app">Launch TV app</string>
<string name="tv_launch_epg">Launch EPG</string>
+ <string name="tv_launch_setup">Launch setup</string>
<string name="tv_channel_not_found">
CtsVerifier channel is not set up. Please set up before proceeding.
</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvInputDiscoveryTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvInputDiscoveryTestActivity.java
index e8e2cee..56c8ac0 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvInputDiscoveryTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvInputDiscoveryTestActivity.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.content.Intent;
import android.media.tv.TvContract;
+import android.media.tv.TvInputManager;
import android.os.AsyncTask;
import android.view.View;
@@ -36,6 +37,8 @@
TvContract.Channels.CONTENT_URI);
private static final Intent EPG_INTENT = new Intent(Intent.ACTION_VIEW,
TvContract.Programs.CONTENT_URI);
+ private static final Intent TV_TRIGGER_SETUP_INTENT = new Intent(
+ TvInputManager.ACTION_SETUP_INPUTS);
private static final long TIMEOUT_MS = 5l * 60l * 1000l; // 5 mins.
@@ -47,6 +50,8 @@
private View mVerifyGlobalSearchItem;
private View mGoToEpgItem;
private View mVerifyEpgItem;
+ private View mTriggerSetupItem;
+ private View mVerifyTriggerSetupItem;
private boolean mTuneVerified;
private boolean mOverlayViewVerified;
private boolean mGlobalSearchVerified;
@@ -109,6 +114,13 @@
setButtonEnabled(mVerifyEpgItem, true);
} else if (containsButton(mVerifyEpgItem, v)) {
setPassState(mVerifyEpgItem, true);
+ setButtonEnabled(mTriggerSetupItem, true);
+ } else if (containsButton(mTriggerSetupItem, v)) {
+ startActivity(TV_TRIGGER_SETUP_INTENT);
+ setPassState(mTriggerSetupItem, true);
+ setButtonEnabled(mVerifyTriggerSetupItem, true);
+ } else if (containsButton(mVerifyTriggerSetupItem, v)) {
+ setPassState(mVerifyTriggerSetupItem, true);
getPassButton().setEnabled(true);
}
}
@@ -130,6 +142,10 @@
R.string.tv_launch_epg, this);
mVerifyEpgItem = createUserItem(R.string.tv_input_discover_test_verify_epg,
android.R.string.yes, this);
+ mTriggerSetupItem = createUserItem(R.string.tv_input_discover_test_trigger_setup,
+ R.string.tv_launch_setup, this);
+ mVerifyTriggerSetupItem = createUserItem(
+ R.string.tv_input_discover_test_verify_trigger_setup, android.R.string.yes, this);
}
@Override
diff --git a/common/host-side/tradefed/res/report/compatibility_result.xsl b/common/host-side/tradefed/res/report/compatibility_result.xsl
index 1fb4e83..ac5c282 100644
--- a/common/host-side/tradefed/res/report/compatibility_result.xsl
+++ b/common/host-side/tradefed/res/report/compatibility_result.xsl
@@ -16,6 +16,7 @@
<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp " "> ]>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
<xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
@@ -31,69 +32,41 @@
<div>
<table class="title">
<tr>
- <td width="40%" align="left"><img src="logo.png"></img></td>
- <td width="60%" align="left">
- <h1>Test Report</h1>
- </td>
+ <td align="left"><img src="logo.png"/></td>
</tr>
</table>
</div>
- <img src="newrule_green.png" align="left"></img>
-
- <br></br>
-
- <center>
- <a href="device-info/GenericDeviceInfo.deviceinfo.json" >Device Information</a>
- </center>
-
- <br></br>
<div>
<table class="summary">
<tr>
- <th colspan="2">Test Summary</th>
+ <th colspan="2">Summary</th>
</tr>
<tr>
- <td class="rowtitle">Compatibility Suite</td>
+ <td class="rowtitle">Suite / Plan</td>
<td>
- <xsl:value-of select="Result/@suite_name"/>
+ <xsl:value-of select="Result/@suite_name"/> / <xsl:value-of select="Result/@plan"/>
</td>
</tr>
<tr>
- <td class="rowtitle">Compatibility Version</td>
+ <td class="rowtitle">Suite / Build</td>
<td>
- <xsl:value-of select="Result/@suite_version"/>
- </td>
- </tr>
- <tr>
- <td class="rowtitle">Report Version</td>
- <td>
- <xsl:value-of select="Result/@report_version"/>
+ <xsl:value-of select="Result/@suite_version"/> / <xsl:value-of select="Result/@suite_build_number"/>
</td>
</tr>
<tr>
<td class="rowtitle">Host Info</td>
<td>
+ Result/@start
<xsl:value-of select="Result/@host_name"/>
(<xsl:value-of select="Result/@os_name"/> - <xsl:value-of select="Result/@os_version"/>)
</td>
</tr>
<tr>
- <td class="rowtitle">Plan</td>
+ <td class="rowtitle">Start time / End Time</td>
<td>
- <xsl:value-of select="Result/@plan"/>
- </td>
- </tr>
- <tr>
- <td class="rowtitle">Start time</td>
- <td>
- <xsl:value-of select="Result/@start"/>
- </td>
- </tr>
- <tr>
- <td class="rowtitle">End time</td>
- <td>
- <xsl:value-of select="Result/@end"/>
+ <xsl:value-of select="Result/@start_display"/> /
+ <xsl:value-of select="Result/@end_display"/>
</td>
</tr>
<tr>
@@ -114,11 +87,35 @@
<xsl:value-of select="Result/Summary/@not_executed"/>
</td>
</tr>
+ <tr>
+ <td class="rowtitle">Fingerprint</td>
+ <td>
+ <xsl:value-of select="Result/Build/@build_fingerprint"/>
+ </td>
+ </tr>
+ <tr>
+ <td class="rowtitle">Security Patch</td>
+ <td>
+ <xsl:value-of select="Result/Build/@build_version_security_patch"/>
+ </td>
+ </tr>
+ <tr>
+ <td class="rowtitle">Release (SDK)</td>
+ <td>
+ <xsl:value-of select="Result/Build/@build_version_release"/> (<xsl:value-of select="Result/Build/@build_version_sdk"/>)
+ </td>
+ </tr>
+ <tr>
+ <td class="rowtitle">ABIs</td>
+ <td>
+ <xsl:value-of select="Result/Build/@build_abis"/>
+ </td>
+ </tr>
</table>
</div>
<!-- High level summary of test execution -->
- <h2 align="center">Test Summary by Module</h2>
+ <br/>
<div>
<table class="testsummary">
<tr>
@@ -135,16 +132,16 @@
<a href="#{$href}"><xsl:value-of select="@name"/> - <xsl:value-of select="@abi"/></a>
</td>
<td>
- <xsl:value-of select="count(Test[@result = 'pass'])"/>
+ <xsl:value-of select="count(TestCase/Test[@result = 'pass'])"/>
</td>
<td>
- <xsl:value-of select="count(Test[@result = 'fail'])"/>
+ <xsl:value-of select="count(TestCase/Test[@result = 'fail'])"/>
</td>
<td>
- <xsl:value-of select="count(Test[@result = 'not_executed'])"/>
+ <xsl:value-of select="count(TestCase/Test[@result = 'not_executed'])"/>
</td>
<td>
- <xsl:value-of select="count(Test)"/>
+ <xsl:value-of select="count(TestCase/Test)"/>
</td>
</tr>
</xsl:for-each> <!-- end Module -->
@@ -161,7 +158,7 @@
<xsl:with-param name="resultFilter" select="'not_executed'" />
</xsl:call-template>
- <h2 align="center">Detailed Test Report</h2>
+ <br/>
<xsl:call-template name="detailedTestReport" />
</body>
@@ -201,46 +198,49 @@
<th>Details</th>
</tr>
- <!-- test -->
- <xsl:for-each select="Test">
- <xsl:if test="$resultFilter='' or $resultFilter=@result">
- <tr>
- <td class="testname"> -- <xsl:value-of select="@name"/></td>
+ <xsl:for-each select="TestCase">
+ <xsl:variable name="TestCase" select="."/>
+ <!-- test -->
+ <xsl:for-each select="Test">
+ <xsl:if test="$resultFilter='' or $resultFilter=@result">
+ <tr>
+ <td class="testname"> <xsl:value-of select="$TestCase/@name"/>#<xsl:value-of select="@name"/></td>
- <!-- test results -->
- <xsl:if test="@result='pass'">
- <td class="pass">
- <div style="text-align: center; margin-left:auto; margin-right:auto;">
- <xsl:value-of select="@result"/>
- </div>
- </td>
- <td class="failuredetails"/>
- </xsl:if>
+ <!-- test results -->
+ <xsl:if test="@result='pass'">
+ <td class="pass">
+ <div style="text-align: center; margin-left:auto; margin-right:auto;">
+ <xsl:value-of select="@result"/>
+ </div>
+ </td>
+ <td class="failuredetails"/>
+ </xsl:if>
- <xsl:if test="@result='fail'">
- <td class="failed">
- <div style="text-align: center; margin-left:auto; margin-right:auto;">
- <xsl:value-of select="@result"/>
- </div>
- </td>
- <td class="failuredetails">
- <div class="details">
- <xsl:value-of select="Failure/@message"/>
- </div>
- </td>
- </xsl:if>
+ <xsl:if test="@result='fail'">
+ <td class="failed">
+ <div style="text-align: center; margin-left:auto; margin-right:auto;">
+ <xsl:value-of select="@result"/>
+ </div>
+ </td>
+ <td class="failuredetails">
+ <div class="details">
+ <xsl:value-of select="Failure/@message"/>
+ </div>
+ </td>
+ </xsl:if>
- <xsl:if test="@result='not_executed'">
- <td class="not_executed">
- <div style="text-align: center; margin-left:auto; margin-right:auto;">
- <xsl:value-of select="@result"/>
- </div>
- </td>
- <td class="failuredetails"></td>
- </xsl:if>
- </tr> <!-- finished with a row -->
- </xsl:if>
- </xsl:for-each> <!-- end test -->
+ <xsl:if test="@result='not_executed'">
+ <td class="not_executed">
+ <div style="text-align: center; margin-left:auto; margin-right:auto;">
+ <xsl:value-of select="@result"/>
+ </div>
+ </td>
+ <td class="failuredetails"></td>
+ </xsl:if>
+ </tr> <!-- finished with a row -->
+ </xsl:if>
+ </xsl:for-each> <!-- end test -->
+ </xsl:for-each>
</table>
</xsl:if>
</xsl:for-each> <!-- end test Module -->
diff --git a/common/host-side/tradefed/res/report/newrule_green.png b/common/host-side/tradefed/res/report/newrule_green.png
deleted file mode 100644
index 10a4194..0000000
--- a/common/host-side/tradefed/res/report/newrule_green.png
+++ /dev/null
Binary files differ
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 81d78c0..9f9728b 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
@@ -75,8 +75,7 @@
"compatibility_result.css",
"compatibility_result.xsd",
"compatibility_result.xsl",
- "logo.png",
- "newrule_green.png"};
+ "logo.png"};
@Option(name = CompatibilityTest.RETRY_OPTION,
shortName = 'r',
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 3fcf8b5..6228cd7 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
@@ -62,8 +62,7 @@
"compatibility_result.css",
"compatibility_result.xsd",
"compatibility_result.xsl",
- "logo.png",
- "newrule_green.png"};
+ "logo.png"};
private ResultReporter mReporter;
private IBuildInfo mBuildInfo;
diff --git a/common/util/src/com/android/compatibility/common/util/ResultHandler.java b/common/util/src/com/android/compatibility/common/util/ResultHandler.java
index 5f05229..d91763c 100644
--- a/common/util/src/com/android/compatibility/common/util/ResultHandler.java
+++ b/common/util/src/com/android/compatibility/common/util/ResultHandler.java
@@ -28,7 +28,9 @@
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Date;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
@@ -50,6 +52,7 @@
private static final String BUILD_TAG = "Build";
private static final String CASE_TAG = "TestCase";
private static final String DEVICES_ATTR = "devices";
+ private static final String END_DISPLAY_TIME_ATTR = "end_display";
private static final String END_TIME_ATTR = "end";
private static final String FAILED_ATTR = "failed";
private static final String FAILURE_TAG = "Failure";
@@ -72,6 +75,7 @@
private static final String RUNTIME_ATTR = "runtime";
private static final String SCREENSHOT_TAG = "Screenshot";
private static final String STACK_TAG = "StackTrace";
+ private static final String START_DISPLAY_TIME_ATTR = "start_display";
private static final String START_TIME_ATTR = "start";
private static final String SUITE_NAME_ATTR = "suite_name";
private static final String SUITE_PLAN_ATTR = "suite_plan";
@@ -205,10 +209,13 @@
serializer.startDocument(ENCODING, false);
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
serializer.processingInstruction(
- "xml-stylesheet type=\"text/xsl\" href=\"compatibility-result.xsl\"");
+ "xml-stylesheet type=\"text/xsl\" href=\"compatibility_result.xsl\"");
serializer.startTag(NS, RESULT_TAG);
serializer.attribute(NS, START_TIME_ATTR, String.valueOf(startTime));
serializer.attribute(NS, END_TIME_ATTR, String.valueOf(endTime));
+ serializer.attribute(NS, START_DISPLAY_TIME_ATTR, toReadableDateString(startTime));
+ serializer.attribute(NS, END_DISPLAY_TIME_ATTR, toReadableDateString(endTime));
+
serializer.attribute(NS, SUITE_NAME_ATTR, suiteName);
serializer.attribute(NS, SUITE_VERSION_ATTR, suiteVersion);
serializer.attribute(NS, SUITE_PLAN_ATTR, suitePlan);
@@ -315,4 +322,15 @@
return resultFile;
}
+ /**
+ * Return the given time as a {@link String} suitable for displaying.
+ * <p/>
+ * Example: Fri Aug 20 15:13:03 PDT 2010
+ *
+ * @param time the epoch time in ms since midnight Jan 1, 1970
+ */
+ static String toReadableDateString(long time) {
+ SimpleDateFormat dateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy");
+ return dateFormat.format(new Date(time));
+ }
}
diff --git a/common/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java b/common/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java
index 215e2ef..1e9aa33 100644
--- a/common/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java
+++ b/common/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java
@@ -69,12 +69,16 @@
"at four.big.insects.Marley.sing(Marley.java:10)";
private static final long START_MS = 1431586801000L;
private static final long END_MS = 1431673199000L;
+ private static final String START_DISPLAY = "Fri Aug 20 15:13:03 PDT 2010";
+ private static final String END_DISPLAY = "Fri Aug 20 15:13:04 PDT 2010";
+
private static final String REFERENCE_URL="http://android.com";
private static final String JOIN = "%s%s";
private static final String XML_BASE =
"<?xml version='1.0' encoding='UTF-8' standalone='no' ?>" +
"<?xml-stylesheet type=\"text/xsl\" href=\"compatibility_result.xsl\"?>\n" +
- "<Result start=\"%d\" end=\"%d\" suite_name=\"%s\" suite_version=\"%s\" " +
+ "<Result start=\"%d\" end=\"%d\" start_display=\"%s\"" +
+ "end_display=\"%s\" suite_name=\"%s\" suite_version=\"%s\" " +
"suite_plan=\"%s\" suite_build_number=\"%s\" report_version=\"%s\" " +
"devices=\"%s\" host_name=\"%s\"" +
"os_name=\"%s\" os_version=\"%s\" os_arch=\"%s\" java_vendor=\"%s\"" +
@@ -204,9 +208,10 @@
try {
hostName = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException ignored) {}
- String output = String.format(XML_BASE, START_MS, END_MS, SUITE_NAME, SUITE_VERSION,
- SUITE_PLAN, SUITE_BUILD, REPORT_VERSION, DEVICES, hostName, OS_NAME, OS_VERSION,
- OS_ARCH, JAVA_VENDOR, JAVA_VERSION, REFERENCE_URL, deviceInfo, summary, modules);
+ String output = String.format(XML_BASE, START_MS, END_MS, START_DISPLAY, END_DISPLAY,
+ SUITE_NAME, SUITE_VERSION, SUITE_PLAN, SUITE_BUILD, REPORT_VERSION, DEVICES,
+ hostName, OS_NAME, OS_VERSION, OS_ARCH, JAVA_VENDOR, JAVA_VERSION, REFERENCE_URL,
+ deviceInfo, summary, modules);
writer.write(output);
writer.flush();
diff --git a/hostsidetests/appsecurity/certs/pkgsigverify/rsa-16384.pk8 b/hostsidetests/appsecurity/certs/pkgsigverify/rsa-16384.pk8
new file mode 100644
index 0000000..c8d2793
--- /dev/null
+++ b/hostsidetests/appsecurity/certs/pkgsigverify/rsa-16384.pk8
Binary files differ
diff --git a/hostsidetests/appsecurity/certs/pkgsigverify/rsa-16384.x509.pem b/hostsidetests/appsecurity/certs/pkgsigverify/rsa-16384.x509.pem
new file mode 100644
index 0000000..22b6148
--- /dev/null
+++ b/hostsidetests/appsecurity/certs/pkgsigverify/rsa-16384.x509.pem
@@ -0,0 +1,93 @@
+-----BEGIN CERTIFICATE-----
+MIIQ+zCCCOOgAwIBAgIJAOd3bpikuRKvMA0GCSqGSIb3DQEBDQUAMBQxEjAQBgNV
+BAMMCXJzYS0xNjM4NDAeFw0xNjA0MDQxOTM0MzFaFw00MzA4MjExOTM0MzFaMBQx
+EjAQBgNVBAMMCXJzYS0xNjM4NDCCCCIwDQYJKoZIhvcNAQEBBQADgggPADCCCAoC
+gggBALDYs7aIK08pNr9fdrpLmUVfSc+3n/RNU2e7o3fzwQf2IMExk/ZmxF/ORgAd
+pXPEkn7uOLYSp+fJHUgqsca+8HsxTN1ypKov0X3OeFbnBLXmsoXgjRzaMEgluupd
+B81xnAKE/Vb+HYaEJ4YP+3UgBLIItnwLtL6vdh+e4qQGF9KEAv+T+PdrNQF0EGWK
+weCaOuMKRKfSnNXMkgIgWgoEefsBXNOR/jRJVFxsnJlwsB2iw0FbKjrxnlmwBL+f
+A8YxdMoCLxjL0TuUEmRyd0jO7Td49kUIkW6ux/b4qOvcUPQiODXeayesJ1lmFepS
+ATjhgCz2+C3pcAJOPvOvC4v0+5OQ3YrU2kKsnj8G2ic3SdPUq4UUvQWqY+rCZVDH
+IqsEs/+XO++wMELkN3uiQcRIEO8aCug+VxMSRiyRSSNtxmcmedUZevbZ6+2leBtn
+AbLP33E5hC80A7WKuddQgOiA1yTUVxatZEaxHFVZlg2nzSYHipvwMVC2+zQ4yrKA
+mbNp5wiVUV5WLsUkYEuSwl+MG9vEjr2gTX+qLrvpIYS2AF/16SOEw5zQBPUcfVIz
+eJU+W//wwXdlNmA6qRCDXqLDBX1MQrChpaI2eRbv64k5C09LtEA5nt/lJt5dm8IF
+XpurOZqHTVG3CCS15SM8PyoApYKN0oM9+6Z+FDUOB+VbTW/hAqKYLNBJmNf8mRkK
++c1peoOAYw5iG8iaSD8f8bcIi3oFPMdt0Gs5vDoLjbWmK2s9P2wknA4hmVe7hvSy
+DMvyxj8j4BLadc3HafcXYPfoNPhfgoiZVLm6ijEj74iKeLSkef8F3x0Agulnitz3
+CWt7X6EXHbqR/0++VTqgnFDe+enf9oFzMsDDbOs59dpyGFSP159dTqJILimF5xUG
+Fw95hsTbdEblZ7Q2MiibB38ifz8WT+Pix72SnHrlcnKonv8Tkeoie0AP+dYkYXpC
+Dy0oIzl7Vhy1e99RjX8kKjZAfCuiQ7wnOGNu6V32UyKMvWD5E6mNLpsvyBRTxDhs
+ePpH5dZWbhg6WxhD68QG/Wi/8FRmc8/TPpPXilOG3HHtX6Q3yfGYHJB6/dJhWQQy
+iZawyEpcyZKjEyWoJayRsKSLb6gW6Idfc1Uf/yb6IHDRlYZEPF7JuznjLCaz2QC9
+8GCBGfUE9OGH+LtdMnsmn2IYEd1FtWrRGduG0HNKubmx8bJmc1HkYDQg3cksPb2o
+jwCND2ALGtTcR30yllmSmEJKpXBYB00iRvxvkBqCkL4THOXhN2V5uEMrS0r8GRZN
+QCvCoFKulPjITmlQ/ciVonN9y9qVeRbFE4ZxiiBxF41K/Mw45ugIqfg4ndJqbub6
+5p15nhYJIC2CbsVL5+1THmd+kompQhUo1ttwof0aHh3KLwe1uq2OEU7Tz71Ct5+G
+b5JjIAlQDuGcfsx3utJY3AE5ailtvaRNAz3FyTsZGkIOeqX4uswWltxGnuSMSbPi
+CPv7ngFXkytkK+3Oqs92XM8mhO1yqPzmm73+qZYDGFdy32C/Rr0enETmgkUFPToH
+28hMcOsEt+7L0GM6A5N708BaF9Csy7XTFz47Hk2CjaKTvP08Tl3bFPULrgJ5KCr6
+4hc/bVIDkU7c1lhDISJ1yuw4KHizmjuf4UeRBBDoB3MpPwZSeEkggGXuX1wkFApu
+RGhjCXQgFU9bNtUHM6Kj0tPQZrgsvx2wwBUFVOfPoej6afrJqpvep+EN1+OJCE4c
+AzuZ1CdE96vEleVbrq3BQaJbsm8JqHs7lAn1aiCK0semqAoXD4cT4L2H4E37IDlm
+PHsxIeTmgD7/TP3InuFB6sYvVM8moG1TLmtUJkpc8kkPBPNbTRHwuRvMGD1pSsP1
+aNbgKkEfGqL1iOrfoTCRGKDeDDxWGsxDOgW1hRs9wGzJuMQjl1Rlb11lnnX7UYyT
+UnD/yw7YaplScWwpsqntQewI59A4ad1wOJlabDUFwkD4i4ERTcjyea1ydE03qaOy
+0ItJbc8kjsEMWFAv1+y7/cxD7kALcytvBHhD8OVJ40qJrtwRsXnv2T74cTPh87qh
+3j2tjdJKVSLxwqg5ZdvIemnWmmFAPuRERResp5j5WLJcOFcXhbp4CAQLViRoktLf
+AKtgKSVa9FQLvombOq8GqWxqeGJEsq+8/X6UOj/RDPu8gUCdodmlxgC5BpJlMTfg
+9ElvHb4oRewPfc5MBV5i++8xagxS1+5NM6z+1qZfT+XJcJ/wFYyeSvGGdEgaDIVd
+XGqOFDmA20bUl0xWSM5j4At2CmymAn32i8FR5lNfB/f8tIGBlXQyrYzpAKoj6FrV
+3u43zKgYBzDTqNs61e+A8MScV5666gvpcOltFiaucc455JGiN2v7N+SAygWaX3nb
+jidmRaIAftup6kXVXxy1ZwpKCtUTqo0M+S/jO9clHy1EYaSX12blCL1B6OFpMRV7
+1foffUHwaPrMqqbPphgN4QRY2Ao2sKSliiP1T8s1T2iteEGiazCdWSOVVi9Acbo5
+DfeBlWwhW6OQpv1nMTznGscc4+ledP5yG5C6boz2aNwK6H6cpDfEc7tWTWhZN5Jm
+Jlra4pseqf9Lsc/Y4QMD1312C3Hu8EtJ/qlxEDhLnCW8PHxdlRsIkmcV8w+as/hu
+6/MlOYcCp9ae6nooFL7ZuDkdDWm84UXdce2ZVVGVoDa+RdpICnp79y/9CLxWue4H
+09VFEFUH//E6lOCBymUjTSO/DQ6z+ceb2W5B3WVV8gqADTDhAgMBAAGjUDBOMB0G
+A1UdDgQWBBQkHp1wX0Sfr0xz7xcip9UwEIFTLDAfBgNVHSMEGDAWgBQkHp1wX0Sf
+r0xz7xcip9UwEIFTLDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBDQUAA4IIAQAd
+FhlHg4E7Yp8kIOfZRU5Cma6wbOSd2eHkV28WHGdwpKsvNhzgQEj+scYWSS8geozi
+vqSdJCoMmY8hWJh4SY0ED1DjPMoRvE8OotyGoCJovvYQia+gbVneT8JnfV3fkdwi
+hpUmAhokrsHkBj0jp2Ubff/D5yflA+QPCmhZZnkow+5QHXtmpy8CL9Fzfonz5uq7
+yCV5uWRicczFbQw3pDSXKn5OFqXuC8H/8R6Caq2TkJ1LusVtZJevcHBkEQ6e+XEX
+kZ+QCNtHw0a67LQEPtMXSyqZ/zR0roqwT6udUgHhdvZjbbb9GDpTW3u472IY18E+
+bf+npZl9kyuv2kyK1d2IjL45TxjBr7vLbjsP2UsmZvb3Wfb/kiMscvTBcxOL7/WA
+GNJ0XifmJWiDTDC+gUBC7LRN9lG8F7ykrMTtMUNlhow5LpIi0HA8TH58yq3/ulGq
+XWpculy33kcVAFTMGh57r8zq9DwkeW+RWggvHO2422S1bFGmKpizKASTvY6iqo4H
+yKvE9uZ41WaEbpp9WKPIaeup+ynxFpcgwMCKwvs7Yaj+mVexv7CoJ9nrEhMOHDxV
+GRyWDdBoIi08S02JHztZBXp5NZ+hqey5HrO4dhrnV1nVYJmH89KcAlXMfTZ2YHsv
+R2+dm6K8ToaX+Irqbz7Xbv8WG/aAdUqMSWkFEss7OT7VZBUiAdFaWqg0D0wtWSSE
+jZJJs9ISUTClq+97o9BEH2sAebchLFP56nY+Bj/zHBq2qPxTKdKE5BH13KcK1fwO
+eNn8a3SlSEHraa0oV6VjgSoMNdFz7b7b0r/Z8L4PEASJgH+VaGRm2TtuVWFHSqvX
+015UGITk6YgAQ25MTprJc/oAd0dut+aCPtOVElfukYvdrbw1YYQ9tc7kU+AVrzaf
+ytWj2GYR5Slfhle0inKlBvbpLTAHs82bp2Dgy9ZSQzW9/gIvLvCt+Hj0kiSYNcbX
+W7Ai5z2i6XKE7DdQO0Uzt+1bXGK3j2PI+81lCw2ejCFwjdYDWQw9f2nzQ5FgeYwG
+tc6fS4GbJM97n0yH9rj0Jb25AummZGnEL11ytPpC6Nv9cQdCuKDbaWQuQyRMCLEm
+hHaqV6k/fI4Etvuo15pyfJ9w7Xrhc6emgdg2HzJ99lDGkzZAF/3FR7N5pLPk5E0/
+PPlXUSiEx17IeWp3rNt0YSMixkGz+EbKyv9RIZzm/LV4zAzs2ZyUHHavUgZ602eg
+89ppqafaBrCwIWB1jUmnHJop9YlXQ3hE7pAV5qf9GxZLwUdzJcyLte1/vkn1yt94
+nLOZPPWUwUjIaBOZ7e/g8fHBjvAYwyoy3toKVpvkhR48NvcYD8pQ9cB6rIL0JkWV
+nQEYeISlJCUOO3K2eZ3ZH02ftha5gLshcGRXy9NS+4fNxDT3H+102RqSxmKPIxV0
+onV9RyOxUPKLRGjCZBZxs5aSxTYjFJ591azt3yAY4vwCnnHqdNGFbTat/Zc8LUOO
+J26n5cOYFGKPvZVvj8jMNYC1wo+R+A+1FeYXBV4MSVxCB7tjBlbU6OIyZSWLZ8Vw
+LMcPbuZ7ESj1LeTONwS1vspZM8Y/M8+RXv9VA8Z998tnNopdU3izVC2z6Zn9hNNI
+XBDbSe6ZRwsjXrm5TZCBgA4ZE18MwxPVhntSvl87Gc3wF4hz4BOiZXmffrXK4nQJ
+aVA8E2IsriCV+GQBN/ui+w3U9LbtsHrbauhjrru5EfYohpuInwvgPlAnTztdv9u7
+ee8RhwaCa+MInZanD6pRAAcfM6O64CPxHZtfVW6JM42N7wQXijvYzJPVR30F+6o1
+C+KwySuMBOGxOctmzLj938/OMrxuLBOmv3PJvSnHV0pWtbR7r7jH3v0uUm54zH56
+Qo/Rm/Aqf+m4Si3Xtsf9zvc89sqG5v2TT882Joja76zlJfaS31QgbnLTmKtAHtIC
+mqfQPvt1LNEJIiB6FZDHJIW5Ccm7imsixerxCBBoAt/J/dhW6N+cjZ0EWG5NiSoz
+9LmAZv8iWyqK/KvdPXUopQWqkYUvuIyNCYqzTRLKudUMohefNwghvl1gSGp4IMZ/
+4LyrJHi9eCcD9Z65PJsRTua+742N2sdhFfU/C4atOUGSK9x/Dl79Qkgsl6HqAoce
+HXiHAIvoOqC+jzEkjjxow30BzJeGsZoFwNvMUW7HcQ523DiIOx6MX8oQyKEo+W6C
+ayFvvvT3qHu2hL2ZxOXE+rGyUJnmwqctz4ChLvyYXa/eNrycs382x2U5XNXgXzNT
+3bwB9B+LnKSMJEB+UvHdbBcafYyevLptbF5xiiiUA0P3fq61AfmNiCzJWb+kaO11
+oHHQNWyG/fO49u3bZJkhvlsk8GXAp9uTqdW7YAqxjy8NohFewmtpTJPE62XKIqiq
++dqo4nUT761iaUBxgyj1v5jKcXT2JiEMnEe4AN7pZJ01pCNXQrXl+6ru4TVV3tpy
+OsDJ9UfZo8xZXEAJ/gvSyiih0xq6xhwGuUyExC3GldBz2frveWImxVEiqQIdHULH
+WwB6eAm9T1f+2hOGq7AB9Jb8CRyQniJWXtWu9uJBt+XwSt5lN6VUjeLt95SitvjO
+llqs0zhvTf52H8siwaO83Cui78iamqv7jVatB3JYW71S5cOyZ/x5Z5FYqKi8/wjO
+L4OyUs54kfcJllsxAmS014UgcTrJpbMNw7jSzLX6FxT4MEbyARK8wWQfEZQ2tCeo
+IOzfcYvlY05mG0KSzs6ZGBrWRZQDPcbJ0CKNSLTFbQ==
+-----END CERTIFICATE-----
diff --git a/hostsidetests/appsecurity/certs/pkgsigverify/rsa-8192.pk8 b/hostsidetests/appsecurity/certs/pkgsigverify/rsa-8192.pk8
new file mode 100644
index 0000000..cc7a7ec
--- /dev/null
+++ b/hostsidetests/appsecurity/certs/pkgsigverify/rsa-8192.pk8
Binary files differ
diff --git a/hostsidetests/appsecurity/certs/pkgsigverify/rsa-8192.x509.pem b/hostsidetests/appsecurity/certs/pkgsigverify/rsa-8192.x509.pem
new file mode 100644
index 0000000..42f1428
--- /dev/null
+++ b/hostsidetests/appsecurity/certs/pkgsigverify/rsa-8192.x509.pem
@@ -0,0 +1,50 @@
+-----BEGIN CERTIFICATE-----
+MIII+TCCBOGgAwIBAgIJAMMCN6DTJaAOMA0GCSqGSIb3DQEBDQUAMBMxETAPBgNV
+BAMMCHJzYS04MTkyMB4XDTE2MDQwNDE5MzI0NloXDTQzMDgyMTE5MzI0NlowEzER
+MA8GA1UEAwwIcnNhLTgxOTIwggQiMA0GCSqGSIb3DQEBAQUAA4IEDwAwggQKAoIE
+AQCt2gaOPSTn1A/WkapaytoE2RGF5nBzlfLocagG+0Bgz0RH3QQq0xBEmQivmbj4
+egyKFQQ9dYrefXRnayLQvHpfeT31QXR3iKOfMnvtxK9UnkXo9S/T+czyj91Ox51w
+HFUyMlXjFs8btxi6Lpkrgl3jmL+e4/WI8khvTrdszrO8rBHBYlD8Y7SAvPcVczYq
+nn4m6Jd0/abR5slHiyGtkTREoHmW/u4r4PfTzanLyzcsWH9/td+sYHcu1Y0XTWTR
+x2qrUmpD+7X5cvXP9rsECU82dtnyPZPIHBqzfLJ8oGELsJxgVZ0u9gW0tlmJQdVo
+Q0QPJSWivnNxPl1czJYbXimbY3Zh5hCzdyNqQewVx6iNsNh008JsXJ5/yvJQgLgZ
+UR2gWZMGzLc4V2wiqxuLzELt5RoXPehAdAiOLQu/3Fw+u4J/d7NEwpKgpdDGyG/U
+9nV6mjvomcgOdWKblaRAeiXauYy/MgW68kIu4O4SoKWRRmOF2p+tch3aDKw9M89O
+88QhEzbzDsioAxeOAqL7th3bSPZ2fX05xtM2vFK71QFM41q+FOL+062Ev/VJyU4g
+kxK643V+Cxso9CZEVtFfkNnVIGOI2h8knkOiLtbMnCx/hcxuZLm/XvYQxOO/7ScL
+rkHLUuKu/dK2ksDn8yBgaHfVlHkMmVoSll6fKB+UXpPX7xClrGQAFpVUji5oZN0s
++EcMQdcMtsb6LxnwC9XS1ELQ5FQGuJFatwY9RSV3cbwI6kNKaZiB5sDDAaAHX9GU
+U3EA2fm0u+4UFOSSmYTfx/jl0V1NMQ1oOAY9QMqzckMo2y9cepLQ3temQ/k4bNqj
+rYB3POdqS9OoT74UKU8gg9rv01PaFlLHhPKwVc+MjY36aVefbfk1KZzBpm2twUUm
+F0kz4pU3BYj0aSrTeKWaTLjdn4ndGMSe3QMQQ5GUchWCcygTyID8Wx8+eDzPIs/U
+sc++7fQRuPawcd11oQ7wTjWIjr7VnsV8hiHSyMupEad8HuBt8CNtDf/m/hD1LsEf
+0dY8nDGSPvV/ih2YqTfhcac65D4JKKbV5x65aEwM7frYwi9QsB7CK2xLMHnatp2a
+TRcA24VEsaBP2+UNSLyxkOeeuzSCksHLPBWkVfcRbKUeD9x4Dtwf2WsUtYjGzOQ7
+ApLBB4XHe+GPr/i+PmJP4IDoU1Mifbjla8rz2ZuebZgPnyV7nSvkG/FUqUYpa3Ut
+LY0nF/2dDRF0NirbWuB4Mkk/KlxCQ3w8EZFY5u6L/ee23WxbnVOEQJBtKh7/I/UV
+2dGqoVJx2UqT0MpjUCFjx+KjWvaEt+FfmjfRRqQfHLkJlYly/YdeUrGPdGgJNr0C
+csnZkAZmKDo4OVv+wVduHxHfAgMBAAGjUDBOMB0GA1UdDgQWBBRdiMpGc1L++yQc
+MtftoeGuLwJ+PzAfBgNVHSMEGDAWgBRdiMpGc1L++yQcMtftoeGuLwJ+PzAMBgNV
+HRMEBTADAQH/MA0GCSqGSIb3DQEBDQUAA4IEAQBo9lUFyV8jI0IpcQLC7hC0ILxx
+6DsDw/YpMd9lRyujKa//OVJOEO3Z+SalfoLslMPCD1eeJBxgx9/xTMxZUrunOMJu
+Ddxc5RypVwdt6NOUQ3pNYU+Qkp73aZzakm6/i1LQDOxGf1PaZooPqXaKMfyb9CQ+
+M5wR9XsLDAyQPlylft3cWsp7DaPsrcp7Sn5u33TtvCDgfMwbKZrzzmCdAHS52p0A
+czMpDgYxhxCuHPwN6XSAxlrWnfpkOsdKneiVr4aDm1fp61PQg+sOKNCNJCMmUB50
+XFj14qLmvjLERNl2vUfDqoj6DxC9OceioZljzFM2d8/DEC1/YUT8AGYZQt0ISLlq
+QW4e4iIxXxVNKwXvJZMCd3z4XX8SvAOXL0+WrOffgkQQpSr2jBXKFe0BpCUnzVkN
+jw/bVJ89jrqfupExJ6kKTLzI+H2u/7LgZUn9/QlvhWR3IL1nEvCCOPHXTreuUp2U
+KauH7WQU+mzF/K+obzYiaPc53dz0C3JcvWgv5cBbhDUsGsziZLPkR3r5TvpTNF3t
+c3Ky84q7CfOKI+hGN/S+BNSv+TdA5uOG+h8GJ6SAwVpimzguhx2/iRg7OiHmhoy4
+UfsCF/QdoF3cEoSMMzorOIM+szZ+XggJMbtWzIv4NAL2TCKJcpB6t0Uxci6JN6lM
+tnbq78QxeOoJ3D3g6ZQoGvCdKwHcMQunS2MK75j9hckX5hR+0xnH++bI+D3qXaul
+zCOAcMoGpM7WgyzAc3mh9aAJFk1J9OYzpFY34nX2cDMc0xtI2s9p2/8X14ir5suK
+R0rqm3BZewDaQVNtrZCm/sch1I0cN4GomvxZ+2xD43vsZm8QEB2fyTvazg6kW2O9
+G0coUmszwI63f7fVx+wzZZxS24N17lIO36hjBq12SKDz9C3cIOZpPYdcaNxDyiwq
++RojbgUnosJji+xZtyK5Bf1kNB+jNoNT5OrWCXCR62Z5CQ+fAdlz4NPdibYnwscF
+SD8OA2I7UIT42KAuDBEMKVXe4SlhqLzOdqXwZ7h/ZxyUlY+zpwLO9vfLVpqZiavl
+bx+RO7lkvxPGEtM4mjXt5dNx2rgML/lXSE63qaqspYLJ806A3GE0918/b+ZDfvzG
+HLbeqIVtAlXwOGFLdifLvsgFybQ5yriR/yTlHXN/T8K+Q6wPo3uNkKNgUDq0FmzF
+N9UDQ+VFAdwaGPfBox3okGPoD6/HdiokuwZm4mlioHjZc513qhDapS3fJcXV6tu9
+OhIPBJ5NXVw3IVXwB+eskd2W5y8QlHZKBNTwzc/PBqL93QA2PxOFispDtevAuyTq
+OhRConYsMhoLf/9NqhEsyKVhwtYhYrUh0Q+hCiAg+YpjKuE2YJoUNMVyF3dY
+-----END CERTIFICATE-----
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-md5-16384.apk b/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-md5-16384.apk
new file mode 100644
index 0000000..3ce1737
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-md5-16384.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-md5-8192.apk b/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-md5-8192.apk
new file mode 100644
index 0000000..10f4654
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-md5-8192.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha1-16384.apk b/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha1-16384.apk
new file mode 100644
index 0000000..784e569
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha1-16384.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha1-8192.apk b/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha1-8192.apk
new file mode 100644
index 0000000..b8f979d
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha1-8192.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha224-16384.apk b/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha224-16384.apk
new file mode 100644
index 0000000..7656ece
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha224-16384.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha224-8192.apk b/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha224-8192.apk
new file mode 100644
index 0000000..99bcba2
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha224-8192.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha256-16384.apk b/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha256-16384.apk
new file mode 100644
index 0000000..21bf67f
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha256-16384.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha256-8192.apk b/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha256-8192.apk
new file mode 100644
index 0000000..d8630b6
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha256-8192.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha384-16384.apk b/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha384-16384.apk
new file mode 100644
index 0000000..bb0caf0
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha384-16384.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha384-8192.apk b/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha384-8192.apk
new file mode 100644
index 0000000..f0b47f6
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha384-8192.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha512-16384.apk b/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha512-16384.apk
new file mode 100644
index 0000000..8cf9eba
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha512-16384.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha512-8192.apk b/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha512-8192.apk
new file mode 100644
index 0000000..ffa6be1
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v1-only-with-rsa-pkcs1-sha512-8192.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v2-only-with-rsa-pkcs1-sha256-16384.apk b/hostsidetests/appsecurity/res/pkgsigverify/v2-only-with-rsa-pkcs1-sha256-16384.apk
new file mode 100644
index 0000000..a832366
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v2-only-with-rsa-pkcs1-sha256-16384.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v2-only-with-rsa-pkcs1-sha256-8192.apk b/hostsidetests/appsecurity/res/pkgsigverify/v2-only-with-rsa-pkcs1-sha256-8192.apk
new file mode 100644
index 0000000..1c9f131
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v2-only-with-rsa-pkcs1-sha256-8192.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v2-only-with-rsa-pkcs1-sha512-16384.apk b/hostsidetests/appsecurity/res/pkgsigverify/v2-only-with-rsa-pkcs1-sha512-16384.apk
new file mode 100644
index 0000000..2b332b1
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v2-only-with-rsa-pkcs1-sha512-16384.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v2-only-with-rsa-pkcs1-sha512-8192.apk b/hostsidetests/appsecurity/res/pkgsigverify/v2-only-with-rsa-pkcs1-sha512-8192.apk
new file mode 100644
index 0000000..146534e
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v2-only-with-rsa-pkcs1-sha512-8192.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v2-only-with-rsa-pss-sha256-16384.apk b/hostsidetests/appsecurity/res/pkgsigverify/v2-only-with-rsa-pss-sha256-16384.apk
new file mode 100644
index 0000000..a205741
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v2-only-with-rsa-pss-sha256-16384.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v2-only-with-rsa-pss-sha256-8192.apk b/hostsidetests/appsecurity/res/pkgsigverify/v2-only-with-rsa-pss-sha256-8192.apk
new file mode 100644
index 0000000..c879ffe
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v2-only-with-rsa-pss-sha256-8192.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v2-only-with-rsa-pss-sha512-16384.apk b/hostsidetests/appsecurity/res/pkgsigverify/v2-only-with-rsa-pss-sha512-16384.apk
new file mode 100644
index 0000000..d398584
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v2-only-with-rsa-pss-sha512-16384.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v2-only-with-rsa-pss-sha512-8192.apk b/hostsidetests/appsecurity/res/pkgsigverify/v2-only-with-rsa-pss-sha512-8192.apk
new file mode 100644
index 0000000..1bdd017
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v2-only-with-rsa-pss-sha512-8192.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
index e3d5817..f6c6f18 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
@@ -40,8 +40,9 @@
private static final String[] DSA_KEY_NAMES = {"1024", "2048", "3072"};
private static final String[] EC_KEY_NAMES = {"p256", "p384", "p521"};
- private static final String[] RSA_KEY_NAMES = {"1024", "2048", "3072", "4096"};
- private static final String[] RSA_KEY_NAMES_2048_AND_LARGER = {"2048", "3072", "4096"};
+ private static final String[] RSA_KEY_NAMES = {"1024", "2048", "3072", "4096", "8192", "16384"};
+ private static final String[] RSA_KEY_NAMES_2048_AND_LARGER =
+ {"2048", "3072", "4096", "8192", "16384"};
/** Device under test. */
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/WifiTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/WifiTest.java
index c4c02e8..685ad82 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/WifiTest.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/WifiTest.java
@@ -44,7 +44,7 @@
private static final String NETWORK_SSID = "com.android.cts.xwde7ktvh8rmjuhr";
// Time duration to allow before assuming that a WiFi operation failed and ceasing to wait.
- private static final long UPDATE_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(30);
+ private static final long UPDATE_TIMEOUT_MS = TimeUnit.MINUTES.toMillis(5);
private static final long UPDATE_INTERVAL_MS = TimeUnit.SECONDS.toMillis(1);
// Shared WifiManager instance.
diff --git a/libs/runner/Android.mk b/libs/runner/Android.mk
index 9642f53..15f64a3 100644
--- a/libs/runner/Android.mk
+++ b/libs/runner/Android.mk
@@ -16,9 +16,7 @@
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(call all-java-files-under, ../../tests/core/runner/src)
-
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_STATIC_JAVA_LIBRARIES := cts-test-runner
LOCAL_MODULE_TAGS := optional
diff --git a/tests/accessibilityservice/AndroidManifest.xml b/tests/accessibilityservice/AndroidManifest.xml
index 02477e4..227602f 100644
--- a/tests/accessibilityservice/AndroidManifest.xml
+++ b/tests/accessibilityservice/AndroidManifest.xml
@@ -21,7 +21,7 @@
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
- <application android:theme="@android:style/Theme.Material.NoActionBar">
+ <application android:theme="@android:style/Theme.Holo.NoActionBar">
<uses-library android:name="android.test.runner" />
diff --git a/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java b/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
index 9ecdc2d..5c97d5c 100644
--- a/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
@@ -301,7 +301,7 @@
// simulate real scenario (preview runs a bit)
waitForNumResults(previewResultListener, NUM_RESULTS_WAIT);
- stopPreview();
+ stopPreviewAndDrain();
}
mReportLog.addValues("Camera " + id
diff --git a/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java b/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
index 539304c..76c91aa 100644
--- a/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
+++ b/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
@@ -216,12 +216,25 @@
}
/**
- * Stop preview for current camera device.
+ * Stop preview for current camera device by closing the session.
+ * Does _not_ wait for the device to go idle
*/
protected void stopPreview() throws Exception {
+ if (VERBOSE) Log.v(TAG, "Stopping preview");
+ // Stop repeat, wait for captures to complete, and disconnect from surfaces
+ mSession.close();
+ }
+
+ /**
+ * Stop preview for current camera device by closing the session and waiting for it to close,
+ * resulting in an idle device.
+ */
+ protected void stopPreviewAndDrain() throws Exception {
if (VERBOSE) Log.v(TAG, "Stopping preview and waiting for idle");
// Stop repeat, wait for captures to complete, and disconnect from surfaces
mSession.close();
+ mSessionListener.getStateWaiter().waitForState(BlockingSessionCallback.SESSION_CLOSED,
+ /*timeoutMs*/WAIT_FOR_RESULT_TIMEOUT_MS);
}
/**
diff --git a/tests/core/libcore/tests/Android.mk b/tests/core/libcore/tests/Android.mk
index 82ab12e..6429558 100644
--- a/tests/core/libcore/tests/Android.mk
+++ b/tests/core/libcore/tests/Android.mk
@@ -16,6 +16,6 @@
include $(CLEAR_VARS)
LOCAL_PACKAGE_NAME := android.core.tests.libcore.package.tests
-LOCAL_STATIC_JAVA_LIBRARIES := core-tests
+LOCAL_STATIC_JAVA_LIBRARIES := core-tests mockito-target-minus-junit4
LOCAL_JAVA_LANGUAGE_VERSION := 1.8
include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/runner/Android.mk b/tests/core/runner/Android.mk
index 158a1f1..1355512 100644
--- a/tests/core/runner/Android.mk
+++ b/tests/core/runner/Android.mk
@@ -23,12 +23,44 @@
# include this package in the tests target for continuous testing
LOCAL_MODULE_TAGS := tests
-LOCAL_SRC_FILES := $(call all-java-files-under,src)
-
LOCAL_PACKAGE_NAME := android.core.tests.runner
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_STATIC_JAVA_LIBRARIES := cts-test-runner
LOCAL_JAVA_LANGUAGE_VERSION := 1.8
include $(BUILD_CTSCORE_PACKAGE)
+
+#==========================================================
+# Build the core runner.
+#==========================================================
+
+# Build library
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := $(call all-java-files-under,src)
+LOCAL_MODULE := cts-core-test-runner
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ compatibility-device-util \
+ android-support-test \
+ android.test.runner \
+ vogarexpect
+
+LOCAL_JAVA_LANGUAGE_VERSION := 1.8
+
+include $(BUILD_JAVA_LIBRARY)
+
+#==========================================================
+# Build the run listener
+#==========================================================
+
+# Build library
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := $(call all-java-files-under,src/com/android/cts/runner)
+LOCAL_MODULE := cts-test-runner
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
+include $(BUILD_JAVA_LIBRARY)
diff --git a/tests/tests/icu/src/android/icu/cts/AndroidJUnitRunnerConstants.java b/tests/core/runner/src/com/android/cts/core/runner/AndroidJUnitRunnerConstants.java
similarity index 95%
rename from tests/tests/icu/src/android/icu/cts/AndroidJUnitRunnerConstants.java
rename to tests/core/runner/src/com/android/cts/core/runner/AndroidJUnitRunnerConstants.java
index 24d8819..c6c8504 100644
--- a/tests/tests/icu/src/android/icu/cts/AndroidJUnitRunnerConstants.java
+++ b/tests/core/runner/src/com/android/cts/core/runner/AndroidJUnitRunnerConstants.java
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-package android.icu.cts;
+package com.android.cts.core.runner;
import android.support.test.runner.AndroidJUnitRunner;
/**
* Constants used to communicate to and from {@link AndroidJUnitRunner}.
*/
-interface AndroidJUnitRunnerConstants {
+public interface AndroidJUnitRunnerConstants {
/**
* The names of the file containing the names of the tests to run.
@@ -82,5 +82,5 @@
/**
* An identifier for tests run using this class.
*/
- String REPORT_VALUE_ID = "IcuTestRunner";
+ String REPORT_VALUE_ID = "CoreTestRunner";
}
diff --git a/tests/tests/icu/src/android/icu/cts/IcuTestRunner.java b/tests/core/runner/src/com/android/cts/core/runner/CoreTestRunner.java
similarity index 72%
rename from tests/tests/icu/src/android/icu/cts/IcuTestRunner.java
rename to tests/core/runner/src/com/android/cts/core/runner/CoreTestRunner.java
index 51c4999..144e9e2 100644
--- a/tests/tests/icu/src/android/icu/cts/IcuTestRunner.java
+++ b/tests/core/runner/src/com/android/cts/core/runner/CoreTestRunner.java
@@ -14,21 +14,21 @@
* limitations under the License.
*/
-package android.icu.cts;
+package com.android.cts.core.runner;
import android.app.Activity;
import android.app.Instrumentation;
-import android.icu.junit.IcuTestRunnerBuilder;
+import com.android.cts.core.runner.support.ExtendedAndroidRunnerBuilder;
import android.os.Bundle;
import android.os.Debug;
import android.support.test.internal.util.AndroidRunnerParams;
import android.util.Log;
+import com.google.common.base.Splitter;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
@@ -45,22 +45,26 @@
import vogar.ExpectationStore;
import vogar.ModeId;
-import static android.icu.cts.AndroidJUnitRunnerConstants.ARGUMENT_COUNT;
-import static android.icu.cts.AndroidJUnitRunnerConstants.ARGUMENT_DEBUG;
-import static android.icu.cts.AndroidJUnitRunnerConstants.ARGUMENT_LOG_ONLY;
-import static android.icu.cts.AndroidJUnitRunnerConstants.ARGUMENT_TEST_CLASS;
-import static android.icu.cts.AndroidJUnitRunnerConstants.ARGUMENT_TEST_FILE;
+import static com.android.cts.core.runner.AndroidJUnitRunnerConstants.ARGUMENT_COUNT;
+import static com.android.cts.core.runner.AndroidJUnitRunnerConstants.ARGUMENT_DEBUG;
+import static com.android.cts.core.runner.AndroidJUnitRunnerConstants.ARGUMENT_LOG_ONLY;
+import static com.android.cts.core.runner.AndroidJUnitRunnerConstants.ARGUMENT_TEST_CLASS;
+import static com.android.cts.core.runner.AndroidJUnitRunnerConstants.ARGUMENT_TEST_FILE;
/**
* A drop-in replacement for AndroidJUnitTestRunner, which understands the same arguments, and has
- * similar functionality, but runs ICU tests instead of calling the JUnit wrapper.
+ * similar functionality, but can filter by expectations and allows a custom runner-builder to be
+ * provided.
*/
-public final class IcuTestRunner extends Instrumentation {
+public class CoreTestRunner extends Instrumentation {
- public static final String TAG = "IcuTestRunner";
+ public static final String TAG = "LibcoreTestRunner";
- private static final List<String> EXPECTATIONS_PATHS =
- Collections.singletonList("expectations/icu-known-failures.txt");
+ private static final java.lang.String ARGUMENT_ROOT_CLASSES = "core-root-classes";
+
+ private static final String ARGUMENT_EXPECTATIONS = "core-expectations";
+
+ private static final Splitter CLASS_LIST_SPLITTER = Splitter.on(',').trimResults();
/** The args for the runner. */
private Bundle args;
@@ -80,10 +84,10 @@
/**
* The list of tests to run.
*/
- private IcuTestList icuTestList;
+ private TestList testList;
@Override
- public void onCreate(Bundle args) {
+ public void onCreate(final Bundle args) {
super.onCreate(args);
this.args = args;
@@ -102,7 +106,9 @@
this.testCountOnly = args.getBoolean(ARGUMENT_COUNT);
try {
- Set<String> expectationResources = new LinkedHashSet<>(EXPECTATIONS_PATHS);
+ // Get the set of resource names containing the expectations.
+ Set<String> expectationResources = new LinkedHashSet<>(
+ CLASS_LIST_SPLITTER.splitToList(args.getString(ARGUMENT_EXPECTATIONS)));
expectationStore = ExpectationStore.parseResources(
getClass(), expectationResources, ModeId.DEVICE);
} catch (IOException e) {
@@ -131,11 +137,16 @@
}
if (testNameList == null) {
- icuTestList = IcuTestList.rootList(Arrays.asList(
- "android.icu.cts.coverage.TestAll",
- "android.icu.dev.test.TestAll"));
+ String rootClasses = args.getString(ARGUMENT_ROOT_CLASSES);
+ if (rootClasses == null) {
+ throw new IllegalStateException(
+ "No tests specified, neither exclusive list or root class");
+ } else {
+ List<String> roots = CLASS_LIST_SPLITTER.splitToList(rootClasses);
+ testList = TestList.rootList(roots);
+ }
} else {
- icuTestList = IcuTestList.exclusiveList(testNameList);
+ testList = TestList.exclusiveList(testNameList);
}
start();
@@ -157,15 +168,15 @@
Request request;
int totalTestCount;
try {
- RunnerBuilder runnerBuilder = new IcuTestRunnerBuilder(runnerParams);
- Class[] classes = icuTestList.getClassesToRun();
+ RunnerBuilder runnerBuilder = new ExtendedAndroidRunnerBuilder(runnerParams);
+ Class[] classes = testList.getClassesToRun();
Runner suite = new Computer().getSuite(runnerBuilder, classes);
if (suite instanceof Filterable) {
Filterable filterable = (Filterable) suite;
// Filter out all the tests that are expected to fail.
- Filter filter = new IcuTestFilter(icuTestList, expectationStore);
+ Filter filter = new TestFilter(testList, expectationStore);
try {
filterable.filter(filter);
@@ -183,17 +194,18 @@
throw new RuntimeException("Could not create a suite", e);
}
- IcuRunListener icuRunListener = new IcuRunListener(this, runnerParams, totalTestCount);
- core.addListener(icuRunListener);
+ StatusUpdaterRunListener statusUpdaterRunListener =
+ new StatusUpdaterRunListener(this, runnerParams, totalTestCount);
+ core.addListener(statusUpdaterRunListener);
core.run(request);
Bundle results;
if (testCountOnly) {
- results = icuRunListener.getCountResults();
+ results = statusUpdaterRunListener.getCountResults();
Log.d(TAG, "test count only: " + results);
} else {
// Get the final results to send back.
- results = icuRunListener.getFinalResults();
+ results = statusUpdaterRunListener.getFinalResults();
}
Log.d(TAG, "Finished");
diff --git a/tests/tests/icu/src/android/icu/cts/IcuRunListener.java b/tests/core/runner/src/com/android/cts/core/runner/StatusUpdaterRunListener.java
similarity index 92%
rename from tests/tests/icu/src/android/icu/cts/IcuRunListener.java
rename to tests/core/runner/src/com/android/cts/core/runner/StatusUpdaterRunListener.java
index 0a6f355..429ae92 100644
--- a/tests/tests/icu/src/android/icu/cts/IcuRunListener.java
+++ b/tests/core/runner/src/com/android/cts/core/runner/StatusUpdaterRunListener.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.icu.cts;
+package com.android.cts.core.runner;
import android.app.Instrumentation;
import android.os.Bundle;
@@ -30,8 +30,8 @@
import static android.app.Instrumentation.REPORT_KEY_IDENTIFIER;
import static android.app.Instrumentation.REPORT_KEY_STREAMRESULT;
-import static android.icu.cts.AndroidJUnitRunnerConstants.REPORT_KEY_RUNTIME;
-import static android.icu.cts.AndroidJUnitRunnerConstants.REPORT_VALUE_ID;
+import static com.android.cts.core.runner.AndroidJUnitRunnerConstants.REPORT_KEY_RUNTIME;
+import static com.android.cts.core.runner.AndroidJUnitRunnerConstants.REPORT_VALUE_ID;
import static android.test.InstrumentationTestRunner.REPORT_KEY_NAME_CLASS;
import static android.test.InstrumentationTestRunner.REPORT_KEY_NAME_TEST;
import static android.test.InstrumentationTestRunner.REPORT_KEY_NUM_CURRENT;
@@ -47,7 +47,7 @@
* Listens to result of running tests, collates details and sends intermediate status information
* back to the host.
*/
-class IcuRunListener extends RunListener {
+class StatusUpdaterRunListener extends RunListener {
/**
* The {@link Instrumentation} for which this will report information.
@@ -77,7 +77,8 @@
private long testStartTime;
- public IcuRunListener(Instrumentation instrumentation, AndroidRunnerParams runnerParams,
+ public StatusUpdaterRunListener(Instrumentation instrumentation,
+ AndroidRunnerParams runnerParams,
int totalTestCount) {
this.instrumentation = instrumentation;
this.runnerParams = runnerParams;
@@ -135,6 +136,7 @@
} else {
resultStatus = REPORT_VALUE_RESULT_ERROR;
}
+
String information = failure.getTrace();
currentTestResult.putString(REPORT_KEY_STACK, information);
String output = "Error: " + description + "\n" + information;
@@ -165,7 +167,7 @@
public Bundle getFinalResults() {
int totalTests = totalFailures + totalSuccess;
- Log.d(IcuTestRunner.TAG, (runnerParams.isSkipExecution() ? "Skipped " : "Ran ")
+ Log.d(CoreTestRunner.TAG, (runnerParams.isSkipExecution() ? "Skipped " : "Ran ")
+ totalTests + " tests, " + totalSuccess + " passed, " + totalFailures + " failed");
Bundle results = new Bundle();
results.putString(REPORT_KEY_IDENTIFIER, REPORT_VALUE_ID);
@@ -189,7 +191,7 @@
}
public Bundle getCountResults() {
- Log.d(IcuTestRunner.TAG, "Counted " + (totalFailures + totalSuccess) + " tests, "
+ Log.d(CoreTestRunner.TAG, "Counted " + (totalFailures + totalSuccess) + " tests, "
+ totalSuccess + " passed, " + totalFailures + " failed");
Bundle results = new Bundle();
results.putString(REPORT_KEY_IDENTIFIER, REPORT_VALUE_ID);
diff --git a/tests/tests/icu/src/android/icu/cts/IcuTestFilter.java b/tests/core/runner/src/com/android/cts/core/runner/TestFilter.java
similarity index 90%
rename from tests/tests/icu/src/android/icu/cts/IcuTestFilter.java
rename to tests/core/runner/src/com/android/cts/core/runner/TestFilter.java
index 3da2976..8cadbcf 100644
--- a/tests/tests/icu/src/android/icu/cts/IcuTestFilter.java
+++ b/tests/core/runner/src/com/android/cts/core/runner/TestFilter.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.icu.cts;
+package com.android.cts.core.runner;
import android.util.Log;
import java.util.List;
@@ -61,15 +61,15 @@
* {@link ParentRunner}, as that would prevent it from traversing the hierarchy and finding
* the leaf nodes.
*/
-class IcuTestFilter extends Filter {
+class TestFilter extends Filter {
private final ExpectationStore expectationStore;
- private final IcuTestList icuTestList;
+ private final TestList testList;
- public IcuTestFilter(IcuTestList icuTestList, @Nullable ExpectationStore expectationStore) {
+ public TestFilter(TestList testList, @Nullable ExpectationStore expectationStore) {
this.expectationStore = expectationStore;
- this.icuTestList = icuTestList;
+ this.testList = testList;
}
@Override
@@ -84,14 +84,14 @@
String testName = className + "#" + methodName;
// If the test isn't in the list of tests to run then do not run it.
- if (!icuTestList.shouldRunTest(testName)) {
+ if (!testList.shouldRunTest(testName)) {
return false;
}
if (expectationStore != null) {
Expectation expectation = expectationStore.get(testName);
if (expectation.getResult() != Result.SUCCESS) {
- Log.d(IcuTestRunner.TAG, "Excluding test " + description
+ Log.d(CoreTestRunner.TAG, "Excluding test " + testDescription
+ " as it matches expectation: " + expectation);
return false;
}
@@ -126,6 +126,6 @@
@Override
public String describe() {
- return "IcuTestFilter";
+ return "TestFilter";
}
}
diff --git a/tests/tests/icu/src/android/icu/cts/IcuTestList.java b/tests/core/runner/src/com/android/cts/core/runner/TestList.java
similarity index 84%
rename from tests/tests/icu/src/android/icu/cts/IcuTestList.java
rename to tests/core/runner/src/com/android/cts/core/runner/TestList.java
index a9c3c5f..4b0452d 100644
--- a/tests/tests/icu/src/android/icu/cts/IcuTestList.java
+++ b/tests/core/runner/src/com/android/cts/core/runner/TestList.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.icu.cts;
+package com.android.cts.core.runner;
import android.util.Log;
import java.util.ArrayList;
@@ -25,7 +25,7 @@
/**
* A list of the tests to run.
*/
-class IcuTestList {
+class TestList {
/**
* The names of the set of tests to run, if null then all tests should be run.
@@ -35,7 +35,7 @@
private final List<Class<?>> classesToRun;
- public static IcuTestList exclusiveList(List<String> testNameList) {
+ public static TestList exclusiveList(List<String> testNameList) {
Set<String> classNamesToRun = new LinkedHashSet<>();
Set<String> testsToRun = new LinkedHashSet<>(testNameList);
@@ -50,19 +50,19 @@
classNamesToRun.add(className);
}
- Log.d(IcuTestRunner.TAG, "Running only the following tests: " + testsToRun);
- return new IcuTestList(getClasses(classNamesToRun), testsToRun);
+ Log.d(CoreTestRunner.TAG, "Running only the following tests: " + testsToRun);
+ return new TestList(getClasses(classNamesToRun), testsToRun);
}
- public static IcuTestList rootList(List<String> rootList) {
+ public static TestList rootList(List<String> rootList) {
// Run from the root test class.
Set<String> classNamesToRun = new LinkedHashSet<>(rootList);
- Log.d(IcuTestRunner.TAG, "Running all tests rooted at " + classNamesToRun);
+ Log.d(CoreTestRunner.TAG, "Running all tests rooted at " + classNamesToRun);
List<Class<?>> classesToRun1 = getClasses(classNamesToRun);
- return new IcuTestList(classesToRun1, null);
+ return new TestList(classesToRun1, null);
}
private static List<Class<?>> getClasses(Set<String> classNames) {
@@ -83,7 +83,7 @@
* @param testsToRun The exclusive set of tests to run or null if all tests reachable from the
* classes are to be run.
*/
- private IcuTestList(List<Class<?>> classes, Set<String> testsToRun) {
+ private TestList(List<Class<?>> classes, Set<String> testsToRun) {
this.testsToRun = testsToRun;
this.classesToRun = classes;
}
diff --git a/tests/core/runner/src/com/android/cts/core/runner/support/AndroidRunnerBuilder.java b/tests/core/runner/src/com/android/cts/core/runner/support/AndroidRunnerBuilder.java
new file mode 100644
index 0000000..bdb3e57
--- /dev/null
+++ b/tests/core/runner/src/com/android/cts/core/runner/support/AndroidRunnerBuilder.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.core.runner.support;
+
+import android.support.test.internal.runner.junit3.AndroidJUnit3Builder;
+import android.support.test.internal.runner.junit3.AndroidSuiteBuilder;
+import android.support.test.internal.runner.junit4.AndroidAnnotatedBuilder;
+import android.support.test.internal.runner.junit4.AndroidJUnit4Builder;
+import android.support.test.internal.util.AndroidRunnerParams;
+
+import org.junit.internal.builders.AllDefaultPossibilitiesBuilder;
+import org.junit.internal.builders.AnnotatedBuilder;
+import org.junit.internal.builders.IgnoredBuilder;
+import org.junit.internal.builders.JUnit3Builder;
+import org.junit.internal.builders.JUnit4Builder;
+import org.junit.runners.model.RunnerBuilder;
+
+/**
+ * A {@link RunnerBuilder} that can handle all types of tests.
+ */
+// A copy of package private class android.support.test.internal.runner.AndroidRunnerBuilder.
+// Copied here so that it can be extended.
+class AndroidRunnerBuilder extends AllDefaultPossibilitiesBuilder {
+
+ private final AndroidJUnit3Builder mAndroidJUnit3Builder;
+ private final AndroidJUnit4Builder mAndroidJUnit4Builder;
+ private final AndroidSuiteBuilder mAndroidSuiteBuilder;
+ private final AndroidAnnotatedBuilder mAndroidAnnotatedBuilder;
+ // TODO: customize for Android ?
+ private final IgnoredBuilder mIgnoredBuilder;
+
+ /**
+ * @param runnerParams {@link AndroidRunnerParams} that stores common runner parameters
+ */
+ AndroidRunnerBuilder(AndroidRunnerParams runnerParams) {
+ super(true);
+ mAndroidJUnit3Builder = new AndroidJUnit3Builder(runnerParams);
+ mAndroidJUnit4Builder = new AndroidJUnit4Builder(runnerParams);
+ mAndroidSuiteBuilder = new AndroidSuiteBuilder(runnerParams);
+ mAndroidAnnotatedBuilder = new AndroidAnnotatedBuilder(this, runnerParams);
+ mIgnoredBuilder = new IgnoredBuilder();
+ }
+
+ @Override
+ protected JUnit4Builder junit4Builder() {
+ return mAndroidJUnit4Builder;
+ }
+
+ @Override
+ protected JUnit3Builder junit3Builder() {
+ return mAndroidJUnit3Builder;
+ }
+
+ @Override
+ protected AnnotatedBuilder annotatedBuilder() {
+ return mAndroidAnnotatedBuilder;
+ }
+
+ @Override
+ protected IgnoredBuilder ignoredBuilder() {
+ return mIgnoredBuilder;
+ }
+
+ @Override
+ protected RunnerBuilder suiteMethodBuilder() {
+ return mAndroidSuiteBuilder;
+ }
+}
diff --git a/tests/core/runner/src/com/android/cts/core/runner/support/ExtendedAndroidAnnotatedBuilder.java b/tests/core/runner/src/com/android/cts/core/runner/support/ExtendedAndroidAnnotatedBuilder.java
new file mode 100644
index 0000000..05c6623
--- /dev/null
+++ b/tests/core/runner/src/com/android/cts/core/runner/support/ExtendedAndroidAnnotatedBuilder.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.core.runner.support;
+
+import android.support.test.internal.runner.junit4.AndroidAnnotatedBuilder;
+import android.support.test.internal.util.AndroidRunnerParams;
+import android.support.test.runner.AndroidJUnit4;
+import junit.framework.TestCase;
+import org.junit.runner.RunWith;
+import org.junit.runner.Runner;
+import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.JUnit4;
+import org.junit.runners.model.RunnerBuilder;
+
+/**
+ * Extends {@link AndroidAnnotatedBuilder} to add support for passing the
+ * {@link AndroidRunnerParams} object to the constructor of any {@link RunnerBuilder}
+ * implementation that is not a {@link BlockJUnit4ClassRunner}.
+ *
+ * <p>If {@link AndroidRunnerParams#isSkipExecution()} is {@code true} the super class will create
+ * a {@link RunnerBuilder} that will fire appropriate events as if the tests are being run but will
+ * not actually run the test. Unfortunately, when it does that it appears to assume that the runner
+ * extends {@link BlockJUnit4ClassRunner}, returns a skipping {@link RunnerBuilder} appropriate for
+ * that and ignores the actual {@code runnerClass}. That is a problem because it will not work for
+ * custom {@link RunnerBuilder} instances that do not extend {@link BlockJUnit4ClassRunner}.
+ *
+ * <p>Therefore, when skipping execution this does some additional checks to make sure that the
+ * {@code runnerClass} does extend {@link BlockJUnit4ClassRunner} before calling the overridden
+ * method.
+ *
+ * <p>It then attempts to construct a {@link RunnerBuilder} by calling the constructor with the
+ * signature {@code <init>(Class, AndroidRunnerParams)}. If that doesn't exist it falls back to
+ * the overridden behavior.
+ */
+class ExtendedAndroidAnnotatedBuilder extends AndroidAnnotatedBuilder {
+
+ private final AndroidRunnerParams runnerParams;
+
+ public ExtendedAndroidAnnotatedBuilder(RunnerBuilder suiteBuilder,
+ AndroidRunnerParams runnerParams) {
+ super(suiteBuilder, runnerParams);
+ this.runnerParams = runnerParams;
+ }
+
+ @Override
+ public Runner runnerForClass(Class<?> testClass) throws Exception {
+
+ RunWith annotation = testClass.getAnnotation(RunWith.class);
+ if (annotation != null) {
+ Class<? extends Runner> runnerClass = annotation.value();
+
+ // If the runner is expected to skip execution and it is a JUnit4, AndroidJUnit4 or
+ // a JUnit3 test class then return a special skipping runner.
+ if (runnerParams.isSkipExecution()) {
+ if (runnerClass == AndroidJUnit4.class || runnerClass == JUnit4.class
+ || TestCase.class.isAssignableFrom(testClass)) {
+ return super.runnerForClass(testClass);
+ }
+ }
+
+ try {
+ // try to build an AndroidJUnit4 runner
+ Runner runner = buildAndroidRunner(runnerClass, testClass);
+ if (runner != null) {
+ return runner;
+ }
+ } catch (NoSuchMethodException e) {
+ // let the super class handle the error for us and throw an InitializationError
+ // exception.
+ return super.buildRunner(runnerClass, testClass);
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/tests/core/runner/src/com/android/cts/core/runner/support/ExtendedAndroidRunnerBuilder.java b/tests/core/runner/src/com/android/cts/core/runner/support/ExtendedAndroidRunnerBuilder.java
new file mode 100644
index 0000000..ed16318
--- /dev/null
+++ b/tests/core/runner/src/com/android/cts/core/runner/support/ExtendedAndroidRunnerBuilder.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.core.runner.support;
+
+import android.support.test.internal.runner.junit4.AndroidAnnotatedBuilder;
+import android.support.test.internal.util.AndroidRunnerParams;
+import org.junit.internal.builders.AnnotatedBuilder;
+import org.junit.runners.model.RunnerBuilder;
+
+/**
+ * Extends {@link AndroidRunnerBuilder} in order to provide alternate {@link RunnerBuilder}
+ * implementations.
+ */
+public class ExtendedAndroidRunnerBuilder extends AndroidRunnerBuilder {
+
+ private final AndroidAnnotatedBuilder mAndroidAnnotatedBuilder;
+
+ /**
+ * @param runnerParams {@link AndroidRunnerParams} that stores common runner parameters
+ */
+ public ExtendedAndroidRunnerBuilder(AndroidRunnerParams runnerParams) {
+ super(runnerParams);
+ mAndroidAnnotatedBuilder = new ExtendedAndroidAnnotatedBuilder(this, runnerParams);
+ }
+
+ @Override
+ protected AnnotatedBuilder annotatedBuilder() {
+ return mAndroidAnnotatedBuilder;
+ }
+}
diff --git a/tests/core/runner/src/com/android/cts/core/runner/support/package-info.java b/tests/core/runner/src/com/android/cts/core/runner/support/package-info.java
new file mode 100644
index 0000000..3ccec3c
--- /dev/null
+++ b/tests/core/runner/src/com/android/cts/core/runner/support/package-info.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Contains all the changes needed to the {@code android.support.test.internal.runner} classes.
+ *
+ * <p>As its name suggests {@code android.support.test.internal.runner} are internal classes that
+ * are not designed to be extended from outside those packages. This package encapsulates all the
+ * workarounds needed to overcome that limitation, from duplicating classes to using reflection.
+ * The intention is that these changes are temporary and they (or a better equivalent) will be
+ * quickly integrated into the internal classes.
+ */
+package com.android.cts.core.runner.support;
diff --git a/tests/tests/app/Android.mk b/tests/tests/app/Android.mk
new file mode 100644
index 0000000..08201a6
--- /dev/null
+++ b/tests/tests/app/Android.mk
@@ -0,0 +1,36 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsAndroidAppTestCases
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := optional
+
+# and when built explicitly put it in the data partition
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/app/AndroidManifest.xml b/tests/tests/app/AndroidManifest.xml
new file mode 100644
index 0000000..be903e3
--- /dev/null
+++ b/tests/tests/app/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.app.cts">
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+
+ <activity android:name=".ApplyOverrideConfigurationActivity"
+ android:configChanges="orientation|screenSize" />
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.app.cts"
+ android:label="CTS tests of android.app">
+ <meta-data android:name="listener"
+ android:value="com.android.cts.runner.CtsTestRunListener" />
+ </instrumentation>
+
+</manifest>
+
diff --git a/tests/tests/app/AndroidTest.xml b/tests/tests/app/AndroidTest.xml
new file mode 100644
index 0000000..739e0ba
--- /dev/null
+++ b/tests/tests/app/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Configuration for app Tests">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsAndroidAppTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.app.cts" />
+ <option name="runtime-hint" value="1s" />
+ </test>
+</configuration>
diff --git a/tests/tests/app/src/android/app/cts/ApplyOverrideConfigurationActivity.java b/tests/tests/app/src/android/app/cts/ApplyOverrideConfigurationActivity.java
new file mode 100644
index 0000000..305d0a8
--- /dev/null
+++ b/tests/tests/app/src/android/app/cts/ApplyOverrideConfigurationActivity.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package android.app.cts;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Configuration;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Future;
+
+public class ApplyOverrideConfigurationActivity extends Activity {
+ public static final int OVERRIDE_SMALLEST_WIDTH = 99999;
+
+ private CompletableFuture<Configuration> mOnConfigurationChangedFuture = null;
+
+ @Override
+ protected void attachBaseContext(Context newBase) {
+ super.attachBaseContext(newBase);
+
+ final Configuration overrideConfig = new Configuration();
+ overrideConfig.smallestScreenWidthDp = OVERRIDE_SMALLEST_WIDTH;
+ applyOverrideConfiguration(overrideConfig);
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+
+ synchronized (this) {
+ if (mOnConfigurationChangedFuture != null) {
+ mOnConfigurationChangedFuture.complete(new Configuration(newConfig));
+ mOnConfigurationChangedFuture = null;
+ }
+ }
+ }
+
+ /**
+ * Hands back a Future that will be completed when onConfigurationChanged() is called.
+ * It will only report a single call to onConfigurationChanged(). Subsequent calls can be
+ * captured by calling this method again. Calling this method will cancel all past
+ * Futures received from this method.
+ * @return A Future that completes with the configuration passed in to onConfigurationChanged().
+ */
+ public synchronized Future<Configuration> watchForSingleOnConfigurationChangedCallback() {
+ if (mOnConfigurationChangedFuture != null) {
+ mOnConfigurationChangedFuture.cancel(true);
+ }
+
+ mOnConfigurationChangedFuture = new CompletableFuture<>();
+ return mOnConfigurationChangedFuture;
+ }
+}
diff --git a/tests/tests/app/src/android/app/cts/ApplyOverrideConfigurationTest.java b/tests/tests/app/src/android/app/cts/ApplyOverrideConfigurationTest.java
new file mode 100644
index 0000000..a8f1473
--- /dev/null
+++ b/tests/tests/app/src/android/app/cts/ApplyOverrideConfigurationTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package android.app.cts;
+
+import android.app.UiAutomation;
+import android.content.res.Configuration;
+import android.support.test.filters.SmallTest;
+import android.test.ActivityInstrumentationTestCase2;
+
+import java.util.concurrent.Future;
+
+/**
+ * Tests the {@link android.view.ContextThemeWrapper#applyOverrideConfiguration(Configuration)}
+ * method and how it affects the Activity's resources and lifecycle callbacks.
+ */
+public class ApplyOverrideConfigurationTest extends
+ ActivityInstrumentationTestCase2<ApplyOverrideConfigurationActivity> {
+ public ApplyOverrideConfigurationTest() {
+ super(ApplyOverrideConfigurationActivity.class);
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ getInstrumentation().getUiAutomation().setRotation(UiAutomation.ROTATION_FREEZE_0);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ getInstrumentation().getUiAutomation().setRotation(UiAutomation.ROTATION_UNFREEZE);
+ super.tearDown();
+ }
+
+ @SmallTest
+ public void testOverriddenConfigurationIsPassedIntoCallback() throws Exception {
+ final Configuration config = getActivity().getResources().getConfiguration();
+ final int originalOrientation = config.orientation;
+ assertEquals(ApplyOverrideConfigurationActivity.OVERRIDE_SMALLEST_WIDTH,
+ config.smallestScreenWidthDp);
+
+ Future<Configuration> callback =
+ getActivity().watchForSingleOnConfigurationChangedCallback();
+
+ getInstrumentation().getUiAutomation().setRotation(UiAutomation.ROTATION_FREEZE_90);
+
+ final Configuration callbackConfig = callback.get();
+ assertNotNull(callbackConfig);
+
+ final Configuration newConfig = getActivity().getResources().getConfiguration();
+ assertTrue(newConfig.orientation != originalOrientation);
+ assertEquals(ApplyOverrideConfigurationActivity.OVERRIDE_SMALLEST_WIDTH,
+ newConfig.smallestScreenWidthDp);
+
+ assertEquals(newConfig, callbackConfig);
+ }
+}
diff --git a/tests/tests/content/src/android/content/cts/ContextTest.java b/tests/tests/content/src/android/content/cts/ContextTest.java
index 4cb85cc..0d9c56d 100644
--- a/tests/tests/content/src/android/content/cts/ContextTest.java
+++ b/tests/tests/content/src/android/content/cts/ContextTest.java
@@ -27,15 +27,19 @@
import android.database.sqlite.SQLiteDatabase;
import android.test.AndroidTestCase;
import android.util.AttributeSet;
+import android.util.Log;
import android.util.Xml;
import android.view.WindowManager;
import org.xmlpull.v1.XmlPullParserException;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
public class ContextTest extends AndroidTestCase {
+ private static final String TAG = "ContextTest";
+
private Context mContext;
@Override
@@ -303,6 +307,44 @@
assertEquals(0xffffff00, color);
}
+ /**
+ * Developers have come to expect at least ext4-style filename behavior, so
+ * verify that the underlying filesystem supports them.
+ */
+ public void testFilenames() throws Exception {
+ final File base = mContext.getFilesDir();
+ assertValidFile(new File(base, "foo"));
+ assertValidFile(new File(base, ".bar"));
+ assertValidFile(new File(base, "foo.bar"));
+ assertValidFile(new File(base, "\u2603"));
+ assertValidFile(new File(base, "\uD83D\uDCA9"));
+
+ final int pid = android.os.Process.myPid();
+ final StringBuilder sb = new StringBuilder(255);
+ while (sb.length() <= 255) {
+ sb.append(pid);
+ sb.append(mContext.getPackageName());
+ }
+ sb.setLength(255);
+
+ final String longName = sb.toString();
+ final File longDir = new File(base, longName);
+ assertValidFile(longDir);
+ longDir.mkdir();
+ final File longFile = new File(longDir, longName);
+ assertValidFile(longFile);
+ }
+
+ private void assertValidFile(File file) throws Exception {
+ Log.d(TAG, "Checking " + file);
+ assertTrue("Failed to create " + file, file.createNewFile());
+ assertTrue("Doesn't exist after create " + file, file.exists());
+ assertTrue("Failed to delete after create " + file, file.delete());
+ new FileOutputStream(file).close();
+ assertTrue("Doesn't exist after stream " + file, file.exists());
+ assertTrue("Failed to delete after stream " + file, file.delete());
+ }
+
private AttributeSet getAttributeSet(int resourceId) {
final XmlResourceParser parser = getContext().getResources().getXml(
resourceId);
diff --git a/tests/tests/icu/Android.mk b/tests/tests/icu/Android.mk
index 39a4b53..6f183d5 100644
--- a/tests/tests/icu/Android.mk
+++ b/tests/tests/icu/Android.mk
@@ -31,9 +31,7 @@
# The aim of this package is to run tests against the implementation in use by
# the current android system.
LOCAL_STATIC_JAVA_LIBRARIES := \
- compatibility-device-util \
- android-support-test \
- vogarexpect \
+ cts-core-test-runner \
android-icu4j-tests
# Tag this module as a cts test artifact
diff --git a/tests/tests/icu/AndroidManifest.xml b/tests/tests/icu/AndroidManifest.xml
index 7d99c0a..c743375 100644
--- a/tests/tests/icu/AndroidManifest.xml
+++ b/tests/tests/icu/AndroidManifest.xml
@@ -22,7 +22,7 @@
<uses-library android:name="android.test.runner" />
</application>
- <instrumentation android:name="android.icu.cts.IcuTestRunner"
+ <instrumentation android:name="com.android.cts.core.runner.CoreTestRunner"
android:targetPackage="android.icu.cts"
- android:label="ICU4J library tests."/>
+ android:label="CTS Repackaged ICU4J library tests."/>
</manifest>
diff --git a/tests/tests/icu/AndroidTest.xml b/tests/tests/icu/AndroidTest.xml
index 18c95cd..769b789 100644
--- a/tests/tests/icu/AndroidTest.xml
+++ b/tests/tests/icu/AndroidTest.xml
@@ -18,8 +18,13 @@
<option name="test-file-name" value="CtsIcuTestCases.apk" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="runner" value="android.icu.cts.IcuTestRunner" /><!-- override AJUR -->
+ <!-- override AJUR -->
+ <option name="runner" value="com.android.cts.core.runner.CoreTestRunner" />
<option name="package" value="android.icu.cts" />
+ <option name="instrumentation-arg" key="core-root-classes"
+ value="android.icu.cts.coverage.TestAll,android.icu.dev.test.TestAll" />
+ <option name="instrumentation-arg" key="core-expectations"
+ value="/android/icu/cts/expectations/icu-known-failures.txt" />
<option name="runtime-hint" value="30m19s" />
</test>
</configuration>
diff --git a/tests/tests/location/src/android/location/cts/GnssMeasurementRegistrationTest.java b/tests/tests/location/src/android/location/cts/GnssMeasurementRegistrationTest.java
index 42e555d..d3a310e 100644
--- a/tests/tests/location/src/android/location/cts/GnssMeasurementRegistrationTest.java
+++ b/tests/tests/location/src/android/location/cts/GnssMeasurementRegistrationTest.java
@@ -92,7 +92,7 @@
mMeasurementListener = new TestGnssMeasurementListener(TAG, GPS_EVENTS_COUNT);
mTestLocationManager.registerGnssMeasurementCallback(mMeasurementListener);
- assertTrue(mMeasurementListener.await());
+ mMeasurementListener.await();
if (!mMeasurementListener.verifyState()) {
return;
}
@@ -113,8 +113,7 @@
mTestLocationManager.requestLocationUpdates(mLocationListener);
// Wait for location updates
- assertTrue(mLocationListener.await());
-
+ mLocationListener.await();
Log.i(TAG, "Location received = " + mLocationListener.isLocationReceived());
// Register for Gps Status updates
@@ -122,8 +121,7 @@
mTestLocationManager.addGpsStatusListener(mGpsStatusListener);
// wait for Gps Status updates
- assertTrue(mGpsStatusListener.await());
-
+ mGpsStatusListener.await();
if (!mGpsStatusListener.isGpsStatusReceived()) {
// Skip the Test. No Satellites are visible. Device may be Indoor
Log.i(TAG, "No Satellites are visible. Device may be Indoor. Skipping Test.");
diff --git a/tests/tests/location/src/android/location/cts/GnssMeasurementWhenNoLocationTest.java b/tests/tests/location/src/android/location/cts/GnssMeasurementWhenNoLocationTest.java
index b3cb0ab..6752a34 100644
--- a/tests/tests/location/src/android/location/cts/GnssMeasurementWhenNoLocationTest.java
+++ b/tests/tests/location/src/android/location/cts/GnssMeasurementWhenNoLocationTest.java
@@ -115,7 +115,7 @@
mTestLocationManager.requestLocationUpdates(mLocationListener);
// Wait for Gps Status updates.
- assertTrue(mGpsStatusListener.await());
+ mGpsStatusListener.await();
if (!mMeasurementListener.verifyState()) {
return;
}
diff --git a/tests/tests/location/src/android/location/cts/GnssNavigationMessageRegistrationTest.java b/tests/tests/location/src/android/location/cts/GnssNavigationMessageRegistrationTest.java
index 4b87919..0b40d53 100644
--- a/tests/tests/location/src/android/location/cts/GnssNavigationMessageRegistrationTest.java
+++ b/tests/tests/location/src/android/location/cts/GnssNavigationMessageRegistrationTest.java
@@ -93,7 +93,7 @@
new TestGnssNavigationMessageListener(TAG, EVENTS_COUNT);
mTestLocationManager.registerGnssNavigationMessageCallback(mTestGnssNavigationMessageListener);
- assertTrue(mTestGnssNavigationMessageListener.await());
+ mTestGnssNavigationMessageListener.await();
if (!mTestGnssNavigationMessageListener.verifyState()) {
return;
}
@@ -116,8 +116,7 @@
mTestLocationManager.requestLocationUpdates(mLocationListener);
// Wait for location updates
- assertTrue(mLocationListener.await());
-
+ mLocationListener.await();
Log.i(TAG, "Location received = " + mLocationListener.isLocationReceived());
// Register for Gps Status updates
@@ -125,8 +124,7 @@
mTestLocationManager.addGpsStatusListener(mGpsStatusListener);
// Wait for Gps Status updates
- assertTrue(mGpsStatusListener.await());
-
+ mGpsStatusListener.await();
if (!mGpsStatusListener.isGpsStatusReceived()) {
// Skip the Test. No Satellites are visible. Device may be Indoor
Log.i(TAG, "No Satellites are visible. Device may be Indoor. Skipping Test.");
diff --git a/tests/tests/location/src/android/location/cts/GnssNavigationMessageTest.java b/tests/tests/location/src/android/location/cts/GnssNavigationMessageTest.java
index 262232e..032c090 100644
--- a/tests/tests/location/src/android/location/cts/GnssNavigationMessageTest.java
+++ b/tests/tests/location/src/android/location/cts/GnssNavigationMessageTest.java
@@ -77,7 +77,7 @@
new TestGnssNavigationMessageListener(TAG, EVENTS_COUNT);
mTestLocationManager.registerGnssNavigationMessageCallback(mTestGnssNavigationMessageListener);
- assertTrue(mTestGnssNavigationMessageListener.await());
+ mTestGnssNavigationMessageListener.await();
if (!mTestGnssNavigationMessageListener.verifyState()) {
return;
}
diff --git a/tests/tests/location/src/android/location/cts/TestUtils.java b/tests/tests/location/src/android/location/cts/TestUtils.java
index 61f63d9..82d644e 100644
--- a/tests/tests/location/src/android/location/cts/TestUtils.java
+++ b/tests/tests/location/src/android/location/cts/TestUtils.java
@@ -22,7 +22,7 @@
public class TestUtils {
private static final long STANDARD_WAIT_TIME_MS = 50;
private static final long STANDARD_SLEEP_TIME_MS = 50;
- private static final long STANDARD_WAIT_TIME_ROUNDS = 3000;
+ private static final long STANDARD_WAIT_TIME_ROUNDS = 1200;
public static boolean waitFor(CountDownLatch latch) throws InterruptedException {
// Since late 2014, if the main thread has been occupied for long enough, Android will
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
index 1d0ab26..4eaefc3 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
@@ -688,55 +688,63 @@
}
private void testGapless(int resid1, int resid2) throws Exception {
-
- MediaPlayer mp1 = new MediaPlayer();
- mp1.setAudioStreamType(AudioManager.STREAM_MUSIC);
+ MediaPlayer mp1 = null;
+ MediaPlayer mp2 = null;
+ AudioEffect vc = null;
+ Visualizer vis = null;
+ AudioManager am = null;
+ int oldRingerMode = Integer.MIN_VALUE;
+ int oldVolume = Integer.MIN_VALUE;
try {
+ Utils.toggleNotificationPolicyAccess(
+ mContext.getPackageName(), getInstrumentation(), true /* on */);
+
+ mp1 = new MediaPlayer();
+ mp1.setAudioStreamType(AudioManager.STREAM_MUSIC);
+
AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(resid1);
mp1.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
afd.close();
mp1.prepare();
- } catch (Exception e) {
- assertTrue(false);
- }
- int session = mp1.getAudioSessionId();
- MediaPlayer mp2 = new MediaPlayer();
- mp2.setAudioSessionId(session);
- mp2.setAudioStreamType(AudioManager.STREAM_MUSIC);
- try {
- AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(resid2);
+ int session = mp1.getAudioSessionId();
+
+ mp2 = new MediaPlayer();
+ mp2.setAudioSessionId(session);
+ mp2.setAudioStreamType(AudioManager.STREAM_MUSIC);
+
+ afd = mContext.getResources().openRawResourceFd(resid2);
mp2.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
afd.close();
mp2.prepare();
- } catch (Exception e) {
- assertTrue(false);
- }
- // creating a volume controller on output mix ensures that ro.audio.silent mutes
- // audio after the effects and not before
- AudioEffect vc = new AudioEffect(
+
+ // creating a volume controller on output mix ensures that ro.audio.silent mutes
+ // audio after the effects and not before
+ vc = new AudioEffect(
AudioEffect.EFFECT_TYPE_NULL,
UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"),
0,
session);
- vc.setEnabled(true);
- int captureintervalms = mp1.getDuration() + mp2.getDuration() - 2000;
- int size = 256;
- int[] range = Visualizer.getCaptureSizeRange();
- if (size < range[0]) {
- size = range[0];
- }
- if (size > range[1]) {
- size = range[1];
- }
- byte [] vizdata = new byte[size];
- Visualizer vis = new Visualizer(session);
- AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
- int oldRingerMode = am.getRingerMode();
- am.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
- int oldvolume = am.getStreamVolume(AudioManager.STREAM_MUSIC);
- am.setStreamVolume(AudioManager.STREAM_MUSIC, 1, 0);
- try {
+ vc.setEnabled(true);
+ int captureintervalms = mp1.getDuration() + mp2.getDuration() - 2000;
+ int size = 256;
+ int[] range = Visualizer.getCaptureSizeRange();
+ if (size < range[0]) {
+ size = range[0];
+ }
+ if (size > range[1]) {
+ size = range[1];
+ }
+ byte[] vizdata = new byte[size];
+
+ vis = new Visualizer(session);
+ am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+ oldRingerMode = am.getRingerMode();
+ // make sure we aren't in silent mode
+ am.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
+ oldVolume = am.getStreamVolume(AudioManager.STREAM_MUSIC);
+ am.setStreamVolume(AudioManager.STREAM_MUSIC, 1, 0);
+
assertEquals("setCaptureSize failed",
Visualizer.SUCCESS, vis.setCaptureSize(vizdata.length));
assertEquals("setEnabled failed", Visualizer.SUCCESS, vis.setEnabled(true));
@@ -770,12 +778,26 @@
first = false;
}
} finally {
- mp1.release();
- mp2.release();
- vis.release();
- vc.release();
- am.setRingerMode(oldRingerMode);
- am.setStreamVolume(AudioManager.STREAM_MUSIC, oldvolume, 0);
+ if (mp1 != null) {
+ mp1.release();
+ }
+ if (mp2 != null) {
+ mp2.release();
+ }
+ if (vis != null) {
+ vis.release();
+ }
+ if (vc != null) {
+ vc.release();
+ }
+ if (oldRingerMode != Integer.MIN_VALUE) {
+ am.setRingerMode(oldRingerMode);
+ }
+ if (oldVolume != Integer.MIN_VALUE) {
+ am.setStreamVolume(AudioManager.STREAM_MUSIC, oldVolume, 0);
+ }
+ Utils.toggleNotificationPolicyAccess(
+ mContext.getPackageName(), getInstrumentation(), false /* on == false */);
}
}
diff --git a/tests/tests/media/src/android/media/cts/MediaScannerConnectionTest.java b/tests/tests/media/src/android/media/cts/MediaScannerConnectionTest.java
index 0272298..952e03f 100644
--- a/tests/tests/media/src/android/media/cts/MediaScannerConnectionTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaScannerConnectionTest.java
@@ -48,10 +48,10 @@
FileCopyHelper copier = new FileCopyHelper(mContext);
String fileName = "test" + System.currentTimeMillis();
- copier.copy(R.raw.testmp3, fileName);
-
- File dir = getContext().getFilesDir();
+ File dir = getContext().getExternalFilesDir(null);
mMediaFile = new File(dir, fileName);
+ copier.copyToExternalStorage(R.raw.testmp3, mMediaFile);
+
assertTrue(mMediaFile.exists());
}
diff --git a/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java
index 9a99c22..6ed4368 100644
--- a/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -265,13 +265,16 @@
}
// We will register for a WIFI network being available or lost.
- NetworkRequest request = new NetworkRequest.Builder()
+ final NetworkRequest request = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.build();
- TestNetworkCallback callback = new TestNetworkCallback();
+ final TestNetworkCallback callback = new TestNetworkCallback();
mCm.registerNetworkCallback(request, callback);
- boolean previousWifiEnabledState = mWifiManager.isWifiEnabled();
+ final TestNetworkCallback defaultTrackingCallback = new TestNetworkCallback();
+ mCm.registerDefaultNetworkCallback(defaultTrackingCallback);
+
+ final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled();
try {
// Make sure WiFi is connected to an access point to start with.
@@ -284,12 +287,16 @@
// is registered.
assertTrue("Did not receive NetworkCallback.onAvailable for TRANSPORT_WIFI",
callback.waitForAvailable());
+
+ assertTrue("Did not receive NetworkCallback.onAvailable for any default network",
+ defaultTrackingCallback.waitForAvailable());
} catch (InterruptedException e) {
fail("Broadcast receiver or NetworkCallback wait was interrupted.");
} finally {
mCm.unregisterNetworkCallback(callback);
+ mCm.unregisterNetworkCallback(defaultTrackingCallback);
- // Return WiFI to its original enabled/disabled state.
+ // Return WiFi to its original enabled/disabled state.
if (!previousWifiEnabledState) {
disconnectFromWifi();
}
@@ -327,7 +334,7 @@
.build();
mCm.registerNetworkCallback(request, pendingIntent);
- boolean previousWifiEnabledState = mWifiManager.isWifiEnabled();
+ final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled();
try {
// Make sure WiFi is connected to an access point to start with.
@@ -347,7 +354,7 @@
pendingIntent.cancel();
mContext.unregisterReceiver(receiver);
- // Return WiFI to its original enabled/disabled state.
+ // Return WiFi to its original enabled/disabled state.
if (!previousWifiEnabledState) {
disconnectFromWifi();
}
diff --git a/tests/tests/os/src/android/os/cts/BuildTest.java b/tests/tests/os/src/android/os/cts/BuildTest.java
index 26b07f1..a0446bf 100644
--- a/tests/tests/os/src/android/os/cts/BuildTest.java
+++ b/tests/tests/os/src/android/os/cts/BuildTest.java
@@ -38,15 +38,15 @@
/** Tests that check the values of {@link Build#CPU_ABI} and {@link Build#CPU_ABI2}. */
public void testCpuAbi() throws Exception {
- testCpuAbiCommon();
+ runTestCpuAbiCommon();
if (VMRuntime.getRuntime().is64Bit()) {
- testCpuAbi64();
+ runTestCpuAbi64();
} else {
- testCpuAbi32();
+ runTestCpuAbi32();
}
}
- private void testCpuAbiCommon() throws Exception {
+ private void runTestCpuAbiCommon() throws Exception {
// The build property must match Build.SUPPORTED_ABIS exactly.
final String[] abiListProperty = getStringList(RO_PRODUCT_CPU_ABILIST);
assertEquals(Arrays.toString(abiListProperty), Arrays.toString(Build.SUPPORTED_ABIS));
@@ -75,7 +75,7 @@
}
}
- private void testCpuAbi32() throws Exception {
+ private void runTestCpuAbi32() throws Exception {
List<String> abi32 = Arrays.asList(Build.SUPPORTED_32_BIT_ABIS);
assertTrue(abi32.contains(Build.CPU_ABI));
@@ -84,7 +84,7 @@
}
}
- private void testCpuAbi64() {
+ private void runTestCpuAbi64() {
List<String> abi64 = Arrays.asList(Build.SUPPORTED_64_BIT_ABIS);
assertTrue(abi64.contains(Build.CPU_ABI));
diff --git a/tests/tests/provider/src/android/provider/cts/BlockedNumberBackupRestoreTest.java b/tests/tests/provider/src/android/provider/cts/BlockedNumberBackupRestoreTest.java
index 5ea4caf..adf558b 100644
--- a/tests/tests/provider/src/android/provider/cts/BlockedNumberBackupRestoreTest.java
+++ b/tests/tests/provider/src/android/provider/cts/BlockedNumberBackupRestoreTest.java
@@ -42,6 +42,7 @@
private Context mContext;
private UiAutomation mUiAutomation;
private String mOldTransport;
+ private boolean mOldBackupEnabled;
private boolean mHasFeature;
@Override
@@ -59,6 +60,7 @@
mOldTransport = ProviderTestUtils.setBackupTransport(
LOCAL_BACKUP_COMPONENT, mUiAutomation);
+ mOldBackupEnabled = ProviderTestUtils.setBackupEnabled(true, mUiAutomation);
clearBlockedNumbers();
wipeBackup();
}
@@ -69,6 +71,7 @@
if (mHasFeature) {
wipeBackup();
clearBlockedNumbers();
+ ProviderTestUtils.setBackupEnabled(mOldBackupEnabled, mUiAutomation);
ProviderTestUtils.setBackupTransport(mOldTransport, mUiAutomation);
ProviderTestUtils.setDefaultSmsApp(false, mContext.getPackageName(), mUiAutomation);
}
diff --git a/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java b/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java
index 874a0a7..e2ed68d 100644
--- a/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java
+++ b/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java
@@ -34,7 +34,9 @@
*/
public class ProviderTestUtils {
- static final int BACKUP_TIMEOUT_MILLIS = 4000;
+ private static final int BACKUP_TIMEOUT_MILLIS = 4000;
+ private static final Pattern BMGR_ENABLED_PATTERN = Pattern.compile(
+ "^Backup Manager currently (enabled|disabled)$");
static void setDefaultSmsApp(boolean setToSmsApp, String packageName, UiAutomation uiAutomation)
throws Exception {
@@ -73,6 +75,22 @@
}
}
+ static boolean setBackupEnabled(boolean enable, UiAutomation uiAutomation) throws Exception {
+ // Check to see the previous state of the backup service
+ boolean previouslyEnabled = false;
+ String output = executeShellCommand("bmgr enabled", uiAutomation);
+ Matcher matcher = BMGR_ENABLED_PATTERN.matcher(output.trim());
+ if (matcher.find()) {
+ previouslyEnabled = "enabled".equals(matcher.group(1));
+ } else {
+ throw new RuntimeException("Backup output format changed. No longer matches"
+ + " expected regex: " + BMGR_ENABLED_PATTERN + "\nactual: '" + output + "'");
+ }
+
+ executeShellCommand("bmgr enable " + enable, uiAutomation);
+ return previouslyEnabled;
+ }
+
static boolean hasBackupTransport(String transport, UiAutomation uiAutomation)
throws Exception {
String output = executeShellCommand("bmgr list transports", uiAutomation);
diff --git a/tests/tests/provider/src/android/provider/cts/SmsBackupRestoreTest.java b/tests/tests/provider/src/android/provider/cts/SmsBackupRestoreTest.java
index f5e3033..fad1019 100644
--- a/tests/tests/provider/src/android/provider/cts/SmsBackupRestoreTest.java
+++ b/tests/tests/provider/src/android/provider/cts/SmsBackupRestoreTest.java
@@ -24,6 +24,7 @@
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.provider.BaseColumns;
@@ -65,6 +66,8 @@
private ContentResolver mContentResolver;
private UiAutomation mUiAutomation;
private String mOldTransport;
+ private boolean mOldBackupEnabled;
+ private boolean mHasFeature;
@Override
protected void setUp() throws Exception {
@@ -74,21 +77,35 @@
mContext = getInstrumentation().getContext();
mContentResolver = mContext.getContentResolver();
mUiAutomation = getInstrumentation().getUiAutomation();
- ProviderTestUtils.setDefaultSmsApp(true, mContext.getPackageName(), mUiAutomation);
- mOldTransport = ProviderTestUtils.setBackupTransport(LOCAL_BACKUP_COMPONENT, mUiAutomation);
- clearMessages();
- wipeBackup();
+ mHasFeature = isFeatureSupported();
+ if (mHasFeature) {
+ ProviderTestUtils.setDefaultSmsApp(true, mContext.getPackageName(), mUiAutomation);
+ mOldTransport =
+ ProviderTestUtils.setBackupTransport(LOCAL_BACKUP_COMPONENT, mUiAutomation);
+ mOldBackupEnabled = ProviderTestUtils.setBackupEnabled(true, mUiAutomation);
+ clearMessages();
+ wipeBackup();
+ }
}
@Override
protected void tearDown() throws Exception {
- wipeBackup();
- clearMessages();
- ProviderTestUtils.setBackupTransport(mOldTransport, mUiAutomation);
- ProviderTestUtils.setDefaultSmsApp(false, mContext.getPackageName(), mUiAutomation);
+ if (mHasFeature) {
+ wipeBackup();
+ clearMessages();
+ ProviderTestUtils.setBackupEnabled(mOldBackupEnabled, mUiAutomation);
+ ProviderTestUtils.setBackupTransport(mOldTransport, mUiAutomation);
+ ProviderTestUtils.setDefaultSmsApp(false, mContext.getPackageName(), mUiAutomation);
+ }
+
super.tearDown();
}
+ private boolean isFeatureSupported() throws Exception {
+ return (ProviderTestUtils.hasBackupTransport(LOCAL_BACKUP_COMPONENT, mUiAutomation)
+ && mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY));
+ }
+
private void clearMessages() {
mContentResolver.delete(Telephony.Sms.CONTENT_URI, SMS_SELECTION, smsAddressBody1);
mContentResolver.delete(Telephony.Sms.CONTENT_URI, SMS_SELECTION, smsAddressBody2);
@@ -117,8 +134,9 @@
* @throws Exception
*/
public void testSmsBackupRestore() throws Exception {
- if (!ProviderTestUtils.hasBackupTransport(LOCAL_BACKUP_COMPONENT, mUiAutomation)) {
+ if (!mHasFeature) {
Log.i(TAG, "skipping testSmsBackupRestore");
+ return;
}
ContentValues smsContentValues[] = new ContentValues[] {
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/reduce.rs b/tests/tests/renderscript/src/android/renderscript/cts/reduce.rs
index c30cb9c..d731561 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/reduce.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/reduce.rs
@@ -375,7 +375,7 @@
}
static void fz3Combine(int3 *accum, const int3 *accum2) {
- if (accum->x >= 0) *accum = *accum2;
+ if (accum2->x >= 0) *accum = *accum2;
}
/////////////////////////////////////////////////////////////////////////
diff --git a/tests/tests/security/jni/Android.mk b/tests/tests/security/jni/Android.mk
index cc182b3..d39ac7e 100644
--- a/tests/tests/security/jni/Android.mk
+++ b/tests/tests/security/jni/Android.mk
@@ -26,23 +26,16 @@
android_security_cts_CharDeviceTest.cpp \
android_security_cts_KernelSettingsTest.cpp \
android_security_cts_LinuxRngTest.cpp \
- android_security_cts_LoadEffectLibraryTest.cpp \
android_security_cts_NativeCodeTest.cpp \
android_security_cts_SELinuxTest.cpp \
android_security_cts_MMapExecutableTest.cpp \
- android_security_cts_AudioPolicyBinderTest.cpp \
android_security_cts_EncryptionTest.cpp \
- android_security_cts_AudioFlingerBinderTest.cpp \
- android_security_cts_AudioEffectBinderTest.cpp \
- android_security_cts_MediaPlayerInfoLeakTest.cpp \
- android_security_cts_GraphicBufferInfoLeakTest.cpp
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE) \
$(TOP)/frameworks/native/include/media/openmax
LOCAL_SHARED_LIBRARIES := libnativehelper \
liblog \
- libbinder \
libutils \
libmedia \
libselinux \
diff --git a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
index 24c87b1..198baa00 100644
--- a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
+++ b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
@@ -21,15 +21,9 @@
extern int register_android_security_cts_CharDeviceTest(JNIEnv*);
extern int register_android_security_cts_LinuxRngTest(JNIEnv*);
extern int register_android_security_cts_NativeCodeTest(JNIEnv*);
-extern int register_android_security_cts_LoadEffectLibraryTest(JNIEnv*);
extern int register_android_security_cts_SELinuxTest(JNIEnv*);
extern int register_android_security_cts_MMapExecutableTest(JNIEnv* env);
-extern int register_android_security_cts_AudioPolicyBinderTest(JNIEnv* env);
-extern int register_android_security_cts_AudioFlingerBinderTest(JNIEnv* env);
extern int register_android_security_cts_EncryptionTest(JNIEnv* env);
-extern int register_android_security_cts_AudioEffectBinderTest(JNIEnv* env);
-extern int register_android_security_cts_MediaPlayerInfoLeakTest(JNIEnv* env);
-extern int register_android_security_cts_GraphicBufferInfoLeakTest(JNIEnv* env);
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env = NULL;
@@ -50,10 +44,6 @@
return JNI_ERR;
}
- if (register_android_security_cts_LoadEffectLibraryTest(env)) {
- return JNI_ERR;
- }
-
if (register_android_security_cts_SELinuxTest(env)) {
return JNI_ERR;
}
@@ -66,33 +56,9 @@
return JNI_ERR;
}
- if (register_android_security_cts_AudioPolicyBinderTest(env)) {
- return JNI_ERR;
- }
-
if (register_android_security_cts_EncryptionTest(env)) {
return JNI_ERR;
}
- if (register_android_security_cts_AudioFlingerBinderTest(env)) {
- return JNI_ERR;
- }
-
- if (register_android_security_cts_AudioEffectBinderTest(env)) {
- return JNI_ERR;
- }
-
- if (register_android_security_cts_MediaPlayerInfoLeakTest(env)) {
- return JNI_ERR;
- }
-
- if (register_android_security_cts_AudioFlingerBinderTest(env)) {
- return JNI_ERR;
- }
-
- if (register_android_security_cts_GraphicBufferInfoLeakTest(env)) {
- return JNI_ERR;
- }
-
return JNI_VERSION_1_4;
}
diff --git a/tests/tests/security/jni/android_security_cts_AudioEffectBinderTest.cpp b/tests/tests/security/jni/android_security_cts_AudioEffectBinderTest.cpp
deleted file mode 100644
index 6e94fce..0000000
--- a/tests/tests/security/jni/android_security_cts_AudioEffectBinderTest.cpp
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "AudioEffectBinderTest-JNI"
-
-#include <jni.h>
-#include <media/AudioEffect.h>
-#include <media/IEffect.h>
-
-using namespace android;
-
-/*
- * Native methods used by
- * cts/tests/tests/security/src/android/security/cts/AudioEffectBinderTest.java
- */
-
-struct EffectClient : public BnEffectClient {
- EffectClient() { }
- virtual void controlStatusChanged(bool controlGranted __unused) { }
- virtual void enableStatusChanged(bool enabled __unused) { }
- virtual void commandExecuted(uint32_t cmdCode __unused,
- uint32_t cmdSize __unused,
- void *pCmdData __unused,
- uint32_t replySize __unused,
- void *pReplyData __unused) { }
-};
-
-struct DeathRecipient : public IBinder::DeathRecipient {
- DeathRecipient() : mDied(false) { }
- virtual void binderDied(const wp<IBinder>& who __unused) { mDied = true; }
- bool died() const { return mDied; }
- bool mDied;
-};
-
-static bool isIEffectCommandSecure(IEffect *effect)
-{
- // some magic constants here
- const int COMMAND_SIZE = 1024 + 12; // different than reply size to get different heap frag
- char cmdData[COMMAND_SIZE];
- memset(cmdData, 0xde, sizeof(cmdData));
-
- const int REPLY_DATA_SIZE = 256;
- char replyData[REPLY_DATA_SIZE];
- bool secure = true;
- for (int k = 0; k < 10; ++k) {
- Parcel data;
- data.writeInterfaceToken(effect->getInterfaceDescriptor());
- data.writeInt32(0); // 0 is EFFECT_CMD_INIT
- data.writeInt32(sizeof(cmdData));
- data.write(cmdData, sizeof(cmdData));
- data.writeInt32(sizeof(replyData));
-
- Parcel reply;
- status_t status = effect->asBinder(effect)->transact(3, data, &reply); // 3 is COMMAND
- ALOGV("transact status: %d", status);
- if (status != NO_ERROR) {
- ALOGW("invalid transaction status %d", status);
- continue;
- }
-
- ALOGV("reply data avail %zu", reply.dataAvail());
- status = reply.readInt32();
- ALOGV("reply status %d", status);
- if (status == NO_ERROR) {
- continue;
- }
-
- int size = reply.readInt32();
- ALOGV("reply size %d", size);
- if (size != sizeof(replyData)) { // we expect 0 or full reply data if command failed
- ALOGW_IF(size != 0, "invalid reply size: %d", size);
- continue;
- }
-
- // Note that if reply.read() returns success, it should completely fill replyData.
- status = reply.read(replyData, sizeof(replyData));
- if (status != NO_ERROR) {
- ALOGW("invalid reply read - ignoring");
- continue;
- }
- unsigned int *out = (unsigned int *)replyData;
- for (size_t index = 0; index < sizeof(replyData) / sizeof(*out); ++index) {
- if (out[index] != 0) {
- secure = false;
- ALOGI("leaked data = %#08x", out[index]);
- }
- }
- }
- ALOGI("secure: %s", secure ? "YES" : "NO");
- return secure;
-}
-
-static jboolean android_security_cts_AudioEffect_test_isCommandSecure()
-{
- const sp<IAudioFlinger> &audioFlinger = AudioSystem::get_audio_flinger();
- if (audioFlinger.get() == NULL) {
- ALOGE("could not get audioflinger");
- return JNI_FALSE;
- }
-
- static const effect_uuid_t EFFECT_UIID_EQUALIZER = // type
- { 0x0bed4300, 0xddd6, 0x11db, 0x8f34, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b }};
- sp<EffectClient> effectClient(new EffectClient());
- effect_descriptor_t descriptor;
- memset(&descriptor, 0, sizeof(descriptor));
- descriptor.type = EFFECT_UIID_EQUALIZER;
- descriptor.uuid = *EFFECT_UUID_NULL;
- const int32_t priority = 0;
- const audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX;
- const audio_io_handle_t io = AUDIO_IO_HANDLE_NONE;
- const String16 opPackageName("Exploitable");
- status_t status;
- int32_t id;
- int enabled;
- sp<IEffect> effect = audioFlinger->createEffect(&descriptor, effectClient,
- priority, io, sessionId, opPackageName, &status, &id, &enabled);
- if (effect.get() == NULL || status != NO_ERROR) {
- ALOGW("could not create effect");
- return JNI_TRUE;
- }
-
- sp<DeathRecipient> deathRecipient(new DeathRecipient());
- IInterface::asBinder(effect)->linkToDeath(deathRecipient);
-
- // check exploit
- if (!isIEffectCommandSecure(effect.get())) {
- ALOGE("not secure!");
- return JNI_FALSE;
- }
-
- sleep(1); // wait to check death
- if (deathRecipient->died()) {
- ALOGE("effect binder died");
- return JNI_FALSE;
- }
- return JNI_TRUE;
-}
-
-int register_android_security_cts_AudioEffectBinderTest(JNIEnv *env)
-{
- static JNINativeMethod methods[] = {
- { "native_test_isCommandSecure", "()Z",
- (void *) android_security_cts_AudioEffect_test_isCommandSecure },
- };
-
- jclass clazz = env->FindClass("android/security/cts/AudioEffectBinderTest");
- return env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0]));
-}
diff --git a/tests/tests/security/jni/android_security_cts_AudioFlingerBinderTest.cpp b/tests/tests/security/jni/android_security_cts_AudioFlingerBinderTest.cpp
deleted file mode 100644
index f4e79e5..0000000
--- a/tests/tests/security/jni/android_security_cts_AudioFlingerBinderTest.cpp
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "AudioFlingerBinderTest-JNI"
-
-#include <jni.h>
-#include <binder/IServiceManager.h>
-#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
-#include <media/IAudioFlinger.h>
-#include <media/AudioSystem.h>
-#include <system/audio.h>
-#include <utils/Log.h>
-#include <utils/SystemClock.h>
-
-using namespace android;
-
-/*
- * Native methods used by
- * cts/tests/tests/security/src/android/security/cts/AudioFlingerBinderTest.java
- */
-
-#define TEST_ARRAY_SIZE 10000
-#define MAX_ARRAY_SIZE 1024
-#define TEST_PATTERN 0x55
-
-class MyDeathClient: public IBinder::DeathRecipient
-{
-public:
- MyDeathClient() :
- mAfIsDead(false) {
- }
-
- bool afIsDead() const { return mAfIsDead; }
-
- // DeathRecipient
- virtual void binderDied(const wp<IBinder>& who __unused) { mAfIsDead = true; }
-
-private:
- bool mAfIsDead;
-};
-
-
-static bool connectAudioFlinger(sp<IAudioFlinger>& af, sp<MyDeathClient> &dr)
-{
- int64_t startTime = 0;
- while (af == 0) {
- sp<IBinder> binder = defaultServiceManager()->checkService(String16("media.audio_flinger"));
- if (binder == 0) {
- if (startTime == 0) {
- startTime = uptimeMillis();
- } else if ((uptimeMillis()-startTime) > 10000) {
- ALOGE("timeout while getting audio flinger service");
- return false;
- }
- sleep(1);
- } else {
- af = interface_cast<IAudioFlinger>(binder);
- dr = new MyDeathClient();
- binder->linkToDeath(dr);
- }
- }
- // Allow binderDied() to be called on MyDeathClient
- sp<ProcessState> proc(ProcessState::self());
- ProcessState::self()->startThreadPool();
- return true;
-}
-
-/*
- * Checks that AudioSystem::setMasterMute() does not crash mediaserver if a duplicated output
- * is opened.
- */
-jboolean android_security_cts_AudioFlinger_test_setMasterMute(JNIEnv* env __unused,
- jobject thiz __unused)
-{
- sp<IAudioFlinger> af;
- sp<MyDeathClient> dr;
-
- if (!connectAudioFlinger(af, dr)) {
- return false;
- }
-
- // force opening of a duplicating output
- status_t status = AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
- AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- "0", "");
- if (status != NO_ERROR) {
- return false;
- }
-
- bool mute;
- status = AudioSystem::getMasterMute(&mute);
- if (status != NO_ERROR) {
- return false;
- }
-
- AudioSystem::setMasterMute(!mute);
-
- sleep(1);
-
- // Check that mediaserver did not crash
- if (dr->afIsDead()) {
- return false;
- }
-
- AudioSystem::setMasterMute(mute);
-
- AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
- AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- "0", "");
-
- AudioSystem::setMasterMute(false);
-
- return true;
-}
-
-jboolean android_security_cts_AudioFlinger_test_setMasterVolume(JNIEnv* env __unused,
- jobject thiz __unused)
-{
- sp<IAudioFlinger> af;
- sp<MyDeathClient> dr;
-
- if (!connectAudioFlinger(af, dr)) {
- return false;
- }
-
- // force opening of a duplicating output
- status_t status = AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
- AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- "0", "");
- if (status != NO_ERROR) {
- return false;
- }
-
- float vol;
- status = AudioSystem::getMasterVolume(&vol);
- if (status != NO_ERROR) {
- return false;
- }
-
- AudioSystem::setMasterVolume(vol < 0.5 ? 1.0 : 0.0);
-
- sleep(1);
-
- // Check that mediaserver did not crash
- if (dr->afIsDead()) {
- return false;
- }
-
- AudioSystem::setMasterMute(vol);
-
- AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
- AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- "0", "");
-
- return true;
-}
-
-jboolean android_security_cts_AudioFlinger_test_listAudioPorts(JNIEnv* env __unused,
- jobject thiz __unused)
-{
- sp<IAudioFlinger> af;
- sp<MyDeathClient> dr;
-
- if (!connectAudioFlinger(af, dr)) {
- return false;
- }
-
- unsigned int num_ports = TEST_ARRAY_SIZE;
- struct audio_port *ports =
- (struct audio_port *)calloc(TEST_ARRAY_SIZE, sizeof(struct audio_port));
-
- memset(ports, TEST_PATTERN, TEST_ARRAY_SIZE * sizeof(struct audio_port));
-
- status_t status = af->listAudioPorts(&num_ports, ports);
-
- sleep(1);
-
- // Check that the memory content above the max allowed array size was not changed
- char *ptr = (char *)(ports + MAX_ARRAY_SIZE);
- for (size_t i = 0; i < TEST_ARRAY_SIZE - MAX_ARRAY_SIZE; i++) {
- if (ptr[i * sizeof(struct audio_port)] != TEST_PATTERN) {
- free(ports);
- return false;
- }
- }
-
- free(ports);
-
- // Check that mediaserver did not crash
- if (dr->afIsDead()) {
- return false;
- }
-
- return true;
-}
-
-jboolean android_security_cts_AudioFlinger_test_listAudioPatches(JNIEnv* env __unused,
- jobject thiz __unused)
-{
- sp<IAudioFlinger> af;
- sp<MyDeathClient> dr;
-
- if (!connectAudioFlinger(af, dr)) {
- return false;
- }
-
- unsigned int num_patches = TEST_ARRAY_SIZE;
- struct audio_patch *patches =
- (struct audio_patch *)calloc(TEST_ARRAY_SIZE, sizeof(struct audio_patch));
-
- memset(patches, TEST_PATTERN, TEST_ARRAY_SIZE * sizeof(struct audio_patch));
-
- status_t status = af->listAudioPatches(&num_patches, patches);
-
- sleep(1);
-
- // Check that the memory content above the max allowed array size was not changed
- char *ptr = (char *)(patches + MAX_ARRAY_SIZE);
- for (size_t i = 0; i < TEST_ARRAY_SIZE - MAX_ARRAY_SIZE; i++) {
- if (ptr[i * sizeof(struct audio_patch)] != TEST_PATTERN) {
- free(patches);
- return false;
- }
- }
-
- free(patches);
-
- // Check that mediaserver did not crash
- if (dr->afIsDead()) {
- return false;
- }
-
- return true;
-}
-
-jboolean android_security_cts_AudioFlinger_test_createEffect(JNIEnv* env __unused,
- jobject thiz __unused)
-{
- sp<IAudioFlinger> af;
- sp<MyDeathClient> dr;
-
- if (!connectAudioFlinger(af, dr)) {
- return false;
- }
-
- for (int j = 0; j < 10; ++j) {
- Parcel data, reply;
- data.writeInterfaceToken(af->getInterfaceDescriptor());
- data.writeInt32((int32_t)j);
- status_t status = af->asBinder(af)->transact(40, data, &reply); // 40 is CREATE_EFFECT
- if (status != NO_ERROR) {
- return false;
- }
-
- status = (status_t)reply.readInt32();
- if (status == NO_ERROR) {
- continue;
- }
-
- int id = reply.readInt32();
- int enabled = reply.readInt32();
- sp<IEffect> effect = interface_cast<IEffect>(reply.readStrongBinder());
- effect_descriptor_t desc;
- effect_descriptor_t descTarget;
- memset(&desc, 0, sizeof(effect_descriptor_t));
- memset(&descTarget, 0, sizeof(effect_descriptor_t));
- reply.read(&desc, sizeof(effect_descriptor_t));
- if (id != 0 || enabled != 0 || memcmp(&desc, &descTarget, sizeof(effect_descriptor_t))) {
- return false;
- }
- }
-
- sleep(1);
-
- // Check that mediaserver did not crash
- if (dr->afIsDead()) {
- return false;
- }
-
- return true;
-}
-
-
-#define NUM_ATTEMPTS 5
-
-jboolean android_security_cts_AudioFlinger_test_getInputBufferSize(JNIEnv* env __unused,
- jobject thiz __unused)
-{
- sp<IAudioFlinger> af;
- sp<MyDeathClient> dr;
-
- if (!connectAudioFlinger(af, dr)) {
- return false;
- }
-
- for (size_t i = 0; i < NUM_ATTEMPTS; i++) {
- af->getInputBufferSize(0, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO);
- sleep(1);
- // Check that mediaserver did not crash
- if (dr->afIsDead()) {
- return false;
- }
- }
-
- return true;
-}
-
-static JNINativeMethod gMethods[] = {
- { "native_test_setMasterMute", "()Z",
- (void *) android_security_cts_AudioFlinger_test_setMasterMute },
- { "native_test_setMasterVolume", "()Z",
- (void *) android_security_cts_AudioFlinger_test_setMasterVolume },
- { "native_test_listAudioPorts", "()Z",
- (void *) android_security_cts_AudioFlinger_test_listAudioPorts },
- { "native_test_listAudioPatches", "()Z",
- (void *) android_security_cts_AudioFlinger_test_listAudioPatches },
- { "native_test_createEffect", "()Z",
- (void *) android_security_cts_AudioFlinger_test_createEffect },
- { "native_test_getInputBufferSize", "()Z",
- (void *) android_security_cts_AudioFlinger_test_getInputBufferSize },
-};
-
-int register_android_security_cts_AudioFlingerBinderTest(JNIEnv* env)
-{
- jclass clazz = env->FindClass("android/security/cts/AudioFlingerBinderTest");
- return env->RegisterNatives(clazz, gMethods,
- sizeof(gMethods) / sizeof(JNINativeMethod));
-}
diff --git a/tests/tests/security/jni/android_security_cts_AudioPolicyBinderTest.cpp b/tests/tests/security/jni/android_security_cts_AudioPolicyBinderTest.cpp
deleted file mode 100644
index d0a8ec9..0000000
--- a/tests/tests/security/jni/android_security_cts_AudioPolicyBinderTest.cpp
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "AudioPolicyBinderTest-JNI"
-
-#include <jni.h>
-#include <binder/IServiceManager.h>
-#include <binder/Parcel.h>
-#include <media/IAudioPolicyService.h>
-#include <media/AudioSystem.h>
-#include <system/audio.h>
-#include <utils/Log.h>
-#include <utils/SystemClock.h>
-
-using namespace android;
-
-/*
- * Native methods used by
- * cts/tests/tests/security/src/android/security/cts/AudioPolicyBinderTest.java
- */
-
-static bool init(sp<IAudioPolicyService>& aps, audio_io_handle_t *output, int *session)
-{
- aps = 0;
- if (output != NULL) {
- *output = AUDIO_IO_HANDLE_NONE;
- }
- if (session != NULL) {
- *session = AUDIO_UNIQUE_ID_ALLOCATE;
- }
-
- int64_t startTime = 0;
- sp<IServiceManager> sm = defaultServiceManager();
- while (aps == 0) {
- sp<IBinder> binder = defaultServiceManager()->checkService(String16("media.audio_policy"));
- if (binder == 0) {
- if (startTime == 0) {
- startTime = uptimeMillis();
- } else if ((uptimeMillis()-startTime) > 10000) {
- ALOGE("timeout while getting audio policy service");
- return false;
- }
- sleep(1);
- } else {
- aps = interface_cast<IAudioPolicyService>(binder);
- }
- }
-
- if (output != NULL) {
- // get a valid output. Any use case will do.
- for (int stream = AUDIO_STREAM_MIN; stream < AUDIO_STREAM_CNT; stream++) {
- *output = AudioSystem::getOutput((audio_stream_type_t)stream);
- if (*output != AUDIO_IO_HANDLE_NONE) {
- break;
- }
- }
- if (*output == AUDIO_IO_HANDLE_NONE) {
- ALOGE("cannot get valid audio output");
- return false;
- }
- }
- if (session != NULL) {
- //get a valid session
- *session = AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
- if (*session == AUDIO_UNIQUE_ID_ALLOCATE) {
- ALOGE("cannot get valid audio session");
- return false;
- }
- }
- return true;
-}
-
-/*
- * Checks that IAudioPolicyService::startOutput() cannot be called with an
- * invalid stream type.
- */
-jboolean android_security_cts_AudioPolicy_test_startOutput(JNIEnv* env __unused,
- jobject thiz __unused)
-{
- sp<IAudioPolicyService> aps;
- audio_io_handle_t output;
- int session;
-
- if (!init(aps, &output, &session)) {
- return false;
- }
-
- status_t status = aps->startOutput(output, (audio_stream_type_t)(AUDIO_STREAM_MIN -1),
- (audio_session_t)session);
- if (status == NO_ERROR) {
- return false;
- }
- status = aps->startOutput(output, (audio_stream_type_t)AUDIO_STREAM_CNT,
- (audio_session_t)session);
- if (status == NO_ERROR) {
- return false;
- }
- return true;
-}
-
-/*
- * Checks that IAudioPolicyService::stopOutput() cannot be called with an
- * invalid stream type.
- */
-jboolean android_security_cts_AudioPolicy_test_stopOutput(JNIEnv* env __unused,
- jobject thiz __unused)
-{
- sp<IAudioPolicyService> aps;
- audio_io_handle_t output;
- int session;
-
- if (!init(aps, &output, &session)) {
- return false;
- }
-
- status_t status = aps->stopOutput(output, (audio_stream_type_t)(AUDIO_STREAM_MIN -1),
- (audio_session_t)session);
- if (status == NO_ERROR) {
- return false;
- }
- status = aps->stopOutput(output, (audio_stream_type_t)AUDIO_STREAM_CNT,
- (audio_session_t)session);
- if (status == NO_ERROR) {
- return false;
- }
- return true;
-}
-
-/*
- * Checks that IAudioPolicyService::isStreamActive() cannot be called with an
- * invalid stream type.
- */
-jboolean android_security_cts_AudioPolicy_test_isStreamActive(JNIEnv* env __unused,
- jobject thiz __unused)
-{
- sp<IAudioPolicyService> aps;
-
- if (!init(aps, NULL, NULL)) {
- return false;
- }
-
- bool status = aps->isStreamActive((audio_stream_type_t)(-1), 0);
- if (status) {
- return false;
- }
- status = aps->isStreamActive((audio_stream_type_t)AUDIO_STREAM_CNT, 0);
- if (status) {
- return false;
- }
- return true;
-}
-
-/*
- * Checks that IAudioPolicyService::isStreamActiveRemotely() cannot be called with an
- * invalid stream type.
- * Test with NUM_RANDOM_TESTS random values for stream type.
- */
-jboolean android_security_cts_AudioPolicy_test_isStreamActiveRemotely(JNIEnv* env __unused,
- jobject thiz __unused)
-{
- sp<IAudioPolicyService> aps;
-
- if (!init(aps, NULL, NULL)) {
- return false;
- }
-
- if (aps->isStreamActiveRemotely((audio_stream_type_t)(AUDIO_STREAM_MIN -1), 0)) {
- return false;
- }
-
- if (aps->isStreamActiveRemotely((audio_stream_type_t)AUDIO_STREAM_CNT, 0)) {
- return false;
- }
- return true;
-}
-
-jint android_security_cts_AudioPolicy_test_getStreamVolumeLeak(JNIEnv* env __unused,
- jobject thiz __unused)
-{
- sp<IAudioPolicyService> aps;
-
- if (!init(aps, NULL, NULL)) {
- return -1;
- }
-
- // Keep synchronized with IAudioPolicyService.cpp!
- enum {
- GET_STREAM_VOLUME = 17,
- };
-
- Parcel data, reply;
- status_t err;
- data.writeInterfaceToken(aps->getInterfaceDescriptor());
- data.writeInt32(-1); // stream type
- data.writeInt32(-1); // device
- IInterface::asBinder(aps)->transact(GET_STREAM_VOLUME, data, &reply);
- int index = reply.readInt32();
- err = reply.readInt32();
-
- return index;
-}
-
-jboolean android_security_cts_AudioPolicy_test_startAudioSource(JNIEnv* env __unused,
- jobject thiz __unused)
-{
- sp<IAudioPolicyService> aps;
-
- if (!init(aps, NULL, NULL)) {
- return false;
- }
-
- // Keep synchronized with IAudioPolicyService.cpp!
- enum {
- START_AUDIO_SOURCE = 41,
- };
-
- for (int i = 0; i < 10; ++i) {
- Parcel data, reply;
- data.writeInterfaceToken(aps->getInterfaceDescriptor());
- data.writeInt32(-i);
- IInterface::asBinder(aps)->transact(START_AUDIO_SOURCE, data, &reply);
- status_t err = (status_t)reply.readInt32();
- if (err == NO_ERROR) {
- continue;
- }
- audio_io_handle_t handle = (audio_io_handle_t)reply.readInt32();
- if (handle != 0) {
- return false;
- }
- }
-
- return true;
-}
-
-static JNINativeMethod gMethods[] = {
- { "native_test_startOutput", "()Z",
- (void *) android_security_cts_AudioPolicy_test_startOutput },
- { "native_test_stopOutput", "()Z",
- (void *) android_security_cts_AudioPolicy_test_stopOutput },
- { "native_test_isStreamActive", "()Z",
- (void *) android_security_cts_AudioPolicy_test_isStreamActive },
- { "native_test_isStreamActiveRemotely", "()Z",
- (void *) android_security_cts_AudioPolicy_test_isStreamActiveRemotely },
- { "native_test_getStreamVolumeLeak", "()I",
- (void *) android_security_cts_AudioPolicy_test_getStreamVolumeLeak },
- { "native_test_startAudioSource", "()Z",
- (void *) android_security_cts_AudioPolicy_test_startAudioSource },
-};
-
-int register_android_security_cts_AudioPolicyBinderTest(JNIEnv* env)
-{
- jclass clazz = env->FindClass("android/security/cts/AudioPolicyBinderTest");
- return env->RegisterNatives(clazz, gMethods,
- sizeof(gMethods) / sizeof(JNINativeMethod));
-}
diff --git a/tests/tests/security/jni/android_security_cts_GraphicBufferInfoLeakTest.cpp b/tests/tests/security/jni/android_security_cts_GraphicBufferInfoLeakTest.cpp
deleted file mode 100644
index d0cd347..0000000
--- a/tests/tests/security/jni/android_security_cts_GraphicBufferInfoLeakTest.cpp
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "GraphicBufferInfoLeakTest-JNI"
-
-#include <jni.h>
-#include <JNIHelp.h>
-
-#include <binder/Parcel.h>
-#include <binder/IServiceManager.h>
-
-#include <gui/IGraphicBufferProducer.h>
-#include <gui/IGraphicBufferConsumer.h>
-#include <media/IMediaPlayerService.h>
-#include <media/IMediaRecorder.h>
-#include <media/IOMX.h>
-#include <media/stagefright/MediaErrors.h>
-
-#include <sys/stat.h>
-#include <fcntl.h>
-
-using namespace android;
-
-static sp<IMediaPlayerService> getMediaPlayerService()
-{
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> mediaPlayerService = sm->checkService(String16("media.player"));
-
- sp<IMediaPlayerService> iMPService = IMediaPlayerService::asInterface(mediaPlayerService);
- return iMPService;
-}
-
-jint android_security_cts_GraphicBuffer_test_attachBufferInfoLeak(JNIEnv* env,
- jobject thiz __unused)
-{
- sp<IMediaPlayerService> iMPService = getMediaPlayerService();
-
- // get IOMX
- // Keep synchronized with IMediaPlayerService.cpp!
- enum {
- GET_OMX = 4,
- };
-
- status_t err;
- Parcel data, reply;
- data.writeInterfaceToken(iMPService->getInterfaceDescriptor());
- err = IMediaPlayerService::asBinder(iMPService)->transact(GET_OMX, data, &reply);
- if (err != NO_ERROR) {
- jniThrowException(env, "java/lang/RuntimeException", "GET_OMX failed");
- }
-
- // get IGraphicBufferConsumer
- sp<IGraphicBufferProducer> iBufferProducer;
- sp<IGraphicBufferConsumer> iBufferConsumer;
- sp<IOMX> iOmx = interface_cast<IOMX>(reply.readStrongBinder());
- err = iOmx->createPersistentInputSurface(&iBufferProducer, &iBufferConsumer);
- if (err != NO_ERROR) {
- jniThrowException(env, "java/lang/RuntimeException", "createPersistentInputSurface failed");
- return err;
- }
-
- // Keep synchronized with IGraphicBufferConsumer.cpp!
- enum {
- ATTACH_BUFFER = 3,
- };
-
- for (;;) {
- Parcel data2, reply2;
- data2.writeInterfaceToken(iBufferConsumer->getInterfaceDescriptor());
- err = IGraphicBufferConsumer::asBinder(iBufferConsumer)->transact(ATTACH_BUFFER, data2, &reply2);
- if (err != NO_ERROR) {
- jniThrowException(env, "java/lang/RuntimeException", "ATTACH_BUFFER failed");
- }
-
- int32_t slot = reply2.readInt32();
- status_t result = reply2.readInt32();
- ALOGV("slot %d", slot);
- if (result != 0) {
- // only check for leaked data in error case
- return slot;
- }
- }
-}
-
-jint android_security_cts_GraphicBuffer_test_queueBufferInfoLeak(JNIEnv* env,
- jobject thiz __unused)
-{
- sp<IMediaPlayerService> iMPService = getMediaPlayerService();
- sp<IMediaRecorder> recorder = iMPService->createMediaRecorder(String16("GraphicBufferInfoLeakTest"));
-
- const char *fileName = "/dev/null";
- int fd = open(fileName, O_RDWR | O_CREAT, 0744);
- if (fd < 0) {
- jniThrowException(env, "java/lang/RuntimeException", "open output failed");
- return fd;
- }
-
- recorder->setVideoSource(2);
- recorder->setOutputFile(fd, 0, 0);
- recorder->setOutputFormat(0);
- recorder->init();
- recorder->prepare();
- recorder->start();
-
- //get IGraphicBufferProducer
- sp<IGraphicBufferProducer> iGBP = recorder->querySurfaceMediaSource();
- ALOGV("fd %d, Get iGBP instance, 0x%08x\n", fd, iGBP.get());
-
- // Keep synchronized with IGraphicBufferProducer.cpp!
- enum {
- QUEUE_BUFFER = 7,
- };
-
- for (;;) {
- status_t err;
- Parcel data, reply;
- data.writeInterfaceToken(iGBP->getInterfaceDescriptor());
- data.writeInt32(-1);
- err = IGraphicBufferProducer::asBinder(iGBP)->transact(QUEUE_BUFFER, data, &reply);
- if (err != NO_ERROR) {
- recorder->stop();
- recorder->release();
- jniThrowException(env, "java/lang/RuntimeException", "QUEUE_BUFFER failed");
- return err;
- }
-
- size_t len = reply.dataAvail();
- int32_t result; // last sizeof(int32_t) bytes of Parcel
- ALOGV("dataAvail = %zu\n", len);
- if (len < sizeof(result)) {
- // must contain result
- recorder->stop();
- recorder->release();
- jniThrowException(env, "java/lang/RuntimeException", "reply malformed");
- return ERROR_MALFORMED;
- }
-
- uint8_t *reply_data = (uint8_t *)reply.data();
- memcpy(&result, reply_data + len - sizeof(result), sizeof(result));
- if (result == NO_ERROR) {
- // only check for leaked data in error case
- continue;
- }
-
- uint8_t leaked_data = 0;
- for (size_t i = 0; i < len - sizeof(result); ++i) {
- ALOGV("IGraphicBufferProducer_InfoLeak reply_data[%d] = 0x%08x", i, reply_data[i]);
- if (reply_data[i]) {
- leaked_data = reply_data[i];
- break;
- }
- }
-
- recorder->stop();
- recorder->release();
- return leaked_data;
- }
-}
-
-static JNINativeMethod gMethods[] = {
- { "native_test_attachBufferInfoLeak", "()I",
- (void *) android_security_cts_GraphicBuffer_test_attachBufferInfoLeak },
- { "native_test_queueBufferInfoLeak", "()I",
- (void *) android_security_cts_GraphicBuffer_test_queueBufferInfoLeak },
-};
-
-int register_android_security_cts_GraphicBufferInfoLeakTest(JNIEnv* env)
-{
- jclass clazz = env->FindClass("android/security/cts/GraphicBufferInfoLeakTest");
- return env->RegisterNatives(clazz, gMethods,
- sizeof(gMethods) / sizeof(JNINativeMethod));
-}
diff --git a/tests/tests/security/jni/android_security_cts_LoadEffectLibraryTest.cpp b/tests/tests/security/jni/android_security_cts_LoadEffectLibraryTest.cpp
deleted file mode 100644
index 6e0f6e1..0000000
--- a/tests/tests/security/jni/android_security_cts_LoadEffectLibraryTest.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <jni.h>
-#include <binder/IServiceManager.h>
-#include <media/IAudioFlinger.h>
-#include <media/AudioEffect.h>
-
-
-using namespace android;
-
-
-/*
- * Native method used by
- * cts/tests/tests/security/src/android/security/cts/LoadEffectLibraryTest.java
- *
- * Checks that no IAudioFlinger binder transaction manages to load an effect library
- * as LOAD_EFFECT_LIBRARY did in gingerbread.
- */
-
-jboolean android_security_cts_LoadEffectLibraryTest_doLoadLibraryTest(JNIEnv* env, jobject thiz)
-{
- sp<IServiceManager> sm = defaultServiceManager();
- if (sm == 0) {
- return false;
- }
-
- sp<IBinder> binder = sm->getService(String16("media.audio_flinger"));
- if (binder == 0) {
- return false;
- }
-
- Parcel data, reply;
- sp<IAudioFlinger> af = interface_cast<IAudioFlinger>(binder);
-
- data.writeInterfaceToken(af->getInterfaceDescriptor());
- // test library path defined in cts/tests/tests/security/testeffect/Android.mk
- data.writeCString("/system/lib/soundfx/libctstesteffect.so");
-
- // test 100 IAudioFlinger binder transaction values and check that none corresponds
- // to LOAD_EFFECT_LIBRARY and successfully loads our test library
- for (uint32_t i = IBinder::FIRST_CALL_TRANSACTION;
- i < IBinder::FIRST_CALL_TRANSACTION + 100;
- i++) {
- status_t status = binder->transact(i, data, &reply);
- if (status != NO_ERROR) {
- continue;
- }
- status = reply.readInt32();
- if (status != NO_ERROR) {
- continue;
- }
-
- // Effect UUID defined in cts/tests/tests/security/testeffect/CTSTestEffect.cpp
- effect_uuid_t uuid =
- {0xff93e360, 0x0c3c, 0x11e3, 0x8a97, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
- effect_descriptor_t desc;
-
- status = AudioEffect::getEffectDescriptor(&uuid, &desc);
- if (status == NO_ERROR) {
- return false;
- }
- }
- return true;
-}
-
-static JNINativeMethod gMethods[] = {
- { "doLoadLibraryTest", "()Z",
- (void *) android_security_cts_LoadEffectLibraryTest_doLoadLibraryTest },
-};
-
-int register_android_security_cts_LoadEffectLibraryTest(JNIEnv* env)
-{
- jclass clazz = env->FindClass("android/security/cts/LoadEffectLibraryTest");
- return env->RegisterNatives(clazz, gMethods,
- sizeof(gMethods) / sizeof(JNINativeMethod));
-}
diff --git a/tests/tests/security/jni/android_security_cts_MediaPlayerInfoLeakTest.cpp b/tests/tests/security/jni/android_security_cts_MediaPlayerInfoLeakTest.cpp
deleted file mode 100644
index 0c61f25..0000000
--- a/tests/tests/security/jni/android_security_cts_MediaPlayerInfoLeakTest.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "MediaPlayerInfoLeakTest-JNI"
-
-#include <jni.h>
-
-#include <binder/Parcel.h>
-#include <binder/IServiceManager.h>
-
-#include <media/IMediaPlayer.h>
-#include <media/IMediaPlayerService.h>
-#include <media/IMediaPlayerClient.h>
-
-#include <sys/stat.h>
-
-using namespace android;
-
-static status_t connectMediaPlayer(sp<IMediaPlayer>& iMP)
-{
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> mediaPlayerService = sm->checkService(String16("media.player"));
-
- sp<IMediaPlayerService> iMPService = IMediaPlayerService::asInterface(mediaPlayerService);
- sp<IMediaPlayerClient> client;
- Parcel data, reply;
- int dummyAudioSessionId = 1;
- data.writeInterfaceToken(iMPService->getInterfaceDescriptor());
- data.writeStrongBinder(IInterface::asBinder(client));
- data.writeInt32(dummyAudioSessionId);
-
- // Keep synchronized with IMediaPlayerService.cpp!
- enum {
- CREATE = IBinder::FIRST_CALL_TRANSACTION,
- };
- status_t err = IInterface::asBinder(iMPService)->transact(CREATE, data, &reply);
- if (err == NO_ERROR) {
- iMP = interface_cast<IMediaPlayer>(reply.readStrongBinder());
- }
- return err;
-}
-
-int testMediaPlayerInfoLeak(int command)
-{
- sp<IMediaPlayer> iMP;
- if (NO_ERROR != connectMediaPlayer(iMP)) {
- return false;
- }
-
-
- Parcel data, reply;
- data.writeInterfaceToken(iMP->getInterfaceDescriptor());
- IInterface::asBinder(iMP)->transact(command, data, &reply);
-
- int leak = reply.readInt32();
- status_t err = reply.readInt32();
- return leak;
-}
-
-jint android_security_cts_MediaPlayer_test_getCurrentPositionLeak(JNIEnv* env __unused,
- jobject thiz __unused)
-{
- // Keep synchronized with IMediaPlayer.cpp!
- enum {
- GET_CURRENT_POSITION = 16,
- };
- return testMediaPlayerInfoLeak(GET_CURRENT_POSITION);
-}
-
-jint android_security_cts_MediaPlayer_test_getDurationLeak(JNIEnv* env __unused,
- jobject thiz __unused)
-{
- // Keep synchronized with IMediaPlayer.cpp!
- enum {
- GET_DURATION = 17,
- };
- return testMediaPlayerInfoLeak(GET_DURATION);
-}
-
-static JNINativeMethod gMethods[] = {
- { "native_test_getCurrentPositionLeak", "()I",
- (void *) android_security_cts_MediaPlayer_test_getCurrentPositionLeak },
- { "native_test_getDurationLeak", "()I",
- (void *) android_security_cts_MediaPlayer_test_getDurationLeak },
-};
-
-int register_android_security_cts_MediaPlayerInfoLeakTest(JNIEnv* env)
-{
- jclass clazz = env->FindClass("android/security/cts/MediaPlayerInfoLeakTest");
- return env->RegisterNatives(clazz, gMethods,
- sizeof(gMethods) / sizeof(JNINativeMethod));
-}
diff --git a/tests/tests/security/src/android/security/cts/AudioEffectBinderTest.java b/tests/tests/security/src/android/security/cts/AudioEffectBinderTest.java
deleted file mode 100644
index 20d9615..0000000
--- a/tests/tests/security/src/android/security/cts/AudioEffectBinderTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.cts;
-
-import android.media.audiofx.AudioEffect;
-
-import java.util.UUID;
-
-import junit.framework.TestCase;
-
-public class AudioEffectBinderTest extends TestCase {
-
- static {
- System.loadLibrary("ctssecurity_jni");
- }
-
- /**
- * Checks that IEffect::command() cannot leak data.
- */
- public void test_isCommandSecure() throws Exception {
- if (isEffectTypeAvailable(AudioEffect.EFFECT_TYPE_EQUALIZER)) {
- assertTrue(native_test_isCommandSecure());
- }
- }
-
- /* see AudioEffect.isEffectTypeAvailable(), implements hidden function */
- private static boolean isEffectTypeAvailable(UUID type) {
- AudioEffect.Descriptor[] desc = AudioEffect.queryEffects();
- if (desc == null) {
- return false;
- }
-
- for (int i = 0; i < desc.length; i++) {
- if (desc[i].type.equals(type)) {
- return true;
- }
- }
- return false;
- }
-
- private static native boolean native_test_isCommandSecure();
-}
diff --git a/tests/tests/security/src/android/security/cts/AudioFlingerBinderTest.java b/tests/tests/security/src/android/security/cts/AudioFlingerBinderTest.java
deleted file mode 100644
index e84d851..0000000
--- a/tests/tests/security/src/android/security/cts/AudioFlingerBinderTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.cts;
-
-import junit.framework.TestCase;
-
-public class AudioFlingerBinderTest extends TestCase {
-
- static {
- System.loadLibrary("ctssecurity_jni");
- }
-
- /**
- * Checks that AudioSystem::setMasterMute() does not crash mediaserver if a duplicated output
- * is opened.
- */
- public void test_setMasterMute() throws Exception {
- assertTrue(native_test_setMasterMute());
- }
-
- /**
- * Checks that AudioSystem::setMasterVolume() does not crash mediaserver if a duplicated output
- * is opened.
- */
- public void test_setMasterVolume() throws Exception {
- assertTrue(native_test_setMasterVolume());
- }
-
- /**
- * Checks that IAudioFlinger::listAudioPorts() does not cause a memory overflow when passed a
- * large number of ports.
- */
- public void test_listAudioPorts() throws Exception {
- assertTrue(native_test_listAudioPorts());
- }
-
- /**
- * Checks that IAudioFlinger::listAudioPatches() does not cause a memory overflow when passed a
- * large number of ports.
- */
- public void test_listAudioPatches() throws Exception {
- assertTrue(native_test_listAudioPatches());
- }
-
- /**
- * Checks that IAudioFlinger::createEffect() does not leak information on the server side.
- */
- public void test_createEffect() throws Exception {
- assertTrue(native_test_createEffect());
- }
-
- /**
- * Checks that passing a sample rate of 0 to IAudioFlinger::getInputBufferSize()
- * does not cause a crash in audioserver.
- */
- public void test_getInputBufferSize() throws Exception {
- assertTrue(native_test_getInputBufferSize());
- }
-
- private static native boolean native_test_setMasterMute();
- private static native boolean native_test_setMasterVolume();
- private static native boolean native_test_listAudioPorts();
- private static native boolean native_test_listAudioPatches();
- private static native boolean native_test_createEffect();
- private static native boolean native_test_getInputBufferSize();
-}
diff --git a/tests/tests/security/src/android/security/cts/AudioPolicyBinderTest.java b/tests/tests/security/src/android/security/cts/AudioPolicyBinderTest.java
deleted file mode 100644
index 82346a1..0000000
--- a/tests/tests/security/src/android/security/cts/AudioPolicyBinderTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.cts;
-
-import junit.framework.TestCase;
-
-public class AudioPolicyBinderTest extends TestCase {
-
- static {
- System.loadLibrary("ctssecurity_jni");
- }
-
- /**
- * Checks that IAudioPolicyService::startOutput() cannot be called with an
- * invalid stream type.
- */
- public void test_startOutput() throws Exception {
- assertTrue(native_test_startOutput());
- }
-
- /**
- * Checks that IAudioPolicyService::stopOutput() cannot be called with an
- * invalid stream type.
- */
- public void test_stopOutput() throws Exception {
- assertTrue(native_test_stopOutput());
- }
-
- /**
- * Checks that IAudioPolicyService::isStreamActive() cannot be called with an
- * invalid stream type.
- */
- public void test_isStreamActive() throws Exception {
- assertTrue(native_test_isStreamActive());
- }
-
- /**
- * Checks that IAudioPolicyService::isStreamActiveRemotely() cannot be called with an
- * invalid stream type.
- */
- public void test_isStreamActiveRemotely() throws Exception {
- assertTrue(native_test_isStreamActiveRemotely());
- }
-
- /**
- * Checks that IAudioPolicyService::getStreamVolumeIndex() does not leak information
- * when called with an invalid stream/device type.
- */
- public void test_getStreamVolumeLeak() throws Exception {
- int volume = native_test_getStreamVolumeLeak();
- assertTrue(String.format("Leaked volume 0x%08X", volume), volume == 0);
- }
-
- /**
- * Checks that IAudioPolicyService::startAudioSource() cannot leak information from
- * server side.
- */
- public void test_startAudioSource() throws Exception {
- assertTrue(native_test_startAudioSource());
- }
-
- private static native boolean native_test_startOutput();
- private static native boolean native_test_stopOutput();
- private static native boolean native_test_isStreamActive();
- private static native boolean native_test_isStreamActiveRemotely();
- private static native int native_test_getStreamVolumeLeak();
- private static native boolean native_test_startAudioSource();
-}
diff --git a/tests/tests/security/src/android/security/cts/GraphicBufferInfoLeakTest.java b/tests/tests/security/src/android/security/cts/GraphicBufferInfoLeakTest.java
deleted file mode 100644
index 6005e37..0000000
--- a/tests/tests/security/src/android/security/cts/GraphicBufferInfoLeakTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.cts;
-
-import junit.framework.TestCase;
-
-public class GraphicBufferInfoLeakTest extends TestCase {
-
- static {
- System.loadLibrary("ctssecurity_jni");
- }
-
- /**
- * Check that IGraphicBufferConsumer::attachBuffer does not leak info in error case
- */
- public void test_attachBufferInfoLeak() throws Exception {
- int slot = native_test_attachBufferInfoLeak();
- assertTrue(String.format("Leaked slot 0x%08X", slot), slot == -1);
- }
-
- /**
- * Check that IGraphicBufferProducer::queueBuffer does not leak info in error case
- */
- public void test_queueBufferInfoLeak() throws Exception {
- int data = native_test_queueBufferInfoLeak();
- assertTrue(String.format("Leaked buffer data 0x%08X", data), data == 0);
- }
-
- private static native int native_test_attachBufferInfoLeak();
- private static native int native_test_queueBufferInfoLeak();
-}
diff --git a/tests/tests/security/src/android/security/cts/LoadEffectLibraryTest.java b/tests/tests/security/src/android/security/cts/LoadEffectLibraryTest.java
deleted file mode 100644
index 900ac7f..0000000
--- a/tests/tests/security/src/android/security/cts/LoadEffectLibraryTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2013 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.security.cts;
-
-import junit.framework.TestCase;
-
-public class LoadEffectLibraryTest extends TestCase {
-
- static {
- System.loadLibrary("ctssecurity_jni");
- }
-
- /**
- * Checks that no binder calls to IAudioFlinger manages to load an effect library.
- */
- public void testLoadLibrary() throws Exception {
- assertTrue(doLoadLibraryTest());
- }
-
- private static native boolean doLoadLibraryTest();
-
-}
diff --git a/tests/tests/security/src/android/security/cts/MediaPlayerInfoLeakTest.java b/tests/tests/security/src/android/security/cts/MediaPlayerInfoLeakTest.java
deleted file mode 100644
index e34fc05..0000000
--- a/tests/tests/security/src/android/security/cts/MediaPlayerInfoLeakTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.cts;
-
-import junit.framework.TestCase;
-
-public class MediaPlayerInfoLeakTest extends TestCase {
-
- static {
- System.loadLibrary("ctssecurity_jni");
- }
-
-
- /**
- * Checks that IMediaPlayer::getCurrentPosition() does not leak info in error case
- */
- public void test_getCurrentPositionLeak() throws Exception {
- int pos = native_test_getCurrentPositionLeak();
- assertTrue(String.format("Leaked pos 0x%08X", pos), pos == 0);
- }
-
- /**
- * Checks that IMediaPlayer::getDuration() does not leak info in error case
- */
- public void test_getDurationLeak() throws Exception {
- int dur = native_test_getDurationLeak();
- assertTrue(String.format("Leaked dur 0x%08X", dur), dur == 0);
- }
-
- private static native int native_test_getCurrentPositionLeak();
- private static native int native_test_getDurationLeak();
-}
diff --git a/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java b/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
index 8cf20bd..074712e 100644
--- a/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
+++ b/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
@@ -45,6 +45,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
@@ -81,6 +82,11 @@
InvokeCounter mOnCallAudioStateChangedCounter;
InvokeCounter mOnPostDialWaitCounter;
InvokeCounter mOnCannedTextResponsesLoadedCounter;
+ InvokeCounter mOnConnectionEventCounter;
+ InvokeCounter mOnExtrasChangedCounter;
+ InvokeCounter mOnPropertiesChangedCounter;
+ Bundle mPreviousExtras;
+ int mPreviousProperties = -1;
InCallServiceCallbacks mInCallCallbacks;
String mPreviousDefaultDialer = null;
@@ -192,6 +198,17 @@
@Override
public void onDetailsChanged(Call call, Call.Details details) {
Log.i(TAG, "onDetailsChanged, Call: " + call + ", Details: " + details);
+ if (!areBundlesEqual(mPreviousExtras, details.getExtras())) {
+ mOnExtrasChangedCounter.invoke(call, details);
+ }
+ mPreviousExtras = details.getExtras();
+
+ if (mPreviousProperties != details.getCallProperties()) {
+ mOnPropertiesChangedCounter.invoke(call, details);
+ Log.i(TAG, "onDetailsChanged; properties changed from " + Call.Details.propertiesToString(mPreviousProperties) +
+ " to " + Call.Details.propertiesToString(details.getCallProperties()));
+ }
+ mPreviousProperties = details.getCallProperties();
}
@Override
public void onCallDestroyed(Call call) {
@@ -218,6 +235,10 @@
public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {
mOnCannedTextResponsesLoadedCounter.invoke(call, cannedTextResponses);
}
+ @Override
+ public void onConnectionEvent(Call call, String event, Bundle extras) {
+ mOnConnectionEventCounter.invoke(call, event, extras);
+ }
};
MockInCallService.setCallbacks(mInCallCallbacks);
@@ -228,6 +249,9 @@
mOnCallAudioStateChangedCounter = new InvokeCounter("OnCallAudioStateChanged");
mOnPostDialWaitCounter = new InvokeCounter("OnPostDialWait");
mOnCannedTextResponsesLoadedCounter = new InvokeCounter("OnCannedTextResponsesLoaded");
+ mOnConnectionEventCounter = new InvokeCounter("OnConnectionEvent");
+ mOnExtrasChangedCounter = new InvokeCounter("OnDetailsChangedCounter");
+ mOnPropertiesChangedCounter = new InvokeCounter("OnPropertiesChangedCounter");
}
/**
@@ -297,6 +321,7 @@
if (mInCallCallbacks.getService() != null) {
currentCallCount = mInCallCallbacks.getService().getCallCount();
}
+ int currentConnectionCount = getNumberOfConnections();
placeNewCallWithPhoneAccount(extras, videoState);
try {
@@ -311,6 +336,20 @@
assertEquals("InCallService should contain 1 more call after adding a call.",
currentCallCount + 1,
mInCallCallbacks.getService().getCallCount());
+
+ // The connectionService.lock is released in
+ // MockConnectionService#onCreateOutgoingConnection, however the connection will not
+ // actually be added to the list of connections in the ConnectionService until shortly
+ // afterwards. So there is still a potential for the lock to be released before it would
+ // be seen by calls to ConnectionService#getAllConnections().
+ // We will wait here until the list of connections includes one more connection to ensure
+ // that placing the call has fully completed.
+ final int expectedConnectionCount = currentConnectionCount + 1;
+ assertCSConnections(expectedConnectionCount);
+ }
+
+ int getNumberOfConnections() {
+ return CtsConnectionService.getAllConnectionsFromTelecom().size();
}
MockConnection verifyConnectionForOutgoingCall() {
@@ -520,6 +559,24 @@
);
}
+ void assertCSConnections(final int numConnections) {
+ waitUntilConditionIsTrueOrTimeout(new Condition() {
+ @Override
+ public Object expected() {
+ return numConnections;
+ }
+
+ @Override
+ public Object actual() {
+ return CtsConnectionService
+ .getAllConnectionsFromTelecom()
+ .size();
+ }
+ },
+ WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
+ "ConnectionService should contain " + numConnections + " connections."
+ );
+ }
void assertNumConnections(final MockConnectionService connService, final int numConnections) {
waitUntilConditionIsTrueOrTimeout(new Condition() {
@@ -865,6 +922,30 @@
);
}
+ /**
+ * Asserts that a call's properties are as expected.
+ *
+ * @param call The call.
+ * @param properties The expected properties.
+ */
+ public void assertCallProperties(final Call call, final int properties) {
+ waitUntilConditionIsTrueOrTimeout(
+ new Condition() {
+ @Override
+ public Object expected() {
+ return true;
+ }
+
+ @Override
+ public Object actual() {
+ return call.getDetails().hasProperty(properties);
+ }
+ },
+ TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
+ "Call should have properties " + properties
+ );
+ }
+
void waitUntilConditionIsTrueOrTimeout(Condition condition, long timeout,
String description) {
final long start = System.currentTimeMillis();
@@ -982,4 +1063,25 @@
}
}
}
+
+ public static boolean areBundlesEqual(Bundle extras, Bundle newExtras) {
+ if (extras == null || newExtras == null) {
+ return extras == newExtras;
+ }
+
+ if (extras.size() != newExtras.size()) {
+ return false;
+ }
+
+ for (String key : extras.keySet()) {
+ if (key != null) {
+ final Object value = extras.get(key);
+ final Object newValue = newExtras.get(key);
+ if (!Objects.equals(value, newValue)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
}
diff --git a/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java b/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java
index 0be05d6..c8e927f 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java
@@ -29,24 +29,32 @@
import android.telecom.ConnectionRequest;
import android.telecom.DisconnectCause;
import android.telecom.GatewayInfo;
-import android.telecom.InCallService;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.StatusHints;
import android.telecom.TelecomManager;
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.List;
/**
* Suites of tests that verifies the various Call details.
*/
public class CallDetailsTest extends BaseTelecomTestWithMockServices {
+ /**
+ * {@link Connection#PROPERTY_HIGH_DEF_AUDIO} is @hide, so define it here for now.
+ */
+ public static final int PROPERTY_HIGH_DEF_AUDIO = 1<<2;
+
+ /**
+ * {@link Connection#PROPERTY_WIFI} is @hide, so define it here for now.
+ */
+ public static final int PROPERTY_WIFI = 1<<3;
+ public static final int CONNECTION_PROPERTIES = PROPERTY_HIGH_DEF_AUDIO | PROPERTY_WIFI;
public static final int CONNECTION_CAPABILITIES =
- Connection.CAPABILITY_HOLD | Connection.CAPABILITY_MUTE |
- /**
- * CAPABILITY_HIGH_DEF_AUDIO & CAPABILITY_WIFI are hidden, so
- * hardcoding the values for now.
- */
- 0x00008000 | 0x00010000;
+ Connection.CAPABILITY_HOLD | Connection.CAPABILITY_MUTE;
public static final int CALL_CAPABILITIES =
Call.Details.CAPABILITY_HOLD | Call.Details.CAPABILITY_MUTE;
public static final int CALL_PROPERTIES =
@@ -57,14 +65,17 @@
public static final String TEST_CHILD_NUMBER = "650-555-1212";
public static final String TEST_FORWARDED_NUMBER = "650-555-1212";
public static final String TEST_EXTRA_KEY = "com.test.extra.TEST";
+ public static final String TEST_EXTRA_KEY2 = "com.test.extra.TEST2";
+ public static final String TEST_EXTRA_KEY3 = "com.test.extra.TEST3";
public static final int TEST_EXTRA_VALUE = 10;
+ public static final String TEST_EVENT = "com.test.event.TEST";
private StatusHints mStatusHints;
private Bundle mExtras = new Bundle();
private MockInCallService mInCallService;
private Call mCall;
- private Connection mConnection;
+ private MockConnection mConnection;
@Override
protected void setUp() throws Exception {
@@ -79,9 +90,10 @@
Connection connection = super.onCreateOutgoingConnection(
connectionManagerPhoneAccount,
request);
- mConnection = connection;
+ mConnection = (MockConnection) connection;
// Modify the connection object created with local values.
connection.setConnectionCapabilities(CONNECTION_CAPABILITIES);
+ connection.setConnectionProperties(CONNECTION_PROPERTIES);
connection.setCallerDisplayName(
CALLER_DISPLAY_NAME,
CALLER_DISPLAY_NAME_PRESENTATION);
@@ -402,6 +414,189 @@
}
/**
+ * Tests that {@link Connection} extras changes made via {@link Connection#putExtras(Bundle)}
+ * are propagated to the {@link Call} via
+ * {@link android.telecom.Call.Callback#onDetailsChanged(Call, Call.Details)}.
+ */
+ public void testConnectionPutExtras() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
+ Bundle testBundle = new Bundle();
+ testBundle.putString(TEST_EXTRA_KEY, TEST_SUBJECT);
+ testBundle.putInt(TEST_EXTRA_KEY2, TEST_EXTRA_VALUE);
+ mConnection.putExtras(testBundle);
+ // Wait for the 2nd invocation; setExtras is called in the setup method.
+ mOnExtrasChangedCounter.waitForCount(2, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
+
+ Bundle extras = mCall.getDetails().getExtras();
+ assertEquals(2, extras.size());
+ assertTrue(extras.containsKey(TEST_EXTRA_KEY));
+ assertEquals(TEST_SUBJECT, extras.getString(TEST_EXTRA_KEY));
+ assertTrue(extras.containsKey(TEST_EXTRA_KEY2));
+ assertEquals(TEST_EXTRA_VALUE, extras.getInt(TEST_EXTRA_KEY2));
+ }
+
+ /**
+ * Tests that {@link Connection} extras changes made via {@link Connection#removeExtras(List)}
+ * are propagated to the {@link Call} via
+ * {@link android.telecom.Call.Callback#onDetailsChanged(Call, Call.Details)}.
+ */
+ public void testConnectionRemoveExtras() {
+ testConnectionPutExtras();
+
+ mConnection.removeExtras(Arrays.asList(TEST_EXTRA_KEY));
+ // testConnectionPutExtra will have waited for the 2nd invocation, so wait for the 3rd here.
+ mOnExtrasChangedCounter.waitForCount(3, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
+
+ Bundle extras = mCall.getDetails().getExtras();
+ assertEquals(1, extras.size());
+ assertFalse(extras.containsKey(TEST_EXTRA_KEY));
+ assertTrue(extras.containsKey(TEST_EXTRA_KEY2));
+ assertEquals(TEST_EXTRA_VALUE, extras.getInt(TEST_EXTRA_KEY2));
+ }
+
+ /**
+ * Tests that {@link Call} extras changes made via {@link Call#putExtras(Bundle)} are propagated
+ * to {@link Connection#onExtrasChanged(Bundle)}.
+ */
+ public void testCallPutExtras() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
+ Bundle testBundle = new Bundle();
+ testBundle.putString(TEST_EXTRA_KEY, TEST_SUBJECT);
+ final InvokeCounter counter = mConnection.getInvokeCounter(
+ MockConnection.ON_EXTRAS_CHANGED);
+ mCall.putExtras(testBundle);
+ counter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
+ Bundle extras = mConnection.getExtras();
+
+ assertNotNull(extras);
+ assertTrue(extras.containsKey(TEST_EXTRA_KEY));
+ assertEquals(TEST_SUBJECT, extras.getString(TEST_EXTRA_KEY));
+ }
+
+ /**
+ * Tests that {@link Call} extra operations using {@link Call#removeExtras(List)} are propagated
+ * to the {@link Connection} via {@link Connection#onExtrasChanged(Bundle)}.
+ *
+ * This test specifically tests addition and removal of extras values.
+ */
+ public void testCallRemoveExtras() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
+ Bundle testBundle = new Bundle();
+ testBundle.putString(TEST_EXTRA_KEY, TEST_SUBJECT);
+ testBundle.putInt(TEST_EXTRA_KEY2, TEST_EXTRA_VALUE);
+ testBundle.putString(TEST_EXTRA_KEY3, TEST_SUBJECT);
+ final InvokeCounter counter = mConnection.getInvokeCounter(
+ MockConnection.ON_EXTRAS_CHANGED);
+ mCall.putExtras(testBundle);
+ counter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
+ Bundle extras = mConnection.getExtras();
+
+ assertNotNull(extras);
+ assertTrue(extras.containsKey(TEST_EXTRA_KEY));
+ assertEquals(TEST_SUBJECT, extras.getString(TEST_EXTRA_KEY));
+ assertTrue(extras.containsKey(TEST_EXTRA_KEY2));
+ assertEquals(TEST_EXTRA_VALUE, extras.getInt(TEST_EXTRA_KEY2));
+ assertTrue(extras.containsKey(TEST_EXTRA_KEY3));
+ assertEquals(TEST_SUBJECT, extras.getString(TEST_EXTRA_KEY3));
+
+ mCall.removeExtras(Arrays.asList(TEST_EXTRA_KEY));
+ counter.waitForCount(2, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
+ extras = mConnection.getExtras();
+ assertNotNull(extras);
+ assertFalse(extras.containsKey(TEST_EXTRA_KEY));
+ assertTrue(extras.containsKey(TEST_EXTRA_KEY2));
+ assertEquals(TEST_EXTRA_VALUE, extras.getInt(TEST_EXTRA_KEY2));
+ assertTrue(extras.containsKey(TEST_EXTRA_KEY3));
+ assertEquals(TEST_SUBJECT, extras.getString(TEST_EXTRA_KEY3));
+
+ mCall.removeExtras(Arrays.asList(TEST_EXTRA_KEY2, TEST_EXTRA_KEY3));
+ counter.waitForCount(3, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
+ extras = mConnection.getExtras();
+ assertTrue(extras.isEmpty());
+ }
+
+ /**
+ * Tests that {@link Connection} events are propagated from
+ * {@link Connection#sendConnectionEvent(String, Bundle)} to
+ * {@link android.telecom.Call.Callback#onConnectionEvent(Call, String, Bundle)}.
+ */
+ public void testConnectionEvent() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
+ Bundle testBundle = new Bundle();
+ testBundle.putString(TEST_EXTRA_KEY, TEST_SUBJECT);
+
+ mConnection.sendConnectionEvent(Connection.EVENT_CALL_PULL_FAILED, testBundle);
+ mOnConnectionEventCounter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
+ String event = (String) (mOnConnectionEventCounter.getArgs(0)[1]);
+ Bundle extras = (Bundle) (mOnConnectionEventCounter.getArgs(0)[2]);
+
+ assertEquals(Connection.EVENT_CALL_PULL_FAILED, event);
+ assertNotNull(extras);
+ assertTrue(extras.containsKey(TEST_EXTRA_KEY));
+ assertEquals(TEST_SUBJECT, extras.getString(TEST_EXTRA_KEY));
+ }
+
+ /**
+ * Tests that {@link Call} events are propagated from {@link Call#sendCallEvent(String, Bundle)}
+ * to {@link Connection#onCallEvent(String, Bundle)}.
+ */
+ public void testCallEvent() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
+ Bundle testBundle = new Bundle();
+ testBundle.putString(TEST_EXTRA_KEY, TEST_SUBJECT);
+ final InvokeCounter counter = mConnection.getInvokeCounter(MockConnection.ON_CALL_EVENT);
+ mCall.sendCallEvent(TEST_EVENT, testBundle);
+ counter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
+
+ String event = (String) (counter.getArgs(0)[0]);
+ Bundle extras = (Bundle) (counter.getArgs(0)[1]);
+
+ assertEquals(TEST_EVENT, event);
+ assertNotNull(extras);
+ assertTrue(extras.containsKey(TEST_EXTRA_KEY));
+ assertEquals(TEST_SUBJECT, extras.getString(TEST_EXTRA_KEY));
+ }
+
+ /**
+ * Tests that a request to pull an external call via {@link Call#pullExternalCall()} is
+ * communicated to the {@link Connection} via {@link Connection#onPullExternalCall()}.
+ */
+ public void testPullExternalCall() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
+ // First, configure the connection as an external call which is pullable.
+ int properties = mConnection.getConnectionProperties();
+ int capabilities = mConnection.getConnectionCapabilities();
+ properties |= Connection.PROPERTY_IS_EXTERNAL_CALL;
+ capabilities |= Connection.CAPABILITY_CAN_PULL_CALL;
+ mConnection.setConnectionCapabilities(capabilities);
+ mConnection.setConnectionProperties(properties);
+ assertCallProperties(mCall, Call.Details.PROPERTY_IS_EXTERNAL_CALL);
+
+ final InvokeCounter counter = mConnection.getInvokeCounter(
+ MockConnection.ON_PULL_EXTERNAL_CALL);
+ mCall.pullExternalCall();
+ counter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
+ }
+
+ /**
* Asserts that a call's capabilities are as expected.
*
* @param call The call.
diff --git a/tests/tests/telecom/src/android/telecom/cts/CallTest.java b/tests/tests/telecom/src/android/telecom/cts/CallTest.java
index efbb69f..b892ede 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CallTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CallTest.java
@@ -31,6 +31,8 @@
assertTrue(Call.Details.can(CAPABILITY_MERGE_CONFERENCE
| CAPABILITY_DISCONNECT_FROM_CONFERENCE | CAPABILITY_MUTE,
CAPABILITY_MUTE));
+ assertTrue(Call.Details.can(CAPABILITY_CAN_PAUSE_VIDEO, CAPABILITY_CAN_PAUSE_VIDEO));
+ assertTrue(Call.Details.can(CAPABILITY_CAN_PULL_CALL, CAPABILITY_CAN_PULL_CALL));
assertFalse(Call.Details.can(CAPABILITY_MUTE, CAPABILITY_HOLD));
assertFalse(Call.Details.can(CAPABILITY_MERGE_CONFERENCE
@@ -78,6 +80,7 @@
assertTrue(Call.Details.hasProperty(PROPERTY_HIGH_DEF_AUDIO, PROPERTY_HIGH_DEF_AUDIO));
assertTrue(Call.Details.hasProperty(PROPERTY_HIGH_DEF_AUDIO | PROPERTY_CONFERENCE
| PROPERTY_WIFI, PROPERTY_CONFERENCE));
+ assertTrue(Call.Details.hasProperty(PROPERTY_IS_EXTERNAL_CALL, PROPERTY_IS_EXTERNAL_CALL));
assertFalse(Call.Details.hasProperty(PROPERTY_WIFI, PROPERTY_CONFERENCE));
assertFalse(Call.Details.hasProperty(PROPERTY_HIGH_DEF_AUDIO | PROPERTY_CONFERENCE
diff --git a/tests/tests/telecom/src/android/telecom/cts/ConferenceTest.java b/tests/tests/telecom/src/android/telecom/cts/ConferenceTest.java
index 508870c..c3168f6 100644
--- a/tests/tests/telecom/src/android/telecom/cts/ConferenceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/ConferenceTest.java
@@ -29,8 +29,11 @@
import android.telecom.StatusHints;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
+import android.util.Log;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
/**
* Extended suite of tests that use {@link CtsConnectionService} and {@link MockInCallService} to
@@ -38,6 +41,11 @@
*/
public class ConferenceTest extends BaseTelecomTestWithMockServices {
+ private static final String TEST_EXTRA_KEY_1 = "android.telecom.test.KEY1";
+ private static final String TEST_EXTRA_KEY_2 = "android.telecom.test.KEY2";
+ private static final String TEST_EXTRA_VALUE_1 = "test";
+ private static final int TEST_EXTRA_VALUE_2 = 42;
+
public static final int CONF_CAPABILITIES = Connection.CAPABILITY_SEPARATE_FROM_CONFERENCE |
Connection.CAPABILITY_DISCONNECT_FROM_CONFERENCE | Connection.CAPABILITY_HOLD |
Connection.CAPABILITY_MERGE_CONFERENCE | Connection.CAPABILITY_SWAP_CONFERENCE;
@@ -45,7 +53,7 @@
private Call mCall1, mCall2;
private MockConnection mConnection1, mConnection2;
MockInCallService mInCallService;
- Conference mConferenceObject;
+ MockConference mConferenceObject;
@Override
protected void setUp() throws Exception {
@@ -213,6 +221,94 @@
assertCallState(conf, Call.STATE_DISCONNECTED);
}
+ /**
+ * Tests end to end propagation of the {@link Conference} properties to the associated
+ * {@link Call}.
+ */
+ public void testConferenceProperties() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+ final Call conf = mInCallService.getLastConferenceCall();
+ assertCallState(conf, Call.STATE_ACTIVE);
+
+ int properties = mConferenceObject.getConnectionProperties();
+ properties |= Connection.PROPERTY_IS_EXTERNAL_CALL;
+
+ mConferenceObject.setConnectionProperties(properties);
+
+ // Wait for 2nd properties change; the first will be when the conference is marked with
+ // Call.Details.PROPERTY_CONFERENCE.
+ assertCallProperties(conf, Call.Details.PROPERTY_IS_EXTERNAL_CALL);
+ assertTrue(conf.getDetails().hasProperty(Call.Details.PROPERTY_IS_EXTERNAL_CALL));
+ }
+
+ /**
+ * Verifies {@link Conference#putExtras(Bundle)} calls are propagated to
+ * {@link android.telecom.Call.Callback#onDetailsChanged(Call, Call.Details)}.
+ */
+ public void testConferencePutExtras() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+ final Call conf = mInCallService.getLastConferenceCall();
+ assertCallState(conf, Call.STATE_ACTIVE);
+
+ Bundle extras = new Bundle();
+ extras.putString(TEST_EXTRA_KEY_1, TEST_EXTRA_VALUE_1);
+ extras.putInt(TEST_EXTRA_KEY_2, TEST_EXTRA_VALUE_2);
+ mConferenceObject.putExtras(extras);
+
+ mOnExtrasChangedCounter.waitForCount(1);
+
+ assertTrue(areBundlesEqual(extras, conf.getDetails().getExtras()));
+ }
+
+ /**
+ * Verifies {@link Conference#removeExtras(List)} calls are propagated to
+ * {@link android.telecom.Call.Callback#onDetailsChanged(Call, Call.Details)}.
+ */
+ public void testConferenceRemoveExtras() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+ final Call conf = mInCallService.getLastConferenceCall();
+ assertCallState(conf, Call.STATE_ACTIVE);
+
+ Bundle extras = new Bundle();
+ extras.putString(TEST_EXTRA_KEY_1, TEST_EXTRA_VALUE_1);
+ extras.putInt(TEST_EXTRA_KEY_2, TEST_EXTRA_VALUE_2);
+ mConferenceObject.putExtras(extras);
+ mOnExtrasChangedCounter.waitForCount(1);
+
+ mConferenceObject.removeExtras(Arrays.asList(TEST_EXTRA_KEY_1));
+ mOnExtrasChangedCounter.waitForCount(2);
+ extras = mConferenceObject.getExtras();
+
+ assertFalse(extras.containsKey(TEST_EXTRA_KEY_1));
+ assertTrue(extras.containsKey(TEST_EXTRA_KEY_2));
+ }
+
+ /**
+ * Verifies {@link android.telecom.Call#putExtras(Bundle)} changes are propagated to
+ * {@link Conference#onExtrasChanged(Bundle)}.
+ */
+ public void testConferenceOnExtraschanged() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+ final Call conf = mInCallService.getLastConferenceCall();
+ assertCallState(conf, Call.STATE_ACTIVE);
+
+ Bundle extras = new Bundle();
+ extras.putString(TEST_EXTRA_KEY_1, TEST_EXTRA_VALUE_1);
+ extras.putInt(TEST_EXTRA_KEY_2, TEST_EXTRA_VALUE_2);
+ conf.putExtras(extras);
+ mConferenceObject.mOnExtrasChanged.waitForCount(1);
+
+ assertTrue(areBundlesEqual(extras, mConferenceObject.getExtras()));
+ }
+
public void testConferenceAddAndRemoveConnection() {
if (!mShouldTestTelecom) {
return;
diff --git a/tests/tests/telecom/src/android/telecom/cts/ConnectionTest.java b/tests/tests/telecom/src/android/telecom/cts/ConnectionTest.java
index b6818c8..874f116 100644
--- a/tests/tests/telecom/src/android/telecom/cts/ConnectionTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/ConnectionTest.java
@@ -27,6 +27,8 @@
import android.telecom.TelecomManager;
import android.test.AndroidTestCase;
+import java.util.Arrays;
+import java.util.List;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
@@ -162,6 +164,22 @@
assertEquals(capabilities, connection.getConnectionCapabilities());
}
+ public void testSetAndGetConnectionProperties() {
+ if (!shouldTestTelecom(getContext())) {
+ return;
+ }
+
+ final Semaphore lock = new Semaphore(0);
+ Connection connection = createConnection(lock);
+ waitForStateChange(lock);
+
+ final int properties = Connection.PROPERTY_IS_EXTERNAL_CALL;
+
+ connection.setConnectionProperties(properties);
+
+ assertEquals(properties, connection.getConnectionProperties());
+ }
+
public void testSetAndGetDisconnectCause() {
if (!shouldTestTelecom(getContext())) {
return;
@@ -215,6 +233,79 @@
assertTrue(extras.getBoolean("test-extra-key"));
}
+ /**
+ * Basic local test of adding extra keys via {@link Connection#removeExtras(List)}.
+ *
+ * Extended end-to-end passing of extras is verified in
+ * {@link CallDetailsTest#testConnectionPutExtras()} and
+ * @link CallDetailsTest#testConnectionRemoveExtras()}.
+ */
+ public void testPutExtras() {
+ if (!shouldTestTelecom(getContext())) {
+ return;
+ }
+
+ final Semaphore lock = new Semaphore(0);
+ Connection connection = createConnection(lock);
+ waitForStateChange(lock);
+
+ assertEquals(null, connection.getExtras());
+
+ final Bundle extras = new Bundle();
+ extras.putBoolean("test-extra-key", true);
+ connection.putExtras(extras);
+
+ final Bundle retrieved = connection.getExtras();
+ assertNotNull(retrieved);
+ assertTrue(extras.getBoolean("test-extra-key"));
+ }
+
+ /**
+ * Basic local test of removing extra keys via {@link Connection#removeExtras(List)}.
+ *
+ * Extended end-to-end passing of extras is verified in
+ * {@link CallDetailsTest#testConnectionPutExtras()} and
+ * @link CallDetailsTest#testConnectionRemoveExtras()}.
+ */
+ public void testRemoveExtras() {
+ if (!shouldTestTelecom(getContext())) {
+ return;
+ }
+
+ final Semaphore lock = new Semaphore(0);
+ Connection connection = createConnection(lock);
+ waitForStateChange(lock);
+
+ assertEquals(null, connection.getExtras());
+
+ final Bundle extras = new Bundle();
+ extras.putBoolean("test-extra-key", true);
+ connection.putExtras(extras);
+ connection.removeExtras(Arrays.asList("test-extra-key"));
+
+ final Bundle retrieved = connection.getExtras();
+ assertNotNull(retrieved);
+ assertFalse(extras.containsKey("test-extra-key"));
+ }
+
+ /**
+ * Tests that the {@link Connection#sendConnectionEvent(String, Bundle)} method exists and can
+ * be called.
+ *
+ * Actual end-to-end tests can be found in {@link CallDetailsTest#testConnectionEvent()}.
+ */
+ public void testSendConnectionEvent() {
+ if (!shouldTestTelecom(getContext())) {
+ return;
+ }
+
+ final Semaphore lock = new Semaphore(0);
+ Connection connection = createConnection(lock);
+ waitForStateChange(lock);
+
+ connection.sendConnectionEvent("test", null);
+ }
+
public void testSetAndGetStatusHints() {
if (!shouldTestTelecom(getContext())) {
return;
@@ -293,6 +384,18 @@
| Connection.CAPABILITY_MANAGE_CONFERENCE));
}
+ /**
+ * Tests the {@link Connection#propertiesToString(int)} method.
+ */
+ public void testPropertiesToString() {
+ if (!shouldTestTelecom(getContext())) {
+ return;
+ }
+
+ assertEquals("[Properties: PROPERTY_IS_EXTERNAL_CALL]",
+ Connection.propertiesToString(Connection.PROPERTY_IS_EXTERNAL_CALL));
+ }
+
private static Connection createConnection(final Semaphore lock) {
BasicConnection connection = new BasicConnection();
connection.setLock(lock);
diff --git a/tests/tests/telecom/src/android/telecom/cts/CtsConnectionService.java b/tests/tests/telecom/src/android/telecom/cts/CtsConnectionService.java
index 2364986..e820e10 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CtsConnectionService.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CtsConnectionService.java
@@ -29,6 +29,7 @@
import android.util.Log;
import java.util.Collection;
+import java.util.Collections;
/**
* This is the official ConnectionService for Telecom's CTS App. Since telecom requires that a
@@ -154,6 +155,9 @@
public static Collection<Connection> getAllConnectionsFromTelecom() {
synchronized(sLock) {
+ if (sTelecomConnectionService == null) {
+ return Collections.EMPTY_LIST;
+ }
return sTelecomConnectionService.getAllConnections();
}
}
diff --git a/tests/tests/telecom/src/android/telecom/cts/MockConference.java b/tests/tests/telecom/src/android/telecom/cts/MockConference.java
index 647d039..d84610d 100644
--- a/tests/tests/telecom/src/android/telecom/cts/MockConference.java
+++ b/tests/tests/telecom/src/android/telecom/cts/MockConference.java
@@ -16,6 +16,7 @@
package android.telecom.cts;
+import android.os.Bundle;
import android.telecom.Conference;
import android.telecom.Connection;
import android.telecom.DisconnectCause;
@@ -31,6 +32,8 @@
private RemoteConference mRemoteConference = null;
private String mDtmfString = "";
+ public BaseTelecomTestWithMockServices.InvokeCounter mOnExtrasChanged =
+ new BaseTelecomTestWithMockServices.InvokeCounter("onExtrasChanged");
public MockConference(PhoneAccountHandle phoneAccount) {
super(phoneAccount);
@@ -149,4 +152,9 @@
public String getDtmfString() {
return mDtmfString;
}
+
+ @Override
+ public void onExtrasChanged(Bundle extras) {
+ mOnExtrasChanged.invoke(extras);
+ }
}
diff --git a/tests/tests/telecom/src/android/telecom/cts/MockConnection.java b/tests/tests/telecom/src/android/telecom/cts/MockConnection.java
index fe33a8d..4436219 100644
--- a/tests/tests/telecom/src/android/telecom/cts/MockConnection.java
+++ b/tests/tests/telecom/src/android/telecom/cts/MockConnection.java
@@ -17,6 +17,8 @@
package android.telecom.cts;
import static android.telecom.CallAudioState.*;
+
+import android.os.Bundle;
import android.telecom.CallAudioState;
import android.telecom.Connection;
import android.telecom.DisconnectCause;
@@ -32,6 +34,9 @@
*/
public class MockConnection extends Connection {
public static final int ON_POST_DIAL_WAIT = 1;
+ public static final int ON_CALL_EVENT = 2;
+ public static final int ON_PULL_EXTERNAL_CALL = 3;
+ public static final int ON_EXTRAS_CHANGED = 4;
private CallAudioState mCallAudioState =
new CallAudioState(false, CallAudioState.ROUTE_EARPIECE, ROUTE_EARPIECE | ROUTE_SPEAKER);
@@ -158,6 +163,30 @@
}
}
+ @Override
+ public void onCallEvent(String event, Bundle extras) {
+ super.onCallEvent(event, extras);
+ if (mInvokeCounterMap.get(ON_CALL_EVENT) != null) {
+ mInvokeCounterMap.get(ON_CALL_EVENT).invoke(event, extras);
+ }
+ }
+
+ @Override
+ public void onPullExternalCall() {
+ super.onPullExternalCall();
+ if (mInvokeCounterMap.get(ON_PULL_EXTERNAL_CALL) != null) {
+ mInvokeCounterMap.get(ON_PULL_EXTERNAL_CALL).invoke();
+ }
+ }
+
+ @Override
+ public void onExtrasChanged(Bundle extras) {
+ super.onExtrasChanged(extras);
+ if (mInvokeCounterMap.get(ON_EXTRAS_CHANGED) != null) {
+ mInvokeCounterMap.get(ON_EXTRAS_CHANGED).invoke(extras);
+ }
+ }
+
public int getCurrentState() {
return mState;
}
@@ -239,6 +268,12 @@
switch (counterIndex) {
case ON_POST_DIAL_WAIT:
return "onPostDialWait";
+ case ON_CALL_EVENT:
+ return "onCallEvent";
+ case ON_PULL_EXTERNAL_CALL:
+ return "onPullExternalCall";
+ case ON_EXTRAS_CHANGED:
+ return "onExtrasChanged";
default:
return "Callback";
}
diff --git a/tests/tests/telecom/src/android/telecom/cts/MockInCallService.java b/tests/tests/telecom/src/android/telecom/cts/MockInCallService.java
index c371ed1..9776c64 100644
--- a/tests/tests/telecom/src/android/telecom/cts/MockInCallService.java
+++ b/tests/tests/telecom/src/android/telecom/cts/MockInCallService.java
@@ -19,6 +19,7 @@
import static org.junit.Assert.assertTrue;
import android.content.Intent;
+import android.os.Bundle;
import android.telecom.Call;
import android.telecom.CallAudioState;
import android.telecom.InCallService;
@@ -58,6 +59,7 @@
public void onCallAudioStateChanged(CallAudioState audioState) {}
public void onPostDialWait(Call call, String remainingPostDialSequence) {}
public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {}
+ public void onConnectionEvent(Call call, String event, Bundle extras) {}
final public MockInCallService getService() {
return mService;
@@ -142,6 +144,14 @@
getCallbacks().onCannedTextResponsesLoaded(call, cannedTextResponses);
}
}
+
+ @Override
+ public void onConnectionEvent(Call call, String event, Bundle extras) {
+ super.onConnectionEvent(call, event, extras);
+ if (getCallbacks() != null) {
+ getCallbacks().onConnectionEvent(call, event, extras);
+ }
+ }
};
private void saveVideoCall(Call call, VideoCall videoCall) {
diff --git a/tests/tests/telecom/src/android/telecom/cts/PhoneAccountOperationsTest.java b/tests/tests/telecom/src/android/telecom/cts/PhoneAccountOperationsTest.java
index cc03288..4374516 100644
--- a/tests/tests/telecom/src/android/telecom/cts/PhoneAccountOperationsTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/PhoneAccountOperationsTest.java
@@ -22,6 +22,7 @@
import android.content.Context;
import android.graphics.Color;
import android.net.Uri;
+import android.os.Bundle;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
@@ -38,6 +39,16 @@
public class PhoneAccountOperationsTest extends InstrumentationTestCase {
public static final PhoneAccountHandle TEST_PHONE_ACCOUNT_HANDLE =
new PhoneAccountHandle(new ComponentName(PACKAGE, COMPONENT), ACCOUNT_ID);
+ public static final Bundle TEST_BUNDLE = createTestBundle();
+ public static final int TEST_LENGTH = 10;
+ public static final String TEST_ENCODING = "enUS";
+
+ private static Bundle createTestBundle() {
+ Bundle testBundle = new Bundle();
+ testBundle.putInt(PhoneAccount.EXTRA_CALL_SUBJECT_MAX_LENGTH, TEST_LENGTH);
+ testBundle.putString(PhoneAccount.EXTRA_CALL_SUBJECT_CHARACTER_ENCODING, TEST_ENCODING);
+ return testBundle;
+ }
public static final PhoneAccount TEST_SIM_PHONE_ACCOUNT = PhoneAccount.builder(
TEST_PHONE_ACCOUNT_HANDLE, ACCOUNT_LABEL)
@@ -59,6 +70,7 @@
.setShortDescription(ACCOUNT_LABEL)
.setSupportedUriSchemes(Arrays.asList(
PhoneAccount.SCHEME_TEL, PhoneAccount.SCHEME_VOICEMAIL))
+ .setExtras(TEST_BUNDLE)
.build();
public static final PhoneAccount TEST_CALL_MANAGER_PHONE_ACCOUNT = PhoneAccount.builder(
@@ -185,6 +197,22 @@
PhoneAccount.CAPABILITY_VIDEO_CALLING));
}
+ public void testRegisterPhoneAccount_CheckExtras() throws Exception {
+ if (!shouldTestTelecom(mContext)) {
+ return;
+ }
+ mTelecomManager.registerPhoneAccount(TEST_NO_SIM_PHONE_ACCOUNT);
+ PhoneAccount retrievedPhoneAccount = mTelecomManager.getPhoneAccount(
+ TEST_PHONE_ACCOUNT_HANDLE);
+ Bundle extras = retrievedPhoneAccount.getExtras();
+ assertTrue(extras.containsKey(PhoneAccount.EXTRA_CALL_SUBJECT_CHARACTER_ENCODING));
+ assertEquals(TEST_ENCODING,
+ extras.getString(PhoneAccount.EXTRA_CALL_SUBJECT_CHARACTER_ENCODING));
+ assertTrue(extras.containsKey(PhoneAccount.EXTRA_CALL_SUBJECT_MAX_LENGTH));
+ assertEquals(TEST_LENGTH,
+ extras.getInt(PhoneAccount.EXTRA_CALL_SUBJECT_MAX_LENGTH));
+ }
+
public void testRegisterPhoneAccount_CheckURISchemeSupported() throws Exception {
if (!shouldTestTelecom(mContext)) {
return;
diff --git a/tests/tests/telecom/src/android/telecom/cts/RemoteConferenceTest.java b/tests/tests/telecom/src/android/telecom/cts/RemoteConferenceTest.java
index 787966a..eeb2ad7 100644
--- a/tests/tests/telecom/src/android/telecom/cts/RemoteConferenceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/RemoteConferenceTest.java
@@ -343,6 +343,35 @@
mRemoteConferenceObject.unregisterCallback(callback);
}
+ public void testRemoteConferenceCallbacks_ConnectionProperties() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+ Handler handler = setupRemoteConferenceCallbacksTest();
+
+ final InvokeCounter callbackInvoker =
+ new InvokeCounter("testRemoteConferenceCallbacks_ConnectionProperties");
+ RemoteConference.Callback callback;
+
+ callback = new RemoteConference.Callback() {
+ @Override
+ public void onConnectionPropertiesChanged(
+ RemoteConference conference,
+ int connectionProperties) {
+ super.onConnectionPropertiesChanged(conference, connectionProperties);
+ callbackInvoker.invoke(conference, connectionProperties);
+ }
+ };
+ mRemoteConferenceObject.registerCallback(callback, handler);
+ int properties = mRemoteConference.getConnectionCapabilities()
+ | Connection.PROPERTY_IS_EXTERNAL_CALL;
+ mRemoteConference.setConnectionProperties(properties);
+ callbackInvoker.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
+ assertEquals(mRemoteConferenceObject, callbackInvoker.getArgs(0)[0]);
+ assertEquals(properties, callbackInvoker.getArgs(0)[1]);
+ mRemoteConferenceObject.unregisterCallback(callback);
+ }
+
public void testRemoteConferenceCallbacks_ConferenceableConnections() {
if (!mShouldTestTelecom) {
return;
@@ -402,6 +431,7 @@
mRemoteConferenceObject.unregisterCallback(callback);
}
+
public void testRemoteConferenceCallbacks_Extras() {
if (!mShouldTestTelecom) {
return;
@@ -425,7 +455,7 @@
mRemoteConference.setExtras(extras);
callbackInvoker.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
assertEquals(mRemoteConferenceObject, callbackInvoker.getArgs(0)[0]);
- assertEquals(extras, callbackInvoker.getArgs(0)[1]);
+ assertTrue(areBundlesEqual(extras, (Bundle) callbackInvoker.getArgs(0)[1]));
mRemoteConferenceObject.unregisterCallback(callback);
}
diff --git a/tests/tests/telecom/src/android/telecom/cts/RemoteConnectionTest.java b/tests/tests/telecom/src/android/telecom/cts/RemoteConnectionTest.java
index 7d095db..81080b0 100644
--- a/tests/tests/telecom/src/android/telecom/cts/RemoteConnectionTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/RemoteConnectionTest.java
@@ -238,7 +238,36 @@
assertEquals(mRemoteConnectionObject, callbackInvoker.getArgs(0)[0]);
assertEquals(capabilities, callbackInvoker.getArgs(0)[1]);
mRemoteConnectionObject.unregisterCallback(callback);
+ }
+ public void testRemoteConnectionCallbacks_ConnectionProperties() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
+ Handler handler = setupRemoteConnectionCallbacksTest();
+
+ final InvokeCounter callbackInvoker =
+ new InvokeCounter("testRemoteConnectionCallbacks_ConnectionCapabilities");
+ RemoteConnection.Callback callback;
+
+ callback = new RemoteConnection.Callback() {
+ @Override
+ public void onConnectionPropertiesChanged(
+ RemoteConnection connection,
+ int connectionProperties) {
+ super.onConnectionPropertiesChanged(connection, connectionProperties);
+ callbackInvoker.invoke(connection, connectionProperties);
+ }
+ };
+ mRemoteConnectionObject.registerCallback(callback, handler);
+ int properties = mRemoteConnection.getConnectionCapabilities()
+ | Connection.PROPERTY_IS_EXTERNAL_CALL;
+ mRemoteConnection.setConnectionProperties(properties);
+ callbackInvoker.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
+ assertEquals(mRemoteConnectionObject, callbackInvoker.getArgs(0)[0]);
+ assertEquals(properties, callbackInvoker.getArgs(0)[1]);
+ mRemoteConnectionObject.unregisterCallback(callback);
}
public void testRemoteConnectionCallbacks_PostDialWait() {
@@ -525,9 +554,42 @@
mRemoteConnection.setExtras(extras);
callbackInvoker.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
assertEquals(mRemoteConnectionObject, callbackInvoker.getArgs(0)[0]);
- assertEquals(extras, callbackInvoker.getArgs(0)[1]);
+ assertTrue(areBundlesEqual(extras, (Bundle) callbackInvoker.getArgs(0)[1]));
mRemoteConnectionObject.unregisterCallback(callback);
+ }
+ /**
+ * Verifies that a {@link RemoteConnection} receives a
+ * {@link Connection#sendConnectionEvent(String, Bundle)} notification.
+ */
+ public void testRemoteConnectionCallbacks_ConnectionEvent() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
+ Handler handler = setupRemoteConnectionCallbacksTest();
+
+ final InvokeCounter callbackInvoker =
+ new InvokeCounter("testRemoteConnectionCallbacks_Extras");
+ RemoteConnection.Callback callback;
+
+ callback = new RemoteConnection.Callback() {
+ @Override
+ public void onConnectionEvent(RemoteConnection connection, String event,
+ Bundle extras) {
+ super.onConnectionEvent(connection, event, extras);
+ callbackInvoker.invoke(connection, event, extras);
+ }
+ };
+ mRemoteConnectionObject.registerCallback(callback, handler);
+ Bundle extras = new Bundle();
+ extras.putString(TelecomManager.EXTRA_CALL_DISCONNECT_MESSAGE, "Test");
+ mRemoteConnection.sendConnectionEvent(Connection.EVENT_CALL_PULL_FAILED, extras);
+ callbackInvoker.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
+ assertEquals(mRemoteConnectionObject, callbackInvoker.getArgs(0)[0]);
+ assertEquals(Connection.EVENT_CALL_PULL_FAILED, callbackInvoker.getArgs(0)[1]);
+ assertTrue(areBundlesEqual(extras, (Bundle) callbackInvoker.getArgs(0)[2]));
+ mRemoteConnectionObject.unregisterCallback(callback);
}
public void testRemoteConnectionCallbacks_Disconnect() {
@@ -559,6 +621,23 @@
mRemoteConnectionObject.unregisterCallback(callback);
}
+ /**
+ * Verifies that a call to {@link RemoteConnection#pullExternalCall()} is proxied to
+ * {@link Connection#onPullExternalCall()}.
+ */
+ public void testRemoteConnectionCallbacks_PullExternalCall() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
+ Handler handler = setupRemoteConnectionCallbacksTest();
+
+ InvokeCounter counter =
+ mRemoteConnection.getInvokeCounter(MockConnection.ON_PULL_EXTERNAL_CALL);
+ mRemoteConnectionObject.pullExternalCall();
+ counter.waitForCount(1);
+ }
+
public void testRemoteConnectionCallbacks_Destroy() {
if (!mShouldTestTelecom) {
return;
@@ -1106,6 +1185,8 @@
remoteConnection.getCallerDisplayNamePresentation());
assertEquals(connection.getConnectionCapabilities(),
remoteConnection.getConnectionCapabilities());
+ assertEquals(connection.getConnectionProperties(),
+ remoteConnection.getConnectionProperties());
assertEquals(connection.getDisconnectCause(), remoteConnection.getDisconnectCause());
assertEquals(connection.getExtras(), remoteConnection.getExtras());
assertEquals(connection.getStatusHints(), remoteConnection.getStatusHints());
diff --git a/tests/tests/text/src/android/text/cts/BoringLayoutTest.java b/tests/tests/text/src/android/text/cts/BoringLayoutTest.java
index 36d2f93..13465ae 100644
--- a/tests/tests/text/src/android/text/cts/BoringLayoutTest.java
+++ b/tests/tests/text/src/android/text/cts/BoringLayoutTest.java
@@ -82,11 +82,10 @@
private void verifyMultAddScale(float spacingMult, float spacingAdd) {
final int height = METRICS_BOTTOM - METRICS_TOP;
- final int bottomPadding = METRICS_BOTTOM - METRICS_DESCENT;
BoringLayout boringLayout = makeBoringLayout(spacingMult, spacingAdd);
assertEquals(height, boringLayout.getHeight());
- assertEquals(height + bottomPadding + METRICS_TOP, boringLayout.getLineDescent(0));
+ assertEquals(height + METRICS_TOP, boringLayout.getLineDescent(0));
}
public void testScale() {
@@ -172,10 +171,8 @@
}
public void testGetLineDescent_withIncludePadding() {
- final int bottomPadding = METRICS_BOTTOM - METRICS_DESCENT;
final int height = METRICS_BOTTOM - METRICS_TOP;
- assertEquals(height + METRICS_TOP + bottomPadding,
- mBoringLayout.getLineDescent(0));
+ assertEquals(height + METRICS_TOP, mBoringLayout.getLineDescent(0));
}
public void testGetLineDescent_withoutIncludePadding() {
diff --git a/tests/tests/tv/AndroidManifest.xml b/tests/tests/tv/AndroidManifest.xml
index 7acfc94..cc64363 100644
--- a/tests/tests/tv/AndroidManifest.xml
+++ b/tests/tests/tv/AndroidManifest.xml
@@ -85,6 +85,16 @@
android:resource="@xml/stub_tv_input_service" />
</service>
+ <service android:name="android.media.tv.cts.TvInputServiceTest$FaultyTvInputService"
+ android:permission="android.permission.BIND_TV_INPUT"
+ android:process=":faultyTvInputService">
+ <intent-filter>
+ <action android:name="android.media.tv.TvInputService" />
+ </intent-filter>
+ <meta-data android:name="android.media.tv.input"
+ android:resource="@xml/stub_tv_input_service" />
+ </service>
+
<service android:name="android.media.tv.cts.HardwareSessionTest$HardwareProxyTvInputService"
android:permission="android.permission.BIND_TV_INPUT">
<intent-filter>
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvInputServiceTest.java b/tests/tests/tv/src/android/media/tv/cts/TvInputServiceTest.java
index a821d97..9b60967 100644
--- a/tests/tests/tv/src/android/media/tv/cts/TvInputServiceTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/TvInputServiceTest.java
@@ -32,6 +32,7 @@
import android.media.tv.cts.TvInputServiceTest.CountingTvInputService.CountingRecordingSession;
import android.net.Uri;
import android.os.Bundle;
+import android.os.Process;
import android.os.SystemClock;
import android.test.ActivityInstrumentationTestCase2;
import android.view.InputDevice;
@@ -65,6 +66,7 @@
private Instrumentation mInstrumentation;
private TvInputManager mManager;
private TvInputInfo mStubInfo;
+ private TvInputInfo mFaultyStubInfo;
private final StubCallback mCallback = new StubCallback();
private final StubTimeShiftPositionCallback mTimeShiftPositionCallback =
new StubTimeShiftPositionCallback();
@@ -177,6 +179,11 @@
for (TvInputInfo info : mManager.getTvInputList()) {
if (info.getServiceInfo().name.equals(CountingTvInputService.class.getName())) {
mStubInfo = info;
+ }
+ if (info.getServiceInfo().name.equals(FaultyTvInputService.class.getName())) {
+ mFaultyStubInfo = info;
+ }
+ if (mStubInfo != null && mFaultyStubInfo != null) {
break;
}
}
@@ -233,13 +240,16 @@
return;
}
verifyCommandTuneForRecording();
+ verifyCallbackConnectionFailed();
verifyCommandTuneForRecordingWithBundle();
verifyCallbackTuned();
verifyCommandStartRecording();
verifyCommandStopRecording();
+ verifyCommandSendAppPrivateCommandForRecording();
verifyCallbackRecordingStopped();
verifyCallbackError();
verifyCommandRelease();
+ verifyCallbackDisconnected();
}
public void verifyCommandTuneForRecording() {
@@ -263,7 +273,7 @@
@Override
protected boolean check() {
CountingRecordingSession session = CountingTvInputService.sRecordingSession;
- return session != null && session.mTuneCount > 0;
+ return session != null && session.mTuneWithBundleCount > 0;
}
}.run();
}
@@ -304,6 +314,20 @@
}.run();
}
+ public void verifyCommandSendAppPrivateCommandForRecording() {
+ resetCounts();
+ String action = "android.media.tv.cts.TvInputServiceTest.privateCommand";
+ mTvRecordingClient.sendAppPrivateCommand(action, null);
+ new PollingCheck(TIME_OUT) {
+ @Override
+ protected boolean check() {
+ CountingRecordingSession session = CountingTvInputService.sRecordingSession;
+ return session != null && session.mAppPrivateCommandCount > 0;
+ }
+ }.run();
+ }
+
+
public void verifyCallbackTuned() {
resetCounts();
CountingRecordingSession session = CountingTvInputService.sRecordingSession;
@@ -345,16 +369,26 @@
}.run();
}
- public void verifyCommandSendAppPrivateCommand() {
+ public void verifyCallbackConnectionFailed() {
resetCounts();
- String action = "android.media.tv.cts.TvInputServiceTest.privateCommand";
- mTvView.sendAppPrivateCommand(action, null);
- mInstrumentation.waitForIdleSync();
+ Uri fakeChannelUri = TvContract.buildChannelUri(0);
+ mTvRecordingClient.tune("invalid_input_id", fakeChannelUri);
new PollingCheck(TIME_OUT) {
@Override
protected boolean check() {
- CountingSession session = CountingTvInputService.sSession;
- return session != null && session.mSendAppPrivateCommand > 0;
+ return mRecordingCallback.mConnectionFailedCount > 0;
+ }
+ }.run();
+ }
+
+ public void verifyCallbackDisconnected() {
+ resetCounts();
+ Uri fakeChannelUri = TvContract.buildChannelUri(0);
+ mTvRecordingClient.tune(mFaultyStubInfo.getId(), fakeChannelUri);
+ new PollingCheck(TIME_OUT) {
+ @Override
+ protected boolean check() {
+ return mRecordingCallback.mDisconnectedCount > 0;
}
}.run();
}
@@ -382,7 +416,7 @@
@Override
protected boolean check() {
CountingSession session = CountingTvInputService.sSession;
- return session != null && session.mTuneCount > 0;
+ return session != null && session.mTuneWithBundleCount > 0;
}
}.run();
}
@@ -613,6 +647,20 @@
}.run();
}
+ public void verifyCommandSendAppPrivateCommand() {
+ resetCounts();
+ String action = "android.media.tv.cts.TvInputServiceTest.privateCommand";
+ mTvView.sendAppPrivateCommand(action, null);
+ mInstrumentation.waitForIdleSync();
+ new PollingCheck(TIME_OUT) {
+ @Override
+ protected boolean check() {
+ CountingSession session = CountingTvInputService.sSession;
+ return session != null && session.mAppPrivateCommandCount > 0;
+ }
+ }.run();
+ }
+
public void verifyCallbackChannelRetuned() {
resetCounts();
CountingSession session = CountingTvInputService.sSession;
@@ -792,8 +840,8 @@
}
public static class CountingSession extends Session {
- public volatile int mSendAppPrivateCommand;
public volatile int mTuneCount;
+ public volatile int mTuneWithBundleCount;
public volatile int mSetStreamVolumeCount;
public volatile int mSetCaptionEnabledCount;
public volatile int mSelectTrackCount;
@@ -813,14 +861,15 @@
public volatile int mTimeShiftPlayCount;
public volatile long mTimeShiftGetCurrentPositionCount;
public volatile long mTimeShiftGetStartPositionCount;
+ public volatile int mAppPrivateCommandCount;
CountingSession(Context context) {
super(context);
}
public void resetCounts() {
- mSendAppPrivateCommand = 0;
mTuneCount = 0;
+ mTuneWithBundleCount = 0;
mSetStreamVolumeCount = 0;
mSetCaptionEnabledCount = 0;
mSelectTrackCount = 0;
@@ -840,11 +889,7 @@
mTimeShiftPlayCount = 0;
mTimeShiftGetCurrentPositionCount = 0;
mTimeShiftGetStartPositionCount = 0;
- }
-
- @Override
- public void onAppPrivateCommand(String action, Bundle data) {
- mSendAppPrivateCommand++;
+ mAppPrivateCommandCount = 0;
}
@Override
@@ -863,6 +908,15 @@
}
@Override
+ public boolean onTune(Uri channelUri, Bundle data) {
+ mTuneWithBundleCount++;
+ // Also calls {@link #onTune(Uri)} since it will never be called if the
+ // implementation overrides {@link #onTune(Uri, Bundle)}.
+ onTune(channelUri);
+ return false;
+ }
+
+ @Override
public void onSetStreamVolume(float volume) {
mSetStreamVolumeCount++;
}
@@ -965,13 +1019,20 @@
public void onOverlayViewSizeChanged(int width, int height) {
mOverlayViewSizeChangedCount++;
}
+
+ @Override
+ public void onAppPrivateCommand(String action, Bundle data) {
+ mAppPrivateCommandCount++;
+ }
}
public static class CountingRecordingSession extends RecordingSession {
public volatile int mTuneCount;
+ public volatile int mTuneWithBundleCount;
public volatile int mReleaseCount;
public volatile int mStartRecordingCount;
public volatile int mStopRecordingCount;
+ public volatile int mAppPrivateCommandCount;
CountingRecordingSession(Context context) {
super(context);
@@ -979,9 +1040,11 @@
public void resetCounts() {
mTuneCount = 0;
+ mTuneWithBundleCount = 0;
mReleaseCount = 0;
mStartRecordingCount = 0;
mStopRecordingCount = 0;
+ mAppPrivateCommandCount = 0;
}
@Override
@@ -990,6 +1053,14 @@
}
@Override
+ public void onTune(Uri channelUri, Bundle data) {
+ mTuneWithBundleCount++;
+ // Also calls {@link #onTune(Uri)} since it will never be called if the
+ // implementation overrides {@link #onTune(Uri, Bundle)}.
+ onTune(channelUri);
+ }
+
+ @Override
public void onRelease() {
mReleaseCount++;
}
@@ -1003,6 +1074,11 @@
public void onStopRecording() {
mStopRecordingCount++;
}
+
+ @Override
+ public void onAppPrivateCommand(String action, Bundle data) {
+ mAppPrivateCommandCount++;
+ }
}
}
@@ -1010,6 +1086,8 @@
private int mTunedCount;
private int mRecordingStoppedCount;
private int mErrorCount;
+ private int mConnectionFailedCount;
+ private int mDisconnectedCount;
@Override
public void onTuned(Uri channelUri) {
@@ -1026,10 +1104,49 @@
mErrorCount++;
}
+ @Override
+ public void onConnectionFailed(String inputId) {
+ mConnectionFailedCount++;
+ }
+
+ @Override
+ public void onDisconnected(String inputId) {
+ mDisconnectedCount++;
+ }
+
public void resetCounts() {
mTunedCount = 0;
mRecordingStoppedCount = 0;
mErrorCount = 0;
+ mConnectionFailedCount = 0;
+ mDisconnectedCount = 0;
+ }
+ }
+
+ public static class FaultyTvInputService extends StubTvInputService {
+ @Override
+ public RecordingSession onCreateRecordingSession(String inputId) {
+ return new FaultyRecordingSession(this);
+ }
+
+ public static class FaultyRecordingSession extends RecordingSession {
+ FaultyRecordingSession(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void onTune(Uri channelUri) {
+ Process.killProcess(android.os.Process.myPid());
+ }
+
+ @Override
+ public void onStartRecording(Uri programHint) { }
+
+ @Override
+ public void onStopRecording() { }
+
+ @Override
+ public void onRelease() { }
}
}
}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapFilterTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapFilterTests.java
index d0820e2..a2f0305 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapFilterTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapFilterTests.java
@@ -16,7 +16,6 @@
package android.uirendering.cts.testclasses;
import android.graphics.Bitmap;
-import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
@@ -112,18 +111,15 @@
final Paint paint = new Paint(filterEnum.equals(FilterEnum.ADD_FILTER) ?
0 : Paint.FILTER_BITMAP_FLAG);
- CanvasClient canvasClient = new CanvasClient() {
- @Override
- public void draw(Canvas canvas, int width, int height) {
- canvas.scale(1.0f * width / gridWidth, 1.0f * height / gridWidth);
- if (filterEnum.equals(FilterEnum.ADD_FILTER)) {
- canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.FILTER_BITMAP_FLAG));
- } else if (filterEnum.equals(FilterEnum.REMOVE_FILTER)) {
- canvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.FILTER_BITMAP_FLAG, 0));
- }
- canvas.drawBitmap(scaleUp ? mSmallGridBitmap : mBigGridBitmap, 0, 0, paint);
- canvas.setDrawFilter(null);
+ CanvasClient canvasClient = (canvas, width, height) -> {
+ canvas.scale(1.0f * width / gridWidth, 1.0f * height / gridWidth);
+ if (filterEnum.equals(FilterEnum.ADD_FILTER)) {
+ canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.FILTER_BITMAP_FLAG));
+ } else if (filterEnum.equals(FilterEnum.REMOVE_FILTER)) {
+ canvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.FILTER_BITMAP_FLAG, 0));
}
+ canvas.drawBitmap(scaleUp ? mSmallGridBitmap : mBigGridBitmap, 0, 0, paint);
+ canvas.setDrawFilter(null);
};
createTest()
.addCanvasClient(canvasClient)
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/CanvasStateTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/CanvasStateTests.java
index 38d884d..1e7a832 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/CanvasStateTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/CanvasStateTests.java
@@ -22,7 +22,6 @@
import android.graphics.Region;
import android.test.suitebuilder.annotation.MediumTest;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
-import android.uirendering.cts.testinfrastructure.CanvasClient;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
@@ -39,17 +38,14 @@
@Test
public void testClipRectReturnValues() {
createTest()
- .addCanvasClient(new CanvasClient() {
- @Override
- public void draw(Canvas canvas, int width, int height) {
- canvas.save();
- boolean isNonEmpty = canvas.clipRect(0, 0, 20, 20);
- assertTrue("clip state should be non empty", isNonEmpty);
+ .addCanvasClient((canvas, width, height) -> {
+ canvas.save();
+ boolean isNonEmpty = canvas.clipRect(0, 0, 20, 20);
+ assertTrue("clip state should be non empty", isNonEmpty);
- isNonEmpty = canvas.clipRect(0, 40, 20, 60);
- assertFalse("clip state should be empty", isNonEmpty);
- canvas.restore();
- }
+ isNonEmpty = canvas.clipRect(0, 40, 20, 60);
+ assertFalse("clip state should be empty", isNonEmpty);
+ canvas.restore();
})
.runWithoutVerification();
}
@@ -57,32 +53,29 @@
@Test
public void testClipRegionReturnValues() {
createTest()
- .addCanvasClient(new CanvasClient() {
- @Override
- public void draw(Canvas canvas, int width, int height) {
- canvas.save();
- RectF clipRectF = new RectF(0, 0, 20, 20);
+ .addCanvasClient((canvas, width, height) -> {
+ canvas.save();
+ RectF clipRectF = new RectF(0, 0, 20, 20);
- assertFalse(canvas.quickReject(0, 0, 20, 20, Canvas.EdgeType.BW));
- if (!canvas.isHardwareAccelerated()) {
- // SW canvas may not be in View space, so we offset the clipping region
- // so it will operate within the canvas client's window.
- // (Currently, this isn't necessary, since SW layer size == draw area)
- canvas.getMatrix().mapRect(clipRectF);
- }
-
- Region rectRegion = new Region();
- rectRegion.set((int) clipRectF.left, (int) clipRectF.top,
- (int) clipRectF.right, (int) clipRectF.bottom);
-
- boolean isNonEmpty = canvas.clipRegion(rectRegion);
- assertTrue("clip state should be non empty", isNonEmpty);
-
- // Note: we don't test that non-intersecting clip regions empty the clip,
- // For region clipping, the impl is allowed to return true conservatively
- // in many cases.
- canvas.restore();
+ assertFalse(canvas.quickReject(0, 0, 20, 20, Canvas.EdgeType.BW));
+ if (!canvas.isHardwareAccelerated()) {
+ // SW canvas may not be in View space, so we offset the clipping region
+ // so it will operate within the canvas client's window.
+ // (Currently, this isn't necessary, since SW layer size == draw area)
+ canvas.getMatrix().mapRect(clipRectF);
}
+
+ Region rectRegion = new Region();
+ rectRegion.set((int) clipRectF.left, (int) clipRectF.top,
+ (int) clipRectF.right, (int) clipRectF.bottom);
+
+ boolean isNonEmpty = canvas.clipRegion(rectRegion);
+ assertTrue("clip state should be non empty", isNonEmpty);
+
+ // Note: we don't test that non-intersecting clip regions empty the clip,
+ // For region clipping, the impl is allowed to return true conservatively
+ // in many cases.
+ canvas.restore();
})
.runWithoutVerification();
}
@@ -90,40 +83,34 @@
@Test
public void testClipPathReturnValues() {
createTest()
- .addCanvasClient(new CanvasClient() {
- @Override
- public void draw(Canvas canvas, int width, int height) {
- canvas.save();
- Path rectPath = new Path();
- rectPath.addRect(0, 0, 20, 20, Path.Direction.CW);
+ .addCanvasClient((canvas, width, height) -> {
+ canvas.save();
+ Path rectPath = new Path();
+ rectPath.addRect(0, 0, 20, 20, Path.Direction.CW);
- boolean isNonEmpty = canvas.clipPath(rectPath);
- assertTrue("clip state should be non empty", isNonEmpty);
+ boolean isNonEmpty = canvas.clipPath(rectPath);
+ assertTrue("clip state should be non empty", isNonEmpty);
- rectPath.offset(0, 40);
- isNonEmpty = canvas.clipPath(rectPath);
- assertFalse("clip state should be empty", isNonEmpty);
- canvas.restore();
- }
+ rectPath.offset(0, 40);
+ isNonEmpty = canvas.clipPath(rectPath);
+ assertFalse("clip state should be empty", isNonEmpty);
+ canvas.restore();
})
.runWithoutVerification();
}
@Test
public void testQuickReject() {
createTest()
- .addCanvasClient(new CanvasClient() {
- @Override
- public void draw(Canvas canvas, int width, int height) {
- canvas.save();
- canvas.clipRect(0, 0, 20, 20);
+ .addCanvasClient((canvas, width, height) -> {
+ canvas.save();
+ canvas.clipRect(0, 0, 20, 20);
- // not rejected!
- assertFalse(canvas.quickReject(0, 0, 20, 20, Canvas.EdgeType.BW));
+ // not rejected!
+ assertFalse(canvas.quickReject(0, 0, 20, 20, Canvas.EdgeType.BW));
- // rejected!
- assertTrue(canvas.quickReject(0, 40, 20, 60, Canvas.EdgeType.BW));
- canvas.restore();
- }
+ // rejected!
+ assertTrue(canvas.quickReject(0, 40, 20, 60, Canvas.EdgeType.BW));
+ canvas.restore();
})
.runWithoutVerification();
}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
index bf68f3e..2a2599b 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
@@ -16,7 +16,6 @@
package android.uirendering.cts.testclasses;
-import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
@@ -28,7 +27,6 @@
import android.uirendering.cts.bitmapverifiers.BitmapVerifier;
import android.uirendering.cts.bitmapverifiers.RectVerifier;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
-import android.uirendering.cts.testinfrastructure.CanvasClient;
import android.uirendering.cts.R;
import org.junit.Test;
@@ -40,14 +38,11 @@
public void testBlueRect() {
final Rect rect = new Rect(10, 10, 80, 80);
createTest()
- .addCanvasClient(new CanvasClient() {
- @Override
- public void draw(Canvas canvas, int width, int height) {
- Paint p = new Paint();
- p.setAntiAlias(false);
- p.setColor(Color.BLUE);
- canvas.drawRect(rect, p);
- }
+ .addCanvasClient((canvas, width, height) -> {
+ Paint p = new Paint();
+ p.setAntiAlias(false);
+ p.setColor(Color.BLUE);
+ canvas.drawRect(rect, p);
})
.runWithVerifier(new RectVerifier(Color.WHITE, Color.BLUE, rect));
}
@@ -55,16 +50,13 @@
@Test
public void testPoints() {
createTest()
- .addCanvasClient(new CanvasClient() {
- @Override
- public void draw(Canvas canvas, int width, int height) {
- Paint p = new Paint();
- p.setAntiAlias(false);
- p.setStrokeWidth(1f);
- p.setColor(Color.BLACK);
- for (int i = 0; i < 10; i++) {
- canvas.drawPoint(i * 10, i * 10, p);
- }
+ .addCanvasClient((canvas, width, height) -> {
+ Paint p = new Paint();
+ p.setAntiAlias(false);
+ p.setStrokeWidth(1f);
+ p.setColor(Color.BLACK);
+ for (int i = 0; i < 10; i++) {
+ canvas.drawPoint(i * 10, i * 10, p);
}
})
.runWithComparer(mExactComparer);
@@ -73,17 +65,14 @@
@Test
public void testBlackRectWithStroke() {
createTest()
- .addCanvasClient(new CanvasClient() {
- @Override
- public void draw(Canvas canvas, int width, int height) {
- Paint p = new Paint();
- p.setColor(Color.RED);
- canvas.drawRect(0, 0, ActivityTestBase.TEST_WIDTH,
- ActivityTestBase.TEST_HEIGHT, p);
- p.setColor(Color.BLACK);
- p.setStrokeWidth(5);
- canvas.drawRect(10, 10, 80, 80, p);
- }
+ .addCanvasClient((canvas, width, height) -> {
+ Paint p = new Paint();
+ p.setColor(Color.RED);
+ canvas.drawRect(0, 0, ActivityTestBase.TEST_WIDTH,
+ ActivityTestBase.TEST_HEIGHT, p);
+ p.setColor(Color.BLACK);
+ p.setStrokeWidth(5);
+ canvas.drawRect(10, 10, 80, 80, p);
})
.runWithComparer(mExactComparer);
}
@@ -91,15 +80,12 @@
@Test
public void testBlackLineOnGreenBack() {
createTest()
- .addCanvasClient(new CanvasClient() {
- @Override
- public void draw(Canvas canvas, int width, int height) {
- canvas.drawColor(Color.GREEN);
- Paint p = new Paint();
- p.setColor(Color.BLACK);
- p.setStrokeWidth(10);
- canvas.drawLine(0, 0, 50, 0, p);
- }
+ .addCanvasClient((canvas, width, height) -> {
+ canvas.drawColor(Color.GREEN);
+ Paint p = new Paint();
+ p.setColor(Color.BLACK);
+ p.setStrokeWidth(10);
+ canvas.drawLine(0, 0, 50, 0, p);
})
.runWithComparer(mExactComparer);
}
@@ -107,14 +93,11 @@
@Test
public void testDrawRedRectOnBlueBack() {
createTest()
- .addCanvasClient(new CanvasClient() {
- @Override
- public void draw(Canvas canvas, int width, int height) {
- canvas.drawColor(Color.BLUE);
- Paint p = new Paint();
- p.setColor(Color.RED);
- canvas.drawRect(10, 10, 40, 40, p);
- }
+ .addCanvasClient((canvas, width, height) -> {
+ canvas.drawColor(Color.BLUE);
+ Paint p = new Paint();
+ p.setColor(Color.RED);
+ canvas.drawRect(10, 10, 40, 40, p);
})
.runWithComparer(mExactComparer);
}
@@ -122,17 +105,14 @@
@Test
public void testDrawLine() {
createTest()
- .addCanvasClient(new CanvasClient() {
- @Override
- public void draw(Canvas canvas, int width, int height) {
- Paint p = new Paint();
- canvas.drawColor(Color.WHITE);
- p.setColor(Color.BLACK);
- float[] pts = {
- 0, 0, 80, 80, 80, 0, 0, 80, 40, 50, 60, 50
- };
- canvas.drawLines(pts, p);
- }
+ .addCanvasClient((canvas, width, height) -> {
+ Paint p = new Paint();
+ canvas.drawColor(Color.WHITE);
+ p.setColor(Color.BLACK);
+ float[] pts = {
+ 0, 0, 80, 80, 80, 0, 0, 80, 40, 50, 60, 50
+ };
+ canvas.drawLines(pts, p);
})
.runWithComparer(mExactComparer);
}
@@ -140,12 +120,7 @@
@Test
public void testDrawWhiteScreen() {
createTest()
- .addCanvasClient(new CanvasClient() {
- @Override
- public void draw(Canvas canvas, int width, int height) {
- canvas.drawColor(Color.WHITE);
- }
- })
+ .addCanvasClient((canvas, width, height) -> canvas.drawColor(Color.WHITE))
.runWithComparer(mExactComparer);
}
@@ -153,15 +128,12 @@
public void testBasicText() {
final String testString = "THIS IS A TEST";
createTest()
- .addCanvasClient(new CanvasClient() {
- @Override
- public void draw(Canvas canvas, int width, int height) {
- Paint p = new Paint();
- canvas.drawColor(Color.BLACK);
- p.setColor(Color.WHITE);
- p.setStrokeWidth(5);
- canvas.drawText(testString, 30, 50, p);
- }
+ .addCanvasClient((canvas, width, height) -> {
+ Paint p = new Paint();
+ canvas.drawColor(Color.BLACK);
+ p.setColor(Color.WHITE);
+ p.setStrokeWidth(5);
+ canvas.drawText(testString, 30, 50, p);
})
.runWithComparer(mExactComparer);
}
@@ -169,12 +141,9 @@
@Test
public void testBasicColorXfermode() {
createTest()
- .addCanvasClient(new CanvasClient() {
- @Override
- public void draw(Canvas canvas, int width, int height) {
- canvas.drawColor(Color.GRAY);
- canvas.drawColor(Color.BLUE, PorterDuff.Mode.MULTIPLY);
- }
+ .addCanvasClient((canvas, width, height) -> {
+ canvas.drawColor(Color.GRAY);
+ canvas.drawColor(Color.BLUE, PorterDuff.Mode.MULTIPLY);
})
.runWithComparer(mExactComparer);
}
@@ -189,21 +158,13 @@
new Rect(10, 10, 80, 80));
createTest()
- .addCanvasClient(new CanvasClient() {
- @Override
- public void draw(Canvas canvas, int width, int height) {
- canvas.drawColor(Color.WHITE);
- Paint p = new Paint();
- p.setColor(Color.BLUE);
- canvas.drawRect(10, 10, 80, 80, p);
- }
+ .addCanvasClient((canvas, width, height) -> {
+ canvas.drawColor(Color.WHITE);
+ Paint p = new Paint();
+ p.setColor(Color.BLUE);
+ canvas.drawRect(10, 10, 80, 80, p);
})
- .addCanvasClient(new CanvasClient() {
- @Override
- public void draw(Canvas canvas, int width, int height) {
- ninePatchDrawable.draw(canvas);
- }
- })
+ .addCanvasClient((canvas, width, height) -> ninePatchDrawable.draw(canvas))
.addLayout(R.layout.blue_padded_square, null)
.runWithVerifier(verifier);
}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/FontRenderingTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/FontRenderingTests.java
index 738dcfb..73779d6 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/FontRenderingTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/FontRenderingTests.java
@@ -53,18 +53,15 @@
final Typeface typeface = Typeface.create(family, style);
createTest()
- .addCanvasClient(new CanvasClient() {
- @Override
- public void draw(Canvas canvas, int width, int height) {
- Paint p = new Paint();
- p.setAntiAlias(true);
- p.setColor(Color.BLACK);
- p.setTextSize(26);
- p.setTypeface(typeface);
- canvas.drawText(sTestString1, 1, 20, p);
- canvas.drawText(sTestString2, 1, 50, p);
- canvas.drawText(sTestString3, 1, 80, p);
- }
+ .addCanvasClient((canvas, width, height) -> {
+ Paint p = new Paint();
+ p.setAntiAlias(true);
+ p.setColor(Color.BLACK);
+ p.setTextSize(26);
+ p.setTypeface(typeface);
+ canvas.drawText(sTestString1, 1, 20, p);
+ canvas.drawText(sTestString2, 1, 50, p);
+ canvas.drawText(sTestString3, 1, 80, p);
})
.runWithVerifier(new GoldenImageVerifier(goldenBitmap, comparer));
}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java
index c070b96..212e666 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java
@@ -19,7 +19,6 @@
import android.test.suitebuilder.annotation.MediumTest;
import android.uirendering.cts.R;
-import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.uirendering.cts.bitmapcomparers.BitmapComparer;
@@ -49,11 +48,8 @@
*/
@Test
public void testRenderSpecIsolation() {
- CanvasClient canvasClient = new CanvasClient() {
- @Override
- public void draw(Canvas canvas, int width, int height) {
- canvas.drawColor(canvas.isHardwareAccelerated() ? Color.BLACK : Color.WHITE);
- }
+ CanvasClient canvasClient = (canvas, width, height) -> {
+ canvas.drawColor(canvas.isHardwareAccelerated() ? Color.BLACK : Color.WHITE);
};
BitmapComparer inverseComparer = new BitmapComparer() {
@Override
@@ -75,12 +71,7 @@
@Test
public void testViewInitializer() {
final Rect clipRect = new Rect(0, 0, 50, 50);
- ViewInitializer viewInitializer = new ViewInitializer() {
- @Override
- public void initializeView(View view) {
- view.setClipBounds(clipRect);
- }
- };
+ ViewInitializer viewInitializer = view -> view.setClipBounds(clipRect);
createTest()
.addLayout(R.layout.simple_red_layout, viewInitializer)
.runWithVerifier(new RectVerifier(Color.WHITE, Color.RED, clipRect));
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java
index 30dbb03..53112d6 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java
@@ -43,17 +43,14 @@
@ColorInt
final int expectedColor = Color.rgb(255, 191, 191);
createTest()
- .addLayout(R.layout.simple_red_layout, new ViewInitializer() {
- @Override
- public void initializeView(View view) {
- // reduce alpha by 50%
- Paint paint = new Paint();
- paint.setAlpha(128);
- view.setLayerType(View.LAYER_TYPE_HARDWARE, paint);
+ .addLayout(R.layout.simple_red_layout, (ViewInitializer) view -> {
+ // reduce alpha by 50%
+ Paint paint = new Paint();
+ paint.setAlpha(128);
+ view.setLayerType(View.LAYER_TYPE_HARDWARE, paint);
- // reduce alpha by another 50% (ensuring two alphas combine correctly)
- view.setAlpha(0.5f);
- }
+ // reduce alpha by another 50% (ensuring two alphas combine correctly)
+ view.setAlpha(0.5f);
})
.runWithVerifier(new ColorVerifier(expectedColor));
}
@@ -65,15 +62,12 @@
@ColorInt
final int expectedColor = Color.rgb(54, 54, 54);
createTest()
- .addLayout(R.layout.simple_red_layout, new ViewInitializer() {
- @Override
- public void initializeView(View view) {
- Paint paint = new Paint();
- ColorMatrix desatMatrix = new ColorMatrix();
- desatMatrix.setSaturation(0.0f);
- paint.setColorFilter(new ColorMatrixColorFilter(desatMatrix));
- view.setLayerType(View.LAYER_TYPE_HARDWARE, paint);
- }
+ .addLayout(R.layout.simple_red_layout, (ViewInitializer) view -> {
+ Paint paint = new Paint();
+ ColorMatrix desatMatrix = new ColorMatrix();
+ desatMatrix.setSaturation(0.0f);
+ paint.setColorFilter(new ColorMatrixColorFilter(desatMatrix));
+ view.setLayerType(View.LAYER_TYPE_HARDWARE, paint);
})
.runWithVerifier(new ColorVerifier(expectedColor));
}
@@ -85,20 +79,17 @@
@ColorInt
final int expectedColor = Color.WHITE;
createTest()
- .addLayout(R.layout.simple_red_layout, new ViewInitializer() {
- @Override
- public void initializeView(View view) {
- Paint paint = new Paint();
- /* Note that when drawing in SW, we're blending within an otherwise empty
- * SW layer, as opposed to in the frame buffer (which has a white
- * background).
- *
- * For this reason we use just use DST, which just throws out the SRC
- * content, regardless of the DST alpha channel.
- */
- paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST));
- view.setLayerType(View.LAYER_TYPE_HARDWARE, paint);
- }
+ .addLayout(R.layout.simple_red_layout, (ViewInitializer) view -> {
+ Paint paint = new Paint();
+ /* Note that when drawing in SW, we're blending within an otherwise empty
+ * SW layer, as opposed to in the frame buffer (which has a white
+ * background).
+ *
+ * For this reason we use just use DST, which just throws out the SRC
+ * content, regardless of the DST alpha channel.
+ */
+ paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST));
+ view.setLayerType(View.LAYER_TYPE_HARDWARE, paint);
})
.runWithVerifier(new ColorVerifier(expectedColor));
}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java
index 03f5e89..7c8a301 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java
@@ -40,57 +40,41 @@
@MediumTest
public class PathClippingTests extends ActivityTestBase {
// draw circle with hole in it, with stroked circle
- static final CanvasClient sTorusDrawCanvasClient = new CanvasClient() {
- @Override
- public String getDebugString() {
- return "TorusDraw";
- }
-
- @Override
- public void draw(Canvas canvas, int width, int height) {
- Paint paint = new Paint();
- paint.setAntiAlias(false);
- paint.setColor(Color.BLUE);
- paint.setStyle(Paint.Style.STROKE);
- paint.setStrokeWidth(20);
- canvas.drawCircle(30, 30, 40, paint);
- }
+ static final CanvasClient sTorusDrawCanvasClient = (canvas, width, height) -> {
+ Paint paint = new Paint();
+ paint.setAntiAlias(false);
+ paint.setColor(Color.BLUE);
+ paint.setStyle(Paint.Style.STROKE);
+ paint.setStrokeWidth(20);
+ canvas.drawCircle(30, 30, 40, paint);
};
// draw circle with hole in it, by path operations + path clipping
- static final CanvasClient sTorusClipCanvasClient = new CanvasClient() {
- @Override
- public String getDebugString() {
- return "TorusClipDraw";
- }
+ static final CanvasClient sTorusClipCanvasClient = (canvas, width, height) -> {
+ canvas.save();
- @Override
- public void draw(Canvas canvas, int width, int height) {
- canvas.save();
+ Path path = new Path();
+ path.addCircle(30, 30, 50, Path.Direction.CW);
+ path.addCircle(30, 30, 30, Path.Direction.CCW);
- Path path = new Path();
- path.addCircle(30, 30, 50, Path.Direction.CW);
- path.addCircle(30, 30, 30, Path.Direction.CCW);
+ canvas.clipPath(path);
+ canvas.drawColor(Color.BLUE);
- canvas.clipPath(path);
- canvas.drawColor(Color.BLUE);
-
- canvas.restore();
- }
+ canvas.restore();
};
@Test
public void testCircleWithCircle() {
createTest()
- .addCanvasClient(sTorusDrawCanvasClient, false)
- .addCanvasClient(sTorusClipCanvasClient)
+ .addCanvasClient("TorusDraw", sTorusDrawCanvasClient, false)
+ .addCanvasClient("TorusClip", sTorusClipCanvasClient)
.runWithComparer(new MSSIMComparer(0.90));
}
@Test
public void testCircleWithPoints() {
createTest()
- .addCanvasClient(sTorusClipCanvasClient)
+ .addCanvasClient("TorusClip", sTorusClipCanvasClient)
.runWithVerifier(new SamplePointVerifier(
new Point[] {
// inside of circle
@@ -112,17 +96,13 @@
@Test
public void testViewRotate() {
createTest()
- .addLayout(R.layout.blue_padded_layout, new ViewInitializer() {
- @Override
- public void initializeView(View view) {
- ViewGroup rootView = (ViewGroup) view;
- rootView.setClipChildren(true);
- View childView = rootView.getChildAt(0);
- childView.setPivotX(40);
- childView.setPivotY(40);
- childView.setRotation(45f);
-
- }
+ .addLayout(R.layout.blue_padded_layout, (ViewInitializer) view -> {
+ ViewGroup rootView = (ViewGroup) view;
+ rootView.setClipChildren(true);
+ View childView = rootView.getChildAt(0);
+ childView.setPivotX(40);
+ childView.setPivotY(40);
+ childView.setRotation(45f);
})
.runWithVerifier(new SamplePointVerifier(
new Point[] {
@@ -144,24 +124,21 @@
@Test
public void testTextClip() {
createTest()
- .addCanvasClient(new CanvasClient() {
- @Override
- public void draw(Canvas canvas, int width, int height) {
- canvas.save();
+ .addCanvasClient((canvas, width, height) -> {
+ canvas.save();
- Path path = new Path();
- path.addCircle(0, 45, 45, Path.Direction.CW);
- path.addCircle(90, 45, 45, Path.Direction.CW);
- canvas.clipPath(path);
+ Path path = new Path();
+ path.addCircle(0, 45, 45, Path.Direction.CW);
+ path.addCircle(90, 45, 45, Path.Direction.CW);
+ canvas.clipPath(path);
- Paint paint = new Paint();
- paint.setAntiAlias(true);
- paint.setTextSize(90);
- paint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
- canvas.drawText("STRING", 0, 90, paint);
+ Paint paint = new Paint();
+ paint.setAntiAlias(true);
+ paint.setTextSize(90);
+ paint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
+ canvas.drawText("STRING", 0, 90, paint);
- canvas.restore();
- }
+ canvas.restore();
})
.runWithComparer(new MSSIMComparer(0.90));
}
@@ -173,23 +150,17 @@
}
createTest()
// golden client - draw a simple non-AA circle
- .addCanvasClient(new CanvasClient() {
- @Override
- public void draw(Canvas canvas, int width, int height) {
- Paint paint = new Paint();
- paint.setAntiAlias(false);
- paint.setColor(Color.BLUE);
- canvas.drawOval(0, 0, width, height, paint);
- }
+ .addCanvasClient((canvas, width, height) -> {
+ Paint paint = new Paint();
+ paint.setAntiAlias(false);
+ paint.setColor(Color.BLUE);
+ canvas.drawOval(0, 0, width, height, paint);
}, false)
// verify against solid color webview, clipped to its parent oval
- .addLayout(R.layout.circle_clipped_webview, new ViewInitializer() {
- @Override
- public void initializeView(View view) {
- WebView webview = (WebView)view.findViewById(R.id.webview);
- assertNotNull(webview);
- webview.loadData("<body style=\"background-color:blue\">", null, null);
- }
+ .addLayout(R.layout.circle_clipped_webview, (ViewInitializer) view -> {
+ WebView webview = (WebView)view.findViewById(R.id.webview);
+ assertNotNull(webview);
+ webview.loadData("<body style=\"background-color:blue\">", null, null);
})
.runWithComparer(new MSSIMComparer(0.95));
}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PictureTest.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PictureTest.java
index 9c8f9ba..a2f3730 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PictureTest.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PictureTest.java
@@ -25,7 +25,6 @@
import android.uirendering.cts.bitmapverifiers.ColorVerifier;
import android.uirendering.cts.bitmapverifiers.RectVerifier;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
-import android.uirendering.cts.testinfrastructure.CanvasClient;
import org.junit.Test;
@MediumTest
@@ -38,8 +37,8 @@
Paint pt = new Paint();
pt.setColor(Color.GREEN);
Picture pic = new Picture();
- Canvas subcanvas = pic.beginRecording(ActivityTestBase.TEST_WIDTH,
- ActivityTestBase.TEST_HEIGHT);
+ Canvas subcanvas = pic.beginRecording(
+ ActivityTestBase.TEST_WIDTH, ActivityTestBase.TEST_HEIGHT);
subcanvas.drawRect(sRect, pt);
pic.endRecording();
@@ -50,14 +49,11 @@
public void testPictureRespectsClip() throws Exception {
createTest()
.addCanvasClient(
- new CanvasClient() {
- @Override
- public void draw(Canvas canvas, int width, int height) {
+ (canvas, width, height) -> {
Picture pic = greenSquare();
canvas.clipRect(sOffsetRect);
pic.draw(canvas); // should be clipped out
}
- }
).runWithVerifier(new ColorVerifier(Color.WHITE));
}
@@ -65,14 +61,11 @@
public void testPictureRespectsTranslate() throws Exception {
createTest()
.addCanvasClient(
- new CanvasClient() {
- @Override
- public void draw(Canvas canvas, int width, int height) {
+ (canvas, width, height) -> {
Picture pic = greenSquare();
canvas.translate(40, 0);
pic.draw(canvas); // should be offset
}
- }
).runWithVerifier(
new RectVerifier(Color.WHITE, Color.GREEN, sOffsetRect));
}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SweepTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SweepTests.java
index f5f59b3..3f51bbe 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SweepTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SweepTests.java
@@ -108,23 +108,21 @@
ResourceModifier.init(getActivity().getResources());
// For each modification combination, we will get the CanvasClient associated with it and
// from there execute a normal canvas test with that.
- CanvasClient canvasClient = new CanvasClient() {
- @Override
- public void draw(Canvas canvas, int width, int height) {
- Paint paint = new Paint();
- modifierAccessor.modifyDrawing(canvas, paint);
- if (drawOp != null) {
- drawOp.modifyDrawing(paint, canvas);
- }
+ CanvasClient canvasClient = (canvas, width, height) -> {
+ Paint paint = new Paint();
+ modifierAccessor.modifyDrawing(canvas, paint);
+ if (drawOp != null) {
+ drawOp.modifyDrawing(paint, canvas);
}
};
int index = 0;
// Create the test cases with each combination
do {
- canvasClient.setDebugString(modifierAccessor.getDebugString());
int arrIndex = Math.min(index, bitmapComparers.length - 1);
- createTest().addCanvasClient(canvasClient).runWithComparer(bitmapComparers[arrIndex]);
+ createTest()
+ .addCanvasClient(modifierAccessor.getDebugString(), canvasClient)
+ .runWithComparer(bitmapComparers[arrIndex]);
index++;
} while (modifierAccessor.step());
}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewClippingTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewClippingTests.java
index 3b1df30..c8ca8c3 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewClippingTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewClippingTests.java
@@ -2,6 +2,7 @@
import android.graphics.Color;
import android.graphics.Outline;
+import android.graphics.Path;
import android.graphics.Rect;
import android.test.suitebuilder.annotation.MediumTest;
import android.uirendering.cts.bitmapverifiers.BitmapVerifier;
@@ -15,6 +16,8 @@
import android.uirendering.cts.R;
import org.junit.Test;
+import static org.junit.Assert.assertFalse;
+
/**
* This tests view clipping by modifying properties of blue_padded_layout, and validating
* the resulting rect of content.
@@ -23,46 +26,35 @@
*/
@MediumTest
public class ViewClippingTests extends ActivityTestBase {
- final Rect FULL_RECT = new Rect(0, 0, 90, 90);
- final Rect BOUNDS_RECT = new Rect(0, 0, 80, 80);
- final Rect PADDED_RECT = new Rect(15, 16, 63, 62);
- final Rect OUTLINE_RECT = new Rect(1, 2, 78, 79);
- final Rect CLIP_BOUNDS_RECT = new Rect(10, 20, 50, 60);
+ static final Rect FULL_RECT = new Rect(0, 0, 90, 90);
+ static final Rect BOUNDS_RECT = new Rect(0, 0, 80, 80);
+ static final Rect PADDED_RECT = new Rect(15, 16, 63, 62);
+ static final Rect OUTLINE_RECT = new Rect(1, 2, 78, 79);
+ static final Rect CLIP_BOUNDS_RECT = new Rect(10, 20, 50, 60);
- final ViewInitializer BOUNDS_CLIP_INIT = new ViewInitializer() {
- @Override
- public void initializeView(View rootView) {
- ((ViewGroup)rootView).setClipChildren(true);
- }
+ static final ViewInitializer BOUNDS_CLIP_INIT =
+ rootView -> ((ViewGroup)rootView).setClipChildren(true);
+
+ static final ViewInitializer PADDING_CLIP_INIT = rootView -> {
+ ViewGroup child = (ViewGroup) rootView.findViewById(R.id.child);
+ child.setClipToPadding(true);
+ child.setWillNotDraw(true);
+ child.addView(new UnclippedBlueView(rootView.getContext()));
};
- final ViewInitializer PADDING_CLIP_INIT = new ViewInitializer() {
- @Override
- public void initializeView(View rootView) {
- ViewGroup child = (ViewGroup) rootView.findViewById(R.id.child);
- child.setClipToPadding(true);
- child.setWillNotDraw(true);
- child.addView(new UnclippedBlueView(rootView.getContext()));
- }
+
+ static final ViewInitializer OUTLINE_CLIP_INIT = rootView -> {
+ View child = rootView.findViewById(R.id.child);
+ child.setOutlineProvider(new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ outline.setRect(OUTLINE_RECT);
+ }
+ });
+ child.setClipToOutline(true);
};
- final ViewInitializer OUTLINE_CLIP_INIT = new ViewInitializer() {
- @Override
- public void initializeView(View rootView) {
- View child = rootView.findViewById(R.id.child);
- child.setOutlineProvider(new ViewOutlineProvider() {
- @Override
- public void getOutline(View view, Outline outline) {
- outline.setRect(OUTLINE_RECT);
- }
- });
- child.setClipToOutline(true);
- }
- };
- final ViewInitializer CLIP_BOUNDS_CLIP_INIT = new ViewInitializer() {
- @Override
- public void initializeView(View view) {
- view.setClipBounds(CLIP_BOUNDS_RECT);
- }
- };
+
+ static final ViewInitializer CLIP_BOUNDS_CLIP_INIT =
+ view -> view.setClipBounds(CLIP_BOUNDS_RECT);
static BitmapVerifier makeClipVerifier(Rect blueBoundsRect) {
// very high error tolerance, since all these tests care about is clip alignment
@@ -96,6 +88,7 @@
.addLayout(R.layout.blue_padded_layout, PADDING_CLIP_INIT)
.runWithVerifier(makeClipVerifier(PADDED_RECT));
}
+ // TODO: add tests with clip + scroll, and with interesting combinations of the above
@Test
public void testSimpleOutlineClip() {
@@ -110,5 +103,25 @@
.runWithVerifier(makeClipVerifier(FULL_RECT));
}
- // TODO: add tests with clip + scroll, and with interesting combinations of the above
+ @Test
+ public void testOvalOutlineClip() {
+ // In hw this works because clipping to a non-round rect isn't supported, and is no-op'd.
+ // In sw this works because Outline clipping isn't supported.
+ createTest()
+ .addLayout(R.layout.blue_padded_layout, view -> {
+ view.setOutlineProvider(new ViewOutlineProvider() {
+ Path mPath = new Path();
+ @Override
+ public void getOutline(View view, Outline outline) {
+ mPath.reset();
+ mPath.addOval(0, 0, view.getWidth(), view.getHeight(),
+ Path.Direction.CW);
+ outline.setConvexPath(mPath);
+ assertFalse(outline.canClip()); // NOTE: non-round-rect, so can't clip
+ }
+ });
+ view.setClipToOutline(true); // should do nothing, since non-rect clip
+ })
+ .runWithVerifier(makeClipVerifier(FULL_RECT));
+ }
}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
index f82bb40..e634528 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
@@ -145,7 +145,7 @@
protected Bitmap captureRenderSpec(TestCase testCase) {
Point testOffset = getActivity().enqueueRenderSpecAndWait(
testCase.layoutID, testCase.canvasClient,
- testCase.webViewUrl, testCase.viewInitializer, testCase.useHardware);
+ null, testCase.viewInitializer, testCase.useHardware);
testCase.wasTestRan = true;
return takeScreenshot(testOffset);
}
@@ -260,36 +260,33 @@
});
}
- public TestCaseBuilder addWebView(String webViewUrl,
- @Nullable ViewInitializer viewInitializer) {
- return addWebView(webViewUrl, viewInitializer, false)
- .addWebView(webViewUrl, viewInitializer, true);
- }
-
public TestCaseBuilder addLayout(int layoutId, @Nullable ViewInitializer viewInitializer) {
return addLayout(layoutId, viewInitializer, false)
.addLayout(layoutId, viewInitializer, true);
}
- public TestCaseBuilder addCanvasClient(CanvasClient canvasClient) {
- return addCanvasClient(canvasClient, false)
- .addCanvasClient(canvasClient, true);
- }
-
- public TestCaseBuilder addWebView(String webViewUrl,
- @Nullable ViewInitializer viewInitializer, boolean useHardware) {
- mTestCases.add(new TestCase(null, 0, webViewUrl, viewInitializer, useHardware));
- return this;
- }
-
public TestCaseBuilder addLayout(int layoutId, @Nullable ViewInitializer viewInitializer,
- boolean useHardware) {
- mTestCases.add(new TestCase(null, layoutId, null, viewInitializer, useHardware));
+ boolean useHardware) {
+ mTestCases.add(new TestCase(layoutId, viewInitializer, useHardware));
return this;
}
+ public TestCaseBuilder addCanvasClient(CanvasClient canvasClient) {
+ return addCanvasClient(null, canvasClient);
+ }
+
public TestCaseBuilder addCanvasClient(CanvasClient canvasClient, boolean useHardware) {
- mTestCases.add(new TestCase(canvasClient, 0, null, null, useHardware));
+ return addCanvasClient(null, canvasClient, useHardware);
+ }
+
+ public TestCaseBuilder addCanvasClient(String debugString, CanvasClient canvasClient) {
+ return addCanvasClient(debugString, canvasClient, false)
+ .addCanvasClient(debugString, canvasClient, true);
+ }
+
+ public TestCaseBuilder addCanvasClient(String debugString,
+ CanvasClient canvasClient, boolean useHardware) {
+ mTestCases.add(new TestCase(canvasClient, debugString, useHardware));
return this;
}
@@ -300,39 +297,35 @@
private class TestCase {
public int layoutID;
- public CanvasClient canvasClient;
- public String webViewUrl;
public ViewInitializer viewInitializer;
- public boolean useHardware;
- public boolean wasTestRan;
- public TestCase(CanvasClient client, int id, String viewUrl,
- ViewInitializer viewInitializer, boolean useHardware) {
- int count = 0;
- count += (client == null ? 0 : 1);
- count += (viewUrl == null ? 0 : 1);
- count += (id == 0 ? 0 : 1);
- assert(count == 1);
- assert(client == null || viewInitializer == null);
- this.layoutID = id;
- this.canvasClient = client;
- this.webViewUrl = viewUrl;
+ public CanvasClient canvasClient;
+ public String canvasClientDebugString;
+
+ public boolean useHardware;
+ public boolean wasTestRan = false;
+
+ public TestCase(int layoutId, ViewInitializer viewInitializer, boolean useHardware) {
+ this.layoutID = layoutId;
this.viewInitializer = viewInitializer;
this.useHardware = useHardware;
- this.wasTestRan = false;
+ }
+
+ public TestCase(CanvasClient client, String debugString, boolean useHardware) {
+ this.canvasClient = client;
+ this.canvasClientDebugString = debugString;
+ this.useHardware = useHardware;
}
public String getDebugString() {
String debug = "";
if (canvasClient != null) {
debug += "CanvasClient : ";
- if (canvasClient.getDebugString() != null) {
- debug += canvasClient.getDebugString();
+ if (canvasClientDebugString != null) {
+ debug += canvasClientDebugString;
} else {
debug += "no debug string given";
}
- } else if (webViewUrl != null) {
- debug += "WebView URL : " + webViewUrl;
} else {
debug += "Layout resource : " +
getActivity().getResources().getResourceName(layoutID);
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/CanvasClient.java b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/CanvasClient.java
index a99c576..99f6cc7 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/CanvasClient.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/CanvasClient.java
@@ -20,16 +20,6 @@
/**
* A class that the tester will implement and create a set of drawing calls the tests would use
*/
-public abstract class CanvasClient {
- private String mDebugString;
-
- public abstract void draw(Canvas canvas, int width, int height);
-
- public String getDebugString() {
- return mDebugString;
- }
-
- public void setDebugString(String debugString) {
- mDebugString = debugString;
- }
+public interface CanvasClient {
+ void draw(Canvas canvas, int width, int height);
}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ViewInitializer.java b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ViewInitializer.java
index 9a3cbb1..43e1fa6 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ViewInitializer.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ViewInitializer.java
@@ -20,6 +20,6 @@
/**
* Called after a view is created to set various properties on the view
*/
-public abstract class ViewInitializer {
- public abstract void initializeView(View view);
+public interface ViewInitializer {
+ void initializeView(View view);
}
diff --git a/tests/tests/view/src/android/view/cts/ContextThemeWrapperTest.java b/tests/tests/view/src/android/view/cts/ContextThemeWrapperTest.java
index b25f733..ccf37949 100644
--- a/tests/tests/view/src/android/view/cts/ContextThemeWrapperTest.java
+++ b/tests/tests/view/src/android/view/cts/ContextThemeWrapperTest.java
@@ -17,6 +17,7 @@
package android.view.cts;
import android.content.Context;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.Resources.Theme;
@@ -25,7 +26,6 @@
import android.view.cts.R;
-
public class ContextThemeWrapperTest extends AndroidTestCase {
private static final int SYSTEM_DEFAULT_THEME = 0;
@@ -103,6 +103,22 @@
}).test());
}
+ public void testApplyOverrideConfiguration() {
+ Context context = getContext();
+ final int realDensity = context.getResources().getConfiguration().densityDpi;
+ final int expectedDensity = realDensity + 1;
+
+ ContextThemeWrapper contextThemeWrapper = new ContextThemeWrapper(
+ context, SYSTEM_DEFAULT_THEME);
+
+ Configuration overrideConfig = new Configuration();
+ overrideConfig.densityDpi = expectedDensity;
+ contextThemeWrapper.applyOverrideConfiguration(overrideConfig);
+
+ Configuration actualConfiguration = contextThemeWrapper.getResources().getConfiguration();
+ assertEquals(expectedDensity, actualConfiguration.densityDpi);
+ }
+
private void assertEqualsTextAppearanceStyle(TypedArray ta) {
final int defValue = -1;
// get Theme and assert
diff --git a/tests/tests/widget/AndroidManifest.xml b/tests/tests/widget/AndroidManifest.xml
index 5acfc18..dcfe4c1 100644
--- a/tests/tests/widget/AndroidManifest.xml
+++ b/tests/tests/widget/AndroidManifest.xml
@@ -77,7 +77,15 @@
</activity>
<activity android:name="android.widget.cts.ImageViewCtsActivity"
- android:label="ImageViewCtsActivity">
+ android:label="ImageViewCtsActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="android.widget.cts.SwitchCtsActivity"
+ android:label="SwitchCtsActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
@@ -352,6 +360,14 @@
</intent-filter>
</activity>
+ <activity android:name="android.widget.cts.CalendarViewCtsActivity"
+ android:label="CalendarViewCtsActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
+
<activity android:name="android.app.ActivityGroup"
android:label="ActivityGroup" />
diff --git a/tests/tests/widget/res/drawable/magenta_fill.xml b/tests/tests/widget/res/drawable/magenta_fill.xml
new file mode 100644
index 0000000..cbb594f
--- /dev/null
+++ b/tests/tests/widget/res/drawable/magenta_fill.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="#FF00FF" />
+</shape>
\ No newline at end of file
diff --git a/tests/tests/widget/res/drawable/yellow_fill.xml b/tests/tests/widget/res/drawable/yellow_fill.xml
new file mode 100644
index 0000000..3bd8097
--- /dev/null
+++ b/tests/tests/widget/res/drawable/yellow_fill.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="#FFFF00" />
+</shape>
\ No newline at end of file
diff --git a/tests/tests/widget/res/layout/calendarview_layout.xml b/tests/tests/widget/res/layout/calendarview_layout.xml
new file mode 100644
index 0000000..3bc5e47
--- /dev/null
+++ b/tests/tests/widget/res/layout/calendarview_layout.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2016 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fillViewport="true">
+
+ <LinearLayout
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <CalendarView
+ android:id="@+id/calendar_view_material"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:firstDayOfWeek="2"
+ android:dateTextAppearance="@style/TextAppearance.WithColor"
+ android:weekDayTextAppearance="@style/TextAppearance.WithColorGreen" />
+
+ <!-- CalendarView in Holo Light style for testing attributes and APIs that control
+ the deprecated visual aspects of this widget. -->
+ <CalendarView
+ style="@android:style/Widget.Holo.Light.CalendarView"
+ android:id="@+id/calendar_view_holoyolo"
+ android:layout_width="match_parent"
+ android:layout_height="320dip"
+ android:firstDayOfWeek="3"
+ android:shownWeekCount="5"
+ android:showWeekNumber="false"
+ android:selectedWeekBackgroundColor="@color/calendarview_week_background"
+ android:focusedMonthDateColor="@color/calendarview_focusedmonthdate"
+ android:unfocusedMonthDateColor="@color/calendarview_unfocusedmonthdate"
+ android:dateTextAppearance="@style/TextAppearance.WithColor"
+ android:weekDayTextAppearance="@style/TextAppearance.WithColorGreen"
+ android:selectedDateVerticalBar="@drawable/blue_fill" />
+
+ </LinearLayout>
+
+</ScrollView>
diff --git a/tests/tests/widget/res/layout/popupwindow.xml b/tests/tests/widget/res/layout/popupwindow.xml
index d84770d..cf69831 100644
--- a/tests/tests/widget/res/layout/popupwindow.xml
+++ b/tests/tests/widget/res/layout/popupwindow.xml
@@ -20,40 +20,76 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
- <android.widget.cts.MockViewForListPopupWindow
+ <View
android:id="@+id/anchor_upper_left"
android:layout_width="10dp"
android:layout_height="10dp"
- android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
- android:background="#f0f" />
-
- <View android:id="@+id/anchor_upper"
- android:layout_width="10dp"
- android:layout_height="30dp"
android:layout_alignParentTop="true"
- android:layout_centerHorizontal="true"
android:background="#f00" />
- <View android:id="@+id/anchor_lower"
+ <View
+ android:id="@+id/anchor_upper"
android:layout_width="10dp"
- android:layout_height="30dp"
- android:layout_alignParentBottom="true"
+ android:layout_height="10dp"
android:layout_centerHorizontal="true"
- android:background="#0f0" />
+ android:layout_alignParentTop="true"
+ android:background="#f00" />
- <View android:id="@+id/anchor_middle_left"
- android:layout_width="30dp"
+ <View
+ android:id="@+id/anchor_upper_right"
+ android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentTop="true"
+ android:background="#f00" />
+
+ <View
+ android:id="@+id/anchor_middle_left"
+ android:layout_width="10dp"
android:layout_height="10dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
- android:background="#00f" />
+ android:background="#0f0" />
- <View android:id="@+id/anchor_middle_right"
- android:layout_width="30dp"
+ <View
+ android:id="@+id/anchor_middle"
+ android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:layout_centerHorizontal="true"
+ android:layout_centerVertical="true"
+ android:background="#0f0" />
+
+ <View
+ android:id="@+id/anchor_middle_right"
+ android:layout_width="10dp"
android:layout_height="10dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
- android:background="#ff0" />
+ android:background="#0f0" />
+
+ <View
+ android:id="@+id/anchor_lower_left"
+ android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentBottom="true"
+ android:background="#00f" />
+
+ <View
+ android:id="@+id/anchor_lower"
+ android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:layout_centerHorizontal="true"
+ android:layout_alignParentBottom="true"
+ android:background="#00f" />
+
+ <View
+ android:id="@+id/anchor_lower_right"
+ android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentBottom="true"
+ android:background="#00f" />
</RelativeLayout>
diff --git a/tests/tests/widget/res/layout/switch_layout.xml b/tests/tests/widget/res/layout/switch_layout.xml
index a34845b..12e10d2 100644
--- a/tests/tests/widget/res/layout/switch_layout.xml
+++ b/tests/tests/widget/res/layout/switch_layout.xml
@@ -16,6 +16,7 @@
-->
<Switch xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/switch_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:thumbTint="@android:color/white"
diff --git a/tests/tests/widget/res/values/colors.xml b/tests/tests/widget/res/values/colors.xml
index f3cc325..f104a6d2 100644
--- a/tests/tests/widget/res/values/colors.xml
+++ b/tests/tests/widget/res/values/colors.xml
@@ -23,4 +23,14 @@
<color name="testcolor1">#ff00ff00</color>
<color name="testcolor2">#ffff0000</color>
<color name="failColor">#ff0000ff</color>
+
+ <color name="calendarview_week_background">#40FF0000</color>
+ <color name="calendarview_focusedmonthdate">#9080A0FF</color>
+ <color name="calendarview_unfocusedmonthdate">#9070F080</color>
+
+ <color name="calendarview_week_background_new">#60808000</color>
+ <color name="calendarview_focusedmonthdate_new">#A0B020FF</color>
+ <color name="calendarview_unfocusedmonthdate_new">#4070F0F0</color>
+ <color name="calendarview_week_number_new">#9090FF</color>
+ <color name="calendarview_week_separatorline_new">#AFAF00</color>
</resources>
diff --git a/tests/tests/widget/res/values/styles.xml b/tests/tests/widget/res/values/styles.xml
index da22652..345b450 100644
--- a/tests/tests/widget/res/values/styles.xml
+++ b/tests/tests/widget/res/values/styles.xml
@@ -71,6 +71,18 @@
<item name="android:textColor">#ffff0000</item>
</style>
+ <style name="TextAppearance.WithColorGreen">
+ <item name="android:textColor">#ff00ff00</item>
+ </style>
+
+ <style name="TextAppearance.WithColorBlue">
+ <item name="android:textColor">#ff0000ff</item>
+ </style>
+
+ <style name="TextAppearance.WithColorMagenta">
+ <item name="android:textColor">#ffff00ff</item>
+ </style>
+
<style name="TextAppearance.All">
<item name="android:textColor">@drawable/black</item>
<item name="android:textSize">20px</item>
@@ -188,4 +200,6 @@
<item name="android:tabStripLeft">@drawable/icon_green</item>
<item name="android:tabStripRight">@drawable/icon_red</item>
</style>
+
+ <style name="ToolbarPopupTheme_Test" parent="@android:style/ThemeOverlay.Material.Light" />
</resources>
diff --git a/tests/tests/widget/src/android/widget/cts/CalendarViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/CalendarViewCtsActivity.java
new file mode 100644
index 0000000..b0a15bf
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/CalendarViewCtsActivity.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.CalendarView;
+import android.widget.Toolbar;
+
+/**
+ * A minimal application for {@link CalendarView} test.
+ */
+public class CalendarViewCtsActivity extends Activity {
+ /**
+ * Called with the activity is first created.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.calendarview_layout);
+ }
+}
+
diff --git a/tests/tests/widget/src/android/widget/cts/CalendarViewTest.java b/tests/tests/widget/src/android/widget/cts/CalendarViewTest.java
new file mode 100644
index 0000000..31ad341
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/CalendarViewTest.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.cts;
+
+import android.annotation.ColorInt;
+import android.app.Instrumentation;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.CalendarView;
+import android.widget.cts.util.TestUtils;
+
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+
+@MediumTest
+public class CalendarViewTest extends ActivityInstrumentationTestCase2<CalendarViewCtsActivity> {
+ private CalendarViewCtsActivity mActivity;
+ private CalendarView mCalendarViewMaterial;
+ private CalendarView mCalendarViewHolo;
+
+ public CalendarViewTest() {
+ super("android.widget.cts", CalendarViewCtsActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mActivity = getActivity();
+ mCalendarViewMaterial = (CalendarView) mActivity.findViewById(R.id.calendar_view_material);
+ mCalendarViewHolo = (CalendarView) mActivity.findViewById(R.id.calendar_view_holoyolo);
+
+ // Initialize both calendar views to the current date
+ final long currentDate = new GregorianCalendar().getTime().getTime();
+ getInstrumentation().runOnMainSync(() -> {
+ mCalendarViewMaterial.setDate(currentDate);
+ mCalendarViewHolo.setDate(currentDate);
+ });
+ }
+
+ public void testConstructor() {
+ new CalendarView(mActivity);
+
+ new CalendarView(mActivity, null);
+
+ new CalendarView(mActivity, null, android.R.attr.calendarViewStyle);
+
+ new CalendarView(mActivity, null, 0, android.R.style.Widget_Material_Light_CalendarView);
+ }
+
+ public void testAccessDate() {
+ final Instrumentation instrumentation = getInstrumentation();
+
+ // Go back one year
+ final Calendar newCalendar = new GregorianCalendar();
+ newCalendar.set(Calendar.YEAR, newCalendar.get(Calendar.YEAR) - 1);
+ final long yearAgoDate = newCalendar.getTime().getTime();
+
+ instrumentation.runOnMainSync(
+ () -> mCalendarViewMaterial.setDate(yearAgoDate));
+ assertEquals(yearAgoDate, mCalendarViewMaterial.getDate());
+
+ // Go forward two years (one year from current date in aggregate)
+ newCalendar.set(Calendar.YEAR, newCalendar.get(Calendar.YEAR) + 2);
+ final long yearHenceDate = newCalendar.getTime().getTime();
+
+ instrumentation.runOnMainSync(
+ () -> mCalendarViewMaterial.setDate(yearHenceDate, true, false));
+ assertEquals(yearHenceDate, mCalendarViewMaterial.getDate());
+ }
+
+ public void testAccessMinMaxDate() {
+ final Instrumentation instrumentation = getInstrumentation();
+
+ // Use a range of minus/plus one year as min/max dates
+ final Calendar minCalendar = new GregorianCalendar();
+ minCalendar.set(Calendar.YEAR, minCalendar.get(Calendar.YEAR) - 1);
+ final Calendar maxCalendar = new GregorianCalendar();
+ maxCalendar.set(Calendar.YEAR, maxCalendar.get(Calendar.YEAR) + 1);
+
+ final long minDate = minCalendar.getTime().getTime();
+ final long maxDate = maxCalendar.getTime().getTime();
+
+ instrumentation.runOnMainSync(() -> {
+ mCalendarViewMaterial.setMinDate(minDate);
+ mCalendarViewMaterial.setMaxDate(maxDate);
+ });
+
+ assertEquals(mCalendarViewMaterial.getMinDate(), minDate);
+ assertEquals(mCalendarViewMaterial.getMaxDate(), maxDate);
+ }
+
+ public void testAppearanceMaterial() {
+ // The logic in this method is performed on a Material-styled CalendarView and
+ // non-deprecated attributes / visual appearance APIs
+
+ // Test the initial appearance defined in the layout XML
+ assertEquals(2, mCalendarViewMaterial.getFirstDayOfWeek());
+ assertEquals(R.style.TextAppearance_WithColor,
+ mCalendarViewMaterial.getDateTextAppearance());
+ assertEquals(R.style.TextAppearance_WithColorGreen,
+ mCalendarViewMaterial.getWeekDayTextAppearance());
+
+ final Instrumentation instrumentation = getInstrumentation();
+
+ // Change the visual appearance of the widget
+ instrumentation.runOnMainSync(() -> {
+ mCalendarViewMaterial.setFirstDayOfWeek(3);
+ mCalendarViewMaterial.setDateTextAppearance(R.style.TextAppearance_WithColorBlue);
+ mCalendarViewMaterial.setWeekDayTextAppearance(R.style.TextAppearance_WithColorMagenta);
+ });
+
+ assertEquals(3, mCalendarViewMaterial.getFirstDayOfWeek());
+ assertEquals(R.style.TextAppearance_WithColorBlue,
+ mCalendarViewMaterial.getDateTextAppearance());
+ assertEquals(R.style.TextAppearance_WithColorMagenta,
+ mCalendarViewMaterial.getWeekDayTextAppearance());
+ }
+
+ public void testAppearanceHolo() {
+ // All the logic in this method is performed on a Holo-styled CalendarView, as
+ // under Material design we are ignoring most of these decorative attributes
+
+ // Test the initial appearance defined in the layout XML
+ assertEquals(3, mCalendarViewHolo.getFirstDayOfWeek());
+ assertEquals(5, mCalendarViewHolo.getShownWeekCount());
+ assertFalse(mCalendarViewHolo.getShowWeekNumber());
+ assertEquals(R.style.TextAppearance_WithColor,
+ mCalendarViewHolo.getDateTextAppearance());
+ assertEquals(R.style.TextAppearance_WithColorGreen,
+ mCalendarViewHolo.getWeekDayTextAppearance());
+ assertEquals(mActivity.getColor(R.color.calendarview_week_background),
+ mCalendarViewHolo.getSelectedWeekBackgroundColor());
+ assertEquals(mActivity.getColor(R.color.calendarview_focusedmonthdate),
+ mCalendarViewHolo.getFocusedMonthDateColor());
+ assertEquals(mActivity.getColor(R.color.calendarview_unfocusedmonthdate),
+ mCalendarViewHolo.getUnfocusedMonthDateColor());
+ TestUtils.assertAllPixelsOfColor("Selected date vertical bar blue",
+ mCalendarViewHolo.getSelectedDateVerticalBar(), 40, 40, true, 0xFF0000FF, 1, true);
+
+ final Instrumentation instrumentation = getInstrumentation();
+
+ // Change the visual appearance of the widget
+ final @ColorInt int newSelectedWeekBackgroundColor =
+ mActivity.getColor(R.color.calendarview_week_background_new);
+ final @ColorInt int newFocusedMonthDateColor =
+ mActivity.getColor(R.color.calendarview_focusedmonthdate_new);
+ final @ColorInt int newUnfocusedMonthDataColor =
+ mActivity.getColor(R.color.calendarview_unfocusedmonthdate_new);
+ final @ColorInt int newWeekNumberColor =
+ mActivity.getColor(R.color.calendarview_week_number_new);
+ final @ColorInt int newWeekSeparatorLineColor =
+ mActivity.getColor(R.color.calendarview_week_separatorline_new);
+
+ instrumentation.runOnMainSync(() -> {
+ mCalendarViewHolo.setFirstDayOfWeek(1);
+ mCalendarViewHolo.setShownWeekCount(4);
+ mCalendarViewHolo.setShowWeekNumber(true);
+ mCalendarViewHolo.setDateTextAppearance(R.style.TextAppearance_WithColorBlue);
+ mCalendarViewHolo.setWeekDayTextAppearance(R.style.TextAppearance_WithColorMagenta);
+ mCalendarViewHolo.setSelectedWeekBackgroundColor(newSelectedWeekBackgroundColor);
+ mCalendarViewHolo.setFocusedMonthDateColor(newFocusedMonthDateColor);
+ mCalendarViewHolo.setUnfocusedMonthDateColor(newUnfocusedMonthDataColor);
+ mCalendarViewHolo.setWeekNumberColor(newWeekNumberColor);
+ mCalendarViewHolo.setWeekSeparatorLineColor(newWeekSeparatorLineColor);
+ });
+
+ assertEquals(1, mCalendarViewHolo.getFirstDayOfWeek());
+ assertEquals(4, mCalendarViewHolo.getShownWeekCount());
+ assertTrue(mCalendarViewHolo.getShowWeekNumber());
+ assertEquals(R.style.TextAppearance_WithColorBlue,
+ mCalendarViewHolo.getDateTextAppearance());
+ assertEquals(R.style.TextAppearance_WithColorMagenta,
+ mCalendarViewHolo.getWeekDayTextAppearance());
+ assertEquals(newSelectedWeekBackgroundColor,
+ mCalendarViewHolo.getSelectedWeekBackgroundColor());
+ assertEquals(newFocusedMonthDateColor,
+ mCalendarViewHolo.getFocusedMonthDateColor());
+ assertEquals(newUnfocusedMonthDataColor,
+ mCalendarViewHolo.getUnfocusedMonthDateColor());
+ assertEquals(newWeekNumberColor,
+ mCalendarViewHolo.getWeekNumberColor());
+ assertEquals(newWeekSeparatorLineColor,
+ mCalendarViewHolo.getWeekSeparatorLineColor());
+
+ instrumentation.runOnMainSync(
+ () -> mCalendarViewHolo.setSelectedDateVerticalBar(R.drawable.yellow_fill));
+ TestUtils.assertAllPixelsOfColor("Selected date vertical bar yellow",
+ mCalendarViewHolo.getSelectedDateVerticalBar(), 40, 40, true, 0xFFFFFF00, 1, true);
+
+ instrumentation.runOnMainSync(
+ () -> mCalendarViewHolo.setSelectedDateVerticalBar(
+ mActivity.getDrawable(R.drawable.magenta_fill)));
+ TestUtils.assertAllPixelsOfColor("Selected date vertical bar magenta",
+ mCalendarViewHolo.getSelectedDateVerticalBar(), 40, 40, true, 0xFFFF00FF, 1, true);
+ }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
index 658307a..15a79bf 100644
--- a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
@@ -16,12 +16,16 @@
package android.widget.cts;
+import junit.framework.AssertionFailedError;
+
import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
import android.graphics.Color;
+import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.os.Debug;
import android.os.SystemClock;
import android.test.ActivityInstrumentationTestCase2;
import android.test.UiThreadTest;
@@ -296,33 +300,281 @@
assertEquals(width, mPopupWindow.getWidth());
}
+ private static final int TOP = 0x00;
+ private static final int BOTTOM = 0x01;
+
+ private static final int LEFT = 0x00;
+ private static final int RIGHT = 0x01;
+
+ private static final int GREATER_THAN = 1;
+ private static final int LESS_THAN = -1;
+ private static final int EQUAL_TO = 0;
+
public void testShowAsDropDown() {
- int[] anchorXY = new int[2];
- int[] viewOnScreenXY = new int[2];
- int[] viewInWindowXY = new int[2];
+ final PopupWindow popup = createPopupWindow(createPopupContent(50, 50));
+ popup.setClipToScreenEnabled(false);
+ popup.setOverlapAnchor(false);
+ popup.setAnimationStyle(0);
+ popup.setExitTransition(null);
+ popup.setEnterTransition(null);
- mPopupWindow = createPopupWindow(createPopupContent());
- final View upperAnchor = mActivity.findViewById(R.id.anchor_upper);
+ assertPosition(popup, R.id.anchor_upper_left,
+ LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, BOTTOM);
+ assertPosition(popup, R.id.anchor_upper,
+ LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, BOTTOM);
+ assertPosition(popup, R.id.anchor_upper_right,
+ RIGHT, EQUAL_TO, RIGHT, TOP, EQUAL_TO, BOTTOM);
- mInstrumentation.runOnMainSync(() -> mPopupWindow.showAsDropDown(upperAnchor));
- mInstrumentation.waitForIdleSync();
+ assertPosition(popup, R.id.anchor_middle_left,
+ LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, BOTTOM);
+ assertPosition(popup, R.id.anchor_middle,
+ LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, BOTTOM);
+ assertPosition(popup, R.id.anchor_middle_right,
+ RIGHT, EQUAL_TO, RIGHT, TOP, EQUAL_TO, BOTTOM);
- assertTrue(mPopupWindow.isShowing());
+ assertPosition(popup, R.id.anchor_lower_left,
+ LEFT, EQUAL_TO, LEFT, BOTTOM, EQUAL_TO, TOP);
+ assertPosition(popup, R.id.anchor_lower,
+ LEFT, EQUAL_TO, LEFT, BOTTOM, EQUAL_TO, TOP);
+ assertPosition(popup, R.id.anchor_lower_right,
+ RIGHT, EQUAL_TO, RIGHT, BOTTOM, EQUAL_TO, TOP);
+ }
- mPopupWindow.getContentView().getLocationOnScreen(viewOnScreenXY);
- upperAnchor.getLocationOnScreen(anchorXY);
- mPopupWindow.getContentView().getLocationInWindow(viewInWindowXY);
- assertEquals(anchorXY[0] + viewInWindowXY[0], viewOnScreenXY[0]);
- assertEquals(anchorXY[1] + viewInWindowXY[1] + upperAnchor.getHeight(), viewOnScreenXY[1]);
+ public void testShowAsDropDown_ClipToScreen() {
+ final PopupWindow popup = createPopupWindow(createPopupContent(50, 50));
+ popup.setClipToScreenEnabled(true);
+ popup.setOverlapAnchor(false);
+ popup.setAnimationStyle(0);
+ popup.setExitTransition(null);
+ popup.setEnterTransition(null);
- dismissPopup();
+ assertPosition(popup, R.id.anchor_upper_left,
+ LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, BOTTOM);
+ assertPosition(popup, R.id.anchor_upper,
+ LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, BOTTOM);
+ assertPosition(popup, R.id.anchor_upper_right,
+ RIGHT, EQUAL_TO, RIGHT, TOP, EQUAL_TO, BOTTOM);
+
+ assertPosition(popup, R.id.anchor_middle_left,
+ LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, BOTTOM);
+ assertPosition(popup, R.id.anchor_middle,
+ LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, BOTTOM);
+ assertPosition(popup, R.id.anchor_middle_right,
+ RIGHT, EQUAL_TO, RIGHT, TOP, EQUAL_TO, BOTTOM);
+
+ assertPosition(popup, R.id.anchor_lower_left,
+ LEFT, EQUAL_TO, LEFT, BOTTOM, EQUAL_TO, TOP);
+ assertPosition(popup, R.id.anchor_lower,
+ LEFT, EQUAL_TO, LEFT, BOTTOM, EQUAL_TO, TOP);
+ assertPosition(popup, R.id.anchor_lower_right,
+ RIGHT, EQUAL_TO, RIGHT, BOTTOM, EQUAL_TO, TOP);
+ }
+
+ public void testShowAsDropDown_ClipToScreen_Overlap() {
+ final PopupWindow popup = createPopupWindow(createPopupContent(50, 50));
+ popup.setClipToScreenEnabled(true);
+ popup.setOverlapAnchor(true);
+ popup.setAnimationStyle(0);
+ popup.setExitTransition(null);
+ popup.setEnterTransition(null);
+
+ assertPosition(popup, R.id.anchor_upper_left,
+ LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, TOP);
+ assertPosition(popup, R.id.anchor_upper,
+ LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, TOP);
+ assertPosition(popup, R.id.anchor_upper_right,
+ RIGHT, EQUAL_TO, RIGHT, TOP, EQUAL_TO, TOP);
+
+ assertPosition(popup, R.id.anchor_middle_left,
+ LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, TOP);
+ assertPosition(popup, R.id.anchor_middle,
+ LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, TOP);
+ assertPosition(popup, R.id.anchor_middle_right,
+ RIGHT, EQUAL_TO, RIGHT, TOP, EQUAL_TO, TOP);
+
+ assertPosition(popup, R.id.anchor_lower_left,
+ LEFT, EQUAL_TO, LEFT, BOTTOM, EQUAL_TO, TOP);
+ assertPosition(popup, R.id.anchor_lower,
+ LEFT, EQUAL_TO, LEFT, BOTTOM, EQUAL_TO, TOP);
+ assertPosition(popup, R.id.anchor_lower_right,
+ RIGHT, EQUAL_TO, RIGHT, BOTTOM, EQUAL_TO, TOP);
+ }
+
+ public void testShowAsDropDown_ClipToScreen_Overlap_Offset() {
+ final PopupWindow popup = createPopupWindow(createPopupContent(50, 50));
+ popup.setClipToScreenEnabled(true);
+ popup.setOverlapAnchor(true);
+ popup.setAnimationStyle(0);
+ popup.setExitTransition(null);
+ popup.setEnterTransition(null);
+
+ final int offsetX = mActivity.findViewById(R.id.anchor_upper).getWidth() / 2;
+ final int offsetY = mActivity.findViewById(R.id.anchor_upper).getHeight() / 2;
+ final int gravity = Gravity.TOP | Gravity.START;
+
+ assertPosition(popup, R.id.anchor_upper_left,
+ LEFT, GREATER_THAN, LEFT, TOP, GREATER_THAN, TOP,
+ offsetX, offsetY, gravity);
+ assertPosition(popup, R.id.anchor_upper,
+ LEFT, GREATER_THAN, LEFT, TOP, GREATER_THAN, TOP,
+ offsetX, offsetY, gravity);
+ assertPosition(popup, R.id.anchor_upper_right,
+ RIGHT, EQUAL_TO, RIGHT, TOP, GREATER_THAN, TOP,
+ offsetX, offsetY, gravity);
+
+ assertPosition(popup, R.id.anchor_middle_left,
+ LEFT, GREATER_THAN, LEFT, TOP, GREATER_THAN, TOP,
+ offsetX, offsetY, gravity);
+ assertPosition(popup, R.id.anchor_middle,
+ LEFT, GREATER_THAN, LEFT, TOP, GREATER_THAN, TOP,
+ offsetX, offsetY, gravity);
+ assertPosition(popup, R.id.anchor_middle_right,
+ RIGHT, EQUAL_TO, RIGHT, TOP, GREATER_THAN, TOP,
+ offsetX, offsetY, gravity);
+
+ assertPosition(popup, R.id.anchor_lower_left,
+ LEFT, GREATER_THAN, LEFT, BOTTOM, LESS_THAN, BOTTOM,
+ offsetX, offsetY, gravity);
+ assertPosition(popup, R.id.anchor_lower,
+ LEFT, GREATER_THAN, LEFT, BOTTOM, LESS_THAN, BOTTOM,
+ offsetX, offsetY, gravity);
+ assertPosition(popup, R.id.anchor_lower_right,
+ RIGHT, EQUAL_TO, RIGHT, BOTTOM, LESS_THAN, BOTTOM,
+ offsetX, offsetY, gravity);
+ }
+
+ public void testShowAsDropDown_ClipToScreen_TooBig() {
+ final View rootView = mActivity.findViewById(R.id.anchor_upper_left).getRootView();
+ final int width = rootView.getWidth() * 2;
+ final int height = rootView.getHeight() * 2;
+
+ final PopupWindow popup = createPopupWindow(createPopupContent(width, height));
+ popup.setWidth(width);
+ popup.setHeight(height);
+
+ popup.setClipToScreenEnabled(true);
+ popup.setOverlapAnchor(false);
+ popup.setAnimationStyle(0);
+ popup.setExitTransition(null);
+ popup.setEnterTransition(null);
+
+ assertPosition(popup, R.id.anchor_upper_left,
+ LEFT, EQUAL_TO, LEFT, TOP, LESS_THAN, TOP);
+ assertPosition(popup, R.id.anchor_upper,
+ LEFT, LESS_THAN, LEFT, TOP, LESS_THAN, TOP);
+ assertPosition(popup, R.id.anchor_upper_right,
+ RIGHT, EQUAL_TO, RIGHT, TOP, LESS_THAN, TOP);
+
+ assertPosition(popup, R.id.anchor_middle_left,
+ LEFT, EQUAL_TO, LEFT, TOP, LESS_THAN, TOP);
+ assertPosition(popup, R.id.anchor_middle,
+ LEFT, LESS_THAN, LEFT, TOP, LESS_THAN, TOP);
+ assertPosition(popup, R.id.anchor_middle_right,
+ RIGHT, EQUAL_TO, RIGHT, TOP, LESS_THAN, TOP);
+
+ assertPosition(popup, R.id.anchor_lower_left,
+ LEFT, EQUAL_TO, LEFT, BOTTOM, EQUAL_TO, BOTTOM);
+ assertPosition(popup, R.id.anchor_lower,
+ LEFT, LESS_THAN, LEFT, BOTTOM, EQUAL_TO, BOTTOM);
+ assertPosition(popup, R.id.anchor_lower_right,
+ RIGHT, EQUAL_TO, RIGHT, BOTTOM, EQUAL_TO, BOTTOM);
+ }
+
+ private void assertPosition(PopupWindow popup, int anchorId,
+ int contentEdgeX, int operatorX, int anchorEdgeX,
+ int contentEdgeY, int operatorY, int anchorEdgeY) {
+ assertPosition(popup, anchorId,
+ contentEdgeX, operatorX, anchorEdgeX,
+ contentEdgeY, operatorY, anchorEdgeY,
+ 0, 0, Gravity.TOP | Gravity.START);
+ }
+
+ private void assertPosition(PopupWindow popup, int anchorId,
+ int contentEdgeX, int operatorX, int anchorEdgeX,
+ int contentEdgeY, int operatorY, int anchorEdgeY,
+ int offsetX, int offsetY, int gravity) {
+ final View content = popup.getContentView();
+ final View anchor = mActivity.findViewById(anchorId);
+
+ getInstrumentation().runOnMainSync(() -> popup.showAsDropDown(
+ anchor, offsetX, offsetY, gravity));
+ getInstrumentation().waitForIdleSync();
+
+ assertTrue(popup.isShowing());
+ assertPositionX(content, contentEdgeX, operatorX, anchor, anchorEdgeX);
+ assertPositionY(content, contentEdgeY, operatorY, anchor, anchorEdgeY);
+
+ // Make sure it fits in the display frame.
+ final Rect displayFrame = new Rect();
+ anchor.getWindowVisibleDisplayFrame(displayFrame);
+ final Rect contentFrame = new Rect();
+ content.getBoundsOnScreen(contentFrame);
+ assertTrue("Content (" + contentFrame + ") extends outside display (" + displayFrame + ")",
+ displayFrame.contains(contentFrame));
+
+ getInstrumentation().runOnMainSync(() -> popup.dismiss());
+ getInstrumentation().waitForIdleSync();
+
+ assertFalse(popup.isShowing());
+ }
+
+ public static void assertPositionY(View content, int contentEdge, int flags,
+ View anchor, int anchorEdge) {
+ final int[] anchorOnScreenXY = new int[2];
+ anchor.getLocationOnScreen(anchorOnScreenXY);
+ int anchorY = anchorOnScreenXY[1];
+ if ((anchorEdge & BOTTOM) == BOTTOM) {
+ anchorY += anchor.getHeight();
+ }
+
+ final int[] contentOnScreenXY = new int[2];
+ content.getLocationOnScreen(contentOnScreenXY);
+ int contentY = contentOnScreenXY[1];
+ if ((contentEdge & BOTTOM) == BOTTOM) {
+ contentY += content.getHeight();
+ }
+
+ assertComparison(contentY, flags, anchorY);
+ }
+
+ private static void assertPositionX(View content, int contentEdge, int flags,
+ View anchor, int anchorEdge) {
+ final int[] anchorOnScreenXY = new int[2];
+ anchor.getLocationOnScreen(anchorOnScreenXY);
+ int anchorX = anchorOnScreenXY[0];
+ if ((anchorEdge & RIGHT) == RIGHT) {
+ anchorX += anchor.getWidth();
+ }
+
+ final int[] contentOnScreenXY = new int[2];
+ content.getLocationOnScreen(contentOnScreenXY);
+ int contentX = contentOnScreenXY[0];
+ if ((contentEdge & RIGHT) == RIGHT) {
+ contentX += content.getWidth();
+ }
+
+ assertComparison(contentX, flags, anchorX);
+ }
+
+ private static void assertComparison(int left, int operator, int right) {
+ switch (operator) {
+ case GREATER_THAN:
+ assertTrue(left + " <= " + right, left > right);
+ break;
+ case LESS_THAN:
+ assertTrue(left + " >= " + right, left < right);
+ break;
+ case EQUAL_TO:
+ assertTrue(left + " != " + right, left == right);
+ break;
+ }
}
public void testShowAtLocation() {
int[] popupContentViewInWindowXY = new int[2];
int[] popupContentViewOnScreenXY = new int[2];
- mPopupWindow = createPopupWindow(createPopupContent());
+ mPopupWindow = createPopupWindow(createPopupContent(50, 50));
// Do not attach within the decor; we will be measuring location
// with regard to screen coordinates.
mPopupWindow.setAttachedInDecor(false);
@@ -355,7 +607,7 @@
int[] viewOnScreenXY = new int[2];
int[] viewInWindowXY = new int[2];
- mPopupWindow = createPopupWindow(createPopupContent());
+ mPopupWindow = createPopupWindow(createPopupContent(50, 50));
final View upperAnchor = mActivity.findViewById(R.id.anchor_upper);
upperAnchor.getLocationOnScreen(anchorXY);
int height = upperAnchor.getHeight();
@@ -379,7 +631,7 @@
int[] viewOnScreenXY = new int[2];
int[] viewInWindowXY = new int[2];
- mPopupWindow = createPopupWindow(createPopupContent());
+ mPopupWindow = createPopupWindow(createPopupContent(50, 50));
final View upperAnchor = mActivity.findViewById(R.id.anchor_upper);
upperAnchor.getLocationOnScreen(anchorXY);
@@ -397,7 +649,7 @@
}
public void testAccessWindowLayoutType() {
- mPopupWindow = createPopupWindow(createPopupContent());
+ mPopupWindow = createPopupWindow(createPopupContent(50, 50));
assertEquals(WindowManager.LayoutParams.TYPE_APPLICATION_PANEL,
mPopupWindow.getWindowLayoutType());
mPopupWindow.setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL);
@@ -406,7 +658,7 @@
}
public void testGetMaxAvailableHeight() {
- mPopupWindow = createPopupWindow(createPopupContent());
+ mPopupWindow = createPopupWindow(createPopupContent(50, 50));
View anchorView = mActivity.findViewById(R.id.anchor_upper);
int avaliable = getDisplay().getHeight() - anchorView.getHeight();
@@ -447,7 +699,7 @@
@UiThreadTest
public void testDismiss() {
- mPopupWindow = createPopupWindow(createPopupContent());
+ mPopupWindow = createPopupWindow(createPopupContent(50, 50));
assertFalse(mPopupWindow.isShowing());
View anchorView = mActivity.findViewById(R.id.anchor_upper);
mPopupWindow.showAsDropDown(anchorView);
@@ -480,7 +732,7 @@
}
public void testUpdate() {
- mPopupWindow = createPopupWindow(createPopupContent());
+ mPopupWindow = createPopupWindow(createPopupContent(50, 50));
mPopupWindow.setBackgroundDrawable(null);
showPopup();
@@ -529,7 +781,7 @@
OnDismissListener dismissListener = mock(OnDismissListener.class);
- mPopupWindow = createPopupWindow(createPopupContent());
+ mPopupWindow = createPopupWindow(createPopupContent(50, 50));
mPopupWindow.setEnterTransition(enterTransition);
mPopupWindow.setExitTransition(exitTransition);
mPopupWindow.setOnDismissListener(dismissListener);
@@ -557,7 +809,7 @@
int[] viewInWindowXY = new int[2];
mInstrumentation.runOnMainSync(() -> {
- mPopupWindow = createPopupWindow(createPopupContent());
+ mPopupWindow = createPopupWindow(createPopupContent(50, 50));
// Do not attach within the decor; we will be measuring location
// with regard to screen coordinates.
mPopupWindow.setAttachedInDecor(false);
@@ -601,7 +853,7 @@
public void testUpdateDimensionAndAlignAnchorView() {
mInstrumentation.runOnMainSync(
- () -> mPopupWindow = createPopupWindow(createPopupContent()));
+ () -> mPopupWindow = createPopupWindow(createPopupContent(50, 50)));
mInstrumentation.waitForIdleSync();
final View anchorView = mActivity.findViewById(R.id.anchor_upper);
@@ -636,7 +888,7 @@
int[] viewInWindowOff = new int[2];
int[] viewXY = new int[2];
- mPopupWindow = createPopupWindow(createPopupContent());
+ mPopupWindow = createPopupWindow(createPopupContent(50, 50));
final View anchorView = mActivity.findViewById(R.id.anchor_upper);
// Do not update if it is not shown
assertFalse(mPopupWindow.isShowing());
@@ -737,7 +989,8 @@
}
public void testIsAboveAnchor() {
- mInstrumentation.runOnMainSync(() -> mPopupWindow = createPopupWindow(createPopupContent()));
+ mInstrumentation.runOnMainSync(() -> mPopupWindow = createPopupWindow(createPopupContent(50,
+ 50)));
mInstrumentation.waitForIdleSync();
final View upperAnchor = mActivity.findViewById(R.id.anchor_upper);
@@ -746,7 +999,7 @@
assertFalse(mPopupWindow.isAboveAnchor());
dismissPopup();
- mPopupWindow = createPopupWindow(createPopupContent());
+ mPopupWindow = createPopupWindow(createPopupContent(50, 50));
final View lowerAnchor = mActivity.findViewById(R.id.anchor_lower);
mInstrumentation.runOnMainSync(() -> mPopupWindow.showAsDropDown(lowerAnchor, 0, 0));
@@ -819,9 +1072,9 @@
public void captureEndValues(TransitionValues transitionValues) {}
}
- private View createPopupContent() {
- View popupView = new View(mActivity);
- popupView.setLayoutParams(new ViewGroup.LayoutParams(50, 50));
+ private View createPopupContent(int width, int height) {
+ final View popupView = new View(mActivity);
+ popupView.setLayoutParams(new ViewGroup.LayoutParams(width, height));
popupView.setBackgroundColor(Color.MAGENTA);
return popupView;
@@ -831,6 +1084,7 @@
PopupWindow window = new PopupWindow(mActivity);
window.setWidth(100);
window.setHeight(100);
+ window.setBackgroundDrawable(new ColorDrawable(Color.YELLOW));
return window;
}
diff --git a/tests/tests/widget/src/android/widget/cts/SwitchCtsActivity.java b/tests/tests/widget/src/android/widget/cts/SwitchCtsActivity.java
new file mode 100644
index 0000000..7be5831
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/SwitchCtsActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.Switch;
+import android.widget.cts.R;
+
+/**
+ * A minimal application for {@link Switch} test.
+ */
+public class SwitchCtsActivity extends Activity {
+ /**
+ * Called with the activity is first created.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.switch_layout);
+ }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/SwitchTest.java b/tests/tests/widget/src/android/widget/cts/SwitchTest.java
index e1124f3..216b17b 100644
--- a/tests/tests/widget/src/android/widget/cts/SwitchTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SwitchTest.java
@@ -16,65 +16,71 @@
package android.widget.cts;
-import android.widget.cts.R;
-
-import android.content.Context;
+import android.app.Activity;
import android.content.res.ColorStateList;
-import android.content.res.XmlResourceParser;
-import android.cts.util.WidgetTestUtils;
import android.graphics.Color;
import android.graphics.PorterDuff.Mode;
-import android.test.AndroidTestCase;
-import android.util.Xml;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.SmallTest;
import android.widget.Switch;
+import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
-import org.xmlpull.v1.XmlPullParserException;
/**
* Test {@link Switch}.
*/
-public class SwitchTest extends AndroidTestCase {
- public void testConstructor() throws XmlPullParserException, IOException {
- new Switch(mContext);
+@SmallTest
+public class SwitchTest extends ActivityInstrumentationTestCase<SwitchCtsActivity> {
+ private Activity mActivity;
+ private Switch mSwitch;
- XmlResourceParser parser = mContext.getResources().getLayout(R.layout.switch_layout);
- WidgetTestUtils.beginDocument(parser, "Switch");
-
- new Switch(mContext, parser);
-
- new Switch(mContext, parser, 0);
-
- new Switch(mContext, parser, 0, 0);
+ public SwitchTest() {
+ super("android.widget.cts", SwitchCtsActivity.class);
}
- public void testAccessThumbTint() throws XmlPullParserException, IOException {
- XmlResourceParser parser = mContext.getResources().getLayout(R.layout.switch_layout);
- WidgetTestUtils.beginDocument(parser, "Switch");
- Switch aSwitch = new Switch(mContext, parser);
- assertEquals(Color.WHITE, aSwitch.getThumbTintList().getDefaultColor());
- assertEquals(Mode.SRC_OVER, aSwitch.getThumbTintMode());
-
- ColorStateList colors = ColorStateList.valueOf(Color.RED);
- aSwitch.setThumbTintList(colors);
- aSwitch.setThumbTintMode(Mode.XOR);
-
- assertSame(colors, aSwitch.getThumbTintList());
- assertEquals(Mode.XOR, aSwitch.getThumbTintMode());
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mActivity = getActivity();
+ mSwitch = (Switch) mActivity.findViewById(R.id.switch_view);
}
- public void testAccessTrackTint() throws XmlPullParserException, IOException {
- XmlResourceParser parser = mContext.getResources().getLayout(R.layout.switch_layout);
- WidgetTestUtils.beginDocument(parser, "Switch");
- Switch aSwitch = new Switch(mContext, parser);
- assertEquals(Color.BLACK, aSwitch.getTrackTintList().getDefaultColor());
- assertEquals(Mode.SRC_ATOP, aSwitch.getTrackTintMode());
+ @UiThreadTest
+ public void testConstructor() {
+ new Switch(mActivity);
+
+ new Switch(mActivity, null);
+
+ new Switch(mActivity, null, android.R.attr.switchStyle);
+
+ new Switch(mActivity, null, 0, android.R.style.Widget_Material_Light_CompoundButton_Switch);
+ }
+
+ @UiThreadTest
+ public void testAccessThumbTint() {
+ assertEquals(Color.WHITE, mSwitch.getThumbTintList().getDefaultColor());
+ assertEquals(Mode.SRC_OVER, mSwitch.getThumbTintMode());
ColorStateList colors = ColorStateList.valueOf(Color.RED);
- aSwitch.setTrackTintList(colors);
- aSwitch.setTrackTintMode(Mode.XOR);
+ mSwitch.setThumbTintList(colors);
+ mSwitch.setThumbTintMode(Mode.XOR);
- assertSame(colors, aSwitch.getTrackTintList());
- assertEquals(Mode.XOR, aSwitch.getTrackTintMode());
+ assertSame(colors, mSwitch.getThumbTintList());
+ assertEquals(Mode.XOR, mSwitch.getThumbTintMode());
+ }
+
+ @UiThreadTest
+ public void testAccessTrackTint() {
+ assertEquals(Color.BLACK, mSwitch.getTrackTintList().getDefaultColor());
+ assertEquals(Mode.SRC_ATOP, mSwitch.getTrackTintMode());
+
+ ColorStateList colors = ColorStateList.valueOf(Color.RED);
+ mSwitch.setTrackTintList(colors);
+ mSwitch.setTrackTintMode(Mode.XOR);
+
+ assertSame(colors, mSwitch.getTrackTintList());
+ assertEquals(Mode.XOR, mSwitch.getTrackTintMode());
}
}
diff --git a/tests/tests/widget/src/android/widget/cts/ToolbarTest.java b/tests/tests/widget/src/android/widget/cts/ToolbarTest.java
index 0fd98c0..7f9690c 100644
--- a/tests/tests/widget/src/android/widget/cts/ToolbarTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ToolbarTest.java
@@ -17,6 +17,9 @@
package android.widget.cts;
import android.app.Instrumentation;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.test.ActivityInstrumentationTestCase2;
import android.test.UiThreadTest;
@@ -24,6 +27,7 @@
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
+import android.widget.ListPopupWindow;
import android.widget.Toolbar;
import android.widget.cts.util.TestUtils;
import android.widget.cts.util.ViewTestUtils;
@@ -46,6 +50,16 @@
mMainToolbar = mActivity.getMainToolbar();
}
+ public void testConstructor() {
+ new Toolbar(mActivity);
+
+ new Toolbar(mActivity, null);
+
+ new Toolbar(mActivity, null, android.R.attr.toolbarStyle);
+
+ new Toolbar(mActivity, null, 0, android.R.style.Widget_Material_Toolbar);
+ }
+
public void testTitleAndSubtitleContent() {
// Note that this method is *not* annotated to run on the UI thread, and every
// call to setTitle / setSubtitle is wrapped to wait until the next draw pass
@@ -72,6 +86,30 @@
assertEquals("New subtitle", mMainToolbar.getSubtitle());
}
+ public void testTitleAndSubtitleAppearance() {
+ final Instrumentation instrumentation = getInstrumentation();
+
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+ () -> mMainToolbar.setTitle(R.string.toolbar_title));
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+ () -> mMainToolbar.setSubtitle(R.string.toolbar_subtitle));
+
+ // Since there are no APIs to get reference to the underlying implementation of
+ // title and subtitle, here we are testing that calling the relevant APIs doesn't crash
+
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+ () -> mMainToolbar.setTitleTextColor(Color.RED));
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+ () -> mMainToolbar.setSubtitleTextColor(Color.BLUE));
+
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+ () -> mMainToolbar.setTitleTextAppearance(
+ mActivity, R.style.TextAppearance_NotColors));
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+ () -> mMainToolbar.setSubtitleTextAppearance(
+ mActivity, R.style.TextAppearance_WithColor));
+ }
+
@UiThreadTest
public void testGetTitleMargins() {
assertEquals(5, mMainToolbar.getTitleMarginStart());
@@ -326,4 +364,22 @@
assertEquals(40, mMainToolbar.getContentInsetRight());
assertEquals(20, mMainToolbar.getContentInsetEnd());
}
+
+ @UiThreadTest
+ public void testPopupTheme() {
+ mMainToolbar.setPopupTheme(R.style.ToolbarPopupTheme_Test);
+ assertEquals(R.style.ToolbarPopupTheme_Test, mMainToolbar.getPopupTheme());
+ }
+
+ public void testNavigationOnClickListener() {
+ View.OnClickListener mockListener = mock(View.OnClickListener.class);
+ mMainToolbar.setNavigationOnClickListener(mockListener);
+
+ verify(mockListener, never()).onClick(any(View.class));
+
+ getInstrumentation().runOnMainSync(() -> mMainToolbar.getNavigationView().performClick());
+ verify(mockListener, times(1)).onClick(any(View.class));
+
+ verifyNoMoreInteractions(mockListener);
+ }
}
diff --git a/tests/vr/AndroidManifest.xml b/tests/vr/AndroidManifest.xml
index 67331fe..877d846 100644
--- a/tests/vr/AndroidManifest.xml
+++ b/tests/vr/AndroidManifest.xml
@@ -37,6 +37,13 @@
android:label="@string/app_name"
android:name="android.vr.cts.OpenGLESActivity">
</activity>
+ <activity android:name=".CtsActivity"
+ android:label="CtsActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
<uses-library android:name="android.test.runner" />
</application>
diff --git a/tests/vr/src/android/vr/cts/CtsActivity.java b/tests/vr/src/android/vr/cts/CtsActivity.java
new file mode 100644
index 0000000..33fff08
--- /dev/null
+++ b/tests/vr/src/android/vr/cts/CtsActivity.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.vr.cts;
+
+import android.app.Activity;
+
+public class CtsActivity extends Activity {
+
+}
diff --git a/tests/vr/src/android/vr/cts/VrCpuTest.java b/tests/vr/src/android/vr/cts/VrCpuTest.java
new file mode 100644
index 0000000..f015899
--- /dev/null
+++ b/tests/vr/src/android/vr/cts/VrCpuTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.vr.cts;
+
+import android.content.pm.PackageManager;
+import android.os.Process;
+import android.test.ActivityInstrumentationTestCase2;
+
+public class VrCpuTest extends ActivityInstrumentationTestCase2<CtsActivity> {
+ private CtsActivity mActivity;
+
+ public VrCpuTest() {
+ super(CtsActivity.class);
+ }
+
+ public void testHasAtLeastTwoCores() {
+ mActivity = getActivity();
+ if (mActivity.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE)) {
+ assertTrue(Runtime.getRuntime().availableProcessors() >= 2);
+ }
+ }
+
+ public void testHasExclusiveCores() {
+ mActivity = getActivity();
+ if (mActivity.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE)) {
+ int[] excl_cores = Process.getExclusiveCores();
+ assertTrue(excl_cores.length >= 1);
+ }
+ }
+}
diff --git a/tools/cts-tradefed/res/config/collect-tests-only.xml b/tools/cts-tradefed/res/config/collect-tests-only.xml
index 1c22b11..9fd7757 100644
--- a/tools/cts-tradefed/res/config/collect-tests-only.xml
+++ b/tools/cts-tradefed/res/config/collect-tests-only.xml
@@ -33,4 +33,7 @@
<!-- Tell all HostTests to only list the tests -->
<option name="compatibility:test-arg" value="com.android.tradefed.testtype.HostTest:collect-tests-only:true" />
+ <!-- Tell all deqp tests to only list the tests -->
+ <option name="compatibility:test-arg" value="com.drawelements.deqp.runner.DeqpTestRunner:collect-tests-only:true" />
+
</configuration>