Merge "Adds VR high-performance temperature CTS test." 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/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/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java
index 639ec88..50d1de1 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java
@@ -76,11 +76,6 @@
public static final String DEVICE_TOKEN_OPTION = "device-token";
private static final String URL = "dynamic-config-url";
- private static final TestStatus[] RETRY_TEST_STATUS = new TestStatus[] {
- TestStatus.FAIL,
- TestStatus.NOT_EXECUTED
- };
-
@Option(name = PLAN_OPTION,
description = "the test suite plan to run, such as \"everything\" or \"cts\"",
importance = Importance.ALWAYS)
@@ -347,21 +342,15 @@
}
// Append each test that failed or was not executed to the filters
for (IModuleResult module : result.getModules()) {
- for (ICaseResult cr : module.getResults()) {
- for (TestStatus status : RETRY_TEST_STATUS) {
- for (ITestResult r : cr.getResults(status)) {
- // Create the filter for the test to be run.
- TestFilter filter = new TestFilter(
- module.getAbi(), module.getName(), r.getFullName());
- mIncludeFilters.add(filter.toString());
- }
+ for (ICaseResult testResultList : module.getResults()) {
+ for (ITestResult testResult : testResultList.getResults(TestStatus.PASS)) {
+ // Create the filter for the test to be run.
+ TestFilter filter = new TestFilter(
+ module.getAbi(), module.getName(), testResult.getFullName());
+ mExcludeFilters.add(filter.toString());
}
}
}
- if (mIncludeFilters.isEmpty()) {
- throw new IllegalArgumentException(String.format(
- "No tests to retry in session %d", mRetrySessionId));
- }
} else if (mModuleName != null) {
mIncludeFilters.clear();
try {
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/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/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/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/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/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 7a3a81c..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,6 +240,7 @@
return;
}
verifyCommandTuneForRecording();
+ verifyCallbackConnectionFailed();
verifyCommandTuneForRecordingWithBundle();
verifyCallbackTuned();
verifyCommandStartRecording();
@@ -241,6 +249,7 @@
verifyCallbackRecordingStopped();
verifyCallbackError();
verifyCommandRelease();
+ verifyCallbackDisconnected();
}
public void verifyCommandTuneForRecording() {
@@ -360,6 +369,30 @@
}.run();
}
+ public void verifyCallbackConnectionFailed() {
+ resetCounts();
+ Uri fakeChannelUri = TvContract.buildChannelUri(0);
+ mTvRecordingClient.tune("invalid_input_id", fakeChannelUri);
+ new PollingCheck(TIME_OUT) {
+ @Override
+ protected boolean check() {
+ 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();
+ }
+
public void verifyCommandTune() {
resetCounts();
Uri fakeChannelUri = TvContract.buildChannelUri(0);
@@ -1053,6 +1086,8 @@
private int mTunedCount;
private int mRecordingStoppedCount;
private int mErrorCount;
+ private int mConnectionFailedCount;
+ private int mDisconnectedCount;
@Override
public void onTuned(Uri channelUri) {
@@ -1069,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/widget/AndroidManifest.xml b/tests/tests/widget/AndroidManifest.xml
index 11057a5..dcfe4c1 100644
--- a/tests/tests/widget/AndroidManifest.xml
+++ b/tests/tests/widget/AndroidManifest.xml
@@ -360,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/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 478dd85..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>
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/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>