Merge "Fix off by one error in timestamp jitter calculation"
diff --git a/apps/CameraITS/tools/run_all_tests.py b/apps/CameraITS/tools/run_all_tests.py
index 46d335f..118e2b9 100644
--- a/apps/CameraITS/tools/run_all_tests.py
+++ b/apps/CameraITS/tools/run_all_tests.py
@@ -167,6 +167,7 @@
 
     # Make output directories to hold the generated files.
     topdir = tempfile.mkdtemp()
+    subprocess.call(['chmod', 'g+rx', topdir])
     print "Saving output files to:", topdir, "\n"
 
     device_id = its.device.get_device_id()
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 9e3111d..eb33878 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -1062,6 +1062,17 @@
             <meta-data android:name="test_required_features" android:value="android.hardware.location.gps" />
         </activity>
 
+        <activity android:name=".location.GnssTtffTestsActivity"
+            android:label="@string/location_gnss_ttff_test"
+            android:screenOrientation="locked">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.cts.intent.category.MANUAL_TEST"/>
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_hardware"/>
+            <meta-data android:name="test_required_features" android:value="android.hardware.location.gps" />
+        </activity>
+
         <activity android:name=".location.GnssMeasurementWhenNoLocationTestsActivity"
             android:label="@string/location_gnss_measure_no_location_test"
             android:screenOrientation="locked">
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 2f9afa2..da1e170 100755
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -604,6 +604,7 @@
     <string name="location_gnss_measure_no_location_test">GNSS Measurement Before Location Test</string>
     <string name="location_gnss_reg_test">GNSS Measurement Registration Test</string>
     <string name="location_gnss_value_test">GNSS Measurement Values Test</string>
+    <string name="location_gnss_ttff_test">GNSS TTFF Test</string>
     <string name="location_gnss_nav_msg_test">GNSS Navigation Message Test</string>
     <string name="location_gnss_status_test">GNSS Status Test</string>
     <string name="location_gnss_test_info">This test verifies basic GNSS behavior.
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/location/GnssTtffTestsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/location/GnssTtffTestsActivity.java
new file mode 100644
index 0000000..1ba925c
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/location/GnssTtffTestsActivity.java
@@ -0,0 +1,15 @@
+package com.android.cts.verifier.location;
+
+import com.android.cts.verifier.location.base.GnssCtsTestActivity;
+import android.location.cts.GnssTtffTests;
+
+/**
+ * Activity to execute CTS GnssStatusTest.
+ * It is a wrapper for {@link GnssTtffTests} running with AndroidJUnitRunner.
+ */
+
+public class GnssTtffTestsActivity extends GnssCtsTestActivity {
+  public GnssTtffTestsActivity() {
+    super(GnssTtffTests.class);
+  }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/AttentionManagementVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/AttentionManagementVerifierActivity.java
index 0355cb4..23744c7 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/AttentionManagementVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/AttentionManagementVerifierActivity.java
@@ -32,7 +32,6 @@
 import android.provider.ContactsContract.CommonDataKinds.Email;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
-import android.provider.Settings;
 import android.service.notification.NotificationListenerService;
 import android.util.Log;
 import android.view.View;
@@ -101,7 +100,7 @@
         tests.add(new SetModeAllTest());
         tests.add(new AllInterceptsNothingTest());
         tests.add(new DefaultOrderTest());
-        tests.add(new PrioritytOrderTest());
+        tests.add(new PriorityOrderTest());
         tests.add(new InterruptionOrderTest());
         tests.add(new AmbientBitsTest());
         tests.add(new LookupUriOrderTest());
@@ -113,13 +112,11 @@
 
     private void createChannels() {
         NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID,
-                NOTIFICATION_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT);
+                NOTIFICATION_CHANNEL_ID, NotificationManager.IMPORTANCE_MIN);
         mNm.createNotificationChannel(channel);
         NotificationChannel noisyChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID_NOISY,
                 NOTIFICATION_CHANNEL_ID_NOISY, NotificationManager.IMPORTANCE_HIGH);
         noisyChannel.enableVibration(true);
-        noisyChannel.setSound(
-                Settings.System.DEFAULT_RINGTONE_URI, Notification.AUDIO_ATTRIBUTES_DEFAULT);
         mNm.createNotificationChannel(noisyChannel);
     }
 
@@ -528,7 +525,7 @@
     }
 
     // ordered by priority: B, C, A
