Merge "Add CTS tests for Bug - 23034759 and Bug - 21132860" into nougat-cts-dev
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 50fd538..aa04882 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -18,7 +18,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="com.android.cts.verifier"
       android:versionCode="5"
-      android:versionName="7.0_r8">
+      android:versionName="7.0_r9">
 
     <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="24"/>
 
diff --git a/common/host-side/tradefed/res/report/compatibility_failures.xsl b/common/host-side/tradefed/res/report/compatibility_failures.xsl
index be65b91..ef067f2 100644
--- a/common/host-side/tradefed/res/report/compatibility_failures.xsl
+++ b/common/host-side/tradefed/res/report/compatibility_failures.xsl
@@ -82,12 +82,6 @@
                             </td>
                         </tr>
                         <tr>
-                            <td class="rowtitle">Tests Not Executed</td>
-                            <td>
-                                <xsl:value-of select="Result/Summary/@not_executed"/>
-                            </td>
-                        </tr>
-                        <tr>
                             <td class="rowtitle">Modules Done</td>
                             <td>
                                 <xsl:value-of select="Result/Summary/@modules_done"/>
@@ -134,8 +128,8 @@
                             <th>Module</th>
                             <th>Passed</th>
                             <th>Failed</th>
-                            <th>Not Executed</th>
                             <th>Total Tests</th>
+                            <th>Done</th>
                         </tr>
                         <xsl:for-each select="Result/Module">
                             <tr>
@@ -155,10 +149,10 @@
                                     <xsl:value-of select="count(TestCase/Test[@result = 'fail'])"/>
                                 </td>
                                 <td>
-                                    <xsl:value-of select="count(TestCase/Test[@result = 'not_executed'])"/>
+                                    <xsl:value-of select="count(TestCase/Test[@result = 'fail']) + @pass"/>
                                 </td>
                                 <td>
-                                    <xsl:value-of select="count(TestCase/Test[@result = 'fail']) + @pass + count(TestCase/Test[@result = 'not_executed']) "/>
+                                    <xsl:value-of select="@done"/>
                                 </td>
                             </tr>
                         </xsl:for-each> <!-- end Module -->
diff --git a/common/host-side/tradefed/res/report/compatibility_result.xsd b/common/host-side/tradefed/res/report/compatibility_result.xsd
index 9b2758c..95bae85 100644
--- a/common/host-side/tradefed/res/report/compatibility_result.xsd
+++ b/common/host-side/tradefed/res/report/compatibility_result.xsd
@@ -36,7 +36,6 @@
 
   <xs:complexType name="summaryType">
     <xs:attribute name="failed" type="xs:integer"/>
-    <xs:attribute name="not_executed" type="xs:integer"/>
     <xs:attribute name="pass" type="xs:integer"/>
   </xs:complexType>
 
@@ -121,7 +120,6 @@
     <xs:restriction base="xs:string">
       <xs:enumeration value="pass"/>
       <xs:enumeration value="fail"/>
-      <xs:enumeration value="not_executed"/>
     </xs:restriction>
   </xs:simpleType>
-</xs:schema>
\ No newline at end of file
+</xs:schema>
diff --git a/common/host-side/tradefed/res/report/compatibility_result.xsl b/common/host-side/tradefed/res/report/compatibility_result.xsl
index b86107d..4f6605f 100644
--- a/common/host-side/tradefed/res/report/compatibility_result.xsl
+++ b/common/host-side/tradefed/res/report/compatibility_result.xsl
@@ -82,12 +82,6 @@
                             </td>
                         </tr>
                         <tr>
-                            <td class="rowtitle">Tests Not Executed</td>
-                            <td>
-                                <xsl:value-of select="Result/Summary/@not_executed"/>
-                            </td>
-                        </tr>
-                        <tr>
                             <td class="rowtitle">Modules Done</td>
                             <td>
                                 <xsl:value-of select="Result/Summary/@modules_done"/>
@@ -134,8 +128,8 @@
                             <th>Module</th>
                             <th>Passed</th>
                             <th>Failed</th>
-                            <th>Not Executed</th>
                             <th>Total Tests</th>
+                            <th>Done</th>
                         </tr>
                         <xsl:for-each select="Result/Module">
                             <tr>
@@ -150,10 +144,10 @@
                                     <xsl:value-of select="count(TestCase/Test[@result = 'fail'])"/>
                                 </td>
                                 <td>
-                                    <xsl:value-of select="count(TestCase/Test[@result = 'not_executed'])"/>
+                                    <xsl:value-of select="count(TestCase/Test)"/>
                                 </td>
                                 <td>
-                                    <xsl:value-of select="count(TestCase/Test)"/>
+                                    <xsl:value-of select="@done"/>
                                 </td>
                             </tr>
                         </xsl:for-each> <!-- end Module -->
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java
index c8d86d08..c67b176 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java
@@ -362,7 +362,6 @@
                         Integer.toString(i),
                         Integer.toString(result.countResults(TestStatus.PASS)),
                         Integer.toString(result.countResults(TestStatus.FAIL)),
-                        Integer.toString(result.getNotExecuted()),
                         moduleProgress,
                         CompatibilityBuildHelper.getDirSuffix(result.getStartTime()),
                         result.getTestPlan(),
@@ -373,9 +372,8 @@
             }
 
             // add the table header to the beginning of the list
-            table.add(0, Arrays.asList("Session", "Pass", "Fail", "Not Executed",
-                    "Modules Complete", "Result Directory", "Test Plan", "Device serial(s)",
-                    "Build ID", "Product"));
+            table.add(0, Arrays.asList("Session", "Pass", "Fail", "Modules Complete",
+                "Result Directory", "Test Plan", "Device serial(s)", "Build ID", "Product"));
             tableFormatter.displayTable(table, new PrintWriter(System.out, true));
         } else {
             printLine(String.format("No results found"));
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 d16b0e0..1c223ff 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
@@ -86,8 +86,8 @@
 
     @Option(name = CompatibilityTest.RETRY_TYPE_OPTION,
             description = "used with " + CompatibilityTest.RETRY_OPTION
-            + ", retry tests of a certain status. Possible values include \"failed\" and "
-            + "\"not_executed\".",
+            + ", retry tests of a certain status. Possible values include \"failed\", "
+            + "\"not_executed\", and \"custom\".",
             importance = Importance.IF_UNSET)
     private RetryType mRetryType = null;
 
@@ -357,23 +357,10 @@
     public void testRunEnded(long elapsedTime, Map<String, String> metrics) {
         mCurrentModuleResult.inProgress(false);
         mCurrentModuleResult.addRuntime(elapsedTime);
-        if (!mModuleWasDone) {
-            // Not executed count now represents an upper-bound for a fix to b/33211104.
-            // Only setNotExecuted this number if the module has already been completely executed.
-            int testCountDiff = Math.max(mTotalTestsInModule - mCurrentTestNum, 0);
-            if (isShardResultReporter()) {
-                // reset value, which is added to total count for master shard upon merge
-                mCurrentModuleResult.setNotExecuted(testCountDiff);
-            } else {
-                // increment value for master shard
-                mCurrentModuleResult.setNotExecuted(mCurrentModuleResult.getNotExecuted()
-                        + testCountDiff);
-            }
-            if (mCanMarkDone) {
-                // Only mark module done if status of the invocation allows it (mCanMarkDone) and
-                // if module has not already been marked done.
-                mCurrentModuleResult.setDone(mCurrentTestNum >= mTotalTestsInModule);
-            }
+        if (!mModuleWasDone && mCanMarkDone) {
+            // Only mark module done if status of the invocation allows it (mCanMarkDone) and
+            // if module has not already been marked done.
+            mCurrentModuleResult.setDone(mCurrentTestNum >= mTotalTestsInModule);
         }
         if (isShardResultReporter()) {
             // Forward module results to the master.
@@ -479,11 +466,10 @@
         String moduleProgress = String.format("%d of %d",
                 mResult.getModuleCompleteCount(), mResult.getModules().size());
 
-        info("Invocation finished in %s. PASSED: %d, FAILED: %d, NOT EXECUTED: %d, MODULES: %s",
+        info("Invocation finished in %s. PASSED: %d, FAILED: %d, MODULES: %s",
                 TimeUtil.formatElapsedTime(elapsedTime),
                 mResult.countResults(TestStatus.PASS),
                 mResult.countResults(TestStatus.FAIL),
-                mResult.getNotExecuted(),
                 moduleProgress);
 
         long startTime = mResult.getStartTime();
@@ -667,6 +653,7 @@
             return true; // always allow modules to be marked done if not retry
         }
         return !(RetryType.FAILED.equals(mRetryType)
+                || RetryType.CUSTOM.equals(mRetryType)
                 || args.contains(CompatibilityTest.INCLUDE_FILTER_OPTION)
                 || args.contains(CompatibilityTest.EXCLUDE_FILTER_OPTION)
                 || args.contains(CompatibilityTest.SUBPLAN_OPTION)
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 248b586..89c95a5 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
@@ -169,7 +169,7 @@
 
     @Option(name = RETRY_TYPE_OPTION,
             description = "used with " + RETRY_OPTION + ", retry tests of a certain status. "
-            + "Possible values include \"failed\" and \"not_executed\".",
+            + "Possible values include \"failed\", \"not_executed\", and \"custom\".",
             importance = Importance.IF_UNSET)
     private RetryType mRetryType = null;
 
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/util/RetryFilterHelper.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/util/RetryFilterHelper.java
index 9a68089..4ff3953 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/util/RetryFilterHelper.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/util/RetryFilterHelper.java
@@ -80,8 +80,9 @@
     protected String mTestName = null;
 
     @Option(name = CompatibilityTest.RETRY_TYPE_OPTION,
-            description = "used with " + CompatibilityTest.RETRY_OPTION + ", retry tests"
-            + " of a certain status. Possible values include \"failed\" and \"not_executed\".",
+            description = "used with " + CompatibilityTest.RETRY_OPTION
+            + ", retry tests of a certain status. Possible values include \"failed\", "
+            + "\"not_executed\", and \"custom\".",
             importance = Importance.IF_UNSET)
     protected RetryType mRetryType = null;
 
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ChecksumReporterTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ChecksumReporterTest.java
index 0646385..e08b002 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ChecksumReporterTest.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ChecksumReporterTest.java
@@ -77,7 +77,6 @@
         mInvocationResult = resultReporter.getResult();
         mModuleResult = mInvocationResult.getOrCreateModule("Module-1");
         mModuleResult.setDone(true);
-        mModuleResult.setNotExecuted(0);
         ICaseResult caseResult = mModuleResult.getOrCreateResult("Case-1");
         ITestResult test1 = caseResult.getOrCreateResult("Test1");
         test1.passed(mReportLog);
@@ -87,7 +86,6 @@
         IModuleResult moduleResult2 = mInvocationResult.getOrCreateModule("Module-2");
         ICaseResult caseResult2 = moduleResult2.getOrCreateResult("Case-2");
         mModuleResult.setDone(false);
-        mModuleResult.setNotExecuted(1);
         ITestResult test3 = caseResult2.getOrCreateResult("Test3");
         test3.passed(mReportLog);
 
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/SubPlanHelperTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/SubPlanHelperTest.java
index cf2006c..d7c4e67 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/SubPlanHelperTest.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/SubPlanHelperTest.java
@@ -137,7 +137,6 @@
         moduleATest1.setResultStatus(TestStatus.PASS);
         ITestResult moduleATest2 = moduleACase.getOrCreateResult(METHOD_2);
         moduleATest2.setResultStatus(null); // not executed test
-        moduleA.setNotExecuted(1);
 
         IModuleResult moduleB = result.getOrCreateModule(ID_B);
         moduleB.setDone(true);
diff --git a/common/util/src/com/android/compatibility/common/util/ChecksumReporter.java b/common/util/src/com/android/compatibility/common/util/ChecksumReporter.java
index 32fa532..ce39f38 100644
--- a/common/util/src/com/android/compatibility/common/util/ChecksumReporter.java
+++ b/common/util/src/com/android/compatibility/common/util/ChecksumReporter.java
@@ -331,7 +331,6 @@
         sb.append(buildFingerprint).append(SEPARATOR)
                 .append(module.getId()).append(SEPARATOR)
                 .append(module.isDone()).append(SEPARATOR)
-                .append(module.getNotExecuted()).append(SEPARATOR)
                 .append(module.countResults(TestStatus.FAIL));
         return sb.toString();
     }
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 dd7bd29..64798e8 100644
--- a/common/util/src/com/android/compatibility/common/util/ResultHandler.java
+++ b/common/util/src/com/android/compatibility/common/util/ResultHandler.java
@@ -94,7 +94,6 @@
     private static final String MODULES_DONE_ATTR = "modules_done";
     private static final String MODULES_TOTAL_ATTR = "modules_total";
     private static final String NAME_ATTR = "name";
-    private static final String NOT_EXECUTED_ATTR = "not_executed";
     private static final String OS_ARCH_ATTR = "os_arch";
     private static final String OS_NAME_ATTR = "os_name";
     private static final String OS_VERSION_ATTR = "os_version";
@@ -211,9 +210,6 @@
                 boolean done = Boolean.parseBoolean(parser.getAttributeValue(NS, DONE_ATTR));
                 IModuleResult module = result.getOrCreateModule(moduleId);
                 module.initializeDone(done);
-                int notExecuted = Integer.parseInt(
-                        parser.getAttributeValue(NS, NOT_EXECUTED_ATTR));
-                module.setNotExecuted(notExecuted);
                 long runtime = Long.parseLong(parser.getAttributeValue(NS, RUNTIME_ATTR));
                 module.addRuntime(runtime);
                 while (parser.nextTag() == XmlPullParser.START_TAG) {
@@ -296,7 +292,6 @@
             throws IOException, XmlPullParserException {
         int passed = result.countResults(TestStatus.PASS);
         int failed = result.countResults(TestStatus.FAIL);
-        int notExecuted = result.getNotExecuted();
         File resultFile = new File(resultDir, TEST_RESULT_FILE_NAME);
         OutputStream stream = new FileOutputStream(resultFile);
         XmlSerializer serializer = XmlPullParserFactory.newInstance(TYPE, null).newSerializer();
@@ -368,7 +363,6 @@
         serializer.startTag(NS, SUMMARY_TAG);
         serializer.attribute(NS, PASS_ATTR, Integer.toString(passed));
         serializer.attribute(NS, FAILED_ATTR, Integer.toString(failed));
-        serializer.attribute(NS, NOT_EXECUTED_ATTR, Integer.toString(notExecuted));
         serializer.attribute(NS, MODULES_DONE_ATTR,
                 Integer.toString(result.getModuleCompleteCount()));
         serializer.attribute(NS, MODULES_TOTAL_ATTR,
@@ -382,7 +376,6 @@
             serializer.attribute(NS, ABI_ATTR, module.getAbi());
             serializer.attribute(NS, RUNTIME_ATTR, String.valueOf(module.getRuntime()));
             serializer.attribute(NS, DONE_ATTR, Boolean.toString(module.isDone()));
-            serializer.attribute(NS, NOT_EXECUTED_ATTR, Integer.toString(module.getNotExecuted()));
             serializer.attribute(NS, PASS_ATTR,
                     Integer.toString(module.countResults(TestStatus.PASS)));
             for (ICaseResult cr : module.getResults()) {
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 9101618..74784bc 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
@@ -48,8 +48,6 @@
     private static final String NAME_B = "ModuleB";
     private static final String DONE_A = "false";
     private static final String DONE_B = "true";
-    private static final String NOT_EXECUTED_A = "1";
-    private static final String NOT_EXECUTED_B = "0";
     private static final String RUNTIME_A = "100";
     private static final String RUNTIME_B = "200";
     private static final String ABI = "mips64";
@@ -101,10 +99,10 @@
             "  <Build build_fingerprint=\"%s\" " + BUILD_ID + "=\"%s\" " +
                BUILD_PRODUCT + "=\"%s\" />\n";
     private static final String XML_SUMMARY =
-            "  <Summary pass=\"%d\" failed=\"%d\" not_executed=\"%d\" " +
+            "  <Summary pass=\"%d\" failed=\"%d\" " +
             "modules_done=\"1\" modules_total=\"1\" />\n";
     private static final String XML_MODULE =
-            "  <Module name=\"%s\" abi=\"%s\" device=\"%s\" runtime=\"%s\" done=\"%s\" not_executed=\"%s\">\n" +
+            "  <Module name=\"%s\" abi=\"%s\" device=\"%s\" runtime=\"%s\" done=\"%s\">\n" +
             "%s" +
             "  </Module>\n";
     private static final String XML_CASE =
@@ -161,7 +159,6 @@
         moduleATest1.setResultStatus(TestStatus.PASS);
         ITestResult moduleATest2 = moduleACase.getOrCreateResult(METHOD_2);
         moduleATest2.setResultStatus(null); // not executed test
-        moduleA.setNotExecuted(1);
 
         IModuleResult moduleB = result.getOrCreateModule(ID_B);
         moduleB.setDone(true);
@@ -221,7 +218,7 @@
             String moduleATest = String.format(XML_TEST_PASS, METHOD_1);
             String moduleACases = String.format(XML_CASE, CLASS_A, moduleATest);
             String moduleA = String.format(XML_MODULE, NAME_A, ABI, DEVICE_A, RUNTIME_A, DONE_A,
-                    NOT_EXECUTED_A, moduleACases);
+                    moduleACases);
             String moduleBTest3 = String.format(XML_TEST_FAIL, METHOD_3, MESSAGE, STACK_TRACE);
             String moduleBTest4 = String.format(XML_TEST_RESULT, METHOD_4,
                     SUMMARY_SOURCE, SUMMARY_MESSAGE, ResultType.HIGHER_BETTER.toReportString(),
@@ -231,7 +228,7 @@
             String moduleBTests = String.format(JOIN, moduleBTest3, moduleBTest4);
             String moduleBCases = String.format(XML_CASE, CLASS_B, moduleBTests);
             String moduleB = String.format(XML_MODULE, NAME_B, ABI, DEVICE_B, RUNTIME_B, DONE_B,
-                    NOT_EXECUTED_B, moduleBCases);
+                    moduleBCases);
             String modules = String.format(JOIN, moduleA, moduleB);
             String hostName = "";
             try {
@@ -255,7 +252,6 @@
     static void checkLightResult(IInvocationResult lightResult) throws Exception {
         assertEquals("Expected 2 passes", 2, lightResult.countResults(TestStatus.PASS));
         assertEquals("Expected 1 failure", 1, lightResult.countResults(TestStatus.FAIL));
-        assertEquals("Expected 1 not executed", 1, lightResult.getNotExecuted());
 
         Map<String, String> buildInfo = lightResult.getInvocationInfo();
         assertEquals("Incorrect Build ID", EXAMPLE_BUILD_ID, buildInfo.get(BUILD_ID));
@@ -277,7 +273,6 @@
     static void checkResult(IInvocationResult result) throws Exception {
         assertEquals("Expected 2 passes", 2, result.countResults(TestStatus.PASS));
         assertEquals("Expected 1 failure", 1, result.countResults(TestStatus.FAIL));
-        assertEquals("Expected 1 not executed", 1, result.getNotExecuted());
 
         Map<String, String> buildInfo = result.getInvocationInfo();
         assertEquals("Incorrect Build ID", EXAMPLE_BUILD_ID, buildInfo.get(BUILD_ID));
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
index 46d243e..793938a 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
@@ -84,6 +84,7 @@
     protected ConnectivityManager mCm;
     protected WifiManager mWfm;
     protected int mUid;
+    private int mMyUid;
     private String mMeteredWifi;
     private boolean mSupported;
 
@@ -96,11 +97,11 @@
         mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
         mWfm = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
         mUid = getUid(TEST_APP2_PKG);
-        final int myUid = getUid(mContext.getPackageName());
+        mMyUid = getUid(mContext.getPackageName());
         mSupported = setUpActiveNetworkMeteringState();
 
         Log.i(TAG, "Apps status on " + getName() + ":\n"
-                + "\ttest app: uid=" + myUid + ", state=" + getProcessStateByUid(myUid) + "\n"
+                + "\ttest app: uid=" + mMyUid + ", state=" + getProcessStateByUid(mMyUid) + "\n"
                 + "\tapp2: uid=" + mUid + ", state=" + getProcessStateByUid(mUid));
    }
 
@@ -175,6 +176,21 @@
         assertEquals("wrong status", toString(expectedStatus), actualStatus);
     }
 
+    protected void assertMyRestrictBackgroundStatus(int expectedStatus) throws Exception {
+        final int actualStatus = mCm.getRestrictBackgroundStatus();
+        assertEquals("Wrong status", toString(expectedStatus), toString(actualStatus));
+    }
+
+    protected boolean isMyRestrictBackgroundStatus(int expectedStatus) throws Exception {
+        final int actualStatus = mCm.getRestrictBackgroundStatus();
+        if (expectedStatus != actualStatus) {
+            Log.d(TAG, "Expected: " + toString(expectedStatus)
+                    + " but actual: " + toString(actualStatus));
+            return false;
+        }
+        return true;
+    }
+
     protected void assertBackgroundNetworkAccess(boolean expectAllowed) throws Exception {
         assertBackgroundState(); // Sanity check.
         assertNetworkAccess(expectAllowed);
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
index ac35bd4..d5e236f 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
@@ -20,16 +20,21 @@
 import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
 import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED;
 
+import android.util.Log;
+
 public class DataSaverModeTest extends AbstractRestrictBackgroundNetworkTestCase {
 
     private static final String[] REQUIRED_WHITELISTED_PACKAGES = {
         "com.android.providers.downloads"
     };
 
+    private boolean mIsDataSaverSupported;
+
     @Override
     public void setUp() throws Exception {
         super.setUp();
 
+        mIsDataSaverSupported = isDataSaverSupported();
         if (!isSupported()) return;
 
         // Set initial state.
@@ -59,6 +64,32 @@
         return setMeteredNetwork();
     }
 
+    @Override
+    protected boolean isSupported() throws Exception {
+        if (!mIsDataSaverSupported) {
+            Log.i(TAG, "Skipping " + getClass() + "." + getName()
+                    + "() because device does not support Data Saver Mode");
+        }
+        return mIsDataSaverSupported && super.isSupported();
+    }
+
+    /**
+     * As per CDD requirements, if the device doesn't support data saver mode then
+     * ConnectivityManager.getRestrictBackgroundStatus() will always return
+     * RESTRICT_BACKGROUND_STATUS_DISABLED. So, enable the data saver mode and check if
+     * ConnectivityManager.getRestrictBackgroundStatus() for an app in background returns
+     * RESTRICT_BACKGROUND_STATUS_DISABLED or not.
+     */
+    private boolean isDataSaverSupported() throws Exception {
+        assertMyRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_DISABLED);
+        try {
+            setRestrictBackground(true);
+            return !isMyRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_DISABLED);
+        } finally {
+            setRestrictBackground(false);
+        }
+    }
+
     public void testGetRestrictBackgroundStatus_disabled() throws Exception {
         if (!isSupported()) return;
 
diff --git a/hostsidetests/theme/src/android/theme/cts/ColorUtils.java b/hostsidetests/theme/src/android/theme/cts/ColorUtils.java
new file mode 100644
index 0000000..a7ed884
--- /dev/null
+++ b/hostsidetests/theme/src/android/theme/cts/ColorUtils.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.theme.cts;
+
+/**
+ * A set of color-related utility methods, building upon those available in {@code Color}.
+ */
+public class ColorUtils {
+
+    private static final double XYZ_WHITE_REFERENCE_X = 95.047;
+    private static final double XYZ_WHITE_REFERENCE_Y = 100;
+    private static final double XYZ_WHITE_REFERENCE_Z = 108.883;
+    private static final double XYZ_EPSILON = 0.008856;
+    private static final double XYZ_KAPPA = 903.3;
+
+    private ColorUtils() {}
+
+    /**
+     * Performs alpha blending of two colors using Porter-Duff SRC_OVER.
+     *
+     * @param src
+     * @param dst
+     */
+    public static int blendSrcOver(int src, int dst) {
+        int x = 255 - a(src);
+        int Ar = clamp(a(src) + a(dst) * x);
+        int Rr = clamp(r(src) + r(dst) * x);
+        int Gr = clamp(g(src) + g(dst) * x);
+        int Br = clamp(b(src) + b(dst) * x);
+        return argb(Ar, Rr, Gr, Br);
+    }
+
+    private static int clamp(int value) {
+        return value > 255 ? 255 : value < 0 ? 0 : value;
+    }
+
+    /**
+     * Return a color-int from alpha, red, green, blue components.
+     * These component values should be \([0..255]\), but there is no
+     * range check performed, so if they are out of range, the
+     * returned color is undefined.
+     *
+     * @param alpha Alpha component \([0..255]\) of the color
+     * @param red Red component \([0..255]\) of the color
+     * @param green Green component \([0..255]\) of the color
+     * @param blue Blue component \([0..255]\) of the color
+     */
+    public static int argb(int alpha, int red, int green, int blue) {
+        return (alpha << 24) | (red << 16) | (green << 8) | blue;
+    }
+
+    /**
+     * Return the alpha component of a color int. This is the same as saying
+     * color >>> 24
+     */
+    public static int a(int color) {
+        return color >>> 24;
+    }
+
+    /**
+     * Return the red component of a color int. This is the same as saying
+     * (color >> 16) & 0xFF
+     */
+    public static int r(int color) {
+        return (color >> 16) & 0xFF;
+    }
+
+    /**
+     * Return the green component of a color int. This is the same as saying
+     * (color >> 8) & 0xFF
+     */
+    public static int g(int color) {
+        return (color >> 8) & 0xFF;
+    }
+
+    /**
+     * Return the blue component of a color int. This is the same as saying
+     * color & 0xFF
+     */
+    public static int b(int color) {
+        return color & 0xFF;
+    }
+
+    /**
+     * Convert the ARGB color to its CIE Lab representative components.
+     *
+     * @param color  the ARGB color to convert. The alpha component is ignored
+     * @param outLab 3-element array which holds the resulting LAB components
+     */
+    public static void colorToLAB(int color, double[] outLab) {
+        RGBToLAB(r(color), g(color), b(color), outLab);
+    }
+
+    /**
+     * Convert RGB components to its CIE Lab representative components.
+     *
+     * <ul>
+     * <li>outLab[0] is L [0 ...1)</li>
+     * <li>outLab[1] is a [-128...127)</li>
+     * <li>outLab[2] is b [-128...127)</li>
+     * </ul>
+     *
+     * @param r      red component value [0..255]
+     * @param g      green component value [0..255]
+     * @param b      blue component value [0..255]
+     * @param outLab 3-element array which holds the resulting LAB components
+     */
+    public static void RGBToLAB(int r, int g, int b, double[] outLab) {
+        // First we convert RGB to XYZ
+        RGBToXYZ(r, g, b, outLab);
+        // outLab now contains XYZ
+        XYZToLAB(outLab[0], outLab[1], outLab[2], outLab);
+        // outLab now contains LAB representation
+    }
+
+    /**
+     * Convert RGB components to its CIE XYZ representative components.
+     *
+     * <p>The resulting XYZ representation will use the D65 illuminant and the CIE
+     * 2°Standard Observer (1931).</p>
+     *
+     * <ul>
+     * <li>outXyz[0] is X [0 ...95.047)</li>
+     * <li>outXyz[1] is Y [0...100)</li>
+     * <li>outXyz[2] is Z [0...108.883)</li>
+     * </ul>
+     *
+     * @param r      red component value [0..255]
+     * @param g      green component value [0..255]
+     * @param b      blue component value [0..255]
+     * @param outXyz 3-element array which holds the resulting XYZ components
+     */
+    public static void RGBToXYZ(int r, int g, int b, double[] outXyz) {
+        if (outXyz.length != 3) {
+            throw new IllegalArgumentException("outXyz must have a length of 3.");
+        }
+
+        double sr = r / 255.0;
+        sr = sr < 0.04045 ? sr / 12.92 : Math.pow((sr + 0.055) / 1.055, 2.4);
+        double sg = g / 255.0;
+        sg = sg < 0.04045 ? sg / 12.92 : Math.pow((sg + 0.055) / 1.055, 2.4);
+        double sb = b / 255.0;
+        sb = sb < 0.04045 ? sb / 12.92 : Math.pow((sb + 0.055) / 1.055, 2.4);
+
+        outXyz[0] = 100 * (sr * 0.4124 + sg * 0.3576 + sb * 0.1805);
+        outXyz[1] = 100 * (sr * 0.2126 + sg * 0.7152 + sb * 0.0722);
+        outXyz[2] = 100 * (sr * 0.0193 + sg * 0.1192 + sb * 0.9505);
+    }
+
+    /**
+     * Converts a color from CIE XYZ to CIE Lab representation.
+     *
+     * <p>This method expects the XYZ representation to use the D65 illuminant and the CIE
+     * 2° Standard Observer (1931).</p>
+     *
+     * <ul>
+     * <li>outLab[0] is L [0 ...1)</li>
+     * <li>outLab[1] is a [-128...127)</li>
+     * <li>outLab[2] is b [-128...127)</li>
+     * </ul>
+     *
+     * @param x      X component value [0...95.047)
+     * @param y      Y component value [0...100)
+     * @param z      Z component value [0...108.883)
+     * @param outLab 3-element array which holds the resulting Lab components
+     */
+    public static void XYZToLAB(double x, double y, double z, double[] outLab) {
+        if (outLab.length != 3) {
+            throw new IllegalArgumentException("outLab must have a length of 3.");
+        }
+        x = pivotXyzComponent(x / XYZ_WHITE_REFERENCE_X);
+        y = pivotXyzComponent(y / XYZ_WHITE_REFERENCE_Y);
+        z = pivotXyzComponent(z / XYZ_WHITE_REFERENCE_Z);
+        outLab[0] = Math.max(0, 116 * y - 16);
+        outLab[1] = 500 * (x - y);
+        outLab[2] = 200 * (y - z);
+    }
+
+    private static double pivotXyzComponent(double component) {
+        return component > XYZ_EPSILON
+                ? Math.pow(component, 1 / 3.0)
+                : (XYZ_KAPPA * component + 16) / 116;
+    }
+}
diff --git a/hostsidetests/theme/src/android/theme/cts/ComparisonTask.java b/hostsidetests/theme/src/android/theme/cts/ComparisonTask.java
index 5f4a741..0f8768e 100755
--- a/hostsidetests/theme/src/android/theme/cts/ComparisonTask.java
+++ b/hostsidetests/theme/src/android/theme/cts/ComparisonTask.java
@@ -34,7 +34,14 @@
 public class ComparisonTask implements Callable<File> {
     private static final String TAG = "ComparisonTask";
 
-    private static final int IMAGE_THRESHOLD = 2;
+    /** Maximum allowed LAB distance between two pixels. */
+    private static final double IMAGE_THRESHOLD = 0.76;
+
+    /** Neutral gray for blending colors. */
+    private static final int GRAY = 0xFF808080;
+
+    /** Maximum allowable number of consecutive failed pixels. */
+    private static final int MAX_CONSECUTIVE_FAILURES = 1;
 
     private final File mExpected;
     private final File mActual;
@@ -87,32 +94,63 @@
         return (color & 0xFF000000) >>> 24;
     }
 
-    private static boolean compare(BufferedImage reference, BufferedImage generated, int threshold) {
+    private static boolean compare(BufferedImage reference, BufferedImage generated,
+            double threshold) {
         final int w = generated.getWidth();
         final int h = generated.getHeight();
         if (w != reference.getWidth() || h != reference.getHeight()) {
             return false;
         }
 
+        double maxDist = 0;
         for (int i = 0; i < w; i++) {
+            int consecutive = 0;
+
             for (int j = 0; j < h; j++) {
                 final int p1 = reference.getRGB(i, j);
                 final int p2 = generated.getRGB(i, j);
+                final double dist = computeLabDistance(p1, p2);
+                if (dist > threshold) {
+                    System.err.println("fail " + dist);
 
-                final int dr = getAlphaScaledRed(p1) - getAlphaScaledRed(p2);
-                final int dg = getAlphaScaledGreen(p1) - getAlphaScaledGreen(p2);
-                final int db = getAlphaScaledBlue(p1) - getAlphaScaledBlue(p2);
+                    consecutive++;
 
-                if (Math.abs(db) > threshold ||
-                        Math.abs(dg) > threshold ||
-                        Math.abs(dr) > threshold) {
-                    return false;
+                    if (consecutive > MAX_CONSECUTIVE_FAILURES) {
+                        System.err.println("consecutive fail");
+                        return false;
+                    }
+                } else {
+                    consecutive = 0;
                 }
             }
         }
         return true;
     }
 
+    /**
+     * Returns the perceptual difference score (lower is better) for the
+     * provided ARGB pixels.
+     */
+    private static double computeLabDistance(int p1, int p2) {
+        // Blend with neutral gray to account for opacity.
+        p1 = ColorUtils.blendSrcOver(p1, GRAY);
+        p2 = ColorUtils.blendSrcOver(p2, GRAY);
+
+        // Convert to LAB.
+        double[] lab1 = new double[3];
+        double[] lab2 = new double[3];
+        ColorUtils.colorToLAB(p1, lab1);
+        ColorUtils.colorToLAB(p2, lab2);
+
+        // Compute the distance
+        double dist = 0;
+        for (int i = 0; i < 3; i++) {
+            double delta = lab1[i] - lab2[i];
+            dist += delta * delta;
+        }
+        return Math.sqrt(dist);
+    }
+
     private static void createDiff(BufferedImage expected, BufferedImage actual, File out)
             throws IOException {
         final int w1 = expected.getWidth();
diff --git a/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java b/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
index a9b4ad2..037074c 100644
--- a/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
@@ -1165,7 +1165,11 @@
     private long getExposureValue(CaptureResult result) throws Exception {
         int expTimeUs = (int) (getValueNotNull(result, CaptureResult.SENSOR_EXPOSURE_TIME) / 1000);
         int sensitivity = getValueNotNull(result, CaptureResult.SENSOR_SENSITIVITY);
-        return expTimeUs * sensitivity;
+        Integer postRawSensitivity = result.get(CaptureResult.CONTROL_POST_RAW_SENSITIVITY_BOOST);
+        if (postRawSensitivity != null) {
+            return (long) sensitivity * postRawSensitivity / 100 * expTimeUs;
+        }
+        return (long) sensitivity * expTimeUs;
     }
 
     private long getMaxExposureValue(CaptureRequest.Builder request, long maxExposureTimeUs,
diff --git a/tests/tests/graphics/assets/ft45987.ttf b/tests/tests/graphics/assets/ft45987.ttf
new file mode 100644
index 0000000..369022f
--- /dev/null
+++ b/tests/tests/graphics/assets/ft45987.ttf
Binary files differ
diff --git a/tests/tests/graphics/assets/ft45987.ttf.README.txt b/tests/tests/graphics/assets/ft45987.ttf.README.txt
new file mode 100644
index 0000000..7586955
--- /dev/null
+++ b/tests/tests/graphics/assets/ft45987.ttf.README.txt
@@ -0,0 +1,4 @@
+ft45987.ttf was automatically generated by LibFuzzer
+(http://llvm.org/docs/LibFuzzer.html). Its base64 encoded version was taken
+from http://savannah.nongnu.org/bugs/?func=detailitem&item_id=45987 and
+decoded back.
diff --git a/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java b/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
index e5a610c..7ac679a 100644
--- a/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
@@ -221,4 +221,9 @@
                 typeface3, typeface4);
     }
 
+    @SmallTest
+    public void testBadFont() {
+        Typeface typeface = Typeface.createFromAsset(getContext().getAssets(), "ft45987.ttf");
+        assertNotNull(typeface);
+    }
 }
diff --git a/tests/tests/location/src/android/location/cts/TestMeasurementUtil.java b/tests/tests/location/src/android/location/cts/TestMeasurementUtil.java
index 662a1fd..9fb30f2 100644
--- a/tests/tests/location/src/android/location/cts/TestMeasurementUtil.java
+++ b/tests/tests/location/src/android/location/cts/TestMeasurementUtil.java
@@ -181,9 +181,9 @@
         int state = measurement.getState();
         softAssert.assertTrue("state: Satellite code sync state",
                 timeInNs,
-                "X > 0",
+                "X >= 0",
                 String.valueOf(state),
-                state > 0);
+                state >= 0);
 
         // Check received_gps_tow_uncertainty_ns
         softAssert.assertTrueAsWarning("received_gps_tow_uncertainty_ns:" +
diff --git a/tests/tests/security/res/raw/bug_33251605.bmp b/tests/tests/security/res/raw/bug_33251605.bmp
new file mode 100644
index 0000000..0060ff4
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_33251605.bmp
Binary files differ
diff --git a/tests/tests/security/src/android/security/cts/BigRleTest.java b/tests/tests/security/src/android/security/cts/BigRleTest.java
new file mode 100644
index 0000000..f3c2302
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/BigRleTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.test.AndroidTestCase;
+
+import java.io.InputStream;
+
+import android.security.cts.R;
+
+public class BigRleTest extends AndroidTestCase {
+    /**
+     * Verifies that the device does not run OOM decoding a particular RLE encoded BMP.
+     *
+     * This image reports that its encoded length is over 4 gigs. Prior to fixing issue 33251605,
+     * we attempted to allocate space for all the encoded data at once, resulting in OOM.
+     */
+    public void test_android_bug_33251605() {
+        InputStream exploitImage = mContext.getResources().openRawResource(R.raw.bug_33251605);
+        Bitmap bitmap = BitmapFactory.decodeStream(exploitImage);
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index 3111897..640c0c5 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -482,6 +482,7 @@
                     codec.release();
                 }
             }
+            ex.unselectTrack(t);
         }
         ex.release();
         String cve = rname.replace("_", "-").toUpperCase();
@@ -532,7 +533,7 @@
         MediaMetadataRetriever retriever = new MediaMetadataRetriever();
         try {
             retriever.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
-        } catch (IllegalArgumentException e) {
+        } catch (RuntimeException e) {
             // ignore
         }
         retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
diff --git a/tools/cts-tradefed/Android.mk b/tools/cts-tradefed/Android.mk
index c447ce8..d684fee 100644
--- a/tools/cts-tradefed/Android.mk
+++ b/tools/cts-tradefed/Android.mk
@@ -25,7 +25,7 @@
 LOCAL_SUITE_TARGET_ARCH := $(TARGET_ARCH)
 LOCAL_SUITE_NAME := CTS
 LOCAL_SUITE_FULLNAME := "Compatibility Test Suite"
-LOCAL_SUITE_VERSION := 7.0_r8
+LOCAL_SUITE_VERSION := 7.0_r9
 
 LOCAL_MODULE := cts-tradefed