-    protected class PrioritytOrderTest extends InteractiveTestCase {
+    protected class PriorityOrderTest extends InteractiveTestCase {
         @Override
         View inflate(ViewGroup parent) {
             return createAutoItem(parent, R.string.attention_priority_order);
@@ -585,8 +582,8 @@
         @Override
         void setUp() {
             createChannels();
-            // send B & C noisy
-            sendNotifications(SEND_B | SEND_C, MODE_NONE, false, true);
+            // send B & C noisy with contact affinity
+            sendNotifications(SEND_B | SEND_C, MODE_URI, false, true);
             status = READY;
             // wait for then to not be recently noisy any more
             delay(15000);
@@ -595,7 +592,7 @@
         @Override
         void test() {
             if (status == READY) {
-                // send A noisy
+                // send A noisy but no contact affinity
                 sendNotifications(SEND_A, MODE_NONE, false, true);
                 status = RETEST;
                 delay();
@@ -650,7 +647,8 @@
         @Override
         void setUp() {
             createChannels();
-            sendNotifications(MODE_NONE, true, false);
+            sendNotifications(SEND_B | SEND_C, MODE_NONE, true, true);
+            sendNotifications(SEND_A, MODE_NONE, true, false);
             status = READY;
             // wait for notifications to move through the system
             delay();
diff --git a/build/config.mk b/build/config.mk
index 573dc7b..159dc8d 100644
--- a/build/config.mk
+++ b/build/config.mk
@@ -20,7 +20,7 @@
 BUILD_COMPATIBILITY_SUITE := cts/build/compatibility_test_suite.mk
 BUILD_CTS_EXECUTABLE := cts/build/test_executable.mk
 BUILD_CTS_PACKAGE := cts/build/test_package.mk
-BUILD_CTS_HOST_JAVA_LIBRARY := $(BUILD_HOST_JAVA_LIBRARY)
+BUILD_CTS_HOST_JAVA_LIBRARY := cts/build/host_java_library.mk
 BUILD_CTS_TARGET_JAVA_LIBRARY := cts/build/test_target_java_library.mk
 BUILD_CTS_SUPPORT_PACKAGE := cts/build/support_package.mk
 BUILD_CTS_DEVICE_INFO_PACKAGE := cts/build/device_info_package.mk
diff --git a/build/device_info_package.mk b/build/device_info_package.mk
index b91c264..e584bc4 100644
--- a/build/device_info_package.mk
+++ b/build/device_info_package.mk
@@ -26,7 +26,6 @@
   $(DEVICE_INFO_PACKAGE).GenericDeviceInfo \
   $(DEVICE_INFO_PACKAGE).GlesStubActivity \
   $(DEVICE_INFO_PACKAGE).GraphicsDeviceInfo \
-  $(DEVICE_INFO_PACKAGE).LibraryDeviceInfo \
   $(DEVICE_INFO_PACKAGE).LocaleDeviceInfo \
   $(DEVICE_INFO_PACKAGE).MediaDeviceInfo \
   $(DEVICE_INFO_PACKAGE).MemoryDeviceInfo \
diff --git a/build/host_java_library.mk b/build/host_java_library.mk
new file mode 100644
index 0000000..303527e
--- /dev/null
+++ b/build/host_java_library.mk
@@ -0,0 +1,22 @@
+# 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.
+
+# Builds a java library (jar)
+#
+# Replace "include $(BUILD_HOST_JAVA_LIBRARY) with "include $(BUILD_CTS_HOST_JAVA_LIBRARY)
+#
+
+-include cts/error_prone_rules_tests.mk
+
+include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/build/support_package.mk b/build/support_package.mk
index e25ba8a..83d7da9 100644
--- a/build/support_package.mk
+++ b/build/support_package.mk
@@ -22,5 +22,6 @@
 LOCAL_DEX_PREOPT := false
 LOCAL_PROGUARD_ENABLED := disabled
 
+-include cts/error_prone_rules_tests.mk
 include $(BUILD_PACKAGE)
 
diff --git a/build/test_package.mk b/build/test_package.mk
index 3cec0af..2aa0852 100644
--- a/build/test_package.mk
+++ b/build/test_package.mk
@@ -20,5 +20,6 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES += platform-test-annotations
 
+-include cts/error_prone_rules_tests.mk
 include $(BUILD_CTS_SUPPORT_PACKAGE)
 
diff --git a/build/test_target_java_library.mk b/build/test_target_java_library.mk
index eb11ef7..c932c30 100644
--- a/build/test_target_java_library.mk
+++ b/build/test_target_java_library.mk
@@ -20,5 +20,6 @@
 LOCAL_DEX_PREOPT := false
 LOCAL_STATIC_JAVA_LIBRARIES += platform-test-annotations
 
+-include cts/error_prone_rules_tests.mk
 include $(BUILD_JAVA_LIBRARY)
 
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/LibraryDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/LibraryDeviceInfo.java
deleted file mode 100644
index 792c88a..0000000
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/LibraryDeviceInfo.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.compatibility.common.deviceinfo;
-
-import android.util.Log;
-
-import com.android.compatibility.common.util.DeviceInfoStore;
-
-import java.io.Closeable;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.Formatter;
-
-/**
- * Library device info collector.
- */
-public final class LibraryDeviceInfo extends DeviceInfo {
-
-    private static final String TAG = "LibraryDeviceInfo";
-    private static final int BUFFER_SIZE_BYTES = 4096;
-
-    @Override
-    protected void collectDeviceInfo(DeviceInfoStore store) throws Exception {
-        collectSystemLibs(store);
-        collectVendorLibs(store);
-        collectFrameworkJars(store);
-    }
-
-    private void collectSystemLibs(DeviceInfoStore store) throws Exception {
-        store.startArray("lib");
-        collectFileDetails(store, "/system/lib", ".so");
-        store.endArray();
-    }
-
-    private void collectVendorLibs(DeviceInfoStore store) throws Exception {
-        store.startArray("vendor_lib");
-        collectFileDetails(store, "/system/vendor/lib", ".so");
-        store.endArray();
-    }
-
-    private void collectFrameworkJars(DeviceInfoStore store) throws Exception {
-        store.startArray("framework_jar");
-        collectFileDetails(store, "/system/framework", ".jar");
-        store.endArray();
-    }
-
-    private void collectFileDetails(DeviceInfoStore store, String path, String suffix)
-            throws Exception {
-        File dir = new File(path);
-        File[] files = dir.listFiles();
-        if (files == null) {
-            return;
-        }
-        for (File file : files) {
-            String name = file.getName();
-            if (file.isFile() && name.endsWith(suffix)) {
-                String sha1 = "unknown";
-                try {
-                    sha1 = getSha1sum(file);
-                } catch (IOException e) {
-                    Log.e(TAG, "Failed to hash " + file + ": ", e);
-                }
-                store.startGroup();
-                store.addResult("name", name);
-                store.addResult("sha1", sha1);
-                store.endGroup();
-            }
-        }
-    }
-
-    private static String getSha1sum(File file) throws IOException {
-        InputStream in = null;
-        try {
-            in = new FileInputStream(file);
-            return sha1(in);
-        } finally {
-            close(in);
-        }
-    }
-
-    private static void close(Closeable s) throws IOException {
-        if (s == null) {
-            return;
-        }
-        s.close();
-    }
-
-    /**
-     * @return the SHA-1 digest of input as a hex string
-     */
-    public static String sha1(InputStream input) throws IOException {
-        try {
-            return toHexString(digest(input, "sha1"));
-        } catch (NoSuchAlgorithmException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    private static byte[] digest(InputStream in, String algorithm)
-        throws NoSuchAlgorithmException, IOException {
-        MessageDigest digest = MessageDigest.getInstance(algorithm);
-        byte[] buffer = new byte[BUFFER_SIZE_BYTES];
-        while (true) {
-            int read = in.read(buffer);
-            if (read < 0) {
-                break;
-            }
-            digest.update(buffer, 0, read);
-        }
-        return digest.digest();
-    }
-
-    private static String toHexString(byte[] buffer) {
-        Formatter formatter = new Formatter();
-        try {
-            for (byte b : buffer) {
-                formatter.format("%02X", b);
-            }
-            return formatter.toString();
-        } finally {
-            formatter.close();
-        }
-    }
-}
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 ad7cf47..6a78019 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
@@ -380,6 +380,7 @@
             // Forward module results to the master.
             mMasterResultReporter.mergeModuleResult(mCurrentModuleResult);
             mCurrentModuleResult.resetTestRuns();
+            mCurrentModuleResult.resetRuntime();
         }
     }
 
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/SubPlanHelper.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/SubPlanHelper.java
index 950a129..21cb203 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/SubPlanHelper.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/SubPlanHelper.java
@@ -307,7 +307,7 @@
         Set<TestStatus> statusesToRun = new HashSet<TestStatus>();
         for (String resultType : mResultTypes) {
             // no test status exists for not-executed tests
-            if (resultType != NOT_EXECUTED) {
+            if (!NOT_EXECUTED.equals(resultType)) {
                 statusesToRun.add(STATUS_MAP.get(resultType));
             }
         }
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java
index 6237c23..d48e9f6 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java
@@ -31,8 +31,6 @@
 
 import java.io.File;
 import java.io.FileNotFoundException;
-import java.util.HashMap;
-import java.util.Map;
 import java.util.Map.Entry;
 
 /**
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PreconditionPreparer.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PreconditionPreparer.java
index 27ef658..d47b56c 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PreconditionPreparer.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PreconditionPreparer.java
@@ -49,7 +49,7 @@
                     + "\"<arg-name>:<arg-value>\"")
     private List<String> mPreconditionArgs = new ArrayList<>();
 
-    protected final String LOG_TAG = getClass().getSimpleName();
+    protected final String mLogTag = getClass().getSimpleName();
 
     @Override
     public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
@@ -80,32 +80,32 @@
             throws TargetSetupError, BuildError, DeviceNotAvailableException;
 
     protected void logInfo(String info) {
-        LogUtil.printLog(Log.LogLevel.INFO, LOG_TAG, info);
+        LogUtil.printLog(Log.LogLevel.INFO, mLogTag, info);
     }
 
     protected void logInfo(String infoFormat, Object... args) {
-        LogUtil.printLog(Log.LogLevel.INFO, LOG_TAG, String.format(infoFormat, args));
+        LogUtil.printLog(Log.LogLevel.INFO, mLogTag, String.format(infoFormat, args));
     }
 
     protected void logWarning(String warning) {
-        LogUtil.printLog(Log.LogLevel.WARN, LOG_TAG, warning);
+        LogUtil.printLog(Log.LogLevel.WARN, mLogTag, warning);
     }
 
     protected void logWarning(String warningFormat, Object... args) {
-        LogUtil.printLog(Log.LogLevel.WARN, LOG_TAG, String.format(warningFormat, args));
+        LogUtil.printLog(Log.LogLevel.WARN, mLogTag, String.format(warningFormat, args));
     }
 
     protected void logError(String error) {
-        LogUtil.printLog(Log.LogLevel.ERROR, LOG_TAG, error);
+        LogUtil.printLog(Log.LogLevel.ERROR, mLogTag, error);
     }
 
     protected void logError(String errorFormat, Object... args) {
-        LogUtil.printLog(Log.LogLevel.ERROR, LOG_TAG, String.format(errorFormat, args));
+        LogUtil.printLog(Log.LogLevel.ERROR, mLogTag, String.format(errorFormat, args));
     }
 
     protected void logError(Throwable t) {
         if (t != null) {
-            Log.e(LOG_TAG, t);
+            Log.e(mLogTag, t);
         }
     }
 
diff --git a/common/host-side/tradefed/tests/Android.mk b/common/host-side/tradefed/tests/Android.mk
index 6bc8bc9..c61594a 100644
--- a/common/host-side/tradefed/tests/Android.mk
+++ b/common/host-side/tradefed/tests/Android.mk
@@ -19,6 +19,7 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
 LOCAL_JAVA_RESOURCE_DIRS := ../res
+include cts/error_prone_rules.mk
 
 LOCAL_SUITE_BUILD_NUMBER := 2
 LOCAL_SUITE_TARGET_ARCH := $(TARGET_ARCH)
@@ -27,7 +28,7 @@
 LOCAL_SUITE_VERSION := 1
 
 LOCAL_MODULE := compatibility-mock-tradefed
-
+include cts/error_prone_rules.mk
 include $(BUILD_COMPATIBILITY_SUITE)
 
 # Make the tests
@@ -36,6 +37,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_JAVA_RESOURCE_DIRS := res
 
+include cts/error_prone_rules.mk
 LOCAL_MODULE := compatibility-tradefed-tests
 
 LOCAL_MODULE_TAGS := optional
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java
index b85a036..dce227f 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java
@@ -48,9 +48,9 @@
      *  This particular module is shipping all it's dependencies in all abis with prebuilt stuff.
      *  Excluding it for now to have the test setup.
      */
-    private String MODULE_EXCEPTION = "CtsSplitApp";
+    private static final String MODULE_EXCEPTION = "CtsSplitApp";
 
-    private static Set<String> BINARY_EXCEPTIONS = new HashSet<>();
+    private static final Set<String> BINARY_EXCEPTIONS = new HashSet<>();
     static {
         /**
          * This binary is a host side helper, so we do not need to check it.
@@ -89,6 +89,20 @@
 
         for (File testApk : listApks) {
             AaptParser result = AaptParser.parse(testApk);
+            // Retry as we have seen flake with aapt sometimes.
+            if (result == null) {
+                for (int i = 0; i < 2; i++) {
+                    result = AaptParser.parse(testApk);
+                    if (result != null) {
+                        break;
+                    }
+                }
+                // If still couldn't parse the apk
+                if (result == null) {
+                    fail(String.format("Fail to run 'aapt dump badging %s'",
+                            testApk.getAbsolutePath()));
+                }
+            }
             // We only check the apk that have native code
             if (!result.getNativeCode().isEmpty()) {
                 List<String> supportedAbiApk = result.getNativeCode();
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/util/CollectorUtilTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/util/CollectorUtilTest.java
index 5e06d26..3f13671 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/util/CollectorUtilTest.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/util/CollectorUtilTest.java
@@ -22,7 +22,7 @@
  */
 public class CollectorUtilTest extends TestCase {
 
-    String UNFORMATTED_JSON = "{"
+    private static final String UNFORMATTED_JSON = "{"
             + "\"stream_name_1\":"
             + "{\"id\":1,\"key1\":\"value1\"},"
             + "\"stream_name_2\":"
@@ -31,7 +31,7 @@
             + "{\"id\":2,\"key1\":\"value2\"},"
             + "}";
 
-    String REFORMATTED_JSON = "{"
+    private static final String REFORMATTED_JSON = "{"
             + "\"stream_name_2\":"
             + "["
             + "{\"id\":1,\"key1\":\"value3\"}"
diff --git a/common/host-side/util/Android.mk b/common/host-side/util/Android.mk
index 771e334..23626bd 100644
--- a/common/host-side/util/Android.mk
+++ b/common/host-side/util/Android.mk
@@ -25,7 +25,7 @@
 LOCAL_MODULE := compatibility-host-util
 
 LOCAL_MODULE_TAGS := optional
-
+include cts/error_prone_rules.mk
 include $(BUILD_HOST_JAVA_LIBRARY)
 
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/common/host-side/util/src/com/android/compatibility/common/util/ApiLevelUtil.java b/common/host-side/util/src/com/android/compatibility/common/util/ApiLevelUtil.java
index d614caf..38158b4 100644
--- a/common/host-side/util/src/com/android/compatibility/common/util/ApiLevelUtil.java
+++ b/common/host-side/util/src/com/android/compatibility/common/util/ApiLevelUtil.java
@@ -23,7 +23,7 @@
  */
 public class ApiLevelUtil {
 
-    public static String CODENAME = "ro.build.version.codename";
+    public static final String CODENAME = "ro.build.version.codename";
 
     public static boolean isBefore(ITestDevice device, int version)
             throws DeviceNotAvailableException {
diff --git a/common/host-side/util/src/com/android/compatibility/common/util/HostInfoStore.java b/common/host-side/util/src/com/android/compatibility/common/util/HostInfoStore.java
index a17f17a..3b7f6c8 100644
--- a/common/host-side/util/src/com/android/compatibility/common/util/HostInfoStore.java
+++ b/common/host-side/util/src/com/android/compatibility/common/util/HostInfoStore.java
@@ -22,7 +22,6 @@
 import java.io.IOException;
 import java.io.OutputStreamWriter;
 import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
 import java.util.List;
 
 public class HostInfoStore extends InfoStore {
diff --git a/common/host-side/util/src/com/android/compatibility/common/util/PropertyUtil.java b/common/host-side/util/src/com/android/compatibility/common/util/PropertyUtil.java
index 199b826..2cdcc23 100644
--- a/common/host-side/util/src/com/android/compatibility/common/util/PropertyUtil.java
+++ b/common/host-side/util/src/com/android/compatibility/common/util/PropertyUtil.java
@@ -28,7 +28,7 @@
      * Name of read-only property detailing the first API level for which the product was
      * shipped. Property should be undefined for factory ROM products.
      */
-    public static String FIRST_API_LEVEL = "ro.product.first_api_level";
+    public static final String FIRST_API_LEVEL = "ro.product.first_api_level";
 
     /** Returns whether the device build is the factory ROM */
     public static boolean isFactoryROM(ITestDevice device) throws DeviceNotAvailableException {
diff --git a/common/host-side/util/tests/Android.mk b/common/host-side/util/tests/Android.mk
index b5806c7..338d6c3 100644
--- a/common/host-side/util/tests/Android.mk
+++ b/common/host-side/util/tests/Android.mk
@@ -23,5 +23,5 @@
 LOCAL_MODULE := compatibility-host-util-tests
 
 LOCAL_MODULE_TAGS := optional
-
+include cts/error_prone_rules.mk
 include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/common/host-side/util/tests/src/com/android/compatibility/common/util/DynamicConfigHandlerTest.java b/common/host-side/util/tests/src/com/android/compatibility/common/util/DynamicConfigHandlerTest.java
index 31dd598..ef0e824 100644
--- a/common/host-side/util/tests/src/com/android/compatibility/common/util/DynamicConfigHandlerTest.java
+++ b/common/host-side/util/tests/src/com/android/compatibility/common/util/DynamicConfigHandlerTest.java
@@ -33,7 +33,7 @@
  */
 public class DynamicConfigHandlerTest extends TestCase {
 
-    private static final String localConfig =
+    private static final String LOCAL_CONFIG =
             "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
             "<dynamicConfig>\n" +
             "    <entry key=\"test-config-1\">\n" +
@@ -61,7 +61,7 @@
             "    </entry>\n" +
             "</dynamicConfig>\n";
 
-    private static final String overrideJson =
+    private static final String OVERRIDE_JSON =
             "{\n" +
             "  \"dynamicConfigEntries\": {\n" +
             "    \"override-config-1\": {\n" +
@@ -94,11 +94,11 @@
 
     public void testDynamicConfigHandler() throws Exception {
         String module = "test1";
-        File localConfigFile = createFileFromStr(localConfig, module);
+        File localConfigFile = createFileFromStr(LOCAL_CONFIG, module);
         File mergedFile = null;
         try {
             mergedFile = DynamicConfigHandler
-                    .getMergedDynamicConfigFile(localConfigFile, overrideJson, module);
+                    .getMergedDynamicConfigFile(localConfigFile, OVERRIDE_JSON, module);
 
             Map<String, List<String>> configMap = DynamicConfig.createConfigMap(mergedFile);
 
diff --git a/common/util/Android.mk b/common/util/Android.mk
index b6cf927..ae89d37 100644
--- a/common/util/Android.mk
+++ b/common/util/Android.mk
@@ -48,7 +48,7 @@
                                 junit-host \
                                 kxml2-2.3.0 \
                                 platform-test-annotations-host
-
+include cts/error_prone_rules.mk
 include $(BUILD_HOST_JAVA_LIBRARY)
 
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/common/util/src/com/android/compatibility/common/util/AbiUtils.java b/common/util/src/com/android/compatibility/common/util/AbiUtils.java
index 76c962c..c9c82b7 100644
--- a/common/util/src/com/android/compatibility/common/util/AbiUtils.java
+++ b/common/util/src/com/android/compatibility/common/util/AbiUtils.java
@@ -15,11 +15,6 @@
  */
 package com.android.compatibility.common.util;
 
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
 /**
  * Utility class for handling device ABIs
  */
diff --git a/common/util/src/com/android/compatibility/common/util/CaseResult.java b/common/util/src/com/android/compatibility/common/util/CaseResult.java
index 36f77d7..a7c3318 100644
--- a/common/util/src/com/android/compatibility/common/util/CaseResult.java
+++ b/common/util/src/com/android/compatibility/common/util/CaseResult.java
@@ -119,7 +119,7 @@
     public void mergeFrom(ICaseResult otherCaseResult) {
         if (!otherCaseResult.getName().equals(getName())) {
             throw new IllegalArgumentException(String.format(
-                "Cannot merge case result with mismatched name. Expected %s, Found %d",
+                "Cannot merge case result with mismatched name. Expected %s, Found %s",
                         otherCaseResult.getName(), getName()));
         }
 
diff --git a/common/util/src/com/android/compatibility/common/util/IModuleResult.java b/common/util/src/com/android/compatibility/common/util/IModuleResult.java
index 06d66c0..2ebf181 100644
--- a/common/util/src/com/android/compatibility/common/util/IModuleResult.java
+++ b/common/util/src/com/android/compatibility/common/util/IModuleResult.java
@@ -30,6 +30,8 @@
 
     void addRuntime(long elapsedTime);
 
+    void resetRuntime();
+
     long getRuntime();
 
     /**
diff --git a/common/util/src/com/android/compatibility/common/util/InfoStore.java b/common/util/src/com/android/compatibility/common/util/InfoStore.java
index b8014f7..c5a411e 100644
--- a/common/util/src/com/android/compatibility/common/util/InfoStore.java
+++ b/common/util/src/com/android/compatibility/common/util/InfoStore.java
@@ -15,7 +15,6 @@
  */
 package com.android.compatibility.common.util;
 
-import java.io.File;
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.List;
diff --git a/common/util/src/com/android/compatibility/common/util/MetricsXmlSerializer.java b/common/util/src/com/android/compatibility/common/util/MetricsXmlSerializer.java
index a7b1153..ce8696b 100644
--- a/common/util/src/com/android/compatibility/common/util/MetricsXmlSerializer.java
+++ b/common/util/src/com/android/compatibility/common/util/MetricsXmlSerializer.java
@@ -19,7 +19,6 @@
 import org.xmlpull.v1.XmlSerializer;
 
 import java.io.IOException;
-import java.util.List;
 
 //TODO(stuartscott): Delete file for v2, ReportLog can serialize itself.
 /**
diff --git a/common/util/src/com/android/compatibility/common/util/ModuleResult.java b/common/util/src/com/android/compatibility/common/util/ModuleResult.java
index 60038cf..60500a2 100644
--- a/common/util/src/com/android/compatibility/common/util/ModuleResult.java
+++ b/common/util/src/com/android/compatibility/common/util/ModuleResult.java
@@ -191,6 +191,14 @@
      * {@inheritDoc}
      */
     @Override
+    public void resetRuntime() {
+        mRuntime = 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
     public long getRuntime() {
         return mRuntime;
     }
diff --git a/common/util/src/com/android/compatibility/common/util/TestStatus.java b/common/util/src/com/android/compatibility/common/util/TestStatus.java
index 744f760..5a9b170 100644
--- a/common/util/src/com/android/compatibility/common/util/TestStatus.java
+++ b/common/util/src/com/android/compatibility/common/util/TestStatus.java
@@ -22,7 +22,7 @@
     PASS("pass"),
     FAIL("fail");
 
-    private String mValue;
+    private final String mValue;
 
     private TestStatus(String storedValue) {
         mValue = storedValue;
diff --git a/common/util/src/com/android/compatibility/common/util/TestSuiteFilter.java b/common/util/src/com/android/compatibility/common/util/TestSuiteFilter.java
index e498c17..d98bc6d 100644
--- a/common/util/src/com/android/compatibility/common/util/TestSuiteFilter.java
+++ b/common/util/src/com/android/compatibility/common/util/TestSuiteFilter.java
@@ -19,7 +19,6 @@
 import junit.framework.TestResult;
 import junit.framework.TestSuite;
 
-import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.List;
 import java.util.Set;
diff --git a/common/util/src/com/android/compatibility/common/util/ZipUtil.java b/common/util/src/com/android/compatibility/common/util/ZipUtil.java
index 6cee83a..b44fd46 100644
--- a/common/util/src/com/android/compatibility/common/util/ZipUtil.java
+++ b/common/util/src/com/android/compatibility/common/util/ZipUtil.java
@@ -27,7 +27,6 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
 import java.util.zip.ZipOutputStream;
 
 public class ZipUtil {
diff --git a/common/util/tests/Android.mk b/common/util/tests/Android.mk
index 5e3370b..1aca670 100644
--- a/common/util/tests/Android.mk
+++ b/common/util/tests/Android.mk
@@ -23,5 +23,5 @@
 LOCAL_MODULE := compatibility-common-util-tests
 
 LOCAL_MODULE_TAGS := optional
-
+include cts/error_prone_rules.mk
 include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/common/util/tests/src/com/android/compatibility/common/util/DynamicConfigTest.java b/common/util/tests/src/com/android/compatibility/common/util/DynamicConfigTest.java
index df50d11..99ef733 100644
--- a/common/util/tests/src/com/android/compatibility/common/util/DynamicConfigTest.java
+++ b/common/util/tests/src/com/android/compatibility/common/util/DynamicConfigTest.java
@@ -30,7 +30,7 @@
  * Unit tests for {@link DynamicConfig}
  */
 public class DynamicConfigTest extends TestCase {
-    private static final String correctConfig =
+    private static final String CORRECT_CONFIG =
             "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
             "<dynamicConfig>\n" +
             "    <entry key=\"test-config-1\">\n" +
@@ -55,7 +55,7 @@
             "    </entry>\n" +
             "</dynamicConfig>\n";
 
-    private static final String configWrongNodeName =
+    private static final String CONFIG_WRONG_NODE_NAME =
             "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
             "<dynamicCsonfig>\n" +  //The node name dynamicConfig is intentionally mistyped
             "    <entry key=\"test-config-1\">\n" +
@@ -82,7 +82,7 @@
 
     public void testCorrectConfig() throws Exception {
         DynamicConfig config = new DynamicConfig();
-        File file = createFileFromStr(correctConfig);
+        File file = createFileFromStr(CORRECT_CONFIG);
         try {
             config.initializeConfig(file);
             assertEquals("Wrong Config", config.getValue("test-config-1"), "test config 1");
@@ -97,7 +97,7 @@
 
     public void testConfigWithWrongNodeName() throws Exception {
         DynamicConfig config = new DynamicConfig();
-        File file = createFileFromStr(configWrongNodeName);
+        File file = createFileFromStr(CONFIG_WRONG_NODE_NAME);
         try {
             config.initializeConfig(file);
             fail("Cannot detect error when config file has wrong node name");
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 49c4045..932db8e 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
@@ -224,7 +224,7 @@
             writer = new FileWriter(resultFile);
             String buildInfo = String.format(XML_BUILD_INFO, DEVICE_A,
                     EXAMPLE_BUILD_ID, EXAMPLE_BUILD_PRODUCT);
-            String summary = String.format(XML_SUMMARY, 2, 1, 1);
+            String summary = String.format(XML_SUMMARY, 2, 1);
             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,
diff --git a/error_prone_rules.mk b/error_prone_rules.mk
new file mode 100644
index 0000000..c2b0c79
--- /dev/null
+++ b/error_prone_rules.mk
@@ -0,0 +1,30 @@
+# 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.
+
+# Set of error prone rules to ensure code quality
+LOCAL_ERROR_PRONE_FLAGS:= -Xep:ArrayToString:ERROR \
+                          -Xep:BoxedPrimitiveConstructor:ERROR \
+                          -Xep:ConstantField:ERROR \
+                          -Xep:FormatString:ERROR \
+                          -Xep:GetClassOnClass:ERROR \
+                          -Xep:JUnitAmbiguousTestClass:ERROR \
+                          -Xep:MissingFail:ERROR \
+                          -Xep:MissingOverride:ERROR \
+                          -Xep:Overrides:ERROR \
+                          -Xep:ReferenceEquality:ERROR \
+                          -Xep:RemoveUnusedImports:ERROR \
+                          -Xep:ReturnValueIgnored:ERROR \
+                          -Xep:SelfEquals:ERROR \
+                          -Xep:SizeGreaterThanOrEqualsZero:ERROR
+
diff --git a/error_prone_rules_tests.mk b/error_prone_rules_tests.mk
new file mode 100644
index 0000000..cec29b7
--- /dev/null
+++ b/error_prone_rules_tests.mk
@@ -0,0 +1,20 @@
+# 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.
+
+# Set of error prone rules to ensure code quality of tests
+
+# Goal is to eventually merge with error_prone_rules.mk
+LOCAL_ERROR_PRONE_FLAGS:= -Xep:JUnit3TestNotRun:ERROR \
+                          -Xep:TryFailThrowable:ERROR
+
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
index 16e2765..78b03e4 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
@@ -269,10 +269,14 @@
             // Kick through a remount cycle, which should purge the adopted app
             getDevice().executeShellCommand("sm mount " + vol.volId);
             runDeviceTests(PKG, CLASS, "testDataInternal");
+            boolean didThrow = false;
             try {
                 runDeviceTests(PKG, CLASS, "testDataRead");
-                fail("Unexpected data from adopted volume picked up");
             } catch (AssertionError expected) {
+                didThrow = true;
+            }
+            if (!didThrow) {
+                fail("Unexpected data from adopted volume picked up");
             }
             getDevice().executeShellCommand("sm unmount " + vol.volId);
 
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
index 3a282bf..6a6c27d 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
@@ -47,8 +47,13 @@
     private static final String MODE_EMULATED = "emulated";
     private static final String MODE_NONE = "none";
 
+    private static final String FEATURE_DEVICE_ADMIN = "feature:android.software.device_admin\n";
+    private static final String FEATURE_AUTOMOTIVE = "feature:android.hardware.type.automotive\n";
+
     private static final long SHUTDOWN_TIME_MS = 30 * 1000;
 
+    private String mFeatureList = null;
+
     private IAbi mAbi;
     private IBuildInfo mCtsBuild;
 
@@ -82,6 +87,22 @@
     }
 
     /**
+     * Automotive devices MUST support native FBE.
+     */
+    public void testAutomotiveNativeFbe() throws Exception {
+        if (!isSupportedDevice()) {
+            Log.v(TAG, "Device not supported; skipping test");
+            return;
+        } else if (!isAutomotiveDevice()) {
+            Log.v(TAG, "Device not automotive; skipping test");
+            return;
+        }
+
+        assertTrue("Automotive devices must support native FBE",
+            MODE_NATIVE.equals(getFbeMode()));
+    }
+
+    /**
      * If device has native FBE, verify lifecycle.
      */
     public void testDirectBootNative() throws Exception {
@@ -227,9 +248,20 @@
         return "1".equals(output);
     }
 
+    private boolean hasSystemFeature(final String feature) throws Exception {
+        if (mFeatureList == null) {
+            mFeatureList = getDevice().executeShellCommand("pm list features");
+        }
+
+        return mFeatureList.contains(feature);
+    }
+
     private boolean isSupportedDevice() throws Exception {
-        final String featureList = getDevice().executeShellCommand("pm list features");
-        return featureList.contains("feature:android.software.device_admin\n");
+        return hasSystemFeature(FEATURE_DEVICE_ADMIN);
+    }
+
+    private boolean isAutomotiveDevice() throws Exception {
+        return hasSystemFeature(FEATURE_AUTOMOTIVE);
     }
 
     private void waitForBootCompleted() throws Exception {
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
index 77513c5..7de83d6 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
@@ -110,12 +110,9 @@
         runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartEphemeral");
     }
 
-    /*
-     * Disabled pending drops of updated prebuilts
     public void testExposedSystemActivities() throws Exception {
         runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testExposedSystemActivities");
     }
-    */
 
     public void testBuildSerialUnknown() throws Exception {
         runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testBuildSerialUnknown");
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java
index b7f7f88..79f838c 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java
@@ -76,22 +76,30 @@
     public void testFail() throws Exception {
         // Sanity check that remote failure is host failure
         assertNull(getDevice().installPackage(mBuildHelper.getTestFile(APK_23), false, false));
+        boolean didThrow = false;
         try {
             runDeviceTests(USES_PERMISSION_PKG, "com.android.cts.usepermission.UsePermissionTest23",
                     "testFail");
-            fail("Expected remote failure");
         } catch (AssertionError expected) {
+            didThrow = true;
+        }
+        if (!didThrow) {
+            fail("Expected remote failure");
         }
     }
 
     public void testKill() throws Exception {
         // Sanity check that remote kill is host failure
         assertNull(getDevice().installPackage(mBuildHelper.getTestFile(APK_23), false, false));
+        boolean didThrow = false;
         try {
             runDeviceTests(USES_PERMISSION_PKG, "com.android.cts.usepermission.UsePermissionTest23",
                     "testKill");
-            fail("Expected remote failure");
         } catch (AssertionError expected) {
+            didThrow = true;
+        }
+        if (!didThrow) {
+            fail("Expected remote failure");
         }
     }
 
@@ -103,11 +111,15 @@
 
     public void testCompatRevoked22() throws Exception {
         assertNull(getDevice().installPackage(mBuildHelper.getTestFile(APK_22), false, false));
+        boolean didThrow = false;
         try {
             runDeviceTests(USES_PERMISSION_PKG, "com.android.cts.usepermission.UsePermissionTest22",
                     "testCompatRevoked_part1");
-            fail("App must be killed on a permission revoke");
         } catch (AssertionError expected) {
+            didThrow = true;
+        }
+        if (!didThrow) {
+            fail("App must be killed on a permission revoke");
         }
         runDeviceTests(USES_PERMISSION_PKG, "com.android.cts.usepermission.UsePermissionTest22",
                 "testCompatRevoked_part2");
@@ -169,10 +181,15 @@
 
     public void testRevokeAffectsWholeGroup23() throws Exception {
         assertNull(getDevice().installPackage(mBuildHelper.getTestFile(APK_23), false, false));
+        boolean didThrow = false;
         try {
             runDeviceTests(USES_PERMISSION_PKG, "com.android.cts.usepermission.UsePermissionTest23",
                     "testRevokeAffectsWholeGroup_part1");
         } catch (AssertionError expected) {
+            didThrow = true;
+        }
+        if (!didThrow) {
+            fail("Should have thrown an exception.");
         }
         runDeviceTests(USES_PERMISSION_PKG, "com.android.cts.usepermission.UsePermissionTest23",
                 "testRevokeAffectsWholeGroup_part2");
@@ -180,11 +197,15 @@
 
     public void testGrantPreviouslyRevokedWithPrejudiceShowsPrompt23() throws Exception {
         assertNull(getDevice().installPackage(mBuildHelper.getTestFile(APK_23), false, false));
+        boolean didThrow = false;
         try {
             runDeviceTests(USES_PERMISSION_PKG, "com.android.cts.usepermission.UsePermissionTest23",
                     "testGrantPreviouslyRevokedWithPrejudiceShowsPrompt_part1");
-            fail("App must be killed on a permission revoke");
         } catch (Throwable expected) {
+            didThrow = true;
+        }
+        if (!didThrow) {
+            fail("App must be killed on a permission revoke");
         }
         runDeviceTests(USES_PERMISSION_PKG, "com.android.cts.usepermission.UsePermissionTest23",
                 "testGrantPreviouslyRevokedWithPrejudiceShowsPrompt_part2");
@@ -225,10 +246,14 @@
 
     public void testNoDowngradePermissionModel() throws Exception {
         assertNull(getDevice().installPackage(mBuildHelper.getTestFile(APK_23), false, false));
+        boolean didThrow = false;
         try {
             assertNull(getDevice().installPackage(mBuildHelper.getTestFile(APK_22), true, false));
-            fail("Permission mode downgrade not allowed");
         } catch (AssertionError expected) {
+            didThrow = true;
+        }
+        if (!didThrow) {
+            fail("Permission mode downgrade not allowed");
         }
     }
 
@@ -244,11 +269,15 @@
 
     public void testRevokePropagatedOnUpgradeOldToNewModel() throws Exception {
         assertNull(getDevice().installPackage(mBuildHelper.getTestFile(APK_22), false, false));
+        boolean didThrow = false;
         try {
             runDeviceTests(USES_PERMISSION_PKG, "com.android.cts.usepermission.UsePermissionTest22",
                     "testRevokePropagatedOnUpgradeOldToNewModel_part1");
-            fail("App must be killed on a permission revoke");
         } catch (AssertionError expected) {
+            didThrow = true;
+        }
+        if (!didThrow) {
+            fail("App must be killed on a permission revoke");
         }
         assertNull(getDevice().installPackage(mBuildHelper.getTestFile(APK_23), true, false));
         runDeviceTests(USES_PERMISSION_PKG, "com.android.cts.usepermission.UsePermissionTest23",
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
index 21afece..fa8730d 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
@@ -97,9 +97,6 @@
                 ContactsContract.CommonDataKinds.Email.CONTENT_TYPE, null),
         makeIntent(Intent.ACTION_PICK, null,
                 ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_TYPE, null),
-        makeIntent(Intent.ACTION_INSERT, null, ContactsContract.Contacts.CONTENT_TYPE, null),
-        // Email
-        makeIntent(Intent.ACTION_SEND, null, "text/plain", Uri.parse("mailto:")),
         // File Storage
         makeIntent(Intent.ACTION_OPEN_DOCUMENT, Intent.CATEGORY_OPENABLE, "*/*", null),
         makeIntent(Intent.ACTION_OPEN_DOCUMENT, null, "*/*", null),
@@ -108,13 +105,8 @@
         makeIntent(Intent.ACTION_OPEN_DOCUMENT_TREE, null, null, null),
         makeIntent(Intent.ACTION_CREATE_DOCUMENT, Intent.CATEGORY_OPENABLE, "text/plain", null),
         makeIntent(Intent.ACTION_CREATE_DOCUMENT, null, "text/plain", null),
-        // Phone call
-        makeIntent(Intent.ACTION_DIAL, null, null, Uri.parse("tel:")),
-        // SMS
-        makeIntent(Intent.ACTION_SEND, null, "text/plain", Uri.parse("sms:")),
-        makeIntent(Intent.ACTION_SEND, null, "text/plain", Uri.parse("smsto:")),
-        // Web
-        makeIntent(Intent.ACTION_VIEW, null, "text/html", Uri.parse("https://example.com")),
+        // Framework
+        makeIntent(Intent.ACTION_CHOOSER, null, null, null),
     };
 
     private BroadcastReceiver mReceiver;
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDeviceAdminServiceTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDeviceAdminServiceTest.java
index b8cc99d..f0b8279 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDeviceAdminServiceTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDeviceAdminServiceTest.java
@@ -105,68 +105,91 @@
         }
 
         // Install
+        CLog.i("Installing apk1...");
         installAppAsUser(OWNER_APK_1, getUserId());
+
+        CLog.i("Making it a device/profile owner...");
         setAsOwnerOrFail(OWNER_COMPONENT);
 
         withRetry(() -> assertServiceBound(OWNER_SERVICE));
 
         // Remove admin.
+        CLog.i("Removing admin...");
         removeAdmin(OWNER_COMPONENT, getUserId());
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE));
 
         // Overwrite -> update.
+        CLog.i("Re-installing apk1...");
         installAppAsUser(OWNER_APK_1, getUserId());
+
+        CLog.i("Making it a device/profile owner...");
         setAsOwnerOrFail(OWNER_COMPONENT);
         withRetry(() -> assertServiceBound(OWNER_SERVICE));
 
+        CLog.i("Installing apk2...");
         installAppAsUser(OWNER_APK_2, getUserId());
         withRetry(() -> assertServiceBound(OWNER_SERVICE)); // Should still be bound.
 
         // Service exported -> not bound.
+        CLog.i("Installing apk3...");
         installAppAsUser(OWNER_APK_3, getUserId());
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE));
 
         // Recover.
+        CLog.i("Installing apk2 again...");
         installAppAsUser(OWNER_APK_2, getUserId());
         withRetry(() -> assertServiceBound(OWNER_SERVICE));
 
         // Multiple service found -> not bound.
+        CLog.i("Installing apk4...");
         installAppAsUser(OWNER_APK_4, getUserId());
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE));
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE2));
 
         // Disable service1 -> now there's only one service, so should be bound.
+        CLog.i("Running testDisableService1...");
         executeDeviceTestMethod(".ComponentController", "testDisableService1");
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE));
         withRetry(() -> assertServiceBound(OWNER_SERVICE2));
 
+        CLog.i("Running testDisableService2...");
         executeDeviceTestMethod(".ComponentController", "testDisableService2");
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE));
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE2));
 
+        CLog.i("Running testEnableService1...");
         executeDeviceTestMethod(".ComponentController", "testEnableService1");
         withRetry(() -> assertServiceBound(OWNER_SERVICE));
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE2));
 
+        CLog.i("Running testEnableService2...");
         executeDeviceTestMethod(".ComponentController", "testEnableService2");
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE));
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE2));
 
         // Remove admin.
+        CLog.i("Removing admin again...");
         removeAdmin(OWNER_COMPONENT, getUserId());
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE));
 
         // Retry with package 1 and remove admin.
+        CLog.i("Installing apk1 again...");
         installAppAsUser(OWNER_APK_1, getUserId());
+
+        CLog.i("Making it a device/profile owner again...");
         setAsOwnerOrFail(OWNER_COMPONENT);
         withRetry(() -> assertServiceBound(OWNER_SERVICE));
 
+        CLog.i("Removing admin again...");
         removeAdmin(OWNER_COMPONENT, getUserId());
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE));
 
         // Now install package B and make it the owner.  OWNER_APK_1 still exists, but it shouldn't
         // interfere.
+        CLog.i("Installing apk B...");
         installAppAsUser(OWNER_APK_B, getUserId());
+
+        CLog.i("Making it a device/profile owner...");
         setAsOwnerOrFail(OWNER_COMPONENT_B);
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE));
         withRetry(() -> assertServiceBound(OWNER_SERVICE_B));
diff --git a/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java b/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java
index fd3e85d..8ba3064 100644
--- a/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java
+++ b/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java
@@ -387,7 +387,7 @@
     }
 
     private void checkBattery(String[] parts) {
-        assertEquals(13, parts.length);
+        assertEquals(15, parts.length);
         if (!parts[4].equals("N/A")) {
             assertInteger(parts[4]);  // startCount
         }
@@ -399,6 +399,9 @@
         long bOffReal = assertInteger(parts[10]); // batteryScreenOffRealtime
         long bOffUp = assertInteger(parts[11]); // batteryScreenOffUptime
         long bEstCap = assertInteger(parts[12]); // batteryEstimatedCapacity
+        assertInteger(parts[13]); // minLearnedBatteryCapacity
+        assertInteger(parts[14]); // maxLearnedBatteryCapacity
+
         // The device cannot be up more than there are real-world seconds.
         assertTrue("batteryRealtime must be >= batteryUptime", bReal >= bUp);
         assertTrue("totalRealtime must be >= totalUptime", tReal >= tUp);
diff --git a/hostsidetests/edi/Android.mk b/hostsidetests/edi/Android.mk
new file mode 100644
index 0000000..efa093f
--- /dev/null
+++ b/hostsidetests/edi/Android.mk
@@ -0,0 +1,32 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_MODULE_TAGS := tests
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_MODULE := CtsEdiHostTestCases
+
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed compatibility-host-util
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/hostsidetests/edi/AndroidTest.xml b/hostsidetests/edi/AndroidTest.xml
new file mode 100644
index 0000000..94be6b6
--- /dev/null
+++ b/hostsidetests/edi/AndroidTest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for CTS EDI host test cases">
+    <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+        <option name="jar" value="CtsEdiHostTestCases.jar" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/hostsidetests/edi/src/android/edi/cts/LibraryDeviceInfo.java b/hostsidetests/edi/src/android/edi/cts/LibraryDeviceInfo.java
new file mode 100644
index 0000000..b9f83f4
--- /dev/null
+++ b/hostsidetests/edi/src/android/edi/cts/LibraryDeviceInfo.java
@@ -0,0 +1,88 @@
+/*
+ * 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.edi.cts;
+
+import com.android.compatibility.common.util.DeviceInfo;
+import com.android.compatibility.common.util.HostInfoStore;
+import com.android.ddmlib.FileListingService.FileEntry;
+import com.android.tradefed.device.IFileEntry;
+import com.android.tradefed.device.ITestDevice;
+
+import java.util.Arrays;
+
+public class LibraryDeviceInfo extends DeviceInfo {
+
+    private ITestDevice mDevice;
+
+    @Override
+    protected void collectDeviceInfo(HostInfoStore store) throws Exception {
+
+        mDevice = getDevice();
+
+        collectSystemLibs(store);
+        collectVendorLibs(store);
+        collectFrameworkJars(store);
+    }
+
+    private void collectSystemLibs(HostInfoStore store) throws Exception {
+        store.startArray("lib");
+        collectFileDetails(store, "/system/lib", ".so");
+        store.endArray();
+    }
+
+    private void collectVendorLibs(HostInfoStore store) throws Exception {
+        store.startArray("vendor_lib");
+        collectFileDetails(store, "/system/vendor/lib", ".so");
+        store.endArray();
+    }
+
+    private void collectFrameworkJars(HostInfoStore store) throws Exception {
+        store.startArray("framework_jar");
+        collectFileDetails(store, "/system/framework", ".jar");
+        store.endArray();
+    }
+
+    private void collectFileDetails(HostInfoStore store, String path, String suffix)
+            throws Exception {
+        IFileEntry dir = mDevice.getFileEntry(path);
+
+        if(dir == null || !dir.isDirectory()) {
+            return;
+        }
+
+        for (IFileEntry file : dir.getChildren(false)) {
+            String name = file.getName();
+            if (!file.isDirectory() && name.endsWith(suffix)) {
+                String sha1 = getSha1(file.getFullPath());
+                store.startGroup();
+                store.addResult("name", name);
+                store.addResult("sha1", sha1);
+                store.endGroup();
+            }
+        }
+    }
+
+    private String getSha1(String filePath) {
+        String sha1 = "unknown";
+        try {
+            String out = mDevice.executeShellCommand("sha1sum " + filePath);
+            sha1 = out.split(" ", 2)[0].toUpperCase();
+        } catch (Exception e) {
+            // Do nothing.
+        }
+        return sha1;
+    }
+}
\ No newline at end of file
diff --git a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBackgroundService.java b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBackgroundService.java
index 496e61a..bc28c07 100644
--- a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBackgroundService.java
+++ b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBackgroundService.java
@@ -17,6 +17,7 @@
 package com.android.server.cts.device.batterystats;
 
 import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions.KEY_ACTION;
+import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions.KEY_REQUEST_CODE;
 import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions.doAction;
 import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions.isAppInBackground;
 
@@ -45,7 +46,9 @@
             Log.w(TAG, "Couldn't determine if app is in background. Proceeding with test anyway.");
         }
 
-        Log.i(TAG, "Starting action from background service");
-        doAction(this, intent.getStringExtra(KEY_ACTION));
+        String action = intent.getStringExtra(KEY_ACTION);
+        String requestCode = intent.getStringExtra(KEY_REQUEST_CODE);
+        Log.i(TAG, "Starting " + action + " from background service as request " + requestCode);
+        doAction(this, action, requestCode);
     }
 }
diff --git a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBgVsFgActions.java b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBgVsFgActions.java
index 480ca2f..3c9abda 100644
--- a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBgVsFgActions.java
+++ b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBgVsFgActions.java
@@ -55,9 +55,10 @@
     public static final String ACTION_WIFI_DOWNLOAD = "action.wifi_download";
     public static final String ACTION_WIFI_UPLOAD = "action.wifi_upload";
 
+    public static final String KEY_REQUEST_CODE = "request_code";
 
     /** Perform the action specified by the given action code (see constants above). */
-    public static void doAction(Context ctx, String actionCode) {
+    public static void doAction(Context ctx, String actionCode, String requestCode) {
         if (actionCode == null) {
             Log.e(TAG, "Intent was missing action.");
             return;
@@ -65,22 +66,22 @@
         sleep(100);
         switch(actionCode) {
             case ACTION_BLE_SCAN:
-                doBleScan(ctx);
+                doBleScan(ctx, requestCode);
                 break;
             case ACTION_JOB_SCHEDULE:
-                doScheduleJob(ctx);
+                doScheduleJob(ctx, requestCode);
                 break;
             case ACTION_SYNC:
-                doSync(ctx);
+                doSync(ctx, requestCode);
                 break;
             case ACTION_WIFI_SCAN:
-                doWifiScan(ctx);
+                doWifiScan(ctx, requestCode);
                 break;
             case ACTION_WIFI_DOWNLOAD:
-                doWifiDownload(ctx);
+                doWifiDownload(ctx, requestCode);
                 break;
             case ACTION_WIFI_UPLOAD:
-                doWifiUpload(ctx);
+                doWifiUpload(ctx, requestCode);
                 break;
             default:
                 Log.e(TAG, "Intent had invalid action");
@@ -88,7 +89,7 @@
         sleep(100);
     }
 
-    private static void doBleScan(Context ctx) {
+    private static void doBleScan(Context ctx, String requestCode) {
         BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
         if (bluetoothAdapter == null) {
             Log.e(TAG, "Device does not support Bluetooth");
@@ -128,9 +129,10 @@
         bleScanner.startScan(null, scanSettings, scanCallback);
         sleep(2_000);
         bleScanner.stopScan(scanCallback);
+        tellHostActionFinished(ACTION_BLE_SCAN, requestCode);
     }
 
-    private static void doScheduleJob(Context ctx) {
+    private static void doScheduleJob(Context ctx, String requestCode) {
         final ComponentName JOB_COMPONENT_NAME =
                 new ComponentName("com.android.server.cts.device.batterystats",
                         SimpleJobService.class.getName());
@@ -148,13 +150,14 @@
         new AsyncTask<Void, Void, Void>() {
             @Override
             protected Void doInBackground(Void... params) {
-                waitForReceiver(null, 3_000, latch, null);
+                waitForReceiver(null, 60_000, latch, null);
+                tellHostActionFinished(ACTION_JOB_SCHEDULE, requestCode);
                 return null;
             }
         }.execute();
     }
 
-    private static void doSync(Context ctx) {
+    private static void doSync(Context ctx, String requestCode) {
         BatteryStatsAuthenticator.removeAllAccounts(ctx);
         final Account account = BatteryStatsAuthenticator.getTestAccount();
         // Create the test account.
@@ -185,36 +188,50 @@
                 if(ctx instanceof Activity){
                     ((Activity) ctx).finish();
                 }
+                tellHostActionFinished(ACTION_SYNC, requestCode);
             }
         }.execute();
     }
 
-    private static void doWifiScan(Context ctx) {
+    private static void doWifiScan(Context ctx, String requestCode) {
         IntentFilter intentFilter = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
         CountDownLatch onReceiveLatch = new CountDownLatch(1);
         BroadcastReceiver receiver = registerReceiver(ctx, onReceiveLatch, intentFilter);
         ctx.getSystemService(WifiManager.class).startScan();
-        waitForReceiver(ctx, 3_000, onReceiveLatch, receiver);
+        waitForReceiver(ctx, 60_000, onReceiveLatch, receiver);
+        tellHostActionFinished(ACTION_WIFI_SCAN, requestCode);
     }
 
-    private static void doWifiDownload(Context ctx) {
+    private static void doWifiDownload(Context ctx, String requestCode) {
+        CountDownLatch latch = new CountDownLatch(1);
+
         new AsyncTask<Void, Void, Void>() {
             @Override
             protected Void doInBackground(Void... params) {
-                BatteryStatsWifiTransferTests.download();
+                BatteryStatsWifiTransferTests.download(requestCode);
+                latch.countDown();
                 return null;
             }
         }.execute();
+
+        waitForReceiver(null, 60_000, latch, null);
+        tellHostActionFinished(ACTION_WIFI_DOWNLOAD, requestCode);
     }
 
-    private static void doWifiUpload(Context ctx) {
+    private static void doWifiUpload(Context ctx, String requestCode) {
+        CountDownLatch latch = new CountDownLatch(1);
+
         new AsyncTask<Void, Void, Void>() {
             @Override
             protected Void doInBackground(Void... params) {
                 BatteryStatsWifiTransferTests.upload();
+                latch.countDown();
                 return null;
             }
         }.execute();
+
+        waitForReceiver(null, 60_000, latch, null);
+        tellHostActionFinished(ACTION_WIFI_UPLOAD, requestCode);
     }
 
     /** Register receiver to determine when given action is complete. */
@@ -258,6 +275,12 @@
         }
     }
 
+    /** Communicates to hostside (via logcat) that action has completed (regardless of success). */
+    private static void tellHostActionFinished(String actionCode, String requestCode) {
+        String s = String.format("Completed performing %s for request %s", actionCode, requestCode);
+        Log.i(TAG, s);
+    }
+
     /** Determines whether the package is running as a background process. */
     public static boolean isAppInBackground(Context context) throws ReflectiveOperationException {
         String pkgName = context.getPackageName();
diff --git a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsForegroundActivity.java b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsForegroundActivity.java
index c41b244..fab306d 100644
--- a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsForegroundActivity.java
+++ b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsForegroundActivity.java
@@ -16,10 +16,9 @@
 
 package com.android.server.cts.device.batterystats;
 
-import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions
-        .ACTION_JOB_SCHEDULE;
 import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions.ACTION_SYNC;
 import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions.KEY_ACTION;
+import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions.KEY_REQUEST_CODE;
 import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions.doAction;
 import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions.isAppInBackground;
 
@@ -53,7 +52,9 @@
         }
 
         String action = intent.getStringExtra(KEY_ACTION);
-        doAction(this, action);
+        String requestCode = intent.getStringExtra(KEY_REQUEST_CODE);
+        Log.i(TAG, "Starting " + action + " from foreground activity as request " + requestCode);
+        doAction(this, action, requestCode);
 
         // ACTION_SYNC will finish itself. Others get finished here.
         if (!ACTION_SYNC.equals(action)) {
diff --git a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsWifiTransferTests.java b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsWifiTransferTests.java
index 1633301..aa5c018 100644
--- a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsWifiTransferTests.java
+++ b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsWifiTransferTests.java
@@ -15,35 +15,14 @@
  */
 package com.android.server.cts.device.batterystats;
 
-import static org.junit.Assert.assertTrue;
-
-import android.app.IntentService;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.Log;
 
 import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.OutputStream;
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.util.Arrays;
-import java.util.Random;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
 
 public class BatteryStatsWifiTransferTests {
     private static final String TAG = "BatteryStatsWifiTransferTests";
@@ -53,7 +32,7 @@
     /** Server to send requests to. */
     private static final String SERVER_URL = "https://developer.android.com/index.html";
 
-    public static String download() {
+    public static String download(String requestCode) {
         HttpURLConnection conn = null;
         try {
             URL url = new URL(SERVER_URL);
@@ -69,7 +48,7 @@
             while ((count = in.read(data)) != -1) {
                 total += count;
             }
-            Log.i(TAG, Integer.toString(total));
+            Log.i(TAG, String.format("request %s d=%d", requestCode, total));
         } catch (IOException e) {
             Log.i(TAG, e.toString());
             return "Caught exception";
diff --git a/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java b/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java
index 758c443..ebe1996 100644
--- a/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java
@@ -15,8 +15,15 @@
  */
 package com.android.server.cts;
 
+import com.android.ddmlib.IShellOutputReceiver;
 import com.android.tradefed.log.LogUtil;
 
+import com.google.common.base.Charsets;
+
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
 /**
  * Test for "dumpsys batterystats -c
  *
@@ -52,6 +59,9 @@
     public static final String ACTION_WIFI_DOWNLOAD = "action.wifi_download";
     public static final String ACTION_WIFI_UPLOAD = "action.wifi_upload";
 
+    public static final String KEY_REQUEST_CODE = "request_code";
+    public static final String BG_VS_FG_TAG = "BatteryStatsBgVsFgActions";
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -130,14 +140,12 @@
         installPackage(DEVICE_SIDE_TEST_APK, true);
 
         // Foreground test.
-        executeForeground(ACTION_BLE_SCAN);
-        Thread.sleep(2_500);
+        executeForeground(ACTION_BLE_SCAN, 30_000);
         assertValueRange("blem", "", 5, 1, 1); // ble_scan_count
         assertValueRange("blem", "", 6, 0, 0); // ble_scan_count_bg
 
         // Background test.
-        executeBackground(ACTION_BLE_SCAN);
-        Thread.sleep(2_500);
+        executeBackground(ACTION_BLE_SCAN, 30_000);
         assertValueRange("blem", "", 5, 2, 2); // ble_scan_count
         assertValueRange("blem", "", 6, 1, 1); // ble_scan_count_bg
 
@@ -149,14 +157,12 @@
         installPackage(DEVICE_SIDE_TEST_APK, true);
 
         // Foreground test.
-        executeForeground(ACTION_JOB_SCHEDULE);
-        Thread.sleep(4_000);
+        executeForeground(ACTION_JOB_SCHEDULE, 60_000);
         assertValueRange("jb", "", 6, 1, 1); // count
         assertValueRange("jb", "", 8, 0, 0); // background_count
 
         // Background test.
-        executeBackground(ACTION_JOB_SCHEDULE);
-        Thread.sleep(4_000);
+        executeBackground(ACTION_JOB_SCHEDULE, 60_000);
         assertValueRange("jb", "", 6, 2, 2); // count
         assertValueRange("jb", "", 8, 1, 1); // background_count
 
@@ -168,15 +174,13 @@
         installPackage(DEVICE_SIDE_TEST_APK, true);
 
         // Foreground test.
-        executeForeground(ACTION_SYNC);
-        Thread.sleep(3_000);
+        executeForeground(ACTION_SYNC, 60_000);
         // Allow one or two syncs in this time frame (not just one) due to unpredictable syncs.
         assertValueRange("sy", DEVICE_SIDE_SYNC_COMPONENT, 6, 1, 2); // count
         assertValueRange("sy", DEVICE_SIDE_SYNC_COMPONENT, 8, 0, 0); // background_count
 
         // Background test.
-        executeBackground(ACTION_SYNC);
-        Thread.sleep(3_000);
+        executeBackground(ACTION_SYNC, 60_000);
         assertValueRange("sy", DEVICE_SIDE_SYNC_COMPONENT, 6, 2, 4); // count
         assertValueRange("sy", DEVICE_SIDE_SYNC_COMPONENT, 8, 1, 2); // background_count
 
@@ -188,14 +192,12 @@
         installPackage(DEVICE_SIDE_TEST_APK, true);
 
         // Foreground count test.
-        executeForeground(ACTION_WIFI_SCAN);
-        Thread.sleep(4_000);
+        executeForeground(ACTION_WIFI_SCAN, 60_000);
         assertValueRange("wfl", "", 7, 1, 1); // scan_count
         assertValueRange("wfl", "", 11, 0, 0); // scan_count_bg
 
         // Background count test.
-        executeBackground(ACTION_WIFI_SCAN);
-        Thread.sleep(6_000);
+        executeBackground(ACTION_WIFI_SCAN, 60_000);
         assertValueRange("wfl", "", 7, 2, 2); // scan_count
         assertValueRange("wfl", "", 11, 1, 1); // scan_count_bg
 
@@ -275,8 +277,8 @@
 
         long prevBytes = getLongValue(getUid(), "nt", "", 6);
 
-        executeForeground(ACTION_WIFI_DOWNLOAD);
-        long downloadedBytes = getDownloadedBytes();
+        String requestCode = executeForeground(ACTION_WIFI_DOWNLOAD, 60_000);
+        long downloadedBytes = getDownloadedBytes(requestCode);
         assertTrue(downloadedBytes > 0);
         long min = prevBytes + downloadedBytes + MIN_HTTP_HEADER_BYTES;
         long max = prevBytes + downloadedBytes + FUZZ; // Add some fuzzing.
@@ -285,9 +287,8 @@
 
         // Do the background download
         long prevBgBytes = getLongValue(getUid(), "nt", "", 20);
-        executeBackground(ACTION_WIFI_DOWNLOAD);
-        Thread.sleep(4000);
-        downloadedBytes = getDownloadedBytes();
+        requestCode = executeBackground(ACTION_WIFI_DOWNLOAD, 60_000);
+        downloadedBytes = getDownloadedBytes(requestCode);
 
         long minBg = prevBgBytes + downloadedBytes + MIN_HTTP_HEADER_BYTES;
         long maxBg = prevBgBytes + downloadedBytes + FUZZ;
@@ -310,14 +311,12 @@
         batteryOnScreenOff();
         installPackage(DEVICE_SIDE_TEST_APK, true);
 
-        executeForeground(ACTION_WIFI_UPLOAD);
-        Thread.sleep(2000);
+        executeForeground(ACTION_WIFI_UPLOAD, 60_000);
         int min = MIN_HTTP_HEADER_BYTES + (2 * 1024);
         int max = min + (6 * 1024); // Add some fuzzing.
         assertValueRange("nt", "", 7, min, max); // wifi_bytes_tx
 
-        executeBackground(ACTION_WIFI_UPLOAD);
-        Thread.sleep(4000);
+        executeBackground(ACTION_WIFI_UPLOAD, 60_000);
         assertValueRange("nt", "", 21, min * 2, max * 2); // wifi_bytes_bg_tx
 
         batteryOffScreenOn();
@@ -371,15 +370,39 @@
     }
 
     /**
+     * Runs a (background) service to perform the given action, and waits for
+     * the device to report that the action has finished (via a logcat message) before returning.
+     * @param actionValue one of the constants in BatteryStatsBgVsFgActions indicating the desired
+     *                    action to perform.
+     * @param maxTimeMs max time to wait (in ms) for action to report that it has completed.
+     * @return A string, representing a random integer, assigned to this particular request for the
+     *                     device to perform the given action. This value can be used to receive
+     *                     communications via logcat from the device about this action.
+     */
+    private String executeBackground(String actionValue, int maxTimeMs) throws Exception {
+        String requestCode = executeBackground(actionValue);
+        String searchString = getCompletedActionString(actionValue, requestCode);
+        checkLogcatForText(BG_VS_FG_TAG, searchString, maxTimeMs);
+        return requestCode;
+    }
+
+    /**
      * Runs a (background) service to perform the given action.
      * @param actionValue one of the constants in BatteryStatsBgVsFgActions indicating the desired
      *                    action to perform.
+     * @return A string, representing a random integer, assigned to this particular request for the
+      *                     device to perform the given action. This value can be used to receive
+      *                     communications via logcat from the device about this action.
      */
-    private void executeBackground(String actionValue) throws Exception {
+    private String executeBackground(String actionValue) throws Exception {
         allowBackgroundServices();
+        String requestCode = Integer.toString(new Random().nextInt());
         getDevice().executeShellCommand(String.format(
-                "am startservice -n '%s' -e %s %s",
-                DEVICE_SIDE_BG_SERVICE_COMPONENT, KEY_ACTION, actionValue));
+                "am startservice -n '%s' -e %s %s -e %s %s",
+                DEVICE_SIDE_BG_SERVICE_COMPONENT,
+                KEY_ACTION, actionValue,
+                KEY_REQUEST_CODE, requestCode));
+        return requestCode;
     }
 
     /** Required to successfully start a background service from adb in O. */
@@ -389,26 +412,119 @@
     }
 
     /**
+     * Runs an activity (in the foreground) to perform the given action, and waits
+     * for the device to report that the action has finished (via a logcat message) before returning.
+     * @param actionValue one of the constants in BatteryStatsBgVsFgActions indicating the desired
+     *                    action to perform.
+     * @param maxTimeMs max time to wait (in ms) for action to report that it has completed.
+     * @return A string, representing a random integer, assigned to this particular request for the
+     *                     device to perform the given action. This value can be used to receive
+     *                     communications via logcat from the device about this action.
+     */
+    private String executeForeground(String actionValue, int maxTimeMs) throws Exception {
+        String requestCode = executeForeground(actionValue);
+        String searchString = getCompletedActionString(actionValue, requestCode);
+        checkLogcatForText(BG_VS_FG_TAG, searchString, maxTimeMs);
+        return requestCode;
+    }
+
+    /**
      * Runs an activity (in the foreground) to perform the given action.
      * @param actionValue one of the constants in BatteryStatsBgVsFgActions indicating the desired
      *                    action to perform.
+     * @return A string, representing a random integer, assigned to this particular request for the
+     *                     device to perform the given action. This value can be used to receive
+     *                     communications via logcat from the device about this action.
      */
-    private void executeForeground(String actionValue) throws Exception {
+    private String executeForeground(String actionValue) throws Exception {
+        String requestCode = Integer.toString(new Random().nextInt());
         getDevice().executeShellCommand(String.format(
-                "am start -n '%s' -e %s %s",
-                DEVICE_SIDE_FG_ACTIVITY_COMPONENT, KEY_ACTION, actionValue));
+                "am start -n '%s' -e %s %s -e %s %s",
+                DEVICE_SIDE_FG_ACTIVITY_COMPONENT,
+                KEY_ACTION, actionValue,
+                KEY_REQUEST_CODE, requestCode));
+        return requestCode;
+    }
+
+    /**
+     * The string that will be printed in the logcat when the action completes. This needs to be
+     * identical to {@link com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions#tellHostActionFinished}.
+     */
+    private String getCompletedActionString(String actionValue, String requestCode) {
+        return String.format("Completed performing %s for request %s", actionValue, requestCode);
+    }
+
+    /**
+    * Runs logcat and waits (for a maximumum of maxTimeMs) until the desired text is displayed with
+    * the given tag.
+    * Logcat is not cleared, so make sure that text is unique (won't get false hits from old data).
+    * Note that, in practice, the actual max wait time seems to be about 10s longer than maxTimeMs.
+    */
+    private void checkLogcatForText(String logcatTag, String text, int maxTimeMs) {
+        IShellOutputReceiver receiver = new IShellOutputReceiver() {
+            private final StringBuilder mOutputBuffer = new StringBuilder();
+            private final AtomicBoolean mIsCanceled = new AtomicBoolean(false);
+
+            @Override
+            public void addOutput(byte[] data, int offset, int length) {
+                if (!isCancelled()) {
+                    synchronized (mOutputBuffer) {
+                        String s = new String(data, offset, length, Charsets.UTF_8);
+                        mOutputBuffer.append(s);
+                        if (checkBufferForText()) {
+                            mIsCanceled.set(true);
+                        }
+                    }
+                }
+            }
+
+            private boolean checkBufferForText() {
+                if (mOutputBuffer.indexOf(text) > -1) {
+                    return true;
+                } else {
+                    // delete all old data (except the last few chars) since they don't contain text
+                    // (presumably large chunks of data will be added at a time, so this is
+                    // sufficiently efficient.)
+                    int newStart = mOutputBuffer.length() - text.length();
+                    if (newStart > 0) {
+                        mOutputBuffer.delete(0, newStart);
+                    }
+                    return false;
+                }
+            }
+
+            @Override
+            public boolean isCancelled() {
+                return mIsCanceled.get();
+            }
+
+            @Override
+            public void flush() {
+            }
+        };
+
+        try {
+            // Wait for at most maxTimeMs for logcat to display the desired text.
+            getDevice().executeShellCommand(String.format("logcat -s %s -e '%s'", logcatTag, text),
+                    receiver, maxTimeMs, TimeUnit.MILLISECONDS, 0);
+        } catch (com.android.tradefed.device.DeviceNotAvailableException e) {
+            System.err.println(e);
+        }
     }
 
     /**
      * Returns the bytes downloaded for the wifi transfer download tests.
+     * @param requestCode the output of executeForeground() or executeBackground() to identify in
+     *                    the logcat the line associated with the desired download information
      */
-    private long getDownloadedBytes() throws Exception {
+    private long getDownloadedBytes(String requestCode) throws Exception {
         String log = getDevice().executeShellCommand(
-                "logcat -d -s BatteryStatsWifiTransferTests -e '\\d+'");
+                String.format("logcat -d -s BatteryStatsWifiTransferTests -e 'request %s d=\\d+'",
+                        requestCode));
         String[] lines = log.split("\n");
         long size = 0;
         for (int i = lines.length - 1; i >= 0; i--) {
-            String[] parts = lines[i].split(":");
+            String[] parts = lines[i].split("d=");
             String num = parts[parts.length - 1].trim();
             if (num.matches("\\d+")) {
                 size = Integer.parseInt(num);
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 577f62c..d43d8aa 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
@@ -817,29 +817,37 @@
     }
 
     protected void launchComponentAndAssertNetworkAccess(int type) throws Exception {
-        if (type == TYPE_COMPONENT_ACTIVTIY) {
+        if (type == TYPE_COMPONENT_FOREGROUND_SERVICE) {
+            startForegroundService();
+            assertForegroundServiceNetworkAccess();
+            return;
+        } else if (type == TYPE_COMPONENT_ACTIVTIY) {
             turnScreenOn();
-        }
-        final CountDownLatch latch = new CountDownLatch(1);
-        final Intent launchIntent = getIntentForComponent(type);
-        final Bundle extras = new Bundle();
-        final String[] errors = new String[] {null};
-        extras.putBinder(KEY_NETWORK_STATE_OBSERVER, getNewNetworkStateObserver(latch, errors));
-        launchIntent.putExtras(extras);
-        if (type == TYPE_COMPONENT_ACTIVTIY) {
+            final CountDownLatch latch = new CountDownLatch(1);
+            final Intent launchIntent = getIntentForComponent(type);
+            final Bundle extras = new Bundle();
+            final String[] errors = new String[]{null};
+            extras.putBinder(KEY_NETWORK_STATE_OBSERVER, getNewNetworkStateObserver(latch, errors));
+            launchIntent.putExtras(extras);
             mContext.startActivity(launchIntent);
-        } else if (type == TYPE_COMPONENT_FOREGROUND_SERVICE) {
-            mContext.startService(launchIntent);
-        }
-        if (latch.await(FOREGROUND_PROC_NETWORK_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
-            if (!errors[0].isEmpty()) {
-                fail("Network is not available for app2 (" + mUid + "): " + errors[0]);
+            if (latch.await(FOREGROUND_PROC_NETWORK_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                if (!errors[0].isEmpty()) {
+                    fail("Network is not available for app2 (" + mUid + "): " + errors[0]);
+                }
+            } else {
+                fail("Timed out waiting for network availability status from app2 (" + mUid + ")");
             }
         } else {
-            fail("Timed out waiting for network availability status from app2 (" + mUid + ")");
+            throw new IllegalArgumentException("Unknown type: " + type);
         }
     }
 
+    private void startForegroundService() throws Exception {
+        final Intent launchIntent = getIntentForComponent(TYPE_COMPONENT_FOREGROUND_SERVICE);
+        mContext.startForegroundService(launchIntent);
+        assertForegroundServiceState();
+    }
+
     private Intent getIntentForComponent(int type) {
         final Intent intent = new Intent();
         if (type == TYPE_COMPONENT_ACTIVTIY) {
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/AndroidManifest.xml b/hostsidetests/services/activityandwindowmanager/activitymanager/app/AndroidManifest.xml
index f406735..3f87165 100755
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/app/AndroidManifest.xml
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/AndroidManifest.xml
@@ -30,6 +30,12 @@
                 android:supportsPictureInPicture="true"
                 android:exported="true"
         />
+        <activity android:name=".TestActivityWithSameAffinity"
+                android:resizeableActivity="true"
+                android:supportsPictureInPicture="true"
+                android:exported="true"
+                android:taskAffinity="nobody.but.PipActivitySameAffinity"
+        />
         <activity android:name=".TranslucentTestActivity"
                 android:resizeableActivity="true"
                 android:supportsPictureInPicture="true"
@@ -103,7 +109,20 @@
                   android:exported="true"
                   android:taskAffinity="nobody.but.PipActivity2"
         />
-
+        <activity android:name=".PipOnStopActivity"
+                  android:resizeableActivity="false"
+                  android:supportsPictureInPicture="true"
+                  android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
+                  android:exported="true"
+                  android:taskAffinity="nobody.but.PipOnStopActivity"
+        />
+        <activity android:name=".PipActivityWithSameAffinity"
+                  android:resizeableActivity="false"
+                  android:supportsPictureInPicture="true"
+                  android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
+                  android:exported="true"
+                  android:taskAffinity="nobody.but.PipActivitySameAffinity"
+        />
         <activity android:name=".AlwaysFocusablePipActivity"
                   android:theme="@style/Theme.Transparent"
                   android:resizeableActivity="false"
@@ -134,19 +153,12 @@
                   android:exported="true"
         />
         <activity android:name=".LaunchImeWithPipActivity"
-            android:resizeableActivity="false"
-            android:supportsPictureInPicture="true"
-            androidprv:alwaysFocusable="true"
-            android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
-            android:exported="true"
-            android:windowSoftInputMode="stateAlwaysVisible"
-        />
-        <activity android:name=".PipOnStopActivity"
-            android:resizeableActivity="false"
-            android:supportsPictureInPicture="true"
-            android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
-            android:exported="true"
-            android:taskAffinity="nobody.but.PipOnStopActivity"
+                  android:resizeableActivity="false"
+                  android:supportsPictureInPicture="true"
+                  androidprv:alwaysFocusable="true"
+                  android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
+                  android:exported="true"
+                  android:windowSoftInputMode="stateAlwaysVisible"
         />
         <activity android:name=".FreeformActivity"
                   android:resizeableActivity="true"
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivityWithSameAffinity.java b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivityWithSameAffinity.java
new file mode 100644
index 0000000..e97dc0e
--- /dev/null
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivityWithSameAffinity.java
@@ -0,0 +1,34 @@
+/*
+ * 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.server.cts;
+
+import android.app.Activity;
+import android.app.PictureInPictureParams;
+
+/**
+ * An activity that can enter PiP with a fixed affinity to match
+ * {@link TestActivityWithSameAffinity}.
+ */
+public class PipActivityWithSameAffinity extends Activity {
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+
+        enterPictureInPictureMode(new PictureInPictureParams.Builder().build());
+    }
+}
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/TestActivityWithSameAffinity.java b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/TestActivityWithSameAffinity.java
new file mode 100644
index 0000000..d835da7
--- /dev/null
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/TestActivityWithSameAffinity.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.cts;
+
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.util.Log;
+
+public class TestActivityWithSameAffinity extends TestActivity {
+
+    private static final String TAG = TestActivityWithSameAffinity.class.getSimpleName();
+
+    // Starts the activity (component name) provided by the value at the end of onCreate
+    private static final String EXTRA_START_ACTIVITY = "start_activity";
+    // Finishes the activity at the end of onResume (after EXTRA_START_ACTIVITY is handled)
+    private static final String EXTRA_FINISH_SELF_ON_RESUME = "finish_self_on_resume";
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        // Launch a new activity if requested
+        String launchActivityComponent = getIntent().getStringExtra(EXTRA_START_ACTIVITY);
+        if (launchActivityComponent != null) {
+            Intent launchIntent = new Intent();
+            launchIntent.setComponent(ComponentName.unflattenFromString(launchActivityComponent));
+            startActivity(launchIntent);
+        }
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+
+        // Finish self if requested
+        if (getIntent().hasExtra(EXTRA_FINISH_SELF_ON_RESUME)) {
+            finish();
+        }
+    }
+
+    @Override
+    protected String getTag() {
+        return TAG;
+    }
+}
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/VirtualDisplayActivity.java b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/VirtualDisplayActivity.java
index 8374f7c..c04ef90 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/VirtualDisplayActivity.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/VirtualDisplayActivity.java
@@ -102,6 +102,9 @@
             case "destroy_display":
                 destroyVirtualDisplays();
                 break;
+            case "resize_display":
+                resizeDisplay();
+                break;
         }
     }
 
@@ -195,4 +198,12 @@
     @Override
     public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
     }
+
+    /** Resize virtual display to half of the surface frame size. */
+    private void resizeDisplay() {
+        final VirtualDisplayEntry vd = (VirtualDisplayEntry) mVirtualDisplays.values().toArray()[0];
+        final SurfaceHolder surfaceHolder = vd.surfaceView.getHolder();
+        vd.display.resize(surfaceHolder.getSurfaceFrame().width() / 2,
+                surfaceHolder.getSurfaceFrame().height() / 2, vd.density);
+    }
 }
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTests.java
index 9ad9d29..dc37d9b 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTests.java
@@ -410,7 +410,7 @@
      * on the primary display. It should land on the primary display and dismiss docked stack.
      */
     public void testLaunchNonResizeableActivityWithSplitScreen() throws Exception {
-        if (!supportsMultiDisplay()) { return; }
+        if (!supportsMultiDisplay() || !supportsSplitScreenMultiWindow()) { return; }
 
         // Start launching activity.
         launchActivityInDockStack(LAUNCHING_ACTIVITY);
@@ -540,10 +540,9 @@
         if (!supportsMultiDisplay()) { return; }
 
         // Start launching activity.
-        launchActivityInDockStack(LAUNCHING_ACTIVITY);
+        launchActivity(LAUNCHING_ACTIVITY);
         // Create new virtual display.
-        final DisplayState newDisplay =
-                new VirtualDisplayBuilder(this).setLaunchInSplitScreen(true).build();
+        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();
 
         // Launch activity on secondary display from the app on primary display.
         getLaunchActivityBuilder().setTargetActivityName(TEST_ACTIVITY_NAME)
@@ -569,28 +568,21 @@
         if (!supportsMultiDisplay()) { return; }
 
         // Start launching activity.
-        launchActivityInDockStack(LAUNCHING_ACTIVITY);
-        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
-
+        launchActivity(LAUNCHING_ACTIVITY);
         // Create new virtual display.
-        final DisplayState newDisplay =
-                new VirtualDisplayBuilder(this).setLaunchInSplitScreen(true).build();
+        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();
         mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
-        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
 
         // Launch activity on new secondary display.
         launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mDisplayId);
         mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true /* visible */);
         mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
-        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
 
         // Launch activity on primary display and check if it doesn't affect activity on secondary
         // display.
         getLaunchActivityBuilder().setTargetActivityName(RESIZEABLE_ACTIVITY_NAME).execute();
-        mAmWmState.waitForValidState(mDevice, RESIZEABLE_ACTIVITY_NAME,
-                FULLSCREEN_WORKSPACE_STACK_ID);
+        mAmWmState.waitForValidState(mDevice, RESIZEABLE_ACTIVITY_NAME);
         mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true /* visible */);
-        mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
         mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY_NAME, true /* visible */);
     }
 
@@ -606,46 +598,54 @@
         mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
         mAmWmState.assertFocusedActivity("Virtual display activity must be focused",
                 VIRTUAL_DISPLAY_ACTIVITY);
-        mAmWmState.assertFocusedStack("Focus must remain on primary display",
-                FULLSCREEN_WORKSPACE_STACK_ID);
+        final int defaultDisplayStackId = mAmWmState.getAmState().getFocusedStackId();
+        ActivityManagerState.ActivityStack focusedStack
+                = mAmWmState.getAmState().getStackById(defaultDisplayStackId);
+        assertEquals("Focus must remain on primary display", DEFAULT_DISPLAY_ID,
+                focusedStack.mDisplayId);
 
         // Launch activity on new secondary display.
         launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mDisplayId);
         mAmWmState.assertFocusedActivity("Focus must be on secondary display", TEST_ACTIVITY_NAME);
-        mAmWmState.assertNotFocusedStack("Focused stack must be on secondary display",
-                FULLSCREEN_WORKSPACE_STACK_ID);
+        int focusedStackId = mAmWmState.getAmState().getFocusedStackId();
+        focusedStack = mAmWmState.getAmState().getStackById(focusedStackId);
+        assertEquals("Focused stack must be on secondary display",
+                newDisplay.mDisplayId, focusedStack.mDisplayId);
 
         // Move activity from secondary display to primary.
-        moveActivityToStack(TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID);
-        mAmWmState.waitForFocusedStack(mDevice, FULLSCREEN_WORKSPACE_STACK_ID);
+        moveActivityToStack(TEST_ACTIVITY_NAME, defaultDisplayStackId);
+        mAmWmState.waitForFocusedStack(mDevice, defaultDisplayStackId);
         mAmWmState.assertFocusedActivity("Focus must be on moved activity", TEST_ACTIVITY_NAME);
-        mAmWmState.assertFocusedStack("Focus must return to primary display",
-                FULLSCREEN_WORKSPACE_STACK_ID);
+        focusedStackId = mAmWmState.getAmState().getFocusedStackId();
+        focusedStack = mAmWmState.getAmState().getStackById(focusedStackId);
+        assertEquals("Focus must return to primary display", DEFAULT_DISPLAY_ID,
+                focusedStack.mDisplayId);
     }
 
     /**
      * Tests launching activities on secondary display and then removing it to see if stack focus
      * is moved correctly.
-     * This version launches virtual display creator to fullscreen stack.
+     * This version launches virtual display creator to fullscreen stack in split-screen.
      */
     @Presubmit
     public void testStackFocusSwitchOnDisplayRemoved() throws Exception {
-        if (!supportsMultiDisplay()) { return; }
+        if (!supportsMultiDisplay() || !supportsSplitScreenMultiWindow()) { return; }
 
         // Start launching activity into docked stack.
         launchActivityInDockStack(LAUNCHING_ACTIVITY);
         mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
 
-        tryCreatingAndRemovingDisplayWithActivity();
+        tryCreatingAndRemovingDisplayWithActivity(true /* splitScreen */,
+                FULLSCREEN_WORKSPACE_STACK_ID);
     }
 
     /**
      * Tests launching activities on secondary display and then removing it to see if stack focus
      * is moved correctly.
-     * This version launches virtual display creator to docked stack.
+     * This version launches virtual display creator to docked stack in split-screen.
      */
     public void testStackFocusSwitchOnDisplayRemoved2() throws Exception {
-        if (!supportsMultiDisplay()) { return; }
+        if (!supportsMultiDisplay() || !supportsSplitScreenMultiWindow()) { return; }
 
         // Setup split-screen.
         launchActivityInDockStack(RESIZEABLE_ACTIVITY_NAME);
@@ -654,21 +654,45 @@
         launchActivityInStack(LAUNCHING_ACTIVITY, FULLSCREEN_WORKSPACE_STACK_ID);
         mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
 
-        tryCreatingAndRemovingDisplayWithActivity();
+        tryCreatingAndRemovingDisplayWithActivity(true /* splitScreen */,
+                FULLSCREEN_WORKSPACE_STACK_ID);
     }
 
     /**
-     * Create a virtual display to side from LaunchingActivity, launch a test activity there,
-     * destroy the display and check if test activity is moved to fullscreen stack.
+     * Tests launching activities on secondary display and then removing it to see if stack focus
+     * is moved correctly.
+     * This version works without split-screen.
      */
-    private void tryCreatingAndRemovingDisplayWithActivity() throws Exception {
+    public void testStackFocusSwitchOnDisplayRemoved3() throws Exception {
+        if (!supportsMultiDisplay()) { return; }
+
+        // Start an activity on default display to determine default stack.
+        launchActivity(BROADCAST_RECEIVER_ACTIVITY);
+        final int focusedStackId = mAmWmState.getAmState().getFrontStackId(DEFAULT_DISPLAY_ID);
+        // Finish probing activity.
+        executeShellCommand(FINISH_ACTIVITY_BROADCAST);
+
+
+        tryCreatingAndRemovingDisplayWithActivity(false /* splitScreen */, focusedStackId);
+    }
+
+    /**
+     * Create a virtual display, launch a test activity there, destroy the display and check if test
+     * activity is moved to a stack on the default display.
+     */
+    private void tryCreatingAndRemovingDisplayWithActivity(boolean splitScreen, int defaultStackId)
+            throws Exception {
         // Create new virtual display.
-        final DisplayState newDisplay = new VirtualDisplayBuilder(this)
-                .setLaunchInSplitScreen(true)
-                .setPublicDisplay(true)
-                .build();
+        final VirtualDisplayBuilder builder = new VirtualDisplayBuilder(this)
+                .setPublicDisplay(true);
+        if (splitScreen) {
+            builder.setLaunchInSplitScreen(true);
+        }
+        final DisplayState newDisplay = builder.build();
         mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
-        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
+        if (splitScreen) {
+            mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
+        }
 
         // Launch activity on new secondary display.
         launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mDisplayId);
@@ -679,15 +703,17 @@
 
         // Destroy virtual display.
         destroyVirtualDisplays();
-        mAmWmState.waitForValidState(mDevice, TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID);
+        mAmWmState.waitForValidState(mDevice, TEST_ACTIVITY_NAME, defaultStackId);
         mAmWmState.assertSanity();
         mAmWmState.assertValidBounds(true /* compareTaskAndStackBounds */);
 
         // Check if the focus is switched back to primary display.
         mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true /* visible */);
-        mAmWmState.assertFocusedStack("Fullscreen stack must be focused after display removed",
-                FULLSCREEN_WORKSPACE_STACK_ID);
-        mAmWmState.assertFocusedActivity("Focus must be switched back to primary display",
+        mAmWmState.assertFocusedStack(
+                "Default stack on primary display must be focused after display removed",
+                defaultStackId);
+        mAmWmState.assertFocusedActivity(
+                "Focus must be switched back to activity on primary display",
                 TEST_ACTIVITY_NAME);
     }
 
@@ -698,15 +724,10 @@
     public void testStackFocusSwitchOnStackEmptied() throws Exception {
         if (!supportsMultiDisplay()) { return; }
 
-        // Start launching activity.
-        launchActivityInDockStack(LAUNCHING_ACTIVITY);
-        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
-
         // Create new virtual display.
-        final DisplayState newDisplay =
-                new VirtualDisplayBuilder(this).setLaunchInSplitScreen(true).build();
+        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();
         mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
-        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
+        final int focusedStackId = mAmWmState.getAmState().getFrontStackId(DEFAULT_DISPLAY_ID);
 
         // Launch activity on new secondary display.
         launchActivityOnDisplay(BROADCAST_RECEIVER_ACTIVITY, newDisplay.mDisplayId);
@@ -721,9 +742,8 @@
 
         // Unlock and check if the focus is switched back to primary display.
         wakeUpAndUnlockDevice();
-        mAmWmState.waitForFocusedStack(mDevice, FULLSCREEN_WORKSPACE_STACK_ID);
-        mAmWmState.waitForValidState(mDevice, LAUNCHING_ACTIVITY);
-        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
+        mAmWmState.waitForFocusedStack(mDevice, focusedStackId);
+        mAmWmState.waitForValidState(mDevice, VIRTUAL_DISPLAY_ACTIVITY);
         mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
         mAmWmState.assertFocusedActivity("Focus must be switched back to primary display",
                 VIRTUAL_DISPLAY_ACTIVITY);
@@ -767,16 +787,20 @@
         mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
         mAmWmState.assertFocusedActivity("Virtual display activity must be focused",
                 VIRTUAL_DISPLAY_ACTIVITY);
-        mAmWmState.assertFocusedStack("Focus must remain on primary display",
-                FULLSCREEN_WORKSPACE_STACK_ID);
+        final int defaultDisplayFocusedStackId = mAmWmState.getAmState().getFocusedStackId();
+        ActivityManagerState.ActivityStack focusedStack
+                = mAmWmState.getAmState().getStackById(defaultDisplayFocusedStackId);
+        assertEquals("Focus must remain on primary display", DEFAULT_DISPLAY_ID,
+                focusedStack.mDisplayId);
 
         // Launch activity on new secondary display.
         launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mDisplayId);
         mAmWmState.assertFocusedActivity("Focus must be on secondary display",
                 TEST_ACTIVITY_NAME);
         final int externalFocusedStackId = mAmWmState.getAmState().getFocusedStackId();
-        assertTrue("Focused stack must be on secondary display",
-                FULLSCREEN_WORKSPACE_STACK_ID != externalFocusedStackId);
+        focusedStack = mAmWmState.getAmState().getStackById(externalFocusedStackId);
+        assertEquals("Focused stack must be on secondary display", newDisplay.mDisplayId,
+                focusedStack.mDisplayId);
 
         // Launch other activity with different uid and check it is launched on dynamic stack on
         // secondary display.
@@ -801,8 +825,11 @@
         mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
         mAmWmState.assertFocusedActivity("Virtual display activity must be focused",
                 VIRTUAL_DISPLAY_ACTIVITY);
-        mAmWmState.assertFocusedStack("Focus must remain on primary display",
-                FULLSCREEN_WORKSPACE_STACK_ID);
+        final int defaultDisplayFocusedStackId = mAmWmState.getAmState().getFocusedStackId();
+        ActivityManagerState.ActivityStack focusedStack
+                = mAmWmState.getAmState().getStackById(defaultDisplayFocusedStackId);
+        assertEquals("Focus must remain on primary display", DEFAULT_DISPLAY_ID,
+                focusedStack.mDisplayId);
 
         // Launch activity with different uid on secondary display.
         final String startCmd =  "am start -n " + SECOND_PACKAGE_NAME + "/." + SECOND_ACTIVITY_NAME;
@@ -814,8 +841,9 @@
         mAmWmState.assertFocusedActivity("Focus must be on newly launched app",
                 SECOND_PACKAGE_NAME, SECOND_ACTIVITY_NAME);
         final int externalFocusedStackId = mAmWmState.getAmState().getFocusedStackId();
-        assertTrue("Focused stack must be on secondary display",
-                FULLSCREEN_WORKSPACE_STACK_ID != externalFocusedStackId);
+        focusedStack = mAmWmState.getAmState().getStackById(externalFocusedStackId);
+        assertEquals("Focused stack must be on secondary display", newDisplay.mDisplayId,
+                focusedStack.mDisplayId);
 
         // Launch another activity with third different uid from app on secondary display and check
         // it is launched on secondary display.
@@ -877,8 +905,11 @@
         mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
         mAmWmState.assertFocusedActivity("Virtual display activity must be focused",
                 VIRTUAL_DISPLAY_ACTIVITY);
-        mAmWmState.assertFocusedStack("Focus must remain on primary display",
-                FULLSCREEN_WORKSPACE_STACK_ID);
+        final int defaultDisplayFocusedStackId = mAmWmState.getAmState().getFocusedStackId();
+        ActivityManagerState.ActivityStack focusedStack
+                = mAmWmState.getAmState().getStackById(defaultDisplayFocusedStackId);
+        assertEquals("Focus must remain on primary display", DEFAULT_DISPLAY_ID,
+                focusedStack.mDisplayId);
 
         // Launch other activity with different uid on secondary display.
         final String startCmd =  "am start -n " + SECOND_PACKAGE_NAME + "/." + SECOND_ACTIVITY_NAME;
@@ -890,8 +921,9 @@
         mAmWmState.assertFocusedActivity("Focus must be on newly launched app",
                 SECOND_PACKAGE_NAME, SECOND_ACTIVITY_NAME);
         final int externalFocusedStackId = mAmWmState.getAmState().getFocusedStackId();
-        assertTrue("Focused stack must be on secondary display",
-                FULLSCREEN_WORKSPACE_STACK_ID != externalFocusedStackId);
+        focusedStack = mAmWmState.getAmState().getStackById(externalFocusedStackId);
+        assertEquals("Focused stack must be on secondary display", newDisplay.mDisplayId,
+                focusedStack.mDisplayId);
 
         // Check that owner uid can launch its own activity on secondary display.
         final String broadcastAction = componentName + ".LAUNCH_BROADCAST_ACTION";
@@ -917,16 +949,20 @@
         mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
         mAmWmState.assertFocusedActivity("Virtual display activity must be focused",
                 VIRTUAL_DISPLAY_ACTIVITY);
-        mAmWmState.assertFocusedStack("Focus must remain on primary display",
-                FULLSCREEN_WORKSPACE_STACK_ID);
+        final int defaultDisplayFocusedStackId = mAmWmState.getAmState().getFocusedStackId();
+        ActivityManagerState.ActivityStack focusedStack
+                = mAmWmState.getAmState().getStackById(defaultDisplayFocusedStackId);
+        assertEquals("Focus must remain on primary display", DEFAULT_DISPLAY_ID,
+                focusedStack.mDisplayId);
 
         // Launch activity on new secondary display.
         launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mDisplayId);
         mAmWmState.assertFocusedActivity("Focus must be on secondary display",
                 TEST_ACTIVITY_NAME);
         final int externalFocusedStackId = mAmWmState.getAmState().getFocusedStackId();
-        assertTrue("Focused stack must be on secondary display",
-                FULLSCREEN_WORKSPACE_STACK_ID != externalFocusedStackId);
+        focusedStack = mAmWmState.getAmState().getStackById(externalFocusedStackId);
+        assertEquals("Focused stack must be on secondary display", newDisplay.mDisplayId,
+                focusedStack.mDisplayId);
 
         final String logSeparator = clearLogcat();
 
@@ -1052,15 +1088,9 @@
     public void testDisplayResize() throws Exception {
         if (!supportsMultiDisplay()) { return; }
 
-        // Start launching activity.
-        launchActivityInDockStack(LAUNCHING_ACTIVITY);
-
-        mAmWmState.waitForValidState(mDevice, LAUNCHING_ACTIVITY, DOCKED_STACK_ID);
         // Create new virtual display.
-        final DisplayState newDisplay =
-                new VirtualDisplayBuilder(this).setLaunchInSplitScreen(true).build();
+        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();
         mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
-        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
 
         // Launch a resizeable activity on new secondary display.
         final String initialLogSeparator = clearLogcat();
@@ -1072,14 +1102,10 @@
         // Grab reported sizes and compute new with slight size change.
         final ReportedSizes initialSize = getLastReportedSizesForActivity(RESIZEABLE_ACTIVITY_NAME,
                 initialLogSeparator);
-        final Rectangle initialBounds
-                = mAmWmState.getAmState().getStackById(DOCKED_STACK_ID).getBounds();
-        final Rectangle newBounds = new Rectangle(initialBounds.x, initialBounds.y,
-                initialBounds.width + SIZE_VALUE_SHIFT, initialBounds.height + SIZE_VALUE_SHIFT);
 
         // Resize the docked stack, so that activity with virtual display will also be resized.
         final String logSeparator = clearLogcat();
-        resizeDockedStack(newBounds.width, newBounds.height, newBounds.width, newBounds.height);
+        executeShellCommand(getResizeVirtualDisplayCommand());
 
         mAmWmState.waitForWithAmState(mDevice, amState -> {
             try {
@@ -1091,16 +1117,8 @@
             }
         }, "Wait for the configuration change to happen and for activity to be resumed.");
 
-        mAmWmState.computeState(mDevice, new String[] {RESIZEABLE_ACTIVITY_NAME, LAUNCHING_ACTIVITY,
+        mAmWmState.computeState(mDevice, new String[] {RESIZEABLE_ACTIVITY_NAME,
                 VIRTUAL_DISPLAY_ACTIVITY}, false /* compareTaskAndStackBounds */);
-        mAmWmState.assertDockedTaskBounds(newBounds.width, newBounds.height,
-                LAUNCHING_ACTIVITY);
-        mAmWmState.assertContainsStack("Must contain docked stack", DOCKED_STACK_ID);
-        mAmWmState.assertContainsStack("Must contain fullscreen stack",
-                FULLSCREEN_WORKSPACE_STACK_ID);
-        assertEquals(new Rectangle(0, 0, newBounds.width, newBounds.height),
-                mAmWmState.getAmState().getStackById(DOCKED_STACK_ID).getBounds());
-        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true);
         mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true);
         mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY_NAME, true);
 
@@ -1112,12 +1130,8 @@
                 logSeparator);
         assertTrue(updatedSize.widthDp <= initialSize.widthDp);
         assertTrue(updatedSize.heightDp <= initialSize.heightDp);
-        assertTrue(updatedSize.displayWidth <= initialSize.displayWidth);
-        assertTrue(updatedSize.displayHeight <= initialSize.displayHeight);
-        final boolean widthUpdated = updatedSize.metricsWidth < initialSize.metricsWidth;
-        final boolean heightUpdated = updatedSize.metricsHeight < initialSize.metricsHeight;
-        assertTrue("Either width or height must be updated after split-screen resize",
-                widthUpdated ^ heightUpdated);
+        assertTrue(updatedSize.displayWidth == initialSize.displayWidth / 2);
+        assertTrue(updatedSize.displayHeight == initialSize.displayHeight / 2);
     }
 
     /** Read the number of configuration changes sent to activity from logs. */
@@ -1174,7 +1188,7 @@
         // Check that task has moved from primary display to secondary.
         final int taskNumFinal = mAmWmState.getAmState().getStackById(defaultDisplayStackId)
                 .getTasks().size();
-        mAmWmState.assertEquals("Task number in fullscreen stack must be decremented.", taskNum - 1,
+        mAmWmState.assertEquals("Task number in default stack must be decremented.", taskNum - 1,
                 taskNumFinal);
         final int taskNumFinalOnSecondary = mAmWmState.getAmState().getStackById(frontStackId)
                 .getTasks().size();
@@ -1246,12 +1260,15 @@
                 null /* stackIds */, false /* compareTaskAndStackBounds */, componentName);
 
         // Check that second activity gets launched on the default display
-        final ActivityManagerState.ActivityStack fullscreenStack =
-                mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID);
+        final int defaultDisplayFrontStackId = mAmWmState.getAmState().getFrontStackId(
+                DEFAULT_DISPLAY_ID);
+        final ActivityManagerState.ActivityStack defaultDisplayFrontStack =
+                mAmWmState.getAmState().getStackById(defaultDisplayFrontStackId);
         assertEquals("Activity launched on default display must be resumed",
-                getActivityComponentName(ALT_LAUNCHING_ACTIVITY), fullscreenStack.mResumedActivity);
+                getActivityComponentName(ALT_LAUNCHING_ACTIVITY),
+                defaultDisplayFrontStack.mResumedActivity);
         mAmWmState.assertFocusedStack("Focus must be on primary display",
-                FULLSCREEN_WORKSPACE_STACK_ID);
+                defaultDisplayFrontStackId);
 
         executeShellCommand("am start -n " + getActivityComponentName(LAUNCHING_ACTIVITY));
         mAmWmState.waitForFocusedStack(mDevice, frontStackId);
@@ -1293,13 +1310,14 @@
         mAmWmState.waitForValidState(mDevice, new String[] {TEST_ACTIVITY_NAME},
                 null /* stackIds */, false /* compareTaskAndStackBounds */, componentName);
 
-        // Check that the second activity is launched onto the fullscreen stack
-        final ActivityManagerState.ActivityStack fullscreenStack =
-                mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID);
+        // Check that the second activity is launched on the default display
+        final int focusedStackId = mAmWmState.getAmState().getFocusedStackId();
+        final ActivityManagerState.ActivityStack focusedStack
+                = mAmWmState.getAmState().getStackById(focusedStackId);
         assertEquals("Activity launched on default display must be resumed",
-                getActivityComponentName(TEST_ACTIVITY_NAME), fullscreenStack.mResumedActivity);
-        mAmWmState.assertFocusedStack("Focus must be on primary display",
-                FULLSCREEN_WORKSPACE_STACK_ID);
+                getActivityComponentName(TEST_ACTIVITY_NAME), focusedStack.mResumedActivity);
+        assertEquals("Focus must be on primary display", DEFAULT_DISPLAY_ID,
+                focusedStack.mDisplayId);
 
         executeShellCommand("am broadcast -a trigger_broadcast --ez launch_activity true "
                 + "--ez new_task true --es target_activity " + LAUNCHING_ACTIVITY);
@@ -1793,6 +1811,11 @@
                 " --es command destroy_display";
     }
 
+    private static String getResizeVirtualDisplayCommand() {
+        return getAmStartCmd(VIRTUAL_DISPLAY_ACTIVITY) + " -f 0x20000000" +
+                " --es command resize_display";
+    }
+
     /** Checks if the device supports multi-display. */
     private boolean supportsMultiDisplay() throws Exception {
         return hasDeviceFeature("android.software.activities_on_secondary_displays");
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
index 65f507e..37c9d93 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
@@ -35,11 +35,13 @@
  */
 public class ActivityManagerPinnedStackTests extends ActivityManagerTestBase {
     private static final String TEST_ACTIVITY = "TestActivity";
+    private static final String TEST_ACTIVITY_WITH_SAME_AFFINITY = "TestActivityWithSameAffinity";
     private static final String TRANSLUCENT_TEST_ACTIVITY = "TranslucentTestActivity";
     private static final String NON_RESIZEABLE_ACTIVITY = "NonResizeableActivity";
     private static final String RESUME_WHILE_PAUSING_ACTIVITY = "ResumeWhilePausingActivity";
     private static final String PIP_ACTIVITY = "PipActivity";
     private static final String PIP_ACTIVITY2 = "PipActivity2";
+    private static final String PIP_ACTIVITY_WITH_SAME_AFFINITY = "PipActivityWithSameAffinity";
     private static final String ALWAYS_FOCUSABLE_PIP_ACTIVITY = "AlwaysFocusablePipActivity";
     private static final String LAUNCH_INTO_PINNED_STACK_PIP_ACTIVITY =
             "LaunchIntoPinnedStackPipActivity";
@@ -914,6 +916,81 @@
         assertTrue(lifecycleCounts.mPauseCount == 0);
     }
 
+    public void testLaunchTaskByComponentMatchMultipleTasks() throws Exception {
+        if (!supportsPip()) return;
+
+        // Launch a fullscreen activity which will launch a PiP activity in a new task with the same
+        // affinity
+        launchActivity(TEST_ACTIVITY_WITH_SAME_AFFINITY);
+        launchActivityInStack(PIP_ACTIVITY_WITH_SAME_AFFINITY, PINNED_STACK_ID);
+        assertPinnedStackExists();
+
+        // Launch the root activity again...
+        int rootActivityTaskId = mAmWmState.getAmState().getTaskByActivityName(
+                TEST_ACTIVITY_WITH_SAME_AFFINITY).mTaskId;
+        launchHomeActivity();
+        launchActivity(TEST_ACTIVITY_WITH_SAME_AFFINITY);
+
+        // ...and ensure that the root activity task is found and reused, and that the pinned stack
+        // is unaffected
+        assertPinnedStackExists();
+        mAmWmState.assertFocusedActivity("Expected root activity focused",
+                TEST_ACTIVITY_WITH_SAME_AFFINITY);
+        assertTrue(rootActivityTaskId == mAmWmState.getAmState().getTaskByActivityName(
+                TEST_ACTIVITY_WITH_SAME_AFFINITY).mTaskId);
+    }
+
+    public void testLaunchTaskByAffinityMatchMultipleTasks() throws Exception {
+        if (!supportsPip()) return;
+
+        // Launch a fullscreen activity which will launch a PiP activity in a new task with the same
+        // affinity, and also launch another activity in the same task, while finishing itself. As
+        // a result, the task will not have a component matching the same activity as what it was
+        // started with
+        launchActivity(TEST_ACTIVITY_WITH_SAME_AFFINITY,
+                EXTRA_START_ACTIVITY, getActivityComponentName(TEST_ACTIVITY),
+                EXTRA_FINISH_SELF_ON_RESUME, "true");
+        mAmWmState.waitForValidState(mDevice, TEST_ACTIVITY, FULLSCREEN_WORKSPACE_STACK_ID);
+        launchActivityInStack(PIP_ACTIVITY_WITH_SAME_AFFINITY, PINNED_STACK_ID);
+        mAmWmState.waitForValidState(mDevice, PIP_ACTIVITY_WITH_SAME_AFFINITY, PINNED_STACK_ID);
+        assertPinnedStackExists();
+
+        // Launch the root activity again...
+        int rootActivityTaskId = mAmWmState.getAmState().getTaskByActivityName(
+                TEST_ACTIVITY).mTaskId;
+        launchHomeActivity();
+        launchActivity(TEST_ACTIVITY_WITH_SAME_AFFINITY);
+
+        // ...and ensure that even while matching purely by task affinity, the root activity task is
+        // found and reused, and that the pinned stack is unaffected
+        assertPinnedStackExists();
+        mAmWmState.assertFocusedActivity("Expected root activity focused", TEST_ACTIVITY);
+        assertTrue(rootActivityTaskId == mAmWmState.getAmState().getTaskByActivityName(
+                TEST_ACTIVITY).mTaskId);
+    }
+
+    public void testLaunchTaskByAffinityMatchSingleTask() throws Exception {
+        if (!supportsPip()) return;
+
+        // Launch an activity into the pinned stack with a fixed affinity
+        launchActivityInStack(TEST_ACTIVITY_WITH_SAME_AFFINITY, PINNED_STACK_ID,
+                EXTRA_START_ACTIVITY, getActivityComponentName(PIP_ACTIVITY),
+                EXTRA_FINISH_SELF_ON_RESUME, "true");
+        mAmWmState.waitForValidState(mDevice, PIP_ACTIVITY, PINNED_STACK_ID);
+        assertPinnedStackExists();
+
+        // Launch the root activity again, of the matching task and ensure that we expand to
+        // fullscreen
+        int activityTaskId = mAmWmState.getAmState().getTaskByActivityName(
+                PIP_ACTIVITY).mTaskId;
+        launchHomeActivity();
+        launchActivity(TEST_ACTIVITY_WITH_SAME_AFFINITY);
+        mAmWmState.waitForValidState(mDevice, PIP_ACTIVITY, FULLSCREEN_WORKSPACE_STACK_ID);
+        assertPinnedStackDoesNotExist();
+        assertTrue(activityTaskId == mAmWmState.getAmState().getTaskByActivityName(
+                PIP_ACTIVITY).mTaskId);
+    }
+
     /**
      * Called after the given {@param activityName} has been moved to the fullscreen stack. Ensures
      * that the {@param focusedStackId} is focused, and checks the top and/or bottom tasks in the
diff --git a/tests/autofillservice/src/android/autofillservice/cts/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
index 8502824..04a0aac 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/Helper.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
@@ -303,14 +303,17 @@
       final CharSequence text = node.getText();
       final String resourceId = node.getIdEntry();
       if (!TextUtils.isEmpty(text)) {
-        throw new AssertionError("text on sanitized field " + resourceId + ": " + text);
+          throw new AssertionError("text on sanitized field " + resourceId + ": " + text);
       }
       assertNodeHasNoAutofillValue(node);
     }
 
     static void assertNodeHasNoAutofillValue(ViewNode node) {
         final AutofillValue value = node.getAutofillValue();
-        assertWithMessage("node.getAutofillValue()").that(value).isNull();
+        if (value != null) {
+            final String text = value.isText() ? value.getTextValue().toString() : "N/A";
+            throw new AssertionError("node has value: " + value + " text=" + text);
+        }
     }
 
     /**
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
index 38f4020..0d5bd74 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
@@ -23,6 +23,7 @@
 import static android.autofillservice.cts.Helper.assertNumberOfChildren;
 import static android.autofillservice.cts.Helper.assertTextAndValue;
 import static android.autofillservice.cts.Helper.assertTextIsSanitized;
+import static android.autofillservice.cts.Helper.assertValue;
 import static android.autofillservice.cts.Helper.eventually;
 import static android.autofillservice.cts.Helper.findNodeByResourceId;
 import static android.autofillservice.cts.Helper.runShellCommand;
@@ -45,6 +46,7 @@
 import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_USERNAME;
 import static android.text.InputType.TYPE_NULL;
 import static android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD;
+import static android.view.View.IMPORTANT_FOR_AUTOFILL_NO;
 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -355,6 +357,10 @@
 
         // Trigger auto-fill.
         mActivity.onUsername(View::requestFocus);
+
+        // Since this is a Presubmit test, wait for connection to avoid flakiness.
+        waitUntilConnected();
+
         sReplier.getNextFillRequest();
 
         // Auto-fill it.
@@ -1287,21 +1293,13 @@
         assertThat(usernameContainer.getChildCount()).isEqualTo(2);
     }
 
-    private static final boolean BUG_36171235_FIXED = false;
-
     @Test
     public void testAutofillManuallyOneDataset() throws Exception {
         // Set service.
         enableService();
 
-        if (BUG_36171235_FIXED)
         // And activity.
-        mActivity.onUsername((v) -> {
-            v.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS);
-            // TODO: setting an empty text, otherwise longPress() does not
-            // display the AUTOFILL context menu. Need to fix it, but it's a test case issue...
-            v.setText("");
-        });
+        mActivity.onUsername((v) -> v.setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_NO));
 
         // Set expectations.
         sReplier.addResponse(new CannedDataset.Builder()
@@ -1311,12 +1309,7 @@
                 .build());
         mActivity.expectAutoFill("dude", "sweet");
 
-        // Long-press field to trigger AUTOFILL menu.
-        if (BUG_36171235_FIXED) {
-            sUiBot.getAutofillMenuOption(ID_USERNAME).click();
-        } else {
-            mActivity.onUsername((v) -> mActivity.getAutofillManager().requestAutofill(v));
-        }
+        sUiBot.getAutofillMenuOption(ID_USERNAME).click();
 
         final FillRequest fillRequest = sReplier.getNextFillRequest();
         assertThat(fillRequest.flags).isEqualTo(FLAG_MANUAL_REQUEST);
@@ -1342,14 +1335,8 @@
         // Set service.
         enableService();
 
-        if (BUG_36171235_FIXED)
         // And activity.
-        mActivity.onUsername((v) -> {
-            v.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS);
-            // TODO: setting an empty text, otherwise longPress() does not display the AUTOFILL
-            // context menu. Need to fix it, but it's a test case issue...
-            v.setText("");
-        });
+        mActivity.onUsername((v) -> v.setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_NO));
 
         // Set expectations.
         sReplier.addResponse(new CannedFillResponse.Builder()
@@ -1372,11 +1359,7 @@
         }
 
         // Long-press field to trigger AUTOFILL menu.
-        if (BUG_36171235_FIXED) {
-            sUiBot.getAutofillMenuOption(ID_USERNAME).click();
-        } else {
-            mActivity.onUsername((v) -> mActivity.getAutofillManager().requestAutofill(v));
-        }
+        sUiBot.getAutofillMenuOption(ID_USERNAME).click();
 
         final FillRequest fillRequest = sReplier.getNextFillRequest();
         assertThat(fillRequest.flags).isEqualTo(FLAG_MANUAL_REQUEST);
@@ -1390,6 +1373,164 @@
     }
 
     @Test
+    public void testAutofillManuallyPartialField() throws Exception {
+        // Set service.
+        enableService();
+
+        // And activity.
+        mActivity.onUsername((v) -> {
+            v.setText("dud");
+            v.setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_NO);
+        });
+        mActivity.onPassword((v) -> v.setText("IamSecretMan"));
+
+        // Set expectations.
+        sReplier.addResponse(new CannedDataset.Builder()
+                .setField(ID_USERNAME, "dude")
+                .setField(ID_PASSWORD, "sweet")
+                .setPresentation(createPresentation("The Dude"))
+                .build());
+        mActivity.expectAutoFill("dude", "sweet");
+
+        sUiBot.getAutofillMenuOption(ID_USERNAME).click();
+
+        final FillRequest fillRequest = sReplier.getNextFillRequest();
+        assertThat(fillRequest.flags).isEqualTo(FLAG_MANUAL_REQUEST);
+        // Username value should be available because it triggered the manual request...
+        assertValue(fillRequest.structure, ID_USERNAME, "dud");
+        // ... but password didn't
+        assertTextIsSanitized(fillRequest.structure, ID_PASSWORD);
+
+        // Should have been automatically filled.
+        sUiBot.assertNoDatasets();
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+    }
+
+    @Test
+    public void testAutofillManuallyAgainAfterAutomaticallyAutofilledBefore() throws Exception {
+        // Set service.
+        enableService();
+
+        /*
+         * 1st fill (automatic).
+         */
+        // Set expectations.
+        sReplier.addResponse(new CannedDataset.Builder()
+                .setField(ID_USERNAME, "dude")
+                .setField(ID_PASSWORD, "sweet")
+                .setPresentation(createPresentation("The Dude"))
+                .build());
+        mActivity.expectAutoFill("dude", "sweet");
+
+        // Trigger auto-fill.
+        mActivity.onUsername(View::requestFocus);
+
+        // Assert request.
+        final FillRequest fillRequest1 = sReplier.getNextFillRequest();
+        assertThat(fillRequest1.flags).isEqualTo(0);
+        assertTextIsSanitized(fillRequest1.structure, ID_USERNAME);
+        assertTextIsSanitized(fillRequest1.structure, ID_PASSWORD);
+
+        // Select it.
+        sUiBot.selectDataset("The Dude");
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+
+        /*
+         * 2nd fill (manual).
+         */
+        // Set expectations.
+        sReplier.addResponse(new CannedDataset.Builder()
+                .setField(ID_USERNAME, "DUDE")
+                .setField(ID_PASSWORD, "SWEET")
+                .setPresentation(createPresentation("THE DUDE"))
+                .build());
+        mActivity.expectAutoFill("DUDE", "SWEET");
+        // Change password to make sure it's not sent to the service.
+        mActivity.onPassword((v) -> v.setText("IamSecretMan"));
+
+        // Trigger auto-fill.
+        sUiBot.getAutofillMenuOption(ID_USERNAME).click();
+
+        // Assert request.
+        final FillRequest fillRequest2 = sReplier.getNextFillRequest();
+        assertThat(fillRequest2.flags).isEqualTo(FLAG_MANUAL_REQUEST);
+        assertValue(fillRequest2.structure, ID_USERNAME, "dude");
+        assertTextIsSanitized(fillRequest2.structure, ID_PASSWORD);
+
+        // Should have been automatically filled.
+        sUiBot.assertNoDatasets();
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+    }
+
+    @Test
+    public void testAutofillManuallyAgainAfterManuallyAutofilledBefore() throws Exception {
+        // Set service.
+        enableService();
+        // And activity
+        mActivity.onUsername((v) -> v.setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_NO));
+
+        /*
+         * 1st fill (manual).
+         */
+        // Set expectations.
+        sReplier.addResponse(new CannedDataset.Builder()
+                .setField(ID_USERNAME, "dude")
+                .setField(ID_PASSWORD, "sweet")
+                .setPresentation(createPresentation("The Dude"))
+                .build());
+        mActivity.expectAutoFill("dude", "sweet");
+
+        // Trigger auto-fill.
+        sUiBot.getAutofillMenuOption(ID_USERNAME).click();
+
+        // Assert request.
+        final FillRequest fillRequest1 = sReplier.getNextFillRequest();
+        assertThat(fillRequest1.flags).isEqualTo(FLAG_MANUAL_REQUEST);
+        assertValue(fillRequest1.structure, ID_USERNAME, "");
+        assertTextIsSanitized(fillRequest1.structure, ID_PASSWORD);
+
+        // Should have been automatically filled.
+        sUiBot.assertNoDatasets();
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+
+        /*
+         * 2nd fill (manual).
+         */
+        // Set expectations.
+        sReplier.addResponse(new CannedDataset.Builder()
+                .setField(ID_USERNAME, "DUDE")
+                .setField(ID_PASSWORD, "SWEET")
+                .setPresentation(createPresentation("THE DUDE"))
+                .build());
+        mActivity.expectAutoFill("DUDE", "SWEET");
+        // Change password to make sure it's not sent to the service.
+        mActivity.onPassword((v) -> v.setText("IamSecretMan"));
+
+        // Trigger auto-fill.
+        sUiBot.getAutofillMenuOption(ID_USERNAME).click();
+
+        // Assert request.
+        final FillRequest fillRequest2 = sReplier.getNextFillRequest();
+        assertThat(fillRequest2.flags).isEqualTo(FLAG_MANUAL_REQUEST);
+        assertValue(fillRequest2.structure, ID_USERNAME, "dude");
+        assertTextIsSanitized(fillRequest2.structure, ID_PASSWORD);
+
+        // Should have been automatically filled.
+        sUiBot.assertNoDatasets();
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+    }
+
+    @Test
     public void testCommitMultipleTimes() throws Throwable {
         // Set service.
         enableService();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java
index 19f6b80..cd1b419 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java
@@ -240,7 +240,11 @@
         final FillRequest fillRequest1 = sReplier.getNextFillRequest();
         assertThat(fillRequest1.flags).isEqualTo(expectedFlag);
 
-        assertTextIsSanitized(fillRequest1.structure, ID_L1C1);
+        if (manually) {
+            assertValue(fillRequest1.structure, ID_L1C1, "");
+        } else {
+            assertTextIsSanitized(fillRequest1.structure, ID_L1C1);
+        }
         assertTextIsSanitized(fillRequest1.structure, ID_L1C2);
 
         // Auto-fill it.
@@ -272,7 +276,11 @@
 
         assertValue(fillRequest2.structure, ID_L1C1, "l1c1");
         assertValue(fillRequest2.structure, ID_L1C2, "l1c2");
-        assertTextIsSanitized(fillRequest2.structure, ID_L2C1);
+        if (manually) {
+            assertValue(fillRequest2.structure, ID_L2C1, "");
+        } else {
+            assertTextIsSanitized(fillRequest2.structure, ID_L2C1);
+        }
         assertTextIsSanitized(fillRequest2.structure, ID_L2C2);
 
         // Auto-fill it.
@@ -306,7 +314,11 @@
         assertValue(fillRequest3.structure, ID_L1C2, "l1c2");
         assertValue(fillRequest3.structure, ID_L2C1, "l2c1");
         assertValue(fillRequest3.structure, ID_L2C2, "l2c2");
-        assertTextIsSanitized(fillRequest3.structure, ID_L3C1);
+        if (manually) {
+            assertValue(fillRequest3.structure, ID_L3C1, "");
+        } else {
+            assertTextIsSanitized(fillRequest3.structure, ID_L3C1);
+        }
         assertTextIsSanitized(fillRequest3.structure, ID_L3C2);
 
         // Auto-fill it.
@@ -342,7 +354,11 @@
         assertValue(fillRequest4.structure, ID_L2C2, "l2c2");
         assertValue(fillRequest4.structure, ID_L3C1, "l3c1");
         assertValue(fillRequest4.structure, ID_L3C2, "l3c2");
-        assertTextIsSanitized(fillRequest4.structure, ID_L4C1);
+        if (manually) {
+            assertValue(fillRequest4.structure, ID_L4C1, "");
+        } else {
+            assertTextIsSanitized(fillRequest4.structure, ID_L4C1);
+        }
         assertTextIsSanitized(fillRequest4.structure, ID_L4C2);
 
         // Auto-fill it.
@@ -389,6 +405,7 @@
 
         // 2nd partition - manual
         // Prepare.
+        mActivity.setText(2, 1, "L2.."); // Must set before creating expectation.
         final CannedFillResponse response2 = new CannedFillResponse.Builder()
                 .addDataset(new CannedDataset.Builder()
                         .setPresentation(createPresentation("Partition 2"))
@@ -408,7 +425,7 @@
 
         assertValue(fillRequest2.structure, ID_L1C1, "l1c1");
         assertValue(fillRequest2.structure, ID_L1C2, "l1c2");
-        assertTextIsSanitized(fillRequest2.structure, ID_L2C1);
+        assertValue(fillRequest2.structure, ID_L2C1, "L2..");
         assertTextIsSanitized(fillRequest2.structure, ID_L2C2);
 
         // Check the results.
@@ -448,6 +465,7 @@
 
         // 4th partition - manual
         // Prepare.
+        mActivity.setText(4, 1, "L4.."); // Must set before creating expectation.
         final CannedFillResponse response4 = new CannedFillResponse.Builder()
                 .addDataset(new CannedDataset.Builder()
                         .setPresentation(createPresentation("Partition 4"))
@@ -471,7 +489,7 @@
         assertValue(fillRequest4.structure, ID_L2C2, "l2c2");
         assertValue(fillRequest4.structure, ID_L3C1, "l3c1");
         assertValue(fillRequest4.structure, ID_L3C2, "l3c2");
-        assertTextIsSanitized(fillRequest4.structure, ID_L4C1);
+        assertValue(fillRequest4.structure, ID_L4C1, "L4..");
         assertTextIsSanitized(fillRequest4.structure, ID_L4C2);
 
         // Check the results.
diff --git a/tests/fragment/Android.mk b/tests/fragment/Android.mk
index 2c277e2..3283744 100644
--- a/tests/fragment/Android.mk
+++ b/tests/fragment/Android.mk
@@ -33,8 +33,7 @@
     mockito-target-minus-junit4 \
     android-common \
     compatibility-device-util \
-    ctstestrunner \
-    platform-test-annotations
+    ctstestrunner
 #LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util android-support-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
@@ -44,4 +43,4 @@
 
 LOCAL_SDK_VERSION := current
 
-include $(BUILD_PACKAGE)
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/fragment/src/android/fragment/cts/FragmentViewTests.java b/tests/fragment/src/android/fragment/cts/FragmentViewTests.java
index f0d5947..2e5133b 100644
--- a/tests/fragment/src/android/fragment/cts/FragmentViewTests.java
+++ b/tests/fragment/src/android/fragment/cts/FragmentViewTests.java
@@ -308,7 +308,7 @@
         try {
             FragmentTestUtil.executePendingTransactions(mActivityRule);
             fail("Removing a fragment that isn't in should throw an exception");
-        } catch (Throwable t) {
+        } catch (Exception t) {
             // expected
         }
     }
@@ -356,7 +356,7 @@
         try {
             FragmentTestUtil.executePendingTransactions(mActivityRule);
             fail("Hiding a hidden fragment should throw an exception");
-        } catch (Throwable t) {
+        } catch (Exception t) {
             // expected
         }
     }
@@ -373,7 +373,7 @@
         try {
             FragmentTestUtil.executePendingTransactions(mActivityRule);
             fail("Hiding a non-existing fragment should throw an exception");
-        } catch (Throwable t) {
+        } catch (Exception t) {
             // expected
         }
     }
@@ -422,7 +422,7 @@
         try {
             FragmentTestUtil.executePendingTransactions(mActivityRule);
             fail("Showing a visible fragment should throw an exception");
-        } catch (Throwable t) {
+        } catch (Exception t) {
             // expected
         }
     }
@@ -439,7 +439,7 @@
         try {
             FragmentTestUtil.executePendingTransactions(mActivityRule);
             fail("Showing a non-existing fragment should throw an exception");
-        } catch (Throwable t) {
+        } catch (Exception t) {
             // expected
         }
     }
@@ -521,7 +521,7 @@
         try {
             FragmentTestUtil.executePendingTransactions(mActivityRule);
             fail("Detaching a detached fragment should throw an exception");
-        } catch (Throwable t) {
+        } catch (Exception t) {
             // expected
         }
     }
@@ -538,7 +538,7 @@
         try {
             FragmentTestUtil.executePendingTransactions(mActivityRule);
             fail("Detaching a non-existing fragment should throw an exception");
-        } catch (Throwable t) {
+        } catch (Exception t) {
             // expected
         }
     }
@@ -621,7 +621,7 @@
         try {
             FragmentTestUtil.executePendingTransactions(mActivityRule);
             fail("Attaching an attached fragment should throw an exception");
-        } catch (Throwable t) {
+        } catch (Exception t) {
             // expected
         }
     }
@@ -638,7 +638,7 @@
         try {
             FragmentTestUtil.executePendingTransactions(mActivityRule);
             fail("Attaching a non-existing fragment should throw an exception");
-        } catch (Throwable t) {
+        } catch (Exception t) {
             // expected
         }
     }
diff --git a/tests/fragment/src/android/fragment/cts/TransitionFragment.java b/tests/fragment/src/android/fragment/cts/TransitionFragment.java
index fbe2250..17363ac 100644
--- a/tests/fragment/src/android/fragment/cts/TransitionFragment.java
+++ b/tests/fragment/src/android/fragment/cts/TransitionFragment.java
@@ -71,7 +71,7 @@
     }
 
     void waitForTransition() throws InterruptedException {
-        verify(mListener, within(300)).onTransitionEnd(any());
+        verify(mListener, within(500)).onTransitionEnd(any());
         reset(mListener);
     }
 
diff --git a/tests/sensor/Android.mk b/tests/sensor/Android.mk
index d34cd42..39311dc 100644
--- a/tests/sensor/Android.mk
+++ b/tests/sensor/Android.mk
@@ -32,7 +32,7 @@
 LOCAL_SDK_VERSION := current
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
+-include cts/error_prone_rules_tests.mk
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
 #
diff --git a/tests/sensor/jni/SensorTestCases.cpp b/tests/sensor/jni/SensorTestCases.cpp
index f86f262..43e07a4 100644
--- a/tests/sensor/jni/SensorTestCases.cpp
+++ b/tests/sensor/jni/SensorTestCases.cpp
@@ -135,7 +135,7 @@
 // Test sensor direct report functionality
 void SensorTest::testDirectReport(JNIEnv* env, int32_t sensorType, int32_t channelType, int32_t rateLevel) {
     constexpr size_t kEventSize = sizeof(ASensorEvent);
-    constexpr size_t kNEvent = 500;
+    constexpr size_t kNEvent = 4096; // enough to contain 1.5 * 800 * 2.2 events
     constexpr size_t kMemSize = kEventSize * kNEvent;
 
     // value check criterion
diff --git a/tests/sensor/src/android/hardware/cts/SensorBatchingTests.java b/tests/sensor/src/android/hardware/cts/SensorBatchingTests.java
index cb4076c..1b2b25c 100644
--- a/tests/sensor/src/android/hardware/cts/SensorBatchingTests.java
+++ b/tests/sensor/src/android/hardware/cts/SensorBatchingTests.java
@@ -87,11 +87,11 @@
         runBatchingSensorTest(Sensor.TYPE_ACCELEROMETER_UNCALIBRATED, RATE_50HZ, BATCHING_PERIOD);
     }
 
-    public void tesAccelUncalibrated_fastest_flush() throws Throwable {
+    public void testAccelUncalibrated_fastest_flush() throws Throwable {
         runFlushSensorTest(Sensor.TYPE_ACCELEROMETER_UNCALIBRATED, RATE_FASTEST, BATCHING_PERIOD);
     }
 
-    public void tesAccelUncalibrated_50hz_flush() throws Throwable {
+    public void testAccelUncalibrated_50hz_flush() throws Throwable {
         runFlushSensorTest(Sensor.TYPE_ACCELEROMETER_UNCALIBRATED, RATE_50HZ, BATCHING_PERIOD);
     }
 
diff --git a/tests/sensor/src/android/hardware/cts/SensorDirectReportTest.java b/tests/sensor/src/android/hardware/cts/SensorDirectReportTest.java
index 6c2462f..78ac59d 100644
--- a/tests/sensor/src/android/hardware/cts/SensorDirectReportTest.java
+++ b/tests/sensor/src/android/hardware/cts/SensorDirectReportTest.java
@@ -65,7 +65,8 @@
     private static final int TEST_RUN_TIME_PERIOD_MILLISEC = 5000;
     private static final int ALLOWED_SENSOR_INIT_TIME_MILLISEC = 500;
     private static final int SENSORS_EVENT_SIZE = 104;
-    private static final int SHARED_MEMORY_SIZE = 2000 * SENSORS_EVENT_SIZE;
+    private static final int SENSORS_EVENT_COUNT = 10240; // 800Hz * 2.2 * 5 sec + extra
+    private static final int SHARED_MEMORY_SIZE = SENSORS_EVENT_COUNT * SENSORS_EVENT_SIZE;
     private static final float MERCY_FACTOR = 0.1f;
 
     private static native boolean nativeReadHardwareBuffer(HardwareBuffer hardwareBuffer,
diff --git a/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/SensorOperationTest.java b/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/SensorOperationTest.java
index 30da9a0..abfa692 100644
--- a/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/SensorOperationTest.java
+++ b/tests/sensor/src/android/hardware/cts/helpers/sensoroperations/SensorOperationTest.java
@@ -59,7 +59,7 @@
         op = new FakeSensorOperation(true, 0, TimeUnit.MILLISECONDS);
         try {
             op.execute(mTestNode);
-            fail("AssertionError expected");
+            throw new Error("AssertionError expected");
         } catch (AssertionError e) {
             // Expected
         }
diff --git a/tests/sensor/src/android/hardware/cts/helpers/sensorverification/EventBasicVerificationTest.java b/tests/sensor/src/android/hardware/cts/helpers/sensorverification/EventBasicVerificationTest.java
index 34be3c4..b682ac5 100644
--- a/tests/sensor/src/android/hardware/cts/helpers/sensorverification/EventBasicVerificationTest.java
+++ b/tests/sensor/src/android/hardware/cts/helpers/sensorverification/EventBasicVerificationTest.java
@@ -65,7 +65,7 @@
 
         try {
             verification.verify(stats);
-            fail("Expect an AssertionError due to insufficient samples");
+            throw new Error("Expect an AssertionError due to insufficient samples");
         } catch (AssertionError e) {
             //Expected
         }
@@ -81,7 +81,7 @@
 
             try {
                 verification.verify(stats);
-                fail("Expect an AssertionError due to wrong sensor event");
+                throw new Error("Expect an AssertionError due to wrong sensor event");
             } catch (AssertionError e) {
                 //Expected
             }
diff --git a/tests/sensor/src/android/hardware/cts/helpers/sensorverification/EventOrderingVerificationTest.java b/tests/sensor/src/android/hardware/cts/helpers/sensorverification/EventOrderingVerificationTest.java
index f1dc229c8..9cb7436 100644
--- a/tests/sensor/src/android/hardware/cts/helpers/sensorverification/EventOrderingVerificationTest.java
+++ b/tests/sensor/src/android/hardware/cts/helpers/sensorverification/EventOrderingVerificationTest.java
@@ -58,7 +58,7 @@
         EventOrderingVerification verification = getVerification(0, 2, 1, 3, 4);
         try {
             verification.verify(stats);
-            fail("Expected an AssertionError");
+            throw new Error("Expected an AssertionError");
         } catch (AssertionError e) {
             // Expected;
         }
@@ -75,7 +75,7 @@
         EventOrderingVerification verification = getVerification(4, 0, 1, 2, 3);
         try {
             verification.verify(stats);
-            fail("Expected an AssertionError");
+            throw new Error("Expected an AssertionError");
         } catch (AssertionError e) {
             // Expected;
         }
diff --git a/tests/sensor/src/android/hardware/cts/helpers/sensorverification/FrequencyVerificationTest.java b/tests/sensor/src/android/hardware/cts/helpers/sensorverification/FrequencyVerificationTest.java
index bbf022a..8780a7d 100644
--- a/tests/sensor/src/android/hardware/cts/helpers/sensorverification/FrequencyVerificationTest.java
+++ b/tests/sensor/src/android/hardware/cts/helpers/sensorverification/FrequencyVerificationTest.java
@@ -55,7 +55,7 @@
         verification = getVerification(850.0, 975.0, timestamps);
         try {
             verification.verify(getEnvironment(950), stats);
-            fail("Expected an AssertionError");
+            throw new Error("Expected an AssertionError");
         } catch (AssertionError e) {
             // Expected;
         }
@@ -65,7 +65,7 @@
         verification = getVerification(1025.0, 1150.0, timestamps);
         try {
             verification.verify(getEnvironment(1050), stats);
-            fail("Expected an AssertionError");
+            throw new Error("Expected an AssertionError");
         } catch (AssertionError e) {
             // Expected;
         }
diff --git a/tests/sensor/src/android/hardware/cts/helpers/sensorverification/JitterVerificationTest.java b/tests/sensor/src/android/hardware/cts/helpers/sensorverification/JitterVerificationTest.java
index d8e1586..4ac4999 100644
--- a/tests/sensor/src/android/hardware/cts/helpers/sensorverification/JitterVerificationTest.java
+++ b/tests/sensor/src/android/hardware/cts/helpers/sensorverification/JitterVerificationTest.java
@@ -62,7 +62,7 @@
         verification = getVerification(1, timestamps);
         try {
             verification.verify(environment, stats);
-            fail("Expected an AssertionError");
+            throw new Error("Expected an AssertionError");
         } catch (AssertionError e) {
             // Expected;
         }
diff --git a/tests/sensor/src/android/hardware/cts/helpers/sensorverification/MagnitudeVerificationTest.java b/tests/sensor/src/android/hardware/cts/helpers/sensorverification/MagnitudeVerificationTest.java
index ac873c1..dfd951d 100644
--- a/tests/sensor/src/android/hardware/cts/helpers/sensorverification/MagnitudeVerificationTest.java
+++ b/tests/sensor/src/android/hardware/cts/helpers/sensorverification/MagnitudeVerificationTest.java
@@ -57,7 +57,7 @@
         } else {
             try {
                 verification.verify(stats);
-                fail("Expected an AssertionError");
+                throw new Error("Expected an AssertionError");
             } catch (AssertionError e) {
                 // Expected;
             }
diff --git a/tests/sensor/src/android/hardware/cts/helpers/sensorverification/MeanVerificationTest.java b/tests/sensor/src/android/hardware/cts/helpers/sensorverification/MeanVerificationTest.java
index d7fcf9f..64aef60 100644
--- a/tests/sensor/src/android/hardware/cts/helpers/sensorverification/MeanVerificationTest.java
+++ b/tests/sensor/src/android/hardware/cts/helpers/sensorverification/MeanVerificationTest.java
@@ -62,7 +62,7 @@
         verification = getVerification(expected, threshold, values);
         try {
             verification.verify(stats);
-            fail("Expected an AssertionError");
+            throw new Error("Expected an AssertionError");
         } catch (AssertionError e) {
             // Expected;
         }
@@ -74,7 +74,7 @@
         verification = getVerification(expected, threshold, values);
         try {
             verification.verify(stats);
-            fail("Expected an AssertionError");
+            throw new Error("Expected an AssertionError");
         } catch (AssertionError e) {
             // Expected;
         }
@@ -85,7 +85,7 @@
         verification = getVerification(expected, threshold, values);
         try {
             verification.verify(stats);
-            fail("Expected an AssertionError");
+            throw new Error("Expected an AssertionError");
         } catch (AssertionError e) {
             // Expected;
         }
diff --git a/tests/sensor/src/android/hardware/cts/helpers/sensorverification/TimestampClockSourceVerificationTest.java b/tests/sensor/src/android/hardware/cts/helpers/sensorverification/TimestampClockSourceVerificationTest.java
index b8412a6..a65323d 100644
--- a/tests/sensor/src/android/hardware/cts/helpers/sensorverification/TimestampClockSourceVerificationTest.java
+++ b/tests/sensor/src/android/hardware/cts/helpers/sensorverification/TimestampClockSourceVerificationTest.java
@@ -191,7 +191,7 @@
             for (int i = 0; i < indices.length; i++) {
                 assertEquals(indices[i], actualIndices[i]);
             }
-        } catch (Throwable t) {
+        } catch (Exception t) {
         }
     }
 
diff --git a/tests/tests/content/res/font/broken_xmlfont.xml b/tests/tests/content/res/font/broken_xmlfont.xml
new file mode 100644
index 0000000..be30f2f
--- /dev/null
+++ b/tests/tests/content/res/font/broken_xmlfont.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:android="http://schemas.android.com/apk/res/android">
+  <font android:fontStyle="normal" android:fontWeight="400" android:font="@font/brokenfont" />
+</font-family>
diff --git a/tests/tests/content/res/font/brokenfont.ttf b/tests/tests/content/res/font/brokenfont.ttf
new file mode 100644
index 0000000..12b2713
--- /dev/null
+++ b/tests/tests/content/res/font/brokenfont.ttf
Binary files differ
diff --git a/tests/tests/content/res/font/brokenfont_source.ttx b/tests/tests/content/res/font/brokenfont_source.ttx
new file mode 100644
index 0000000..34217b4
--- /dev/null
+++ b/tests/tests/content/res/font/brokenfont_source.ttx
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="a"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Mon May 1 00:00:00 2017"/>
+    <macStyle value="00000000 00000000"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="1.0"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="400"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 01000000"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="a" width="500" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+      <map code="0x0061" name="a" />
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="a" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="1" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      Broken Font
+    </namerecord>
+    <namerecord nameID="2" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      Broken Font
+    </namerecord>
+    <namerecord nameID="6" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      BrokenFont-Regular
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Broken Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Broken Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      BrokenFont-Regular
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/tests/tests/content/res/font/invalid_xmlfont_nosource.xml b/tests/tests/content/res/font/invalid_xmlfont_nosource.xml
new file mode 100644
index 0000000..6b70222
--- /dev/null
+++ b/tests/tests/content/res/font/invalid_xmlfont_nosource.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:android="http://schemas.android.com/apk/res/android">
+  <!-- missing the android:font entry -->
+  <font android:fontStyle="normal" android:fontWeight="400" />
+</font-family>
diff --git a/tests/tests/content/src/android/content/res/cts/ResourcesTest.java b/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
index 89ea29b..be15e57 100644
--- a/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
+++ b/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
@@ -814,6 +814,30 @@
         } catch (RuntimeException e) {
             // pass
         }
+
+        try {
+            mResources.getFont(R.font.invalid_xmlfont_nosource);
+            fail();
+        } catch (RuntimeException e) {
+            // pass
+        }
+
+    }
+
+    public void testGetFont_brokenFontFiles() {
+        try {
+            mResources.getFont(R.font.brokenfont);
+            fail();
+        } catch (RuntimeException e) {
+            // pass
+        }
+
+        try {
+            mResources.getFont(R.font.broken_xmlfont);
+            fail();
+        } catch (RuntimeException e) {
+            // pass
+        }
     }
 
     public void testGetFont_fontFileIsCached() {
diff --git a/tests/tests/graphics/Android.mk b/tests/tests/graphics/Android.mk
index 302b820..6ac89fe 100644
--- a/tests/tests/graphics/Android.mk
+++ b/tests/tests/graphics/Android.mk
@@ -40,6 +40,9 @@
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts general-tests
 
+# Enforce public / test api only
+LOCAL_SDK_VERSION := test_current
+
 include $(BUILD_CTS_PACKAGE)
 
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java b/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
index 52db21f..b36c23a 100644
--- a/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
@@ -1153,6 +1153,13 @@
     }
 
     @Test
+    public void testClipOutPath() {
+        final Path p = new Path();
+        p.addRect(new RectF(5, 5, 10, 10), Direction.CW);
+        assertTrue(mCanvas.clipOutPath(p));
+    }
+
+    @Test
     public void testClipInversePath() {
         final Path p = new Path();
         p.addRoundRect(new RectF(0, 0, 10, 10), 0.5f, 0.5f, Direction.CW);
diff --git a/tests/tests/location/AndroidManifest.xml b/tests/tests/location/AndroidManifest.xml
index f9985ba..1357a38 100644
--- a/tests/tests/location/AndroidManifest.xml
+++ b/tests/tests/location/AndroidManifest.xml
@@ -27,6 +27,10 @@
     <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.INTERNET" />
+
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="android.location.cts"
                      android:label="CTS tests of android.location">
diff --git a/tests/tests/location/src/android/location/cts/GnssPseudorangeVerificationTest.java b/tests/tests/location/src/android/location/cts/GnssPseudorangeVerificationTest.java
new file mode 100644
index 0000000..709fb3a
--- /dev/null
+++ b/tests/tests/location/src/android/location/cts/GnssPseudorangeVerificationTest.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2017 Google Inc.
+ *
+ * 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.location.cts;
+
+
+import android.location.GnssMeasurement;
+import android.location.GnssMeasurementsEvent;
+import android.util.Log;
+import com.android.compatibility.common.util.CddTest;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Test computing and verifying the pseudoranges based on the raw measurements
+ * reported by the GNSS chipset
+ */
+public class GnssPseudorangeVerificationTest extends GnssTestCase {
+  private static final String TAG = "GnssPseudorangeValTest";
+  private static final int LOCATION_TO_COLLECT_COUNT = 5;
+  private static final int MIN_SATELLITES_REQUIREMENT = 4;
+  private static final double SECONDS_PER_NANO = 1.0e-9;
+
+  private TestGnssMeasurementListener mMeasurementListener;
+  private TestLocationListener mLocationListener;
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+
+    mTestLocationManager = new TestLocationManager(getContext());
+  }
+
+  @Override
+  protected void tearDown() throws Exception {
+    // Unregister listeners
+    if (mLocationListener != null) {
+      mTestLocationManager.removeLocationUpdates(mLocationListener);
+    }
+    if (mMeasurementListener != null) {
+      mTestLocationManager.unregisterGnssMeasurementCallback(mMeasurementListener);
+    }
+    super.tearDown();
+  }
+
+  /**
+   * Tests that one can listen for {@link GnssMeasurementsEvent} for collection purposes.
+   * It only performs sanity checks for the measurements received.
+   * This tests uses actual data retrieved from Gnss HAL.
+   */
+  @CddTest(requirement="7.3.3")
+  public void testPseudorangeValue() throws Exception {
+    // Checks if Gnss hardware feature is present, skips test (pass) if not,
+    // and hard asserts that Location/Gnss (Provider) is turned on if is Cts Verifier.
+    if (!TestMeasurementUtil.canTestRunOnCurrentDevice(mTestLocationManager,
+        TAG, MIN_HARDWARE_YEAR_MEASUREMENTS_REQUIRED, isCtsVerifierTest())) {
+      return;
+    }
+
+    mLocationListener = new TestLocationListener(LOCATION_TO_COLLECT_COUNT);
+    mTestLocationManager.requestLocationUpdates(mLocationListener);
+
+    mMeasurementListener = new TestGnssMeasurementListener(TAG);
+    mTestLocationManager.registerGnssMeasurementCallback(mMeasurementListener);
+
+    boolean success = mLocationListener.await();
+    SoftAssert.failOrWarning(isMeasurementTestStrict(),
+        "Time elapsed without getting enough location fixes."
+            + " Possibly, the test has been run deep indoors."
+            + " Consider retrying test outdoors.",
+        success);
+
+    Log.i(TAG, "Location status received = " + mLocationListener.isLocationReceived());
+
+    if (!mMeasurementListener.verifyStatus(isMeasurementTestStrict())) {
+      // If test is strict and verifyStatus reutrns false, an assert exception happens and
+      // test fails.   If test is not strict, we arrive here, and:
+      return; // exit (with pass)
+    }
+
+    List<GnssMeasurementsEvent> events = mMeasurementListener.getEvents();
+    int eventCount = events.size();
+    Log.i(TAG, "Number of GNSS measurement events received = " + eventCount);
+    SoftAssert.failOrWarning(isMeasurementTestStrict(),
+        "GnssMeasurementEvent count: expected > 0, received = " + eventCount,
+        eventCount > 0);
+
+    SoftAssert softAssert = new SoftAssert(TAG);
+
+    boolean hasEventWithEnoughMeasurements = false;
+    // we received events, so perform a quick sanity check on mandatory fields
+    for (GnssMeasurementsEvent event : events) {
+      // Verify Gnss Event mandatory fields are in required ranges
+      assertNotNull("GnssMeasurementEvent cannot be null.", event);
+
+
+      long timeInNs = event.getClock().getTimeNanos();
+      TestMeasurementUtil.assertGnssClockFields(event.getClock(), softAssert, timeInNs);
+
+      // we need at least 4 satellites to calculate the pseudorange
+      if(event.getMeasurements().size() >= MIN_SATELLITES_REQUIREMENT) {
+        validatePseudorange(event.getMeasurements(), softAssert, timeInNs);
+        hasEventWithEnoughMeasurements = true;
+      }
+    }
+
+    SoftAssert.failOrWarning(isMeasurementTestStrict(),
+        "Should have at least one GnssMeasurementEvent with at least 4"
+            + "GnssMeasurement.  If failed, retry near window or outdoors?",
+        hasEventWithEnoughMeasurements);
+
+    softAssert.assertAll();
+  }
+
+  /**
+   * Uses the common reception time approach to calculate pseudorange time
+   * measurements reported by the receiver according to http://cdn.intechopen.com/pdfs-wm/27712.pdf.
+   */
+  private void validatePseudorange(Collection<GnssMeasurement> measurements,
+      SoftAssert softAssert, long timeInNs) {
+    long largestReceivedSvTimeNanos = 0;
+    for(GnssMeasurement measurement : measurements) {
+      if (largestReceivedSvTimeNanos < measurement.getReceivedSvTimeNanos()) {
+        largestReceivedSvTimeNanos =  measurement.getReceivedSvTimeNanos();
+      }
+    }
+    for (GnssMeasurement measurement : measurements) {
+      double deltaiNanos = largestReceivedSvTimeNanos
+                          - measurement.getReceivedSvTimeNanos();
+      double deltaiSeconds = deltaiNanos * SECONDS_PER_NANO;
+      // according to http://cdn.intechopen.com/pdfs-wm/27712.pdf
+      // the pseudorange in time is 65-83 ms, which is 18 ms range,
+      // deltaiSeconds should be in the range of [0.0, 0.018] seconds
+      softAssert.assertTrue("deltaiSeconds in Seconds." ,
+          timeInNs,
+          "0.0 <= deltaiSeconds <= 0.018",
+          String.valueOf(deltaiSeconds),
+          (deltaiSeconds >= 0.0 && deltaiSeconds <= 0.018));
+    }
+
+  }
+}
diff --git a/tests/tests/location/src/android/location/cts/GnssTtffTests.java b/tests/tests/location/src/android/location/cts/GnssTtffTests.java
new file mode 100644
index 0000000..8c407d5
--- /dev/null
+++ b/tests/tests/location/src/android/location/cts/GnssTtffTests.java
@@ -0,0 +1,169 @@
+package android.location.cts;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+import com.android.compatibility.common.util.CddTest;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Tests for the ttff (time to the first fix) validating whether TTFF is
+ * below the expected thresholds in differnt scenario
+ */
+public class GnssTtffTests extends GnssTestCase {
+
+  private static final String TAG = "GnssTtffTests";
+  private static final int LOCATION_TO_COLLECT_COUNT = 1;
+  private static final int STATUS_TO_COLLECT_COUNT = 3;
+  private static final int AIDING_DATA_RESET_DELAY_SECS = 10;
+  // Threshold values
+  private static final int TTFF_WITH_WIFI_CELLUAR_WARM_TH_SECS = 7;
+  private static final int TTFF_WITH_WIFI_CELLUAR_HOT_TH_SECS = 5;
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    mTestLocationManager = new TestLocationManager(getContext());
+  }
+
+  /**
+   * Test the TTFF in the case where there is a network connection for both
+   * warm and hot start TTFF cases.
+   * @throws Exception
+   */
+  @CddTest(requirement="7.3.3")
+  public void testTtffWithNetwork() throws Exception {
+    checkTtffWarmWithCellularAndWifiOn();
+    checkTtffHotWithCellularAndWifiOn();
+  }
+
+  /**
+   * Test Scenario 1
+   * check whether TTFF is below the threshold on the warm start, without any network
+   * 1) Turn on wifi, turn on mobile data
+   * 2) Get GPS, check the TTFF value
+   */
+  public void checkTtffWarmWithCellularAndWifiOn() throws Exception {
+    ensureNetworkStatus();
+    SoftAssert softAssert = new SoftAssert(TAG);
+    mTestLocationManager.sendExtraCommand("delete_aiding_data");
+    Thread.sleep(TimeUnit.SECONDS.toMillis(AIDING_DATA_RESET_DELAY_SECS));
+    checkTtffByThreshold("checkTtffWarmWithCellularAndWifiOn",
+        TimeUnit.SECONDS.toMillis(TTFF_WITH_WIFI_CELLUAR_WARM_TH_SECS), softAssert);
+    softAssert.assertAll();
+  }
+
+  /**
+   * Test Scenario 2
+   * check whether TTFF is below the threhold on the hot start, without any network
+   * 1) Turn on wifi, turn on mobile data
+   * 2) Get GPS, check the TTFF value
+   */
+  public void checkTtffHotWithCellularAndWifiOn() throws Exception {
+    ensureNetworkStatus();
+    SoftAssert softAssert = new SoftAssert(TAG);
+    checkTtffByThreshold("checkTtffHotWithCellularAndWifiOn",
+        TimeUnit.SECONDS.toMillis(TTFF_WITH_WIFI_CELLUAR_HOT_TH_SECS), softAssert);
+    softAssert.assertAll();
+
+  }
+
+  /**
+   * Make sure the device has mobile data and wifi connection
+   */
+  private void ensureNetworkStatus(){
+    assertTrue("Device has to connect to Wifi to complete this test.",
+        isConnectedToWifi(getContext()));
+    ConnectivityManager connManager = getConnectivityManager(getContext());
+    NetworkInfo mobileNetworkInfo = connManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
+    // check whether the mobile data is ON if the device has cellular capability
+    if (mobileNetworkInfo != null) {
+      TelephonyManager telephonyManager = (TelephonyManager) getContext().getApplicationContext()
+          .getSystemService(getContext().TELEPHONY_SERVICE);
+      assertTrue("Device has to have mobile data ON to complete this test.",
+          telephonyManager.isDataEnabled());
+    }
+    else {
+      Log.i(TAG, "This is a wifi only device.");
+    }
+
+  }
+
+  /*
+   * Check whether TTFF is below the threshold
+   * @param testName
+   * @param threshold, the threshold for the TTFF value
+   */
+  private void checkTtffByThreshold(String testName,
+      long threshold, SoftAssert softAssert) throws Exception {
+    TestLocationListener networkLocationListener
+        = new TestLocationListener(LOCATION_TO_COLLECT_COUNT);
+    // fetch the networklocation first to make sure the ttff is not flaky
+    mTestLocationManager.requestNetworkLocationUpdates(networkLocationListener);
+    networkLocationListener.await();
+
+    TestGnssStatusCallback testGnssStatusCallback =
+        new TestGnssStatusCallback(TAG, STATUS_TO_COLLECT_COUNT);
+    mTestLocationManager.registerGnssStatusCallback(testGnssStatusCallback);
+
+    TestLocationListener locationListener = new TestLocationListener(LOCATION_TO_COLLECT_COUNT);
+    mTestLocationManager.requestLocationUpdates(locationListener);
+
+
+    long startTimeMillis = System.currentTimeMillis();
+    boolean success = testGnssStatusCallback.awaitTtff();
+    long ttffTimeMillis = System.currentTimeMillis() - startTimeMillis;
+
+    SoftAssert.failOrWarning(isMeasurementTestStrict(),
+            "Test case:" + testName
+            + ". Threshold exceeded without getting a location."
+            + " Possibly, the test has been run deep indoors."
+            + " Consider retrying test outdoors.",
+        success);
+    mTestLocationManager.removeLocationUpdates(locationListener);
+    mTestLocationManager.unregisterGnssStatusCallback(testGnssStatusCallback);
+    softAssert.assertTrue("Test case: " + testName +", TTFF should be less than " + threshold
+        + " . In current test, TTFF value is: " + ttffTimeMillis, ttffTimeMillis < threshold);
+  }
+
+  /**
+   * Returns whether the device is currently connected to a wifi.
+   *
+   * @param context {@link Context} object
+   * @return {@code true} if connected to Wifi; {@code false} otherwise
+   */
+  public static boolean isConnectedToWifi(Context context) {
+    NetworkInfo info = getActiveNetworkInfo(context);
+    return info != null
+        && info.isConnected()
+        && info.getType() == ConnectivityManager.TYPE_WIFI;
+  }
+
+  /**
+   * Gets the active network info.
+   *
+   * @param context {@link Context} object
+   * @return {@link NetworkInfo}
+   */
+  private static NetworkInfo getActiveNetworkInfo(Context context) {
+    ConnectivityManager cm = getConnectivityManager(context);
+    if (cm != null) {
+      return cm.getActiveNetworkInfo();
+    }
+    return null;
+  }
+
+  /**
+   * Gets the connectivity manager.
+   *
+   * @param context {@link Context} object
+   * @return {@link ConnectivityManager}
+   */
+  private static ConnectivityManager getConnectivityManager(Context context) {
+    return (ConnectivityManager) context.getApplicationContext()
+        .getSystemService(Context.CONNECTIVITY_SERVICE);
+  }
+
+}
\ No newline at end of file
diff --git a/tests/tests/location/src/android/location/cts/TestLocationManager.java b/tests/tests/location/src/android/location/cts/TestLocationManager.java
index cca2b78..390d450 100644
--- a/tests/tests/location/src/android/location/cts/TestLocationManager.java
+++ b/tests/tests/location/src/android/location/cts/TestLocationManager.java
@@ -117,6 +117,21 @@
     }
 
     /**
+     * See {@code LocationManager#requestNetworkLocationUpdates}.
+     *
+     * @param locationListener location listener for request
+     */
+    public void requestNetworkLocationUpdates(LocationListener locationListener) {
+        if (mLocationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) {
+            Log.i(TAG, "Request Network Location updates.");
+            mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
+                0 /* minTime*/,
+                0 /* minDistance */,
+                locationListener,
+                Looper.getMainLooper());
+        }
+    }
+    /**
      * See {@link android.location.LocationManager#addGpsStatusListener (GpsStatus.Listener)}.
      * @param listener the GpsStatus.Listener to add
      */
diff --git a/tests/tests/location/src/android/location/cts/TestUtils.java b/tests/tests/location/src/android/location/cts/TestUtils.java
index a038457..113af49 100644
--- a/tests/tests/location/src/android/location/cts/TestUtils.java
+++ b/tests/tests/location/src/android/location/cts/TestUtils.java
@@ -16,6 +16,7 @@
 
 package android.location.cts;
 
+import java.util.concurrent.Callable;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -46,4 +47,14 @@
         }
         return false;
     }
+    public static boolean waitForWithCondition(int timeInSec, Callable<Boolean> callback)
+        throws Exception {
+        long waitTimeRounds = (TimeUnit.SECONDS.toMillis(timeInSec)) / STANDARD_SLEEP_TIME_MS;
+        for (int i = 0; i < waitTimeRounds; ++i) {
+            Thread.sleep(STANDARD_SLEEP_TIME_MS);
+            if(callback.call()) return true;
+        }
+        return false;
+    }
+
 }
diff --git a/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java b/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
index 4b5b1d7..93f3b66 100644
--- a/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
+++ b/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
@@ -205,7 +205,7 @@
     public void onlyH263SW()  { ex(H263(SW),  allTests); }
 
     public void bytebuffer() { ex(H264(SW), new EarlyEosTest().byteBuffer()); }
-    public void texture() { ex(H264(HW), new EarlyEosTest().texture()); }
+    public void onlyTexture() { ex(H264(HW), new EarlyEosTest().texture()); }
 
     /* inidividual tests */
     public void testH264_adaptiveEarlyEos()  { ex(H264(),  adaptiveEarlyEos); }
diff --git a/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp b/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp
index 37b434e..c57682f 100644
--- a/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp
+++ b/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp
@@ -57,6 +57,58 @@
 
 }
 
+
+// Test creating a default stream with specific devices
+void runtest_aaudio_devices(int32_t deviceId, bool expectFail) {
+    AAudioStreamBuilder *aaudioBuilder = nullptr;
+    AAudioStream *aaudioStream = nullptr;
+
+    // Use an AAudioStreamBuilder to define the stream.
+    aaudio_result_t result = AAudio_createStreamBuilder(&aaudioBuilder);
+    ASSERT_EQ(AAUDIO_OK, result);
+    ASSERT_NE(nullptr, aaudioBuilder);
+
+    AAudioStreamBuilder_setDeviceId(aaudioBuilder,deviceId);
+
+    // Create an AAudioStream using the Builder.
+    result = AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream);
+    if (expectFail) {
+        ASSERT_NE(AAUDIO_OK, result);
+        ASSERT_EQ(nullptr, aaudioStream);
+    } else {
+        // Pass or fail is OK. Just don't crash.
+        ASSERT_TRUE(((result < 0) && (aaudioStream == nullptr))
+                    || ((result == AAUDIO_OK) && (aaudioStream != nullptr)));
+    }
+
+    // Cleanup
+    EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(aaudioBuilder));
+    if (aaudioStream != nullptr) {
+        AAudioStream_close(aaudioStream);
+    }
+}
+
+TEST(test_aaudio, aaudio_stream_device_unspecified) {
+    runtest_aaudio_devices(AAUDIO_DEVICE_UNSPECIFIED, false);
+}
+
+/* FIXME - why can we open this device? What is an illegal deviceId?
+TEST(test_aaudio, aaudio_stream_device_absurd) {
+    runtest_aaudio_devices(19736459, true);
+}
+*/
+/* FIXME review
+TEST(test_aaudio, aaudio_stream_device_reasonable) {
+    runtest_aaudio_devices(1, false);
+}
+*/
+
+/* FIXME - why can we open this device? What is an illegal deviceId?
+TEST(test_aaudio, aaudio_stream_device_negative) {
+    runtest_aaudio_devices(-765, true);
+}
+*/
+
 // Test creating a default stream with everything unspecified.
 TEST(test_aaudio, aaudio_stream_unspecified) {
     AAudioStreamBuilder *aaudioBuilder = nullptr;
@@ -120,7 +172,12 @@
     AAudioStreamBuilder_setBufferCapacityInFrames(aaudioBuilder, 2000);
 
     // Create an AAudioStream using the Builder.
-    ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
+    result = AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream);
+    if (requestedSharingMode == AAUDIO_SHARING_MODE_EXCLUSIVE
+        && result != AAUDIO_OK) {
+        return; // EXCLUSIVE just may not be available. Should not crash.
+    }
+    ASSERT_EQ(AAUDIO_OK, result);
     EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(aaudioBuilder));
 
     EXPECT_EQ(AAUDIO_STREAM_STATE_OPEN, AAudioStream_getState(aaudioStream));
@@ -184,15 +241,14 @@
         // Write some data while we are running. Read counter should be advancing.
         writeLoops = 1 * actualSampleRate / framesPerBurst; // 1 second
         ASSERT_LT(2, writeLoops); // detect absurdly high framesPerBurst
-        timeoutNanos = 10 * NANOS_PER_SECOND * framesPerBurst / actualSampleRate; // bursts
+        timeoutNanos = 100 * (NANOS_PER_SECOND * framesPerBurst / actualSampleRate); // N bursts
         framesWritten = 1;
         aaudioFramesRead = AAudioStream_getFramesRead(aaudioStream);
         aaudioFramesRead1 = aaudioFramesRead;
         int64_t beginTime = getNanoseconds(CLOCK_MONOTONIC);
         do {
             framesWritten = AAudioStream_write(aaudioStream, data, framesPerBurst, timeoutNanos);
-            ASSERT_GE(framesWritten, 0);
-            ASSERT_LE(framesWritten, framesPerBurst);
+            ASSERT_EQ(framesWritten, framesPerBurst);
 
             framesTotal += framesWritten;
             aaudioFramesWritten = AAudioStream_getFramesWritten(aaudioStream);
@@ -211,8 +267,8 @@
         aaudioFramesRead2 = AAudioStream_getFramesRead(aaudioStream);
         int64_t endTime = getNanoseconds(CLOCK_MONOTONIC);
         ASSERT_GT(aaudioFramesRead2, 0);
-        ASSERT_GT(aaudioFramesRead2, aaudioFramesRead1);
-        ASSERT_LE(aaudioFramesRead2, aaudioFramesWritten);
+        EXPECT_GT(aaudioFramesRead2, aaudioFramesRead1);
+
 
         // TODO why is AudioTrack path so inaccurate?
         const double rateTolerance = 200.0; // arbitrary tolerance for sample rate
@@ -236,15 +292,16 @@
     aaudioFramesRead = AAudioStream_getFramesRead(aaudioStream);
     ASSERT_GE(aaudioFramesRead, aaudioFramesRead2); // monotonic increase
 
-    // Use this to sleep by waiting for something that won't happen.
-    AAudioStream_waitForStateChange(aaudioStream, AAUDIO_STREAM_STATE_PAUSED, &state, timeoutNanos);
+    // Use this to sleep by waiting for a state that won't happen.
+    timeoutNanos = 100 * NANOS_PER_MILLISECOND;
+    AAudioStream_waitForStateChange(aaudioStream, AAUDIO_STREAM_STATE_OPEN, &state, timeoutNanos);
     aaudioFramesRead2 = AAudioStream_getFramesRead(aaudioStream);
     EXPECT_EQ(aaudioFramesRead, aaudioFramesRead2);
 
     // ------------------- TEST FLUSH -----------------
     // Prime the buffer.
     timeoutNanos = 0;
-    writeLoops = 100;
+    writeLoops = 1000;
     do {
         framesWritten = AAudioStream_write(aaudioStream, data, framesPerBurst, timeoutNanos);
         framesTotal += framesWritten;
@@ -282,12 +339,10 @@
     runtest_aaudio_stream(AAUDIO_SHARING_MODE_SHARED);
 }
 
-/* TODO Enable exclusive mode test.
-// Test Writing to an AAudioStream using EXCLUSIVE sharing mode.
+// Test Writing to an AAudioStream using EXCLUSIVE sharing mode. It may fail gracefully.
 TEST(test_aaudio, aaudio_stream_exclusive) {
     runtest_aaudio_stream(AAUDIO_SHARING_MODE_EXCLUSIVE);
 }
-*/
 
 int main(int argc, char **argv) {
     testing::InitGoogleTest(&argc, argv);
diff --git a/tests/tests/nativemedia/aaudio/src/test_aaudio_callback.cpp b/tests/tests/nativemedia/aaudio/src/test_aaudio_callback.cpp
index 2ec1e1c..3786967 100644
--- a/tests/tests/nativemedia/aaudio/src/test_aaudio_callback.cpp
+++ b/tests/tests/nativemedia/aaudio/src/test_aaudio_callback.cpp
@@ -18,17 +18,55 @@
 #define LOG_TAG "AAudioTest"
 
 #include <gtest/gtest.h>
+#include <atomic>
 #include <utils/Log.h>
 
 #include <aaudio/AAudio.h>
 #include "test_aaudio.h"
 
 typedef struct AAudioCallbackTestData {
-    int32_t callbackCount;
     int32_t expectedFramesPerCallback;
     int32_t actualFramesPerCallback;
+    int32_t minLatency;
+    int32_t maxLatency;
+    std::atomic<aaudio_result_t> callbackError;
+    std::atomic<int32_t> callbackCount;
 } AAudioCallbackTestData;
 
+static int32_t measureLatency(AAudioStream *stream) {
+    int64_t presentationTime = 0;
+    int64_t presentationPosition = 0;
+    int64_t now = getNanoseconds();
+    int32_t sampleRate = AAudioStream_getSampleRate(stream);
+    int64_t framesWritten = AAudioStream_getFramesWritten(stream);
+    aaudio_result_t result = AAudioStream_getTimestamp(stream,
+                                                       CLOCK_MONOTONIC,
+                                                       &presentationPosition,
+                                                       &presentationTime);
+    if (result < 0) {
+        return result;
+    }
+    // Calculate when the last frame written would be played.
+    int64_t deltaFrames = framesWritten - presentationPosition;
+    EXPECT_GE(framesWritten, presentationPosition);
+    int64_t calculatedDeltaNanos = deltaFrames * NANOS_PER_SECOND / sampleRate;
+    int64_t calculatedTimeNanos = presentationTime +  calculatedDeltaNanos;
+    int64_t latencyNanos = calculatedTimeNanos - now;
+    int32_t latencyMillis = (int32_t) ((latencyNanos + NANOS_PER_MILLISECOND - 1)
+                            / NANOS_PER_MILLISECOND);
+    return latencyMillis;
+}
+
+static void MyErrorCallbackProc(
+        AAudioStream *stream,
+        void *userData,
+        aaudio_result_t error) {
+    (void) stream;
+    AAudioCallbackTestData *myData = (AAudioCallbackTestData *) userData;
+    myData->callbackError = error;
+
+}
+
 // Callback function that fills the audio output buffer.
 static aaudio_data_callback_result_t MyDataCallbackProc(
         AAudioStream *stream,
@@ -54,6 +92,17 @@
         float *floatData = (float *) audioData;
         for (int i = 0; i < numSamples; i++) *floatData++ = 0.0f;
     }
+
+    int32_t latency = measureLatency(stream);
+    if (latency > 0) {
+        if (latency < myData->minLatency) {
+            myData->minLatency = latency;
+        }
+        if (latency > myData->maxLatency) {
+            myData->maxLatency = latency;
+        }
+    }
+
     myData->callbackCount++;
     return AAUDIO_CALLBACK_RESULT_CONTINUE;
 }
@@ -61,7 +110,7 @@
 // Test Writing to an AAudioStream using a Callback
 void runtest_aaudio_callback(aaudio_sharing_mode_t requestedSharingMode,
                              int32_t framesPerDataCallback) {
-    AAudioCallbackTestData myTestData = { 0, 0, 0 };
+    AAudioCallbackTestData myTestData;
     const int32_t requestedSampleRate = 48000;
     const int32_t requestedSamplesPerFrame = 2;
     const aaudio_audio_format_t requestedDataFormat = AAUDIO_FORMAT_PCM_I16;
@@ -79,6 +128,10 @@
     AAudioStream *stream = nullptr;
 
     aaudio_result_t result = AAUDIO_OK;
+    myTestData.callbackCount.store(0);
+    myTestData.callbackError = AAUDIO_OK;
+    myTestData.actualFramesPerCallback = 0;
+    myTestData.expectedFramesPerCallback = 0;
 
     // Use an AAudioStreamBuilder to define the stream.
     result = AAudio_createStreamBuilder(&builder);
@@ -93,6 +146,7 @@
     AAudioStreamBuilder_setSharingMode(builder, requestedSharingMode);
     AAudioStreamBuilder_setBufferCapacityInFrames(builder, 2000);
 
+    AAudioStreamBuilder_setErrorCallback(builder, MyErrorCallbackProc, &myTestData);
     AAudioStreamBuilder_setDataCallback(builder, MyDataCallbackProc, &myTestData);
     if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
         AAudioStreamBuilder_setFramesPerDataCallback(builder, framesPerDataCallback);
@@ -118,8 +172,8 @@
 
     actualDataFormat = AAudioStream_getFormat(stream);
 
-    // TODO test this on full build
-    // ASSERT_NE(AAUDIO_DEVICE_UNSPECIFIED, AAudioStream_getDeviceId(stream));
+    // TODO Why does getDeviceId() always return 0?
+    // EXPECT_NE(AAUDIO_DEVICE_UNSPECIFIED, AAudioStream_getDeviceId(stream));
 
     framesPerBurst = AAudioStream_getFramesPerBurst(stream);
     ASSERT_TRUE(framesPerBurst >= 16 && framesPerBurst <= 1024); // TODO what is min/max?
@@ -136,18 +190,27 @@
     // Start/stop more than once to see if it fails after the first time.
     // Write some data and measure the rate to see if the timing is OK.
     for (int loopIndex = 0; loopIndex < 2; loopIndex++) {
+
         myTestData.callbackCount = 0;
+        myTestData.minLatency = INT32_MAX;
+        myTestData.maxLatency = 0;
+        myTestData.callbackCount.store(0);
+
         myTestData.expectedFramesPerCallback = actualFramesPerDataCallback;
 
         // Start and wait for server to respond.
         ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(stream));
+
         ASSERT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(stream,
                                                              AAUDIO_STREAM_STATE_STARTING,
                                                              &state,
                                                              DEFAULT_STATE_TIMEOUT));
         EXPECT_EQ(AAUDIO_STREAM_STATE_STARTED, state);
 
-        sleep(2);
+        sleep(2); // let the stream run
+
+        ASSERT_EQ(myTestData.callbackError.load(), AAUDIO_OK);
+        ASSERT_GT(myTestData.callbackCount.load(), 10);
 
         // For more coverage, alternate pausing and stopping.
         if ((loopIndex & 1) == 0) {
@@ -168,29 +231,34 @@
             EXPECT_EQ(AAUDIO_STREAM_STATE_STOPPED, state);
         }
 
-        int32_t oldCallbackCount = myTestData.callbackCount;
+        int32_t oldCallbackCount = myTestData.callbackCount.load();
         EXPECT_GT(oldCallbackCount, 10);
         sleep(1);
-        EXPECT_EQ(oldCallbackCount, myTestData.callbackCount); // expect not advancing
+        EXPECT_EQ(oldCallbackCount, myTestData.callbackCount.load()); // expect not advancing
 
         if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
             ASSERT_EQ(framesPerDataCallback, myTestData.actualFramesPerCallback);
         }
+
+        EXPECT_GE(myTestData.minLatency, 1);   // Absurdly low
+        EXPECT_LE(myTestData.maxLatency, 200); // Absurdly high, should be < 30
+        //printf("latency: %d, %d\n", myTestData.minLatency, myTestData.maxLatency);
     }
 
+    ASSERT_EQ(myTestData.callbackError.load(), AAUDIO_OK);
+
     EXPECT_EQ(AAUDIO_OK, AAudioStream_close(stream));
 }
 
 // Test Using an AAudioStream callback in SHARED mode.
-
 TEST(test_aaudio, aaudio_callback_shared_unspecified) {
-runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, AAUDIO_UNSPECIFIED);
+    runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, AAUDIO_UNSPECIFIED);
 }
 
 TEST(test_aaudio, aaudio_callback_shared_109) {
-runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, 109); // arbitrary prime number < 192
+    runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, 109); // arbitrary prime number < 192
 }
 
 TEST(test_aaudio, aaudio_callback_shared_223) {
-runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, 223); // arbitrary prime number > 192
+    runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, 223); // arbitrary prime number > 192
 }
diff --git a/tests/tests/nativemedia/aaudio/src/test_aaudio_misc.cpp b/tests/tests/nativemedia/aaudio/src/test_aaudio_misc.cpp
index 8599d48..6662b72 100644
--- a/tests/tests/nativemedia/aaudio/src/test_aaudio_misc.cpp
+++ b/tests/tests/nativemedia/aaudio/src/test_aaudio_misc.cpp
@@ -1,7 +1,7 @@
 /*
  * Copyright 2017 The Android Open Source Project
  *
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * Licensed under the Apache License, Version 2.0 (the "License", ENUM_CANNOT_CHANGE);
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
@@ -25,53 +25,55 @@
 // Make sure enums do not change value.
 TEST(test_aaudio_misc, aaudio_freeze_enums) {
 
-    ASSERT_EQ(0, AAUDIO_DIRECTION_OUTPUT);
-    ASSERT_EQ(1, AAUDIO_DIRECTION_INPUT);
+#define ENUM_CANNOT_CHANGE "enum in API cannot change"
 
-    ASSERT_EQ(-1, AAUDIO_FORMAT_INVALID);
-    ASSERT_EQ(0, AAUDIO_FORMAT_UNSPECIFIED);
-    ASSERT_EQ(1, AAUDIO_FORMAT_PCM_I16);
-    ASSERT_EQ(2, AAUDIO_FORMAT_PCM_FLOAT);
+    static_assert(0 == AAUDIO_DIRECTION_OUTPUT, ENUM_CANNOT_CHANGE);
+    static_assert(1 == AAUDIO_DIRECTION_INPUT, ENUM_CANNOT_CHANGE);
 
-    ASSERT_EQ(0, AAUDIO_OK);
-    ASSERT_EQ(-900, AAUDIO_ERROR_BASE);
-    ASSERT_EQ(-899, AAUDIO_ERROR_DISCONNECTED);
-    ASSERT_EQ(-898, AAUDIO_ERROR_ILLEGAL_ARGUMENT);
-    ASSERT_EQ(-897, AAUDIO_ERROR_INCOMPATIBLE);
-    ASSERT_EQ(-896, AAUDIO_ERROR_INTERNAL);
-    ASSERT_EQ(-895, AAUDIO_ERROR_INVALID_STATE);
-    ASSERT_EQ(-894, AAUDIO_ERROR_UNEXPECTED_STATE);
-    ASSERT_EQ(-893, AAUDIO_ERROR_UNEXPECTED_VALUE);
-    ASSERT_EQ(-892, AAUDIO_ERROR_INVALID_HANDLE);
-    ASSERT_EQ(-891, AAUDIO_ERROR_INVALID_QUERY);
-    ASSERT_EQ(-890, AAUDIO_ERROR_UNIMPLEMENTED);
-    ASSERT_EQ(-889, AAUDIO_ERROR_UNAVAILABLE);
-    ASSERT_EQ(-888, AAUDIO_ERROR_NO_FREE_HANDLES);
-    ASSERT_EQ(-887, AAUDIO_ERROR_NO_MEMORY);
-    ASSERT_EQ(-886, AAUDIO_ERROR_NULL);
-    ASSERT_EQ(-885, AAUDIO_ERROR_TIMEOUT);
-    ASSERT_EQ(-884, AAUDIO_ERROR_WOULD_BLOCK);
-    ASSERT_EQ(-883, AAUDIO_ERROR_INVALID_FORMAT);
-    ASSERT_EQ(-882, AAUDIO_ERROR_OUT_OF_RANGE);
-    ASSERT_EQ(-881, AAUDIO_ERROR_NO_SERVICE);
+    static_assert(-1 == AAUDIO_FORMAT_INVALID, ENUM_CANNOT_CHANGE);
+    static_assert(0 == AAUDIO_FORMAT_UNSPECIFIED, ENUM_CANNOT_CHANGE);
+    static_assert(1 == AAUDIO_FORMAT_PCM_I16, ENUM_CANNOT_CHANGE);
+    static_assert(2 == AAUDIO_FORMAT_PCM_FLOAT, ENUM_CANNOT_CHANGE);
 
-    ASSERT_EQ(0, AAUDIO_STREAM_STATE_UNINITIALIZED);
-    ASSERT_EQ(1, AAUDIO_STREAM_STATE_UNKNOWN);
-    ASSERT_EQ(2, AAUDIO_STREAM_STATE_OPEN);
-    ASSERT_EQ(3, AAUDIO_STREAM_STATE_STARTING);
-    ASSERT_EQ(4, AAUDIO_STREAM_STATE_STARTED);
-    ASSERT_EQ(5, AAUDIO_STREAM_STATE_PAUSING);
-    ASSERT_EQ(6, AAUDIO_STREAM_STATE_PAUSED);
-    ASSERT_EQ(7, AAUDIO_STREAM_STATE_FLUSHING);
-    ASSERT_EQ(8, AAUDIO_STREAM_STATE_FLUSHED);
-    ASSERT_EQ(9, AAUDIO_STREAM_STATE_STOPPING);
-    ASSERT_EQ(10, AAUDIO_STREAM_STATE_STOPPED);
-    ASSERT_EQ(11, AAUDIO_STREAM_STATE_CLOSING);
-    ASSERT_EQ(12, AAUDIO_STREAM_STATE_CLOSED);
+    static_assert(0 == AAUDIO_OK, ENUM_CANNOT_CHANGE);
+    static_assert(-900 == AAUDIO_ERROR_BASE, ENUM_CANNOT_CHANGE);
+    static_assert(-899 == AAUDIO_ERROR_DISCONNECTED, ENUM_CANNOT_CHANGE);
+    static_assert(-898 == AAUDIO_ERROR_ILLEGAL_ARGUMENT, ENUM_CANNOT_CHANGE);
+    static_assert(-897 == AAUDIO_ERROR_INCOMPATIBLE, ENUM_CANNOT_CHANGE);
+    static_assert(-896 == AAUDIO_ERROR_INTERNAL, ENUM_CANNOT_CHANGE);
+    static_assert(-895 == AAUDIO_ERROR_INVALID_STATE, ENUM_CANNOT_CHANGE);
+    static_assert(-894 == AAUDIO_ERROR_UNEXPECTED_STATE, ENUM_CANNOT_CHANGE);
+    static_assert(-893 == AAUDIO_ERROR_UNEXPECTED_VALUE, ENUM_CANNOT_CHANGE);
+    static_assert(-892 == AAUDIO_ERROR_INVALID_HANDLE, ENUM_CANNOT_CHANGE);
+    static_assert(-891 == AAUDIO_ERROR_INVALID_QUERY, ENUM_CANNOT_CHANGE);
+    static_assert(-890 == AAUDIO_ERROR_UNIMPLEMENTED, ENUM_CANNOT_CHANGE);
+    static_assert(-889 == AAUDIO_ERROR_UNAVAILABLE, ENUM_CANNOT_CHANGE);
+    static_assert(-888 == AAUDIO_ERROR_NO_FREE_HANDLES, ENUM_CANNOT_CHANGE);
+    static_assert(-887 == AAUDIO_ERROR_NO_MEMORY, ENUM_CANNOT_CHANGE);
+    static_assert(-886 == AAUDIO_ERROR_NULL, ENUM_CANNOT_CHANGE);
+    static_assert(-885 == AAUDIO_ERROR_TIMEOUT, ENUM_CANNOT_CHANGE);
+    static_assert(-884 == AAUDIO_ERROR_WOULD_BLOCK, ENUM_CANNOT_CHANGE);
+    static_assert(-883 == AAUDIO_ERROR_INVALID_FORMAT, ENUM_CANNOT_CHANGE);
+    static_assert(-882 == AAUDIO_ERROR_OUT_OF_RANGE, ENUM_CANNOT_CHANGE);
+    static_assert(-881 == AAUDIO_ERROR_NO_SERVICE, ENUM_CANNOT_CHANGE);
 
-    ASSERT_EQ(0, AAUDIO_SHARING_MODE_EXCLUSIVE);
-    ASSERT_EQ(1, AAUDIO_SHARING_MODE_SHARED);
+    static_assert(0 == AAUDIO_STREAM_STATE_UNINITIALIZED, ENUM_CANNOT_CHANGE);
+    static_assert(1 == AAUDIO_STREAM_STATE_UNKNOWN, ENUM_CANNOT_CHANGE);
+    static_assert(2 == AAUDIO_STREAM_STATE_OPEN, ENUM_CANNOT_CHANGE);
+    static_assert(3 == AAUDIO_STREAM_STATE_STARTING, ENUM_CANNOT_CHANGE);
+    static_assert(4 == AAUDIO_STREAM_STATE_STARTED, ENUM_CANNOT_CHANGE);
+    static_assert(5 == AAUDIO_STREAM_STATE_PAUSING, ENUM_CANNOT_CHANGE);
+    static_assert(6 == AAUDIO_STREAM_STATE_PAUSED, ENUM_CANNOT_CHANGE);
+    static_assert(7 == AAUDIO_STREAM_STATE_FLUSHING, ENUM_CANNOT_CHANGE);
+    static_assert(8 == AAUDIO_STREAM_STATE_FLUSHED, ENUM_CANNOT_CHANGE);
+    static_assert(9 == AAUDIO_STREAM_STATE_STOPPING, ENUM_CANNOT_CHANGE);
+    static_assert(10 == AAUDIO_STREAM_STATE_STOPPED, ENUM_CANNOT_CHANGE);
+    static_assert(11 == AAUDIO_STREAM_STATE_CLOSING, ENUM_CANNOT_CHANGE);
+    static_assert(12 == AAUDIO_STREAM_STATE_CLOSED, ENUM_CANNOT_CHANGE);
 
-    ASSERT_EQ(0, AAUDIO_CALLBACK_RESULT_CONTINUE);
-    ASSERT_EQ(1, AAUDIO_CALLBACK_RESULT_STOP);
+    static_assert(0 == AAUDIO_SHARING_MODE_EXCLUSIVE, ENUM_CANNOT_CHANGE);
+    static_assert(1 == AAUDIO_SHARING_MODE_SHARED, ENUM_CANNOT_CHANGE);
+
+    static_assert(0 == AAUDIO_CALLBACK_RESULT_CONTINUE, ENUM_CANNOT_CHANGE);
+    static_assert(1 == AAUDIO_CALLBACK_RESULT_STOP, ENUM_CANNOT_CHANGE);
 }
diff --git a/tests/tests/os/src/android/os/cts/AsyncTaskTest.java b/tests/tests/os/src/android/os/cts/AsyncTaskTest.java
index 335818a..1c2f91e 100644
--- a/tests/tests/os/src/android/os/cts/AsyncTaskTest.java
+++ b/tests/tests/os/src/android/os/cts/AsyncTaskTest.java
@@ -201,7 +201,7 @@
                 try {
                     command.run();
                     fail("Exception not thrown");
-                } catch (Throwable tr) {
+                } catch (Exception tr) {
                     // expected
                 }
             }
diff --git a/tests/tests/os/src/android/os/cts/LooperTest.java b/tests/tests/os/src/android/os/cts/LooperTest.java
index c0a176c..b89f590 100644
--- a/tests/tests/os/src/android/os/cts/LooperTest.java
+++ b/tests/tests/os/src/android/os/cts/LooperTest.java
@@ -97,11 +97,15 @@
     public void testMyQueue() throws Throwable {
         TestThread t = new TestThread(new Runnable() {
             public void run() {
+                boolean didThrow = false;
                 try {
                     assertNull(Looper.myQueue());
-                    fail("should throw exception");
                 } catch (Throwable e) {
                     // expected
+                    didThrow = true;
+                }
+                if (!didThrow) {
+                    fail("should throw exception");
                 }
                 Looper.prepare();
                 MessageQueue mq = Looper.myQueue();
@@ -132,7 +136,7 @@
                 try {
                     Looper.prepare();
                     fail("should throw exception");
-                } catch (Throwable e) {
+                } catch (Exception e) {
                     //expected
                 }
             }
@@ -147,7 +151,7 @@
                 try {
                     Looper.prepareMainLooper();
                     fail("should throw exception because the main thread was already prepared");
-                } catch (Throwable e) {
+                } catch (Exception e) {
                     //expected
                 }
             }
diff --git a/tests/tests/telecom/AndroidManifest.xml b/tests/tests/telecom/AndroidManifest.xml
index 6dcd6ca..f0cad67 100644
--- a/tests/tests/telecom/AndroidManifest.xml
+++ b/tests/tests/telecom/AndroidManifest.xml
@@ -74,6 +74,13 @@
             </intent-filter>
         </receiver>
 
+        <receiver android:name="android.telecom.cts.MockPhoneAccountChangedReceiver">
+            <intent-filter>
+                <action android:name="android.telecom.action.PHONE_ACCOUNT_REGISTERED"/>
+                <action android:name="android.telecom.action.PHONE_ACCOUNT_UNREGISTERED"/>
+            </intent-filter>
+        </receiver>
+
         <activity android:name="android.telecom.cts.MockDialerActivity">
             <intent-filter>
                 <action android:name="android.intent.action.DIAL" />
diff --git a/tests/tests/telecom/src/android/telecom/cts/MockPhoneAccountChangedReceiver.java b/tests/tests/telecom/src/android/telecom/cts/MockPhoneAccountChangedReceiver.java
new file mode 100644
index 0000000..0601d75
--- /dev/null
+++ b/tests/tests/telecom/src/android/telecom/cts/MockPhoneAccountChangedReceiver.java
@@ -0,0 +1,54 @@
+/*
+ * 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.telecom.cts;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
+
+/**
+ * Receives {@link android.telecom.TelecomManager#ACTION_PHONE_ACCOUNT_REGISTERED} and
+ * {@link android.telecom.TelecomManager#ACTION_PHONE_ACCOUNT_UNREGISTERED} intents.
+ */
+public class MockPhoneAccountChangedReceiver extends BroadcastReceiver {
+    public interface IntentListener {
+        void onPhoneAccountRegistered(PhoneAccountHandle handle);
+        void onPhoneAccountUnregistered(PhoneAccountHandle handle);
+    }
+
+    private static IntentListener sIntentListener = null;
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (sIntentListener != null) {
+            if (TelecomManager.ACTION_PHONE_ACCOUNT_REGISTERED.equals(intent.getAction())) {
+                sIntentListener.onPhoneAccountRegistered(intent.getParcelableExtra(
+                        TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE));
+            } else if (TelecomManager.ACTION_PHONE_ACCOUNT_UNREGISTERED.equals(
+                    intent.getAction())) {
+                sIntentListener.onPhoneAccountUnregistered(intent.getParcelableExtra(
+                        TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE));
+            }
+        }
+    }
+
+    public static void setIntentListener(IntentListener listener) {
+        sIntentListener = listener;
+    }
+}
diff --git a/tests/tests/telecom/src/android/telecom/cts/PhoneAccountOperationsTest.java b/tests/tests/telecom/src/android/telecom/cts/PhoneAccountOperationsTest.java
index 4374516..c9b5000 100644
--- a/tests/tests/telecom/src/android/telecom/cts/PhoneAccountOperationsTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/PhoneAccountOperationsTest.java
@@ -43,6 +43,22 @@
     public static final int TEST_LENGTH = 10;
     public static final String TEST_ENCODING = "enUS";
 
+    private TestUtils.InvokeCounter mPhoneAccountRegisteredLatch;
+    private TestUtils.InvokeCounter mPhoneAccountUnRegisteredLatch;
+
+    MockPhoneAccountChangedReceiver.IntentListener mPhoneAccountIntentListener =
+            new MockPhoneAccountChangedReceiver.IntentListener() {
+                @Override
+                public void onPhoneAccountRegistered(PhoneAccountHandle handle) {
+                    mPhoneAccountRegisteredLatch.invoke(handle);
+                }
+
+                @Override
+                public void onPhoneAccountUnregistered(PhoneAccountHandle handle) {
+                    mPhoneAccountUnRegisteredLatch.invoke(handle);
+                }
+            };
+
     private static Bundle createTestBundle() {
         Bundle testBundle = new Bundle();
         testBundle.putInt(PhoneAccount.EXTRA_CALL_SUBJECT_MAX_LENGTH, TEST_LENGTH);
@@ -96,6 +112,8 @@
             return;
         }
         mTelecomManager = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
+        mPhoneAccountRegisteredLatch = new TestUtils.InvokeCounter("registerPhoneAcct");
+        mPhoneAccountUnRegisteredLatch = new TestUtils.InvokeCounter("unRegisterPhoneAcct");
     }
 
     @Override
@@ -225,4 +243,38 @@
         assertTrue("Phone account should support voicemail URI scheme.",
                 retrievedPhoneAccount.supportsUriScheme(PhoneAccount.SCHEME_VOICEMAIL));
     }
+
+    /**
+     * Verifies that the {@link TelecomManager#ACTION_PHONE_ACCOUNT_REGISTERED} intent is sent to
+     * the default dialer when a phone account is registered and,
+     * {@link TelecomManager#ACTION_PHONE_ACCOUNT_UNREGISTERED} is sent when a phone account is
+     * unregistered.
+     * @throws Exception
+     */
+    public void testRegisterUnregisterPhoneAccountIntent() throws Exception {
+        if (!shouldTestTelecom(mContext)) {
+            return;
+        }
+
+        MockPhoneAccountChangedReceiver.setIntentListener(mPhoneAccountIntentListener);
+        String previousDefaultDialer = TestUtils.getDefaultDialer(getInstrumentation());
+        try {
+            TestUtils.setDefaultDialer(getInstrumentation(), TestUtils.PACKAGE);
+
+            mTelecomManager.registerPhoneAccount(TEST_NO_SIM_PHONE_ACCOUNT);
+
+            mPhoneAccountRegisteredLatch.waitForCount(1);
+            PhoneAccountHandle handle =
+                    (PhoneAccountHandle) mPhoneAccountRegisteredLatch.getArgs(0)[0];
+            assertEquals(TEST_PHONE_ACCOUNT_HANDLE, handle);
+
+            mTelecomManager.unregisterPhoneAccount(TEST_PHONE_ACCOUNT_HANDLE);
+            mPhoneAccountUnRegisteredLatch.waitForCount(1);
+            PhoneAccountHandle handle2 =
+                    (PhoneAccountHandle) mPhoneAccountUnRegisteredLatch.getArgs(0)[0];
+            assertEquals(TEST_PHONE_ACCOUNT_HANDLE, handle2);
+        } finally {
+            TestUtils.setDefaultDialer(getInstrumentation(), previousDefaultDialer);
+        }
+    }
 }
diff --git a/tests/tests/text/src/android/text/format/cts/FormatterTest.java b/tests/tests/text/src/android/text/format/cts/FormatterTest.java
index fa11023..8c7fdc9 100644
--- a/tests/tests/text/src/android/text/format/cts/FormatterTest.java
+++ b/tests/tests/text/src/android/text/format/cts/FormatterTest.java
@@ -19,6 +19,8 @@
 import static org.junit.Assert.assertEquals;
 
 import android.content.Context;
+import android.content.res.Configuration;
+import android.os.LocaleList;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -29,6 +31,7 @@
 
 import java.math.BigDecimal;
 import java.math.MathContext;
+import java.util.Locale;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -38,9 +41,12 @@
         // test null Context
         assertEquals("", Formatter.formatFileSize(null, 0));
 
-        MathContext mc = MathContext.DECIMAL64;
-        BigDecimal bd = new BigDecimal((long) 1000, mc);
-        Context context = InstrumentationRegistry.getTargetContext();
+        final MathContext mc = MathContext.DECIMAL64;
+        final BigDecimal bd = new BigDecimal((long) 1000, mc);
+        final Configuration config = new Configuration();
+        config.setLocales(new LocaleList(Locale.US));
+        final Context context =
+                InstrumentationRegistry.getTargetContext().createConfigurationContext(config);
 
         // test different long values with various length
         assertEquals("0 B", Formatter.formatFileSize(context, 0));
@@ -53,6 +59,8 @@
         assertEquals("0.90 kB", Formatter.formatFileSize(context, 901));
 
         assertEquals("1.00 kB", Formatter.formatFileSize(context, bd.pow(1).longValue()));
+        assertEquals("1.50 kB", Formatter.formatFileSize(context, bd.pow(1).longValue() * 3 / 2));
+        assertEquals("12.50 kB", Formatter.formatFileSize(context, bd.pow(1).longValue() * 25 / 2));
 
         assertEquals("1.00 MB", Formatter.formatFileSize(context, bd.pow(2).longValue()));
 
@@ -69,6 +77,48 @@
     }
 
     @Test
+    public void testFormatShortFileSize() {
+        // test null Context
+        assertEquals("", Formatter.formatFileSize(null, 0));
+
+        final MathContext mc = MathContext.DECIMAL64;
+        final BigDecimal bd = new BigDecimal((long) 1000, mc);
+        final Configuration config = new Configuration();
+        config.setLocales(new LocaleList(Locale.US));
+        final Context context =
+                InstrumentationRegistry.getTargetContext().createConfigurationContext(config);
+
+        // test different long values with various length
+        assertEquals("0 B", Formatter.formatShortFileSize(context, 0));
+        assertEquals("1 B", Formatter.formatShortFileSize(context, 1));
+        assertEquals("9 B", Formatter.formatShortFileSize(context, 9));
+        assertEquals("10 B", Formatter.formatShortFileSize(context, 10));
+        assertEquals("99 B", Formatter.formatShortFileSize(context, 99));
+        assertEquals("100 B", Formatter.formatShortFileSize(context, 100));
+        assertEquals("900 B", Formatter.formatShortFileSize(context, 900));
+        assertEquals("0.90 kB", Formatter.formatShortFileSize(context, 901));
+
+        assertEquals("1.0 kB", Formatter.formatShortFileSize(context, bd.pow(1).longValue()));
+        assertEquals("1.5 kB", Formatter.formatShortFileSize(context,
+                bd.pow(1).longValue() * 3 / 2));
+        assertEquals("13 kB", Formatter.formatShortFileSize(context,
+                bd.pow(1).longValue() * 25 / 2));
+
+        assertEquals("1.0 MB", Formatter.formatShortFileSize(context, bd.pow(2).longValue()));
+
+        assertEquals("1.0 GB", Formatter.formatShortFileSize(context, bd.pow(3).longValue()));
+
+        assertEquals("1.0 TB", Formatter.formatShortFileSize(context, bd.pow(4).longValue()));
+
+        assertEquals("1.0 PB", Formatter.formatShortFileSize(context, bd.pow(5).longValue()));
+
+        assertEquals("1000 PB", Formatter.formatShortFileSize(context, bd.pow(6).longValue()));
+
+        // test Negative value
+        assertEquals("-1 B", Formatter.formatShortFileSize(context, -1));
+    }
+
+    @Test
     public void testFormatIpAddress() {
         assertEquals("1.0.168.192", Formatter.formatIpAddress(0xC0A80001));
         assertEquals("1.0.0.127", Formatter.formatIpAddress(0x7F000001));
diff --git a/tests/tests/text/src/android/text/format/cts/TimeTest.java b/tests/tests/text/src/android/text/format/cts/TimeTest.java
index 7c44c77..e085a29 100644
--- a/tests/tests/text/src/android/text/format/cts/TimeTest.java
+++ b/tests/tests/text/src/android/text/format/cts/TimeTest.java
@@ -1995,6 +1995,54 @@
     }
 
     @Test
+    public void testGetJulianMondayFromWeeksSinceEpoch() {
+        final int mondayBeforeEpoch = Time.MONDAY_BEFORE_JULIAN_EPOCH;
+        assertEquals(mondayBeforeEpoch, Time.getJulianMondayFromWeeksSinceEpoch(0));
+        assertEquals(mondayBeforeEpoch + 7, Time.getJulianMondayFromWeeksSinceEpoch(1));
+        assertEquals(mondayBeforeEpoch + 14, Time.getJulianMondayFromWeeksSinceEpoch(2));
+        assertEquals(mondayBeforeEpoch - 7, Time.getJulianMondayFromWeeksSinceEpoch(-1));
+    }
+
+    @Test
+    public void testGetWeeksSinceEpochFromJulianDay() {
+        final int epoch = Time.EPOCH_JULIAN_DAY;  // a Thursday
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epoch, Time.SUNDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epoch, Time.MONDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epoch, Time.TUESDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epoch, Time.WEDNESDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epoch, Time.THURSDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epoch, Time.FRIDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epoch, Time.SATURDAY));
+
+        final int epochFriday = epoch + 1;
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epochFriday, Time.SUNDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epochFriday, Time.MONDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epochFriday, Time.TUESDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epochFriday, Time.WEDNESDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epochFriday, Time.THURSDAY));
+        assertEquals(1, Time.getWeeksSinceEpochFromJulianDay(epochFriday, Time.FRIDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epochFriday, Time.SATURDAY));
+
+        final int epochSaturday = epoch + 2;
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epochSaturday, Time.SUNDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epochSaturday, Time.MONDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epochSaturday, Time.TUESDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epochSaturday, Time.WEDNESDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epochSaturday, Time.THURSDAY));
+        assertEquals(1, Time.getWeeksSinceEpochFromJulianDay(epochSaturday, Time.FRIDAY));
+        assertEquals(1, Time.getWeeksSinceEpochFromJulianDay(epochSaturday, Time.SATURDAY));
+
+        final int tenWeeksLater = epochSaturday + 10 * 7;
+        assertEquals(10, Time.getWeeksSinceEpochFromJulianDay(tenWeeksLater, Time.SUNDAY));
+        assertEquals(10, Time.getWeeksSinceEpochFromJulianDay(tenWeeksLater, Time.MONDAY));
+        assertEquals(10, Time.getWeeksSinceEpochFromJulianDay(tenWeeksLater, Time.TUESDAY));
+        assertEquals(10, Time.getWeeksSinceEpochFromJulianDay(tenWeeksLater, Time.WEDNESDAY));
+        assertEquals(10, Time.getWeeksSinceEpochFromJulianDay(tenWeeksLater, Time.THURSDAY));
+        assertEquals(11, Time.getWeeksSinceEpochFromJulianDay(tenWeeksLater, Time.FRIDAY));
+        assertEquals(11, Time.getWeeksSinceEpochFromJulianDay(tenWeeksLater, Time.SATURDAY));
+    }
+
+    @Test
     public void testNormalize_utc() {
         Time t = new Time(Time.TIMEZONE_UTC);
         Time expected = new Time(Time.TIMEZONE_UTC);
diff --git a/tests/tests/uirendering/res/drawable-nodpi/pathclippingtest_torus.png b/tests/tests/uirendering/res/drawable-nodpi/pathclippingtest_torus.png
new file mode 100644
index 0000000..76dcbc5
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable-nodpi/pathclippingtest_torus.png
Binary files differ
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java
index ae4fee1..d78972f 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java
@@ -29,6 +29,7 @@
 import android.support.test.runner.AndroidJUnit4;
 import android.uirendering.cts.R;
 import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
+import android.uirendering.cts.bitmapverifiers.GoldenImageVerifier;
 import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
 import android.uirendering.cts.testinfrastructure.CanvasClient;
@@ -71,18 +72,38 @@
         canvas.restore();
     };
 
+    // draw circle with hole in it, by path operations + path clipping
+    static final CanvasClient sTorusClipOutCanvasClient = (canvas, width, height) -> {
+        canvas.save();
+
+        Path path1 = new Path();
+        path1.addCircle(30, 30, 50, Path.Direction.CW);
+
+        Path path2 = new Path();
+        path2.addCircle(30, 30, 30, Path.Direction.CW);
+
+        canvas.clipPath(path1);
+        canvas.clipOutPath(path2);
+        canvas.drawColor(Color.BLUE);
+
+        canvas.restore();
+    };
+
     @Test
     public void testCircleWithCircle() {
         createTest()
                 .addCanvasClient("TorusDraw", sTorusDrawCanvasClient, false)
                 .addCanvasClient("TorusClip", sTorusClipCanvasClient)
-                .runWithComparer(new MSSIMComparer(0.90));
+                .addCanvasClient("TorusClipOut", sTorusClipOutCanvasClient)
+                .runWithVerifier(new GoldenImageVerifier(getActivity(),
+                        R.drawable.pathclippingtest_torus, new MSSIMComparer(0.95)));
     }
 
     @Test
     public void testCircleWithPoints() {
         createTest()
                 .addCanvasClient("TorusClip", sTorusClipCanvasClient)
+                .addCanvasClient("TorusClipOut", sTorusClipOutCanvasClient)
                 .runWithVerifier(new SamplePointVerifier(
                         new Point[] {
                                 // inside of circle
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
index 94c981f..d6a196a 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
@@ -127,6 +127,7 @@
                     TEST_WIDTH, TEST_HEIGHT, Config.ARGB_8888);
             Rect srcRect = new Rect(testOffset.x, testOffset.y,
                     testOffset.x + TEST_WIDTH, testOffset.y + TEST_HEIGHT);
+            Log.d("UiRendering", "capturing screenshot of " + srcRect.toShortString());
             int copyResult = copy.request(getActivity().getWindow(), srcRect, dest);
             Assert.assertEquals(PixelCopy.SUCCESS, copyResult);
             return dest;
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java
index 3b57af2..2b8f3b3 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java
@@ -209,6 +209,7 @@
         @Override
         public void onDraw() {
             mView.post(() -> {
+                Log.d("UiRendering", "notifying capture");
                 mView.getViewTreeObserver().removeOnDrawListener(this);
                 synchronized (mLock) {
                     mViewWrapper.getLocationOnScreen(mLocationOnScreen);
diff --git a/tests/tests/view/src/android/view/cts/FocusFinderTest.java b/tests/tests/view/src/android/view/cts/FocusFinderTest.java
index 8d56087..a8015ab 100644
--- a/tests/tests/view/src/android/view/cts/FocusFinderTest.java
+++ b/tests/tests/view/src/android/view/cts/FocusFinderTest.java
@@ -18,6 +18,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
 import android.graphics.Rect;
@@ -244,6 +245,19 @@
         assertTrue(nextFocus == mBottomRight || nextFocus == mBottomLeft);
     }
 
+    @Test
+    public void testChainVisibility() {
+        mBottomRight.setNextFocusForwardId(mBottomLeft.getId());
+        mBottomLeft.setNextFocusForwardId(mTopRight.getId());
+        mBottomLeft.setVisibility(View.INVISIBLE);
+        View next = mFocusFinder.findNextFocus(mLayout, mBottomRight, View.FOCUS_FORWARD);
+        assertSame(mTopRight, next);
+
+        mBottomLeft.setNextFocusForwardId(View.NO_ID);
+        next = mFocusFinder.findNextFocus(mLayout, mBottomRight, View.FOCUS_FORWARD);
+        assertSame(mTopLeft, next);
+    }
+
     private void verifyNextCluster(View currentCluster, int direction, View expectedNextCluster) {
         View actualNextCluster = mFocusFinder.findNextKeyboardNavigationCluster(
                 mLayout, currentCluster, direction);
diff --git a/tests/tests/view/src/android/view/cts/InputDeviceEnabledTest.java b/tests/tests/view/src/android/view/cts/InputDeviceEnabledTest.java
new file mode 100644
index 0000000..9a960e2
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/InputDeviceEnabledTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.view.cts;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import android.app.Instrumentation;
+import android.hardware.input.InputManager;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.InputDevice;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test {@link android.view.InputDevice} enable/disable functionality.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class InputDeviceEnabledTest {
+    private InputManager mInputManager;
+    private Instrumentation mInstrumentation;
+
+    @Before
+    public void setup() {
+        mInstrumentation = InstrumentationRegistry.getInstrumentation();
+        mInputManager = mInstrumentation.getTargetContext().getSystemService(InputManager.class);
+        assertNotNull(mInputManager);
+    }
+
+    @Test
+    public void testIsEnabled() {
+        final int[] inputDeviceIds = mInputManager.getInputDeviceIds();
+        assertNotNull(inputDeviceIds);
+        for (int inputDeviceId : inputDeviceIds) {
+            final InputDevice inputDevice = mInputManager.getInputDevice(inputDeviceId);
+            // this function call should not produce an error
+            inputDevice.isEnabled(); // output is not checked
+        }
+    }
+
+    @Test
+    public void testEnableDisableException() {
+        // Check that InputDevice.enable() and InputDevice.disable() throw SecurityException
+        final String failMsgNotThrown = "Expected SecurityException not thrown";
+
+        final int[] inputDeviceIds = mInputManager.getInputDeviceIds();
+        for (int inputDeviceId : inputDeviceIds) {
+            final InputDevice inputDevice = mInputManager.getInputDevice(inputDeviceId);
+
+            try {
+                inputDevice.enable();
+                fail(failMsgNotThrown);
+            } catch (SecurityException e) {
+                // Expect to get this exception
+            }
+
+            try {
+                inputDevice.disable();
+                fail(failMsgNotThrown);
+            } catch (SecurityException e) {
+                // Expect to get this exception
+            }
+        }
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/ListViewTest.java b/tests/tests/widget/src/android/widget/cts/ListViewTest.java
index 4b1e6bb..8cd85b1 100644
--- a/tests/tests/widget/src/android/widget/cts/ListViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ListViewTest.java
@@ -348,6 +348,8 @@
     public void testAccessHeaderView() {
         final TextView headerView1 = (TextView) mActivity.findViewById(R.id.headerview1);
         final TextView headerView2 = (TextView) mActivity.findViewById(R.id.headerview2);
+        ((ViewGroup) headerView1.getParent()).removeView(headerView1);
+        ((ViewGroup) headerView2.getParent()).removeView(headerView2);
 
         mListView.setHeaderDividersEnabled(true);
         assertTrue(mListView.areHeaderDividersEnabled());
@@ -574,6 +576,7 @@
     public void testFindViewTraversal() {
         MyListView listView = new MyListView(mActivity, mAttributeSet);
         TextView headerView = (TextView) mActivity.findViewById(R.id.headerview1);
+        ((ViewGroup) headerView.getParent()).removeView(headerView);
 
         assertNull(listView.findViewTraversal(R.id.headerview1));
 
@@ -587,6 +590,7 @@
     public void testFindViewWithTagTraversal() {
         MyListView listView = new MyListView(mActivity, mAttributeSet);
         TextView headerView = (TextView) mActivity.findViewById(R.id.headerview1);
+        ((ViewGroup) headerView.getParent()).removeView(headerView);
 
         assertNull(listView.findViewWithTagTraversal("header"));
 
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index a70fd54..b40b2f1 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -162,7 +162,6 @@
 
 import java.io.IOException;
 import java.lang.annotation.Retention;
-import java.util.Arrays;
 import java.util.Locale;
 
 /**
@@ -2809,12 +2808,18 @@
         mInstrumentation.waitForIdleSync();
         assertTrue(mTextView.isFocused());
 
-        // Arrows should not cause focus to leave the textfield
+        // Pure-keyboard arrows should not cause focus to leave the textfield
         CtsKeyEventUtil.sendKeyDownUp(mInstrumentation, mTextView, KeyEvent.KEYCODE_DPAD_UP);
         mInstrumentation.waitForIdleSync();
         assertTrue(mTextView.isFocused());
 
-        CtsKeyEventUtil.sendKeyDownUp(mInstrumentation, mTextView, KeyEvent.KEYCODE_DPAD_DOWN);
+        // Non-pure-keyboard arrows, however, should.
+        int dpadRemote = InputDevice.SOURCE_DPAD | InputDevice.SOURCE_KEYBOARD;
+        sendSourceKeyDownUp(mInstrumentation, mTextView, KeyEvent.KEYCODE_DPAD_UP, dpadRemote);
+        mInstrumentation.waitForIdleSync();
+        assertFalse(mTextView.isFocused());
+
+        sendSourceKeyDownUp(mInstrumentation, mTextView, KeyEvent.KEYCODE_DPAD_DOWN, dpadRemote);
         mInstrumentation.waitForIdleSync();
         assertTrue(mTextView.isFocused());
 
@@ -2824,6 +2829,16 @@
         assertFalse(mTextView.isFocused());
     }
 
+    private void sendSourceKeyDownUp(Instrumentation instrumentation, View targetView, int key,
+            int source) {
+        KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, key);
+        event.setSource(source);
+        CtsKeyEventUtil.sendKey(instrumentation, targetView, event);
+        event = new KeyEvent(KeyEvent.ACTION_UP, key);
+        event.setSource(source);
+        CtsKeyEventUtil.sendKey(instrumentation, targetView, event);
+    }
+
     @Test
     public void testSetIncludeFontPadding() throws Throwable {
         mTextView = findTextView(R.id.textview_text);
@@ -3537,6 +3552,7 @@
     public void testGetOffsetForPositionSingleLineLtr() throws Throwable {
         // asserts getOffsetPosition returns correct values for a single line LTR text
         final String text = "aaaaa";
+
         mActivityRule.runOnUiThread(() -> {
             mTextView = new TextView(mActivity);
             mTextView.setText(text);
@@ -3560,17 +3576,21 @@
         mActivityRule.runOnUiThread(() -> mActivity.setContentView(layout));
         mInstrumentation.waitForIdleSync();
 
+        final float halfCharWidth = (float) Math.ceil(mTextView.getPaint().measureText("a") / 2f);
+        final int paddingTop = mTextView.getTotalPaddingTop();
+        final int paddingLeft = mTextView.getTotalPaddingLeft();
+
         final int firstOffset = 0;
         final int lastOffset = text.length() - 1;
         final int midOffset = text.length() / 2;
 
         // left edge of view
         float x = 0f;
-        float y = mTextView.getHeight() / 2f;
+        float y = mTextView.getHeight() / 2f + paddingTop;
         assertEquals(firstOffset, mTextView.getOffsetForPosition(x, y));
 
         // right edge of text
-        x = mTextView.getLayout().getLineWidth(0) - 1f;
+        x = mTextView.getLayout().getLineWidth(0) + paddingLeft - halfCharWidth;
         assertEquals(lastOffset, mTextView.getOffsetForPosition(x, y));
 
         // right edge of view
@@ -3582,7 +3602,7 @@
         assertEquals(firstOffset, mTextView.getOffsetForPosition(x, y));
 
         // horizontal center of text
-        x = (float) Math.floor(mTextView.getLayout().getLineWidth(0) / 2f + 0.5f);
+        x = mTextView.getLayout().getLineWidth(0) / 2f + paddingLeft - halfCharWidth;
         assertEquals(midOffset, mTextView.getOffsetForPosition(x, y));
     }
 
@@ -3616,9 +3636,13 @@
         final Rect lineBounds = new Rect();
         mTextView.getLayout().getLineBounds(0, lineBounds);
 
+        final float halfCharWidth = (float) Math.ceil(mTextView.getPaint().measureText("a") / 2f);
+        final int paddingTop = mTextView.getTotalPaddingTop();
+        final int paddingLeft = mTextView.getTotalPaddingLeft();
+
         // left edge of view at first line
         float x = 0f;
-        float y = lineBounds.height() / 2f;
+        float y = lineBounds.height() / 2f + paddingTop;
         assertEquals(0, mTextView.getOffsetForPosition(x, y));
 
         // right edge of view at first line
@@ -3627,14 +3651,14 @@
 
         // update lineBounds to be the second line
         mTextView.getLayout().getLineBounds(1, lineBounds);
-        y = lineBounds.top + lineBounds.height() / 2;
+        y = lineBounds.top + lineBounds.height() / 2f + paddingTop;
 
         // left edge of view at second line
         x = 0f;
         assertEquals(line.length(), mTextView.getOffsetForPosition(x, y));
 
         // right edge of text at second line
-        x = mTextView.getLayout().getLineWidth(1) - 1f;
+        x = mTextView.getLayout().getLineWidth(1) + paddingLeft - halfCharWidth;
         assertEquals(line.length() + line.length() - 1, mTextView.getOffsetForPosition(x, y));
 
         // right edge of view at second line
@@ -3642,7 +3666,7 @@
         assertEquals(line.length() + line.length() - 1, mTextView.getOffsetForPosition(x, y));
 
         // horizontal center of text at second line
-        x = (float) Math.floor(mTextView.getLayout().getLineWidth(1) / 2f + 0.5f);
+        x = mTextView.getLayout().getLineWidth(1) / 2f + paddingLeft - halfCharWidth;
         // second line mid offset should not include next line, therefore subtract one
         assertEquals(line.length() + (line.length() - 1) / 2, mTextView.getOffsetForPosition(x, y));
     }
@@ -3677,9 +3701,14 @@
         final Rect lineBounds = new Rect();
         mTextView.getLayout().getLineBounds(0, lineBounds);
 
+        final float halfCharWidth = (float) Math.ceil(
+                mTextView.getPaint().measureText("\u0635") / 2f);
+        final int paddingTop = mTextView.getTotalPaddingTop();
+        final int paddingRight = mTextView.getTotalPaddingRight();
+
         // right edge of view at first line
         float x = mTextView.getWidth() - 1f;
-        float y = lineBounds.height() / 2f;
+        float y = lineBounds.height() / 2f + paddingTop;
         assertEquals(0, mTextView.getOffsetForPosition(x, y));
 
         // left edge of view at first line
@@ -3688,7 +3717,7 @@
 
         // update lineBounds to be the second line
         mTextView.getLayout().getLineBounds(1, lineBounds);
-        y = lineBounds.top + lineBounds.height() / 2f;
+        y = lineBounds.top + lineBounds.height() / 2f + paddingTop;
 
         // right edge of view at second line
         x = mTextView.getWidth() - 1f;
@@ -3698,13 +3727,14 @@
         x = 0f;
         assertEquals(line.length() + line.length() - 1, mTextView.getOffsetForPosition(x, y));
 
-        // right edge of text at second line
-        x = mTextView.getWidth() - mTextView.getLayout().getLineWidth(1) + 1f;
+        // left edge of text at second line
+        x = mTextView.getWidth() - (mTextView.getLayout().getLineWidth(1) + paddingRight
+                - halfCharWidth);
         assertEquals(line.length() + line.length() - 1, mTextView.getOffsetForPosition(x, y));
 
         // horizontal center of text at second line
-        x = mTextView.getWidth() - (float) Math.floor(
-                mTextView.getLayout().getLineWidth(1) / 2f + 0.5f);
+        x = mTextView.getWidth() - (mTextView.getLayout().getLineWidth(1) / 2f + paddingRight
+                - halfCharWidth);
         // second line mid offset should not include next line, therefore subtract one
         assertEquals(line.length() + (line.length() - 1) / 2, mTextView.getOffsetForPosition(x, y));
     }
@@ -6988,13 +7018,6 @@
                 (int) (0.5f + TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PT, 10f, m)),
                 (int) (0.5f + TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_IN, 10f, m)),
                 (int) (0.5f + TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 10f, m))};
-        expectedSizesInPx = Arrays.stream(expectedSizesInPx)
-                .filter(x -> x > 0)
-                .distinct()
-                .sorted()
-                .toArray();
-        assertArrayEquals(expectedSizesInPx,
-                autoSizeTextViewUniform.getAutoSizeTextAvailableSizes());
 
         boolean containsValueFromExpectedSizes = false;
         int textSize = (int) autoSizeTextViewUniform.getTextSize();
@@ -7317,12 +7340,17 @@
         PollingCheck.waitFor(() -> mTextView.getSelectionStart() == SMARTSELECT_START
                 && mTextView.getSelectionEnd() == SMARTSELECT_END);
 
-        // Click to reset selection. Expect selection of original selection.
+        // Tap to reset selection. Expect tapped word to be selected.
+        startIndex = text.indexOf("Filip");
+        endIndex = startIndex + "Filip".length();
+        offset = getCenterPositionOfTextAt(mTextView, startIndex, endIndex);
         emulateClickOnView(mTextView, offset.x, offset.y);
-        PollingCheck.waitFor(() -> mTextView.getSelectionStart() == startIndex
-                && mTextView.getSelectionEnd() == endIndex);
+        final int selStart = startIndex;
+        final int selEnd = endIndex;
+        PollingCheck.waitFor(() -> mTextView.getSelectionStart() == selStart
+                && mTextView.getSelectionEnd() == selEnd);
 
-        // Click one more time to dismiss the selection.
+        // Tap one more time to dismiss the selection.
         emulateClickOnView(mTextView, offset.x, offset.y);
         assertFalse(mTextView.hasSelection());
     }
diff --git a/tools/cts-tradefed/Android.mk b/tools/cts-tradefed/Android.mk
index 7783e58c..a247d06 100644
--- a/tools/cts-tradefed/Android.mk
+++ b/tools/cts-tradefed/Android.mk
@@ -28,7 +28,7 @@
 LOCAL_SUITE_VERSION := 7.1_r2
 
 LOCAL_MODULE := cts-tradefed
-
+include cts/error_prone_rules.mk
 include $(BUILD_COMPATIBILITY_SUITE)
 
 # Build all sub-directories