Merge "Fix BYOD CTS Verifier Test"
diff --git a/apps/CameraITS/pymodules/its/image.py b/apps/CameraITS/pymodules/its/image.py
index d4776c7..1654faa8 100644
--- a/apps/CameraITS/pymodules/its/image.py
+++ b/apps/CameraITS/pymodules/its/image.py
@@ -414,7 +414,7 @@
     return img
 
 
-def get_black_level(chan, props, cap_res):
+def get_black_level(chan, props, cap_res=None):
     """Return the black level to use for a given capture.
 
     Uses a dynamic value from the capture result if available, else falls back
@@ -428,7 +428,7 @@
     Returns:
         The black level value for the specified channel.
     """
-    if (cap_res.has_key('android.sensor.dynamicBlackLevel') and
+    if (cap_res is not None and cap_res.has_key('android.sensor.dynamicBlackLevel') and
             cap_res['android.sensor.dynamicBlackLevel'] is not None):
         black_levels = cap_res['android.sensor.dynamicBlackLevel']
     else:
diff --git a/apps/CameraITS/tests/scene1/test_raw_exposure.py b/apps/CameraITS/tests/scene1/test_raw_exposure.py
new file mode 100644
index 0000000..3a0dcf6
--- /dev/null
+++ b/apps/CameraITS/tests/scene1/test_raw_exposure.py
@@ -0,0 +1,160 @@
+# Copyright 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import its.device
+import its.caps
+import its.objects
+import its.image
+import os.path
+import numpy as np
+from matplotlib import pylab
+import matplotlib.pyplot
+
+IMG_STATS_GRID = 9  # find used to find the center 11.11%
+NAME = os.path.basename(__file__).split(".")[0]
+NUM_ISO_STEPS = 5
+SATURATION_TOL = 0.01
+BLK_LVL_TOL = 0.1
+# Test 3 steps per 2x exposure
+EXP_MULT = pow(2, 1.0/3)
+INCREASING_THR = 0.99
+# slice captures into burst of SLICE_LEN requests
+SLICE_LEN = 10
+
+def main():
+    """Capture a set of raw images with increasing exposure time and measure the pixel values.
+    """
+
+    with its.device.ItsSession() as cam:
+
+        props = cam.get_camera_properties()
+        its.caps.skip_unless(its.caps.raw16(props) and
+                             its.caps.manual_sensor(props) and
+                             its.caps.read_3a(props) and
+                             its.caps.per_frame_control(props))
+        debug = its.caps.debug_mode()
+
+        # Expose for the scene with min sensitivity
+        exp_min, exp_max = props["android.sensor.info.exposureTimeRange"]
+        sens_min, _ = props["android.sensor.info.sensitivityRange"]
+        # Digital gains might not be visible on RAW data
+        sens_max = props["android.sensor.maxAnalogSensitivity"]
+        sens_step = (sens_max - sens_min) / NUM_ISO_STEPS
+        white_level = float(props["android.sensor.info.whiteLevel"])
+        black_levels = [its.image.get_black_level(i,props) for i in range(4)]
+        # Get the active array width and height.
+        aax = props["android.sensor.info.activeArraySize"]["left"]
+        aay = props["android.sensor.info.activeArraySize"]["top"]
+        aaw = props["android.sensor.info.activeArraySize"]["right"]-aax
+        aah = props["android.sensor.info.activeArraySize"]["bottom"]-aay
+        raw_stat_fmt = {"format": "rawStats",
+                        "gridWidth": aaw/IMG_STATS_GRID,
+                        "gridHeight": aah/IMG_STATS_GRID}
+
+        e_test = []
+        mult = 1.0
+        while exp_min*mult < exp_max:
+            e_test.append(int(exp_min*mult))
+            mult *= EXP_MULT
+        if e_test[-1] < exp_max * INCREASING_THR:
+            e_test.append(int(exp_max))
+        e_test_ms = [e / 1000000.0 for e in e_test]
+
+        for s in range(sens_min, sens_max, sens_step):
+            means = []
+            means.append(black_levels)
+            reqs = [its.objects.manual_capture_request(s, e, 0) for e in e_test]
+            # Capture raw in debug mode, rawStats otherwise
+            caps = []
+            for i in range(len(reqs) / SLICE_LEN):
+                if debug:
+                    caps += cam.do_capture(reqs[i*SLICE_LEN:(i+1)*SLICE_LEN], cam.CAP_RAW)
+                else:
+                    caps += cam.do_capture(reqs[i*SLICE_LEN:(i+1)*SLICE_LEN], raw_stat_fmt)
+            last_n = len(reqs) % SLICE_LEN
+            if last_n == 1:
+                if debug:
+                    caps += [cam.do_capture(reqs[-last_n:], cam.CAP_RAW)]
+                else:
+                    caps += [cam.do_capture(reqs[-last_n:], raw_stat_fmt)]
+            elif last_n > 0:
+                if debug:
+                    caps += cam.do_capture(reqs[-last_n:], cam.CAP_RAW)
+                else:
+                    caps += cam.do_capture(reqs[-last_n:], raw_stat_fmt)
+
+            # Measure the mean of each channel.
+            # Each shot should be brighter (except underexposed/overexposed scene)
+            for i,cap in enumerate(caps):
+                if debug:
+                    planes = its.image.convert_capture_to_planes(cap, props)
+                    tiles = [its.image.get_image_patch(p, 0.445, 0.445, 0.11, 0.11) for p in planes]
+                    mean = [m * white_level for tile in tiles
+                            for m in its.image.compute_image_means(tile)]
+                    img = its.image.convert_capture_to_rgb_image(cap, props=props)
+                    its.image.write_image(img, "%s_s=%d_e=%05d.jpg" % (NAME, s, e_test))
+                else:
+                    mean_image, _ = its.image.unpack_rawstats_capture(cap)
+                    mean = mean_image[IMG_STATS_GRID/2, IMG_STATS_GRID/2]
+
+                print "ISO=%d, exposure time=%.3fms, mean=%s" % (
+                        s, e_test[i] / 1000000.0, str(mean))
+                means.append(mean)
+
+
+            # means[0] is black level value
+            r = [m[0] for m in means[1:]]
+            gr = [m[1] for m in means[1:]]
+            gb = [m[2] for m in means[1:]]
+            b = [m[3] for m in means[1:]]
+
+            pylab.plot(e_test_ms, r, "r.-")
+            pylab.plot(e_test_ms, b, "b.-")
+            pylab.plot(e_test_ms, gr, "g.-")
+            pylab.plot(e_test_ms, gb, "k.-")
+            pylab.xscale('log')
+            pylab.yscale('log')
+            pylab.title("%s ISO=%d" % (NAME, s))
+            pylab.xlabel("Exposure time (ms)")
+            pylab.ylabel("Center patch pixel mean")
+            matplotlib.pyplot.savefig("%s_s=%d.png" % (NAME, s))
+            pylab.clf()
+
+            allow_under_saturated = True
+            for i in xrange(1, len(means)):
+                prev_mean = means[i-1]
+                mean = means[i]
+
+                if np.isclose(max(mean), white_level, rtol=SATURATION_TOL):
+                    print "Saturated: white_level %f, max_mean %f"% (white_level, max(mean))
+                    break;
+
+                if allow_under_saturated and np.allclose(mean, black_levels, rtol=BLK_LVL_TOL):
+                    # All channel means are close to black level
+                    continue
+
+                allow_under_saturated = False
+                # Check pixel means are increasing (with small tolerance)
+                channels = ["Red", "Gr", "Gb", "Blue"]
+                for chan in range(4):
+                    err_msg = "ISO=%d, %s, exptime %3fms mean: %.2f, %s mean: %.2f, TOL=%.f%%" % (
+                            s, channels[chan],
+                            e_test_ms[i-1], mean[chan],
+                            "black level" if i == 1 else "exptime %3fms"%e_test_ms[i-2],
+                            prev_mean[chan],
+                            INCREASING_THR*100)
+                    assert mean[chan] > prev_mean[chan] * INCREASING_THR, err_msg
+
+if __name__ == "__main__":
+    main()
diff --git a/apps/CameraITS/tests/scene5/test_lens_shading_and_color_uniformity.py b/apps/CameraITS/tests/scene5/test_lens_shading_and_color_uniformity.py
index 065f854..f7f2003 100644
--- a/apps/CameraITS/tests/scene5/test_lens_shading_and_color_uniformity.py
+++ b/apps/CameraITS/tests/scene5/test_lens_shading_and_color_uniformity.py
@@ -52,6 +52,8 @@
 
     with its.device.ItsSession() as cam:
         props = cam.get_camera_properties()
+        its.caps.skip_unless(its.caps.ae_lock(props) and
+                             its.caps.awb_lock(props))
         if its.caps.read_3a(props):
             # Converge 3A and get the estimates.
             sens, exp, gains, xform, focus = cam.do_3a(get_results=True,
diff --git a/apps/CameraITS/tools/validate_scene.py b/apps/CameraITS/tools/validate_scene.py
index cfe14e2..1c0f0fd 100644
--- a/apps/CameraITS/tools/validate_scene.py
+++ b/apps/CameraITS/tools/validate_scene.py
@@ -49,8 +49,9 @@
                 " to frame the test scene: " + scene_name +
                 "\nThe scene setup should be: " + scene_desc )
         # Converge 3A prior to capture.
-        cam.do_3a(do_af=do_af, lock_ae=True, lock_awb=True)
         props = cam.get_camera_properties()
+        cam.do_3a(do_af=do_af, lock_ae=its.caps.ae_lock(props),
+                  lock_awb=its.caps.awb_lock(props))
         req = its.objects.fastest_auto_capture_request(props)
         if its.caps.ae_lock(props):
             req["android.control.awbLock"] = True
diff --git a/apps/CtsVerifier/Android.mk b/apps/CtsVerifier/Android.mk
index 10c33ba..144333d 100644
--- a/apps/CtsVerifier/Android.mk
+++ b/apps/CtsVerifier/Android.mk
@@ -25,6 +25,9 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-Iaidl-files-under, src)
 
+LOCAL_AIDL_INCLUDES := \
+    frameworks/native/aidl/gui
+
 LOCAL_STATIC_JAVA_LIBRARIES := android-ex-camera2 \
                                compatibility-common-util-devicesidelib \
                                cts-sensors-tests \
@@ -46,6 +49,7 @@
 LOCAL_JAVA_LIBRARIES += android.test.base.stubs
 LOCAL_JAVA_LIBRARIES += android.test.mock.stubs
 LOCAL_JAVA_LIBRARIES += bouncycastle
+LOCAL_JAVA_LIBRARIES += voip-common
 
 LOCAL_PACKAGE_NAME := CtsVerifier
 
@@ -55,8 +59,6 @@
 
 LOCAL_PROGUARD_FLAG_FILES := proguard.flags
 
-LOCAL_SDK_VERSION := test_current
-
 LOCAL_DEX_PREOPT := false
 -include cts/error_prone_rules_tests.mk
 include $(BUILD_PACKAGE)
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralButtonsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralButtonsActivity.java
index 861af28..8345184 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralButtonsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralButtonsActivity.java
@@ -16,6 +16,7 @@
 
 package com.android.cts.verifier.audio;
 
+import android.content.res.Resources;
 import android.graphics.Color;
 import android.os.Bundle;
 import android.util.Log;
@@ -110,13 +111,15 @@
         if (mIsPeripheralAttached && mSelectedProfile != null) {
             ProfileButtonAttributes mButtonAttributes = mSelectedProfile.getButtonAttributes();
             boolean match = mButtonAttributes != null;
+            boolean interceptedVolume = getResources().getBoolean(Resources.getSystem()
+                .getIdentifier("config_handleVolumeKeysInWindowManager", "bool", "android"));
             if (match && mButtonAttributes.mHasBtnA != mHasBtnA) {
                 match = false;
             }
-            if (match && mButtonAttributes.mHasBtnB != mHasBtnB) {
+            if (match && mButtonAttributes.mHasBtnB != mHasBtnB && !interceptedVolume) {
                 match = false;
             }
-            if (match && mButtonAttributes.mHasBtnC != mHasBtnC) {
+            if (match && mButtonAttributes.mHasBtnC != mHasBtnC && !interceptedVolume) {
                 match = false;
             }
             Log.i(TAG, "match:" + match);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
index 5dbbc79..81226a6 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
@@ -1328,7 +1328,8 @@
 
                 int newCount = mCountCallbacksRemaining.get();
                 if (newCount == currentCount) {
-                    throw new ItsException("No callback received within timeout");
+                    throw new ItsException("No callback received within timeout " +
+                            timeoutMs + "ms");
                 }
                 currentCount = newCount;
             }
@@ -1802,8 +1803,8 @@
                     logMsg.append(String.format(
                             "sens=%d, exp=%.1fms, dur=%.1fms, ",
                             result.get(CaptureResult.SENSOR_SENSITIVITY),
-                            result.get(CaptureResult.SENSOR_EXPOSURE_TIME).intValue() / 1000000.0f,
-                            result.get(CaptureResult.SENSOR_FRAME_DURATION).intValue() /
+                            result.get(CaptureResult.SENSOR_EXPOSURE_TIME).longValue() / 1000000.0f,
+                            result.get(CaptureResult.SENSOR_FRAME_DURATION).longValue() /
                                         1000000.0f));
                 }
                 if (result.get(CaptureResult.COLOR_CORRECTION_GAINS) != null) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ICrossUserService.aidl b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ICrossUserService.aidl
index 630fe1e..8894745 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ICrossUserService.aidl
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ICrossUserService.aidl
@@ -16,6 +16,8 @@
 
 package com.android.cts.verifier.managedprovisioning;
 
+import android.os.UserHandle;
+
 interface ICrossUserService {
     void switchUser(in UserHandle userHandle);
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/LockTaskUiTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/LockTaskUiTestActivity.java
index a6e6b2f..5447536 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/LockTaskUiTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/LockTaskUiTestActivity.java
@@ -21,12 +21,11 @@
 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD;
 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NONE;
 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS;
-import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_RECENTS;
+import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW;
 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO;
 
 import static com.android.cts.verifier.managedprovisioning.Utils.createInteractiveTestItem;
 
-import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.Notification;
 import android.app.NotificationChannel;
@@ -152,7 +151,7 @@
 
         adapter.add(createSetLockTaskFeaturesTest(
                 TEST_ID_RECENTS,
-                LOCK_TASK_FEATURE_RECENTS,
+                LOCK_TASK_FEATURE_OVERVIEW,
                 R.string.device_owner_lock_task_ui_recents_test,
                 R.string.device_owner_lock_task_ui_recents_test_info));
 
diff --git a/tests/autofillservice/src/android/autofillservice/cts/RequiredFeatureRule.java b/common/device-side/util/src/com/android/compatibility/common/util/RequiredFeatureRule.java
similarity index 95%
rename from tests/autofillservice/src/android/autofillservice/cts/RequiredFeatureRule.java
rename to common/device-side/util/src/com/android/compatibility/common/util/RequiredFeatureRule.java
index 17b2504..0968ddc 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/RequiredFeatureRule.java
+++ b/common/device-side/util/src/com/android/compatibility/common/util/RequiredFeatureRule.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.autofillservice.cts;
+package com.android.compatibility.common.util;
 
 import android.support.test.InstrumentationRegistry;
 import android.util.Log;
@@ -26,7 +26,6 @@
 /**
  * Custom JUnit4 rule that does not run a test case if the device does not have a given feature.
  */
-// TODO: move to common CTS codebase
 public class RequiredFeatureRule implements TestRule {
     private static final String TAG = "RequiredFeatureRule";
 
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildProvider.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildProvider.java
index db8a888..60400be 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildProvider.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildProvider.java
@@ -71,6 +71,9 @@
     @Option(name="build-flavor", description="build flavor name to supply.")
     private String mBuildFlavor = null;
 
+    @Option(name="build-target", description="build target name to supply.")
+    private String mBuildTarget = null;
+
     @Option(name="build-attribute", description="build attributes to supply.")
     private Map<String, String> mBuildAttributes = new HashMap<String,String>();
 
@@ -103,6 +106,9 @@
         for (Map.Entry<String, String> entry : mBuildAttributes.entrySet()) {
             buildInfo.addBuildAttribute(entry.getKey(), entry.getValue());
         }
+        if (mTestTag != null) {
+            buildInfo.setTestTag(mTestTag);
+        }
     }
 
     /**
@@ -117,7 +123,7 @@
      * {@inheritDoc}
      */
     @Override
-    public IBuildInfo getBuild() {
+    public IBuildInfo getBuild() throws BuildRetrievalError {
         // Create a blank BuildInfo which will get populated later.
         String version = null;
         if (mBuildId != null) {
@@ -128,7 +134,7 @@
                 version = IBuildInfo.UNKNOWN_BUILD_ID;
             }
         }
-        IBuildInfo ctsBuild = new DeviceBuildInfo(version, mTestTag);
+        IBuildInfo ctsBuild = new DeviceBuildInfo(version, mBuildTarget);
         if (mBranch  != null) {
             ctsBuild.setBuildBranch(mBranch);
         }
@@ -151,9 +157,18 @@
             // build info fields
             return getBuild();
         } else {
-            String buildId = device.getBuildId();
-            String buildFlavor = device.getBuildFlavor();
-            IBuildInfo info = new DeviceBuildInfo(buildId, mTestTag);
+            if (mBuildId == null) {
+                mBuildId = device.getBuildId();
+            }
+            if (mBuildFlavor == null) {
+                mBuildFlavor = device.getBuildFlavor();
+            }
+            if (mBuildTarget == null) {
+                String name = device.getProperty("ro.product.name");
+                String variant = device.getProperty("ro.build.type");
+                mBuildTarget = name + "-" + variant;
+            }
+            IBuildInfo info = new DeviceBuildInfo(mBuildId, mBuildTarget);
             if (mBranch == null) {
                 // if branch is not specified via param, make a pseudo branch name based on platform
                 // version and product info from device
@@ -164,7 +179,7 @@
                         device.getProperty("ro.build.version.release"));
             }
             info.setBuildBranch(mBranch);
-            info.setBuildFlavor(buildFlavor);
+            info.setBuildFlavor(mBuildFlavor);
             String buildAlias = device.getBuildAlias();
             if (RELEASE_BUILD.matcher(buildAlias).matches()) {
                 info.addBuildAttribute("build_alias", buildAlias);
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java
index fe29c7f..5dcf2dd 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java
@@ -22,6 +22,7 @@
 import com.android.compatibility.common.util.IInvocationResult;
 import com.android.compatibility.common.util.ResultHandler;
 import com.android.compatibility.common.util.TestStatus;
+import com.android.tradefed.build.BuildRetrievalError;
 import com.android.tradefed.command.Console;
 import com.android.tradefed.config.ArgsOptionParser;
 import com.android.tradefed.config.ConfigurationException;
@@ -426,8 +427,12 @@
 
     private CompatibilityBuildHelper getBuildHelper() {
         if (mBuildHelper == null) {
-            CompatibilityBuildProvider buildProvider = new CompatibilityBuildProvider();
-            mBuildHelper = new CompatibilityBuildHelper(buildProvider.getBuild());
+            try {
+                CompatibilityBuildProvider buildProvider = new CompatibilityBuildProvider();
+                mBuildHelper = new CompatibilityBuildHelper(buildProvider.getBuild());
+            } catch (BuildRetrievalError e) {
+                e.printStackTrace();
+            }
         }
         return mBuildHelper;
     }
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/suite/CertificationSuiteResultReporter.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/suite/CertificationSuiteResultReporter.java
index f57126d..7934abd 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/suite/CertificationSuiteResultReporter.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/suite/CertificationSuiteResultReporter.java
@@ -60,7 +60,8 @@
 import javax.xml.transform.stream.StreamSource;
 
 /**
- * Extension of {@link SuiteResultReporter} to handle Compatibility specific format and operations.
+ * Extension of {@link XmlFormattedGeneratorReporter} and {@link SuiteResultReporter} to handle
+ * Compatibility specific format and operations.
  */
 public class CertificationSuiteResultReporter extends XmlFormattedGeneratorReporter
         implements ILogSaverListener, ITestSummaryListener {
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/retry/RetryFactoryTest.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/retry/RetryFactoryTest.java
index a95ebfb..1ac2014 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/retry/RetryFactoryTest.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/retry/RetryFactoryTest.java
@@ -199,6 +199,7 @@
         test.setInvocationContext(mContext);
         // reset the retry id - Ensure that retry of retry does not throw
         test.resetRetryId();
+        test.isRetry();
         // clean the helper
         helper.tearDown();
         return test;
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/suite/CompatibilityTestSuite.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/suite/CompatibilityTestSuite.java
index be64ccd..dd6a457 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/suite/CompatibilityTestSuite.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/suite/CompatibilityTestSuite.java
@@ -19,11 +19,13 @@
 import com.android.compatibility.common.tradefed.testtype.ISubPlan;
 import com.android.compatibility.common.tradefed.testtype.SubPlan;
 import com.android.compatibility.common.tradefed.testtype.retry.RetryFactoryTest;
+import com.android.ddmlib.Log.LogLevel;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.config.IConfiguration;
 import com.android.tradefed.config.Option;
 import com.android.tradefed.config.Option.Importance;
 import com.android.tradefed.config.OptionClass;
+import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.testtype.IAbi;
 import com.android.tradefed.testtype.suite.BaseTestSuite;
 import com.android.tradefed.testtype.suite.SuiteModuleLoader;
@@ -59,6 +61,8 @@
     private String mSubPlan;
 
     private CompatibilityBuildHelper mBuildHelper;
+    /** Tag if the current instance is running as a retry from RetryFactory */
+    private boolean mIsRetry = false;
 
     @Override
     public void setBuild(IBuildInfo buildInfo) {
@@ -84,8 +88,8 @@
     @Override
     public LinkedHashMap<String, IConfiguration> loadTests() {
         if (mRetrySessionId != null) {
-            throw new IllegalArgumentException("--retry cannot be specified with cts-suite.xml. "
-                    + "Use 'run cts --retry <session id>' instead.");
+            throw new IllegalArgumentException("--retry cannot be specified with cts[*].xml. "
+                    + "Use 'run retry --retry <session id>' instead.");
         }
         return super.loadTests();
     }
@@ -125,6 +129,13 @@
     }
 
     /**
+     * Mark the instance of CompatibilityTestSuite as a retry.
+     */
+    public final void isRetry() {
+        mIsRetry = true;
+    }
+
+    /**
      * {@inheritDoc}
      */
     @Override
@@ -136,9 +147,15 @@
                 getModuleLoader().loadConfigsFromDirectory(testsDir, abis, suitePrefix, suiteTag));
         // Add an extra check in CTS since we never expect the config folder to be empty.
         if (loadedConfigs.size() == 0) {
-            throw new IllegalArgumentException(
-                    String.format("No config files found in %s or in resources.",
-                            testsDir.getAbsolutePath()));
+            if (mIsRetry) {
+                // Only log if it's a retry
+                CLog.logAndDisplay(LogLevel.DEBUG,
+                        "No module that needed to run in retry were found. nothing to do.");
+            } else {
+                throw new IllegalArgumentException(
+                        String.format("No config files found in %s or in resources.",
+                                testsDir.getAbsolutePath()));
+            }
         }
         return loadedConfigs;
     }
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildProviderTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildProviderTest.java
index 0e02c023..f7116d7 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildProviderTest.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildProviderTest.java
@@ -85,6 +85,8 @@
         EasyMock.expect(mMockDevice.getBuildId()).andReturn("8888");
         EasyMock.expect(mMockDevice.getBuildFlavor()).andReturn("flavor");
         EasyMock.expect(mMockDevice.getBuildAlias()).andReturn("alias");
+        EasyMock.expect(mMockDevice.getProperty("ro.product.name")).andReturn("product");
+        EasyMock.expect(mMockDevice.getProperty("ro.build.type")).andReturn("userdebug");
         EasyMock.replay(mMockDevice);
         IBuildInfo info = mProvider.getBuild(mMockDevice);
         EasyMock.verify(mMockDevice);
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/CtsConfigLoadingTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/CtsConfigLoadingTest.java
index 0a972f1..ede86ef 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/CtsConfigLoadingTest.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/CtsConfigLoadingTest.java
@@ -56,6 +56,7 @@
             "art",
             "auth",
             "auto",
+            "autofill",
             "backup",
             "bionic",
             "bluetooth",
diff --git a/common/util/src/com/android/compatibility/common/util/ResultHandler.java b/common/util/src/com/android/compatibility/common/util/ResultHandler.java
index c394b8d..d85c678 100644
--- a/common/util/src/com/android/compatibility/common/util/ResultHandler.java
+++ b/common/util/src/com/android/compatibility/common/util/ResultHandler.java
@@ -156,8 +156,9 @@
      * @return an IInvocationResult for this result, or null upon error
      */
     public static IInvocationResult getResultFromDir(File resultDir, Boolean useChecksum) {
+        File resultFile = null;
         try {
-            File resultFile = new File(resultDir, TEST_RESULT_FILE_NAME);
+            resultFile = new File(resultDir, TEST_RESULT_FILE_NAME);
             if (!resultFile.exists()) {
                 return null;
             }
@@ -277,6 +278,9 @@
             parser.require(XmlPullParser.END_TAG, NS, RESULT_TAG);
             return invocation;
         } catch (XmlPullParserException | IOException e) {
+            System.out.println(
+                    String.format("Exception when trying to load %s",
+                            resultFile.getAbsolutePath()));
             e.printStackTrace();
             return null;
         }
diff --git a/hostsidetests/appsecurity/test-apps/AccessSerialLegacy/Android.mk b/hostsidetests/appsecurity/test-apps/AccessSerialLegacy/Android.mk
index e4b7962..bfb88f0 100644
--- a/hostsidetests/appsecurity/test-apps/AccessSerialLegacy/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/AccessSerialLegacy/Android.mk
@@ -25,6 +25,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsAccessSerialLegacy
+LOCAL_SDK_VERSION := current
 
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
diff --git a/hostsidetests/appsecurity/test-apps/AccessSerialModern/Android.mk b/hostsidetests/appsecurity/test-apps/AccessSerialModern/Android.mk
index 20d51b6..4bdb346 100644
--- a/hostsidetests/appsecurity/test-apps/AccessSerialModern/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/AccessSerialModern/Android.mk
@@ -26,6 +26,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsAccessSerialModern
+LOCAL_SDK_VERSION := current
 
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
diff --git a/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_a/Android.mk b/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_a/Android.mk
index 2683128..f37be44 100644
--- a/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_a/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_a/Android.mk
@@ -22,6 +22,7 @@
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 LOCAL_EXPORT_PACKAGE_RESOURCES := true
 LOCAL_PACKAGE_NAME := CtsClassloaderSplitAppFeatureA
+LOCAL_SDK_VERSION := current
 
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
diff --git a/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_b/Android.mk b/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_b/Android.mk
index a1b43ea..3262e15 100644
--- a/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_b/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/ClassLoaderSplitApp/feature_b/Android.mk
@@ -21,6 +21,7 @@
 LOCAL_MODULE_TAGS := tests
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 LOCAL_PACKAGE_NAME := CtsClassloaderSplitAppFeatureB
+LOCAL_SDK_VERSION := current
 
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
diff --git a/hostsidetests/appsecurity/test-apps/DeclareNotRuntimePermissions/Android.mk b/hostsidetests/appsecurity/test-apps/DeclareNotRuntimePermissions/Android.mk
index dbf5284..6af9e72 100644
--- a/hostsidetests/appsecurity/test-apps/DeclareNotRuntimePermissions/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/DeclareNotRuntimePermissions/Android.mk
@@ -21,6 +21,7 @@
 LOCAL_MODULE_TAGS := tests
 
 LOCAL_PACKAGE_NAME := CtsDeclareNonRuntimePermissions
+LOCAL_SDK_VERSION := current
 
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/Android.mk b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/Android.mk
index 99ee67c..dab340b 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/Android.mk
@@ -32,6 +32,7 @@
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 
 LOCAL_PACKAGE_NAME := CtsEphemeralTestsEphemeralApp1
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_PROGUARD_ENABLED := disabled
 LOCAL_DEX_PREOPT := false
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp2/Android.mk b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp2/Android.mk
index 4f0ee6c..a5bc4b0 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp2/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp2/Android.mk
@@ -26,6 +26,7 @@
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 
 LOCAL_PACKAGE_NAME := CtsEphemeralTestsEphemeralApp2
+LOCAL_SDK_VERSION := current
 
 LOCAL_PROGUARD_ENABLED := disabled
 LOCAL_DEX_PREOPT := false
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/ImplicitlyExposedApp/Android.mk b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/ImplicitlyExposedApp/Android.mk
index 6309704..8b04f9b 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/ImplicitlyExposedApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/ImplicitlyExposedApp/Android.mk
@@ -29,6 +29,7 @@
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 
 LOCAL_PACKAGE_NAME := CtsEphemeralTestsImplicitApp
+LOCAL_SDK_VERSION := current
 
 LOCAL_PROGUARD_ENABLED := disabled
 LOCAL_DEX_PREOPT := false
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/Android.mk b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/Android.mk
index bd1b2d8..d2c3667 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/Android.mk
@@ -31,6 +31,7 @@
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 
 LOCAL_PACKAGE_NAME := CtsEphemeralTestsNormalApp
+LOCAL_SDK_VERSION := system_current
 
 LOCAL_PROGUARD_ENABLED := disabled
 LOCAL_DEX_PREOPT := false
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/UnexposedApp/Android.mk b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/UnexposedApp/Android.mk
index 5fa3765..7ceaff3 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/UnexposedApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/UnexposedApp/Android.mk
@@ -26,6 +26,7 @@
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 
 LOCAL_PACKAGE_NAME := CtsEphemeralTestsUnexposedApp
+LOCAL_SDK_VERSION := current
 
 LOCAL_PROGUARD_ENABLED := disabled
 LOCAL_DEX_PREOPT := false
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/UserApp/Android.mk b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/UserApp/Android.mk
index 35c089f..28560d3 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/UserApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/UserApp/Android.mk
@@ -29,6 +29,7 @@
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 
 LOCAL_PACKAGE_NAME := CtsEphemeralTestsUserApp
+LOCAL_SDK_VERSION := current
 
 LOCAL_PROGUARD_ENABLED := disabled
 LOCAL_DEX_PREOPT := false
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/UserAppTest/Android.mk b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/UserAppTest/Android.mk
index cfa0b55..64f02cb 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/UserAppTest/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/UserAppTest/Android.mk
@@ -28,6 +28,7 @@
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 
 LOCAL_PACKAGE_NAME := CtsEphemeralTestsUserAppTest
+LOCAL_SDK_VERSION := current
 
 LOCAL_PROGUARD_ENABLED := disabled
 LOCAL_DEX_PREOPT := false
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/util/Android.mk b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/util/Android.mk
index fc1bd83..df29c03 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/util/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/util/Android.mk
@@ -23,5 +23,7 @@
 
 LOCAL_MODULE := cts-aia-util
 
+LOCAL_SDK_VERSION := current
+
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/util/src/com/android/cts/util/TestResult.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/util/src/com/android/cts/util/TestResult.java
index 9664823..0f52e80 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/util/src/com/android/cts/util/TestResult.java
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/util/src/com/android/cts/util/TestResult.java
@@ -119,7 +119,7 @@
         mStatus = source.readString();
         mException = source.readString();
         mIntent = source.readParcelable(Object.class.getClassLoader());
-        mInstantAppPackageInfoExposed = source.readBoolean();
+        mInstantAppPackageInfoExposed = source.readInt() != 0;
     }
 
     public static class Builder {
diff --git a/hostsidetests/appsecurity/test-apps/EscalateToRuntimePermissions/Android.mk b/hostsidetests/appsecurity/test-apps/EscalateToRuntimePermissions/Android.mk
index cd3c04e..5945188 100644
--- a/hostsidetests/appsecurity/test-apps/EscalateToRuntimePermissions/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/EscalateToRuntimePermissions/Android.mk
@@ -25,6 +25,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsEscalateToRuntimePermissions
+LOCAL_SDK_VERSION := current
 
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
diff --git a/hostsidetests/appsecurity/test-apps/InstantCookieApp/Android.mk b/hostsidetests/appsecurity/test-apps/InstantCookieApp/Android.mk
index 1f9063c..78eb619 100644
--- a/hostsidetests/appsecurity/test-apps/InstantCookieApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/InstantCookieApp/Android.mk
@@ -25,6 +25,7 @@
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
 
 LOCAL_PACKAGE_NAME := CtsInstantCookieApp
+LOCAL_SDK_VERSION := current
 
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
diff --git a/hostsidetests/appsecurity/test-apps/InstantCookieApp2/Android.mk b/hostsidetests/appsecurity/test-apps/InstantCookieApp2/Android.mk
index b154ae2..6385123 100644
--- a/hostsidetests/appsecurity/test-apps/InstantCookieApp2/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/InstantCookieApp2/Android.mk
@@ -25,6 +25,7 @@
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
 
 LOCAL_PACKAGE_NAME := CtsInstantCookieApp2
+LOCAL_SDK_VERSION := current
 
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
diff --git a/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_a/Android.mk b/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_a/Android.mk
index dd76592..c089660 100644
--- a/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_a/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_a/Android.mk
@@ -18,6 +18,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_PACKAGE_NAME := CtsIsolatedSplitAppFeatureA
+LOCAL_SDK_VERSION := current
 LOCAL_USE_AAPT2 := true
 LOCAL_MODULE_TAGS := tests
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
diff --git a/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_b/Android.mk b/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_b/Android.mk
index 240fc2c..42fd4cc 100644
--- a/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_b/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_b/Android.mk
@@ -18,6 +18,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_PACKAGE_NAME := CtsIsolatedSplitAppFeatureB
+LOCAL_SDK_VERSION := current
 LOCAL_USE_AAPT2 := true
 LOCAL_MODULE_TAGS := tests
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
diff --git a/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_c/Android.mk b/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_c/Android.mk
index 35b3252..d7f6687 100644
--- a/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_c/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/IsolatedSplitApp/feature_c/Android.mk
@@ -18,6 +18,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_PACKAGE_NAME := CtsIsolatedSplitAppFeatureC
+LOCAL_SDK_VERSION := current
 LOCAL_USE_AAPT2 := true
 LOCAL_MODULE_TAGS := tests
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
diff --git a/hostsidetests/appsecurity/test-apps/NoRestartApp/Android.mk b/hostsidetests/appsecurity/test-apps/NoRestartApp/Android.mk
index 32f36d0..23db742 100644
--- a/hostsidetests/appsecurity/test-apps/NoRestartApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/NoRestartApp/Android.mk
@@ -21,6 +21,7 @@
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 
 LOCAL_PACKAGE_NAME := CtsNoRestartBase
+LOCAL_SDK_VERSION := current
 
 LOCAL_MODULE_TAGS := tests
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
diff --git a/hostsidetests/appsecurity/test-apps/NoRestartApp/feature/Android.mk b/hostsidetests/appsecurity/test-apps/NoRestartApp/feature/Android.mk
index 626c0be..08fa1bd 100644
--- a/hostsidetests/appsecurity/test-apps/NoRestartApp/feature/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/NoRestartApp/feature/Android.mk
@@ -21,6 +21,7 @@
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 
 LOCAL_PACKAGE_NAME := CtsNoRestartFeature
+LOCAL_SDK_VERSION := current
 
 LOCAL_MODULE_TAGS := tests
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
diff --git a/hostsidetests/appsecurity/test-apps/PermissionPolicy25/Android.mk b/hostsidetests/appsecurity/test-apps/PermissionPolicy25/Android.mk
index 0d53ac8..a8d659b 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionPolicy25/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/PermissionPolicy25/Android.mk
@@ -28,6 +28,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsPermissionPolicyTest25
+LOCAL_SDK_VERSION := current
 
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/feature/Android.mk
index a248b71..06901d8 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/feature/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/Android.mk
@@ -19,6 +19,7 @@
 
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 LOCAL_PACKAGE_NAME := CtsSplitAppFeature
+LOCAL_SDK_VERSION := current
 LOCAL_PACKAGE_SPLITS := v7
 
 LOCAL_ASSET_DIR := $(LOCAL_PATH)/assets
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/Android.mk
index bad39fb..5337057 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/Android.mk
@@ -19,6 +19,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_PACKAGE_NAME := CtsSplitApp_arm64-v8a
+LOCAL_SDK_VERSION := current
 
 LOCAL_JAVA_RESOURCE_DIRS := raw
 
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/Android.mk
index 9951098..7fceede 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/Android.mk
@@ -19,6 +19,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_PACKAGE_NAME := CtsSplitApp_armeabi-v7a
+LOCAL_SDK_VERSION := current
 
 LOCAL_JAVA_RESOURCE_DIRS := raw
 
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/Android.mk
index f6efcd6..9149930 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/Android.mk
@@ -19,6 +19,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_PACKAGE_NAME := CtsSplitApp_armeabi
+LOCAL_SDK_VERSION := current
 
 LOCAL_JAVA_RESOURCE_DIRS := raw
 
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/Android.mk
index aa2de06..95d02d0 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/Android.mk
@@ -19,6 +19,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_PACKAGE_NAME := CtsSplitApp_mips
+LOCAL_SDK_VERSION := current
 
 LOCAL_JAVA_RESOURCE_DIRS := raw
 
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/Android.mk
index cd4eafc..ad10be0 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/Android.mk
@@ -19,6 +19,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_PACKAGE_NAME := CtsSplitApp_mips64
+LOCAL_SDK_VERSION := current
 
 LOCAL_JAVA_RESOURCE_DIRS := raw
 
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/Android.mk
index 2d7d008..f008564 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/Android.mk
@@ -19,6 +19,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_PACKAGE_NAME := CtsSplitApp_x86
+LOCAL_SDK_VERSION := current
 
 LOCAL_JAVA_RESOURCE_DIRS := raw
 
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/Android.mk
index 291a3c6..ded5b29 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/Android.mk
@@ -19,6 +19,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_PACKAGE_NAME := CtsSplitApp_x86_64
+LOCAL_SDK_VERSION := current
 
 LOCAL_JAVA_RESOURCE_DIRS := raw
 
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/Android.mk b/hostsidetests/appsecurity/test-apps/UsePermissionApp22/Android.mk
index e1395bb..7a62f09 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp22/Android.mk
@@ -33,6 +33,7 @@
     ../UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java
 
 LOCAL_PACKAGE_NAME := CtsUsePermissionApp22
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 # tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/Android.mk b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/Android.mk
index 74f6e6c..58ee1c7 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/Android.mk
@@ -31,6 +31,7 @@
     ../ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java
 
 LOCAL_PACKAGE_NAME := CtsUsePermissionApp23
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 # tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java
index b9b652a..01f9c7d 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java
@@ -51,6 +51,7 @@
     }
 
     @Ignore
+    @Test
     public void testFail() throws Exception {
         fail("Expected");
     }
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp25/Android.mk b/hostsidetests/appsecurity/test-apps/UsePermissionApp25/Android.mk
index 82d69ba..8528752 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp25/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp25/Android.mk
@@ -32,6 +32,7 @@
 LOCAL_RESOURCE_DIR := cts/hostsidetests/appsecurity/test-apps/UsePermissionApp23/res
 
 LOCAL_PACKAGE_NAME := CtsUsePermissionApp25
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 # tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp26/Android.mk b/hostsidetests/appsecurity/test-apps/UsePermissionApp26/Android.mk
index 7064288..52c8ba4 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp26/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp26/Android.mk
@@ -31,6 +31,7 @@
 LOCAL_RESOURCE_DIR := cts/hostsidetests/appsecurity/test-apps/UsePermissionApp23/res
 
 LOCAL_PACKAGE_NAME := CtsUsePermissionApp26
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 # tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
diff --git a/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/Android.mk b/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/Android.mk
index 92e8cdf..3069bac 100644
--- a/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/Android.mk
+++ b/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/Android.mk
@@ -25,6 +25,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsSyncInvalidAccountAuthorityTestCases
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/api23/Android.mk b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/api23/Android.mk
index 71aeff6..3032da7 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/api23/Android.mk
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/api23/Android.mk
@@ -32,8 +32,6 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 compatibility-device-util ctstestrunner ub-uiautomator
 
-LOCAL_SDK_VERSION := test_current
-
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/../res
 
 # tag this module as a cts test artifact
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/api25/Android.mk b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/api25/Android.mk
index 6e6227c..fd3705a 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/api25/Android.mk
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/api25/Android.mk
@@ -32,8 +32,6 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 compatibility-device-util ctstestrunner ub-uiautomator
 
-LOCAL_SDK_VERSION := test_current
-
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/../res
 
 # tag this module as a cts test artifact
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/Android.mk b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/Android.mk
index 4e2b51c..f8f1c1a 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/Android.mk
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/Android.mk
@@ -32,8 +32,6 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 compatibility-device-util ctstestrunner ub-uiautomator
 
-LOCAL_SDK_VERSION := test_current
-
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/../res
 
 # tag this module as a cts test artifact
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk b/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk
index 835a0f2..66bc40f 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk
@@ -41,8 +41,6 @@
     android-support-test \
     cts-security-test-support-library
 
-LOCAL_SDK_VERSION := test_current
-
 # tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := arcts cts vts general-tests
 
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/LockTaskTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/LockTaskTest.java
index 6ef2ba1..8874660 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/LockTaskTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/LockTaskTest.java
@@ -20,7 +20,7 @@
 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD;
 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NONE;
 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS;
-import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_RECENTS;
+import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW;
 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO;
 
 import static junit.framework.Assert.assertEquals;
@@ -191,7 +191,7 @@
                 LOCK_TASK_FEATURE_SYSTEM_INFO,
                 LOCK_TASK_FEATURE_NOTIFICATIONS,
                 LOCK_TASK_FEATURE_HOME,
-                LOCK_TASK_FEATURE_RECENTS,
+                LOCK_TASK_FEATURE_OVERVIEW,
                 LOCK_TASK_FEATURE_GLOBAL_ACTIONS,
                 LOCK_TASK_FEATURE_KEYGUARD
         };
@@ -505,11 +505,11 @@
     }
 
     /**
-     * Starts LockTaskUtilityActivity with {@link ActivityOptions#setLockTaskMode(boolean)}
+     * Starts LockTaskUtilityActivity with {@link ActivityOptions#setLockTaskEnabled(boolean)}
      */
     private void startLockTaskWithOptions(String className) throws InterruptedException {
         Intent intent = getLockTaskUtility(className);
-        Bundle options = ActivityOptions.makeBasic().setLockTaskMode(true).toBundle();
+        Bundle options = ActivityOptions.makeBasic().setLockTaskEnabled(true).toBundle();
         startAndWait(intent, options);
     }
 
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/WipeDataTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/WipeDataTest.java
index 26f627e..65c7724 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/WipeDataTest.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/WipeDataTest.java
@@ -44,7 +44,7 @@
      * external storage should be allowed.
      */
     public void testWipeDataWithReason() throws InterruptedException {
-        mDevicePolicyManager.wipeDataWithReason(0, TEST_WIPE_DATA_REASON);
+        mDevicePolicyManager.wipeData(0, TEST_WIPE_DATA_REASON);
         // The test that the profile will indeed be removed is done in the host.
         // Notification verification is done in another test.
     }
diff --git a/hostsidetests/devicepolicy/app/ProfileOwner/Android.mk b/hostsidetests/devicepolicy/app/ProfileOwner/Android.mk
index 1903ced..117558c 100644
--- a/hostsidetests/devicepolicy/app/ProfileOwner/Android.mk
+++ b/hostsidetests/devicepolicy/app/ProfileOwner/Android.mk
@@ -36,8 +36,6 @@
     compatibility-device-util \
     ub-uiautomator
 
-LOCAL_SDK_VERSION := test_current
-
 # tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
diff --git a/hostsidetests/devicepolicy/app/TransferOwnerIncomingApp/Android.mk b/hostsidetests/devicepolicy/app/TransferOwnerIncomingApp/Android.mk
index d99fd39..5f3212f 100644
--- a/hostsidetests/devicepolicy/app/TransferOwnerIncomingApp/Android.mk
+++ b/hostsidetests/devicepolicy/app/TransferOwnerIncomingApp/Android.mk
@@ -24,7 +24,7 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs conscrypt cts-junit
+LOCAL_JAVA_LIBRARIES := android.test.runner.stubs cts-junit
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     android-support-v4 \
diff --git a/hostsidetests/devicepolicy/app/TransferOwnerOutgoingApp/Android.mk b/hostsidetests/devicepolicy/app/TransferOwnerOutgoingApp/Android.mk
index 5e3f6a9..71e2078 100644
--- a/hostsidetests/devicepolicy/app/TransferOwnerOutgoingApp/Android.mk
+++ b/hostsidetests/devicepolicy/app/TransferOwnerOutgoingApp/Android.mk
@@ -24,7 +24,7 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs conscrypt cts-junit
+LOCAL_JAVA_LIBRARIES := android.test.runner.stubs cts-junit
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     android-support-v4 \
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index ed2b193..6beff2a 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -20,6 +20,7 @@
 import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
 import com.android.ddmlib.testrunner.TestResult.TestStatus;
 import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.Option;
 import com.android.tradefed.device.CollectingOutputReceiver;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.log.LogUtil.CLog;
@@ -54,6 +55,14 @@
  */
 public class BaseDevicePolicyTest extends DeviceTestCase implements IBuildReceiver {
 
+    @Option(
+            name = "skip-device-admin-feature-check",
+            description = "Flag that allows to skip the check for android.software.device_admin "
+                + "and run the tests no matter what. This is useful for system that do not what "
+                + "to expose that feature publicly."
+    )
+    private boolean mSkipDeviceAdminFeatureCheck = false;
+
     private static final String RUNNER = "android.support.test.runner.AndroidJUnitRunner";
 
     protected static final int USER_SYSTEM = 0; // From the UserHandle class.
@@ -122,8 +131,10 @@
     protected void setUp() throws Exception {
         super.setUp();
         assertNotNull(mCtsBuild);  // ensure build has been set before test is run.
-        mHasFeature = getDevice().getApiLevel() >= 21 /* Build.VERSION_CODES.L */
-                && hasDeviceFeature("android.software.device_admin");
+        mHasFeature = getDevice().getApiLevel() >= 21; /* Build.VERSION_CODES.L */
+        if (!mSkipDeviceAdminFeatureCheck) {
+            mHasFeature = mHasFeature && hasDeviceFeature("android.software.device_admin");
+        }
         mSupportsMultiUser = getMaxNumberOfUsersSupported() > 1;
         mSupportsFbe = hasDeviceFeature("android.software.file_based_encryption");
         mFixedPackages = getDevice().getInstalledPackageNames();
diff --git a/hostsidetests/gputools/apps/Android.mk b/hostsidetests/gputools/apps/Android.mk
index 2a2cdd9..c913837 100644
--- a/hostsidetests/gputools/apps/Android.mk
+++ b/hostsidetests/gputools/apps/Android.mk
@@ -30,6 +30,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_MODULE_TAGS := tests
 LOCAL_PACKAGE_NAME := CtsGpuToolsRootlessGpuDebugApp-DEBUG
+LOCAL_SDK_VERSION := current
 
 # tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
@@ -51,6 +52,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_MODULE_TAGS := tests
 LOCAL_PACKAGE_NAME := CtsGpuToolsRootlessGpuDebugApp-RELEASE
+LOCAL_SDK_VERSION := current
 
 # tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
diff --git a/hostsidetests/gputools/layers/Android.mk b/hostsidetests/gputools/layers/Android.mk
index 69f6930..201fafd 100644
--- a/hostsidetests/gputools/layers/Android.mk
+++ b/hostsidetests/gputools/layers/Android.mk
@@ -54,6 +54,7 @@
 LOCAL_MODULE_TAGS := tests
 
 LOCAL_PACKAGE_NAME := CtsGpuToolsRootlessGpuDebugApp-LAYERS
+LOCAL_SDK_VERSION := current
 
 # tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
diff --git a/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/DeviceEventConstants.java b/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/DeviceEventConstants.java
index 1f694d2..06a68f7 100644
--- a/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/DeviceEventConstants.java
+++ b/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/DeviceEventConstants.java
@@ -76,6 +76,11 @@
         ON_CREATE,
 
         /**
+         * {@link android.inputmethodservice.InputMethodService#onBindInput()} callback.
+         */
+        ON_BIND_INPUT,
+
+        /**
          * {@link android.inputmethodservice.InputMethodService#onStartInput(android.view.inputmethod.EditorInfo,boolean) onStartInput(EditorInfo,boolean}
          * callback.
          */
@@ -87,6 +92,11 @@
         ON_START_INPUT_VIEW,
 
         /**
+         * {@link android.inputmethodservice.InputMethodService#onUnbindInput()} callback.
+         */
+        ON_UNBIND_INPUT,
+
+        /**
          * {@link android.inputmethodservice.InputMethodService#onFinishInputView(boolean) onFinishInputView(boolean)}
          * callback.
          */
diff --git a/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/EditTextAppConstants.java b/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/EditTextAppConstants.java
new file mode 100644
index 0000000..f575c55
--- /dev/null
+++ b/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/EditTextAppConstants.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.inputmethodservice.cts.common;
+
+public class EditTextAppConstants {
+    // This is constants holding class, can't instantiate.
+    private EditTextAppConstants() {}
+
+    public static final String PACKAGE = "android.inputmethodservice.cts.edittextapp";
+    public static final String CLASS =   PACKAGE + ".MainActivity";
+    public static final String APK = "EditTextApp.apk";
+}
diff --git a/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/test/DeviceTestConstants.java b/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/test/DeviceTestConstants.java
index 049f32e..dae6db5 100644
--- a/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/test/DeviceTestConstants.java
+++ b/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/test/DeviceTestConstants.java
@@ -45,4 +45,6 @@
     public static final String TEST_SET_INPUTMETHOD_AND_SUBTYPE = "testSetInputMethodAndSubtype";
     public static final String TEST_SWITCH_NEXT_INPUT = "testSwitchToNextInputMethod";
     public static final String TEST_SWITCH_LAST_INPUT = "testSwitchToLastInputMethod";
+    public static final String TEST_INPUT_UNBINDS_ON_IME_STOPPED = "testInputUnbindsOnImeStopped";
+    public static final String TEST_INPUT_UNBINDS_ON_APP_STOPPED = "testInputUnbindsOnAppStopped";
 }
diff --git a/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/test/ShellCommandUtils.java b/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/test/ShellCommandUtils.java
index 643eb52..3d46894 100644
--- a/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/test/ShellCommandUtils.java
+++ b/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/test/ShellCommandUtils.java
@@ -61,6 +61,10 @@
         return "content delete --uri " + contentUri;
     }
 
+    public static String uninstallPackage(String packageName) {
+        return "pm uninstall " + packageName;
+    }
+
     /**
      * Command to send broadcast {@code Intent}.
      *
diff --git a/hostsidetests/inputmethodservice/deviceside/devicetest/src/android/inputmethodservice/cts/devicetest/InputMethodServiceDeviceTest.java b/hostsidetests/inputmethodservice/deviceside/devicetest/src/android/inputmethodservice/cts/devicetest/InputMethodServiceDeviceTest.java
index 0b43dd6..73410e4 100644
--- a/hostsidetests/inputmethodservice/deviceside/devicetest/src/android/inputmethodservice/cts/devicetest/InputMethodServiceDeviceTest.java
+++ b/hostsidetests/inputmethodservice/deviceside/devicetest/src/android/inputmethodservice/cts/devicetest/InputMethodServiceDeviceTest.java
@@ -19,9 +19,14 @@
 import static android.inputmethodservice.cts.DeviceEvent.isFrom;
 import static android.inputmethodservice.cts.DeviceEvent.isNewerThan;
 import static android.inputmethodservice.cts.DeviceEvent.isType;
+import static android.inputmethodservice.cts.common.DeviceEventConstants.DeviceEventType
+        .ON_BIND_INPUT;
 import static android.inputmethodservice.cts.common.DeviceEventConstants.DeviceEventType.ON_CREATE;
 import static android.inputmethodservice.cts.common.DeviceEventConstants.DeviceEventType.ON_DESTROY;
 import static android.inputmethodservice.cts.common.DeviceEventConstants.DeviceEventType.ON_START_INPUT;
+
+import static android.inputmethodservice.cts.common.DeviceEventConstants.DeviceEventType
+        .ON_UNBIND_INPUT;
 import static android.inputmethodservice.cts.common.ImeCommandConstants.ACTION_IME_COMMAND;
 import static android.inputmethodservice.cts.common.ImeCommandConstants
         .COMMAND_SET_INPUT_METHOD_AND_SUBTYPE;
@@ -37,6 +42,7 @@
 
 import android.inputmethodservice.cts.DeviceEvent;
 import android.inputmethodservice.cts.common.DeviceEventConstants.DeviceEventType;
+import android.inputmethodservice.cts.common.EditTextAppConstants;
 import android.inputmethodservice.cts.common.Ime1Constants;
 import android.inputmethodservice.cts.common.Ime2Constants;
 import android.inputmethodservice.cts.common.test.DeviceTestConstants;
@@ -192,6 +198,62 @@
                 TIMEOUT, initialIme + " is current IME");
     }
 
+    @Test
+    public void testInputUnbindsOnImeStopped() throws Throwable {
+        final TestHelper helper = new TestHelper(
+                getClass(), DeviceTestConstants.TEST_INPUT_UNBINDS_ON_IME_STOPPED);
+        final long startActivityTime = SystemClock.uptimeMillis();
+        helper.launchActivity(DeviceTestConstants.PACKAGE, DeviceTestConstants.TEST_ACTIVITY_CLASS);
+        helper.findUiObject(R.id.text_entry).click();
+
+        pollingCheck(() -> helper.queryAllEvents()
+                        .filter(isNewerThan(startActivityTime))
+                        .anyMatch(isFrom(Ime1Constants.CLASS).and(isType(ON_START_INPUT))),
+                TIMEOUT, "CtsInputMethod1.onStartInput is called");
+        pollingCheck(() -> helper.queryAllEvents()
+                        .filter(isNewerThan(startActivityTime))
+                        .anyMatch(isFrom(Ime1Constants.CLASS).and(isType(ON_BIND_INPUT))),
+                TIMEOUT, "CtsInputMethod1.onBindInput is called");
+
+        final long imeForceStopTime = SystemClock.uptimeMillis();
+        helper.shell(ShellCommandUtils.uninstallPackage(Ime1Constants.PACKAGE));
+
+        helper.shell(ShellCommandUtils.setCurrentIme(Ime2Constants.IME_ID));
+        helper.findUiObject(R.id.text_entry).click();
+        pollingCheck(() -> helper.queryAllEvents()
+                        .filter(isNewerThan(imeForceStopTime))
+                        .anyMatch(isFrom(Ime2Constants.CLASS).and(isType(ON_START_INPUT))),
+                TIMEOUT, "CtsInputMethod2.onStartInput is called");
+        pollingCheck(() -> helper.queryAllEvents()
+                        .filter(isNewerThan(imeForceStopTime))
+                        .anyMatch(isFrom(Ime2Constants.CLASS).and(isType(ON_BIND_INPUT))),
+                TIMEOUT, "CtsInputMethod2.onBindInput is called");
+    }
+
+    @Test
+    public void testInputUnbindsOnAppStopped() throws Throwable {
+        final TestHelper helper = new TestHelper(
+                getClass(), DeviceTestConstants.TEST_INPUT_UNBINDS_ON_APP_STOPPED);
+        final long startActivityTime = SystemClock.uptimeMillis();
+        helper.launchActivity(EditTextAppConstants.PACKAGE, EditTextAppConstants.CLASS);
+
+        pollingCheck(() -> helper.queryAllEvents()
+                        .filter(isNewerThan(startActivityTime))
+                        .anyMatch(isFrom(Ime1Constants.CLASS).and(isType(ON_START_INPUT))),
+                TIMEOUT, "CtsInputMethod1.onStartInput is called");
+        pollingCheck(() -> helper.queryAllEvents()
+                        .filter(isNewerThan(startActivityTime))
+                        .anyMatch(isFrom(Ime1Constants.CLASS).and(isType(ON_BIND_INPUT))),
+                TIMEOUT, "CtsInputMethod1.onBindInput is called");
+
+        helper.shell(ShellCommandUtils.uninstallPackage(EditTextAppConstants.PACKAGE));
+
+        pollingCheck(() -> helper.queryAllEvents()
+                        .filter(isNewerThan(startActivityTime))
+                        .anyMatch(isFrom(Ime1Constants.CLASS).and(isType(ON_UNBIND_INPUT))),
+                TIMEOUT, "CtsInputMethod1.onUnBindInput is called");
+    }
+
     /**
      * Build stream collector of {@link DeviceEvent} collecting sequence that elements have
      * specified types.
diff --git a/hostsidetests/inputmethodservice/deviceside/edittextapp/Android.mk b/hostsidetests/inputmethodservice/deviceside/edittextapp/Android.mk
new file mode 100644
index 0000000..96e4e8c
--- /dev/null
+++ b/hostsidetests/inputmethodservice/deviceside/edittextapp/Android.mk
@@ -0,0 +1,41 @@
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Don't include this package in any target
+LOCAL_MODULE_TAGS := tests
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_JAVA_RESOURCE_DIR := res
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    CtsInputMethodServiceCommon \
+    CtsInputMethodServiceLib
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+
+LOCAL_PACKAGE_NAME := EditTextApp
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/inputmethodservice/deviceside/edittextapp/AndroidManifest.xml b/hostsidetests/inputmethodservice/deviceside/edittextapp/AndroidManifest.xml
new file mode 100755
index 0000000..e88ec8e
--- /dev/null
+++ b/hostsidetests/inputmethodservice/deviceside/edittextapp/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2018 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.inputmethodservice.cts.edittextapp">
+    <application
+        android:label="@string/app_name">
+        <activity
+            android:name=".MainActivity"
+            android:exported="true"
+            android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+            </intent-filter>
+        </activity>
+    </application>
+
+    <instrumentation
+        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.inputmethodservice.cts.edittextapp" />
+</manifest>
diff --git a/hostsidetests/inputmethodservice/deviceside/edittextapp/res/layout/activity_inputmethod_test.xml b/hostsidetests/inputmethodservice/deviceside/edittextapp/res/layout/activity_inputmethod_test.xml
new file mode 100644
index 0000000..5c7091a
--- /dev/null
+++ b/hostsidetests/inputmethodservice/deviceside/edittextapp/res/layout/activity_inputmethod_test.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2018 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:padding="10px">
+
+    <EditText
+        android:id="@+id/edit_text_entry"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:background="@android:drawable/editbox_background">
+        <requestFocus />
+    </EditText>
+
+</RelativeLayout>
diff --git a/hostsidetests/inputmethodservice/deviceside/edittextapp/res/values/strings.xml b/hostsidetests/inputmethodservice/deviceside/edittextapp/res/values/strings.xml
new file mode 100644
index 0000000..091901d
--- /dev/null
+++ b/hostsidetests/inputmethodservice/deviceside/edittextapp/res/values/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2018 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<resources>
+    <string name="app_name" translatable="false">EditTextApp</string>
+</resources>
\ No newline at end of file
diff --git a/hostsidetests/inputmethodservice/deviceside/edittextapp/src/android/inputmethodservice/cts/edittextapp/MainActivity.java b/hostsidetests/inputmethodservice/deviceside/edittextapp/src/android/inputmethodservice/cts/edittextapp/MainActivity.java
new file mode 100644
index 0000000..86e9e0a
--- /dev/null
+++ b/hostsidetests/inputmethodservice/deviceside/edittextapp/src/android/inputmethodservice/cts/edittextapp/MainActivity.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package android.inputmethodservice.cts.edittextapp;
+
+import android.app.Activity;
+import android.content.Context;
+import android.widget.EditText;
+import android.os.Bundle;
+import android.view.inputmethod.InputMethodManager;
+import android.view.View;
+import android.view.View.OnFocusChangeListener;
+
+public class MainActivity extends Activity {
+    @Override
+    protected void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_inputmethod_test);
+    }
+}
\ No newline at end of file
diff --git a/hostsidetests/inputmethodservice/deviceside/lib/src/android/inputmethodservice/cts/ime/CtsBaseInputMethod.java b/hostsidetests/inputmethodservice/deviceside/lib/src/android/inputmethodservice/cts/ime/CtsBaseInputMethod.java
index 6ae3568..7896b6e 100644
--- a/hostsidetests/inputmethodservice/deviceside/lib/src/android/inputmethodservice/cts/ime/CtsBaseInputMethod.java
+++ b/hostsidetests/inputmethodservice/deviceside/lib/src/android/inputmethodservice/cts/ime/CtsBaseInputMethod.java
@@ -16,6 +16,8 @@
 
 package android.inputmethodservice.cts.ime;
 
+import static android.inputmethodservice.cts.common.DeviceEventConstants.DeviceEventType
+        .ON_BIND_INPUT;
 import static android.inputmethodservice.cts.common.DeviceEventConstants.DeviceEventType.ON_CREATE;
 import static android.inputmethodservice.cts.common.DeviceEventConstants.DeviceEventType.ON_DESTROY;
 import static android.inputmethodservice.cts.common.DeviceEventConstants.DeviceEventType.ON_FINISH_INPUT;
@@ -23,6 +25,10 @@
 import static android.inputmethodservice.cts.common.DeviceEventConstants.DeviceEventType.ON_START_INPUT;
 import static android.inputmethodservice.cts.common.DeviceEventConstants.DeviceEventType.ON_START_INPUT_VIEW;
 
+
+import static android.inputmethodservice.cts.common.DeviceEventConstants.DeviceEventType
+        .ON_UNBIND_INPUT;
+
 import android.content.Intent;
 import android.inputmethodservice.InputMethodService;
 import android.inputmethodservice.cts.DeviceEvent;
@@ -44,7 +50,7 @@
 
     @Override
     public void onCreate() {
-        mLogTag = getClass().getSimpleName();
+        mLogTag = "CtsBaseInputMethod";//getClass().getSimpleName();
         if (DEBUG) {
             Log.d(mLogTag, "onCreate:");
         }
@@ -56,6 +62,15 @@
     }
 
     @Override
+    public void onBindInput() {
+        if (DEBUG) {
+            Log.d(mLogTag, "onBindInput");
+        }
+        sendEvent(ON_BIND_INPUT);
+        super.onBindInput();
+    }
+
+    @Override
     public void onStartInput(EditorInfo editorInfo, boolean restarting) {
         if (DEBUG) {
             Log.d(mLogTag, "onStartInput:"
@@ -80,6 +95,15 @@
     }
 
     @Override
+    public void onUnbindInput() {
+        super.onUnbindInput();
+        if (DEBUG) {
+            Log.d(mLogTag, "onUnbindInput");
+        }
+        sendEvent(ON_UNBIND_INPUT);
+    }
+
+    @Override
     public void onFinishInputView(boolean finishingInput) {
         if (DEBUG) {
             Log.d(mLogTag, "onFinishInputView: finishingInput=" + finishingInput);
diff --git a/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/InputMethodServiceLifecycleTest.java b/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/InputMethodServiceLifecycleTest.java
index 2e8a8b0..8badded 100644
--- a/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/InputMethodServiceLifecycleTest.java
+++ b/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/InputMethodServiceLifecycleTest.java
@@ -25,6 +25,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
+import android.inputmethodservice.cts.common.EditTextAppConstants;
 import android.inputmethodservice.cts.common.EventProviderConstants.EventTableConstants;
 import android.inputmethodservice.cts.common.Ime1Constants;
 import android.inputmethodservice.cts.common.Ime2Constants;
@@ -151,6 +152,35 @@
         assertTrue(runDeviceTestMethod(testSwitchInputs));
     }
 
+    @Test
+    public void testInputUnbindsOnImeStopped() throws Exception {
+        final TestInfo testUnbind = new TestInfo(
+                DeviceTestConstants.PACKAGE, DeviceTestConstants.TEST_CLASS,
+                DeviceTestConstants.TEST_INPUT_UNBINDS_ON_IME_STOPPED);
+        sendTestStartEvent(testUnbind);
+        installPackage(Ime1Constants.APK, "-r");
+        installPackage(Ime2Constants.APK, "-r");
+        shell(ShellCommandUtils.enableIme(Ime1Constants.IME_ID));
+        shell(ShellCommandUtils.enableIme(Ime2Constants.IME_ID));
+        shell(ShellCommandUtils.setCurrentIme(Ime1Constants.IME_ID));
+
+        assertTrue(runDeviceTestMethod(testUnbind));
+    }
+
+    @Test
+    public void testInputUnbindsOnAppStop() throws Exception {
+        final TestInfo testUnbind = new TestInfo(
+                DeviceTestConstants.PACKAGE, DeviceTestConstants.TEST_CLASS,
+                DeviceTestConstants.TEST_INPUT_UNBINDS_ON_APP_STOPPED);
+        sendTestStartEvent(testUnbind);
+        installPackage(Ime1Constants.APK, "-r");
+        installPackage(EditTextAppConstants.APK, "-r");
+        shell(ShellCommandUtils.enableIme(Ime1Constants.IME_ID));
+        shell(ShellCommandUtils.setCurrentIme(Ime1Constants.IME_ID));
+
+        assertTrue(runDeviceTestMethod(testUnbind));
+    }
+
     private void sendTestStartEvent(final TestInfo deviceTest) throws Exception {
         final String sender = deviceTest.getTestName();
         // {@link EventType#EXTRA_EVENT_TIME} will be recorded at device side.
diff --git a/hostsidetests/jvmti/attaching/app/jni/Android.mk b/hostsidetests/jvmti/attaching/app/jni/Android.mk
index 554fccf..a2c1db6 100644
--- a/hostsidetests/jvmti/attaching/app/jni/Android.mk
+++ b/hostsidetests/jvmti/attaching/app/jni/Android.mk
@@ -27,14 +27,15 @@
 LOCAL_HEADER_LIBRARIES := libopenjdkjvmti_headers
 
 LOCAL_SHARED_LIBRARIES := liblog \
-                          libdl
+                          libdl \
+                          libz
 
 # The test implementation. We get this provided by ART.
 # Note: Needs to be "whole" as this exposes JNI functions.
 LOCAL_WHOLE_STATIC_LIBRARIES := libctstiagent
 
 # Platform libraries that may not be available to apps. Link in statically.
-LOCAL_STATIC_LIBRARIES += libbase libcutils libutils
+LOCAL_STATIC_LIBRARIES += libbase_ndk
 
 LOCAL_STRIP_MODULE := keep_symbols
 
@@ -58,6 +59,7 @@
                  -g \
                  -O0 \
 
-LOCAL_CXX_STL := libc++_static
+LOCAL_SDK_VERSION := current
+LOCAL_NDK_STL_VARIANT := c++_static
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/hostsidetests/jvmti/base/jni/Android.mk b/hostsidetests/jvmti/base/jni/Android.mk
index 0ed5327..8ecf315 100644
--- a/hostsidetests/jvmti/base/jni/Android.mk
+++ b/hostsidetests/jvmti/base/jni/Android.mk
@@ -36,14 +36,15 @@
 LOCAL_HEADER_LIBRARIES := libopenjdkjvmti_headers
 
 LOCAL_SHARED_LIBRARIES := liblog \
-                          libdl
+                          libdl \
+                          libz
 
 # The test implementation. We get this provided by ART.
 # Note: Needs to be "whole" as this exposes JNI functions.
 LOCAL_WHOLE_STATIC_LIBRARIES := libctstiagent
 
 # Platform libraries  that may not be available to apps. Link in statically.
-LOCAL_STATIC_LIBRARIES += libbase libcutils libutils
+LOCAL_STATIC_LIBRARIES += libbase_ndk
 
 LOCAL_STRIP_MODULE := keep_symbols
 
@@ -67,6 +68,7 @@
                  -g \
                  -O0 \
 
-LOCAL_CXX_STL := libc++_static
+LOCAL_SDK_VERSION := current
+LOCAL_NDK_STL_VARIANT := c++_static
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/hostsidetests/os/test-apps/StaticSharedLibConsumerApp1/Android.mk b/hostsidetests/os/test-apps/StaticSharedLibConsumerApp1/Android.mk
index 9d0d001..e4189b1 100644
--- a/hostsidetests/os/test-apps/StaticSharedLibConsumerApp1/Android.mk
+++ b/hostsidetests/os/test-apps/StaticSharedLibConsumerApp1/Android.mk
@@ -29,6 +29,7 @@
 LOCAL_RES_LIBRARIES := CtsStaticSharedLibProviderApp1
 
 LOCAL_PACKAGE_NAME := CtsStaticSharedLibConsumerApp1
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
diff --git a/hostsidetests/os/test-apps/StaticSharedLibConsumerApp2/Android.mk b/hostsidetests/os/test-apps/StaticSharedLibConsumerApp2/Android.mk
index 0c7351a..83bd2b0 100644
--- a/hostsidetests/os/test-apps/StaticSharedLibConsumerApp2/Android.mk
+++ b/hostsidetests/os/test-apps/StaticSharedLibConsumerApp2/Android.mk
@@ -26,6 +26,7 @@
 LOCAL_RES_LIBRARIES := CtsStaticSharedLibProviderApp4
 
 LOCAL_PACKAGE_NAME := CtsStaticSharedLibConsumerApp2
+LOCAL_SDK_VERSION := current
 
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
diff --git a/hostsidetests/os/test-apps/StaticSharedLibConsumerApp3/Android.mk b/hostsidetests/os/test-apps/StaticSharedLibConsumerApp3/Android.mk
index 71f9e8c..8d3a6d2 100644
--- a/hostsidetests/os/test-apps/StaticSharedLibConsumerApp3/Android.mk
+++ b/hostsidetests/os/test-apps/StaticSharedLibConsumerApp3/Android.mk
@@ -26,6 +26,7 @@
 LOCAL_RES_LIBRARIES := CtsStaticSharedLibProviderApp7
 
 LOCAL_PACKAGE_NAME := CtsStaticSharedLibConsumerApp3
+LOCAL_SDK_VERSION := current
 
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
diff --git a/hostsidetests/os/test-apps/StaticSharedLibProviderApp1/Android.mk b/hostsidetests/os/test-apps/StaticSharedLibProviderApp1/Android.mk
index 2e2a5e4..38ccf69 100644
--- a/hostsidetests/os/test-apps/StaticSharedLibProviderApp1/Android.mk
+++ b/hostsidetests/os/test-apps/StaticSharedLibProviderApp1/Android.mk
@@ -23,6 +23,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsStaticSharedLibProviderApp1
+LOCAL_SDK_VERSION := current
 
 LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b
 
diff --git a/hostsidetests/os/test-apps/StaticSharedLibProviderApp3/Android.mk b/hostsidetests/os/test-apps/StaticSharedLibProviderApp3/Android.mk
index 61adc17..16af99a 100644
--- a/hostsidetests/os/test-apps/StaticSharedLibProviderApp3/Android.mk
+++ b/hostsidetests/os/test-apps/StaticSharedLibProviderApp3/Android.mk
@@ -20,6 +20,7 @@
 LOCAL_MODULE_TAGS := tests
 
 LOCAL_PACKAGE_NAME := CtsStaticSharedLibProviderApp3
+LOCAL_SDK_VERSION := current
 
 LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b
 
diff --git a/hostsidetests/os/test-apps/StaticSharedLibProviderApp4/Android.mk b/hostsidetests/os/test-apps/StaticSharedLibProviderApp4/Android.mk
index 0205259..e2c69f2 100644
--- a/hostsidetests/os/test-apps/StaticSharedLibProviderApp4/Android.mk
+++ b/hostsidetests/os/test-apps/StaticSharedLibProviderApp4/Android.mk
@@ -22,6 +22,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsStaticSharedLibProviderApp4
+LOCAL_SDK_VERSION := current
 
 LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
 
diff --git a/hostsidetests/os/test-apps/StaticSharedLibProviderApp7/Android.mk b/hostsidetests/os/test-apps/StaticSharedLibProviderApp7/Android.mk
index 074cae3..4ed03f4 100644
--- a/hostsidetests/os/test-apps/StaticSharedLibProviderApp7/Android.mk
+++ b/hostsidetests/os/test-apps/StaticSharedLibProviderApp7/Android.mk
@@ -23,6 +23,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsStaticSharedLibProviderApp7
+LOCAL_SDK_VERSION := current
 
 LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b
 
diff --git a/hostsidetests/os/test-apps/StaticSharedNativeLibConsumer/Android.mk b/hostsidetests/os/test-apps/StaticSharedNativeLibConsumer/Android.mk
index 54ebdd1..1aed785 100644
--- a/hostsidetests/os/test-apps/StaticSharedNativeLibConsumer/Android.mk
+++ b/hostsidetests/os/test-apps/StaticSharedNativeLibConsumer/Android.mk
@@ -28,6 +28,7 @@
 LOCAL_JNI_SHARED_LIBRARIES := libstaticsharednativelibconsumerjni
 
 LOCAL_PACKAGE_NAME := CtsStaticSharedNativeLibConsumer
+LOCAL_SDK_VERSION := current
 
 LOCAL_MULTILIB := both
 
diff --git a/hostsidetests/os/test-apps/StaticSharedNativeLibProvider/Android.mk b/hostsidetests/os/test-apps/StaticSharedNativeLibProvider/Android.mk
index 3d48af2..b469eac 100644
--- a/hostsidetests/os/test-apps/StaticSharedNativeLibProvider/Android.mk
+++ b/hostsidetests/os/test-apps/StaticSharedNativeLibProvider/Android.mk
@@ -23,6 +23,7 @@
 LOCAL_JNI_SHARED_LIBRARIES := libstaticsharednativelibprovider
 
 LOCAL_PACKAGE_NAME := CtsStaticSharedNativeLibProvider
+LOCAL_SDK_VERSION := current
 
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
diff --git a/hostsidetests/os/test-apps/StaticSharedNativeLibProvider1/Android.mk b/hostsidetests/os/test-apps/StaticSharedNativeLibProvider1/Android.mk
index fee38a7..ff8ef3a 100644
--- a/hostsidetests/os/test-apps/StaticSharedNativeLibProvider1/Android.mk
+++ b/hostsidetests/os/test-apps/StaticSharedNativeLibProvider1/Android.mk
@@ -23,6 +23,7 @@
 LOCAL_JNI_SHARED_LIBRARIES := libstaticsharednativelibprovider
 
 LOCAL_PACKAGE_NAME := CtsStaticSharedNativeLibProvider1
+LOCAL_SDK_VERSION := current
 
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
diff --git a/hostsidetests/statsd/apps/statsdapp/Android.mk b/hostsidetests/statsd/apps/statsdapp/Android.mk
index 9e5890a..ec4b86a 100644
--- a/hostsidetests/statsd/apps/statsdapp/Android.mk
+++ b/hostsidetests/statsd/apps/statsdapp/Android.mk
@@ -16,7 +16,8 @@
 
 include $(CLEAR_VARS)
 
-LOCAL_PACKAGE_NAME := CtsStatsdAtomsApp
+LOCAL_PACKAGE_NAME := CtsStatsdApp
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 # don't include this package in any target
 LOCAL_MODULE_TAGS := optional
diff --git a/hostsidetests/statsd/apps/statsdapp/AndroidManifest.xml b/hostsidetests/statsd/apps/statsdapp/AndroidManifest.xml
index 8f23cd9..04c8c08 100644
--- a/hostsidetests/statsd/apps/statsdapp/AndroidManifest.xml
+++ b/hostsidetests/statsd/apps/statsdapp/AndroidManifest.xml
@@ -43,6 +43,9 @@
         <activity
             android:name=".VideoPlayerActivity"
             android:label="@string/app_name"
+            android:resizeableActivity="true"
+            android:supportsPictureInPicture="true"
+            android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
             android:launchMode="singleTop" >
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
diff --git a/hostsidetests/statsd/apps/statsdapp/AndroidTest.xml b/hostsidetests/statsd/apps/statsdapp/AndroidTest.xml
deleted file mode 100644
index 402a73b..0000000
--- a/hostsidetests/statsd/apps/statsdapp/AndroidTest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?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 Statsd test cases">
-    <option name="test-suite-tag" value="cts" />
-    <option name="config-descriptor:metadata" key="component" value="misc" />
-    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
-        <option name="cleanup-apks" value="true" />
-        <option name="test-file-name" value="CtsStatsdAtomsApp.apk" />
-    </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-        <option name="run-command" value="pm grant com.android.server.cts.device.statsd android.permission.DUMP" />
-        <option name="teardown-command" value="pm revoke com.android.server.cts.device.statsd android.permission.DUMP"/>
-    </target_preparer>
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="com.android.server.cts.device.statsd" />
-        <option name="runtime-hint" value="1m" />
-    </test>
-</configuration>
\ No newline at end of file
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/VideoPlayerActivity.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/VideoPlayerActivity.java
index b15ec35..ea1fcec 100644
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/VideoPlayerActivity.java
+++ b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/VideoPlayerActivity.java
@@ -17,19 +17,71 @@
 package com.android.server.cts.device.statsd;
 
 import android.app.Activity;
+import android.content.Intent;
+import android.os.AsyncTask;
 import android.os.Bundle;
+import android.os.SystemClock;
+import android.util.Log;
 import android.widget.VideoView;
 
 public class VideoPlayerActivity extends Activity {
-    /** Called when the activity is first created. */
+    private static final String TAG = VideoPlayerActivity.class.getSimpleName();
+
+    public static final String KEY_ACTION = "action";
+    public static final String ACTION_PLAY_VIDEO = "action.play_video";
+    public static final String ACTION_PLAY_VIDEO_PICTURE_IN_PICTURE_MODE =
+            "action.play_video_picture_in_picture_mode";
+
+    public static final int DELAY_MILLIS = 2000;
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+
+        Intent intent = this.getIntent();
+        if (intent == null) {
+            Log.e(TAG, "Intent was null.");
+            finish();
+        }
+
+        String action = intent.getStringExtra(KEY_ACTION);
+        Log.i(TAG, "Starting " + action + " from foreground activity.");
+
+        switch (action) {
+            case ACTION_PLAY_VIDEO:
+                playVideo();
+                break;
+            case ACTION_PLAY_VIDEO_PICTURE_IN_PICTURE_MODE:
+                playVideo();
+                this.enterPictureInPictureMode();
+                break;
+            default:
+                Log.e(TAG, "Intent had invalid action " + action);
+                finish();
+        }
+        delay();
+    }
+
+    private void playVideo() {
         setContentView(R.layout.activity_main);
         VideoView videoView = (VideoView)findViewById(R.id.video_player_view);
         videoView.setVideoPath("android.resource://" + getPackageName() + "/" + R.raw.colors_video);
         videoView.start();
     }
+
+    private void delay() {
+        new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(Void... params) {
+                SystemClock.sleep(DELAY_MILLIS);
+                return null;
+            }
+            @Override
+            protected void onPostExecute(Void nothing) {
+                finish();
+            }
+        }.execute();
+    }
 }
 
 
diff --git a/hostsidetests/statsd/src/android/cts/statsd/alert/AnomalyDetectionTests.java b/hostsidetests/statsd/src/android/cts/statsd/alert/AnomalyDetectionTests.java
index 25cb53d..dc2da39 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/alert/AnomalyDetectionTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/alert/AnomalyDetectionTests.java
@@ -47,6 +47,8 @@
     private static final boolean TESTS_ENABLED = false;
     private static final boolean INCIDENTD_TESTS_ENABLED = true;
 
+    private static final int WAIT_AFTER_BREADCRUMB_MS = 2000;
+
     // Config constants
     private static final int APP_BREADCRUMB_REPORTED_MATCH_START_ID = 1;
     private static final int APP_BREADCRUMB_REPORTED_MATCH_STOP_ID = 2;
@@ -109,7 +111,7 @@
         if (INCIDENTD_TESTS_ENABLED) assertFalse("Incident", didIncidentdFireSince(markTime));
 
         doAppBreadcrumbReportedStart(6); // count(label=6) -> 3 (anomaly, since "greater than 2"!)
-        Thread.sleep(1000);
+        Thread.sleep(WAIT_AFTER_BREADCRUMB_MS);
 
         List<EventMetricData> data = getEventMetricDataList();
         assertEquals("Expected 1 anomaly", 1, data.size());
@@ -260,12 +262,12 @@
 
         String markTime = getCurrentLogcatDate();
         doAppBreadcrumbReportedStart(6); // value = 6, which is NOT > trigger
-        Thread.sleep(2000);
+        Thread.sleep(WAIT_AFTER_BREADCRUMB_MS);
         assertEquals("Premature anomaly", 0, getEventMetricDataList().size());
         if (INCIDENTD_TESTS_ENABLED) assertFalse("Incident", didIncidentdFireSince(markTime));
 
         doAppBreadcrumbReportedStart(14); // value = 14 > trigger
-        Thread.sleep(2000);
+        Thread.sleep(WAIT_AFTER_BREADCRUMB_MS);
 
         List<EventMetricData> data = getEventMetricDataList();
         assertEquals("Expected 1 anomaly", 1, data.size());
@@ -274,42 +276,40 @@
         if (INCIDENTD_TESTS_ENABLED) assertTrue("No incident", didIncidentdFireSince(markTime));
     }
 
-    // TODO: Removed until b/73091354 is solved, since it keeps crashing statsd. Update CTS later.
     // Tests that anomaly detection for gauge works.
-//    public void testGaugeAnomalyDetection() throws Exception {
-//        if (!TESTS_ENABLED) return;
-//        StatsdConfig.Builder config = getBaseConfig(1, 20, 6)
-//                .addGaugeMetric(GaugeMetric.newBuilder()
-//                        .setId(METRIC_ID)
-//                        .setWhat(APP_BREADCRUMB_REPORTED_MATCH_START_ID)
-//                        .setBucket(TimeUnit.ONE_MINUTE)
-//                        // Get the label field's value into the gauge:
-//                        .setGaugeFieldsFilter(
-//                                FieldFilter.newBuilder().setFields(FieldMatcher.newBuilder()
-//                                        .setField(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
-//                                        .addChild(FieldMatcher.newBuilder()
-//                                                .setField(AppBreadcrumbReported
-// .LABEL_FIELD_NUMBER))
-//                                )
-//                        )
-//                );
-//        uploadConfig(config);
-//
-//        String markTime = getCurrentLogcatDate();
-//        doAppBreadcrumbReportedStart(6); // gauge = 6, which is NOT > trigger
-//        Thread.sleep(2000);
-//        assertEquals("Premature anomaly", 0, getEventMetricDataList().size());
-//        if (INCIDENTD_TESTS_ENABLED) assertFalse("Incident", didIncidentdFireSince(markTime));
-//
-//        doAppBreadcrumbReportedStart(14); // gauge = 6+1 > trigger
-//        Thread.sleep(2000);
-//
-//        List<EventMetricData> data = getEventMetricDataList();
-//        assertEquals("Expected 1 anomaly", 1, data.size());
-//        AnomalyDetected a = data.get(0).getAtom().getAnomalyDetected();
-//        assertEquals("Wrong alert_id", ALERT_ID, a.getAlertId());
-//        if (INCIDENTD_TESTS_ENABLED) assertTrue("No incident", didIncidentdFireSince(markTime));
-//    }
+    public void testGaugeAnomalyDetection() throws Exception {
+        StatsdConfig.Builder config = getBaseConfig(1, 20, 6 /* threshold: value > 6 */)
+                .addGaugeMetric(GaugeMetric.newBuilder()
+                        .setId(METRIC_ID)
+                        .setWhat(APP_BREADCRUMB_REPORTED_MATCH_START_ID)
+                        .setBucket(TimeUnit.CTS)
+                        // Get the label field's value into the gauge:
+                        .setGaugeFieldsFilter(
+                                FieldFilter.newBuilder().setFields(FieldMatcher.newBuilder()
+                                        .setField(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
+                                        .addChild(FieldMatcher.newBuilder()
+                                                .setField(AppBreadcrumbReported.LABEL_FIELD_NUMBER))
+                                )
+                        )
+                );
+        uploadConfig(config);
+
+        String markTime = getCurrentLogcatDate();
+        doAppBreadcrumbReportedStart(6); // gauge = 6, which is NOT > trigger
+        Thread.sleep(Math.max(WAIT_AFTER_BREADCRUMB_MS, 1_100)); // Must be >1s to push next bucket.
+        assertEquals("Premature anomaly", 0, getEventMetricDataList().size());
+        if (INCIDENTD_TESTS_ENABLED) assertFalse("Incident", didIncidentdFireSince(markTime));
+
+        // We waited for >1s above, so we are now in the next bucket (which is essential).
+        doAppBreadcrumbReportedStart(14); // gauge = 14 > trigger
+        Thread.sleep(WAIT_AFTER_BREADCRUMB_MS);
+
+        List<EventMetricData> data = getEventMetricDataList();
+        assertEquals("Expected 1 anomaly", 1, data.size());
+        AnomalyDetected a = data.get(0).getAtom().getAnomalyDetected();
+        assertEquals("Wrong alert_id", ALERT_ID, a.getAlertId());
+        if (INCIDENTD_TESTS_ENABLED) assertTrue("No incident", didIncidentdFireSince(markTime));
+    }
 
     private final StatsdConfig.Builder getBaseConfig(int numBuckets,
                                                      int refractorySecs,
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java b/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java
index 7f68c63..a067f9d 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java
@@ -504,45 +504,6 @@
         getDevice().rebootUntilOnline();
     }
 
-    protected void assertScreenOff() throws Exception {
-        final long deadLine = System.currentTimeMillis() + SCREEN_STATE_CHANGE_TIMEOUT;
-        boolean screenAwake = true;
-        do {
-            final String dumpsysPower = getDevice().executeShellCommand("dumpsys power").trim();
-            for (String line : dumpsysPower.split("\n")) {
-                if (line.contains("Display Power")) {
-                    screenAwake = line.trim().endsWith("ON");
-                    break;
-                }
-            }
-            Thread.sleep(SCREEN_STATE_POLLING_INTERVAL);
-        } while (screenAwake && System.currentTimeMillis() < deadLine);
-        assertFalse("Screen could not be turned off", screenAwake);
-    }
-
-    protected void assertScreenOn() throws Exception {
-        // this also checks that the keyguard is dismissed
-        final long deadLine = System.currentTimeMillis() + SCREEN_STATE_CHANGE_TIMEOUT;
-        boolean screenAwake;
-        do {
-            final String dumpsysWindowPolicy =
-                    getDevice().executeShellCommand("dumpsys window policy").trim();
-            boolean keyguardStateLines = false;
-            screenAwake = true;
-            for (String line : dumpsysWindowPolicy.split("\n")) {
-                if (line.contains("KeyguardServiceDelegate")) {
-                    keyguardStateLines = true;
-                } else if (keyguardStateLines && line.contains("showing=")) {
-                    screenAwake &= line.trim().endsWith("false");
-                } else if (keyguardStateLines && line.contains("screenState=")) {
-                    screenAwake &= line.trim().endsWith("SCREEN_STATE_ON");
-                }
-            }
-            Thread.sleep(SCREEN_STATE_POLLING_INTERVAL);
-        } while (!screenAwake && System.currentTimeMillis() < deadLine);
-        assertTrue("Screen could not be turned on", screenAwake);
-    }
-
     /**
      * Asserts that the two events are within the specified range of each other.
      *
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/DeviceAtomTestCase.java b/hostsidetests/statsd/src/android/cts/statsd/atom/DeviceAtomTestCase.java
index 0ee2c0d..27a4bc6 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/DeviceAtomTestCase.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/DeviceAtomTestCase.java
@@ -30,7 +30,7 @@
  */
 public class DeviceAtomTestCase extends AtomTestCase {
 
-    protected static final String DEVICE_SIDE_TEST_APK = "CtsStatsdAtomsApp.apk";
+    protected static final String DEVICE_SIDE_TEST_APK = "CtsStatsdApp.apk";
     protected static final String DEVICE_SIDE_TEST_PACKAGE
             = "com.android.server.cts.device.statsd";
 
@@ -164,6 +164,7 @@
      */
     protected void installTestApp() throws Exception {
         installPackage(DEVICE_SIDE_TEST_APK, true);
+        LogUtil.CLog.i("Installing device-side test app with uid " + getUid());
         allowBackgroundServices();
     }
 
@@ -178,10 +179,21 @@
     /**
      * Runs the specified activity for WAIT_TME_LONG.
      */
-    protected void runActivity(String activity) throws Exception {
+    protected void runActivity(String activity, String actionKey, String actionValue)
+            throws Exception {
+        String intentString = null;
+        if (actionKey != null && actionValue != null) {
+            intentString = actionKey + " " + actionValue;
+        }
         turnScreenOn();
-        getDevice().executeShellCommand(
-                "am start -n " + DEVICE_SIDE_TEST_PACKAGE + "/." + activity);
+        if (intentString == null) {
+            getDevice().executeShellCommand(
+                    "am start -n " + DEVICE_SIDE_TEST_PACKAGE + "/." + activity);
+        } else {
+            getDevice().executeShellCommand(
+                    "am start -n " + DEVICE_SIDE_TEST_PACKAGE + "/." + activity + " -e " +
+                            intentString);
+        }
 
         Thread.sleep(WAIT_TIME_LONG);
         getDevice().executeShellCommand(
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/ProcStateAtomTests.java b/hostsidetests/statsd/src/android/cts/statsd/atom/ProcStateAtomTests.java
index 3052937..fdebaa5 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/ProcStateAtomTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/ProcStateAtomTests.java
@@ -143,16 +143,14 @@
         Thread.sleep(WAIT_TIME_FOR_CONFIG_UPDATE_MS);
 
         turnScreenOn();
-        assertScreenOn();
         executeForegroundActivity(ACTION_SHOW_APPLICATION_OVERLAY);
-        final int waitTime = 2 * EXTRA_WAIT_TIME_MS;
+        final int waitTime = EXTRA_WAIT_TIME_MS + 5_000; // Overlay may need to sit there a while.
         Thread.sleep(waitTime + STATSD_REPORT_WAIT_TIME_MS);
+        turnScreenOff();
 
         List<EventMetricData> data = getEventMetricDataList();
         popUntilFind(data, onStates, PROC_STATE_FUNCTION); // clear out initial proc states.
         assertStatesOccurred(stateSet, data, 0, PROC_STATE_FUNCTION);
-
-        turnScreenOff();
     }
 
     public void testBackground() throws Exception {
@@ -184,10 +182,10 @@
         Thread.sleep(WAIT_TIME_FOR_CONFIG_UPDATE_MS);
 
         turnScreenOn();
-        assertScreenOn();
         executeForegroundActivity(ACTION_SLEEP_WHILE_TOP);
         final int waitTime = SLEEP_OF_ACTION_SLEEP_WHILE_TOP + EXTRA_WAIT_TIME_MS;
         Thread.sleep(waitTime + STATSD_REPORT_WAIT_TIME_MS);
+        turnScreenOff();
 
         List<EventMetricData> data = getEventMetricDataList();
         popUntilFind(data, onStates, PROC_STATE_FUNCTION); // clear out initial proc states.
@@ -205,11 +203,9 @@
         Thread.sleep(WAIT_TIME_FOR_CONFIG_UPDATE_MS);
 
         turnScreenOn();
-        assertScreenOn();
         executeForegroundActivity(ACTION_SLEEP_WHILE_TOP);
         // ASAP, turn off the screen to make proc state -> top_sleeping.
         turnScreenOff();
-        assertScreenOff();
         final int waitTime = SLEEP_OF_ACTION_SLEEP_WHILE_TOP + EXTRA_WAIT_TIME_MS;
         Thread.sleep(waitTime + STATSD_REPORT_WAIT_TIME_MS);
 
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
index 0a800f0..344ec44 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
@@ -15,6 +15,8 @@
  */
 package android.cts.statsd.atom;
 
+import static org.junit.Assert.assertTrue;
+
 import android.os.WakeLockLevelEnum;
 
 import com.android.internal.os.StatsdConfigProto.FieldMatcher;
@@ -31,6 +33,7 @@
 import com.android.os.AtomsProto.ForegroundServiceStateChanged;
 import com.android.os.AtomsProto.GpsScanStateChanged;
 import com.android.os.AtomsProto.MediaCodecActivityChanged;
+import com.android.os.AtomsProto.PictureInPictureStateChanged;
 import com.android.os.AtomsProto.ScheduledJobStateChanged;
 import com.android.os.AtomsProto.SyncStateChanged;
 import com.android.os.AtomsProto.WakelockStateChanged;
@@ -45,6 +48,7 @@
 import java.util.List;
 import java.util.Set;
 
+
 /**
  * Statsd atom tests that are done via app, for atoms that report a uid.
  */
@@ -319,7 +323,7 @@
         final int atomTag = Atom.DAVEY_OCCURRED_FIELD_NUMBER;
         createAndUploadConfig(atomTag); // Does not have UID, but needs a device-side compnent.
 
-        runActivity("DaveyActivity");
+        runActivity("DaveyActivity", null, null);
 
         List<EventMetricData> data = getEventMetricDataList();
         assertTrue(data.size() == 1);
@@ -548,7 +552,7 @@
         createAndUploadConfig(atomTag, true);  // True: uses attribution.
         Thread.sleep(WAIT_TIME_SHORT);
 
-        runActivity("VideoPlayerActivity");
+        runActivity("VideoPlayerActivity", "action", "action.play_video");
 
         // Sorted list of events in order in which they occurred.
         List<EventMetricData> data = getEventMetricDataList();
@@ -557,4 +561,26 @@
         assertStatesOccurred(stateSet, data, WAIT_TIME_LONG,
                 atom -> atom.getMediaCodecActivityChanged().getState().getNumber());
     }
+
+    public void testPictureInPictureState() throws Exception {
+        if (!TESTS_ENABLED) return;
+        final int atomTag = Atom.PICTURE_IN_PICTURE_STATE_CHANGED_FIELD_NUMBER;
+
+        Set<Integer> entered = new HashSet<>(
+                Arrays.asList(PictureInPictureStateChanged.State.ENTERED_VALUE));
+
+        // Add state sets to the list in order.
+        List<Set<Integer>> stateSet = Arrays.asList(entered);
+
+        createAndUploadConfig(atomTag, false);
+
+        runActivity("VideoPlayerActivity", "action", "action.play_video_picture_in_picture_mode");
+
+        // Sorted list of events in order in which they occurred.
+        List<EventMetricData> data = getEventMetricDataList();
+
+        // Assert that the events happened in the expected order.
+        assertStatesOccurred(stateSet, data, WAIT_TIME_LONG,
+                atom -> atom.getPictureInPictureStateChanged().getState().getNumber());
+    }
 }
diff --git a/hostsidetests/statsd/src/android/cts/statsd/metric/DurationMetricsTests.java b/hostsidetests/statsd/src/android/cts/statsd/metric/DurationMetricsTests.java
index 0bb333f..1969e5b 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/metric/DurationMetricsTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/metric/DurationMetricsTests.java
@@ -44,8 +44,10 @@
 
     public void testDurationMetric() throws Exception {
         // Add AtomMatcher's.
-        AtomMatcher startAtomMatcher = startAtomMatcher(APP_BREADCRUMB_REPORTED_A_MATCH_START_ID);
-        AtomMatcher stopAtomMatcher = stopAtomMatcher(APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID);
+        AtomMatcher startAtomMatcher =
+            MetricsUtils.startAtomMatcher(APP_BREADCRUMB_REPORTED_A_MATCH_START_ID);
+        AtomMatcher stopAtomMatcher =
+            MetricsUtils.stopAtomMatcher(APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID);
 
         StatsdConfigProto.StatsdConfig.Builder builder = MetricsUtils.getEmptyConfig();
         builder.addAtomMatcher(startAtomMatcher);
@@ -57,15 +59,16 @@
                 .setStop(APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID)
                 .build();
         Predicate predicate = Predicate.newBuilder()
-                .setId(StringToId("Predicate"))
-                .setSimplePredicate(simplePredicate)
-                .build();
+                                  .setId(MetricsUtils.StringToId("Predicate"))
+                                  .setSimplePredicate(simplePredicate)
+                                  .build();
         builder.addPredicate(predicate);
 
         // Add DurationMetric.
-        builder.addDurationMetric(StatsdConfigProto.DurationMetric.newBuilder()
+        builder.addDurationMetric(
+            StatsdConfigProto.DurationMetric.newBuilder()
                 .setId(MetricsUtils.DURATION_METRIC_ID)
-                .setWhat(StringToId("Predicate"))
+                .setWhat(predicate.getId())
                 .setAggregationType(StatsdConfigProto.DurationMetric.AggregationType.SUM)
                 .setBucket(StatsdConfigProto.TimeUnit.CTS));
 
@@ -92,10 +95,14 @@
 
     public void testDurationMetricWithDimension() throws Exception {
         // Add AtomMatcher's.
-        AtomMatcher startAtomMatcherA = startAtomMatcher(APP_BREADCRUMB_REPORTED_A_MATCH_START_ID);
-        AtomMatcher stopAtomMatcherA = stopAtomMatcher(APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID);
-        AtomMatcher startAtomMatcherB = startAtomMatcher(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID);
-        AtomMatcher stopAtomMatcherB = stopAtomMatcher(APP_BREADCRUMB_REPORTED_B_MATCH_STOP_ID);
+        AtomMatcher startAtomMatcherA =
+            MetricsUtils.startAtomMatcher(APP_BREADCRUMB_REPORTED_A_MATCH_START_ID);
+        AtomMatcher stopAtomMatcherA =
+            MetricsUtils.stopAtomMatcher(APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID);
+        AtomMatcher startAtomMatcherB =
+            MetricsUtils.startAtomMatcher(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID);
+        AtomMatcher stopAtomMatcherB =
+            MetricsUtils.stopAtomMatcher(APP_BREADCRUMB_REPORTED_B_MATCH_STOP_ID);
 
         StatsdConfigProto.StatsdConfig.Builder builder = MetricsUtils.getEmptyConfig();
         builder.addAtomMatcher(startAtomMatcherA);
@@ -109,9 +116,9 @@
                 .setStop(APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID)
                 .build();
         Predicate predicateA = Predicate.newBuilder()
-                .setId(StringToId("Predicate_A"))
-                .setSimplePredicate(simplePredicateA)
-                .build();
+                                   .setId(MetricsUtils.StringToId("Predicate_A"))
+                                   .setSimplePredicate(simplePredicateA)
+                                   .build();
         builder.addPredicate(predicateA);
 
         FieldMatcher.Builder dimensionsBuilder = FieldMatcher.newBuilder()
@@ -121,30 +128,33 @@
                 .setPosition(Position.FIRST)
                 .addChild(FieldMatcher.newBuilder().setField(
                         AppBreadcrumbReported.LABEL_FIELD_NUMBER)));
-        Predicate predicateB = Predicate.newBuilder()
-                .setId(StringToId("Predicate_B"))
+        Predicate predicateB =
+            Predicate.newBuilder()
+                .setId(MetricsUtils.StringToId("Predicate_B"))
                 .setSimplePredicate(SimplePredicate.newBuilder()
-                        .setStart(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID)
-                        .setStop(APP_BREADCRUMB_REPORTED_B_MATCH_STOP_ID)
-                        .setDimensions(dimensionsBuilder.build())
-                        .build())
+                                        .setStart(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID)
+                                        .setStop(APP_BREADCRUMB_REPORTED_B_MATCH_STOP_ID)
+                                        .setDimensions(dimensionsBuilder.build())
+                                        .build())
                 .build();
         builder.addPredicate(predicateB);
 
         // Add DurationMetric.
-        builder.addDurationMetric(StatsdConfigProto.DurationMetric.newBuilder()
+        builder.addDurationMetric(
+            StatsdConfigProto.DurationMetric.newBuilder()
                 .setId(MetricsUtils.DURATION_METRIC_ID)
-                .setWhat(StringToId("Predicate_B"))
-                .setCondition(StringToId("Predicate_A"))
+                .setWhat(predicateB.getId())
+                .setCondition(predicateA.getId())
                 .setAggregationType(StatsdConfigProto.DurationMetric.AggregationType.SUM)
                 .setBucket(StatsdConfigProto.TimeUnit.CTS)
-                .setDimensionsInWhat(FieldMatcher.newBuilder()
+                .setDimensionsInWhat(
+                    FieldMatcher.newBuilder()
                         .setField(Atom.BATTERY_SAVER_MODE_STATE_CHANGED_FIELD_NUMBER)
                         .addChild(FieldMatcher.newBuilder()
-                                .setField(AppBreadcrumbReported.STATE_FIELD_NUMBER)
-                                .setPosition(Position.FIRST)
-                                .addChild(FieldMatcher.newBuilder().setField(
-                                        AppBreadcrumbReported.LABEL_FIELD_NUMBER)))));
+                                      .setField(AppBreadcrumbReported.STATE_FIELD_NUMBER)
+                                      .setPosition(Position.FIRST)
+                                      .addChild(FieldMatcher.newBuilder().setField(
+                                          AppBreadcrumbReported.LABEL_FIELD_NUMBER)))));
 
         // Upload config.
         uploadConfig(builder);
@@ -173,30 +183,4 @@
             assertTrue(bucketInfo.getDurationNanos() < 1e10);
         }
     }
-
-    private AtomMatcher startAtomMatcher(int id) {
-        return AtomMatcher.newBuilder()
-                .setId(id)
-                .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
-                        .setAtomId(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
-                        .addFieldValueMatcher(FieldValueMatcher.newBuilder()
-                                .setField(AppBreadcrumbReported.STATE_FIELD_NUMBER)
-                                .setEqInt(AppBreadcrumbReported.State.START.ordinal())))
-                .build();
-    }
-
-    private AtomMatcher stopAtomMatcher(int id) {
-        return AtomMatcher.newBuilder()
-                .setId(id)
-                .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
-                        .setAtomId(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
-                        .addFieldValueMatcher(FieldValueMatcher.newBuilder()
-                                .setField(AppBreadcrumbReported.STATE_FIELD_NUMBER)
-                                .setEqInt(AppBreadcrumbReported.State.STOP.ordinal())))
-                .build();
-    }
-
-    private long StringToId(String str) {
-        return str.hashCode();
-    }
 }
diff --git a/hostsidetests/statsd/src/android/cts/statsd/metric/GaugeMetricsTests.java b/hostsidetests/statsd/src/android/cts/statsd/metric/GaugeMetricsTests.java
new file mode 100644
index 0000000..92b840e
--- /dev/null
+++ b/hostsidetests/statsd/src/android/cts/statsd/metric/GaugeMetricsTests.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.cts.statsd.metric;
+
+import android.cts.statsd.atom.DeviceAtomTestCase;
+
+import com.android.internal.os.StatsdConfigProto;
+import com.android.internal.os.StatsdConfigProto.AtomMatcher;
+import com.android.internal.os.StatsdConfigProto.FieldFilter;
+import com.android.internal.os.StatsdConfigProto.FieldMatcher;
+import com.android.internal.os.StatsdConfigProto.FieldValueMatcher;
+import com.android.internal.os.StatsdConfigProto.Predicate;
+import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
+import com.android.internal.os.StatsdConfigProto.SimplePredicate;
+import com.android.os.AtomsProto.AppBreadcrumbReported;
+import com.android.os.AtomsProto.Atom;
+import com.android.os.StatsLog.GaugeMetricData;
+import com.android.os.StatsLog.StatsLogReport;
+
+public class GaugeMetricsTests extends DeviceAtomTestCase {
+
+  private static final int APP_BREADCRUMB_REPORTED_A_MATCH_START_ID = 0;
+  private static final int APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID = 1;
+  private static final int APP_BREADCRUMB_REPORTED_B_MATCH_START_ID = 2;
+
+  public void testGaugeMetric() throws Exception {
+    // Add AtomMatcher's.
+    AtomMatcher startAtomMatcher =
+        MetricsUtils.startAtomMatcher(APP_BREADCRUMB_REPORTED_A_MATCH_START_ID);
+    AtomMatcher stopAtomMatcher =
+        MetricsUtils.stopAtomMatcher(APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID);
+    AtomMatcher atomMatcher =
+        MetricsUtils.simpleAtomMatcher(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID);
+
+    StatsdConfigProto.StatsdConfig.Builder builder = MetricsUtils.getEmptyConfig();
+    builder.addAtomMatcher(startAtomMatcher);
+    builder.addAtomMatcher(stopAtomMatcher);
+    builder.addAtomMatcher(atomMatcher);
+
+    // Add Predicate's.
+    SimplePredicate simplePredicate = SimplePredicate.newBuilder()
+                                          .setStart(APP_BREADCRUMB_REPORTED_A_MATCH_START_ID)
+                                          .setStop(APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID)
+                                          .build();
+    Predicate predicate = Predicate.newBuilder()
+                              .setId(MetricsUtils.StringToId("Predicate"))
+                              .setSimplePredicate(simplePredicate)
+                              .build();
+    builder.addPredicate(predicate);
+
+    // Add GaugeMetric.
+    FieldMatcher fieldMatcher =
+        FieldMatcher.newBuilder().setField(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID).build();
+    builder.addGaugeMetric(
+        StatsdConfigProto.GaugeMetric.newBuilder()
+            .setId(MetricsUtils.GAUGE_METRIC_ID)
+            .setWhat(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID)
+            .setCondition(predicate.getId())
+            .setGaugeFieldsFilter(
+                FieldFilter.newBuilder().setIncludeAll(false).setFields(fieldMatcher).build())
+            .setDimensionsInWhat(
+                FieldMatcher.newBuilder()
+                    .setField(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID)
+                    .addChild(FieldMatcher.newBuilder()
+                                  .setField(AppBreadcrumbReported.STATE_FIELD_NUMBER)
+                                  .build())
+                    .build())
+            .setBucket(StatsdConfigProto.TimeUnit.CTS)
+            .build());
+
+    // Upload config.
+    uploadConfig(builder);
+
+    // Create AppBreadcrumbReported Start/Stop events.
+    doAppBreadcrumbReportedStart(0);
+    Thread.sleep(10);
+    doAppBreadcrumbReportedStart(1);
+    Thread.sleep(10);
+    doAppBreadcrumbReportedStart(2);
+    Thread.sleep(2000);
+    doAppBreadcrumbReportedStop(2);
+    Thread.sleep(10);
+    doAppBreadcrumbReportedStop(0);
+    Thread.sleep(10);
+    doAppBreadcrumbReportedStop(1);
+    doAppBreadcrumbReportedStart(2);
+    Thread.sleep(10);
+    doAppBreadcrumbReportedStart(1);
+    Thread.sleep(2000);
+    doAppBreadcrumbReportedStop(2);
+    Thread.sleep(10);
+    doAppBreadcrumbReportedStop(1);
+
+    // Wait for the metrics to propagate to statsd.
+    Thread.sleep(2000);
+
+    StatsLogReport metricReport = getStatsLogReport();
+    assertEquals(MetricsUtils.GAUGE_METRIC_ID, metricReport.getMetricId());
+    assertTrue(metricReport.hasGaugeMetrics());
+    StatsLogReport.GaugeMetricDataWrapper gaugeData = metricReport.getGaugeMetrics();
+    assertEquals(gaugeData.getDataCount(), 1);
+
+    int bucketCount = gaugeData.getData(0).getBucketInfoCount();
+    GaugeMetricData data = gaugeData.getData(0);
+    assertTrue(bucketCount > 2);
+    assertTrue(data.getBucketInfo(0).hasStartBucketNanos());
+    assertTrue(data.getBucketInfo(0).hasEndBucketNanos());
+    assertEquals(data.getBucketInfo(0).getAtomCount(), 1);
+    assertEquals(data.getBucketInfo(0).getAtom(0).getAppBreadcrumbReported().getLabel(), 0);
+    assertEquals(data.getBucketInfo(0).getAtom(0).getAppBreadcrumbReported().getState(),
+        AppBreadcrumbReported.State.START);
+
+    assertTrue(data.getBucketInfo(1).hasStartBucketNanos());
+    assertTrue(data.getBucketInfo(1).hasEndBucketNanos());
+    assertEquals(data.getBucketInfo(1).getAtomCount(), 1);
+
+    assertTrue(data.getBucketInfo(bucketCount - 1).hasStartBucketNanos());
+    assertTrue(data.getBucketInfo(bucketCount - 1).hasEndBucketNanos());
+    assertEquals(data.getBucketInfo(bucketCount - 1).getAtomCount(), 1);
+    assertEquals(
+        data.getBucketInfo(bucketCount - 1).getAtom(0).getAppBreadcrumbReported().getLabel(), 2);
+    assertEquals(
+        data.getBucketInfo(bucketCount - 1).getAtom(0).getAppBreadcrumbReported().getState(),
+        AppBreadcrumbReported.State.STOP);
+  }
+}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/metric/MetricsUtils.java b/hostsidetests/statsd/src/android/cts/statsd/metric/MetricsUtils.java
index e7b21a6..c5ef40c 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/metric/MetricsUtils.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/metric/MetricsUtils.java
@@ -17,11 +17,16 @@
 
 import com.android.internal.os.StatsdConfigProto;
 import com.android.internal.os.StatsdConfigProto.AtomMatcher;
+import com.android.internal.os.StatsdConfigProto.FieldValueMatcher;
 import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
+import com.android.os.AtomsProto.Atom;
+import com.android.os.AtomsProto.AppBreadcrumbReported;
 
 public class MetricsUtils {
     public static final long COUNT_METRIC_ID = 3333;
     public static final long DURATION_METRIC_ID = 4444;
+    public static final long GAUGE_METRIC_ID = 5555;
+    public static final long VALUE_METRIC_ID = 6666;
 
     public static StatsdConfigProto.StatsdConfig.Builder getEmptyConfig() {
         StatsdConfigProto.StatsdConfig.Builder builder =
@@ -38,4 +43,40 @@
                         .setAtomId(atomId).build());
         return builder;
     }
+
+    public static AtomMatcher startAtomMatcher(int id) {
+      return AtomMatcher.newBuilder()
+          .setId(id)
+          .setSimpleAtomMatcher(
+              SimpleAtomMatcher.newBuilder()
+                  .setAtomId(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
+                  .addFieldValueMatcher(FieldValueMatcher.newBuilder()
+                                            .setField(AppBreadcrumbReported.STATE_FIELD_NUMBER)
+                                            .setEqInt(AppBreadcrumbReported.State.START.ordinal())))
+          .build();
+    }
+
+    public static AtomMatcher stopAtomMatcher(int id) {
+      return AtomMatcher.newBuilder()
+          .setId(id)
+          .setSimpleAtomMatcher(
+              SimpleAtomMatcher.newBuilder()
+                  .setAtomId(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
+                  .addFieldValueMatcher(FieldValueMatcher.newBuilder()
+                                            .setField(AppBreadcrumbReported.STATE_FIELD_NUMBER)
+                                            .setEqInt(AppBreadcrumbReported.State.STOP.ordinal())))
+          .build();
+    }
+
+    public static AtomMatcher simpleAtomMatcher(int id) {
+      return AtomMatcher.newBuilder()
+          .setId(id)
+          .setSimpleAtomMatcher(
+              SimpleAtomMatcher.newBuilder().setAtomId(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER))
+          .build();
+    }
+
+    public static long StringToId(String str) {
+      return str.hashCode();
+    }
 }
diff --git a/hostsidetests/statsd/src/android/cts/statsd/metric/ValueMetricsTests.java b/hostsidetests/statsd/src/android/cts/statsd/metric/ValueMetricsTests.java
new file mode 100644
index 0000000..44b3a48
--- /dev/null
+++ b/hostsidetests/statsd/src/android/cts/statsd/metric/ValueMetricsTests.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.cts.statsd.metric;
+
+import android.cts.statsd.atom.DeviceAtomTestCase;
+
+import com.android.internal.os.StatsdConfigProto;
+import com.android.internal.os.StatsdConfigProto.AtomMatcher;
+import com.android.internal.os.StatsdConfigProto.FieldMatcher;
+import com.android.internal.os.StatsdConfigProto.ValueMetric;
+import com.android.os.AtomsProto.AppBreadcrumbReported;
+import com.android.os.AtomsProto.Atom;
+import com.android.os.StatsLog.ValueBucketInfo;
+import com.android.os.StatsLog.ValueMetricData;
+import com.android.os.StatsLog.StatsLogReport;
+
+public class ValueMetricsTests extends DeviceAtomTestCase {
+  private static final int APP_BREADCRUMB_REPORTED_A_MATCH_START_ID = 0;
+  private static final int APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID = 1;
+  private static final int APP_BREADCRUMB_REPORTED_B_MATCH_START_ID = 2;
+
+  public void testValueMetric() throws Exception {
+    // Add AtomMatcher's.
+    AtomMatcher startAtomMatcher =
+        MetricsUtils.startAtomMatcher(APP_BREADCRUMB_REPORTED_A_MATCH_START_ID);
+    AtomMatcher stopAtomMatcher =
+        MetricsUtils.stopAtomMatcher(APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID);
+    AtomMatcher atomMatcher =
+        MetricsUtils.simpleAtomMatcher(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID);
+
+    StatsdConfigProto.StatsdConfig.Builder builder = MetricsUtils.getEmptyConfig();
+    builder.addAtomMatcher(startAtomMatcher);
+    builder.addAtomMatcher(stopAtomMatcher);
+    builder.addAtomMatcher(atomMatcher);
+
+    // Add ValueMetric.
+    FieldMatcher fieldMatcher =
+        FieldMatcher.newBuilder().setField(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID).build();
+    builder.addValueMetric(
+        ValueMetric.newBuilder()
+            .setId(MetricsUtils.VALUE_METRIC_ID)
+            .setWhat(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID)
+            .setBucket(StatsdConfigProto.TimeUnit.CTS)
+            .setValueField(FieldMatcher.newBuilder()
+                               .setField(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
+                               .addChild(FieldMatcher.newBuilder().setField(
+                                   AppBreadcrumbReported.LABEL_FIELD_NUMBER)))
+            .setDimensionsInWhat(FieldMatcher.newBuilder()
+                                     .setField(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID)
+                                     .build())
+            .build());
+
+    // Upload config.
+    uploadConfig(builder);
+
+    // Create AppBreadcrumbReported Start/Stop events.
+    doAppBreadcrumbReportedStart(1);
+    Thread.sleep(1000);
+    doAppBreadcrumbReportedStop(1);
+    doAppBreadcrumbReportedStart(3);
+    doAppBreadcrumbReportedStop(3);
+
+    // Wait for the metrics to propagate to statsd.
+    Thread.sleep(2000);
+
+    StatsLogReport metricReport = getStatsLogReport();
+    assertEquals(MetricsUtils.VALUE_METRIC_ID, metricReport.getMetricId());
+    assertTrue(metricReport.hasValueMetrics());
+    StatsLogReport.ValueMetricDataWrapper valueData = metricReport.getValueMetrics();
+    assertEquals(valueData.getDataCount(), 1);
+
+    int bucketCount = valueData.getData(0).getBucketInfoCount();
+    assertTrue(bucketCount > 1);
+    ValueMetricData data = valueData.getData(0);
+    int totalValue = 0;
+    for (ValueBucketInfo bucketInfo : data.getBucketInfoList()) {
+      assertTrue(bucketInfo.hasStartBucketElapsedNanos());
+      assertTrue(bucketInfo.hasEndBucketElapsedNanos());
+      totalValue += (int) bucketInfo.getValue();
+    }
+    assertEquals(totalValue, 8);
+  }
+}
diff --git a/tests/JobScheduler/Android.mk b/tests/JobScheduler/Android.mk
index 0ea7527..622c06e 100755
--- a/tests/JobScheduler/Android.mk
+++ b/tests/JobScheduler/Android.mk
@@ -36,6 +36,7 @@
 LOCAL_PACKAGE_NAME := CtsJobSchedulerTestCases
 
 #LOCAL_SDK_VERSION := current
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_CTS_PACKAGE)
 
diff --git a/tests/JobScheduler/JobTestApp/Android.mk b/tests/JobScheduler/JobTestApp/Android.mk
index f7b7a1d..61f7116 100644
--- a/tests/JobScheduler/JobTestApp/Android.mk
+++ b/tests/JobScheduler/JobTestApp/Android.mk
@@ -26,5 +26,6 @@
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
 LOCAL_PACKAGE_NAME := CtsJobTestApp
+LOCAL_SDK_VERSION := current
 
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/JobScheduler/jobperm/Android.mk b/tests/JobScheduler/jobperm/Android.mk
index f54f8d6..af892d9 100644
--- a/tests/JobScheduler/jobperm/Android.mk
+++ b/tests/JobScheduler/jobperm/Android.mk
@@ -29,5 +29,6 @@
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
 LOCAL_PACKAGE_NAME := CtsJobSchedulerJobPerm
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/JobScheduler/shareduid/Android.mk b/tests/JobScheduler/shareduid/Android.mk
index ac4d8b3f..98a9707 100644
--- a/tests/JobScheduler/shareduid/Android.mk
+++ b/tests/JobScheduler/shareduid/Android.mk
@@ -29,5 +29,6 @@
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
 LOCAL_PACKAGE_NAME := CtsJobSchedulerSharedUid
+LOCAL_SDK_VERSION := current
 
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/ProcessTest/NoShareUidApp/Android.mk b/tests/ProcessTest/NoShareUidApp/Android.mk
index c667dbe..7645b5c 100644
--- a/tests/ProcessTest/NoShareUidApp/Android.mk
+++ b/tests/ProcessTest/NoShareUidApp/Android.mk
@@ -24,6 +24,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := NoShareUidApp
+LOCAL_SDK_VERSION := current
 
 LOCAL_PROGUARD_ENABLED := disabled
 LOCAL_DEX_PREOPT := false
diff --git a/tests/ProcessTest/ShareUidApp/Android.mk b/tests/ProcessTest/ShareUidApp/Android.mk
index d79eda4..fdd3feb 100644
--- a/tests/ProcessTest/ShareUidApp/Android.mk
+++ b/tests/ProcessTest/ShareUidApp/Android.mk
@@ -24,6 +24,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := ShareUidApp
+LOCAL_SDK_VERSION := current
 
 LOCAL_PROGUARD_ENABLED := disabled
 LOCAL_DEX_PREOPT := false
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityEventTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityEventTest.java
index 5348373..d123d8f 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityEventTest.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityEventTest.java
@@ -18,6 +18,7 @@
 
 import android.os.Message;
 import android.os.Parcel;
+import android.platform.test.annotations.Presubmit;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.text.TextUtils;
 import android.view.accessibility.AccessibilityEvent;
@@ -29,6 +30,7 @@
 /**
  * Class for testing {@link AccessibilityEvent}.
  */
+@Presubmit
 public class AccessibilityEventTest extends TestCase {
 
     /** The number of properties of the {@link AccessibilityEvent} class. */
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
index 6a4efd8..ccb5a6d 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
@@ -46,8 +46,6 @@
     private static final String MULTIPLE_FEEDBACK_TYPES_ACCESSIBILITY_SERVICE_NAME =
         "android.view.accessibility.cts.SpeakingAndVibratingAccessibilityService";
 
-    private static final long WAIT_FOR_ACCESSIBILITY_ENABLED_TIMEOUT = 3000; // 3s
-
     private AccessibilityManager mAccessibilityManager;
 
     private Context mTargetContext;
@@ -334,7 +332,8 @@
     private void assertAtomicBooleanBecomes(AtomicBoolean atomicBoolean,
             boolean expectedValue, Object waitObject, String message)
             throws Exception {
-        long timeoutTime = System.currentTimeMillis() + WAIT_FOR_ACCESSIBILITY_ENABLED_TIMEOUT;
+        long timeoutTime =
+                System.currentTimeMillis() + ServiceControlUtils.TIMEOUT_FOR_SERVICE_ENABLE;
         synchronized (waitObject) {
             while ((atomicBoolean.get() != expectedValue)
                     && (System.currentTimeMillis() < timeoutTime)) {
@@ -353,7 +352,8 @@
             }
         };
         mAccessibilityManager.addAccessibilityStateChangeListener(listener);
-        long timeoutTime = System.currentTimeMillis() + WAIT_FOR_ACCESSIBILITY_ENABLED_TIMEOUT;
+        long timeoutTime =
+                System.currentTimeMillis() + ServiceControlUtils.TIMEOUT_FOR_SERVICE_ENABLE;
         synchronized (waitObject) {
             while (!mAccessibilityManager.isEnabled()
                     && (System.currentTimeMillis() < timeoutTime)) {
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java
index 2b5f6ae..458c0d3 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java
@@ -18,6 +18,7 @@
 
 import android.graphics.Rect;
 import android.os.Parcel;
+import android.platform.test.annotations.Presubmit;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.text.TextUtils;
@@ -33,6 +34,7 @@
 /**
  * Class for testing {@link AccessibilityNodeInfo}.
  */
+@Presubmit
 public class AccessibilityNodeInfoTest extends AndroidTestCase {
 
     /** The number of properties of the {@link AccessibilityNodeInfo} class that are marshalled. */
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfo_CollectionInfoTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfo_CollectionInfoTest.java
index d64bd94..98b87fc 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfo_CollectionInfoTest.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfo_CollectionInfoTest.java
@@ -16,6 +16,7 @@
 
 package android.view.accessibility.cts;
 
+import android.platform.test.annotations.Presubmit;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.view.accessibility.AccessibilityNodeInfo.CollectionInfo;
@@ -23,6 +24,7 @@
 /**
  * Class for testing {@link CollectionInfo}.
  */
+@Presubmit
 public class AccessibilityNodeInfo_CollectionInfoTest extends AndroidTestCase {
 
     @SmallTest
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfo_RangeInfoTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfo_RangeInfoTest.java
index 954d762..4b01129 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfo_RangeInfoTest.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfo_RangeInfoTest.java
@@ -16,6 +16,7 @@
 
 package android.view.accessibility.cts;
 
+import android.platform.test.annotations.Presubmit;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -24,6 +25,7 @@
 /**
  * Class for testing {@link AccessibilityNodeInfo.RangeInfo}.
  */
+@Presubmit
 public class AccessibilityNodeInfo_RangeInfoTest extends AndroidTestCase {
 
     /** Allowed tolerance for floating point equality comparisons. */
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeProviderTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeProviderTest.java
index eeee235..0c2a2dd 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeProviderTest.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeProviderTest.java
@@ -16,6 +16,7 @@
 
 package android.view.accessibility.cts;
 
+import android.platform.test.annotations.Presubmit;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.view.accessibility.AccessibilityNodeProvider;
@@ -23,6 +24,7 @@
 /**
  * Class for testing {@link AccessibilityNodeProvider}.
  */
+@Presubmit
 public class AccessibilityNodeProviderTest extends AndroidTestCase {
     @SmallTest
     public void testDefaultBehavior() {
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityRecordTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityRecordTest.java
index 5bf02c8..a12ccce 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityRecordTest.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityRecordTest.java
@@ -17,6 +17,7 @@
 package android.view.accessibility.cts;
 
 import android.os.Message;
+import android.platform.test.annotations.Presubmit;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.view.accessibility.AccessibilityEvent;
@@ -32,6 +33,7 @@
 /**
  * Class for testing {@link AccessibilityRecord}.
  */
+@Presubmit
 public class AccessibilityRecordTest extends AndroidTestCase {
 
     /** The number of properties of the {@link AccessibilityEvent} class. */
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityWindowInfoTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityWindowInfoTest.java
index ffbe833..760340d 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityWindowInfoTest.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityWindowInfoTest.java
@@ -18,6 +18,7 @@
 
 import android.graphics.Rect;
 import android.os.Parcel;
+import android.platform.test.annotations.Presubmit;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.text.TextUtils;
@@ -26,6 +27,7 @@
 /**
  * Class for testing {@link AccessibilityWindowInfo}.
  */
+@Presubmit
 public class AccessibilityWindowInfoTest extends AndroidTestCase {
 
     @SmallTest
diff --git a/tests/accessibility/src/android/view/accessibility/cts/CaptioningManagerTest.java b/tests/accessibility/src/android/view/accessibility/cts/CaptioningManagerTest.java
index 86c6f41..d0db868 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/CaptioningManagerTest.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/CaptioningManagerTest.java
@@ -16,19 +16,6 @@
 
 package android.view.accessibility.cts;
 
-import android.app.UiAutomation;
-import android.os.ParcelFileDescriptor;
-import android.test.InstrumentationTestCase;
-import android.view.accessibility.CaptioningManager;
-import android.view.accessibility.CaptioningManager.CaptionStyle;
-import android.view.accessibility.CaptioningManager.CaptioningChangeListener;
-import org.mockito.Mockito;
-
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Locale;
-
 import static org.mockito.Matchers.anyFloat;
 import static org.mockito.Matchers.anyObject;
 import static org.mockito.Mockito.mock;
@@ -36,6 +23,20 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyZeroInteractions;
 
+import android.app.UiAutomation;
+import android.os.ParcelFileDescriptor;
+import android.test.InstrumentationTestCase;
+import android.view.accessibility.CaptioningManager;
+import android.view.accessibility.CaptioningManager.CaptionStyle;
+import android.view.accessibility.CaptioningManager.CaptioningChangeListener;
+
+import org.mockito.Mockito;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Locale;
+
 /**
  * Tests whether the CaptioningManager APIs are functional.
  */
diff --git a/tests/accessibility/src/android/view/accessibility/cts/ServiceControlUtils.java b/tests/accessibility/src/android/view/accessibility/cts/ServiceControlUtils.java
index 01275f3..5e8755f 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/ServiceControlUtils.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/ServiceControlUtils.java
@@ -16,6 +16,10 @@
 
 package android.view.accessibility.cts;
 
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
 import android.app.Instrumentation;
 import android.app.UiAutomation;
 import android.content.ContentResolver;
@@ -28,12 +32,13 @@
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * Utility methods for enabling and disabling the services used in this package
  */
 public class ServiceControlUtils {
-    private static final int TIMEOUT_FOR_SERVICE_ENABLE = 10000; // millis; 10s
+    public static final int TIMEOUT_FOR_SERVICE_ENABLE = 10000; // millis; 10s
 
     private static final String SETTING_ENABLE_SPEAKING_AND_VIBRATING_SERVICES =
             "android.view.accessibility.cts/.SpeakingAccessibilityService:"
@@ -181,31 +186,32 @@
         final Object waitLockForA11yOff = new Object();
         AccessibilityManager manager = (AccessibilityManager) instrumentation
                 .getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
-        if (!manager.isEnabled()) {
-            return;
-        }
-        manager.addAccessibilityStateChangeListener(
-                new AccessibilityManager.AccessibilityStateChangeListener() {
-                    @Override
-                    public void onAccessibilityStateChanged(boolean b) {
-                        synchronized (waitLockForA11yOff) {
-                            waitLockForA11yOff.notifyAll();
-                        }
-                    }
-                });
-        long timeoutTimeMillis = SystemClock.uptimeMillis() + TIMEOUT_FOR_SERVICE_ENABLE;
-        while (SystemClock.uptimeMillis() < timeoutTimeMillis) {
+        // Updates to manager.isEnabled() aren't synchronized
+        AtomicBoolean accessibilityEnabled = new AtomicBoolean(manager.isEnabled());
+        AccessibilityManager.AccessibilityStateChangeListener listener = (boolean b) -> {
             synchronized (waitLockForA11yOff) {
-                if (!manager.isEnabled()) {
-                    return;
-                }
-                try {
-                    waitLockForA11yOff.wait(timeoutTimeMillis - SystemClock.uptimeMillis());
-                } catch (InterruptedException e) {
-                    // Ignored; loop again
+                waitLockForA11yOff.notifyAll();
+                accessibilityEnabled.set(b);
+            }
+        };
+        manager.addAccessibilityStateChangeListener(listener);
+        try {
+            long timeoutTimeMillis = SystemClock.uptimeMillis() + TIMEOUT_FOR_SERVICE_ENABLE;
+            while (SystemClock.uptimeMillis() < timeoutTimeMillis) {
+                synchronized (waitLockForA11yOff) {
+                    if (!accessibilityEnabled.get()) {
+                        return;
+                    }
+                    try {
+                        waitLockForA11yOff.wait(timeoutTimeMillis - SystemClock.uptimeMillis());
+                    } catch (InterruptedException e) {
+                        // Ignored; loop again
+                    }
                 }
             }
+        } finally {
+            manager.removeAccessibilityStateChangeListener(listener);
         }
-        throw new RuntimeException("Unable to turn accessibility off");
+        assertThat("Unable to turn accessibility off", manager.isEnabled(), is(equalTo(false)));
     }
 }
diff --git a/tests/accessibilityservice/res/values/strings.xml b/tests/accessibilityservice/res/values/strings.xml
index 454102a..ad5d3fd 100644
--- a/tests/accessibilityservice/res/values/strings.xml
+++ b/tests/accessibilityservice/res/values/strings.xml
@@ -139,6 +139,8 @@
 
     <string name="a_b">A B</string>
 
+    <string name="german_text_with_strong_s">ß</string>
+
     <string name="android_wiki_search">Android is a Linux-based</string>
 
     <string name="foo_bar_baz">Foo bar baz.</string>
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityButtonTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityButtonTest.java
index 8521a56..359c6ac 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityButtonTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityButtonTest.java
@@ -16,12 +16,11 @@
 
 import android.accessibilityservice.AccessibilityButtonController;
 import android.app.Instrumentation;
-import android.os.Looper;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
index 8202399..b24846c 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
@@ -16,13 +16,16 @@
 
 package android.accessibilityservice.cts;
 
-import static android.accessibilityservice.cts.utils.AccessibilityEventFilterUtils.filterForEventType;
+import static android.accessibilityservice.cts.utils.AccessibilityEventFilterUtils
+        .filterForEventType;
 import static android.accessibilityservice.cts.utils.RunOnMainUtils.getOnMain;
-import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_HIDE_TOOLTIP;
-import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_SHOW_TOOLTIP;
+import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction
+        .ACTION_HIDE_TOOLTIP;
+import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction
+        .ACTION_SHOW_TOOLTIP;
 
 import static org.hamcrest.Matchers.in;
-import static org.hamcrest.core.IsNot.not;
+import static org.hamcrest.Matchers.not;
 import static org.junit.Assert.assertThat;
 
 import android.accessibilityservice.cts.activities.AccessibilityEndToEndActivity;
@@ -44,6 +47,7 @@
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.os.Process;
+import android.platform.test.annotations.Presubmit;
 import android.test.suitebuilder.annotation.MediumTest;
 import android.text.TextUtils;
 import android.util.Log;
@@ -58,7 +62,6 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * This class performs end-to-end testing of the accessibility feature by
@@ -86,6 +89,7 @@
     }
 
     @MediumTest
+    @Presubmit
     public void testTypeViewSelectedAccessibilityEvent() throws Throwable {
         // create and populate the expected event
         final AccessibilityEvent expected = AccessibilityEvent.obtain();
@@ -127,6 +131,7 @@
     }
 
     @MediumTest
+    @Presubmit
     public void testTypeViewClickedAccessibilityEvent() throws Throwable {
         // create and populate the expected event
         final AccessibilityEvent expected = AccessibilityEvent.obtain();
@@ -163,6 +168,7 @@
     }
 
     @MediumTest
+    @Presubmit
     public void testTypeViewLongClickedAccessibilityEvent() throws Throwable {
         // create and populate the expected event
         final AccessibilityEvent expected = AccessibilityEvent.obtain();
@@ -199,6 +205,7 @@
     }
 
     @MediumTest
+    @Presubmit
     public void testTypeViewFocusedAccessibilityEvent() throws Throwable {
         // create and populate the expected event
         final AccessibilityEvent expected = AccessibilityEvent.obtain();
@@ -237,6 +244,7 @@
     }
 
     @MediumTest
+    @Presubmit
     public void testTypeViewTextChangedAccessibilityEvent() throws Throwable {
         // focus the edit text
         final EditText editText = (EditText) getActivity().findViewById(R.id.edittext);
@@ -305,6 +313,7 @@
     }
 
     @MediumTest
+    @Presubmit
     public void testTypeWindowStateChangedAccessibilityEvent() throws Throwable {
         // create and populate the expected event
         final AccessibilityEvent expected = AccessibilityEvent.obtain();
@@ -342,6 +351,7 @@
 
     @MediumTest
     @SuppressWarnings("deprecation")
+    @Presubmit
     public void testTypeNotificationStateChangedAccessibilityEvent() throws Throwable {
         // No notification UI on televisions.
         if ((getActivity().getResources().getConfiguration().uiMode
@@ -484,6 +494,7 @@
     }
 
     @MediumTest
+    @Presubmit
     public void testPackageNameCannotBeFakedAppWidget() throws Exception {
         if (!hasAppWidgets()) {
             return;
@@ -561,6 +572,7 @@
     }
 
     @MediumTest
+    @Presubmit
     public void testViewHeadingReportedToAccessibility() throws Exception {
         final Instrumentation instrumentation = getInstrumentation();
         final EditText editText = (EditText) getOnMain(instrumentation, () -> {
@@ -590,6 +602,7 @@
     }
 
     @MediumTest
+    @Presubmit
     public void testTooltipTextReportedToAccessibility() {
         final Instrumentation instrumentation = getInstrumentation();
         final UiAutomation uiAutomation = instrumentation.getUiAutomation();
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFingerprintGestureTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFingerprintGestureTest.java
index c9b0027..0e9c181 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFingerprintGestureTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFingerprintGestureTest.java
@@ -14,6 +14,15 @@
 
 package android.accessibilityservice.cts;
 
+import static android.content.pm.PackageManager.FEATURE_FINGERPRINT;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+
 import android.accessibilityservice.FingerprintGestureController;
 import android.accessibilityservice.FingerprintGestureController.FingerprintGestureCallback;
 import android.accessibilityservice.cts.activities.AccessibilityEndToEndActivity;
@@ -23,6 +32,7 @@
 import android.support.test.InstrumentationRegistry;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
@@ -31,17 +41,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import static android.content.pm.PackageManager.FEATURE_FINGERPRINT;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.verify;
-
 /**
  * Verify that a service listening for fingerprint gestures gets called back when apps
  * use the fingerprint sensor to authenticate.
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFocusAndInputFocusSyncTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFocusAndInputFocusSyncTest.java
index aad045f..7cb569c 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFocusAndInputFocusSyncTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFocusAndInputFocusSyncTest.java
@@ -17,16 +17,16 @@
 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS;
 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS;
 
+import android.accessibilityservice.cts.R;
 import android.accessibilityservice.cts.activities.AccessibilityFocusAndInputFocusSyncActivity;
 import android.app.Instrumentation;
 import android.app.UiAutomation;
+import android.platform.test.annotations.Presubmit;
 import android.test.suitebuilder.annotation.MediumTest;
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 
-import android.accessibilityservice.cts.R;
-
 import java.util.LinkedList;
 import java.util.Queue;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -45,6 +45,7 @@
     }
 
     @MediumTest
+    @Presubmit
     public void testFindAccessibilityFocus() throws Exception {
         getInstrumentation().runOnMainSync(() -> {
             getActivity().findViewById(R.id.firstEditText).requestFocus();
@@ -81,6 +82,7 @@
     }
 
     @MediumTest
+    @Presubmit
     public void testInitialStateNoAccessibilityFocus() throws Exception {
         // Get the root which is only accessibility focused.
         AccessibilityNodeInfo focused = getInstrumentation().getUiAutomation()
@@ -118,6 +120,7 @@
     }
 
     @MediumTest
+    @Presubmit
     public void testActionClearAccessibilityFocus() throws Exception {
         // Get the root linear layout info.
         final AccessibilityNodeInfo rootLinearLayout = getInstrumentation().getUiAutomation()
@@ -166,6 +169,7 @@
     }
 
     @MediumTest
+    @Presubmit
     public void testOnlyOneNodeHasAccessibilityFocus() throws Exception {
         // Get the first not focused edit text.
         final AccessibilityNodeInfo firstEditText = getInstrumentation().getUiAutomation()
@@ -233,6 +237,7 @@
         }
     }
 
+    @Presubmit
     public void testScreenReaderFocusableAttribute_reportedToAccessibility() {
         final Instrumentation instrumentation = getInstrumentation();
         final UiAutomation uiAutomation = instrumentation.getUiAutomation();
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDetectorTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDetectorTest.java
index fd1a9fd..6ac693f 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDetectorTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDetectorTest.java
@@ -15,7 +15,6 @@
 package android.accessibilityservice.cts;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.verify;
@@ -32,8 +31,7 @@
 import android.support.test.runner.AndroidJUnit4;
 import android.util.DisplayMetrics;
 import android.view.WindowManager;
-import android.view.accessibility.AccessibilityEvent;
-import java.util.ArrayList;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -41,6 +39,8 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.ArrayList;
+
 /**
  * Verify that motion events are recognized as accessibility gestures.
  */
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGlobalActionsTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGlobalActionsTest.java
index fc71a79..95e4753 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGlobalActionsTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGlobalActionsTest.java
@@ -18,6 +18,7 @@
 
 import android.accessibilityservice.AccessibilityService;
 import android.os.SystemClock;
+import android.platform.test.annotations.Presubmit;
 import android.test.InstrumentationTestCase;
 import android.test.suitebuilder.annotation.MediumTest;
 
@@ -26,6 +27,7 @@
 /**
  * Test global actions
  */
+@Presubmit
 public class AccessibilityGlobalActionsTest extends InstrumentationTestCase {
     /**
      * Timeout required for pending Binder calls or event processing to
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityLoggingTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityLoggingTest.java
index 4593d06..9299807 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityLoggingTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityLoggingTest.java
@@ -14,11 +14,13 @@
 package android.accessibilityservice.cts;
 
 import static android.app.AppOpsManager.OPSTR_BIND_ACCESSIBILITY_SERVICE;
+
 import static junit.framework.Assert.assertTrue;
 
 import android.content.Context;
-import android.support.test.runner.AndroidJUnit4;
+import android.platform.test.annotations.Presubmit;
 import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
 
 import com.android.compatibility.common.util.AppOpsUtils;
 
@@ -26,6 +28,7 @@
 import org.junit.runner.RunWith;
 
 @RunWith(AndroidJUnit4.class)
+@Presubmit
 public class AccessibilityLoggingTest {
 
     /**
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityMagnificationTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityMagnificationTest.java
index 1abb2ab..8446702 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityMagnificationTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityMagnificationTest.java
@@ -16,22 +16,25 @@
 
 package android.accessibilityservice.cts;
 
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyFloat;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+
 import android.accessibilityservice.AccessibilityService.MagnificationController;
 import android.accessibilityservice.AccessibilityService.MagnificationController.OnMagnificationChangedListener;
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.app.Instrumentation;
 import android.content.Context;
-import android.content.res.Resources;
 import android.graphics.Region;
-import android.provider.Settings;
 import android.test.InstrumentationTestCase;
 import android.util.DisplayMetrics;
 import android.view.WindowManager;
 
 import java.util.concurrent.atomic.AtomicBoolean;
 
-import static org.mockito.Mockito.*;
-
 /**
  * Class for testing {@link AccessibilityServiceInfo}.
  */
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityPaneTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityPaneTest.java
index b07e3ca..a870dd9 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityPaneTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityPaneTest.java
@@ -16,10 +16,14 @@
 
 package android.accessibilityservice.cts;
 
-import static android.accessibilityservice.cts.utils.AccessibilityEventFilterUtils.AccessibilityEventTypeMatcher;
-import static android.accessibilityservice.cts.utils.AccessibilityEventFilterUtils.ContentChangesMatcher;
-import static android.accessibilityservice.cts.AccessibilityActivityTestCase.TIMEOUT_ASYNC_PROCESSING;
-import static android.accessibilityservice.cts.utils.ActivityLaunchUtils.launchActivityAndWaitForItToBeOnscreen;
+import static android.accessibilityservice.cts.AccessibilityActivityTestCase
+        .TIMEOUT_ASYNC_PROCESSING;
+import static android.accessibilityservice.cts.utils.AccessibilityEventFilterUtils
+        .AccessibilityEventTypeMatcher;
+import static android.accessibilityservice.cts.utils.AccessibilityEventFilterUtils
+        .ContentChangesMatcher;
+import static android.accessibilityservice.cts.utils.ActivityLaunchUtils
+        .launchActivityAndWaitForItToBeOnscreen;
 import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_APPEARED;
 import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED;
 import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_TITLE;
@@ -33,6 +37,7 @@
 import android.app.Instrumentation;
 import android.app.UiAutomation;
 import android.app.UiAutomation.AccessibilityEventFilter;
+import android.platform.test.annotations.Presubmit;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
@@ -50,6 +55,7 @@
  * Tests reporting of window-like views
  */
 @RunWith(AndroidJUnit4.class)
+@Presubmit
 public class AccessibilityPaneTest {
     private static Instrumentation sInstrumentation;
     private static UiAutomation sUiAutomation;
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java
index 1761117..b27ceaf 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java
@@ -18,6 +18,7 @@
 
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.os.Parcel;
+import android.platform.test.annotations.Presubmit;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.MediumTest;
 import android.view.accessibility.AccessibilityEvent;
@@ -25,6 +26,7 @@
 /**
  * Class for testing {@link AccessibilityServiceInfo}.
  */
+@Presubmit
 public class AccessibilityServiceInfoTest extends AndroidTestCase {
 
     @MediumTest
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilitySettingsTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilitySettingsTest.java
index ccbd1b5..6575034 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilitySettingsTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilitySettingsTest.java
@@ -19,6 +19,7 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.MediumTest;
@@ -29,6 +30,7 @@
  * This test case is responsible to verify that the intent for launching
  * accessibility settings has an activity that handles it.
  */
+@Presubmit
 public class AccessibilitySettingsTest extends AndroidTestCase {
 
     @MediumTest
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilitySoftKeyboardModesTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilitySoftKeyboardModesTest.java
index fb396b4..c179409 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilitySoftKeyboardModesTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilitySoftKeyboardModesTest.java
@@ -14,8 +14,9 @@
 
 package android.accessibilityservice.cts;
 
-import android.accessibilityservice.AccessibilityServiceInfo;
 import android.accessibilityservice.AccessibilityService.SoftKeyboardController;
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.accessibilityservice.cts.R;
 import android.accessibilityservice.cts.activities.AccessibilityTestActivity;
 import android.app.Activity;
 import android.app.Instrumentation;
@@ -28,8 +29,6 @@
 import android.test.ActivityInstrumentationTestCase2;
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
-
-import android.accessibilityservice.cts.R;
 import android.view.accessibility.AccessibilityWindowInfo;
 import android.view.inputmethod.InputMethodManager;
 
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextActionTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextActionTest.java
index 38bb738..115eb5f 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextActionTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextActionTest.java
@@ -14,6 +14,19 @@
 
 package android.accessibilityservice.cts;
 
+import static android.view.accessibility.AccessibilityNodeInfo
+        .EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH;
+import static android.view.accessibility.AccessibilityNodeInfo
+        .EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX;
+import static android.view.accessibility.AccessibilityNodeInfo
+        .EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.accessibilityservice.cts.R;
 import android.accessibilityservice.cts.activities.AccessibilityTextTraversalActivity;
 import android.app.UiAutomation;
 import android.graphics.RectF;
@@ -33,26 +46,11 @@
 import android.widget.EditText;
 import android.widget.TextView;
 
-import android.accessibilityservice.cts.R;
-
 import java.util.Arrays;
-import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 
-import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH;
-import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX;
-import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
 /**
  * Test cases for actions taken on text views.
  */
@@ -198,10 +196,14 @@
 
     public void testTextLocations_textViewShouldProvideWhenRequested() {
         final TextView textView = (TextView) getActivity().findViewById(R.id.text);
-        makeTextViewVisibleAndSetText(textView, getString(R.string.a_b));
+        // Use text with a strong s, since that gets replaced with a double s for all caps.
+        // That replacement requires us to properly handle the length of the string changing.
+        String stringToSet = getString(R.string.german_text_with_strong_s);
+        makeTextViewVisibleAndSetText(textView, stringToSet);
+        getInstrumentation().runOnMainSync(() -> textView.setAllCaps(true));
 
         final AccessibilityNodeInfo text = mUiAutomation.getRootInActiveWindow()
-                .findAccessibilityNodeInfosByText(getString(R.string.a_b)).get(0);
+                .findAccessibilityNodeInfosByText(stringToSet).get(0);
         List<String> textAvailableExtraData = text.getAvailableExtraData();
         assertTrue("Text view should offer text location to accessibility",
                 textAvailableExtraData.contains(EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY));
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalTest.java
index 646d9c3..d0bab51 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalTest.java
@@ -14,6 +14,7 @@
 
 package android.accessibilityservice.cts;
 
+import android.accessibilityservice.cts.R;
 import android.accessibilityservice.cts.activities.AccessibilityTextTraversalActivity;
 import android.app.UiAutomation;
 import android.content.pm.PackageManager;
@@ -27,8 +28,6 @@
 import android.widget.EditText;
 import android.widget.TextView;
 
-import android.accessibilityservice.cts.R;
-
 /**
  * Test cases for testing the accessibility APIs for traversing the text content of
  * a View at several granularities.
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityViewTreeReportingTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityViewTreeReportingTest.java
index a76a027..720e23f 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityViewTreeReportingTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityViewTreeReportingTest.java
@@ -14,7 +14,8 @@
 
 package android.accessibilityservice.cts;
 
-import static android.accessibilityservice.cts.utils.ActivityLaunchUtils.launchActivityAndWaitForItToBeOnscreen;
+import static android.accessibilityservice.cts.utils.ActivityLaunchUtils
+        .launchActivityAndWaitForItToBeOnscreen;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -23,20 +24,19 @@
 import static org.junit.Assert.assertTrue;
 
 import android.accessibilityservice.AccessibilityServiceInfo;
+import android.accessibilityservice.cts.R;
 import android.accessibilityservice.cts.activities.AccessibilityViewTreeReportingActivity;
 import android.app.Instrumentation;
 import android.app.UiAutomation;
 import android.content.Context;
+import android.support.test.InstrumentationRegistry;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
-import android.support.test.InstrumentationRegistry;
 import android.text.TextUtils;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
-
-import android.accessibilityservice.cts.R;
 import android.widget.Button;
 import android.widget.LinearLayout;
 
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityVolumeTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityVolumeTest.java
index 8b1154e..c718718 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityVolumeTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityVolumeTest.java
@@ -13,18 +13,21 @@
  */
 package android.accessibilityservice.cts;
 
+import static android.content.Context.AUDIO_SERVICE;
+
+import static org.junit.Assert.assertEquals;
+
 import android.app.Instrumentation;
 import android.content.pm.PackageManager;
+import android.media.AudioManager;
+import android.platform.test.annotations.Presubmit;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
-import android.media.AudioManager;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import static android.content.Context.AUDIO_SERVICE;
-import static org.junit.Assert.assertEquals;
-
 /**
  * Verify that accessibility services can control the accessibility volume.
  */
@@ -47,6 +50,7 @@
     }
 
     @Test
+    @Presubmit
     public void testChangeAccessibilityVolume_outsideValidAccessibilityService_shouldFail() {
         if (mSingleVolume) {
             return;
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowReportingTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowReportingTest.java
index 2977843..e9f3f52 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowReportingTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowReportingTest.java
@@ -29,7 +29,6 @@
 import static android.view.accessibility.AccessibilityEvent.WINDOWS_CHANGE_BOUNDS;
 import static android.view.accessibility.AccessibilityEvent.WINDOWS_CHANGE_CHILDREN;
 import static android.view.accessibility.AccessibilityEvent.WINDOWS_CHANGE_FOCUSED;
-import static android.view.accessibility.AccessibilityEvent.WINDOWS_CHANGE_PIP;
 import static android.view.accessibility.AccessibilityEvent.WINDOWS_CHANGE_REMOVED;
 import static android.view.accessibility.AccessibilityEvent.WINDOWS_CHANGE_TITLE;
 
@@ -44,15 +43,12 @@
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.app.UiAutomation;
-import android.os.Debug;
+import android.support.test.InstrumentationRegistry;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
-import android.support.test.InstrumentationRegistry;
-import android.util.Log;
 import android.view.Gravity;
 import android.view.View;
 import android.view.WindowManager;
-import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityWindowInfo;
 import android.widget.ArrayAdapter;
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/GestureDescriptionTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/GestureDescriptionTest.java
index 3df8d0c..4c1d064 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/GestureDescriptionTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/GestureDescriptionTest.java
@@ -18,11 +18,13 @@
 import android.accessibilityservice.GestureDescription.StrokeDescription;
 import android.graphics.Path;
 import android.graphics.PathMeasure;
+import android.platform.test.annotations.Presubmit;
 import android.test.InstrumentationTestCase;
 
 /**
  * Tests for creating gesture descriptions.
  */
+@Presubmit
 public class GestureDescriptionTest extends InstrumentationTestCase {
     static final int NOMINAL_PATH_DURATION = 100;
     private Path mNominalPath;
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/MagnificationGestureHandlerTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/MagnificationGestureHandlerTest.java
index 5cc46ea1..a9bd769 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/MagnificationGestureHandlerTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/MagnificationGestureHandlerTest.java
@@ -34,8 +34,8 @@
 import static android.view.MotionEvent.ACTION_MOVE;
 import static android.view.MotionEvent.ACTION_UP;
 
-import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.Matchers.is;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertThat;
@@ -53,9 +53,9 @@
 import android.graphics.PointF;
 import android.os.SystemClock;
 import android.provider.Settings;
+import android.support.test.InstrumentationRegistry;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
-import android.support.test.InstrumentationRegistry;
 import android.view.MotionEvent;
 import android.widget.TextView;
 
diff --git a/tests/app/CantSaveState1/Android.mk b/tests/app/CantSaveState1/Android.mk
index ad7e880..72c762d 100644
--- a/tests/app/CantSaveState1/Android.mk
+++ b/tests/app/CantSaveState1/Android.mk
@@ -28,5 +28,6 @@
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
 LOCAL_PACKAGE_NAME := CtsCantSaveState1
+LOCAL_SDK_VERSION := current
 
 include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/app/CantSaveState2/Android.mk b/tests/app/CantSaveState2/Android.mk
index 05da3f6..40230633 100644
--- a/tests/app/CantSaveState2/Android.mk
+++ b/tests/app/CantSaveState2/Android.mk
@@ -28,5 +28,6 @@
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
 LOCAL_PACKAGE_NAME := CtsCantSaveState2
+LOCAL_SDK_VERSION := current
 
 include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/app/app/Android.mk b/tests/app/app/Android.mk
index 5e22eb2..d157c41 100644
--- a/tests/app/app/Android.mk
+++ b/tests/app/app/Android.mk
@@ -45,5 +45,6 @@
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
 LOCAL_PACKAGE_NAME := CtsAppTestStubs
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/app/src/android/app/cts/ActivityManagerMemoryClassTest.java b/tests/app/src/android/app/cts/ActivityManagerMemoryClassTest.java
index fefa546..0668ff8 100644
--- a/tests/app/src/android/app/cts/ActivityManagerMemoryClassTest.java
+++ b/tests/app/src/android/app/cts/ActivityManagerMemoryClassTest.java
@@ -67,6 +67,7 @@
             expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_360, 48);
             expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_400, 56);
             expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_420, 64);
+            expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_440, 88);
             expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_XXHIGH, 88);
             expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_560, 112);
             expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_XXXHIGH, 154);
@@ -85,6 +86,7 @@
             expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_360, 80);
             expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_400, 96);
             expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_420, 112);
+            expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_440, 128);
             expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_XXHIGH, 128);
             expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_560, 192);
             expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_XXXHIGH, 256);
@@ -103,6 +105,7 @@
             expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_360, 160);
             expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_400, 192);
             expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_420, 228);
+            expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_440, 256);
             expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_XXHIGH, 256);
             expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_560, 384);
             expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_XXXHIGH, 512);
@@ -121,6 +124,7 @@
             expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_360, 240);
             expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_400, 288);
             expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_420, 336);
+            expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_440, 384);
             expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_XXHIGH, 384);
             expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_560, 576);
             expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_XXXHIGH, 768);
diff --git a/tests/app/src/android/app/cts/DialogTest.java b/tests/app/src/android/app/cts/DialogTest.java
index ee1836a..b2749c7 100755
--- a/tests/app/src/android/app/cts/DialogTest.java
+++ b/tests/app/src/android/app/cts/DialogTest.java
@@ -746,6 +746,7 @@
         assertFalse(d.isOnContextMenuClosedCalled);
     }
 
+    @Test
     public void testOnSearchRequested() {
     }
 
diff --git a/tests/app/src/android/app/cts/NotificationManagerTest.java b/tests/app/src/android/app/cts/NotificationManagerTest.java
index eca5e24..070b2eb 100644
--- a/tests/app/src/android/app/cts/NotificationManagerTest.java
+++ b/tests/app/src/android/app/cts/NotificationManagerTest.java
@@ -97,58 +97,55 @@
         }
     }
 
-    public void testPrePCannotDisallowAlarmsOrMediaTest() throws Exception {
+    public void testOnlyPostPCanToggleAlarmsAndMediaTest() throws Exception {
         toggleNotificationPolicyAccess(mContext.getPackageName(),
                 InstrumentationRegistry.getInstrumentation(), true);
-        mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.O;
 
-        // toggle on alarms and media
-        mNotificationManager.setNotificationPolicy(new NotificationManager.Policy(
-                NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS
-                        | NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER, 0, 0));
+        if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.P) {
+            // Post-P can toggle alarms and media
+            // toggle on alarms and media:
+            mNotificationManager.setNotificationPolicy(new NotificationManager.Policy(
+                    NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS
+                            | NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER, 0, 0));
+            NotificationManager.Policy policy = mNotificationManager.getNotificationPolicy();
+            assertTrue((policy.priorityCategories
+                    & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS) != 0);
+            assertTrue((policy.priorityCategories
+                    & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER) != 0);
 
-        NotificationManager.Policy policy = mNotificationManager.getNotificationPolicy();
-        assert((policy.priorityCategories & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS)
-                != 0);
-        assert((policy.priorityCategories &
-                NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER) != 0);
+            // toggle off alarms and media
+            mNotificationManager.setNotificationPolicy(new NotificationManager.Policy(0, 0, 0));
+            policy = mNotificationManager.getNotificationPolicy();
+            assertTrue((policy.priorityCategories
+                    & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS) == 0);
+            assertTrue((policy.priorityCategories &
+                    NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER) == 0);
+        } else {
+            // Pre-P cannot toggle alarms and media
+            NotificationManager.Policy origPolicy = mNotificationManager.getNotificationPolicy();
+            int alarmBit = origPolicy.priorityCategories & NotificationManager.Policy
+                    .PRIORITY_CATEGORY_ALARMS;
+            int mediaBit = origPolicy.priorityCategories & NotificationManager.Policy
+                    .PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER;
 
-        // attempt to toggle off alarms and media
-        // toggle on alarms and media
-        mNotificationManager.setNotificationPolicy(new NotificationManager.Policy(0, 0, 0));
+            // attempt to toggle off alarms and media:
+            mNotificationManager.setNotificationPolicy(new NotificationManager.Policy(0, 0, 0));
+            NotificationManager.Policy policy = mNotificationManager.getNotificationPolicy();
+            assertEquals(alarmBit, policy.priorityCategories
+                    & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS);
+            assertEquals(mediaBit, policy.priorityCategories
+                    & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER);
 
-        policy = mNotificationManager.getNotificationPolicy();
-        assert((policy.priorityCategories & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS)
-                != 0);
-        assert((policy.priorityCategories &
-                NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER) != 0);
-    }
-
-    public void testPostPCanDisallowAlarmsOrMediaTest() throws Exception {
-        toggleNotificationPolicyAccess(mContext.getPackageName(),
-                InstrumentationRegistry.getInstrumentation(), true);
-        mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.P;
-
-        // toggle on alarms and media
-        mNotificationManager.setNotificationPolicy(new NotificationManager.Policy(
-                NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS
-                        | NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER, 0, 0));
-
-        NotificationManager.Policy policy = mNotificationManager.getNotificationPolicy();
-        assert((policy.priorityCategories & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS)
-                != 0);
-        assert((policy.priorityCategories &
-                NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER) != 0);
-
-        // attempt to toggle off alarms and media
-        // toggle on alarms and media
-        mNotificationManager.setNotificationPolicy(new NotificationManager.Policy(0, 0, 0));
-
-        policy = mNotificationManager.getNotificationPolicy();
-        assert((policy.priorityCategories & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS)
-                == 0);
-        assert((policy.priorityCategories &
-                NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER) == 0);
+            // attempt to toggle on alarms and media:
+            mNotificationManager.setNotificationPolicy(new NotificationManager.Policy(
+                    NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS
+                            | NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER, 0, 0));
+            policy = mNotificationManager.getNotificationPolicy();
+            assertEquals(alarmBit, policy.priorityCategories
+                    & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS);
+            assertEquals(mediaBit, policy.priorityCategories
+                    & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER);
+        }
     }
 
     public void testCreateChannelGroup() throws Exception {
diff --git a/tests/autofillservice/AndroidManifest.xml b/tests/autofillservice/AndroidManifest.xml
index e63a752..a16086b 100644
--- a/tests/autofillservice/AndroidManifest.xml
+++ b/tests/autofillservice/AndroidManifest.xml
@@ -47,7 +47,14 @@
         <activity android:name=".TimePickerClockActivity" />
         <activity android:name=".TimePickerSpinnerActivity" />
         <activity android:name=".FatActivity" />
-        <activity android:name=".VirtualContainerActivity"/>
+        <activity android:name=".VirtualContainerActivity">
+            <intent-filter>
+                <!-- This intent filter is not really needed by CTS, but it maks easier to launch
+                     this app during CTS development... -->
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
         <activity android:name=".OptionalSaveActivity" />
         <activity android:name=".AllAutofillableViewsActivity" />
         <activity android:name=".GridActivity"/>
diff --git a/tests/autofillservice/AndroidTest.xml b/tests/autofillservice/AndroidTest.xml
index 73fffd2..e8cfc3c 100644
--- a/tests/autofillservice/AndroidTest.xml
+++ b/tests/autofillservice/AndroidTest.xml
@@ -15,7 +15,7 @@
 -->
 <configuration description="Config for AutoFill Framework CTS tests.">
   <option name="test-suite-tag" value="cts" />
-  <option name="config-descriptor:metadata" key="component" value="framework" />
+  <option name="config-descriptor:metadata" key="component" value="autofill" />
 
   <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
     <option name="cleanup-apks" value="true" />
diff --git a/tests/autofillservice/res/layout/grid_activity.xml b/tests/autofillservice/res/layout/grid_activity.xml
index 2ad125c..7888720 100644
--- a/tests/autofillservice/res/layout/grid_activity.xml
+++ b/tests/autofillservice/res/layout/grid_activity.xml
@@ -24,6 +24,7 @@
     android:orientation="vertical" >
 
     <GridLayout
+        android:id="@+id/grid"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="horizontal"
diff --git a/tests/autofillservice/res/layout/virtual_container_activity.xml b/tests/autofillservice/res/layout/virtual_container_activity.xml
index 2596fbb..bc47819 100644
--- a/tests/autofillservice/res/layout/virtual_container_activity.xml
+++ b/tests/autofillservice/res/layout/virtual_container_activity.xml
@@ -15,8 +15,34 @@
  * limitations under the License.
 -->
 
-<android.autofillservice.cts.VirtualContainerView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/virtual_container_view"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent"
-/>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:focusable="true"
+    android:focusableInTouchMode="true"
+    android:orientation="vertical" >
+
+    <LinearLayout
+        android:id="@+id/username_container"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal" >
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="URL" />
+
+        <EditText
+            android:id="@+id/my_url_bar"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" />
+    </LinearLayout>
+
+    <android.autofillservice.cts.VirtualContainerView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/virtual_container_view"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+    />
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/autofillservice/res/xml/autofill_service_compat_mode_config.xml b/tests/autofillservice/res/xml/autofill_service_compat_mode_config.xml
index 1314999..a340fc2 100644
--- a/tests/autofillservice/res/xml/autofill_service_compat_mode_config.xml
+++ b/tests/autofillservice/res/xml/autofill_service_compat_mode_config.xml
@@ -15,5 +15,8 @@
  * limitations under the License.
 -->
 <autofill-service xmlns:android="http://schemas.android.com/apk/res/android">
-    <compatibility-package android:name="android.autofillservice.cts" android:maxLongVersionCode="1000000000"/>
+  <compatibility-package
+    android:name="android.autofillservice.cts"
+    android:urlBarResourceId="my_url_bar"
+    android:maxLongVersionCode="1000000000" />
 </autofill-service>
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AbstractLoginActivityTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/AbstractLoginActivityTestCase.java
new file mode 100644
index 0000000..da684d6
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/AbstractLoginActivityTestCase.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.autofillservice.cts;
+
+import static android.autofillservice.cts.Helper.getContext;
+
+import android.view.View;
+
+import org.junit.Before;
+import org.junit.Rule;
+
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Base class for test cases using {@link LoginActivity}.
+ */
+abstract class AbstractLoginActivityTestCase extends AutoFillServiceTestCase {
+    @Rule
+    public final AutofillActivityTestRule<LoginActivity> mActivityRule =
+            new AutofillActivityTestRule<LoginActivity>(LoginActivity.class);
+
+    @Rule
+    public final AutofillActivityTestRule<CheckoutActivity> mCheckoutActivityRule =
+            new AutofillActivityTestRule<CheckoutActivity>(CheckoutActivity.class, false);
+
+    protected LoginActivity mActivity;
+    protected boolean mCanPassKeys;
+
+    @Before
+    public void setActivity() {
+        mActivity = mActivityRule.getActivity();
+        mCanPassKeys = !Helper.isAutofillWindowFullScreen(getContext());
+    }
+
+    /**
+     * Requests focus on username and expect Window event happens.
+     */
+    protected void requestFocusOnUsername() throws TimeoutException {
+        mUiBot.waitForWindowChange(() -> mActivity.onUsername(View::requestFocus),
+                Timeouts.UI_TIMEOUT.getMaxValue());
+    }
+
+    /**
+     * Requests focus on username and expect no Window event happens.
+     */
+    protected void requestFocusOnUsernameNoWindowChange() {
+        try {
+            // TODO: define a small value in Timeout
+            mUiBot.waitForWindowChange(() -> mActivity.onUsername(View::requestFocus),
+                    Timeouts.UI_TIMEOUT.ms());
+        } catch (TimeoutException ex) {
+            // no window events! looking good
+            return;
+        }
+        throw new IllegalStateException("Expect no window event when focusing to"
+                + " username, but event happened");
+    }
+
+    /**
+     * Requests focus on password and expect Window event happens.
+     */
+    protected void requestFocusOnPassword() throws TimeoutException {
+        mUiBot.waitForWindowChange(() -> mActivity.onPassword(View::requestFocus),
+                Timeouts.UI_TIMEOUT.getMaxValue());
+    }
+
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AuthenticationTest.java b/tests/autofillservice/src/android/autofillservice/cts/AuthenticationTest.java
new file mode 100644
index 0000000..f47bac5
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/AuthenticationTest.java
@@ -0,0 +1,1154 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.autofillservice.cts;
+
+import static android.app.Activity.RESULT_CANCELED;
+import static android.app.Activity.RESULT_OK;
+import static android.autofillservice.cts.Helper.ID_PASSWORD;
+import static android.autofillservice.cts.Helper.ID_USERNAME;
+import static android.autofillservice.cts.Helper.UNUSED_AUTOFILL_VALUE;
+import static android.autofillservice.cts.LoginActivity.getWelcomeMessage;
+import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_PASSWORD;
+import static android.view.View.IMPORTANT_FOR_AUTOFILL_NO;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.autofillservice.cts.CannedFillResponse.CannedDataset;
+import android.autofillservice.cts.InstrumentedAutoFillService.SaveRequest;
+import android.content.IntentSender;
+import android.os.Bundle;
+import android.support.test.uiautomator.UiObject2;
+import android.view.View;
+import android.view.autofill.AutofillValue;
+
+import org.junit.Test;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.regex.Pattern;
+
+public class AuthenticationTest extends AbstractLoginActivityTestCase {
+
+    @Test
+    public void testDatasetAuthTwoFields() throws Exception {
+        datasetAuthTwoFields(false);
+    }
+
+    @Test
+    public void testDatasetAuthTwoFieldsUserCancelsFirstAttempt() throws Exception {
+        datasetAuthTwoFields(true);
+    }
+
+    private void datasetAuthTwoFields(boolean cancelFirstAttempt) throws Exception {
+        // Set service.
+        enableService();
+        final MyAutofillCallback callback = mActivity.registerCallback();
+
+        // Prepare the authenticated response
+        final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
+                new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "dude")
+                        .setField(ID_PASSWORD, "sweet")
+                        .build());
+
+        // Configure the service behavior
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, UNUSED_AUTOFILL_VALUE)
+                        .setField(ID_PASSWORD, UNUSED_AUTOFILL_VALUE)
+                        .setPresentation(createPresentation("Tap to auth dataset"))
+                        .setAuthentication(authentication)
+                        .build())
+                .build());
+
+        // Set expectation for the activity
+        mActivity.expectAutoFill("dude", "sweet");
+
+        // Trigger auto-fill.
+        requestFocusOnUsername();
+
+        // Wait for onFill() before proceeding.
+        sReplier.getNextFillRequest();
+        final View username = mActivity.getUsername();
+        callback.assertUiShownEvent(username);
+        mUiBot.assertDatasets("Tap to auth dataset");
+
+        // Make sure UI is show on 2nd field as well
+        final View password = mActivity.getPassword();
+        requestFocusOnPassword();
+        callback.assertUiHiddenEvent(username);
+        callback.assertUiShownEvent(password);
+        mUiBot.assertDatasets("Tap to auth dataset");
+
+        // Now tap on 1st field to show it again...
+        requestFocusOnUsername();
+        callback.assertUiHiddenEvent(password);
+        callback.assertUiShownEvent(username);
+        mUiBot.assertDatasets("Tap to auth dataset");
+
+        if (cancelFirstAttempt) {
+            // Trigger the auth dialog, but emulate cancel.
+            AuthenticationActivity.setResultCode(RESULT_CANCELED);
+            mUiBot.selectDataset("Tap to auth dataset");
+            callback.assertUiHiddenEvent(username);
+            callback.assertUiShownEvent(username);
+            mUiBot.assertDatasets("Tap to auth dataset");
+
+            // Make sure it's still shown on other fields...
+            requestFocusOnPassword();
+            callback.assertUiHiddenEvent(username);
+            callback.assertUiShownEvent(password);
+            mUiBot.assertDatasets("Tap to auth dataset");
+
+            // Tap on 1st field to show it again...
+            requestFocusOnUsername();
+            callback.assertUiHiddenEvent(password);
+            callback.assertUiShownEvent(username);
+        }
+
+        // ...and select it this time
+        AuthenticationActivity.setResultCode(RESULT_OK);
+        mUiBot.selectDataset("Tap to auth dataset");
+        callback.assertUiHiddenEvent(username);
+        mUiBot.assertNoDatasets();
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+    }
+
+    @Test
+    public void testDatasetAuthTwoFieldsReplaceResponse() throws Exception {
+        // Set service.
+        enableService();
+        final MyAutofillCallback callback = mActivity.registerCallback();
+
+        // Prepare the authenticated response
+        final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
+                new CannedFillResponse.Builder().addDataset(
+                        new CannedDataset.Builder()
+                                .setField(ID_USERNAME, "dude")
+                                .setField(ID_PASSWORD, "sweet")
+                                .setPresentation(createPresentation("Dataset"))
+                                .build())
+                        .build());
+
+        // Set up the authentication response client state
+        final Bundle authentionClientState = new Bundle();
+        authentionClientState.putCharSequence("clientStateKey1", "clientStateValue1");
+
+        // Configure the service behavior
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, (AutofillValue) null)
+                        .setField(ID_PASSWORD, (AutofillValue) null)
+                        .setPresentation(createPresentation("Tap to auth dataset"))
+                        .setAuthentication(authentication)
+                        .build())
+                .setExtras(authentionClientState)
+                .build());
+
+        // Set expectation for the activity
+        mActivity.expectAutoFill("dude", "sweet");
+
+        // Trigger auto-fill.
+        requestFocusOnUsername();
+
+        // Wait for onFill() before proceeding.
+        sReplier.getNextFillRequest();
+        final View username = mActivity.getUsername();
+
+        // Authenticate
+        callback.assertUiShownEvent(username);
+        mUiBot.selectDataset("Tap to auth dataset");
+        callback.assertUiHiddenEvent(username);
+
+        // Select a dataset from the new response
+        callback.assertUiShownEvent(username);
+        mUiBot.selectDataset("Dataset");
+        callback.assertUiHiddenEvent(username);
+        mUiBot.assertNoDatasets();
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+
+        final Bundle data = AuthenticationActivity.getData();
+        assertThat(data).isNotNull();
+        final String extraValue = data.getString("clientStateKey1");
+        assertThat(extraValue).isEqualTo("clientStateValue1");
+    }
+
+    @Test
+    public void testDatasetAuthTwoFieldsNoValues() throws Exception {
+        // Set service.
+        enableService();
+        final MyAutofillCallback callback = mActivity.registerCallback();
+
+        // Create the authentication intent
+        final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
+                new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "dude")
+                        .setField(ID_PASSWORD, "sweet")
+                        .build());
+
+        // Configure the service behavior
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, (String) null)
+                        .setField(ID_PASSWORD, (String) null)
+                        .setPresentation(createPresentation("Tap to auth dataset"))
+                        .setAuthentication(authentication)
+                        .build())
+                .build());
+
+        // Set expectation for the activity
+        mActivity.expectAutoFill("dude", "sweet");
+
+        // Trigger auto-fill.
+        requestFocusOnUsername();
+
+        // Wait for onFill() before proceeding.
+        sReplier.getNextFillRequest();
+        final View username = mActivity.getUsername();
+
+        // Authenticate
+        callback.assertUiShownEvent(username);
+        mUiBot.selectDataset("Tap to auth dataset");
+        callback.assertUiHiddenEvent(username);
+        mUiBot.assertNoDatasets();
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+    }
+
+    @Test
+    public void testDatasetAuthTwoDatasets() throws Exception {
+        // Set service.
+        enableService();
+        final MyAutofillCallback callback = mActivity.registerCallback();
+
+        // Create the authentication intents
+        final CannedDataset unlockedDataset = new CannedDataset.Builder()
+                .setField(ID_USERNAME, "dude")
+                .setField(ID_PASSWORD, "sweet")
+                .build();
+        final IntentSender authentication1 = AuthenticationActivity.createSender(mContext, 1,
+                unlockedDataset);
+        final IntentSender authentication2 = AuthenticationActivity.createSender(mContext, 2,
+                unlockedDataset);
+
+        // Configure the service behavior
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, UNUSED_AUTOFILL_VALUE)
+                        .setField(ID_PASSWORD, UNUSED_AUTOFILL_VALUE)
+                        .setPresentation(createPresentation("Tap to auth dataset 1"))
+                        .setAuthentication(authentication1)
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, UNUSED_AUTOFILL_VALUE)
+                        .setField(ID_PASSWORD, UNUSED_AUTOFILL_VALUE)
+                        .setPresentation(createPresentation("Tap to auth dataset 2"))
+                        .setAuthentication(authentication2)
+                        .build())
+                .build());
+
+        // Set expectation for the activity
+        mActivity.expectAutoFill("dude", "sweet");
+
+        // Trigger auto-fill.
+        requestFocusOnUsername();
+
+        // Wait for onFill() before proceeding.
+        sReplier.getNextFillRequest();
+        final View username = mActivity.getUsername();
+
+        // Authenticate
+        callback.assertUiShownEvent(username);
+        mUiBot.assertDatasets("Tap to auth dataset 1", "Tap to auth dataset 2");
+
+        mUiBot.selectDataset("Tap to auth dataset 1");
+        callback.assertUiHiddenEvent(username);
+        mUiBot.assertNoDatasets();
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+    }
+
+    @Test
+    public void testDatasetAuthMixedSelectAuth() throws Exception {
+        datasetAuthMixedTest(true);
+    }
+
+    @Test
+    public void testDatasetAuthMixedSelectNonAuth() throws Exception {
+        datasetAuthMixedTest(false);
+    }
+
+    private void datasetAuthMixedTest(boolean selectAuth) throws Exception {
+        // Set service.
+        enableService();
+        final MyAutofillCallback callback = mActivity.registerCallback();
+
+        // Prepare the authenticated response
+        final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
+                new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "dude")
+                        .setField(ID_PASSWORD, "sweet")
+                        .build());
+
+        // Configure the service behavior
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "dude")
+                        .setField(ID_PASSWORD, "sweet")
+                        .setPresentation(createPresentation("Tap to auth dataset"))
+                        .setAuthentication(authentication)
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "DUDE")
+                        .setField(ID_PASSWORD, "SWEET")
+                        .setPresentation(createPresentation("What, me auth?"))
+                        .build())
+                .build());
+
+        // Set expectation for the activity
+        if (selectAuth) {
+            mActivity.expectAutoFill("dude", "sweet");
+        } else {
+            mActivity.expectAutoFill("DUDE", "SWEET");
+        }
+
+        // Trigger auto-fill.
+        requestFocusOnUsername();
+
+        // Wait for onFill() before proceeding.
+        sReplier.getNextFillRequest();
+        final View username = mActivity.getUsername();
+
+        // Authenticate
+        callback.assertUiShownEvent(username);
+        mUiBot.assertDatasets("Tap to auth dataset", "What, me auth?");
+
+        final String chosenOne = selectAuth ? "Tap to auth dataset" : "What, me auth?";
+        mUiBot.selectDataset(chosenOne);
+        callback.assertUiHiddenEvent(username);
+        mUiBot.assertNoDatasets();
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+    }
+
+    @Test
+    public void testDatasetAuthNoFiltering() throws Exception {
+        // Set service.
+        enableService();
+        final MyAutofillCallback callback = mActivity.registerCallback();
+
+        // Create the authentication intents
+        final CannedDataset unlockedDataset = new CannedDataset.Builder()
+                .setField(ID_USERNAME, "dude")
+                .setField(ID_PASSWORD, "sweet")
+                .build();
+        final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
+                unlockedDataset);
+
+        // Configure the service behavior
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, UNUSED_AUTOFILL_VALUE)
+                        .setField(ID_PASSWORD, UNUSED_AUTOFILL_VALUE)
+                        .setPresentation(createPresentation("Tap to auth dataset"))
+                        .setAuthentication(authentication)
+                        .build())
+                .build());
+
+        // Set expectation for the activity
+        mActivity.expectAutoFill("dude", "sweet");
+
+        // Trigger auto-fill.
+        requestFocusOnUsername();
+
+        // Wait for onFill() before proceeding.
+        sReplier.getNextFillRequest();
+        final View username = mActivity.getUsername();
+
+        // Make sure it's showing initially...
+        callback.assertUiShownEvent(username);
+        mUiBot.assertDatasets("Tap to auth dataset");
+
+        // ..then type something to hide it.
+        mActivity.onUsername((v) -> v.setText("a"));
+        callback.assertUiHiddenEvent(username);
+        mUiBot.assertNoDatasets();
+
+        // Now delete the char and assert it's shown again...
+        mActivity.onUsername((v) -> v.setText(""));
+        callback.assertUiShownEvent(username);
+        mUiBot.assertDatasets("Tap to auth dataset");
+
+        // ...and select it this time
+        mUiBot.selectDataset("Tap to auth dataset");
+        callback.assertUiHiddenEvent(username);
+        mUiBot.assertNoDatasets();
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+    }
+
+    @Test
+    public void testDatasetAuthFilteringUsingAutofillValue() throws Exception {
+        // Set service.
+        enableService();
+        final MyAutofillCallback callback = mActivity.registerCallback();
+
+        // Create the authentication intents
+        final CannedDataset unlockedDataset = new CannedDataset.Builder()
+                .setField(ID_USERNAME, "dude")
+                .setField(ID_PASSWORD, "sweet")
+                .build();
+        final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
+                unlockedDataset);
+
+        // Configure the service behavior
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "dude")
+                        .setField(ID_PASSWORD, "sweet")
+                        .setPresentation(createPresentation("DS1"))
+                        .setAuthentication(authentication)
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "DUDE,THE")
+                        .setField(ID_PASSWORD, "SWEET")
+                        .setPresentation(createPresentation("DS2"))
+                        .setAuthentication(authentication)
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "ZzBottom")
+                        .setField(ID_PASSWORD, "top")
+                        .setPresentation(createPresentation("DS3"))
+                        .setAuthentication(authentication)
+                        .build())
+                .build());
+
+        // Set expectation for the activity
+        mActivity.expectAutoFill("dude", "sweet");
+
+        // Trigger auto-fill.
+        requestFocusOnUsername();
+
+        // Wait for onFill() before proceeding.
+        sReplier.getNextFillRequest();
+        final View username = mActivity.getUsername();
+
+        // Make sure it's showing initially...
+        callback.assertUiShownEvent(username);
+        mUiBot.assertDatasets("DS1", "DS2", "DS3");
+
+        // ...then type something to hide them.
+        mActivity.onUsername((v) -> v.setText("a"));
+        callback.assertUiHiddenEvent(username);
+        mUiBot.assertNoDatasets();
+
+        // Now delete the char and assert they're shown again...
+        mActivity.onUsername((v) -> v.setText(""));
+        callback.assertUiShownEvent(username);
+        mUiBot.assertDatasets("DS1", "DS2", "DS3");
+
+        // ...then filter for 2
+        mActivity.onUsername((v) -> v.setText("d"));
+        mUiBot.assertDatasets("DS1", "DS2");
+
+        // ...up to 1
+        mActivity.onUsername((v) -> v.setText("du"));
+        mUiBot.assertDatasets("DS1", "DS2");
+        mActivity.onUsername((v) -> v.setText("dud"));
+        mUiBot.assertDatasets("DS1", "DS2");
+        mActivity.onUsername((v) -> v.setText("dude"));
+        mUiBot.assertDatasets("DS1", "DS2");
+        mActivity.onUsername((v) -> v.setText("dude,"));
+        mUiBot.assertDatasets("DS2");
+
+        // Now delete the char and assert 2 are shown again...
+        mActivity.onUsername((v) -> v.setText("dude"));
+        final UiObject2 picker = mUiBot.assertDatasets("DS1", "DS2");
+
+        // ...and select it this time
+        mUiBot.selectDataset(picker, "DS1");
+        callback.assertUiHiddenEvent(username);
+        mUiBot.assertNoDatasets();
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+    }
+
+    @Test
+    public void testDatasetAuthFilteringUsingRegex() throws Exception {
+        // Set service.
+        enableService();
+        final MyAutofillCallback callback = mActivity.registerCallback();
+
+        // Create the authentication intents
+        final CannedDataset unlockedDataset = new CannedDataset.Builder()
+                .setField(ID_USERNAME, "dude")
+                .setField(ID_PASSWORD, "sweet")
+                .build();
+        final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
+                unlockedDataset);
+
+        // Configure the service behavior
+
+        final Pattern min2Chars = Pattern.compile(".{2,}");
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, UNUSED_AUTOFILL_VALUE, min2Chars)
+                        .setField(ID_PASSWORD, UNUSED_AUTOFILL_VALUE)
+                        .setPresentation(createPresentation("Tap to auth dataset"))
+                        .setAuthentication(authentication)
+                        .build())
+                .build());
+
+        // Set expectation for the activity
+        mActivity.expectAutoFill("dude", "sweet");
+
+        // Trigger auto-fill.
+        requestFocusOnUsername();
+
+        // Wait for onFill() before proceeding.
+        sReplier.getNextFillRequest();
+        final View username = mActivity.getUsername();
+
+        // Make sure it's showing initially...
+        callback.assertUiShownEvent(username);
+        mUiBot.assertDatasets("Tap to auth dataset");
+
+        // ...then type something to hide it.
+        mActivity.onUsername((v) -> v.setText("a"));
+        callback.assertUiHiddenEvent(username);
+        mUiBot.assertNoDatasets();
+
+        // ...now type something again to show it, as the input will have 2 chars.
+        mActivity.onUsername((v) -> v.setText("aa"));
+        callback.assertUiShownEvent(username);
+        mUiBot.assertDatasets("Tap to auth dataset");
+
+        // Delete the char and assert it's not shown again...
+        mActivity.onUsername((v) -> v.setText("a"));
+        callback.assertUiHiddenEvent(username);
+        mUiBot.assertNoDatasets();
+
+        // ...then type something again to show it, as the input will have 2 chars.
+        mActivity.onUsername((v) -> v.setText("aa"));
+        callback.assertUiShownEvent(username);
+
+        // ...and select it this time
+        mUiBot.selectDataset("Tap to auth dataset");
+        callback.assertUiHiddenEvent(username);
+        mUiBot.assertNoDatasets();
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+    }
+
+    @Test
+    public void testDatasetAuthMixedFilteringSelectAuth() throws Exception {
+        datasetAuthMixedFilteringTest(true);
+    }
+
+    @Test
+    public void testDatasetAuthMixedFilteringSelectNonAuth() throws Exception {
+        datasetAuthMixedFilteringTest(false);
+    }
+
+    private void datasetAuthMixedFilteringTest(boolean selectAuth) throws Exception {
+        // Set service.
+        enableService();
+        final MyAutofillCallback callback = mActivity.registerCallback();
+
+        // Create the authentication intents
+        final CannedDataset unlockedDataset = new CannedDataset.Builder()
+                .setField(ID_USERNAME, "DUDE")
+                .setField(ID_PASSWORD, "SWEET")
+                .build();
+        final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
+                unlockedDataset);
+
+        // Configure the service behavior
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, UNUSED_AUTOFILL_VALUE)
+                        .setField(ID_PASSWORD, UNUSED_AUTOFILL_VALUE)
+                        .setPresentation(createPresentation("Tap to auth dataset"))
+                        .setAuthentication(authentication)
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "dude")
+                        .setField(ID_PASSWORD, "sweet")
+                        .setPresentation(createPresentation("What, me auth?"))
+                        .build())
+                .build());
+
+        // Set expectation for the activity
+        if (selectAuth) {
+            mActivity.expectAutoFill("DUDE", "SWEET");
+        } else {
+            mActivity.expectAutoFill("dude", "sweet");
+        }
+
+        // Trigger auto-fill.
+        requestFocusOnUsername();
+
+        // Wait for onFill() before proceeding.
+        sReplier.getNextFillRequest();
+        final View username = mActivity.getUsername();
+
+        // Make sure it's showing initially...
+        callback.assertUiShownEvent(username);
+        mUiBot.assertDatasets("Tap to auth dataset", "What, me auth?");
+
+        // Filter the auth dataset.
+        mActivity.onUsername((v) -> v.setText("d"));
+        mUiBot.assertDatasets("What, me auth?");
+
+        // Filter all.
+        mActivity.onUsername((v) -> v.setText("dw"));
+        callback.assertUiHiddenEvent(username);
+        mUiBot.assertNoDatasets();
+
+        // Now delete the char and assert the non-auth is shown again.
+        mActivity.onUsername((v) -> v.setText("d"));
+        callback.assertUiShownEvent(username);
+        mUiBot.assertDatasets("What, me auth?");
+
+        // Delete again and assert all dataset are shown.
+        mActivity.onUsername((v) -> v.setText(""));
+        mUiBot.assertDatasets("Tap to auth dataset", "What, me auth?");
+
+        // ...and select it this time
+        final String chosenOne = selectAuth ? "Tap to auth dataset" : "What, me auth?";
+        mUiBot.selectDataset(chosenOne);
+        callback.assertUiHiddenEvent(username);
+        mUiBot.assertNoDatasets();
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+    }
+
+    @Test
+    public void testDatasetAuthClientStateSetOnIntentOnly() throws Exception {
+        fillDatasetAuthWithClientState(ClientStateLocation.INTENT_ONLY);
+    }
+
+    @Test
+    public void testDatasetAuthClientStateSetOnFillResponseOnly() throws Exception {
+        fillDatasetAuthWithClientState(ClientStateLocation.FILL_RESPONSE_ONLY);
+    }
+
+    @Test
+    public void testDatasetAuthClientStateSetOnIntentAndFillResponse() throws Exception {
+        fillDatasetAuthWithClientState(ClientStateLocation.BOTH);
+    }
+
+    private void fillDatasetAuthWithClientState(ClientStateLocation where) throws Exception {
+        // Set service.
+        enableService();
+
+        // Prepare the authenticated response
+        final CannedDataset dataset = new CannedDataset.Builder()
+                .setField(ID_USERNAME, "dude")
+                .setField(ID_PASSWORD, "sweet")
+                .build();
+        final IntentSender authentication = where == ClientStateLocation.FILL_RESPONSE_ONLY
+                ? AuthenticationActivity.createSender(mContext, 1,
+                        dataset)
+                : AuthenticationActivity.createSender(mContext, 1,
+                        dataset, newClientState("CSI", "FromIntent"));
+
+        // Configure the service behavior
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
+                .setExtras(newClientState("CSI", "FromResponse"))
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, UNUSED_AUTOFILL_VALUE)
+                        .setField(ID_PASSWORD, UNUSED_AUTOFILL_VALUE)
+                        .setPresentation(createPresentation("Tap to auth dataset"))
+                        .setAuthentication(authentication)
+                        .build())
+                .build());
+
+        // Set expectation for the activity
+        mActivity.expectAutoFill("dude", "sweet");
+
+        // Trigger auto-fill.
+        requestFocusOnUsername();
+        sReplier.getNextFillRequest();
+
+        // Tap authentication request.
+        mUiBot.selectDataset("Tap to auth dataset");
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+
+        // Now trigger save.
+        mActivity.onUsername((v) -> v.setText("malkovich"));
+        mActivity.onPassword((v) -> v.setText("malkovich"));
+        final String expectedMessage = getWelcomeMessage("malkovich");
+        final String actualMessage = mActivity.tapLogin();
+        assertWithMessage("Wrong welcome msg").that(actualMessage).isEqualTo(expectedMessage);
+        mUiBot.saveForAutofill(true, SAVE_DATA_TYPE_PASSWORD);
+
+        // Assert client state on authentication activity.
+        assertClientState("auth activity", AuthenticationActivity.getData(), "CSI", "FromResponse");
+
+        // Assert client state on save request.
+        final SaveRequest saveRequest = sReplier.getNextSaveRequest();
+        final String expectedValue = where == ClientStateLocation.FILL_RESPONSE_ONLY
+                ? "FromResponse" : "FromIntent";
+        assertClientState("on save", saveRequest.data, "CSI", expectedValue);
+    }
+
+    @Test
+    public void testFillResponseAuthBothFields() throws Exception {
+        fillResponseAuthBothFields(false);
+    }
+
+    @Test
+    public void testFillResponseAuthBothFieldsUserCancelsFirstAttempt() throws Exception {
+        fillResponseAuthBothFields(true);
+    }
+
+    private void fillResponseAuthBothFields(boolean cancelFirstAttempt) throws Exception {
+        // Set service.
+        enableService();
+        final MyAutofillCallback callback = mActivity.registerCallback();
+
+        // Prepare the authenticated response
+        final Bundle clientState = new Bundle();
+        clientState.putString("numbers", "4815162342");
+        final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
+                new CannedFillResponse.Builder().addDataset(
+                        new CannedDataset.Builder()
+                                .setField(ID_USERNAME, "dude")
+                                .setField(ID_PASSWORD, "sweet")
+                                .setId("name")
+                                .setPresentation(createPresentation("Dataset"))
+                                .build())
+                        .setExtras(clientState).build());
+
+        // Configure the service behavior
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .setAuthentication(authentication, ID_USERNAME, ID_PASSWORD)
+                .setPresentation(createPresentation("Tap to auth response"))
+                .setExtras(clientState)
+                .build());
+
+        // Set expectation for the activity
+        mActivity.expectAutoFill("dude", "sweet");
+
+        // Trigger auto-fill.
+        requestFocusOnUsername();
+
+        // Wait for onFill() before proceeding.
+        sReplier.getNextFillRequest();
+        final View username = mActivity.getUsername();
+        callback.assertUiShownEvent(username);
+        mUiBot.assertDatasets("Tap to auth response");
+
+        // Make sure UI is show on 2nd field as well
+        final View password = mActivity.getPassword();
+        requestFocusOnPassword();
+        callback.assertUiHiddenEvent(username);
+        callback.assertUiShownEvent(password);
+        mUiBot.assertDatasets("Tap to auth response");
+
+        // Now tap on 1st field to show it again...
+        requestFocusOnUsername();
+        callback.assertUiHiddenEvent(password);
+        callback.assertUiShownEvent(username);
+
+        if (cancelFirstAttempt) {
+            // Trigger the auth dialog, but emulate cancel.
+            AuthenticationActivity.setResultCode(RESULT_CANCELED);
+            mUiBot.selectDataset("Tap to auth response");
+            callback.assertUiHiddenEvent(username);
+            callback.assertUiShownEvent(username);
+            mUiBot.assertDatasets("Tap to auth response");
+
+            // Make sure it's still shown on other fields...
+            requestFocusOnPassword();
+            callback.assertUiHiddenEvent(username);
+            callback.assertUiShownEvent(password);
+            mUiBot.assertDatasets("Tap to auth response");
+
+            // Tap on 1st field to show it again...
+            requestFocusOnUsername();
+            callback.assertUiHiddenEvent(password);
+            callback.assertUiShownEvent(username);
+        }
+
+        // ...and select it this time
+        AuthenticationActivity.setResultCode(RESULT_OK);
+        mUiBot.selectDataset("Tap to auth response");
+        callback.assertUiHiddenEvent(username);
+        callback.assertUiShownEvent(username);
+        final UiObject2 picker = mUiBot.assertDatasets("Dataset");
+        mUiBot.selectDataset(picker, "Dataset");
+        callback.assertUiHiddenEvent(username);
+        mUiBot.assertNoDatasets();
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+
+        final Bundle data = AuthenticationActivity.getData();
+        assertThat(data).isNotNull();
+        final String extraValue = data.getString("numbers");
+        assertThat(extraValue).isEqualTo("4815162342");
+    }
+
+    @Test
+    public void testFillResponseAuthJustOneField() throws Exception {
+        // Set service.
+        enableService();
+        final MyAutofillCallback callback = mActivity.registerCallback();
+
+        // Prepare the authenticated response
+        final Bundle clientState = new Bundle();
+        clientState.putString("numbers", "4815162342");
+        final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
+                new CannedFillResponse.Builder().addDataset(
+                        new CannedDataset.Builder()
+                                .setField(ID_USERNAME, "dude")
+                                .setField(ID_PASSWORD, "sweet")
+                                .setPresentation(createPresentation("Dataset"))
+                                .build())
+                        .build());
+
+        // Configure the service behavior
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .setAuthentication(authentication, ID_USERNAME)
+                .setIgnoreFields(ID_PASSWORD)
+                .setPresentation(createPresentation("Tap to auth response"))
+                .setExtras(clientState)
+                .build());
+
+        // Set expectation for the activity
+        mActivity.expectAutoFill("dude", "sweet");
+
+        // Trigger auto-fill.
+        requestFocusOnUsername();
+
+        // Wait for onFill() before proceeding.
+        sReplier.getNextFillRequest();
+        final View username = mActivity.getUsername();
+        callback.assertUiShownEvent(username);
+        mUiBot.assertDatasets("Tap to auth response");
+
+        // Make sure UI is not show on 2nd field
+        requestFocusOnPassword();
+        callback.assertUiHiddenEvent(username);
+        mUiBot.assertNoDatasets();
+        // Now tap on 1st field to show it again...
+        requestFocusOnUsername();
+        callback.assertUiShownEvent(username);
+
+        // ...and select it this time
+        mUiBot.selectDataset("Tap to auth response");
+        callback.assertUiHiddenEvent(username);
+        final UiObject2 picker = mUiBot.assertDatasets("Dataset");
+
+        callback.assertUiShownEvent(username);
+        mUiBot.selectDataset(picker, "Dataset");
+        callback.assertUiHiddenEvent(username);
+        mUiBot.assertNoDatasets();
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+        final Bundle data = AuthenticationActivity.getData();
+        assertThat(data).isNotNull();
+        final String extraValue = data.getString("numbers");
+        assertThat(extraValue).isEqualTo("4815162342");
+    }
+
+    @Test
+    public void testFillResponseAuthWhenAppCallsCancel() throws Exception {
+        // Set service.
+        enableService();
+        final MyAutofillCallback callback = mActivity.registerCallback();
+
+        // Prepare the authenticated response
+        final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
+                new CannedFillResponse.Builder().addDataset(
+                        new CannedDataset.Builder()
+                                .setField(ID_USERNAME, "dude")
+                                .setField(ID_PASSWORD, "sweet")
+                                .setId("name")
+                                .setPresentation(createPresentation("Dataset"))
+                                .build())
+                        .build());
+
+        // Configure the service behavior
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .setAuthentication(authentication, ID_USERNAME, ID_PASSWORD)
+                .setPresentation(createPresentation("Tap to auth response"))
+                .build());
+
+        // Trigger autofill.
+        requestFocusOnUsername();
+
+        // Wait for onFill() before proceeding.
+        sReplier.getNextFillRequest();
+        final View username = mActivity.getUsername();
+        callback.assertUiShownEvent(username);
+        mUiBot.assertDatasets("Tap to auth response");
+
+        // Disables autofill so it's not triggered again after the auth activity is finished
+        // (and current session is canceled) and the login activity is resumed.
+        username.setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_NO);
+
+        // Autofill it.
+        final CountDownLatch latch = new CountDownLatch(1);
+        AuthenticationActivity.setResultCode(latch, RESULT_OK);
+
+        mUiBot.selectDataset("Tap to auth response");
+        callback.assertUiHiddenEvent(username);
+
+        // Cancel session...
+        mActivity.getAutofillManager().cancel();
+
+        // ...before finishing the Auth UI.
+        latch.countDown();
+
+        mUiBot.assertNoDatasets();
+    }
+
+    @Test
+    public void testFillResponseAuthServiceHasNoDataButCanSave() throws Exception {
+        fillResponseAuthServiceHasNoDataTest(true);
+    }
+
+    @Test
+    public void testFillResponseAuthServiceHasNoData() throws Exception {
+        fillResponseAuthServiceHasNoDataTest(false);
+    }
+
+    private void fillResponseAuthServiceHasNoDataTest(boolean canSave) throws Exception {
+        // Set service.
+        enableService();
+        final MyAutofillCallback callback = mActivity.registerCallback();
+
+        // Prepare the authenticated response
+        final CannedFillResponse response = canSave
+                ? new CannedFillResponse.Builder()
+                        .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
+                        .build()
+                : CannedFillResponse.NO_RESPONSE;
+
+        final IntentSender authentication =
+                AuthenticationActivity.createSender(mContext, 1, response);
+
+        // Configure the service behavior
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .setAuthentication(authentication, ID_USERNAME, ID_PASSWORD)
+                .setPresentation(createPresentation("Tap to auth response"))
+                .build());
+
+        // Trigger auto-fill.
+        requestFocusOnUsername();
+
+        // Wait for onFill() before proceeding.
+        sReplier.getNextFillRequest();
+        final View username = mActivity.getUsername();
+        callback.assertUiShownEvent(username);
+
+        // Select the authentication dialog.
+        mUiBot.selectDataset("Tap to auth response");
+        callback.assertUiHiddenEvent(username);
+        mUiBot.assertNoDatasets();
+    }
+
+    @Test
+    public void testFillResponseAuthClientStateSetOnIntentOnly() throws Exception {
+        fillResponseAuthWithClientState(ClientStateLocation.INTENT_ONLY);
+    }
+
+    @Test
+    public void testFillResponseAuthClientStateSetOnFillResponseOnly() throws Exception {
+        fillResponseAuthWithClientState(ClientStateLocation.FILL_RESPONSE_ONLY);
+    }
+
+    @Test
+    public void testFillResponseAuthClientStateSetOnIntentAndFillResponse() throws Exception {
+        fillResponseAuthWithClientState(ClientStateLocation.BOTH);
+    }
+
+    enum ClientStateLocation {
+        INTENT_ONLY,
+        FILL_RESPONSE_ONLY,
+        BOTH
+    }
+
+    private void fillResponseAuthWithClientState(ClientStateLocation where) throws Exception {
+        // Set service.
+        enableService();
+
+        // Prepare the authenticated response
+        final CannedFillResponse.Builder authenticatedResponseBuilder =
+                new CannedFillResponse.Builder()
+                .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "dude")
+                        .setField(ID_PASSWORD, "sweet")
+                        .setPresentation(createPresentation("Dataset"))
+                        .build());
+
+        if (where == ClientStateLocation.FILL_RESPONSE_ONLY || where == ClientStateLocation.BOTH) {
+            authenticatedResponseBuilder.setExtras(newClientState("CSI", "FromAuthResponse"));
+        }
+
+        final IntentSender authentication = where == ClientStateLocation.FILL_RESPONSE_ONLY
+                ? AuthenticationActivity.createSender(mContext, 1,
+                        authenticatedResponseBuilder.build())
+                : AuthenticationActivity.createSender(mContext, 1,
+                        authenticatedResponseBuilder.build(), newClientState("CSI", "FromIntent"));
+
+        // Configure the service behavior
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .setAuthentication(authentication, ID_USERNAME)
+                .setIgnoreFields(ID_PASSWORD)
+                .setPresentation(createPresentation("Tap to auth response"))
+                .setExtras(newClientState("CSI", "FromResponse"))
+                .build());
+
+        // Set expectation for the activity
+        mActivity.expectAutoFill("dude", "sweet");
+
+        // Trigger autofill.
+        requestFocusOnUsername();
+        sReplier.getNextFillRequest();
+
+        // Tap authentication request.
+        mUiBot.selectDataset("Tap to auth response");
+
+        // Tap dataset.
+        mUiBot.selectDataset("Dataset");
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+
+        // Now trigger save.
+        mActivity.onUsername((v) -> v.setText("malkovich"));
+        mActivity.onPassword((v) -> v.setText("malkovich"));
+        final String expectedMessage = getWelcomeMessage("malkovich");
+        final String actualMessage = mActivity.tapLogin();
+        assertWithMessage("Wrong welcome msg").that(actualMessage).isEqualTo(expectedMessage);
+        mUiBot.saveForAutofill(true, SAVE_DATA_TYPE_PASSWORD);
+
+        // Assert client state on authentication activity.
+        assertClientState("auth activity", AuthenticationActivity.getData(), "CSI", "FromResponse");
+
+        // Assert client state on save request.
+        final SaveRequest saveRequest = sReplier.getNextSaveRequest();
+        final String expectedValue = where == ClientStateLocation.FILL_RESPONSE_ONLY
+                ? "FromAuthResponse" : "FromIntent";
+        assertClientState("on save", saveRequest.data, "CSI", expectedValue);
+    }
+
+    // TODO(on master): move to helper / reuse in other places
+    private void assertClientState(String where, Bundle data, String expectedKey,
+            String expectedValue) {
+        assertWithMessage("no client state on %s", where).that(data).isNotNull();
+        final String extraValue = data.getString(expectedKey);
+        assertWithMessage("invalid value for %s on %s", expectedKey, where)
+            .that(extraValue).isEqualTo(expectedValue);
+    }
+
+    // TODO(on master): move to helper / reuse in other places
+    private Bundle newClientState(String key, String value) {
+        final Bundle clientState = new Bundle();
+        clientState.putString(key, value);
+        return clientState;
+    }
+
+    @Test
+    public void testFillResponseFiltering() throws Exception {
+        // Set service.
+        enableService();
+        final MyAutofillCallback callback = mActivity.registerCallback();
+
+        // Prepare the authenticated response
+        final Bundle clientState = new Bundle();
+        clientState.putString("numbers", "4815162342");
+        final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
+                new CannedFillResponse.Builder().addDataset(
+                        new CannedDataset.Builder()
+                                .setField(ID_USERNAME, "dude")
+                                .setField(ID_PASSWORD, "sweet")
+                                .setId("name")
+                                .setPresentation(createPresentation("Dataset"))
+                                .build())
+                        .setExtras(clientState).build());
+
+        // Configure the service behavior
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .setAuthentication(authentication, ID_USERNAME, ID_PASSWORD)
+                .setPresentation(createPresentation("Tap to auth response"))
+                .setExtras(clientState)
+                .build());
+
+        // Set expectation for the activity
+        mActivity.expectAutoFill("dude", "sweet");
+
+        // Trigger auto-fill.
+        requestFocusOnUsername();
+
+        // Wait for onFill() before proceeding.
+        sReplier.getNextFillRequest();
+        final View username = mActivity.getUsername();
+
+        // Make sure it's showing initially...
+        callback.assertUiShownEvent(username);
+        mUiBot.assertDatasets("Tap to auth response");
+
+        // ..then type something to hide it.
+        mActivity.onUsername((v) -> v.setText("a"));
+        callback.assertUiHiddenEvent(username);
+        mUiBot.assertNoDatasets();
+
+        // Now delete the char and assert it's shown again...
+        mActivity.onUsername((v) -> v.setText(""));
+        callback.assertUiShownEvent(username);
+        mUiBot.assertDatasets("Tap to auth response");
+
+        // ...and select it this time
+        AuthenticationActivity.setResultCode(RESULT_OK);
+        mUiBot.selectDataset("Tap to auth response");
+        callback.assertUiHiddenEvent(username);
+        callback.assertUiShownEvent(username);
+        final UiObject2 picker = mUiBot.assertDatasets("Dataset");
+        mUiBot.selectDataset(picker, "Dataset");
+        callback.assertUiHiddenEvent(username);
+        mUiBot.assertNoDatasets();
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+
+        final Bundle data = AuthenticationActivity.getData();
+        assertThat(data).isNotNull();
+        final String extraValue = data.getString("numbers");
+        assertThat(extraValue).isEqualTo("4815162342");
+    }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
index 4d39cb1..53dba8b 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
@@ -33,6 +33,8 @@
 import android.util.Log;
 import android.widget.RemoteViews;
 
+import com.android.compatibility.common.util.RequiredFeatureRule;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.BeforeClass;
@@ -74,7 +76,7 @@
     };
 
     @Rule
-    public final RetryRule mRetryRule = new RetryRule(2);
+    public final RetryRule mRetryRule = new RetryRule(5);
 
     @Rule
     public final AutofillLoggingTestRule mLoggingRule = new AutofillLoggingTestRule(TAG);
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AutoFinishSessionTest.java b/tests/autofillservice/src/android/autofillservice/cts/AutoFinishSessionTest.java
index 9262808..d576ce4 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AutoFinishSessionTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AutoFinishSessionTest.java
@@ -33,6 +33,7 @@
 import android.widget.EditText;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 
@@ -249,6 +250,7 @@
                 .getAutofillValue().getTextValue().toString()).isEqualTo("editText1-filled");
     }
 
+    @Ignore("temporarily disabled because UI is shown - b/73736562")
     @Test
     public void removeViewInBackground() throws Exception {
         activityToBackgroundShouldNotTriggerSave(
@@ -261,6 +263,7 @@
                 null);
     }
 
+    @Ignore("temporarily disabled because UI is shown - b/73736562")
     @Test
     public void hideViewInBackground() throws Exception {
         activityToBackgroundShouldNotTriggerSave(() -> {
@@ -272,12 +275,14 @@
                 null);
     }
 
+    @Ignore("temporarily disabled because UI is shown - b/73736562")
     @Test
     public void hideParentInBackground() throws Exception {
         activityToBackgroundShouldNotTriggerSave(() -> mParent.setVisibility(ViewGroup.INVISIBLE),
                 null);
     }
 
+    @Ignore("temporarily disabled because UI is shown - b/73736562")
     @Test
     public void removeParentInBackground() throws Exception {
         activityToBackgroundShouldNotTriggerSave(
diff --git a/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java b/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
index 78b6d9c..33aa025 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
@@ -69,6 +69,7 @@
     private final Validator mValidator;
     private final String[] mRequiredSavableIds;
     private final String[] mOptionalSavableIds;
+    private final AutofillId[] mRequiredSavableAutofillIds;
     private final String mSaveDescription;
     private final CustomDescription mCustomDescription;
     private final Bundle mExtras;
@@ -93,6 +94,7 @@
         mFailureMessage = builder.mFailureMessage;
         mValidator = builder.mValidator;
         mRequiredSavableIds = builder.mRequiredSavableIds;
+        mRequiredSavableAutofillIds = builder.mRequiredSavableAutofillIds;
         mOptionalSavableIds = builder.mOptionalSavableIds;
         mSaveDescription = builder.mSaveDescription;
         mCustomDescription = builder.mCustomDescription;
@@ -151,12 +153,16 @@
                 builder.addDataset(dataset);
             }
         }
-        if (mRequiredSavableIds != null) {
-            final SaveInfo.Builder saveInfo =
-                    mRequiredSavableIds == null || mRequiredSavableIds.length == 0
+        if (mRequiredSavableIds != null || mRequiredSavableAutofillIds != null) {
+            final SaveInfo.Builder saveInfo;
+            if (mRequiredSavableAutofillIds != null) {
+                saveInfo = new SaveInfo.Builder(mSaveType, mRequiredSavableAutofillIds);
+            } else {
+                saveInfo = mRequiredSavableIds == null || mRequiredSavableIds.length == 0
                         ? new SaveInfo.Builder(mSaveType)
                             : new SaveInfo.Builder(mSaveType,
                                     getAutofillIds(nodeResolver, mRequiredSavableIds));
+            }
 
             saveInfo.setFlags(mSaveInfoFlags);
 
@@ -222,6 +228,7 @@
                 + ",datasets=" + mDatasets
                 + ", requiredSavableIds=" + Arrays.toString(mRequiredSavableIds)
                 + ", optionalSavableIds=" + Arrays.toString(mOptionalSavableIds)
+                + ", requiredSavableAutofillIds=" + Arrays.toString(mRequiredSavableAutofillIds)
                 + ", saveInfoFlags=" + mSaveInfoFlags
                 + ", fillResponseFlags=" + mFillResponseFlags
                 + ", failureMessage=" + mFailureMessage
@@ -255,6 +262,7 @@
         private Validator mValidator;
         private String[] mRequiredSavableIds;
         private String[] mOptionalSavableIds;
+        private AutofillId[] mRequiredSavableAutofillIds;
         private String mSaveDescription;
         public CustomDescription mCustomDescription;
         public int mSaveType = -1;
@@ -297,14 +305,31 @@
         }
 
         /**
-         * Sets the required savable ids based on they {@code resourceId}.
+         * Sets the required savable ids based on their {@code resourceId}.
          */
         public Builder setRequiredSavableIds(int type, String... ids) {
+            if (mRequiredSavableAutofillIds != null) {
+                throw new IllegalStateException("Already set required autofill ids: "
+                        + Arrays.toString(mRequiredSavableAutofillIds));
+            }
             mSaveType = type;
             mRequiredSavableIds = ids;
             return this;
         }
 
+        /**
+         * Sets the required savable ids based on their {@code autofillId}.
+         */
+        public Builder setRequiredSavableAutofillIds(int type, AutofillId... ids) {
+            if (mRequiredSavableIds != null) {
+                throw new IllegalStateException("Already set required resource ids: "
+                        + Arrays.toString(mRequiredSavableIds));
+            }
+            mSaveType = type;
+            mRequiredSavableAutofillIds = ids;
+            return this;
+        }
+
         public Builder setSaveInfoFlags(int flags) {
             mSaveInfoFlags = flags;
             return this;
@@ -465,6 +490,8 @@
      */
     static class CannedDataset {
         private final Map<String, AutofillValue> mFieldValues;
+        private final Map<AutofillId, AutofillValue> mFieldValuesById;
+        private final Map<AutofillId, RemoteViews> mFieldPresentationsById;
         private final Map<String, RemoteViews> mFieldPresentations;
         private final Map<String, Pair<Boolean, Pattern>> mFieldFilters;
         private final RemoteViews mPresentation;
@@ -473,6 +500,8 @@
 
         private CannedDataset(Builder builder) {
             mFieldValues = builder.mFieldValues;
+            mFieldValuesById = builder.mFieldValuesById;
+            mFieldPresentationsById = builder.mFieldPresentationsById;
             mFieldPresentations = builder.mFieldPresentations;
             mFieldFilters = builder.mFieldFilters;
             mPresentation = builder.mPresentation;
@@ -495,25 +524,39 @@
                     if (node == null) {
                         throw new AssertionError("No node with resource id " + id);
                     }
-                    final AutofillId autofillid = node.getAutofillId();
+                    final AutofillId autofillId = node.getAutofillId();
                     final AutofillValue value = entry.getValue();
                     final RemoteViews presentation = mFieldPresentations.get(id);
                     final Pair<Boolean, Pattern> filter = mFieldFilters.get(id);
                     if (presentation != null) {
                         if (filter == null) {
-                            builder.setValue(autofillid, value, presentation);
+                            builder.setValue(autofillId, value, presentation);
                         } else {
-                            builder.setValue(autofillid, value, filter.second, presentation);
+                            builder.setValue(autofillId, value, filter.second, presentation);
                         }
                     } else {
                         if (filter == null) {
-                            builder.setValue(autofillid, value);
+                            builder.setValue(autofillId, value);
                         } else {
-                            builder.setValue(autofillid, value, filter.second);
+                            builder.setValue(autofillId, value, filter.second);
                         }
                     }
                 }
             }
+            if (mFieldValuesById != null) {
+                // NOTE: filter is not yet supported when calling methods that explicitly pass
+                // autofill id
+                for (Map.Entry<AutofillId, AutofillValue> entry : mFieldValuesById.entrySet()) {
+                    final AutofillId autofillId = entry.getKey();
+                    final AutofillValue value = entry.getValue();
+                    final RemoteViews presentation = mFieldPresentationsById.get(autofillId);
+                    if (presentation != null) {
+                        builder.setValue(autofillId, value, presentation);
+                    } else {
+                        builder.setValue(autofillId, value);
+                    }
+                }
+            }
             builder.setId(mId).setAuthentication(mAuthentication);
             return builder.build();
         }
@@ -522,14 +565,18 @@
         public String toString() {
             return "CannedDataset " + mId + " : [hasPresentation=" + (mPresentation != null)
                     + ", fieldPresentations=" + (mFieldPresentations)
+                    + ", fieldPresentationsById=" + (mFieldPresentationsById)
                     + ", hasAuthentication=" + (mAuthentication != null)
                     + ", fieldValues=" + mFieldValues
+                    + ", fieldValuesById=" + mFieldValuesById
                     + ", fieldFilters=" + mFieldFilters + "]";
         }
 
         static class Builder {
             private final Map<String, AutofillValue> mFieldValues = new HashMap<>();
+            private final Map<AutofillId, AutofillValue> mFieldValuesById = new HashMap<>();
             private final Map<String, RemoteViews> mFieldPresentations = new HashMap<>();
+            private final Map<AutofillId, RemoteViews> mFieldPresentationsById = new HashMap<>();
             private final Map<String, Pair<Boolean, Pattern>> mFieldFilters = new HashMap<>();
 
             private RemoteViews mPresentation;
@@ -616,6 +663,14 @@
             }
 
             /**
+             * Sets the canned value of a date field based on its {@code autofillId}.
+             */
+            public Builder setField(AutofillId autofillId, AutofillValue value) {
+                mFieldValuesById.put(autofillId, value);
+                return this;
+            }
+
+            /**
              * Sets the canned value of a date field based on its {@code id}.
              *
              * <p>The meaning of the id is defined by the object using the canned dataset.
@@ -643,6 +698,15 @@
             }
 
             /**
+             * Sets the canned value of a date field based on its {@code autofillId}.
+             */
+            public Builder setField(AutofillId autofillId, String text, RemoteViews presentation) {
+                setField(autofillId, AutofillValue.forText(text));
+                mFieldPresentationsById.put(autofillId, presentation);
+                return this;
+            }
+
+            /**
              * Sets the canned value of a field based on its {@code id}.
              *
              * <p>The meaning of the id is defined by the object using the canned dataset.
diff --git a/tests/autofillservice/src/android/autofillservice/cts/DatasetFilteringTest.java b/tests/autofillservice/src/android/autofillservice/cts/DatasetFilteringTest.java
new file mode 100644
index 0000000..91595a2
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/DatasetFilteringTest.java
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.autofillservice.cts;
+
+import static android.autofillservice.cts.Helper.ID_USERNAME;
+import static android.autofillservice.cts.common.ShellHelper.runShellCommand;
+
+import android.autofillservice.cts.CannedFillResponse.CannedDataset;
+
+import org.junit.Test;
+
+import java.util.regex.Pattern;
+
+public class DatasetFilteringTest extends AbstractLoginActivityTestCase {
+
+    @Test
+    public void testFilter() throws Exception {
+        final String aa = "Two A's";
+        final String ab = "A and B";
+        final String b = "Only B";
+
+        enableService();
+
+        // Set expectations.
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "aa")
+                        .setPresentation(createPresentation(aa))
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "ab")
+                        .setPresentation(createPresentation(ab))
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "b")
+                        .setPresentation(createPresentation(b))
+                        .build())
+                .build());
+
+        // Trigger auto-fill.
+        requestFocusOnUsername();
+        sReplier.getNextFillRequest();
+
+        // With no filter text all datasets should be shown
+        mUiBot.assertDatasets(aa, ab, b);
+
+        // Only two datasets start with 'a'
+        mActivity.onUsername((v) -> v.setText("a"));
+        mUiBot.assertDatasets(aa, ab);
+
+        // Only one dataset start with 'aa'
+        mActivity.onUsername((v) -> v.setText("aa"));
+        mUiBot.assertDatasets(aa);
+
+        // Only two datasets start with 'a'
+        mActivity.onUsername((v) -> v.setText("a"));
+        mUiBot.assertDatasets(aa, ab);
+
+        // With no filter text all datasets should be shown
+        mActivity.onUsername((v) -> v.setText(""));
+        mUiBot.assertDatasets(aa, ab, b);
+
+        // No dataset start with 'aaa'
+        final MyAutofillCallback callback = mActivity.registerCallback();
+        mActivity.onUsername((v) -> v.setText("aaa"));
+        callback.assertUiHiddenEvent(mActivity.getUsername());
+        mUiBot.assertNoDatasets();
+    }
+
+    @Test
+    public void testFilter_usingKeyboard() throws Exception {
+        if (!mCanPassKeys) {
+            return;
+        }
+
+        final String aa = "Two A's";
+        final String ab = "A and B";
+        final String b = "Only B";
+
+        enableService();
+
+        // Set expectations.
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "aa")
+                        .setPresentation(createPresentation(aa))
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "ab")
+                        .setPresentation(createPresentation(ab))
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "b")
+                        .setPresentation(createPresentation(b))
+                        .build())
+                .build());
+
+        // Trigger auto-fill.
+        requestFocusOnUsername();
+        sReplier.getNextFillRequest();
+
+        // With no filter text all datasets should be shown
+        mUiBot.assertDatasets(aa, ab, b);
+
+        // Only two datasets start with 'a'
+        runShellCommand("input keyevent KEYCODE_A");
+        mUiBot.assertDatasets(aa, ab);
+
+        // Only one dataset start with 'aa'
+        runShellCommand("input keyevent KEYCODE_A");
+        mUiBot.assertDatasets(aa);
+
+        // Only two datasets start with 'a'
+        runShellCommand("input keyevent KEYCODE_DEL");
+        mUiBot.assertDatasets(aa, ab);
+
+        // With no filter text all datasets should be shown
+        runShellCommand("input keyevent KEYCODE_DEL");
+        mUiBot.assertDatasets(aa, ab, b);
+
+        // No dataset start with 'aaa'
+        final MyAutofillCallback callback = mActivity.registerCallback();
+        runShellCommand("input keyevent KEYCODE_A");
+        runShellCommand("input keyevent KEYCODE_A");
+        runShellCommand("input keyevent KEYCODE_A");
+        callback.assertUiHiddenEvent(mActivity.getUsername());
+        mUiBot.assertNoDatasets();
+    }
+
+    @Test
+    public void testFilter_nullValuesAlwaysMatched() throws Exception {
+        final String aa = "Two A's";
+        final String ab = "A and B";
+        final String b = "Only B";
+
+        enableService();
+
+        // Set expectations.
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "aa")
+                        .setPresentation(createPresentation(aa))
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "ab")
+                        .setPresentation(createPresentation(ab))
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, (String) null)
+                        .setPresentation(createPresentation(b))
+                        .build())
+                .build());
+
+        // Trigger auto-fill.
+        requestFocusOnUsername();
+        sReplier.getNextFillRequest();
+
+        // With no filter text all datasets should be shown
+        mUiBot.assertDatasets(aa, ab, b);
+
+        // Two datasets start with 'a' and one with null value always shown
+        mActivity.onUsername((v) -> v.setText("a"));
+        mUiBot.assertDatasets(aa, ab, b);
+
+        // One dataset start with 'aa' and one with null value always shown
+        mActivity.onUsername((v) -> v.setText("aa"));
+        mUiBot.assertDatasets(aa, b);
+
+        // Two datasets start with 'a' and one with null value always shown
+        mActivity.onUsername((v) -> v.setText("a"));
+        mUiBot.assertDatasets(aa, ab, b);
+
+        // With no filter text all datasets should be shown
+        mActivity.onUsername((v) -> v.setText(""));
+        mUiBot.assertDatasets(aa, ab, b);
+
+        // No dataset start with 'aaa' and one with null value always shown
+        mActivity.onUsername((v) -> v.setText("aaa"));
+        mUiBot.assertDatasets(b);
+    }
+
+    @Test
+    public void testFilter_differentPrefixes() throws Exception {
+        final String a = "aaa";
+        final String b = "bra";
+        final String c = "cadabra";
+
+        enableService();
+
+        // Set expectations.
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, a)
+                        .setPresentation(createPresentation(a))
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, b)
+                        .setPresentation(createPresentation(b))
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, c)
+                        .setPresentation(createPresentation(c))
+                        .build())
+                .build());
+
+        // Trigger auto-fill.
+        requestFocusOnUsername();
+        sReplier.getNextFillRequest();
+
+        // With no filter text all datasets should be shown
+        mUiBot.assertDatasets(a, b, c);
+
+        mActivity.onUsername((v) -> v.setText("a"));
+        mUiBot.assertDatasets(a);
+
+        mActivity.onUsername((v) -> v.setText("b"));
+        mUiBot.assertDatasets(b);
+
+        mActivity.onUsername((v) -> v.setText("c"));
+        mUiBot.assertDatasets(c);
+    }
+
+    @Test
+    public void testFilter_usingRegex() throws Exception {
+        // Dataset presentations.
+        final String aa = "Two A's";
+        final String ab = "A and B";
+        final String b = "Only B";
+
+        enableService();
+
+        // Set expectations.
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "whatever", Pattern.compile("a|aa"))
+                        .setPresentation(createPresentation(aa))
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "whatsoever", createPresentation(ab),
+                                Pattern.compile("a|ab"))
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, (String) null, Pattern.compile("b"))
+                        .setPresentation(createPresentation(b))
+                        .build())
+                .build());
+
+        // Trigger auto-fill.
+        requestFocusOnUsername();
+        sReplier.getNextFillRequest();
+
+        // With no filter text all datasets should be shown
+        mUiBot.assertDatasets(aa, ab, b);
+
+        // Only two datasets start with 'a'
+        mActivity.onUsername((v) -> v.setText("a"));
+        mUiBot.assertDatasets(aa, ab);
+
+        // Only one dataset start with 'aa'
+        mActivity.onUsername((v) -> v.setText("aa"));
+        mUiBot.assertDatasets(aa);
+
+        // Only two datasets start with 'a'
+        mActivity.onUsername((v) -> v.setText("a"));
+        mUiBot.assertDatasets(aa, ab);
+
+        // With no filter text all datasets should be shown
+        mActivity.onUsername((v) -> v.setText(""));
+        mUiBot.assertDatasets(aa, ab, b);
+
+        // No dataset start with 'aaa'
+        final MyAutofillCallback callback = mActivity.registerCallback();
+        mActivity.onUsername((v) -> v.setText("aaa"));
+        callback.assertUiHiddenEvent(mActivity.getUsername());
+        mUiBot.assertNoDatasets();
+    }
+
+    @Test
+    public void testFilter_disabledUsingNullRegex() throws Exception {
+        // Dataset presentations.
+        final String unfilterable = "Unfilterabled";
+        final String aOrW = "A or W";
+        final String w = "Wazzup";
+
+        enableService();
+
+        // Set expectations.
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                // This dataset has a value but filter is disabled
+                .addDataset(new CannedDataset.Builder()
+                        .setUnfilterableField(ID_USERNAME, "a am I")
+                        .setPresentation(createPresentation(unfilterable))
+                        .build())
+                // This dataset uses pattern to filter
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "whatsoever", createPresentation(aOrW),
+                                Pattern.compile("a|aw"))
+                        .build())
+                // This dataset uses value to filter
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "wazzup")
+                        .setPresentation(createPresentation(w))
+                        .build())
+                .build());
+
+        // Trigger auto-fill.
+        requestFocusOnUsername();
+        sReplier.getNextFillRequest();
+
+        // With no filter text all datasets should be shown
+        mUiBot.assertDatasets(unfilterable, aOrW, w);
+
+        // Only one dataset start with 'a'
+        mActivity.onUsername((v) -> v.setText("a"));
+        mUiBot.assertDatasets(aOrW);
+
+        // No dataset starts with 'aa'
+        mActivity.onUsername((v) -> v.setText("aa"));
+        mUiBot.assertNoDatasets();
+
+        // Only one datasets start with 'a'
+        mActivity.onUsername((v) -> v.setText("a"));
+        mUiBot.assertDatasets(aOrW);
+
+        // With no filter text all datasets should be shown
+        mActivity.onUsername((v) -> v.setText(""));
+        mUiBot.assertDatasets(unfilterable, aOrW, w);
+
+        // Only one datasets start with 'w'
+        mActivity.onUsername((v) -> v.setText("w"));
+        mUiBot.assertDatasets(w);
+
+        // No dataset start with 'aaa'
+        final MyAutofillCallback callback = mActivity.registerCallback();
+        mActivity.onUsername((v) -> v.setText("aaa"));
+        callback.assertUiHiddenEvent(mActivity.getUsername());
+        mUiBot.assertNoDatasets();
+    }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/GridActivity.java b/tests/autofillservice/src/android/autofillservice/cts/GridActivity.java
index 29af4a2..65deff56 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/GridActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/GridActivity.java
@@ -20,6 +20,7 @@
 import android.view.autofill.AutofillManager;
 import android.widget.Button;
 import android.widget.EditText;
+import android.widget.GridLayout;
 
 import java.util.ArrayList;
 import java.util.concurrent.BlockingQueue;
@@ -45,6 +46,7 @@
     public static final String ID_L4C1 = getResourceId(4, 1);
     public static final String ID_L4C2 = getResourceId(4, 2);
 
+    private GridLayout mGrid;
     private final EditText[][] mCells = new EditText[4][2];
     private Button mSaveButton;
     private Button mClearButton;
@@ -55,16 +57,17 @@
 
         setContentView(R.layout.grid_activity);
 
-        mCells[0][0] = (EditText) findViewById(R.id.l1c1);
-        mCells[0][1] = (EditText) findViewById(R.id.l1c2);
-        mCells[1][0] = (EditText) findViewById(R.id.l2c1);
-        mCells[1][1] = (EditText) findViewById(R.id.l2c2);
-        mCells[2][0] = (EditText) findViewById(R.id.l3c1);
-        mCells[2][1] = (EditText) findViewById(R.id.l3c2);
-        mCells[3][0] = (EditText) findViewById(R.id.l4c1);
-        mCells[3][1] = (EditText) findViewById(R.id.l4c2);
-        mSaveButton = (Button) findViewById(R.id.save);
-        mClearButton = (Button) findViewById(R.id.clear);
+        mGrid = findViewById(R.id.grid);
+        mCells[0][0] = findViewById(R.id.l1c1);
+        mCells[0][1] = findViewById(R.id.l1c2);
+        mCells[1][0] = findViewById(R.id.l2c1);
+        mCells[1][1] = findViewById(R.id.l2c2);
+        mCells[2][0] = findViewById(R.id.l3c1);
+        mCells[2][1] = findViewById(R.id.l3c2);
+        mCells[3][0] = findViewById(R.id.l4c1);
+        mCells[3][1] = findViewById(R.id.l4c2);
+        mSaveButton = findViewById(R.id.save);
+        mClearButton = findViewById(R.id.clear);
 
         mSaveButton.setOnClickListener((v) -> save());
         mClearButton.setOnClickListener((v) -> resetFields());
@@ -112,6 +115,16 @@
         onCell(row, column, (c) -> getAutofillManager().requestAutofill(c));
     }
 
+    public void removeCell(int row, int column) {
+        onCell(row, column, (c) -> mGrid.removeView(c));
+    }
+
+    public void addCell(int row, int column, EditText cell) {
+        mCells[row - 1][column - 1] = cell;
+        // TODO: ideally it should be added in the right place...
+        syncRunOnUiThread(() -> mGrid.addView(cell));
+    }
+
     public void triggerAutofill(boolean manually, int row, int column) {
         if (manually) {
             forceAutofill(row, column);
diff --git a/tests/autofillservice/src/android/autofillservice/cts/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
index 4d11050..7030ace 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/Helper.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
@@ -58,6 +58,8 @@
 import android.view.autofill.AutofillValue;
 import android.webkit.WebView;
 
+import com.android.compatibility.common.util.RequiredFeatureRule;
+
 import java.lang.reflect.Field;
 import java.util.List;
 import java.util.Map;
@@ -104,13 +106,17 @@
         /**
          * Returns whether the node passes the filter for such given id.
          */
-        boolean matches(T node, String id);
+        boolean matches(T node, Object id);
     }
 
     private static final NodeFilter<ViewNode> RESOURCE_ID_FILTER = (node, id) -> {
         return id.equals(node.getIdEntry());
     };
 
+    private static final NodeFilter<ViewNode> AUTOFILL_ID_FILTER = (node, id) -> {
+        return id.equals(node.getAutofillId());
+    };
+
     private static final NodeFilter<ViewNode> HTML_NAME_FILTER = (node, id) -> {
         return id.equals(getHtmlName(node));
     };
@@ -209,7 +215,7 @@
     /**
      * Gets a node if it matches the filter criteria for the given id.
      */
-    static ViewNode findNodeByFilter(@NonNull AssistStructure structure, @NonNull String id,
+    static ViewNode findNodeByFilter(@NonNull AssistStructure structure, @NonNull Object id,
             @NonNull NodeFilter<ViewNode> filter) {
         Log.v(TAG, "Parsing request for activity " + structure.getActivityComponent());
         final int nodes = structure.getWindowNodeCount();
@@ -227,7 +233,7 @@
     /**
      * Gets a node if it matches the filter criteria for the given id.
      */
-    static ViewNode findNodeByFilter(@NonNull List<FillContext> contexts, @NonNull String id,
+    static ViewNode findNodeByFilter(@NonNull List<FillContext> contexts, @NonNull Object id,
             @NonNull NodeFilter<ViewNode> filter) {
         for (FillContext context : contexts) {
             ViewNode node = findNodeByFilter(context.getStructure(), id, filter);
@@ -241,7 +247,7 @@
     /**
      * Gets a node if it matches the filter criteria for the given id.
      */
-    static ViewNode findNodeByFilter(@NonNull ViewNode node, @NonNull String id,
+    static ViewNode findNodeByFilter(@NonNull ViewNode node, @NonNull Object id,
             @NonNull NodeFilter<ViewNode> filter) {
         if (filter.matches(node, id)) {
             return node;
@@ -370,6 +376,14 @@
     }
 
     /**
+     * Gets a view (or a descendant of it) that has the given {@code id}, or {@code null} if
+     * not found.
+     */
+    static ViewNode findNodeByAutofillId(AssistStructure structure, AutofillId id) {
+        return findNodeByFilter(structure, id, AUTOFILL_ID_FILTER);
+    }
+
+    /**
      * Asserts a text-based node is sanitized.
      */
     static void assertTextIsSanitized(ViewNode node) {
@@ -730,6 +744,13 @@
     }
 
     /**
+     * Check if autofill window is fullscreen, see com.android.server.autofill.ui.FillUi
+     */
+    public static boolean isAutofillWindowFullScreen(Context context) {
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+    }
+
+    /**
      * Uses Shell command to get the Autofill logging level.
      */
     public static String getLoggingLevel() {
@@ -1160,7 +1181,7 @@
         }
     }
 
-    public static boolean hasHint(@Nullable String[] hints, @Nullable String expectedHint) {
+    public static boolean hasHint(@Nullable String[] hints, @Nullable Object expectedHint) {
         if (hints == null || expectedHint == null) return false;
         for (String actualHint : hints) {
             if (expectedHint.equals(actualHint)) return true;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
index 6137b4b..e0b0aa7 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
@@ -16,15 +16,12 @@
 
 package android.autofillservice.cts;
 
-import static android.app.Activity.RESULT_CANCELED;
-import static android.app.Activity.RESULT_OK;
 import static android.autofillservice.cts.CannedFillResponse.DO_NOT_REPLY_RESPONSE;
 import static android.autofillservice.cts.CannedFillResponse.NO_RESPONSE;
 import static android.autofillservice.cts.Helper.ID_PASSWORD;
 import static android.autofillservice.cts.Helper.ID_PASSWORD_LABEL;
 import static android.autofillservice.cts.Helper.ID_USERNAME;
 import static android.autofillservice.cts.Helper.ID_USERNAME_LABEL;
-import static android.autofillservice.cts.Helper.UNUSED_AUTOFILL_VALUE;
 import static android.autofillservice.cts.Helper.assertHasFlags;
 import static android.autofillservice.cts.Helper.assertNumberOfChildren;
 import static android.autofillservice.cts.Helper.assertTextAndValue;
@@ -82,75 +79,23 @@
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeProvider;
 import android.view.autofill.AutofillManager;
-import android.view.autofill.AutofillValue;
 import android.widget.RemoteViews;
 
-import org.junit.Before;
 import org.junit.Ignore;
-import org.junit.Rule;
 import org.junit.Test;
 
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicInteger;
-import java.util.regex.Pattern;
 
 /**
  * This is the test case covering most scenarios - other test cases will cover characteristics
  * specific to that test's activity (for example, custom views).
  */
-public class LoginActivityTest extends AutoFillServiceTestCase {
+public class LoginActivityTest extends AbstractLoginActivityTestCase {
 
     private static final String TAG = "LoginActivityTest";
 
-    @Rule
-    public final AutofillActivityTestRule<LoginActivity> mActivityRule =
-        new AutofillActivityTestRule<LoginActivity>(LoginActivity.class);
-
-    @Rule
-    public final AutofillActivityTestRule<CheckoutActivity> mCheckoutActivityRule =
-            new AutofillActivityTestRule<CheckoutActivity>(CheckoutActivity.class, false);
-
-    private LoginActivity mActivity;
-
-    @Before
-    public void setActivity() {
-        mActivity = mActivityRule.getActivity();
-    }
-
-    /**
-     * Request focus on username and expect Window event happens.
-     */
-    void requestFocusOnUsername() throws TimeoutException {
-        mUiBot.waitForWindowChange(() -> mActivity.onUsername(View::requestFocus),
-                Timeouts.UI_TIMEOUT.getMaxValue());
-    }
-
-    /**
-     * Request focus on username and expect no Window event happens.
-     */
-    void requestFocusOnUsernameNoWindowChange() {
-        try {
-            // TODO: define a small value in Timeout
-            mUiBot.waitForWindowChange(() -> mActivity.onUsername(View::requestFocus),
-                    Timeouts.UI_TIMEOUT.ms());
-        } catch (TimeoutException ex) {
-            // no window events! looking good
-            return;
-        }
-        throw new IllegalStateException("Expect no window event when focusing to"
-                + " username, but event happened");
-    }
-
-    /**
-     * Request focus on password and expect Window event happens.
-     */
-    void requestFocusOnPassword() throws TimeoutException {
-        mUiBot.waitForWindowChange(() -> mActivity.onPassword(View::requestFocus),
-                Timeouts.UI_TIMEOUT.getMaxValue());
-    }
-
     @Test
     public void testAutoFillNoDatasets() throws Exception {
         // Set service.
@@ -1184,270 +1129,6 @@
     }
 
     @Test
-    public void filterText() throws Exception {
-        final String AA = "Two A's";
-        final String AB = "A and B";
-        final String B = "Only B";
-
-        enableService();
-
-        // Set expectations.
-        sReplier.addResponse(new CannedFillResponse.Builder()
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, "aa")
-                        .setPresentation(createPresentation(AA))
-                        .build())
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, "ab")
-                        .setPresentation(createPresentation(AB))
-                        .build())
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, "b")
-                        .setPresentation(createPresentation(B))
-                        .build())
-                .build());
-
-        // Trigger auto-fill.
-        requestFocusOnUsername();
-        sReplier.getNextFillRequest();
-
-        // With no filter text all datasets should be shown
-        mUiBot.assertDatasets(AA, AB, B);
-
-        // Only two datasets start with 'a'
-        mActivity.onUsername((v) -> v.setText("a"));
-        mUiBot.assertDatasets(AA, AB);
-
-        // Only one dataset start with 'aa'
-        mActivity.onUsername((v) -> v.setText("aa"));
-        mUiBot.assertDatasets(AA);
-
-        // Only two datasets start with 'a'
-        mActivity.onUsername((v) -> v.setText("a"));
-        mUiBot.assertDatasets(AA, AB);
-
-        // With no filter text all datasets should be shown
-        mActivity.onUsername((v) -> v.setText(""));
-        mUiBot.assertDatasets(AA, AB, B);
-
-        // No dataset start with 'aaa'
-        final MyAutofillCallback callback = mActivity.registerCallback();
-        mActivity.onUsername((v) -> v.setText("aaa"));
-        callback.assertUiHiddenEvent(mActivity.getUsername());
-        mUiBot.assertNoDatasets();
-    }
-
-    @Test
-    public void filterTextNullValuesAlwaysMatched() throws Exception {
-        final String AA = "Two A's";
-        final String AB = "A and B";
-        final String B = "Only B";
-
-        enableService();
-
-        // Set expectations.
-        sReplier.addResponse(new CannedFillResponse.Builder()
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, "aa")
-                        .setPresentation(createPresentation(AA))
-                        .build())
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, "ab")
-                        .setPresentation(createPresentation(AB))
-                        .build())
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, (String) null)
-                        .setPresentation(createPresentation(B))
-                        .build())
-                .build());
-
-        // Trigger auto-fill.
-        requestFocusOnUsername();
-        sReplier.getNextFillRequest();
-
-        // With no filter text all datasets should be shown
-        mUiBot.assertDatasets(AA, AB, B);
-
-        // Two datasets start with 'a' and one with null value always shown
-        mActivity.onUsername((v) -> v.setText("a"));
-        mUiBot.assertDatasets(AA, AB, B);
-
-        // One dataset start with 'aa' and one with null value always shown
-        mActivity.onUsername((v) -> v.setText("aa"));
-        mUiBot.assertDatasets(AA, B);
-
-        // Two datasets start with 'a' and one with null value always shown
-        mActivity.onUsername((v) -> v.setText("a"));
-        mUiBot.assertDatasets(AA, AB, B);
-
-        // With no filter text all datasets should be shown
-        mActivity.onUsername((v) -> v.setText(""));
-        mUiBot.assertDatasets(AA, AB, B);
-
-        // No dataset start with 'aaa' and one with null value always shown
-        mActivity.onUsername((v) -> v.setText("aaa"));
-        mUiBot.assertDatasets(B);
-    }
-
-    @Test
-    public void filterTextDifferentPrefixes() throws Exception {
-        final String A = "aaa";
-        final String B = "bra";
-        final String C = "cadabra";
-
-        enableService();
-
-        // Set expectations.
-        sReplier.addResponse(new CannedFillResponse.Builder()
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, A)
-                        .setPresentation(createPresentation(A))
-                        .build())
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, B)
-                        .setPresentation(createPresentation(B))
-                        .build())
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, C)
-                        .setPresentation(createPresentation(C))
-                        .build())
-                .build());
-
-        // Trigger auto-fill.
-        requestFocusOnUsername();
-        sReplier.getNextFillRequest();
-
-        // With no filter text all datasets should be shown
-        mUiBot.assertDatasets(A, B, C);
-
-        mActivity.onUsername((v) -> v.setText("a"));
-        mUiBot.assertDatasets(A);
-
-        mActivity.onUsername((v) -> v.setText("b"));
-        mUiBot.assertDatasets(B);
-
-        mActivity.onUsername((v) -> v.setText("c"));
-        mUiBot.assertDatasets(C);
-    }
-
-    @Test
-    public void filterTextUsingRegex() throws Exception {
-        // Dataset presentations.
-        final String aa = "Two A's";
-        final String ab = "A and B";
-        final String b = "Only B";
-
-        enableService();
-
-        // Set expectations.
-        sReplier.addResponse(new CannedFillResponse.Builder()
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, "whatever", Pattern.compile("a|aa"))
-                        .setPresentation(createPresentation(aa))
-                        .build())
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, "whatsoever", createPresentation(ab),
-                                Pattern.compile("a|ab"))
-                        .build())
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, (String) null, Pattern.compile("b"))
-                        .setPresentation(createPresentation(b))
-                        .build())
-                .build());
-
-        // Trigger auto-fill.
-        requestFocusOnUsername();
-        sReplier.getNextFillRequest();
-
-        // With no filter text all datasets should be shown
-        mUiBot.assertDatasets(aa, ab, b);
-
-        // Only two datasets start with 'a'
-        mActivity.onUsername((v) -> v.setText("a"));
-        mUiBot.assertDatasets(aa, ab);
-
-        // Only one dataset start with 'aa'
-        mActivity.onUsername((v) -> v.setText("aa"));
-        mUiBot.assertDatasets(aa);
-
-        // Only two datasets start with 'a'
-        mActivity.onUsername((v) -> v.setText("a"));
-        mUiBot.assertDatasets(aa, ab);
-
-        // With no filter text all datasets should be shown
-        mActivity.onUsername((v) -> v.setText(""));
-        mUiBot.assertDatasets(aa, ab, b);
-
-        // No dataset start with 'aaa'
-        final MyAutofillCallback callback = mActivity.registerCallback();
-        mActivity.onUsername((v) -> v.setText("aaa"));
-        callback.assertUiHiddenEvent(mActivity.getUsername());
-        mUiBot.assertNoDatasets();
-    }
-
-    @Test
-    public void filterTextDisabledUsingNullRegex() throws Exception {
-        // Dataset presentations.
-        final String unfilterable = "Unfilterabled";
-        final String aOrW = "A or W";
-        final String w = "Wazzup";
-
-        enableService();
-
-        // Set expectations.
-        sReplier.addResponse(new CannedFillResponse.Builder()
-                // This dataset has a value but filter is disabled
-                .addDataset(new CannedDataset.Builder()
-                        .setUnfilterableField(ID_USERNAME, "a am I")
-                        .setPresentation(createPresentation(unfilterable))
-                        .build())
-                // This dataset uses pattern to filter
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, "whatsoever", createPresentation(aOrW),
-                                Pattern.compile("a|aw"))
-                        .build())
-                // This dataset uses value to filter
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, "wazzup")
-                        .setPresentation(createPresentation(w))
-                        .build())
-                .build());
-
-        // Trigger auto-fill.
-        requestFocusOnUsername();
-        sReplier.getNextFillRequest();
-
-        // With no filter text all datasets should be shown
-        mUiBot.assertDatasets(unfilterable, aOrW, w);
-
-        // Only one dataset start with 'a'
-        mActivity.onUsername((v) -> v.setText("a"));
-        mUiBot.assertDatasets(aOrW);
-
-        // No dataset starts with 'aa'
-        mActivity.onUsername((v) -> v.setText("aa"));
-        mUiBot.assertNoDatasets();
-
-        // Only one datasets start with 'a'
-        mActivity.onUsername((v) -> v.setText("a"));
-        mUiBot.assertDatasets(aOrW);
-
-        // With no filter text all datasets should be shown
-        mActivity.onUsername((v) -> v.setText(""));
-        mUiBot.assertDatasets(unfilterable, aOrW, w);
-
-        // Only one datasets start with 'w'
-        mActivity.onUsername((v) -> v.setText("w"));
-        mUiBot.assertDatasets(w);
-
-        // No dataset start with 'aaa'
-        final MyAutofillCallback callback = mActivity.registerCallback();
-        mActivity.onUsername((v) -> v.setText("aaa"));
-        callback.assertUiHiddenEvent(mActivity.getUsername());
-        mUiBot.assertNoDatasets();
-    }
-
-    @Test
     public void testSaveOnly() throws Exception {
         saveOnlyTest(false);
     }
@@ -1939,1115 +1620,6 @@
     }
 
     @Test
-    public void testFillResponseAuthBothFields() throws Exception {
-        fillResponseAuthBothFields(false);
-    }
-
-    @Test
-    public void testFillResponseAuthBothFieldsUserCancelsFirstAttempt() throws Exception {
-        fillResponseAuthBothFields(true);
-    }
-
-    private void fillResponseAuthBothFields(boolean cancelFirstAttempt) throws Exception {
-        // Set service.
-        enableService();
-        final MyAutofillCallback callback = mActivity.registerCallback();
-
-        // Prepare the authenticated response
-        final Bundle clientState = new Bundle();
-        clientState.putString("numbers", "4815162342");
-        final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
-                new CannedFillResponse.Builder().addDataset(
-                        new CannedDataset.Builder()
-                                .setField(ID_USERNAME, "dude")
-                                .setField(ID_PASSWORD, "sweet")
-                                .setId("name")
-                                .setPresentation(createPresentation("Dataset"))
-                                .build())
-                        .setExtras(clientState).build());
-
-        // Configure the service behavior
-        sReplier.addResponse(new CannedFillResponse.Builder()
-                .setAuthentication(authentication, ID_USERNAME, ID_PASSWORD)
-                .setPresentation(createPresentation("Tap to auth response"))
-                .setExtras(clientState)
-                .build());
-
-        // Set expectation for the activity
-        mActivity.expectAutoFill("dude", "sweet");
-
-        // Trigger auto-fill.
-        requestFocusOnUsername();
-
-        // Wait for onFill() before proceeding.
-        sReplier.getNextFillRequest();
-        final View username = mActivity.getUsername();
-        callback.assertUiShownEvent(username);
-        mUiBot.assertDatasets("Tap to auth response");
-
-        // Make sure UI is show on 2nd field as well
-        final View password = mActivity.getPassword();
-        requestFocusOnPassword();
-        callback.assertUiHiddenEvent(username);
-        callback.assertUiShownEvent(password);
-        mUiBot.assertDatasets("Tap to auth response");
-
-        // Now tap on 1st field to show it again...
-        requestFocusOnUsername();
-        callback.assertUiHiddenEvent(password);
-        callback.assertUiShownEvent(username);
-
-        if (cancelFirstAttempt) {
-            // Trigger the auth dialog, but emulate cancel.
-            AuthenticationActivity.setResultCode(RESULT_CANCELED);
-            mUiBot.selectDataset("Tap to auth response");
-            callback.assertUiHiddenEvent(username);
-            callback.assertUiShownEvent(username);
-            mUiBot.assertDatasets("Tap to auth response");
-
-            // Make sure it's still shown on other fields...
-            requestFocusOnPassword();
-            callback.assertUiHiddenEvent(username);
-            callback.assertUiShownEvent(password);
-            mUiBot.assertDatasets("Tap to auth response");
-
-            // Tap on 1st field to show it again...
-            requestFocusOnUsername();
-            callback.assertUiHiddenEvent(password);
-            callback.assertUiShownEvent(username);
-        }
-
-        // ...and select it this time
-        AuthenticationActivity.setResultCode(RESULT_OK);
-        mUiBot.selectDataset("Tap to auth response");
-        callback.assertUiHiddenEvent(username);
-        callback.assertUiShownEvent(username);
-        final UiObject2 picker = mUiBot.assertDatasets("Dataset");
-        mUiBot.selectDataset(picker, "Dataset");
-        callback.assertUiHiddenEvent(username);
-        mUiBot.assertNoDatasets();
-
-        // Check the results.
-        mActivity.assertAutoFilled();
-
-        final Bundle data = AuthenticationActivity.getData();
-        assertThat(data).isNotNull();
-        final String extraValue = data.getString("numbers");
-        assertThat(extraValue).isEqualTo("4815162342");
-    }
-
-    @Test
-    public void testFillResponseAuthJustOneField() throws Exception {
-        // Set service.
-        enableService();
-        final MyAutofillCallback callback = mActivity.registerCallback();
-
-        // Prepare the authenticated response
-        final Bundle clientState = new Bundle();
-        clientState.putString("numbers", "4815162342");
-        final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
-                new CannedFillResponse.Builder().addDataset(
-                        new CannedDataset.Builder()
-                                .setField(ID_USERNAME, "dude")
-                                .setField(ID_PASSWORD, "sweet")
-                                .setPresentation(createPresentation("Dataset"))
-                                .build())
-                        .build());
-
-        // Configure the service behavior
-        sReplier.addResponse(new CannedFillResponse.Builder()
-                .setAuthentication(authentication, ID_USERNAME)
-                .setIgnoreFields(ID_PASSWORD)
-                .setPresentation(createPresentation("Tap to auth response"))
-                .setExtras(clientState)
-                .build());
-
-        // Set expectation for the activity
-        mActivity.expectAutoFill("dude", "sweet");
-
-        // Trigger auto-fill.
-        requestFocusOnUsername();
-
-        // Wait for onFill() before proceeding.
-        sReplier.getNextFillRequest();
-        final View username = mActivity.getUsername();
-        callback.assertUiShownEvent(username);
-        mUiBot.assertDatasets("Tap to auth response");
-
-        // Make sure UI is not show on 2nd field
-        requestFocusOnPassword();
-        callback.assertUiHiddenEvent(username);
-        mUiBot.assertNoDatasets();
-        // Now tap on 1st field to show it again...
-        requestFocusOnUsername();
-        callback.assertUiShownEvent(username);
-
-        // ...and select it this time
-        mUiBot.selectDataset("Tap to auth response");
-        callback.assertUiHiddenEvent(username);
-        final UiObject2 picker = mUiBot.assertDatasets("Dataset");
-
-        callback.assertUiShownEvent(username);
-        mUiBot.selectDataset(picker, "Dataset");
-        callback.assertUiHiddenEvent(username);
-        mUiBot.assertNoDatasets();
-
-        // Check the results.
-        mActivity.assertAutoFilled();
-        final Bundle data = AuthenticationActivity.getData();
-        assertThat(data).isNotNull();
-        final String extraValue = data.getString("numbers");
-        assertThat(extraValue).isEqualTo("4815162342");
-    }
-
-    @Test
-    public void testFillResponseAuthWhenAppCallsCancel() throws Exception {
-        // Set service.
-        enableService();
-        final MyAutofillCallback callback = mActivity.registerCallback();
-
-        // Prepare the authenticated response
-        final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
-                new CannedFillResponse.Builder().addDataset(
-                        new CannedDataset.Builder()
-                                .setField(ID_USERNAME, "dude")
-                                .setField(ID_PASSWORD, "sweet")
-                                .setId("name")
-                                .setPresentation(createPresentation("Dataset"))
-                                .build())
-                        .build());
-
-        // Configure the service behavior
-        sReplier.addResponse(new CannedFillResponse.Builder()
-                .setAuthentication(authentication, ID_USERNAME, ID_PASSWORD)
-                .setPresentation(createPresentation("Tap to auth response"))
-                .build());
-
-        // Trigger autofill.
-        requestFocusOnUsername();
-
-        // Wait for onFill() before proceeding.
-        sReplier.getNextFillRequest();
-        final View username = mActivity.getUsername();
-        callback.assertUiShownEvent(username);
-        mUiBot.assertDatasets("Tap to auth response");
-
-        // Disables autofill so it's not triggered again after the auth activity is finished
-        // (and current session is canceled) and the login activity is resumed.
-        username.setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_NO);
-
-        // Autofill it.
-        final CountDownLatch latch = new CountDownLatch(1);
-        AuthenticationActivity.setResultCode(latch, RESULT_OK);
-
-        mUiBot.selectDataset("Tap to auth response");
-        callback.assertUiHiddenEvent(username);
-
-        // Cancel session...
-        mActivity.getAutofillManager().cancel();
-
-        // ...before finishing the Auth UI.
-        latch.countDown();
-
-        mUiBot.assertNoDatasets();
-    }
-
-    @Test
-    public void testFillResponseAuthServiceHasNoDataButCanSave() throws Exception {
-        fillResponseAuthServiceHasNoDataTest(true);
-    }
-
-    @Test
-    public void testFillResponseAuthServiceHasNoData() throws Exception {
-        fillResponseAuthServiceHasNoDataTest(false);
-    }
-
-    private void fillResponseAuthServiceHasNoDataTest(boolean canSave) throws Exception {
-        // Set service.
-        enableService();
-        final MyAutofillCallback callback = mActivity.registerCallback();
-
-        // Prepare the authenticated response
-        final CannedFillResponse response = canSave
-                ? new CannedFillResponse.Builder()
-                        .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
-                        .build()
-                : CannedFillResponse.NO_RESPONSE;
-
-        final IntentSender authentication =
-                AuthenticationActivity.createSender(mContext, 1, response);
-
-        // Configure the service behavior
-        sReplier.addResponse(new CannedFillResponse.Builder()
-                .setAuthentication(authentication, ID_USERNAME, ID_PASSWORD)
-                .setPresentation(createPresentation("Tap to auth response"))
-                .build());
-
-        // Trigger auto-fill.
-        requestFocusOnUsername();
-
-        // Wait for onFill() before proceeding.
-        sReplier.getNextFillRequest();
-        final View username = mActivity.getUsername();
-        callback.assertUiShownEvent(username);
-
-        // Select the authentication dialog.
-        mUiBot.selectDataset("Tap to auth response");
-        callback.assertUiHiddenEvent(username);
-        mUiBot.assertNoDatasets();
-    }
-
-    @Test
-    public void testFillResponseAuthClientStateSetOnIntentOnly() throws Exception {
-        fillResponseAuthWithClientState(ClientStateLocation.INTENT_ONLY);
-    }
-
-    @Test
-    public void testFillResponseAuthClientStateSetOnFillResponseOnly() throws Exception {
-        fillResponseAuthWithClientState(ClientStateLocation.FILL_RESPONSE_ONLY);
-    }
-
-    @Test
-    public void testFillResponseAuthClientStateSetOnIntentAndFillResponse() throws Exception {
-        fillResponseAuthWithClientState(ClientStateLocation.BOTH);
-    }
-
-    enum ClientStateLocation {
-        INTENT_ONLY,
-        FILL_RESPONSE_ONLY,
-        BOTH
-    }
-
-    private void fillResponseAuthWithClientState(ClientStateLocation where) throws Exception {
-        // Set service.
-        enableService();
-
-        // Prepare the authenticated response
-        final CannedFillResponse.Builder authenticatedResponseBuilder =
-                new CannedFillResponse.Builder()
-                .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, "dude")
-                        .setField(ID_PASSWORD, "sweet")
-                        .setPresentation(createPresentation("Dataset"))
-                        .build());
-
-        if (where == ClientStateLocation.FILL_RESPONSE_ONLY || where == ClientStateLocation.BOTH) {
-            authenticatedResponseBuilder.setExtras(newClientState("CSI", "FromAuthResponse"));
-        }
-
-        final IntentSender authentication = where == ClientStateLocation.FILL_RESPONSE_ONLY
-                ? AuthenticationActivity.createSender(mContext, 1,
-                        authenticatedResponseBuilder.build())
-                : AuthenticationActivity.createSender(mContext, 1,
-                        authenticatedResponseBuilder.build(), newClientState("CSI", "FromIntent"));
-
-        // Configure the service behavior
-        sReplier.addResponse(new CannedFillResponse.Builder()
-                .setAuthentication(authentication, ID_USERNAME)
-                .setIgnoreFields(ID_PASSWORD)
-                .setPresentation(createPresentation("Tap to auth response"))
-                .setExtras(newClientState("CSI", "FromResponse"))
-                .build());
-
-        // Set expectation for the activity
-        mActivity.expectAutoFill("dude", "sweet");
-
-        // Trigger autofill.
-        requestFocusOnUsername();
-        sReplier.getNextFillRequest();
-
-        // Tap authentication request.
-        mUiBot.selectDataset("Tap to auth response");
-
-        // Tap dataset.
-        mUiBot.selectDataset("Dataset");
-
-        // Check the results.
-        mActivity.assertAutoFilled();
-
-        // Now trigger save.
-        mActivity.onUsername((v) -> v.setText("malkovich"));
-        mActivity.onPassword((v) -> v.setText("malkovich"));
-        final String expectedMessage = getWelcomeMessage("malkovich");
-        final String actualMessage = mActivity.tapLogin();
-        assertWithMessage("Wrong welcome msg").that(actualMessage).isEqualTo(expectedMessage);
-        mUiBot.saveForAutofill(true, SAVE_DATA_TYPE_PASSWORD);
-
-        // Assert client state on authentication activity.
-        assertClientState("auth activity", AuthenticationActivity.getData(), "CSI", "FromResponse");
-
-        // Assert client state on save request.
-        final SaveRequest saveRequest = sReplier.getNextSaveRequest();
-        final String expectedValue = where == ClientStateLocation.FILL_RESPONSE_ONLY
-                ? "FromAuthResponse" : "FromIntent";
-        assertClientState("on save", saveRequest.data, "CSI", expectedValue);
-    }
-
-    // TODO(on master): move to helper / reuse in other places
-    private void assertClientState(String where, Bundle data, String expectedKey,
-            String expectedValue) {
-        assertWithMessage("no client state on %s", where).that(data).isNotNull();
-        final String extraValue = data.getString(expectedKey);
-        assertWithMessage("invalid value for %s on %s", expectedKey, where)
-            .that(extraValue).isEqualTo(expectedValue);
-    }
-
-    // TODO(on master): move to helper / reuse in other places
-    private Bundle newClientState(String key, String value) {
-        final Bundle clientState = new Bundle();
-        clientState.putString(key, value);
-        return clientState;
-    }
-
-    @Test
-    public void testFillResponseFiltering() throws Exception {
-        // Set service.
-        enableService();
-        final MyAutofillCallback callback = mActivity.registerCallback();
-
-        // Prepare the authenticated response
-        final Bundle clientState = new Bundle();
-        clientState.putString("numbers", "4815162342");
-        final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
-                new CannedFillResponse.Builder().addDataset(
-                        new CannedDataset.Builder()
-                                .setField(ID_USERNAME, "dude")
-                                .setField(ID_PASSWORD, "sweet")
-                                .setId("name")
-                                .setPresentation(createPresentation("Dataset"))
-                                .build())
-                        .setExtras(clientState).build());
-
-        // Configure the service behavior
-        sReplier.addResponse(new CannedFillResponse.Builder()
-                .setAuthentication(authentication, ID_USERNAME, ID_PASSWORD)
-                .setPresentation(createPresentation("Tap to auth response"))
-                .setExtras(clientState)
-                .build());
-
-        // Set expectation for the activity
-        mActivity.expectAutoFill("dude", "sweet");
-
-        // Trigger auto-fill.
-        requestFocusOnUsername();
-
-        // Wait for onFill() before proceeding.
-        sReplier.getNextFillRequest();
-        final View username = mActivity.getUsername();
-
-        // Make sure it's showing initially...
-        callback.assertUiShownEvent(username);
-        mUiBot.assertDatasets("Tap to auth response");
-
-        // ..then type something to hide it.
-        mActivity.onUsername((v) -> v.setText("a"));
-        callback.assertUiHiddenEvent(username);
-        mUiBot.assertNoDatasets();
-
-        // Now delete the char and assert it's shown again...
-        mActivity.onUsername((v) -> v.setText(""));
-        callback.assertUiShownEvent(username);
-        mUiBot.assertDatasets("Tap to auth response");
-
-        // ...and select it this time
-        AuthenticationActivity.setResultCode(RESULT_OK);
-        mUiBot.selectDataset("Tap to auth response");
-        callback.assertUiHiddenEvent(username);
-        callback.assertUiShownEvent(username);
-        final UiObject2 picker = mUiBot.assertDatasets("Dataset");
-        mUiBot.selectDataset(picker, "Dataset");
-        callback.assertUiHiddenEvent(username);
-        mUiBot.assertNoDatasets();
-
-        // Check the results.
-        mActivity.assertAutoFilled();
-
-        final Bundle data = AuthenticationActivity.getData();
-        assertThat(data).isNotNull();
-        final String extraValue = data.getString("numbers");
-        assertThat(extraValue).isEqualTo("4815162342");
-    }
-
-    @Test
-    public void testDatasetAuthTwoFields() throws Exception {
-        datasetAuthTwoFields(false);
-    }
-
-    @Test
-    public void testDatasetAuthTwoFieldsUserCancelsFirstAttempt() throws Exception {
-        datasetAuthTwoFields(true);
-    }
-
-    private void datasetAuthTwoFields(boolean cancelFirstAttempt) throws Exception {
-        // Set service.
-        enableService();
-        final MyAutofillCallback callback = mActivity.registerCallback();
-
-        // Prepare the authenticated response
-        final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
-                new CannedDataset.Builder()
-                        .setField(ID_USERNAME, "dude")
-                        .setField(ID_PASSWORD, "sweet")
-                        .build());
-
-        // Configure the service behavior
-        sReplier.addResponse(new CannedFillResponse.Builder()
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, UNUSED_AUTOFILL_VALUE)
-                        .setField(ID_PASSWORD, UNUSED_AUTOFILL_VALUE)
-                        .setPresentation(createPresentation("Tap to auth dataset"))
-                        .setAuthentication(authentication)
-                        .build())
-                .build());
-
-        // Set expectation for the activity
-        mActivity.expectAutoFill("dude", "sweet");
-
-        // Trigger auto-fill.
-        requestFocusOnUsername();
-
-        // Wait for onFill() before proceeding.
-        sReplier.getNextFillRequest();
-        final View username = mActivity.getUsername();
-        callback.assertUiShownEvent(username);
-        mUiBot.assertDatasets("Tap to auth dataset");
-
-        // Make sure UI is show on 2nd field as well
-        final View password = mActivity.getPassword();
-        requestFocusOnPassword();
-        callback.assertUiHiddenEvent(username);
-        callback.assertUiShownEvent(password);
-        mUiBot.assertDatasets("Tap to auth dataset");
-
-        // Now tap on 1st field to show it again...
-        requestFocusOnUsername();
-        callback.assertUiHiddenEvent(password);
-        callback.assertUiShownEvent(username);
-        mUiBot.assertDatasets("Tap to auth dataset");
-
-        if (cancelFirstAttempt) {
-            // Trigger the auth dialog, but emulate cancel.
-            AuthenticationActivity.setResultCode(RESULT_CANCELED);
-            mUiBot.selectDataset("Tap to auth dataset");
-            callback.assertUiHiddenEvent(username);
-            callback.assertUiShownEvent(username);
-            mUiBot.assertDatasets("Tap to auth dataset");
-
-            // Make sure it's still shown on other fields...
-            requestFocusOnPassword();
-            callback.assertUiHiddenEvent(username);
-            callback.assertUiShownEvent(password);
-            mUiBot.assertDatasets("Tap to auth dataset");
-
-            // Tap on 1st field to show it again...
-            requestFocusOnUsername();
-            callback.assertUiHiddenEvent(password);
-            callback.assertUiShownEvent(username);
-        }
-
-        // ...and select it this time
-        AuthenticationActivity.setResultCode(RESULT_OK);
-        mUiBot.selectDataset("Tap to auth dataset");
-        callback.assertUiHiddenEvent(username);
-        mUiBot.assertNoDatasets();
-
-        // Check the results.
-        mActivity.assertAutoFilled();
-    }
-
-    @Test
-    public void testDatasetAuthTwoFieldsReplaceResponse() throws Exception {
-        // Set service.
-        enableService();
-        final MyAutofillCallback callback = mActivity.registerCallback();
-
-        // Prepare the authenticated response
-        final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
-                new CannedFillResponse.Builder().addDataset(
-                        new CannedDataset.Builder()
-                                .setField(ID_USERNAME, "dude")
-                                .setField(ID_PASSWORD, "sweet")
-                                .setPresentation(createPresentation("Dataset"))
-                                .build())
-                        .build());
-
-        // Set up the authentication response client state
-        final Bundle authentionClientState = new Bundle();
-        authentionClientState.putCharSequence("clientStateKey1", "clientStateValue1");
-
-        // Configure the service behavior
-        sReplier.addResponse(new CannedFillResponse.Builder()
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, (AutofillValue) null)
-                        .setField(ID_PASSWORD, (AutofillValue) null)
-                        .setPresentation(createPresentation("Tap to auth dataset"))
-                        .setAuthentication(authentication)
-                        .build())
-                .setExtras(authentionClientState)
-                .build());
-
-        // Set expectation for the activity
-        mActivity.expectAutoFill("dude", "sweet");
-
-        // Trigger auto-fill.
-        requestFocusOnUsername();
-
-        // Wait for onFill() before proceeding.
-        sReplier.getNextFillRequest();
-        final View username = mActivity.getUsername();
-
-        // Authenticate
-        callback.assertUiShownEvent(username);
-        mUiBot.selectDataset("Tap to auth dataset");
-        callback.assertUiHiddenEvent(username);
-
-        // Select a dataset from the new response
-        callback.assertUiShownEvent(username);
-        mUiBot.selectDataset("Dataset");
-        callback.assertUiHiddenEvent(username);
-        mUiBot.assertNoDatasets();
-
-        // Check the results.
-        mActivity.assertAutoFilled();
-
-        final Bundle data = AuthenticationActivity.getData();
-        assertThat(data).isNotNull();
-        final String extraValue = data.getString("clientStateKey1");
-        assertThat(extraValue).isEqualTo("clientStateValue1");
-    }
-
-    @Test
-    public void testDatasetAuthTwoFieldsNoValues() throws Exception {
-        // Set service.
-        enableService();
-        final MyAutofillCallback callback = mActivity.registerCallback();
-
-        // Create the authentication intent
-        final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
-                new CannedDataset.Builder()
-                        .setField(ID_USERNAME, "dude")
-                        .setField(ID_PASSWORD, "sweet")
-                        .build());
-
-        // Configure the service behavior
-        sReplier.addResponse(new CannedFillResponse.Builder()
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, (String) null)
-                        .setField(ID_PASSWORD, (String) null)
-                        .setPresentation(createPresentation("Tap to auth dataset"))
-                        .setAuthentication(authentication)
-                        .build())
-                .build());
-
-        // Set expectation for the activity
-        mActivity.expectAutoFill("dude", "sweet");
-
-        // Trigger auto-fill.
-        requestFocusOnUsername();
-
-        // Wait for onFill() before proceeding.
-        sReplier.getNextFillRequest();
-        final View username = mActivity.getUsername();
-
-        // Authenticate
-        callback.assertUiShownEvent(username);
-        mUiBot.selectDataset("Tap to auth dataset");
-        callback.assertUiHiddenEvent(username);
-        mUiBot.assertNoDatasets();
-
-        // Check the results.
-        mActivity.assertAutoFilled();
-    }
-
-    @Test
-    public void testDatasetAuthTwoDatasets() throws Exception {
-        // Set service.
-        enableService();
-        final MyAutofillCallback callback = mActivity.registerCallback();
-
-        // Create the authentication intents
-        final CannedDataset unlockedDataset = new CannedDataset.Builder()
-                .setField(ID_USERNAME, "dude")
-                .setField(ID_PASSWORD, "sweet")
-                .build();
-        final IntentSender authentication1 = AuthenticationActivity.createSender(mContext, 1,
-                unlockedDataset);
-        final IntentSender authentication2 = AuthenticationActivity.createSender(mContext, 2,
-                unlockedDataset);
-
-        // Configure the service behavior
-        sReplier.addResponse(new CannedFillResponse.Builder()
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, UNUSED_AUTOFILL_VALUE)
-                        .setField(ID_PASSWORD, UNUSED_AUTOFILL_VALUE)
-                        .setPresentation(createPresentation("Tap to auth dataset 1"))
-                        .setAuthentication(authentication1)
-                        .build())
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, UNUSED_AUTOFILL_VALUE)
-                        .setField(ID_PASSWORD, UNUSED_AUTOFILL_VALUE)
-                        .setPresentation(createPresentation("Tap to auth dataset 2"))
-                        .setAuthentication(authentication2)
-                        .build())
-                .build());
-
-        // Set expectation for the activity
-        mActivity.expectAutoFill("dude", "sweet");
-
-        // Trigger auto-fill.
-        requestFocusOnUsername();
-
-        // Wait for onFill() before proceeding.
-        sReplier.getNextFillRequest();
-        final View username = mActivity.getUsername();
-
-        // Authenticate
-        callback.assertUiShownEvent(username);
-        mUiBot.assertDatasets("Tap to auth dataset 1", "Tap to auth dataset 2");
-
-        mUiBot.selectDataset("Tap to auth dataset 1");
-        callback.assertUiHiddenEvent(username);
-        mUiBot.assertNoDatasets();
-
-        // Check the results.
-        mActivity.assertAutoFilled();
-    }
-
-    @Test
-    public void testDatasetAuthMixedSelectAuth() throws Exception {
-        datasetAuthMixedTest(true);
-    }
-
-    @Test
-    public void testDatasetAuthMixedSelectNonAuth() throws Exception {
-        datasetAuthMixedTest(false);
-    }
-
-    private void datasetAuthMixedTest(boolean selectAuth) throws Exception {
-        // Set service.
-        enableService();
-        final MyAutofillCallback callback = mActivity.registerCallback();
-
-        // Prepare the authenticated response
-        final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
-                new CannedDataset.Builder()
-                        .setField(ID_USERNAME, "dude")
-                        .setField(ID_PASSWORD, "sweet")
-                        .build());
-
-        // Configure the service behavior
-        sReplier.addResponse(new CannedFillResponse.Builder()
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, "dude")
-                        .setField(ID_PASSWORD, "sweet")
-                        .setPresentation(createPresentation("Tap to auth dataset"))
-                        .setAuthentication(authentication)
-                        .build())
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, "DUDE")
-                        .setField(ID_PASSWORD, "SWEET")
-                        .setPresentation(createPresentation("What, me auth?"))
-                        .build())
-                .build());
-
-        // Set expectation for the activity
-        if (selectAuth) {
-            mActivity.expectAutoFill("dude", "sweet");
-        } else {
-            mActivity.expectAutoFill("DUDE", "SWEET");
-        }
-
-        // Trigger auto-fill.
-        requestFocusOnUsername();
-
-        // Wait for onFill() before proceeding.
-        sReplier.getNextFillRequest();
-        final View username = mActivity.getUsername();
-
-        // Authenticate
-        callback.assertUiShownEvent(username);
-        mUiBot.assertDatasets("Tap to auth dataset", "What, me auth?");
-
-        final String chosenOne = selectAuth ? "Tap to auth dataset" : "What, me auth?";
-        mUiBot.selectDataset(chosenOne);
-        callback.assertUiHiddenEvent(username);
-        mUiBot.assertNoDatasets();
-
-        // Check the results.
-        mActivity.assertAutoFilled();
-    }
-
-    @Test
-    public void testDatasetAuthNoFiltering() throws Exception {
-        // Set service.
-        enableService();
-        final MyAutofillCallback callback = mActivity.registerCallback();
-
-        // Create the authentication intents
-        final CannedDataset unlockedDataset = new CannedDataset.Builder()
-                .setField(ID_USERNAME, "dude")
-                .setField(ID_PASSWORD, "sweet")
-                .build();
-        final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
-                unlockedDataset);
-
-        // Configure the service behavior
-        sReplier.addResponse(new CannedFillResponse.Builder()
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, UNUSED_AUTOFILL_VALUE)
-                        .setField(ID_PASSWORD, UNUSED_AUTOFILL_VALUE)
-                        .setPresentation(createPresentation("Tap to auth dataset"))
-                        .setAuthentication(authentication)
-                        .build())
-                .build());
-
-        // Set expectation for the activity
-        mActivity.expectAutoFill("dude", "sweet");
-
-        // Trigger auto-fill.
-        requestFocusOnUsername();
-
-        // Wait for onFill() before proceeding.
-        sReplier.getNextFillRequest();
-        final View username = mActivity.getUsername();
-
-        // Make sure it's showing initially...
-        callback.assertUiShownEvent(username);
-        mUiBot.assertDatasets("Tap to auth dataset");
-
-        // ..then type something to hide it.
-        mActivity.onUsername((v) -> v.setText("a"));
-        callback.assertUiHiddenEvent(username);
-        mUiBot.assertNoDatasets();
-
-        // Now delete the char and assert it's shown again...
-        mActivity.onUsername((v) -> v.setText(""));
-        callback.assertUiShownEvent(username);
-        mUiBot.assertDatasets("Tap to auth dataset");
-
-        // ...and select it this time
-        mUiBot.selectDataset("Tap to auth dataset");
-        callback.assertUiHiddenEvent(username);
-        mUiBot.assertNoDatasets();
-
-        // Check the results.
-        mActivity.assertAutoFilled();
-    }
-
-    @Test
-    public void testDatasetAuthFilteringUsingAutofillValue() throws Exception {
-        // Set service.
-        enableService();
-        final MyAutofillCallback callback = mActivity.registerCallback();
-
-        // Create the authentication intents
-        final CannedDataset unlockedDataset = new CannedDataset.Builder()
-                .setField(ID_USERNAME, "dude")
-                .setField(ID_PASSWORD, "sweet")
-                .build();
-        final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
-                unlockedDataset);
-
-        // Configure the service behavior
-        sReplier.addResponse(new CannedFillResponse.Builder()
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, "dude")
-                        .setField(ID_PASSWORD, "sweet")
-                        .setPresentation(createPresentation("DS1"))
-                        .setAuthentication(authentication)
-                        .build())
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, "DUDE,THE")
-                        .setField(ID_PASSWORD, "SWEET")
-                        .setPresentation(createPresentation("DS2"))
-                        .setAuthentication(authentication)
-                        .build())
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, "ZzBottom")
-                        .setField(ID_PASSWORD, "top")
-                        .setPresentation(createPresentation("DS3"))
-                        .setAuthentication(authentication)
-                        .build())
-                .build());
-
-        // Set expectation for the activity
-        mActivity.expectAutoFill("dude", "sweet");
-
-        // Trigger auto-fill.
-        requestFocusOnUsername();
-
-        // Wait for onFill() before proceeding.
-        sReplier.getNextFillRequest();
-        final View username = mActivity.getUsername();
-
-        // Make sure it's showing initially...
-        callback.assertUiShownEvent(username);
-        mUiBot.assertDatasets("DS1", "DS2", "DS3");
-
-        // ...then type something to hide them.
-        mActivity.onUsername((v) -> v.setText("a"));
-        callback.assertUiHiddenEvent(username);
-        mUiBot.assertNoDatasets();
-
-        // Now delete the char and assert they're shown again...
-        mActivity.onUsername((v) -> v.setText(""));
-        callback.assertUiShownEvent(username);
-        mUiBot.assertDatasets("DS1", "DS2", "DS3");
-
-        // ...then filter for 2
-        mActivity.onUsername((v) -> v.setText("d"));
-        mUiBot.assertDatasets("DS1", "DS2");
-
-        // ...up to 1
-        mActivity.onUsername((v) -> v.setText("du"));
-        mUiBot.assertDatasets("DS1", "DS2");
-        mActivity.onUsername((v) -> v.setText("dud"));
-        mUiBot.assertDatasets("DS1", "DS2");
-        mActivity.onUsername((v) -> v.setText("dude"));
-        mUiBot.assertDatasets("DS1", "DS2");
-        mActivity.onUsername((v) -> v.setText("dude,"));
-        mUiBot.assertDatasets("DS2");
-
-        // Now delete the char and assert 2 are shown again...
-        mActivity.onUsername((v) -> v.setText("dude"));
-        final UiObject2 picker = mUiBot.assertDatasets("DS1", "DS2");
-
-        // ...and select it this time
-        mUiBot.selectDataset(picker, "DS1");
-        callback.assertUiHiddenEvent(username);
-        mUiBot.assertNoDatasets();
-
-        // Check the results.
-        mActivity.assertAutoFilled();
-    }
-
-    @Test
-    public void testDatasetAuthFilteringUsingRegex() throws Exception {
-        // Set service.
-        enableService();
-        final MyAutofillCallback callback = mActivity.registerCallback();
-
-        // Create the authentication intents
-        final CannedDataset unlockedDataset = new CannedDataset.Builder()
-                .setField(ID_USERNAME, "dude")
-                .setField(ID_PASSWORD, "sweet")
-                .build();
-        final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
-                unlockedDataset);
-
-        // Configure the service behavior
-
-        final Pattern min2Chars = Pattern.compile(".{2,}");
-        sReplier.addResponse(new CannedFillResponse.Builder()
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, UNUSED_AUTOFILL_VALUE, min2Chars)
-                        .setField(ID_PASSWORD, UNUSED_AUTOFILL_VALUE)
-                        .setPresentation(createPresentation("Tap to auth dataset"))
-                        .setAuthentication(authentication)
-                        .build())
-                .build());
-
-        // Set expectation for the activity
-        mActivity.expectAutoFill("dude", "sweet");
-
-        // Trigger auto-fill.
-        requestFocusOnUsername();
-
-        // Wait for onFill() before proceeding.
-        sReplier.getNextFillRequest();
-        final View username = mActivity.getUsername();
-
-        // Make sure it's showing initially...
-        callback.assertUiShownEvent(username);
-        mUiBot.assertDatasets("Tap to auth dataset");
-
-        // ...then type something to hide it.
-        mActivity.onUsername((v) -> v.setText("a"));
-        callback.assertUiHiddenEvent(username);
-        mUiBot.assertNoDatasets();
-
-        // ...now type something again to show it, as the input will have 2 chars.
-        mActivity.onUsername((v) -> v.setText("aa"));
-        callback.assertUiShownEvent(username);
-        mUiBot.assertDatasets("Tap to auth dataset");
-
-        // Delete the char and assert it's not shown again...
-        mActivity.onUsername((v) -> v.setText("a"));
-        callback.assertUiHiddenEvent(username);
-        mUiBot.assertNoDatasets();
-
-        // ...then type something again to show it, as the input will have 2 chars.
-        mActivity.onUsername((v) -> v.setText("aa"));
-        callback.assertUiShownEvent(username);
-
-        // ...and select it this time
-        mUiBot.selectDataset("Tap to auth dataset");
-        callback.assertUiHiddenEvent(username);
-        mUiBot.assertNoDatasets();
-
-        // Check the results.
-        mActivity.assertAutoFilled();
-    }
-
-    @Test
-    public void testDatasetAuthMixedFilteringSelectAuth() throws Exception {
-        datasetAuthMixedFilteringTest(true);
-    }
-
-    @Test
-    public void testDatasetAuthMixedFilteringSelectNonAuth() throws Exception {
-        datasetAuthMixedFilteringTest(false);
-    }
-
-    private void datasetAuthMixedFilteringTest(boolean selectAuth) throws Exception {
-        // Set service.
-        enableService();
-        final MyAutofillCallback callback = mActivity.registerCallback();
-
-        // Create the authentication intents
-        final CannedDataset unlockedDataset = new CannedDataset.Builder()
-                .setField(ID_USERNAME, "DUDE")
-                .setField(ID_PASSWORD, "SWEET")
-                .build();
-        final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
-                unlockedDataset);
-
-        // Configure the service behavior
-        sReplier.addResponse(new CannedFillResponse.Builder()
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, UNUSED_AUTOFILL_VALUE)
-                        .setField(ID_PASSWORD, UNUSED_AUTOFILL_VALUE)
-                        .setPresentation(createPresentation("Tap to auth dataset"))
-                        .setAuthentication(authentication)
-                        .build())
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, "dude")
-                        .setField(ID_PASSWORD, "sweet")
-                        .setPresentation(createPresentation("What, me auth?"))
-                        .build())
-                .build());
-
-        // Set expectation for the activity
-        if (selectAuth) {
-            mActivity.expectAutoFill("DUDE", "SWEET");
-        } else {
-            mActivity.expectAutoFill("dude", "sweet");
-        }
-
-        // Trigger auto-fill.
-        requestFocusOnUsername();
-
-        // Wait for onFill() before proceeding.
-        sReplier.getNextFillRequest();
-        final View username = mActivity.getUsername();
-
-        // Make sure it's showing initially...
-        callback.assertUiShownEvent(username);
-        mUiBot.assertDatasets("Tap to auth dataset", "What, me auth?");
-
-        // Filter the auth dataset.
-        mActivity.onUsername((v) -> v.setText("d"));
-        mUiBot.assertDatasets("What, me auth?");
-
-        // Filter all.
-        mActivity.onUsername((v) -> v.setText("dw"));
-        callback.assertUiHiddenEvent(username);
-        mUiBot.assertNoDatasets();
-
-        // Now delete the char and assert the non-auth is shown again.
-        mActivity.onUsername((v) -> v.setText("d"));
-        callback.assertUiShownEvent(username);
-        mUiBot.assertDatasets("What, me auth?");
-
-        // Delete again and assert all dataset are shown.
-        mActivity.onUsername((v) -> v.setText(""));
-        mUiBot.assertDatasets("Tap to auth dataset", "What, me auth?");
-
-        // ...and select it this time
-        final String chosenOne = selectAuth ? "Tap to auth dataset" : "What, me auth?";
-        mUiBot.selectDataset(chosenOne);
-        callback.assertUiHiddenEvent(username);
-        mUiBot.assertNoDatasets();
-
-        // Check the results.
-        mActivity.assertAutoFilled();
-    }
-
-    @Test
-    public void testDatasetAuthClientStateSetOnIntentOnly() throws Exception {
-        fillDatasetAuthWithClientState(ClientStateLocation.INTENT_ONLY);
-    }
-
-    @Test
-    public void testDatasetAuthClientStateSetOnFillResponseOnly() throws Exception {
-        fillDatasetAuthWithClientState(ClientStateLocation.FILL_RESPONSE_ONLY);
-    }
-
-    @Test
-    public void testDatasetAuthClientStateSetOnIntentAndFillResponse() throws Exception {
-        fillDatasetAuthWithClientState(ClientStateLocation.BOTH);
-    }
-
-    private void fillDatasetAuthWithClientState(ClientStateLocation where) throws Exception {
-        // Set service.
-        enableService();
-
-        // Prepare the authenticated response
-        final CannedDataset dataset = new CannedDataset.Builder()
-                .setField(ID_USERNAME, "dude")
-                .setField(ID_PASSWORD, "sweet")
-                .build();
-        final IntentSender authentication = where == ClientStateLocation.FILL_RESPONSE_ONLY
-                ? AuthenticationActivity.createSender(mContext, 1,
-                        dataset)
-                : AuthenticationActivity.createSender(mContext, 1,
-                        dataset, newClientState("CSI", "FromIntent"));
-
-        // Configure the service behavior
-        sReplier.addResponse(new CannedFillResponse.Builder()
-                .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
-                .setExtras(newClientState("CSI", "FromResponse"))
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, UNUSED_AUTOFILL_VALUE)
-                        .setField(ID_PASSWORD, UNUSED_AUTOFILL_VALUE)
-                        .setPresentation(createPresentation("Tap to auth dataset"))
-                        .setAuthentication(authentication)
-                        .build())
-                .build());
-
-        // Set expectation for the activity
-        mActivity.expectAutoFill("dude", "sweet");
-
-        // Trigger auto-fill.
-        requestFocusOnUsername();
-        sReplier.getNextFillRequest();
-
-        // Tap authentication request.
-        mUiBot.selectDataset("Tap to auth dataset");
-
-        // Check the results.
-        mActivity.assertAutoFilled();
-
-        // Now trigger save.
-        mActivity.onUsername((v) -> v.setText("malkovich"));
-        mActivity.onPassword((v) -> v.setText("malkovich"));
-        final String expectedMessage = getWelcomeMessage("malkovich");
-        final String actualMessage = mActivity.tapLogin();
-        assertWithMessage("Wrong welcome msg").that(actualMessage).isEqualTo(expectedMessage);
-        mUiBot.saveForAutofill(true, SAVE_DATA_TYPE_PASSWORD);
-
-        // Assert client state on authentication activity.
-        assertClientState("auth activity", AuthenticationActivity.getData(), "CSI", "FromResponse");
-
-        // Assert client state on save request.
-        final SaveRequest saveRequest = sReplier.getNextSaveRequest();
-        final String expectedValue = where == ClientStateLocation.FILL_RESPONSE_ONLY
-                ? "FromResponse" : "FromIntent";
-        assertClientState("on save", saveRequest.data, "CSI", expectedValue);
-    }
-
-    @Test
     public void testDisableSelf() throws Exception {
         enableService();
 
diff --git a/tests/autofillservice/src/android/autofillservice/cts/MutableAutofillIdTest.java b/tests/autofillservice/src/android/autofillservice/cts/MutableAutofillIdTest.java
new file mode 100644
index 0000000..3c9969f
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/MutableAutofillIdTest.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.autofillservice.cts;
+
+import static android.autofillservice.cts.GridActivity.ID_L1C1;
+import static android.autofillservice.cts.GridActivity.ID_L1C2;
+import static android.autofillservice.cts.Helper.assertTextIsSanitized;
+import static android.autofillservice.cts.Helper.findNodeByAutofillId;
+import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_GENERIC;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import android.app.assist.AssistStructure;
+import android.app.assist.AssistStructure.ViewNode;
+import android.autofillservice.cts.CannedFillResponse.CannedDataset;
+import android.autofillservice.cts.GridActivity.FillExpectation;
+import android.autofillservice.cts.InstrumentedAutoFillService.FillRequest;
+import android.autofillservice.cts.InstrumentedAutoFillService.SaveRequest;
+import android.service.autofill.FillContext;
+import android.support.test.uiautomator.UiObject2;
+import android.util.Log;
+import android.view.autofill.AutofillId;
+import android.widget.EditText;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.util.List;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Test cases for the cases where the autofill id of a view is changed by the app.
+ */
+public class MutableAutofillIdTest extends AutoFillServiceTestCase {
+
+    private static final String TAG = "MutableAutofillIdTest";
+
+    @Rule
+    public final AutofillActivityTestRule<GridActivity> mActivityRule =
+            new AutofillActivityTestRule<GridActivity>(GridActivity.class);
+
+    private GridActivity mActivity;
+
+    @Before
+    public void setActivity() {
+        mActivity = mActivityRule.getActivity();
+    }
+
+    @Test
+    public void testDatasetPickerIsNotShownAfterViewIsSwappedOut() throws Exception {
+        enableService();
+
+        final EditText field1 = mActivity.getCell(1, 1);
+        final AutofillId oldIdField1 = field1.getAutofillId();
+        final EditText field2 = mActivity.getCell(1, 2);
+        final AutofillId idField2 = field2.getAutofillId();
+
+        // Prepare response
+        final CannedFillResponse response1 = new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setField(oldIdField1, "l1c1", createPresentation("l1c1"))
+                        .setField(idField2, "l1c2", createPresentation("l1c2"))
+                        .build())
+                .build();
+        sReplier.addResponse(response1);
+
+        // Trigger autofill on 1st view.
+        focusCell(1, 1);
+        final FillRequest fillRequest1 = sReplier.getNextFillRequest();
+        final ViewNode node1Request1 = assertTextIsSanitized(fillRequest1.structure, ID_L1C1);
+        assertThat(node1Request1.getAutofillId()).isEqualTo(oldIdField1);
+        mUiBot.assertDatasets("l1c1");
+
+        // Make sure 2nd field shows picker
+        focusCell(1, 2);
+        mUiBot.assertDatasets("l1c2");
+
+        // Now change id of 1st view
+        final AutofillId newIdField1 = mActivity.getAutofillManager().getNextAutofillId();
+
+        // TODO: move to an autofill unit test class for View
+        // Make sure view has to be detached first
+        assertThrows(IllegalStateException.class, () -> field1.setAutofillId(newIdField1));
+
+        // Change id
+        mActivity.removeCell(1, 1);
+
+        // TODO: move to an autofill unit test class for View
+        // Also assert it does not accept virtual ids
+        assertThrows(IllegalStateException.class,
+                () -> field1.setAutofillId(new AutofillId(newIdField1, 42)));
+
+        field1.setAutofillId(newIdField1);
+        assertThat(field1.getAutofillId()).isEqualTo(newIdField1);
+
+        Log.d(TAG, "Changed id of " + ID_L1C1 + " from " + oldIdField1 + " to " + newIdField1);
+
+        // Trigger another request because 1st view has a different id. Service will ignore it now.
+        final CannedFillResponse response2 = new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setField(idField2, "l1c2", createPresentation("l1c2"))
+                        .build())
+                .build();
+        sReplier.addResponse(response2);
+
+        // Re-add the cell before triggering autofill on it
+        mActivity.addCell(1, 1, field1);
+        mActivity.focusCell(1, 1);
+
+        final FillRequest fillRequest2 = sReplier.getNextFillRequest();
+        final ViewNode node1Request2 = assertTextIsSanitized(fillRequest2.structure, ID_L1C1);
+        // Make sure node has new id.
+        assertThat(node1Request2.getAutofillId()).isEqualTo(newIdField1);
+        mUiBot.assertNoDatasets();
+
+        // Make sure 2nd field shows picker
+        focusCell(1, 2);
+        final UiObject2 datasetPicker = mUiBot.assertDatasets("l1c2");
+
+        // Now autofill
+        final FillExpectation expectation = mActivity.expectAutofill()
+                .onCell(1, 2, "l1c2");
+        mUiBot.selectDataset(datasetPicker, "l1c2");
+        expectation.assertAutoFilled();
+    }
+
+    @Test
+    public void testSave_serviceIgnoresNewId() throws Exception {
+        saveWhenIdChanged(true);
+    }
+
+    @Test
+    public void testSave_serviceExpectingOldId() throws Exception {
+        saveWhenIdChanged(false);
+    }
+
+    private void saveWhenIdChanged(boolean serviceIgnoresNewId) throws Exception {
+        enableService();
+
+        final EditText field1 = mActivity.getCell(1, 1);
+        final AutofillId oldIdField1 = field1.getAutofillId();
+        final EditText field2 = mActivity.getCell(1, 2);
+        final AutofillId idField2 = field2.getAutofillId();
+
+        // Prepare response
+        final CannedFillResponse response1 = new CannedFillResponse.Builder()
+                .setRequiredSavableAutofillIds(SAVE_DATA_TYPE_GENERIC, oldIdField1, idField2)
+                .build();
+        sReplier.addResponse(response1);
+
+        // Trigger autofill on 1st view.
+        mActivity.focusCell(1, 1); // No window change because it's not showing dataset picker.
+        final FillRequest fillRequest1 = sReplier.getNextFillRequest();
+        final ViewNode node1Request1 = assertTextIsSanitized(fillRequest1.structure, ID_L1C1);
+        assertThat(node1Request1.getAutofillId()).isEqualTo(oldIdField1);
+        mUiBot.assertNoDatasets();
+
+        // Make sure 2nd field doesn't trigger a new request
+        mActivity.focusCell(1, 2); // No window change because it's not showing dataset picker.
+        mUiBot.assertNoDatasets();
+
+        // Now change 1st view value...
+        mActivity.setText(1, 1, "OLD");
+        // ...and its id
+        final AutofillId newIdField1 = mActivity.getAutofillManager().getNextAutofillId();
+        mActivity.removeCell(1, 1);
+        field1.setAutofillId(newIdField1);
+        assertThat(field1.getAutofillId()).isEqualTo(newIdField1);
+        Log.d(TAG, "Changed id of " + ID_L1C1 + " from " + oldIdField1 + " to " + newIdField1);
+
+        // Trigger another request because 1st view has a different id...
+        final CannedFillResponse.Builder response2 = new CannedFillResponse.Builder();
+        if (serviceIgnoresNewId) {
+            // ... and service will ignore it now.
+            response2.setRequiredSavableAutofillIds(SAVE_DATA_TYPE_GENERIC, idField2);
+        } else {
+            // ..but service is still expecting the old id.
+            response2.setRequiredSavableAutofillIds(SAVE_DATA_TYPE_GENERIC, oldIdField1, idField2);
+        }
+        sReplier.addResponse(response2.build());
+
+        mActivity.addCell(1, 1, field1);
+        mActivity.focusCell(1, 1); // No window change because it's not showing dataset picker.
+        final FillRequest fillRequest2 = sReplier.getNextFillRequest();
+        final ViewNode node1Request2 = assertTextIsSanitized(fillRequest2.structure, ID_L1C1);
+        // Make sure node has new id.
+        assertThat(node1Request2.getAutofillId()).isEqualTo(newIdField1);
+        mUiBot.assertNoDatasets();
+
+        // Now triggers save
+        mActivity.setText(1, 1, "NEW");
+        mActivity.setText(1, 2, "NOD2");
+        mActivity.save();
+
+        mUiBot.saveForAutofill(true, SAVE_DATA_TYPE_GENERIC);
+        final SaveRequest saveRequest = sReplier.getNextSaveRequest();
+        final List<FillContext> contexts = saveRequest.contexts;
+        assertThat(contexts).hasSize(2);
+
+        // Assert 1st context
+        final AssistStructure structure1 = contexts.get(0).getStructure();
+
+        final ViewNode oldNode1Context1 = findNodeByAutofillId(structure1, oldIdField1);
+        assertThat(oldNode1Context1).isNotNull();
+        assertThat(oldNode1Context1.getIdEntry()).isEqualTo(ID_L1C1);
+        assertThat(oldNode1Context1.getText().toString()).isEqualTo("OLD");
+
+        final ViewNode newNode1Context1 = findNodeByAutofillId(structure1, newIdField1);
+        assertThat(newNode1Context1).isNull();
+
+        final ViewNode node2Context1 = findNodeByAutofillId(structure1, idField2);
+        assertThat(node2Context1).isNotNull();
+        assertThat(node2Context1.getIdEntry()).isEqualTo(ID_L1C2);
+        assertThat(node2Context1.getText().toString()).isEqualTo("NOD2");
+
+        // Assert 2nd context
+        final AssistStructure structure2 = contexts.get(1).getStructure();
+
+        final ViewNode oldNode1Context2 = findNodeByAutofillId(structure2, oldIdField1);
+        assertThat(oldNode1Context2).isNull();
+
+        final ViewNode newNode1Context2 = findNodeByAutofillId(structure2, newIdField1);
+        assertThat(newNode1Context2).isNotNull();
+        assertThat(newNode1Context2.getIdEntry()).isEqualTo(ID_L1C1);
+        assertThat(newNode1Context2.getText().toString()).isEqualTo("NEW");
+
+        final ViewNode node2Context2 = findNodeByAutofillId(structure2, idField2);
+        assertThat(node2Context2).isNotNull();
+        assertThat(node2Context2.getIdEntry()).isEqualTo(ID_L1C2);
+        assertThat(node2Context2.getText().toString()).isEqualTo("NOD2");
+    }
+
+    /**
+     * Focus to a cell and expect window event
+     */
+    void focusCell(int row, int column) throws TimeoutException {
+        mUiBot.waitForWindowChange(() -> mActivity.focusCell(row, column),
+                Timeouts.UI_TIMEOUT.getMaxValue());
+    }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/RetryRule.java b/tests/autofillservice/src/android/autofillservice/cts/RetryRule.java
index 2de94f8..0eda6be 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/RetryRule.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/RetryRule.java
@@ -50,19 +50,29 @@
                 for (int i = 1; i <= mMaxAttempts; i++) {
                     try {
                         base.evaluate();
+                        if (i == 1) {
+                            Log.v(TAG, "Good News, Everyone! " + name + " passed right away");
+                        } else {
+                            Log.d(TAG,
+                                    "Better late than never: " + name + "passed at attempt #" + i);
+                        }
                         return;
                     } catch (RetryableException e) {
                         final Timeout timeout = e.getTimeout();
                         if (timeout != null) {
+                            long before = timeout.ms();
                             timeout.increase();
+                            Log.d(TAG, "Increased " + timeout.getName() + " from " + before + "ms "
+                                    + " to " + timeout.ms() + "ms");
                         }
                         caught = e;
                     } catch (StaleObjectException e) {
                         caught = e;
                     }
-                    Log.w(TAG, name + ": attempt " + i + " failed: " + caught);
+                    Log.w(TAG, "Arrrr! " + name + " failed at attempt " + i + "/" + mMaxAttempts
+                            + ": " + caught);
                 }
-                Log.e(TAG, name + ": giving up after " + mMaxAttempts + " attempts");
+                Log.e(TAG, "D'OH! " + name + ": giving up after " + mMaxAttempts + " attempts");
                 throw caught;
             }
         };
diff --git a/tests/autofillservice/src/android/autofillservice/cts/Timeouts.java b/tests/autofillservice/src/android/autofillservice/cts/Timeouts.java
index 81cf81e..81265e3 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/Timeouts.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/Timeouts.java
@@ -24,7 +24,7 @@
     /**
      * Timeout until framework binds / unbinds from service.
      */
-    static final Timeout CONNECTION_TIMEOUT = new Timeout("CONNECTION_TIMEOUT", 1000, 2F, 2000);
+    static final Timeout CONNECTION_TIMEOUT = new Timeout("CONNECTION_TIMEOUT", 1000, 2F, 10000);
 
     /**
      * Timeout until framework unbinds from a service.
@@ -39,17 +39,23 @@
     /**
      * Timeout for expected autofill requests.
      */
-    static final Timeout FILL_TIMEOUT = new Timeout("FILL_TIMEOUT", 1000, 2F, 2000);
+    static final Timeout FILL_TIMEOUT = new Timeout("FILL_TIMEOUT", 500, 2F, 10000);
 
     /**
      * Timeout for expected save requests.
      */
-    static final Timeout SAVE_TIMEOUT = new Timeout("SAVE_TIMEOUT", 2000, 3F, 5000);
+    static final Timeout SAVE_TIMEOUT = new Timeout("SAVE_TIMEOUT", 1000, 2F, 10000);
+
+    /**
+     * Timeout used when save is not expected to be shown - test will sleep for that amount of time
+     * as there is no callback that be received to assert it's not shown.
+     */
+    static final long SAVE_NOT_SHOWN_NAPTIME_MS = 5000;
 
     /**
      * Timeout for UI operations. Typically used by {@link UiBot}.
      */
-    static final Timeout UI_TIMEOUT = new Timeout("UI_TIMEOUT", 1000, 2F, 2000);
+    static final Timeout UI_TIMEOUT = new Timeout("UI_TIMEOUT", 500, 2F, 10000);
 
     /**
      * Timeout for webview operations. Typically used by {@link UiBot}.
diff --git a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
index bf64dc0..47720d1 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
@@ -16,6 +16,7 @@
 
 package android.autofillservice.cts;
 
+import static android.autofillservice.cts.Timeouts.SAVE_NOT_SHOWN_NAPTIME_MS;
 import static android.autofillservice.cts.Timeouts.SAVE_TIMEOUT;
 import static android.autofillservice.cts.Timeouts.UI_DATASET_PICKER_TIMEOUT;
 import static android.autofillservice.cts.Timeouts.UI_RECENTS_SWITCH_TIMEOUT;
@@ -399,8 +400,7 @@
      * Asserts the save snackbar is not showing and returns it.
      */
     void assertSaveNotShowing(int type) throws Exception {
-        // TODO: need a better mechanism to wait undefinitely than using getMaxValue()
-        assertNeverShown("save UI for type " + type, SAVE_UI_SELECTOR, SAVE_TIMEOUT.getMaxValue());
+        assertNeverShown("save UI for type " + type, SAVE_UI_SELECTOR, SAVE_NOT_SHOWN_NAPTIME_MS);
     }
 
     private String getSaveTypeString(int type) {
diff --git a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivity.java b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivity.java
index 9e8bf57..888201a 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivity.java
@@ -28,6 +28,7 @@
 import android.os.Bundle;
 import android.util.Log;
 import android.view.autofill.AutofillId;
+import android.widget.EditText;
 
 /**
  * A custom activity that uses {@link Canvas} to draw the following fields:
@@ -44,6 +45,7 @@
 
     static final String BLANK_VALUE = "        ";
 
+    EditText mUrlBar;
     VirtualContainerView mCustomView;
 
     Line mUsername;
@@ -59,8 +61,10 @@
 
         setContentView(R.layout.virtual_container_activity);
 
+        mUrlBar = findViewById(R.id.my_url_bar);
         mCustomView = findViewById(R.id.virtual_container_view);
 
+        mUrlBar.setText("ftp://dev.null/4/8/15/16/23/42");
         mUsername = mCustomView.addLine(ID_USERNAME_LABEL, "Username", ID_USERNAME, BLANK_VALUE);
         mPassword = mCustomView.addLine(ID_PASSWORD_LABEL, "Password", ID_PASSWORD, BLANK_VALUE);
 
diff --git a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityCompatModeTest.java b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityCompatModeTest.java
index b6fb279..54ac252 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityCompatModeTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityCompatModeTest.java
@@ -15,6 +15,7 @@
  */
 package android.autofillservice.cts;
 
+import static android.autofillservice.cts.Helper.assertTextIsSanitized;
 import static android.autofillservice.cts.Helper.getContext;
 import static android.autofillservice.cts.Helper.hasAutofillFeature;
 import static android.autofillservice.cts.InstrumentedAutoFillServiceCompatMode.SERVICE_NAME;
@@ -22,12 +23,14 @@
 import static android.autofillservice.cts.common.SettingsHelper.NAMESPACE_GLOBAL;
 import static android.provider.Settings.Global.AUTOFILL_COMPAT_ALLOWED_PACKAGES;
 
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.assist.AssistStructure.ViewNode;
 import android.autofillservice.cts.common.SettingsStateChangerRule;
 import android.content.Context;
 import android.support.test.InstrumentationRegistry;
 
 import org.junit.After;
-import org.junit.Before;
 import org.junit.ClassRule;
 
 /**
@@ -76,8 +79,15 @@
         InstrumentedAutoFillServiceCompatMode.setIgnoreUnexpectedRequests(true);
     }
 
+    @Override
+    protected void assertUrlBarIsSanitized(ViewNode urlBar) {
+        assertTextIsSanitized(urlBar);
+        assertThat(urlBar.getWebDomain()).isEqualTo("dev.null");
+        assertThat(urlBar.getWebScheme()).isEqualTo("ftp");
+    }
+
     // TODO(b/72811561): currently only one test pass at time; remove once they all pass
-    @Before
+    @After
     public void thereCanBeOnlyOne() {
         sRanAlready = true;
     }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java
index 72d8d17..ef9f8f0 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java
@@ -25,6 +25,7 @@
 import static android.autofillservice.cts.Helper.assertTextOnly;
 import static android.autofillservice.cts.Helper.dumpStructure;
 import static android.autofillservice.cts.Helper.findNodeByResourceId;
+import static android.autofillservice.cts.VirtualContainerView.ID_URL_BAR;
 import static android.autofillservice.cts.VirtualContainerView.LABEL_CLASS;
 import static android.autofillservice.cts.VirtualContainerView.TEXT_CLASS;
 import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_PASSWORD;
@@ -37,7 +38,6 @@
 import android.autofillservice.cts.CannedFillResponse.CannedDataset;
 import android.autofillservice.cts.InstrumentedAutoFillService.FillRequest;
 import android.autofillservice.cts.InstrumentedAutoFillService.SaveRequest;
-import android.autofillservice.cts.VirtualContainerActivityTest.CommitType;
 import android.autofillservice.cts.VirtualContainerView.Line;
 import android.content.ComponentName;
 import android.graphics.Rect;
@@ -162,11 +162,13 @@
 
         // Make sure input was sanitized.
         final FillRequest request = sReplier.getNextFillRequest();
+        final ViewNode urlBar = findNodeByResourceId(request.structure, ID_URL_BAR);
         final ViewNode usernameLabel = findNodeByResourceId(request.structure, ID_USERNAME_LABEL);
         final ViewNode username = findNodeByResourceId(request.structure, ID_USERNAME);
         final ViewNode passwordLabel = findNodeByResourceId(request.structure, ID_PASSWORD_LABEL);
         final ViewNode password = findNodeByResourceId(request.structure, ID_PASSWORD);
 
+        assertUrlBarIsSanitized(urlBar);
         assertTextIsSanitized(username);
         assertTextIsSanitized(password);
         assertLabel(usernameLabel, "Username");
@@ -604,6 +606,12 @@
         }
     }
 
+    protected void assertUrlBarIsSanitized(ViewNode urlBar) {
+        assertTextIsSanitized(urlBar);
+        assertThat(urlBar.getWebDomain()).isNull();
+        assertThat(urlBar.getWebScheme()).isNull();
+    }
+
     // TODO(b/72811561): currently only one test pass at time
     protected static boolean sRanAlready = false;
 }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java
index d1e4749..f36328c 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java
@@ -61,6 +61,7 @@
 
     static final String LABEL_CLASS = "my.readonly.view";
     static final String TEXT_CLASS = "my.editable.view";
+    static final String ID_URL_BAR = "my_url_bar";
 
     private final ArrayList<Line> mLines = new ArrayList<>();
     private final SparseArray<Item> mItems = new SparseArray<>();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/Visitor.java b/tests/autofillservice/src/android/autofillservice/cts/Visitor.java
index 96ee370..a8e0314 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/Visitor.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/Visitor.java
@@ -28,7 +28,7 @@
  * }
  * </code></pre>
  */
-interface Visitor<T>{
+interface Visitor<T> {
 
     void visit(T view);
 }
\ No newline at end of file
diff --git a/tests/backup/app/fullbackup/Android.mk b/tests/backup/app/fullbackup/Android.mk
index ac53252..68bf8f1 100644
--- a/tests/backup/app/fullbackup/Android.mk
+++ b/tests/backup/app/fullbackup/Android.mk
@@ -23,6 +23,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
 
 LOCAL_PACKAGE_NAME := CtsFullBackupApp
+LOCAL_SDK_VERSION := current
 
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
diff --git a/tests/backup/app/keyvalue/Android.mk b/tests/backup/app/keyvalue/Android.mk
index 3c36f50..f9034db0 100644
--- a/tests/backup/app/keyvalue/Android.mk
+++ b/tests/backup/app/keyvalue/Android.mk
@@ -23,6 +23,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
 
 LOCAL_PACKAGE_NAME := CtsKeyValueBackupApp
+LOCAL_SDK_VERSION := current
 
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
diff --git a/tests/camera/src/android/hardware/camera2/cts/CaptureResultTest.java b/tests/camera/src/android/hardware/camera2/cts/CaptureResultTest.java
index 1f6737f..d653f25 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CaptureResultTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CaptureResultTest.java
@@ -576,9 +576,7 @@
 
         if (!staticInfo.isOisDataModeSupported()) {
             waiverKeys.add(CaptureResult.STATISTICS_OIS_DATA_MODE);
-            waiverKeys.add(CaptureResult.STATISTICS_OIS_TIMESTAMPS);
-            waiverKeys.add(CaptureResult.STATISTICS_OIS_X_SHIFTS);
-            waiverKeys.add(CaptureResult.STATISTICS_OIS_Y_SHIFTS);
+            waiverKeys.add(CaptureResult.STATISTICS_OIS_SAMPLES);
         }
 
         if (staticInfo.isHardwareLevelAtLeastFull()) {
@@ -861,9 +859,7 @@
         resultKeys.add(CaptureResult.STATISTICS_HOT_PIXEL_MAP);
         resultKeys.add(CaptureResult.STATISTICS_LENS_SHADING_MAP_MODE);
         resultKeys.add(CaptureResult.STATISTICS_OIS_DATA_MODE);
-        resultKeys.add(CaptureResult.STATISTICS_OIS_TIMESTAMPS);
-        resultKeys.add(CaptureResult.STATISTICS_OIS_X_SHIFTS);
-        resultKeys.add(CaptureResult.STATISTICS_OIS_Y_SHIFTS);
+        resultKeys.add(CaptureResult.STATISTICS_OIS_SAMPLES);
         resultKeys.add(CaptureResult.TONEMAP_CURVE);
         resultKeys.add(CaptureResult.TONEMAP_MODE);
         resultKeys.add(CaptureResult.TONEMAP_GAMMA);
diff --git a/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java b/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
index 1d5e911..4361a56 100644
--- a/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
@@ -33,6 +33,7 @@
 import android.hardware.camera2.cts.helpers.StaticMetadata;
 import android.hardware.camera2.cts.testcases.Camera2AndroidTestCase;
 import android.hardware.camera2.params.InputConfiguration;
+import android.hardware.camera2.params.OisSample;
 import android.hardware.camera2.params.OutputConfiguration;
 import android.hardware.camera2.params.StreamConfigurationMap;
 import android.media.CamcorderProfile;
@@ -1051,33 +1052,21 @@
                         TotalCaptureResult result =
                             previewListener.getTotalCaptureResult(CAPTURE_TIMEOUT);
 
-                        long[] oisTimestamps = result.get(CaptureResult.STATISTICS_OIS_TIMESTAMPS);
-                        float[] oisXShifts = result.get(CaptureResult.STATISTICS_OIS_X_SHIFTS);
-                        float[] oisYShifts = result.get(CaptureResult.STATISTICS_OIS_Y_SHIFTS);
+                        OisSample[] oisSamples = result.get(CaptureResult.STATISTICS_OIS_SAMPLES);
 
                         if (oisMode == CameraCharacteristics.STATISTICS_OIS_DATA_MODE_OFF) {
                             mCollector.expectKeyValueEquals(result,
                                     CaptureResult.STATISTICS_OIS_DATA_MODE,
                                     CaptureResult.STATISTICS_OIS_DATA_MODE_OFF);
-                            mCollector.expectTrue("OIS timestamps reported in OIS_DATA_MODE_OFF",
-                                    oisTimestamps == null || oisTimestamps.length == 0);
-                            mCollector.expectTrue("OIS x shifts reported in OIS_DATA_MODE_OFF",
-                                    oisXShifts == null || oisXShifts.length == 0);
-                            mCollector.expectTrue("OIS y shifts reported in OIS_DATA_MODE_OFF",
-                                    oisYShifts == null || oisYShifts.length == 0);
+                            mCollector.expectTrue("OIS samples reported in OIS_DATA_MODE_OFF",
+                                    oisSamples == null || oisSamples.length == 0);
 
                         } else if (oisMode == CameraCharacteristics.STATISTICS_OIS_DATA_MODE_ON) {
                             mCollector.expectKeyValueEquals(result,
                                     CaptureResult.STATISTICS_OIS_DATA_MODE,
                                     CaptureResult.STATISTICS_OIS_DATA_MODE_ON);
-                            mCollector.expectTrue("OIS timestamps not reported in OIS_DATA_MODE_ON",
-                                    oisTimestamps != null && oisTimestamps.length != 0);
-                            mCollector.expectTrue(
-                                    "Number of x shifts doesn't match number of OIS timetamps.",
-                                    oisXShifts != null && oisXShifts.length == oisTimestamps.length);
-                            mCollector.expectTrue(
-                                    "Number of y shifts doesn't match number of OIS timetamps.",
-                                    oisYShifts != null && oisYShifts.length == oisTimestamps.length);
+                            mCollector.expectTrue("OIS samples not reported in OIS_DATA_MODE_ON",
+                                    oisSamples != null && oisSamples.length != 0);
                         } else {
                             mCollector.addMessage(String.format("Invalid OIS mode: %d", oisMode));
                         }
diff --git a/tests/framework/base/activitymanager/Android.mk b/tests/framework/base/activitymanager/Android.mk
index c502843..25cfd6b 100644
--- a/tests/framework/base/activitymanager/Android.mk
+++ b/tests/framework/base/activitymanager/Android.mk
@@ -20,12 +20,14 @@
 
 # Must match the package name in CtsTestCaseList.mk
 LOCAL_PACKAGE_NAME := CtsActivityManagerDeviceTestCases
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_SRC_FILES := \
     $(call all-java-files-under, src) \
     $(call all-named-files-under,Components.java, app) \
     $(call all-named-files-under,Components.java, app27) \
     $(call all-named-files-under,Components.java, appDebuggable) \
+    $(call all-named-files-under,Components.java, appDeprecatedSdk) \
     $(call all-named-files-under,Components.java, appDisplaySize) \
     $(call all-named-files-under,Components.java, appSecondUid) \
     $(call all-named-files-under,Components.java, appThirdUid) \
diff --git a/tests/framework/base/activitymanager/AndroidManifest.xml b/tests/framework/base/activitymanager/AndroidManifest.xml
index 7afc2d4..1e79464 100644
--- a/tests/framework/base/activitymanager/AndroidManifest.xml
+++ b/tests/framework/base/activitymanager/AndroidManifest.xml
@@ -57,6 +57,10 @@
 
         <activity android:name="android.server.am.lifecycle.ActivityLifecycleClientTestBase$SecondActivity"/>
 
+        <activity
+                android:name="android.server.am.lifecycle.ActivityLifecycleClientTestBase$TranslucentActivity"
+                android:theme="@android:style/Theme.Translucent.NoTitleBar" />
+
         <activity android:name="android.server.am.StartActivityTests$TestActivity2" />
 
     </application>
diff --git a/tests/framework/base/activitymanager/app/src/android/server/am/BroadcastReceiverActivity.java b/tests/framework/base/activitymanager/app/src/android/server/am/BroadcastReceiverActivity.java
index 9e53e23..282d750 100644
--- a/tests/framework/base/activitymanager/app/src/android/server/am/BroadcastReceiverActivity.java
+++ b/tests/framework/base/activitymanager/app/src/android/server/am/BroadcastReceiverActivity.java
@@ -25,7 +25,6 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.Bundle;
-import android.server.am.util.ActivityLauncher;
 import android.util.Log;
 
 /**
diff --git a/tests/framework/base/activitymanager/app/src/android/server/am/Components.java b/tests/framework/base/activitymanager/app/src/android/server/am/Components.java
index 8310c69..49bcae3 100644
--- a/tests/framework/base/activitymanager/app/src/android/server/am/Components.java
+++ b/tests/framework/base/activitymanager/app/src/android/server/am/Components.java
@@ -20,13 +20,31 @@
 import android.server.am.component.ComponentsBase;
 
 public class Components extends ComponentsBase {
+    public static final ComponentName ALT_LAUNCHING_ACTIVITY = component("AltLaunchingActivity");
     public static final ComponentName ALWAYS_FOCUSABLE_PIP_ACTIVITY =
             component("AlwaysFocusablePipActivity");
     public static final ComponentName ANIMATION_TEST_ACTIVITY = component("AnimationTestActivity");
     public static final ComponentName ASSISTANT_ACTIVITY = component("AssistantActivity");
+    public static final ComponentName BOTTOM_ACTIVITY = component("BottomActivity");
+    public static final ComponentName BOTTOM_LEFT_LAYOUT_ACTIVITY =
+            component("BottomLeftLayoutActivity");
+    public static final ComponentName BOTTOM_RIGHT_LAYOUT_ACTIVITY =
+            component("BottomRightLayoutActivity");
+    public static final ComponentName BROADCAST_RECEIVER_ACTIVITY =
+            component("BroadcastReceiverActivity");
+    public static final ComponentName DIALOG_WHEN_LARGE_ACTIVITY =
+            component("DialogWhenLargeActivity");
+    public static final ComponentName DISMISS_KEYGUARD_ACTIVITY =
+            component("DismissKeyguardActivity");
     public static final ComponentName DOCKED_ACTIVITY = component("DockedActivity");
     public static final ComponentName ENTRY_POINT_ALIAS_ACTIVITY =
             component("EntryPointAliasActivity");
+    public static final ComponentName FONT_SCALE_ACTIVITY = component("FontScaleActivity");
+    public static final ComponentName FONT_SCALE_NO_RELAUNCH_ACTIVITY =
+            component("FontScaleNoRelaunchActivity");
+    public static final ComponentName FREEFORM_ACTIVITY = component("FreeformActivity");
+    public static final ComponentName LANDSCAPE_ORIENTATION_ACTIVITY =
+            component("LandscapeOrientationActivity");
     public static final ComponentName LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION =
             component("LaunchAssistantActivityFromSession");
     public static final ComponentName LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK  =
@@ -34,17 +52,38 @@
     public static final ComponentName LAUNCH_PIP_ON_PIP_ACTIVITY =
             component("LaunchPipOnPipActivity");
     public static final ComponentName LAUNCHING_ACTIVITY = component("LaunchingActivity");
+    public static final ComponentName LOG_CONFIGURATION_ACTIVITY =
+            component("LogConfigurationActivity");
     public static final ComponentName MOVE_TASK_TO_BACK_ACTIVITY =
             component("MoveTaskToBackActivity");
+    public static final ComponentName NIGHT_MODE_ACTIVITY = component("NightModeActivity");
     public static final ComponentName NO_HISTORY_ACTIVITY = component("NoHistoryActivity");
+    public static final ComponentName NO_RELAUNCH_ACTIVITY = component("NoRelaunchActivity");
+    public static final ComponentName NON_RESIZEABLE_ACTIVITY = component("NonResizeableActivity");
     public static final ComponentName PIP_ACTIVITY = component("PipActivity");
+    public static final ComponentName PORTRAIT_ORIENTATION_ACTIVITY =
+            component("PortraitOrientationActivity");
+    public static final ComponentName RESIZEABLE_ACTIVITY = component("ResizeableActivity");
+    public static final ComponentName SHOW_WHEN_LOCKED_ACTIVITY =
+            component("ShowWhenLockedActivity");
+    public static final ComponentName SHOW_WHEN_LOCKED_ATTR_ACTIVITY =
+            component("ShowWhenLockedAttrActivity");
+    public static final ComponentName SINGLE_INSTANCE_ACTIVITY =
+            component("SingleInstanceActivity");
     public static final ComponentName SINGLE_TASK_ACTIVITY = component("SingleTaskActivity");
+    public static final ComponentName SLOW_CREATE_ACTIVITY = component("SlowCreateActivity");
     public static final ComponentName SPLASHSCREEN_ACTIVITY = component("SplashscreenActivity");
     public static final ComponentName SWIPE_REFRESH_ACTIVITY = component("SwipeRefreshActivity");
     public static final ComponentName TEST_ACTIVITY = component("TestActivity");
+    public static final ComponentName TOP_ACTIVITY = component("TopActivity");
+    public static final ComponentName TOP_LEFT_LAYOUT_ACTIVITY = component("TopLeftLayoutActivity");
+    public static final ComponentName TOP_RIGHT_LAYOUT_ACTIVITY =
+            component("TopRightLayoutActivity");
     public static final ComponentName TRANSLUCENT_ACTIVITY = component("TranslucentActivity");
     public static final ComponentName TRANSLUCENT_ASSISTANT_ACTIVITY =
             component("TranslucentAssistantActivity");
+    public static final ComponentName TRANSLUCENT_TOP_ACTIVITY =
+            component("TranslucentTopActivity");
     public static final ComponentName TURN_SCREEN_ON_ACTIVITY = component("TurnScreenOnActivity");
     public static final ComponentName TURN_SCREEN_ON_ATTR_ACTIVITY =
             component("TurnScreenOnAttrActivity");
@@ -56,6 +95,9 @@
             component("TurnScreenOnSingleTaskActivity");
     public static final ComponentName TURN_SCREEN_ON_WITH_RELAYOUT_ACTIVITY =
             component("TurnScreenOnWithRelayoutActivity");
+    public static final ComponentName VIRTUAL_DISPLAY_ACTIVITY =
+            component("VirtualDisplayActivity");
+    public static final ComponentName VR_TEST_ACTIVITY = component("VrTestActivity");
 
     public static final ComponentName ASSISTANT_VOICE_INTERACTION_SERVICE =
             component("AssistantVoiceInteractionService");
diff --git a/tests/framework/base/activitymanager/app/src/android/server/am/LaunchBroadcastReceiver.java b/tests/framework/base/activitymanager/app/src/android/server/am/LaunchBroadcastReceiver.java
index 1e51cef..f3cb966 100644
--- a/tests/framework/base/activitymanager/app/src/android/server/am/LaunchBroadcastReceiver.java
+++ b/tests/framework/base/activitymanager/app/src/android/server/am/LaunchBroadcastReceiver.java
@@ -19,7 +19,6 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
-import android.server.am.util.ActivityLauncher;
 import android.util.Log;
 
 /** Broadcast receiver that can launch activities. */
diff --git a/tests/framework/base/activitymanager/app/src/android/server/am/SlowCreateActivity.java b/tests/framework/base/activitymanager/app/src/android/server/am/SlowCreateActivity.java
index 26992c1..4b78fc5 100644
--- a/tests/framework/base/activitymanager/app/src/android/server/am/SlowCreateActivity.java
+++ b/tests/framework/base/activitymanager/app/src/android/server/am/SlowCreateActivity.java
@@ -18,13 +18,14 @@
 
 import android.app.Activity;
 import android.os.Bundle;
+import android.os.SystemClock;
+
+import java.util.concurrent.TimeUnit;
 
 public class SlowCreateActivity extends Activity {
     @Override
     protected void onCreate(Bundle savedInstanceState) {
-        try {
-            Thread.sleep(2000);
-        } catch(InterruptedException e) {}
+        SystemClock.sleep(TimeUnit.SECONDS.toMillis(2));
         super.onCreate(savedInstanceState);
     }
 }
diff --git a/tests/framework/base/activitymanager/app/src/android/server/am/VirtualDisplayActivity.java b/tests/framework/base/activitymanager/app/src/android/server/am/VirtualDisplayActivity.java
index 8947a15..bf96af2 100644
--- a/tests/framework/base/activitymanager/app/src/android/server/am/VirtualDisplayActivity.java
+++ b/tests/framework/base/activitymanager/app/src/android/server/am/VirtualDisplayActivity.java
@@ -18,13 +18,15 @@
 
 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
+import static android.server.am.ActivityLauncher.KEY_DISPLAY_ID;
+import static android.server.am.ActivityLauncher.KEY_LAUNCH_ACTIVITY;
+import static android.server.am.ActivityLauncher.KEY_TARGET_ACTIVITY;
 
 import android.app.Activity;
 import android.content.Intent;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.VirtualDisplay;
 import android.os.Bundle;
-import android.server.am.util.ActivityLauncher;
 import android.util.Log;
 import android.view.Surface;
 import android.view.SurfaceHolder;
@@ -227,9 +229,9 @@
 
     private void launchActivity(String activityName, int displayId) {
         final Bundle extras = new Bundle();
-        extras.putBoolean("launch_activity", true);
-        extras.putString("target_activity", activityName);
-        extras.putInt("display_id", displayId);
+        extras.putBoolean(KEY_LAUNCH_ACTIVITY, true);
+        extras.putString(KEY_TARGET_ACTIVITY, activityName);
+        extras.putInt(KEY_DISPLAY_ID, displayId);
         ActivityLauncher.launchActivityFromExtras(this, extras);
     }
 }
diff --git a/tests/framework/base/activitymanager/appDeprecatedSdk/Android.mk b/tests/framework/base/activitymanager/appDeprecatedSdk/Android.mk
index d28d30b..2b556f6 100644
--- a/tests/framework/base/activitymanager/appDeprecatedSdk/Android.mk
+++ b/tests/framework/base/activitymanager/appDeprecatedSdk/Android.mk
@@ -19,6 +19,8 @@
 # don't include this package in any target
 LOCAL_MODULE_TAGS := optional
 
+LOCAL_STATIC_JAVA_LIBRARIES := cts-am-app-base
+
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_SDK_VERSION := 16
diff --git a/tests/framework/base/activitymanager/appDeprecatedSdk/src/android/server/am/deprecatedsdk/Components.java b/tests/framework/base/activitymanager/appDeprecatedSdk/src/android/server/am/deprecatedsdk/Components.java
new file mode 100644
index 0000000..180738d
--- /dev/null
+++ b/tests/framework/base/activitymanager/appDeprecatedSdk/src/android/server/am/deprecatedsdk/Components.java
@@ -0,0 +1,9 @@
+package android.server.am.deprecatedsdk;
+
+import android.content.ComponentName;
+import android.server.am.component.ComponentsBase;
+
+public class Components extends ComponentsBase {
+
+    public static final ComponentName MAIN_ACTIVITY = component(Components.class, "MainActivity");
+}
diff --git a/tests/framework/base/activitymanager/appSecondUid/src/android/server/am/second/LaunchBroadcastReceiver.java b/tests/framework/base/activitymanager/appSecondUid/src/android/server/am/second/LaunchBroadcastReceiver.java
index caa9e9e..1b975ac 100644
--- a/tests/framework/base/activitymanager/appSecondUid/src/android/server/am/second/LaunchBroadcastReceiver.java
+++ b/tests/framework/base/activitymanager/appSecondUid/src/android/server/am/second/LaunchBroadcastReceiver.java
@@ -19,7 +19,7 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
-import android.server.am.util.ActivityLauncher;
+import android.server.am.ActivityLauncher;
 import android.util.Log;
 
 /** Broadcast receiver that can launch activities. */
diff --git a/tests/framework/base/activitymanager/app_base/Android.mk b/tests/framework/base/activitymanager/app_base/Android.mk
index c395f97..384d715 100644
--- a/tests/framework/base/activitymanager/app_base/Android.mk
+++ b/tests/framework/base/activitymanager/app_base/Android.mk
@@ -8,6 +8,7 @@
 LOCAL_STATIC_JAVA_LIBRARIES := \
     android-support-test \
     android-support-v4 \
+    cts-amwm-util \
 
 LOCAL_SRC_FILES := \
     $(call all-java-files-under, src) \
diff --git a/tests/framework/base/activitymanager/app_base/src/android/server/am/LaunchingActivity.java b/tests/framework/base/activitymanager/app_base/src/android/server/am/LaunchingActivity.java
index 2b8d3be..1eadf61 100644
--- a/tests/framework/base/activitymanager/app_base/src/android/server/am/LaunchingActivity.java
+++ b/tests/framework/base/activitymanager/app_base/src/android/server/am/LaunchingActivity.java
@@ -17,11 +17,8 @@
 package android.server.am;
 
 import android.os.Bundle;
-import android.server.am.util.ActivityLauncher;
 import android.app.Activity;
 import android.content.Intent;
-import android.server.am.util.ActivityLauncher;
-import android.util.Log;
 
 /**
  * Activity that launches another activities when new intent is received.
diff --git a/tests/framework/base/activitymanager/app_base/src/android/server/am/component/ComponentsBase.java b/tests/framework/base/activitymanager/app_base/src/android/server/am/component/ComponentsBase.java
index 2843c4c..f6c3471 100644
--- a/tests/framework/base/activitymanager/app_base/src/android/server/am/component/ComponentsBase.java
+++ b/tests/framework/base/activitymanager/app_base/src/android/server/am/component/ComponentsBase.java
@@ -16,24 +16,10 @@
 
 package android.server.am.component;
 
-import static org.hamcrest.Matchers.allOf;
-import static org.hamcrest.Matchers.hasSize;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertThat;
 
-import android.app.Activity;
-import android.app.Service;
-import android.content.BroadcastReceiver;
 import android.content.ComponentName;
-import android.content.Context;
-
-import org.hamcrest.Matchers;
-
-import java.lang.reflect.Modifier;
-import java.util.Arrays;
-import java.util.stream.Collectors;
 
 /**
  * Base class for Components constants holding class.
diff --git a/tests/framework/base/activitymanager/app_base/src/android/server/am/util/ActivityLauncher.java b/tests/framework/base/activitymanager/app_base/src/android/server/am/util/ActivityLauncher.java
deleted file mode 100644
index 4f60e0a..0000000
--- a/tests/framework/base/activitymanager/app_base/src/android/server/am/util/ActivityLauncher.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.server.am.util;
-
-import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
-import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
-import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
-import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
-
-import android.app.ActivityOptions;
-import android.content.Intent;
-import android.content.ComponentName;
-import android.content.Context;
-import android.net.Uri;
-import android.os.Bundle;
-import android.server.am.TestActivity;
-import android.text.TextUtils;
-import android.util.Log;
-
-/** Utility class which contains common code for launching activities. */
-public class ActivityLauncher {
-    private static final String TAG = ActivityLauncher.class.getSimpleName();
-
-    public static void launchActivityFromExtras(final Context context, Bundle extras) {
-        if (extras == null || !extras.getBoolean("launch_activity")) {
-            return;
-        }
-
-        Log.i(TAG, "launchActivityFromExtras: extras=" + extras);
-
-        final Intent newIntent = new Intent();
-        final String targetComponent = extras.getString("target_component");
-        final String targetActivity = extras.getString("target_activity");
-        if (!TextUtils.isEmpty(targetComponent)) {
-            newIntent.setComponent(ComponentName.unflattenFromString(targetComponent));
-        } else if (targetActivity != null) {
-            final String extraPackageName = extras.getString("package_name");
-            final String packageName = extraPackageName != null ? extraPackageName
-                    : context.getApplicationContext().getPackageName();
-            newIntent.setComponent(new ComponentName(packageName,
-                    packageName + "." + targetActivity));
-        } else {
-            newIntent.setClass(context, TestActivity.class);
-        }
-
-        if (extras.getBoolean("launch_to_the_side")) {
-            newIntent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_LAUNCH_ADJACENT);
-            if (extras.getBoolean("random_data")) {
-                final Uri data = new Uri.Builder()
-                        .path(String.valueOf(System.currentTimeMillis()))
-                        .build();
-                newIntent.setData(data);
-            }
-        }
-        if (extras.getBoolean("multiple_task")) {
-            newIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
-        }
-        if (extras.getBoolean("new_task")) {
-            newIntent.addFlags(FLAG_ACTIVITY_NEW_TASK);
-        }
-
-        if (extras.getBoolean("reorder_to_front")) {
-            newIntent.addFlags(FLAG_ACTIVITY_REORDER_TO_FRONT);
-        }
-
-        ActivityOptions options = null;
-        final int displayId = extras.getInt("display_id", -1);
-        if (displayId != -1) {
-            options = ActivityOptions.makeBasic();
-            options.setLaunchDisplayId(displayId);
-            newIntent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK);
-        }
-
-        final Context launchContext = extras.getBoolean("use_application_context") ?
-                context.getApplicationContext() : context;
-
-        try {
-            launchContext.startActivity(newIntent, options != null ? options.toBundle() : null);
-        } catch (SecurityException e) {
-            Log.e(TAG, "SecurityException launching activity");
-        } catch (Exception e) {
-            if (extras.getBoolean("suppress_exceptions")) {
-                Log.e(TAG, "Exception launching activity");
-            } else {
-                throw e;
-            }
-        }
-    }
-}
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityAndWindowManagerOverrideConfigTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityAndWindowManagerOverrideConfigTests.java
index 0f83cee..21d6c69 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityAndWindowManagerOverrideConfigTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityAndWindowManagerOverrideConfigTests.java
@@ -17,7 +17,10 @@
 package android.server.am;
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.server.am.ComponentNameUtils.getLogTag;
+import static android.server.am.Components.LOG_CONFIGURATION_ACTIVITY;
 import static android.server.am.StateLogger.log;
+import static android.server.am.StateLogger.logAlways;
 import static android.view.Surface.ROTATION_0;
 import static android.view.Surface.ROTATION_180;
 
@@ -25,6 +28,9 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
+import android.content.ComponentName;
+import android.os.SystemClock;
+
 import org.junit.Test;
 
 import java.util.regex.Matcher;
@@ -35,35 +41,33 @@
  *     atest CtsActivityManagerDeviceTestCases:ActivityAndWindowManagerOverrideConfigTests
  */
 public class ActivityAndWindowManagerOverrideConfigTests extends ActivityManagerTestBase {
-    private static final String TEST_ACTIVITY_NAME = "LogConfigurationActivity";
 
     private static class ConfigurationChangeObserver {
-        private final Pattern mConfigurationChangedPattern =
+        private static final Pattern CONFIGURATION_CHANGED_PATTERN =
             Pattern.compile("(.+)Configuration changed: (\\d+),(\\d+)");
 
         private ConfigurationChangeObserver() {
         }
 
-        private boolean findConfigurationChange(String activityName, LogSeparator logSeparator)
-                throws InterruptedException {
-            int tries = 0;
-            boolean observedChange = false;
-            while (tries < 5 && !observedChange) {
-                final String[] lines = getDeviceLogsForComponents(logSeparator, activityName);
+        private boolean findConfigurationChange(
+                ComponentName activityName, LogSeparator logSeparator) {
+            for (int retry = 1; retry <= 5; retry++) {
+                final String[] lines =
+                        getDeviceLogsForComponents(logSeparator, getLogTag(activityName));
                 log("Looking at logcat");
                 for (int i = lines.length - 1; i >= 0; i--) {
                     final String line = lines[i].trim();
                     log(line);
-                    Matcher matcher = mConfigurationChangedPattern.matcher(line);
+                    Matcher matcher = CONFIGURATION_CHANGED_PATTERN.matcher(line);
                     if (matcher.matches()) {
-                        observedChange = true;
-                        break;
+                        return true;
                     }
                 }
-                tries++;
-                Thread.sleep(500);
+                logAlways("***Waiting configuration change of " + getLogTag(activityName)
+                        + " retry=" + retry);
+                SystemClock.sleep(500);
             }
-            return observedChange;
+            return false;
         }
     }
 
@@ -71,22 +75,22 @@
     public void testReceiveOverrideConfigFromRelayout() throws Exception {
         assumeTrue("Device doesn't support freeform. Skipping test.", supportsFreeform());
 
-        launchActivity(TEST_ACTIVITY_NAME, WINDOWING_MODE_FREEFORM);
+        launchActivity(LOG_CONFIGURATION_ACTIVITY, WINDOWING_MODE_FREEFORM);
 
         try (final RotationSession rotationSession = new RotationSession()) {
             rotationSession.set(ROTATION_0);
             LogSeparator logSeparator = clearLogcat();
-            resizeActivityTask(TEST_ACTIVITY_NAME, 0, 0, 100, 100);
+            resizeActivityTask(LOG_CONFIGURATION_ACTIVITY, 0, 0, 100, 100);
             ConfigurationChangeObserver c = new ConfigurationChangeObserver();
-            final boolean reportedSizeAfterResize = c.findConfigurationChange(TEST_ACTIVITY_NAME,
-                    logSeparator);
+            final boolean reportedSizeAfterResize = c.findConfigurationChange(
+                    LOG_CONFIGURATION_ACTIVITY, logSeparator);
             assertTrue("Expected to observe configuration change when resizing",
                     reportedSizeAfterResize);
 
             logSeparator = clearLogcat();
             rotationSession.set(ROTATION_180);
-            final boolean reportedSizeAfterRotation = c.findConfigurationChange(TEST_ACTIVITY_NAME,
-                    logSeparator);
+            final boolean reportedSizeAfterRotation = c.findConfigurationChange(
+                    LOG_CONFIGURATION_ACTIVITY, logSeparator);
             assertFalse("Not expected to observe configuration change after flip rotation",
                     reportedSizeAfterRotation);
         }
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerActivityVisibilityTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerActivityVisibilityTests.java
index 613bda4..accefe5 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerActivityVisibilityTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerActivityVisibilityTests.java
@@ -25,8 +25,11 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.server.am.ActivityManagerState.STATE_PAUSED;
 import static android.server.am.ActivityManagerState.STATE_RESUMED;
+import static android.server.am.Components.ALT_LAUNCHING_ACTIVITY;
 import static android.server.am.Components.ALWAYS_FOCUSABLE_PIP_ACTIVITY;
+import static android.server.am.Components.BROADCAST_RECEIVER_ACTIVITY;
 import static android.server.am.Components.DOCKED_ACTIVITY;
+import static android.server.am.Components.LAUNCHING_ACTIVITY;
 import static android.server.am.Components.LAUNCH_PIP_ON_PIP_ACTIVITY;
 import static android.server.am.Components.MOVE_TASK_TO_BACK_ACTIVITY;
 import static android.server.am.Components.NO_HISTORY_ACTIVITY;
@@ -39,6 +42,7 @@
 import static android.server.am.Components.TURN_SCREEN_ON_SHOW_ON_LOCK_ACTIVITY;
 import static android.server.am.Components.TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY;
 import static android.server.am.Components.TURN_SCREEN_ON_WITH_RELAYOUT_ACTIVITY;
+import static android.server.am.UiDeviceUtils.pressBackButton;
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
@@ -169,7 +173,7 @@
 
         // Launch two activities in docked stack.
         launchActivityInSplitScreenWithRecents(LAUNCHING_ACTIVITY);
-        getLaunchActivityBuilder().setTargetActivityName(BROADCAST_RECEIVER_ACTIVITY).execute();
+        getLaunchActivityBuilder().setTargetActivity(BROADCAST_RECEIVER_ACTIVITY).execute();
         mAmWmState.computeState(BROADCAST_RECEIVER_ACTIVITY);
         mAmWmState.assertVisibility(BROADCAST_RECEIVER_ACTIVITY, true);
         // Launch something to fullscreen stack to make it focused.
@@ -244,13 +248,14 @@
         launchActivity(LAUNCHING_ACTIVITY);
 
         // Launch the alternate launching activity from launching activity with reorder to front.
-        getLaunchActivityBuilder().setTargetActivityName(ALT_LAUNCHING_ACTIVITY)
+        getLaunchActivityBuilder().setTargetActivity(ALT_LAUNCHING_ACTIVITY)
                 .setReorderToFront(true).execute();
 
         // Launch the launching activity from the alternate launching activity with reorder to
         // front.
-        getLaunchActivityBuilder().setTargetActivityName(LAUNCHING_ACTIVITY)
-                .setLaunchingActivityName(ALT_LAUNCHING_ACTIVITY).setReorderToFront(true)
+        getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY)
+                .setLaunchingActivity(ALT_LAUNCHING_ACTIVITY)
+                .setReorderToFront(true)
                 .execute();
 
         // Press back
@@ -279,8 +284,9 @@
         launchActivity(LAUNCHING_ACTIVITY);
 
         // Launch the alternate launching activity from launching activity with reorder to front.
-        getLaunchActivityBuilder().setTargetActivityName(ALT_LAUNCHING_ACTIVITY)
-                .setReorderToFront(true).execute();
+        getLaunchActivityBuilder().setTargetActivity(ALT_LAUNCHING_ACTIVITY)
+                .setReorderToFront(true)
+                .execute();
 
         // Return home
         launchHomeActivity();
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmProfileTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmProfileTests.java
index 99472b5..3adec21 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmProfileTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmProfileTests.java
@@ -17,6 +17,7 @@
 package android.server.am;
 
 import static android.server.am.ComponentNameUtils.getActivityName;
+import static android.server.am.UiDeviceUtils.pressHomeButton;
 import static android.server.am.debuggable.Components.DEBUGGABLE_APP_ACTIVITY;
 
 import static org.junit.Assert.assertEquals;
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmStartOptionsTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmStartOptionsTests.java
index b5bb1da..ab73fcd 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmStartOptionsTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmStartOptionsTests.java
@@ -20,6 +20,7 @@
 import static android.server.am.Components.ENTRY_POINT_ALIAS_ACTIVITY;
 import static android.server.am.Components.SINGLE_TASK_ACTIVITY;
 import static android.server.am.Components.TEST_ACTIVITY;
+import static android.server.am.UiDeviceUtils.pressHomeButton;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAppConfigurationTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAppConfigurationTests.java
index adf2e14..59a2509 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAppConfigurationTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAppConfigurationTests.java
@@ -22,6 +22,15 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.server.am.ActivityAndWindowManagersState.dpToPx;
 import static android.server.am.ActivityManagerState.STATE_RESUMED;
+import static android.server.am.ComponentNameUtils.getWindowName;
+import static android.server.am.Components.BROADCAST_RECEIVER_ACTIVITY;
+import static android.server.am.Components.DIALOG_WHEN_LARGE_ACTIVITY;
+import static android.server.am.Components.LANDSCAPE_ORIENTATION_ACTIVITY;
+import static android.server.am.Components.LAUNCHING_ACTIVITY;
+import static android.server.am.Components.NIGHT_MODE_ACTIVITY;
+import static android.server.am.Components.PORTRAIT_ORIENTATION_ACTIVITY;
+import static android.server.am.Components.RESIZEABLE_ACTIVITY;
+import static android.server.am.Components.TEST_ACTIVITY;
 import static android.server.am.StateLogger.log;
 import static android.server.am.StateLogger.logE;
 import static android.server.am.translucentapp.Components.TRANSLUCENT_LANDSCAPE_ACTIVITY;
@@ -37,10 +46,12 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
+import android.content.ComponentName;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 import android.support.test.filters.FlakyTest;
 
+import org.junit.Ignore;
 import org.junit.Test;
 
 import java.util.ArrayList;
@@ -51,12 +62,6 @@
  *     atest CtsActivityManagerDeviceTestCases:ActivityManagerAppConfigurationTests
  */
 public class ActivityManagerAppConfigurationTests extends ActivityManagerTestBase {
-    private static final String RESIZEABLE_ACTIVITY_NAME = "ResizeableActivity";
-    private static final String TEST_ACTIVITY_NAME = "TestActivity";
-    private static final String PORTRAIT_ACTIVITY_NAME = "PortraitOrientationActivity";
-    private static final String LANDSCAPE_ACTIVITY_NAME = "LandscapeOrientationActivity";
-    private static final String NIGHT_MODE_ACTIVITY = "NightModeActivity";
-    private static final String DIALOG_WHEN_LARGE_ACTIVITY = "DialogWhenLargeActivity";
 
     private static final int SMALL_WIDTH_DP = 426;
     private static final int SMALL_HEIGHT_DP = 320;
@@ -75,13 +80,13 @@
         assumeTrue("Skipping test: no multi-window support", supportsSplitScreenMultiWindow());
 
         LogSeparator logSeparator = clearLogcat();
-        launchActivity(RESIZEABLE_ACTIVITY_NAME, WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
-        final ReportedSizes fullscreenSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
+        launchActivity(RESIZEABLE_ACTIVITY, WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
+        final ReportedSizes fullscreenSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY,
                 logSeparator);
 
         logSeparator = clearLogcat();
-        setActivityTaskWindowingMode(RESIZEABLE_ACTIVITY_NAME, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
-        final ReportedSizes dockedSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
+        setActivityTaskWindowingMode(RESIZEABLE_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+        final ReportedSizes dockedSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY,
                 logSeparator);
 
         assertSizesAreSane(fullscreenSizes, dockedSizes);
@@ -98,13 +103,13 @@
         assumeTrue("Skipping test: no multi-window support", supportsSplitScreenMultiWindow());
 
         LogSeparator logSeparator = clearLogcat();
-        launchActivity(RESIZEABLE_ACTIVITY_NAME, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
-        final ReportedSizes dockedSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
+        launchActivity(RESIZEABLE_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+        final ReportedSizes dockedSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY,
                 logSeparator);
 
         logSeparator = clearLogcat();
-        setActivityTaskWindowingMode(RESIZEABLE_ACTIVITY_NAME, WINDOWING_MODE_FULLSCREEN);
-        final ReportedSizes fullscreenSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
+        setActivityTaskWindowingMode(RESIZEABLE_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
+        final ReportedSizes fullscreenSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY,
                 logSeparator);
 
         assertSizesAreSane(fullscreenSizes, dockedSizes);
@@ -121,9 +126,9 @@
             rotationSession.set(ROTATION_0);
 
             final LogSeparator logSeparator = clearLogcat();
-            launchActivity(RESIZEABLE_ACTIVITY_NAME,
+            launchActivity(RESIZEABLE_ACTIVITY,
                     WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
-            final ReportedSizes initialSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
+            final ReportedSizes initialSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY,
                     logSeparator);
 
             rotateAndCheckSizes(rotationSession, initialSizes);
@@ -145,10 +150,12 @@
             final LogSeparator logSeparator = clearLogcat();
             // Launch our own activity to side in case Recents (or other activity to side) doesn't
             // support rotation.
-            launchActivitiesInSplitScreen(LAUNCHING_ACTIVITY, TEST_ACTIVITY_NAME);
+            launchActivitiesInSplitScreen(
+                    getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
+                    getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
             // Launch target activity in docked stack.
-            getLaunchActivityBuilder().setTargetActivityName(RESIZEABLE_ACTIVITY_NAME).execute();
-            final ReportedSizes initialSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
+            getLaunchActivityBuilder().setTargetActivity(RESIZEABLE_ACTIVITY).execute();
+            final ReportedSizes initialSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY,
                     logSeparator);
 
             rotateAndCheckSizes(rotationSession, initialSizes);
@@ -168,8 +175,10 @@
             rotationSession.set(ROTATION_0);
 
             final LogSeparator logSeparator = clearLogcat();
-            launchActivitiesInSplitScreen(LAUNCHING_ACTIVITY, RESIZEABLE_ACTIVITY_NAME);
-            final ReportedSizes initialSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
+            launchActivitiesInSplitScreen(
+                    getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
+                    getLaunchActivityBuilder().setTargetActivity(RESIZEABLE_ACTIVITY));
+            final ReportedSizes initialSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY,
                     logSeparator);
 
             rotateAndCheckSizes(rotationSession, initialSizes);
@@ -181,8 +190,8 @@
         final int[] rotations = { ROTATION_270, ROTATION_180, ROTATION_90, ROTATION_0 };
         for (final int rotation : rotations) {
             final LogSeparator logSeparator = clearLogcat();
-            final int actualStackId = mAmWmState.getAmState().getTaskByActivityName(
-                    RESIZEABLE_ACTIVITY_NAME).mStackId;
+            final int actualStackId =
+                    mAmWmState.getAmState().getTaskByActivity(RESIZEABLE_ACTIVITY).mStackId;
             final int displayId = mAmWmState.getAmState().getStackById(actualStackId).mDisplayId;
             rotationSession.set(rotation);
             final int newDeviceRotation = getDeviceRotation(displayId);
@@ -195,7 +204,7 @@
                 return;
             }
 
-            final ReportedSizes rotatedSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
+            final ReportedSizes rotatedSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY,
                     logSeparator);
             assertSizesRotate(prevSizes, rotatedSizes);
             prevSizes = rotatedSizes;
@@ -208,7 +217,7 @@
      */
     @Test
     public void testSameConfigurationFullSplitFullRelaunch() throws Exception {
-        moveActivityFullSplitFull(TEST_ACTIVITY_NAME);
+        moveActivityFullSplitFull(TEST_ACTIVITY);
     }
 
     /**
@@ -217,7 +226,7 @@
     @Presubmit
     @Test
     public void testSameConfigurationFullSplitFullNoRelaunch() throws Exception {
-        moveActivityFullSplitFull(RESIZEABLE_ACTIVITY_NAME);
+        moveActivityFullSplitFull(RESIZEABLE_ACTIVITY);
     }
 
     /**
@@ -227,7 +236,7 @@
      * user long-presses overview/recents button to exit split-screen.
      * Asserts that initial and final reported sizes in fullscreen stack are the same.
      */
-    private void moveActivityFullSplitFull(String activityName) throws Exception {
+    private void moveActivityFullSplitFull(ComponentName activityName) throws Exception {
         assumeTrue("Skipping test: no multi-window support", supportsSplitScreenMultiWindow());
 
         // Launch to fullscreen stack and record size.
@@ -271,7 +280,7 @@
      */
     @Test
     public void testSameConfigurationSplitFullSplitRelaunch() throws Exception {
-        moveActivitySplitFullSplit(TEST_ACTIVITY_NAME);
+        moveActivitySplitFullSplit(TEST_ACTIVITY);
     }
 
     /**
@@ -279,7 +288,7 @@
      */
     @Test
     public void testSameConfigurationSplitFullSplitNoRelaunch() throws Exception {
-        moveActivitySplitFullSplit(RESIZEABLE_ACTIVITY_NAME);
+        moveActivitySplitFullSplit(RESIZEABLE_ACTIVITY);
     }
 
     /**
@@ -301,8 +310,11 @@
         final int smallHeightPx = dpToPx(SMALL_HEIGHT_DP, density);
 
         mAm.resizeStack(stack.mStackId, new Rect(0, 0, smallWidthPx, smallHeightPx));
-        mAmWmState.waitForValidState(DIALOG_WHEN_LARGE_ACTIVITY,
-                WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
+        mAmWmState.waitForValidState(
+                new WaitForValidActivityState.Builder(DIALOG_WHEN_LARGE_ACTIVITY)
+                        .setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)
+                        .setActivityType(ACTIVITY_TYPE_STANDARD)
+                        .build());
     }
 
     /**
@@ -313,26 +325,26 @@
     @FlakyTest(bugId = 71875755)
     public void testFullscreenAppOrientationRequests() throws Exception {
         LogSeparator logSeparator = clearLogcat();
-        launchActivity(PORTRAIT_ACTIVITY_NAME);
-        mAmWmState.assertVisibility(PORTRAIT_ACTIVITY_NAME, true /* visible */);
+        launchActivity(PORTRAIT_ORIENTATION_ACTIVITY);
+        mAmWmState.assertVisibility(PORTRAIT_ORIENTATION_ACTIVITY, true /* visible */);
         ReportedSizes reportedSizes =
-                getLastReportedSizesForActivity(PORTRAIT_ACTIVITY_NAME, logSeparator);
+                getLastReportedSizesForActivity(PORTRAIT_ORIENTATION_ACTIVITY, logSeparator);
         assertEquals("portrait activity should be in portrait",
                 1 /* portrait */, reportedSizes.orientation);
         logSeparator = clearLogcat();
 
-        launchActivity(LANDSCAPE_ACTIVITY_NAME);
-        mAmWmState.assertVisibility(LANDSCAPE_ACTIVITY_NAME, true /* visible */);
+        launchActivity(LANDSCAPE_ORIENTATION_ACTIVITY);
+        mAmWmState.assertVisibility(LANDSCAPE_ORIENTATION_ACTIVITY, true /* visible */);
         reportedSizes =
-                getLastReportedSizesForActivity(LANDSCAPE_ACTIVITY_NAME, logSeparator);
+                getLastReportedSizesForActivity(LANDSCAPE_ORIENTATION_ACTIVITY, logSeparator);
         assertEquals("landscape activity should be in landscape",
                 2 /* landscape */, reportedSizes.orientation);
         logSeparator = clearLogcat();
 
-        launchActivity(PORTRAIT_ACTIVITY_NAME);
-        mAmWmState.assertVisibility(PORTRAIT_ACTIVITY_NAME, true /* visible */);
+        launchActivity(PORTRAIT_ORIENTATION_ACTIVITY);
+        mAmWmState.assertVisibility(PORTRAIT_ORIENTATION_ACTIVITY, true /* visible */);
         reportedSizes =
-                getLastReportedSizesForActivity(PORTRAIT_ACTIVITY_NAME, logSeparator);
+                getLastReportedSizesForActivity(PORTRAIT_ORIENTATION_ACTIVITY, logSeparator);
         assertEquals("portrait activity should be in portrait",
                 1 /* portrait */, reportedSizes.orientation);
         logSeparator = clearLogcat();
@@ -341,9 +353,9 @@
     @Test
     public void testNonfullscreenAppOrientationRequests() throws Exception {
         LogSeparator logSeparator = clearLogcat();
-        launchActivity(PORTRAIT_ACTIVITY_NAME);
+        launchActivity(PORTRAIT_ORIENTATION_ACTIVITY);
         final ReportedSizes initialReportedSizes =
-                getLastReportedSizesForActivity(PORTRAIT_ACTIVITY_NAME, logSeparator);
+                getLastReportedSizesForActivity(PORTRAIT_ORIENTATION_ACTIVITY, logSeparator);
         assertEquals("portrait activity should be in portrait",
                 1 /* portrait */, initialReportedSizes.orientation);
         logSeparator = clearLogcat();
@@ -360,13 +372,14 @@
     }
 
     // TODO(b/70870253): This test seems malfunction.
-    // @Test
+    @Ignore("b/70870253")
+    @Test
     public void testNonFullscreenActivityProhibited() throws Exception {
         // We do not wait for the activity as it should not launch based on the restrictions around
         // specifying orientation. We instead start an activity known to launch immediately after
         // so that we can ensure processing the first activity occurred.
         launchActivityNoWait(TRANSLUCENT_LANDSCAPE_ACTIVITY);
-        launchActivity(PORTRAIT_ACTIVITY_NAME);
+        launchActivity(PORTRAIT_ORIENTATION_ACTIVITY);
 
         assertFalse("target SDK > 26 non-fullscreen activity should not reach onResume",
                 mAmWmState.getAmState().containsActivity(TRANSLUCENT_LANDSCAPE_ACTIVITY));
@@ -392,8 +405,8 @@
     @Test
     public void testTaskCloseRestoreOrientation() throws Exception {
         // Start landscape activity.
-        launchActivity(LANDSCAPE_ACTIVITY_NAME);
-        mAmWmState.assertVisibility(LANDSCAPE_ACTIVITY_NAME, true /* visible */);
+        launchActivity(LANDSCAPE_ORIENTATION_ACTIVITY);
+        mAmWmState.assertVisibility(LANDSCAPE_ORIENTATION_ACTIVITY, true /* visible */);
         assertEquals("Fullscreen app requested landscape orientation",
                 0 /* landscape */, mAmWmState.getWmState().getLastOrientation());
 
@@ -408,8 +421,7 @@
         executeShellCommand(FINISH_ACTIVITY_BROADCAST);
 
         // Verify that activity brought to front is in originally requested orientation.
-        mAmWmState.computeState(
-            new WaitForValidActivityState.Builder(LANDSCAPE_ACTIVITY_NAME).build());
+        mAmWmState.computeState(LANDSCAPE_ORIENTATION_ACTIVITY);
         assertEquals("Should return to app in landscape orientation",
                 0 /* landscape */, mAmWmState.getWmState().getLastOrientation());
     }
@@ -422,8 +434,8 @@
     @FlakyTest(bugId = 71792393)
     public void testTaskMoveToBackOrientation() throws Exception {
         // Start landscape activity.
-        launchActivity(LANDSCAPE_ACTIVITY_NAME);
-        mAmWmState.assertVisibility(LANDSCAPE_ACTIVITY_NAME, true /* visible */);
+        launchActivity(LANDSCAPE_ORIENTATION_ACTIVITY);
+        mAmWmState.assertVisibility(LANDSCAPE_ORIENTATION_ACTIVITY, true /* visible */);
         assertEquals("Fullscreen app requested landscape orientation",
                 0 /* landscape */, mAmWmState.getWmState().getLastOrientation());
 
@@ -438,7 +450,7 @@
         executeShellCommand(MOVE_TASK_TO_BACK_BROADCAST);
 
         // Verify that activity brought to front is in originally requested orientation.
-        mAmWmState.waitForValidState(LANDSCAPE_ACTIVITY_NAME);
+        mAmWmState.waitForValidState(LANDSCAPE_ORIENTATION_ACTIVITY);
         assertEquals("Should return to app in landscape orientation",
                 0 /* landscape */, mAmWmState.getWmState().getLastOrientation());
     }
@@ -454,7 +466,7 @@
 
         try (final RotationSession rotationSession = new RotationSession()) {
             requestOrientationInSplitScreen(rotationSession,
-                    ROTATION_90 /* portrait */, LANDSCAPE_ACTIVITY_NAME);
+                    ROTATION_90 /* portrait */, LANDSCAPE_ORIENTATION_ACTIVITY);
         }
     }
 
@@ -468,7 +480,7 @@
 
         try (final RotationSession rotationSession = new RotationSession()) {
             requestOrientationInSplitScreen(rotationSession,
-                    ROTATION_0 /* landscape */, PORTRAIT_ACTIVITY_NAME);
+                    ROTATION_0 /* landscape */, PORTRAIT_ORIENTATION_ACTIVITY);
         }
     }
 
@@ -477,7 +489,7 @@
      * didn't change.
      */
     private void requestOrientationInSplitScreen(RotationSession rotationSession, int orientation,
-            String activity) throws Exception {
+            ComponentName activity) throws Exception {
         assumeTrue("Skipping test: no multi-window support", supportsSplitScreenMultiWindow());
 
         // Set initial orientation.
@@ -485,15 +497,15 @@
 
         // Launch activities that request orientations and check that device doesn't rotate.
         launchActivitiesInSplitScreen(
-                getLaunchActivityBuilder().setTargetActivityName(LAUNCHING_ACTIVITY),
-                getLaunchActivityBuilder().setTargetActivityName(activity).setMultipleTask(true));
+                getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
+                getLaunchActivityBuilder().setTargetActivity(activity).setMultipleTask(true));
 
         mAmWmState.assertVisibility(activity, true /* visible */);
         assertEquals("Split-screen apps shouldn't influence device orientation",
                 orientation, mAmWmState.getWmState().getRotation());
 
-        getLaunchActivityBuilder().setMultipleTask(true).setTargetActivityName(activity).execute();
-        mAmWmState.computeState(new String[] {activity});
+        getLaunchActivityBuilder().setMultipleTask(true).setTargetActivity(activity).execute();
+        mAmWmState.computeState(activity);
         mAmWmState.assertVisibility(activity, true /* visible */);
         assertEquals("Split-screen apps shouldn't influence device orientation",
                 orientation, mAmWmState.getWmState().getRotation());
@@ -503,7 +515,7 @@
      * Launches activity in docked stack, moves to fullscreen stack and back to docked stack.
      * Asserts that initial and final reported sizes in docked stack are the same.
      */
-    private void moveActivitySplitFullSplit(String activityName) throws Exception {
+    private void moveActivitySplitFullSplit(ComponentName activityName) throws Exception {
         assumeTrue("Skipping test: no multi-window support", supportsSplitScreenMultiWindow());
 
         // Launch to docked stack and record size.
@@ -587,20 +599,20 @@
         assertEquals(firstSize.smallestWidthDp, secondSize.smallestWidthDp);
     }
 
-    private ReportedSizes getActivityDisplaySize(String activityName, LogSeparator logSeparator)
-            throws Exception {
+    private ReportedSizes getActivityDisplaySize(ComponentName activityName,
+            LogSeparator logSeparator) throws Exception {
         mAmWmState.computeState(false /* compareTaskAndStackBounds */,
-                new WaitForValidActivityState.Builder(activityName).build());
+                new WaitForValidActivityState(activityName));
         final ReportedSizes details = getLastReportedSizesForActivity(activityName, logSeparator);
         assertNotNull(details);
         return details;
     }
 
-    private Rect getDisplayRect(String activityName)
+    private Rect getDisplayRect(ComponentName activityName)
             throws Exception {
-        final String windowName = getActivityWindowName(activityName);
+        final String windowName = getWindowName(activityName);
 
-        mAmWmState.computeState(new String[] {activityName});
+        mAmWmState.computeState(activityName);
         mAmWmState.assertFocusedWindow("Test window must be the front window.", windowName);
 
         final List<WindowManagerState.WindowState> tempWindowList = new ArrayList<>();
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAssistantStackTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAssistantStackTests.java
index fca289c..84c22d2 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAssistantStackTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAssistantStackTests.java
@@ -42,6 +42,7 @@
 import static android.server.am.Components.TEST_ACTIVITY;
 import static android.server.am.Components.TRANSLUCENT_ASSISTANT_ACTIVITY;
 import static android.server.am.Components.TestActivity.TEST_ACTIVITY_ACTION_FINISH_SELF;
+import static android.server.am.UiDeviceUtils.pressBackButton;
 
 import static org.hamcrest.Matchers.hasSize;
 import static org.junit.Assert.assertEquals;
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerConfigChangeTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerConfigChangeTests.java
index fd8d9eb..ab1a820 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerConfigChangeTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerConfigChangeTests.java
@@ -17,17 +17,23 @@
 package android.server.am;
 
 import static android.server.am.ActivityManagerState.STATE_RESUMED;
+import static android.server.am.ComponentNameUtils.getLogTag;
+import static android.server.am.Components.FONT_SCALE_ACTIVITY;
+import static android.server.am.Components.FONT_SCALE_NO_RELAUNCH_ACTIVITY;
+import static android.server.am.Components.NO_RELAUNCH_ACTIVITY;
+import static android.server.am.Components.TEST_ACTIVITY;
 import static android.server.am.StateLogger.log;
 import static android.server.am.StateLogger.logE;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
+import android.content.ComponentName;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
 import android.server.am.settings.SettingsSession;
-
 import android.support.test.filters.FlakyTest;
+
 import org.junit.Test;
 
 import java.util.regex.Matcher;
@@ -38,66 +44,61 @@
  *     atest CtsActivityManagerDeviceTestCases:ActivityManagerConfigChangeTests
  */
 public class ActivityManagerConfigChangeTests extends ActivityManagerTestBase {
-    private static final String TEST_ACTIVITY_NAME = "TestActivity";
-    private static final String NO_RELAUNCH_ACTIVITY_NAME = "NoRelaunchActivity";
-
-    private static final String FONT_SCALE_ACTIVITY_NAME = "FontScaleActivity";
-    private static final String FONT_SCALE_NO_RELAUNCH_ACTIVITY_NAME =
-            "FontScaleNoRelaunchActivity";
 
     private static final float EXPECTED_FONT_SIZE_SP = 10.0f;
 
     @Test
     public void testRotation90Relaunch() throws Exception{
         // Should relaunch on every rotation and receive no onConfigurationChanged()
-        testRotation(TEST_ACTIVITY_NAME, 1, 1, 0);
+        testRotation(TEST_ACTIVITY, 1, 1, 0);
     }
 
     @Test
     public void testRotation90NoRelaunch() throws Exception {
         // Should receive onConfigurationChanged() on every rotation and no relaunch
-        testRotation(NO_RELAUNCH_ACTIVITY_NAME, 1, 0, 1);
+        testRotation(NO_RELAUNCH_ACTIVITY, 1, 0, 1);
     }
 
     @Test
     public void testRotation180Relaunch() throws Exception {
         // Should receive nothing
-        testRotation(TEST_ACTIVITY_NAME, 2, 0, 0);
+        testRotation(TEST_ACTIVITY, 2, 0, 0);
     }
 
     @Test
     public void testRotation180NoRelaunch() throws Exception {
         // Should receive nothing
-        testRotation(NO_RELAUNCH_ACTIVITY_NAME, 2, 0, 0);
+        testRotation(NO_RELAUNCH_ACTIVITY, 2, 0, 0);
     }
 
+    @FlakyTest(bugId = 73701185)
     @Presubmit
     @Test
     public void testChangeFontScaleRelaunch() throws Exception {
         // Should relaunch and receive no onConfigurationChanged()
-        testChangeFontScale(FONT_SCALE_ACTIVITY_NAME, true /* relaunch */);
+        testChangeFontScale(FONT_SCALE_ACTIVITY, true /* relaunch */);
     }
 
+    @FlakyTest(bugId = 73812451)
     @Presubmit
     @Test
     public void testChangeFontScaleNoRelaunch() throws Exception {
         // Should receive onConfigurationChanged() and no relaunch
-        testChangeFontScale(FONT_SCALE_NO_RELAUNCH_ACTIVITY_NAME, false /* relaunch */);
+        testChangeFontScale(FONT_SCALE_NO_RELAUNCH_ACTIVITY, false /* relaunch */);
     }
 
-    private void testRotation(String activityName, int rotationStep, int numRelaunch,
+    private void testRotation(ComponentName activityName, int rotationStep, int numRelaunch,
             int numConfigChange) throws Exception {
         launchActivity(activityName);
 
-        final String[] waitForActivitiesVisible = new String[] {activityName};
-        mAmWmState.computeState(waitForActivitiesVisible);
+        mAmWmState.computeState(activityName);
 
         final int initialRotation = 4 - rotationStep;
         try (final RotationSession rotationSession = new RotationSession()) {
             rotationSession.set(initialRotation);
-            mAmWmState.computeState(waitForActivitiesVisible);
-            final int actualStackId = mAmWmState.getAmState().getTaskByActivityName(
-                    activityName).mStackId;
+            mAmWmState.computeState(activityName);
+            final int actualStackId =
+                    mAmWmState.getAmState().getTaskByActivity(activityName).mStackId;
             final int displayId = mAmWmState.getAmState().getStackById(actualStackId).mDisplayId;
             final int newDeviceRotation = getDeviceRotation(displayId);
             if (newDeviceRotation == INVALID_DEVICE_ROTATION) {
@@ -112,7 +113,7 @@
             for (int rotation = 0; rotation < 4; rotation += rotationStep) {
                 final LogSeparator logSeparator = clearLogcat();
                 rotationSession.set(rotation);
-                mAmWmState.computeState(waitForActivitiesVisible);
+                mAmWmState.computeState(activityName);
                 assertRelaunchOrConfigChanged(activityName, numRelaunch, numConfigChange,
                         logSeparator);
             }
@@ -129,20 +130,19 @@
     }
 
     private void testChangeFontScale(
-            String activityName, boolean relaunch) throws Exception {
+            ComponentName activityName, boolean relaunch) throws Exception {
         try (final FontScaleSession fontScaleSession = new FontScaleSession()) {
             fontScaleSession.set(1.0f);
             LogSeparator logSeparator = clearLogcat();
             launchActivity(activityName);
-            final String[] waitForActivitiesVisible = new String[]{activityName};
-            mAmWmState.computeState(waitForActivitiesVisible);
+            mAmWmState.computeState(activityName);
 
             final int densityDpi = getActivityDensityDpi(activityName, logSeparator);
 
             for (float fontScale = 0.85f; fontScale <= 1.3f; fontScale += 0.15f) {
                 logSeparator = clearLogcat();
                 fontScaleSession.set(fontScale);
-                mAmWmState.computeState(waitForActivitiesVisible);
+                mAmWmState.computeState(activityName);
                 assertRelaunchOrConfigChanged(activityName, relaunch ? 1 : 0, relaunch ? 0 : 1,
                         logSeparator);
 
@@ -164,8 +164,8 @@
         final LogSeparator firstLogSeparator = clearLogcat();
 
         // Launch an activity that prints applied config.
-        launchActivity(TEST_ACTIVITY_NAME);
-        final int assetSeq = readAssetSeqNumber(TEST_ACTIVITY_NAME, firstLogSeparator);
+        launchActivity(TEST_ACTIVITY);
+        final int assetSeq = readAssetSeqNumber(TEST_ACTIVITY, firstLogSeparator);
 
         final LogSeparator logSeparator = clearLogcat();
         // Update package info.
@@ -173,8 +173,8 @@
         mAmWmState.waitForWithAmState((amState) -> {
             // Wait for activity to be resumed and asset seq number to be updated.
             try {
-                return readAssetSeqNumber(TEST_ACTIVITY_NAME, logSeparator) == assetSeq + 1
-                        && amState.hasActivityState(TEST_ACTIVITY_NAME, STATE_RESUMED);
+                return readAssetSeqNumber(TEST_ACTIVITY, logSeparator) == assetSeq + 1
+                        && amState.hasActivityState(TEST_ACTIVITY, STATE_RESUMED);
             } catch (Exception e) {
                 logE("Error waiting for valid state: " + e.getMessage());
                 return false;
@@ -182,9 +182,9 @@
         }, "Waiting asset sequence number to be updated and for activity to be resumed.");
 
         // Check if activity is relaunched and asset seq is updated.
-        assertRelaunchOrConfigChanged(TEST_ACTIVITY_NAME, 1 /* numRelaunch */,
+        assertRelaunchOrConfigChanged(TEST_ACTIVITY, 1 /* numRelaunch */,
                 0 /* numConfigChange */, logSeparator);
-        final int newAssetSeq = readAssetSeqNumber(TEST_ACTIVITY_NAME, logSeparator);
+        final int newAssetSeq = readAssetSeqNumber(TEST_ACTIVITY, logSeparator);
         assertEquals("Asset sequence number must be incremented.", assetSeq + 1, newAssetSeq);
     }
 
@@ -192,9 +192,9 @@
             "(.+): Configuration: \\{(.*) as.(\\d+)(.*)\\}");
 
     /** Read asset sequence number in last applied configuration from logs. */
-    private int readAssetSeqNumber(String activityName, LogSeparator logSeparator)
+    private int readAssetSeqNumber(ComponentName activityName, LogSeparator logSeparator)
             throws Exception {
-        final String[] lines = getDeviceLogsForComponents(logSeparator, activityName);
+        final String[] lines = getDeviceLogsForComponents(logSeparator, getLogTag(activityName));
         for (int i = lines.length - 1; i >= 0; i--) {
             final String line = lines[i].trim();
             final Matcher matcher = sConfigurationPattern.matcher(line);
@@ -219,9 +219,9 @@
 
     private static Pattern sDeviceDensityPattern = Pattern.compile("^(.+): fontActivityDpi=(.+)$");
 
-    private int getActivityDensityDpi(String activityName, LogSeparator logSeparator)
+    private int getActivityDensityDpi(ComponentName activityName, LogSeparator logSeparator)
             throws Exception {
-        final String[] lines = getDeviceLogsForComponents(logSeparator, activityName);
+        final String[] lines = getDeviceLogsForComponents(logSeparator, getLogTag(activityName));
         for (int i = lines.length - 1; i >= 0; i--) {
             final String line = lines[i].trim();
             final Matcher matcher = sDeviceDensityPattern.matcher(line);
@@ -236,9 +236,9 @@
     private static final Pattern sFontSizePattern = Pattern.compile("^(.+): fontPixelSize=(.+)$");
 
     /** Read the font size in the last log line. */
-    private void assertExpectedFontPixelSize(String activityName, int fontPixelSize,
+    private void assertExpectedFontPixelSize(ComponentName activityName, int fontPixelSize,
             LogSeparator logSeparator) throws Exception {
-        final String[] lines = getDeviceLogsForComponents(logSeparator, activityName);
+        final String[] lines = getDeviceLogsForComponents(logSeparator, getLogTag(activityName));
         for (int i = lines.length - 1; i >= 0; i--) {
             final String line = lines[i].trim();
             final Matcher matcher = sFontSizePattern.matcher(line);
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayKeyguardTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayKeyguardTests.java
index a24b7ad..32262d5 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayKeyguardTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayKeyguardTests.java
@@ -16,6 +16,8 @@
 
 package android.server.am;
 
+import static android.server.am.Components.DISMISS_KEYGUARD_ACTIVITY;
+
 import static org.junit.Assume.assumeTrue;
 
 import android.server.am.ActivityManagerState.ActivityDisplay;
@@ -30,7 +32,6 @@
  *     atest CtsActivityManagerDeviceTestCases:ActivityManagerDisplayKeyguardTests
  */
 public class ActivityManagerDisplayKeyguardTests extends ActivityManagerDisplayTestBase {
-    private static final String DISMISS_KEYGUARD_ACTIVITY = "DismissKeyguardActivity";
 
     @Before
     @Override
@@ -52,7 +53,6 @@
             final ActivityDisplay newDisplay = virtualDisplaySession.createDisplay();
 
             lockScreenSession.gotoKeyguard();
-            mAmWmState.waitForKeyguardShowingAndNotOccluded();
             mAmWmState.assertKeyguardShowingAndNotOccluded();
             launchActivityOnDisplay(DISMISS_KEYGUARD_ACTIVITY, newDisplay.mId);
             mAmWmState.waitForKeyguardShowingAndNotOccluded();
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayLockedKeyguardTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayLockedKeyguardTests.java
index fb8ead8..a68dafd 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayLockedKeyguardTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayLockedKeyguardTests.java
@@ -18,6 +18,10 @@
 
 import static android.server.am.ActivityManagerState.STATE_RESUMED;
 import static android.server.am.ActivityManagerState.STATE_STOPPED;
+import static android.server.am.Components.DISMISS_KEYGUARD_ACTIVITY;
+import static android.server.am.Components.SHOW_WHEN_LOCKED_ACTIVITY;
+import static android.server.am.Components.TEST_ACTIVITY;
+import static android.server.am.Components.VIRTUAL_DISPLAY_ACTIVITY;
 
 import static org.junit.Assume.assumeTrue;
 
@@ -34,11 +38,6 @@
  */
 public class ActivityManagerDisplayLockedKeyguardTests extends ActivityManagerDisplayTestBase {
 
-    private static final String TEST_ACTIVITY_NAME = "TestActivity";
-    private static final String VIRTUAL_DISPLAY_ACTIVITY = "VirtualDisplayActivity";
-    private static final String DISMISS_KEYGUARD_ACTIVITY = "DismissKeyguardActivity";
-    private static final String SHOW_WHEN_LOCKED_ACTIVITY = "ShowWhenLockedActivity";
-
     @Before
     @Override
     public void setUp() throws Exception {
@@ -62,21 +61,20 @@
             mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
 
             // Launch activity on new secondary display.
-            launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mId);
-            mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true /* visible */);
+            launchActivityOnDisplay(TEST_ACTIVITY, newDisplay.mId);
+            mAmWmState.assertVisibility(TEST_ACTIVITY, true /* visible */);
 
             // Lock the device.
             lockScreenSession.gotoKeyguard();
-            mAmWmState.waitForKeyguardShowingAndNotOccluded();
-            mAmWmState.waitForActivityState(TEST_ACTIVITY_NAME, STATE_STOPPED);
-            mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, false /* visible */);
+            mAmWmState.waitForActivityState(TEST_ACTIVITY, STATE_STOPPED);
+            mAmWmState.assertVisibility(TEST_ACTIVITY, false /* visible */);
 
             // Unlock and check if visibility is back.
             lockScreenSession.unlockDevice()
                     .enterAndConfirmLockCredential();
             mAmWmState.waitForKeyguardGone();
-            mAmWmState.waitForActivityState(TEST_ACTIVITY_NAME, STATE_RESUMED);
-            mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true /* visible */);
+            mAmWmState.waitForActivityState(TEST_ACTIVITY, STATE_RESUMED);
+            mAmWmState.assertVisibility(TEST_ACTIVITY, true /* visible */);
         }
     }
 
@@ -91,7 +89,6 @@
             final ActivityDisplay newDisplay = virtualDisplaySession.createDisplay();
 
             lockScreenSession.gotoKeyguard();
-            mAmWmState.waitForKeyguardShowingAndNotOccluded();
             mAmWmState.assertKeyguardShowingAndNotOccluded();
             launchActivityOnDisplay(DISMISS_KEYGUARD_ACTIVITY, newDisplay.mId);
             lockScreenSession.enterAndConfirmLockCredential();
@@ -109,10 +106,9 @@
             final ActivityDisplay newDisplay = virtualDisplaySession.createDisplay();
 
             lockScreenSession.gotoKeyguard();
-            mAmWmState.waitForKeyguardShowingAndNotOccluded();
             mAmWmState.assertKeyguardShowingAndNotOccluded();
             launchActivity(SHOW_WHEN_LOCKED_ACTIVITY);
-            mAmWmState.computeState(new WaitForValidActivityState(SHOW_WHEN_LOCKED_ACTIVITY));
+            mAmWmState.computeState(SHOW_WHEN_LOCKED_ACTIVITY);
             mAmWmState.assertVisibility(SHOW_WHEN_LOCKED_ACTIVITY, true);
             launchActivityOnDisplay(DISMISS_KEYGUARD_ACTIVITY, newDisplay.mId);
             lockScreenSession.enterAndConfirmLockCredential();
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTestBase.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTestBase.java
index a13d7811..85bf4d5 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTestBase.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTestBase.java
@@ -18,11 +18,14 @@
 
 import static android.content.pm.PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS;
 import static android.server.am.ActivityAndWindowManagersState.DEFAULT_DISPLAY_ID;
+import static android.server.am.ComponentNameUtils.getSimpleClassName;
+import static android.server.am.Components.VIRTUAL_DISPLAY_ACTIVITY;
 import static android.server.am.StateLogger.log;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
+import android.content.ComponentName;
 import android.content.res.Configuration;
 import android.provider.Settings;
 import android.server.am.ActivityManagerState.ActivityDisplay;
@@ -43,13 +46,9 @@
  * @see ActivityManagerDisplayTests
  * @see ActivityManagerDisplayLockedKeyguardTests
  */
-public class ActivityManagerDisplayTestBase extends ActivityManagerTestBase {
-    private static final String WM_SIZE = "wm size";
-    private static final String WM_DENSITY = "wm density";
+class ActivityManagerDisplayTestBase extends ActivityManagerTestBase {
 
     static final int CUSTOM_DENSITY_DPI = 222;
-
-    private static final String VIRTUAL_DISPLAY_ACTIVITY = "VirtualDisplayActivity";
     private static final int INVALID_DENSITY_DPI = -1;
 
     ActivityDisplay getDisplayState(List<ActivityDisplay> displays, int displayId) {
@@ -196,7 +195,7 @@
         private boolean mCanShowWithInsecureKeyguard = false;
         private boolean mPublicDisplay = false;
         private boolean mResizeDisplay = true;
-        private String mLaunchActivity = null;
+        private ComponentName mLaunchActivity = null;
         private boolean mSimulateDisplay = false;
         private boolean mMustBeCreated = true;
 
@@ -230,7 +229,7 @@
             return this;
         }
 
-        public VirtualDisplaySession setLaunchActivity(String launchActivity) {
+        public VirtualDisplaySession setLaunchActivity(ComponentName launchActivity) {
             mLaunchActivity = launchActivity;
             return this;
         }
@@ -307,7 +306,7 @@
             if (mLaunchInSplitScreen) {
                 getLaunchActivityBuilder()
                         .setToSide(true)
-                        .setTargetActivityName(VIRTUAL_DISPLAY_ACTIVITY)
+                        .setTargetActivity(VIRTUAL_DISPLAY_ACTIVITY)
                         .execute();
             } else {
                 launchActivity(VIRTUAL_DISPLAY_ACTIVITY);
@@ -337,7 +336,8 @@
             if (mLaunchActivity != null) {
                 createVirtualDisplayCommand
                         .append(" --es launch_target_activity ")
-                        .append(mLaunchActivity);
+                        // TODO(b/73349193): Should pass component name.
+                        .append(getSimpleClassName(mLaunchActivity));
             }
             executeShellCommand(createVirtualDisplayCommand.toString());
             mVirtualDisplayCreated = true;
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTests.java
index 459aa57..6a0291f 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTests.java
@@ -17,6 +17,8 @@
 package android.server.am;
 
 import static android.server.am.ActivityAndWindowManagersState.DEFAULT_DISPLAY_ID;
+import static android.server.am.ComponentNameUtils.getActivityName;
+import static android.server.am.Components.TEST_ACTIVITY;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assume.assumeFalse;
@@ -34,7 +36,6 @@
  *     atest CtsActivityManagerDeviceTestCases:ActivityManagerDisplayTests
  */
 public class ActivityManagerDisplayTests extends ActivityManagerDisplayTestBase {
-    private static final String TEST_ACTIVITY_NAME = "TestActivity";
 
     /**
      * Tests that the global configuration is equal to the default display's override configuration.
@@ -79,18 +80,18 @@
             final ActivityDisplay newDisplay = virtualDisplaySession.createDisplay();
 
             // Launch activity on new secondary display.
-            launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mId);
-            mAmWmState.computeState(new WaitForValidActivityState(TEST_ACTIVITY_NAME));
+            launchActivityOnDisplay(TEST_ACTIVITY, newDisplay.mId);
+            mAmWmState.computeState(TEST_ACTIVITY);
 
             mAmWmState.assertFocusedActivity("Launched activity must be focused",
-                    TEST_ACTIVITY_NAME);
+                    TEST_ACTIVITY);
 
             // Check that activity is on the right display.
             final int frontStackId = mAmWmState.getAmState().getFrontStackId(DEFAULT_DISPLAY_ID);
             final ActivityManagerState.ActivityStack frontStack =
                     mAmWmState.getAmState().getStackById(frontStackId);
             assertEquals("Launched activity must be resumed",
-                    getActivityComponentName(TEST_ACTIVITY_NAME), frontStack.mResumedActivity);
+                    getActivityName(TEST_ACTIVITY), frontStack.mResumedActivity);
             assertEquals("Front stack must be on the default display", DEFAULT_DISPLAY_ID,
                     frontStack.mDisplayId);
             mAmWmState.assertFocusedStack("Focus must be on the default display", frontStackId);
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerFreeformStackTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerFreeformStackTests.java
index 64f79b7..d8808ea 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerFreeformStackTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerFreeformStackTests.java
@@ -18,6 +18,11 @@
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.server.am.Components.FREEFORM_ACTIVITY;
+import static android.server.am.Components.NON_RESIZEABLE_ACTIVITY;
+import static android.server.am.Components.NO_RELAUNCH_ACTIVITY;
+import static android.server.am.Components.TEST_ACTIVITY;
+
 import static org.junit.Assert.assertEquals;
 
 import android.graphics.Rect;
@@ -32,7 +37,6 @@
  */
 public class ActivityManagerFreeformStackTests extends ActivityManagerTestBase {
 
-    private static final String TEST_ACTIVITY = "TestActivity";
     private static final int TEST_TASK_OFFSET = 20;
     private static final int TEST_TASK_OFFSET_2 = 100;
     private static final int TEST_TASK_SIZE_1 = 900;
@@ -42,9 +46,6 @@
 
     // NOTE: Launching the FreeformActivity will automatically launch the TestActivity
     // with bounds (0, 0, 900, 900)
-    private static final String FREEFORM_ACTIVITY = "FreeformActivity";
-    private static final String NON_RESIZEABLE_ACTIVITY = "NonResizeableActivity";
-    private static final String NO_RELAUNCH_ACTIVITY = "NoRelaunchActivity";
 
     @Test
     public void testFreeformWindowManagementSupport() throws Exception {
@@ -66,17 +67,17 @@
         mAmWmState.assertFocusedActivity(
                 TEST_ACTIVITY + " must be focused Activity", TEST_ACTIVITY);
         assertEquals(new Rect(0, 0, TEST_TASK_SIZE_1, TEST_TASK_SIZE_1),
-                mAmWmState.getAmState().getTaskByActivityName(TEST_ACTIVITY).getBounds());
+                mAmWmState.getAmState().getTaskByActivity(TEST_ACTIVITY).getBounds());
     }
 
     @Test
     public void testNonResizeableActivityHasFullDisplayBounds() throws Exception {
         launchActivity(NON_RESIZEABLE_ACTIVITY, WINDOWING_MODE_FREEFORM);
 
-        mAmWmState.computeState(new WaitForValidActivityState.Builder(NON_RESIZEABLE_ACTIVITY).build());
+        mAmWmState.computeState(NON_RESIZEABLE_ACTIVITY);
 
         final ActivityTask task =
-                mAmWmState.getAmState().getTaskByActivityName(NON_RESIZEABLE_ACTIVITY);
+                mAmWmState.getAmState().getTaskByActivity(NON_RESIZEABLE_ACTIVITY);
         final ActivityStack stack = mAmWmState.getAmState().getStackById(task.mStackId);
 
         if (task.isFullscreen()) {
@@ -96,8 +97,7 @@
         launchActivity(TEST_ACTIVITY, WINDOWING_MODE_FREEFORM);
         launchActivity(NO_RELAUNCH_ACTIVITY, WINDOWING_MODE_FREEFORM);
 
-        mAmWmState.computeState(new WaitForValidActivityState.Builder(TEST_ACTIVITY).build(),
-                new WaitForValidActivityState.Builder(NO_RELAUNCH_ACTIVITY).build());
+        mAmWmState.computeState(TEST_ACTIVITY, NO_RELAUNCH_ACTIVITY);
 
         if (!supportsFreeform()) {
             mAmWmState.assertDoesNotContainStack("Must not contain freeform stack.",
@@ -127,8 +127,7 @@
                 TEST_TASK_OFFSET, TEST_TASK_OFFSET, testTaskSize2, testTaskSize1);
         resizeActivityTask(NO_RELAUNCH_ACTIVITY,
                 TEST_TASK_OFFSET_2, TEST_TASK_OFFSET_2, testTaskSize2, testTaskSize1);
-        mAmWmState.computeState(new WaitForValidActivityState.Builder(TEST_ACTIVITY).build(),
-                new WaitForValidActivityState.Builder(NO_RELAUNCH_ACTIVITY).build());
+        mAmWmState.computeState(TEST_ACTIVITY, NO_RELAUNCH_ACTIVITY);
 
         assertActivityLifecycle(TEST_ACTIVITY, true /* relaunched */, logSeparator);
         assertActivityLifecycle(NO_RELAUNCH_ACTIVITY, false /* relaunched */, logSeparator);
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerManifestLayoutTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerManifestLayoutTests.java
index 2929d90..3aa514a 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerManifestLayoutTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerManifestLayoutTests.java
@@ -19,15 +19,22 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.server.am.ActivityAndWindowManagersState.dpToPx;
+import static android.server.am.ComponentNameUtils.getWindowName;
+import static android.server.am.Components.BOTTOM_LEFT_LAYOUT_ACTIVITY;
+import static android.server.am.Components.BOTTOM_RIGHT_LAYOUT_ACTIVITY;
+import static android.server.am.Components.TOP_LEFT_LAYOUT_ACTIVITY;
+import static android.server.am.Components.TOP_RIGHT_LAYOUT_ACTIVITY;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
 
 import static org.junit.Assume.assumeTrue;
 
+import android.content.ComponentName;
 import android.graphics.Rect;
 import android.server.am.WindowManagerState.Display;
 import android.server.am.WindowManagerState.WindowState;
 
-import junit.framework.Assert;
-
 import org.junit.Test;
 
 import java.util.ArrayList;
@@ -93,33 +100,37 @@
     }
 
     private void testMinimalSize(int windowingMode) throws Exception {
-        final String activityName = "BottomRightLayoutActivity";
-
         // Issue command to resize to <0,0,1,1>. We expect the size to be floored at
         // MIN_WIDTH_DPxMIN_HEIGHT_DP.
         if (windowingMode == WINDOWING_MODE_FREEFORM) {
-            launchActivity(activityName, WINDOWING_MODE_FREEFORM);
-            resizeActivityTask(activityName, 0, 0, 1, 1);
+            launchActivity(BOTTOM_RIGHT_LAYOUT_ACTIVITY, WINDOWING_MODE_FREEFORM);
+            resizeActivityTask(BOTTOM_RIGHT_LAYOUT_ACTIVITY, 0, 0, 1, 1);
         } else { // stackId == DOCKED_STACK_ID
-            launchActivityInSplitScreenWithRecents(activityName);
+            launchActivityInSplitScreenWithRecents(BOTTOM_RIGHT_LAYOUT_ACTIVITY);
             resizeDockedStack(1, 1, 1, 1);
         }
-        getDisplayAndWindowState(activityName, false);
+        getDisplayAndWindowState(BOTTOM_RIGHT_LAYOUT_ACTIVITY, false);
 
         final int minWidth = dpToPx(MIN_WIDTH_DP, mDisplay.getDpi());
         final int minHeight = dpToPx(MIN_HEIGHT_DP, mDisplay.getDpi());
         final Rect containingRect = mWindowState.getContainingFrame();
 
-        Assert.assertEquals("Min width is incorrect", minWidth, containingRect.width());
-        Assert.assertEquals("Min height is incorrect", minHeight, containingRect.height());
+        assertEquals("Min width is incorrect", minWidth, containingRect.width());
+        assertEquals("Min height is incorrect", minHeight, containingRect.height());
     }
 
     private void testLayout(
             int vGravity, int hGravity, boolean fraction) throws Exception {
         assumeTrue("Skipping test: no freeform support", supportsFreeform());
 
-        final String activityName = (vGravity == GRAVITY_VER_TOP ? "Top" : "Bottom")
-                + (hGravity == GRAVITY_HOR_LEFT ? "Left" : "Right") + "LayoutActivity";
+        final ComponentName activityName;
+        if (vGravity == GRAVITY_VER_TOP) {
+            activityName = (hGravity == GRAVITY_HOR_LEFT) ? TOP_LEFT_LAYOUT_ACTIVITY
+                    : TOP_RIGHT_LAYOUT_ACTIVITY;
+        } else {
+            activityName = (hGravity == GRAVITY_HOR_LEFT) ? BOTTOM_LEFT_LAYOUT_ACTIVITY
+                    : BOTTOM_RIGHT_LAYOUT_ACTIVITY;
+        }
 
         // Launch in freeform stack
         launchActivity(activityName, WINDOWING_MODE_FREEFORM);
@@ -145,11 +156,11 @@
                 vGravity, hGravity, expectedWidthPx, expectedHeightPx, containingRect, appRect);
     }
 
-    private void getDisplayAndWindowState(String activityName, boolean checkFocus)
+    private void getDisplayAndWindowState(ComponentName activityName, boolean checkFocus)
             throws Exception {
-        final String windowName = getActivityWindowName(activityName);
+        final String windowName = getWindowName(activityName);
 
-        mAmWmState.computeState(new WaitForValidActivityState.Builder(activityName).build());
+        mAmWmState.computeState(activityName);
 
         if (checkFocus) {
             mAmWmState.assertFocusedWindow("Test window must be the front window.", windowName);
@@ -159,34 +170,32 @@
 
         mAmWmState.getWmState().getMatchingVisibleWindowState(windowName, mTempWindowList);
 
-        Assert.assertEquals("Should have exactly one window state for the activity.",
+        assertEquals("Should have exactly one window state for the activity.",
                 1, mTempWindowList.size());
 
         mWindowState = mTempWindowList.get(0);
-        Assert.assertNotNull("Should have a valid window", mWindowState);
+        assertNotNull("Should have a valid window", mWindowState);
 
         mDisplay = mAmWmState.getWmState().getDisplay(mWindowState.getDisplayId());
-        Assert.assertNotNull("Should be on a display", mDisplay);
+        assertNotNull("Should be on a display", mDisplay);
     }
 
     private void verifyFrameSizeAndPosition(
             int vGravity, int hGravity, int expectedWidthPx, int expectedHeightPx,
             Rect containingFrame, Rect parentFrame) {
-        Assert.assertEquals("Width is incorrect", expectedWidthPx, containingFrame.width());
-        Assert.assertEquals("Height is incorrect", expectedHeightPx, containingFrame.height());
+        assertEquals("Width is incorrect", expectedWidthPx, containingFrame.width());
+        assertEquals("Height is incorrect", expectedHeightPx, containingFrame.height());
 
         if (vGravity == GRAVITY_VER_TOP) {
-            Assert.assertEquals("Should be on the top", parentFrame.top, containingFrame.top);
+            assertEquals("Should be on the top", parentFrame.top, containingFrame.top);
         } else if (vGravity == GRAVITY_VER_BOTTOM) {
-            Assert.assertEquals("Should be on the bottom",
-                    parentFrame.bottom, containingFrame.bottom);
+            assertEquals("Should be on the bottom", parentFrame.bottom, containingFrame.bottom);
         }
 
         if (hGravity == GRAVITY_HOR_LEFT) {
-            Assert.assertEquals("Should be on the left", parentFrame.left, containingFrame.left);
+            assertEquals("Should be on the left", parentFrame.left, containingFrame.left);
         } else if (hGravity == GRAVITY_HOR_RIGHT){
-            Assert.assertEquals("Should be on the right",
-                    parentFrame.right, containingFrame.right);
+            assertEquals("Should be on the right", parentFrame.right, containingFrame.right);
         }
     }
 }
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerMultiDisplayTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerMultiDisplayTests.java
index 3961d83..7c49d13 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerMultiDisplayTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerMultiDisplayTests.java
@@ -20,12 +20,30 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.server.am.ActivityAndWindowManagersState.DEFAULT_DISPLAY_ID;
+import static android.server.am.ActivityLauncher.KEY_LAUNCH_ACTIVITY;
+import static android.server.am.ActivityLauncher.KEY_NEW_TASK;
+import static android.server.am.ActivityLauncher.KEY_TARGET_ACTIVITY;
 import static android.server.am.ActivityManagerDisplayTestBase.ReportedDisplayMetrics
         .getDisplayMetrics;
 import static android.server.am.ActivityManagerState.STATE_RESUMED;
 import static android.server.am.ActivityManagerState.STATE_STOPPED;
 import static android.server.am.ComponentNameUtils.getActivityName;
+import static android.server.am.ComponentNameUtils.getSimpleClassName;
+import static android.server.am.ComponentNameUtils.getWindowName;
+import static android.server.am.Components.ALT_LAUNCHING_ACTIVITY;
+import static android.server.am.Components.BROADCAST_RECEIVER_ACTIVITY;
+import static android.server.am.Components.LAUNCHING_ACTIVITY;
+import static android.server.am.Components.LAUNCH_BROADCAST_ACTION;
+import static android.server.am.Components.LAUNCH_BROADCAST_RECEIVER;
+import static android.server.am.Components.NON_RESIZEABLE_ACTIVITY;
+import static android.server.am.Components.RESIZEABLE_ACTIVITY;
+import static android.server.am.Components.SHOW_WHEN_LOCKED_ATTR_ACTIVITY;
+import static android.server.am.Components.TEST_ACTIVITY;
+import static android.server.am.Components.VIRTUAL_DISPLAY_ACTIVITY;
+import static android.server.am.StateLogger.logAlways;
 import static android.server.am.StateLogger.logE;
+import static android.server.am.UiDeviceUtils.pressSleepButton;
+import static android.server.am.UiDeviceUtils.pressWakeupButton;
 import static android.server.am.second.Components.SECOND_ACTIVITY;
 import static android.server.am.second.Components.SECOND_LAUNCH_BROADCAST_ACTION;
 import static android.server.am.second.Components.SECOND_LAUNCH_BROADCAST_RECEIVER;
@@ -59,17 +77,6 @@
  *     atest CtsActivityManagerDeviceTestCases:ActivityManagerMultiDisplayTests
  */
 public class ActivityManagerMultiDisplayTests extends ActivityManagerDisplayTestBase {
-    private static final String TEST_ACTIVITY_NAME = "TestActivity";
-    private static final String VIRTUAL_DISPLAY_ACTIVITY = "VirtualDisplayActivity";
-    private static final String RESIZEABLE_ACTIVITY_NAME = "ResizeableActivity";
-    private static final String NON_RESIZEABLE_ACTIVITY_NAME = "NonResizeableActivity";
-    private static final String SHOW_WHEN_LOCKED_ATTR_ACTIVITY_NAME = "ShowWhenLockedAttrActivity";
-
-    private static final ComponentName TEST_ACTIVITY = ComponentName.createRelative(
-            componentName, "." + TEST_ACTIVITY_NAME);
-    private final ComponentName LAUNCH_BROADCAST_RECEIVER = ComponentName.createRelative(
-            componentName, ".LaunchBroadcastReceiver");
-    private final String LAUNCH_BROADCAST_ACTION = componentName + ".LAUNCH_BROADCAST_ACTION";
 
     @Before
     @Override
@@ -91,23 +98,23 @@
 
             // Launch activity on new secondary display.
             final LogSeparator logSeparator = clearLogcat();
-            launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mId);
-            mAmWmState.computeState(new WaitForValidActivityState(TEST_ACTIVITY_NAME));
+            launchActivityOnDisplay(TEST_ACTIVITY, newDisplay.mId);
+            mAmWmState.computeState(TEST_ACTIVITY);
 
             mAmWmState.assertFocusedActivity(
                     "Activity launched on secondary display must be focused",
-                    TEST_ACTIVITY_NAME);
+                    TEST_ACTIVITY);
 
             // Check that activity is on the right display.
             final int frontStackId = mAmWmState.getAmState().getFrontStackId(newDisplay.mId);
             final ActivityManagerState.ActivityStack frontStack =
                     mAmWmState.getAmState().getStackById(frontStackId);
             assertEquals("Launched activity must be on the secondary display and resumed",
-                    getActivityComponentName(TEST_ACTIVITY_NAME), frontStack.mResumedActivity);
+                    getActivityName(TEST_ACTIVITY), frontStack.mResumedActivity);
             mAmWmState.assertFocusedStack("Focus must be on secondary display", frontStackId);
 
             // Check that activity config corresponds to display config.
-            final ReportedSizes reportedSizes = getLastReportedSizesForActivity(TEST_ACTIVITY_NAME,
+            final ReportedSizes reportedSizes = getLastReportedSizesForActivity(TEST_ACTIVITY,
                     logSeparator);
             assertEquals("Activity launched on secondary display must have proper configuration",
                     CUSTOM_DENSITY_DPI, reportedSizes.densityDpi);
@@ -125,19 +132,19 @@
             final ActivityDisplay newDisplay = virtualDisplaySession.createDisplay();
 
             // Launch activity on new secondary display.
-            launchActivityOnDisplay(NON_RESIZEABLE_ACTIVITY_NAME, newDisplay.mId);
-            mAmWmState.computeState(new WaitForValidActivityState(NON_RESIZEABLE_ACTIVITY_NAME));
+            launchActivityOnDisplay(NON_RESIZEABLE_ACTIVITY, newDisplay.mId);
+            mAmWmState.computeState(NON_RESIZEABLE_ACTIVITY);
 
             mAmWmState.assertFocusedActivity(
                     "Activity launched on secondary display must be focused",
-                    NON_RESIZEABLE_ACTIVITY_NAME);
+                    NON_RESIZEABLE_ACTIVITY);
 
             // Check that activity is on the right display.
             final int frontStackId = mAmWmState.getAmState().getFrontStackId(DEFAULT_DISPLAY_ID);
             final ActivityManagerState.ActivityStack frontStack =
                     mAmWmState.getAmState().getStackById(frontStackId);
             assertEquals("Launched activity must be on the primary display and resumed",
-                    getActivityComponentName(NON_RESIZEABLE_ACTIVITY_NAME),
+                    getActivityName(NON_RESIZEABLE_ACTIVITY),
                     frontStack.mResumedActivity);
             mAmWmState.assertFocusedStack("Focus must be on the primary display", frontStackId);
         }
@@ -160,19 +167,19 @@
                     .createDisplay();
 
             // Launch activity on new secondary display.
-            launchActivityOnDisplay(NON_RESIZEABLE_ACTIVITY_NAME, newDisplay.mId);
-            mAmWmState.computeState(new WaitForValidActivityState(NON_RESIZEABLE_ACTIVITY_NAME));
+            launchActivityOnDisplay(NON_RESIZEABLE_ACTIVITY, newDisplay.mId);
+            mAmWmState.computeState(NON_RESIZEABLE_ACTIVITY);
 
             mAmWmState.assertFocusedActivity(
                     "Activity launched on secondary display must be focused",
-                    NON_RESIZEABLE_ACTIVITY_NAME);
+                    NON_RESIZEABLE_ACTIVITY);
 
             // Check that activity is on the right display.
             final int frontStackId = mAmWmState.getAmState().getFrontStackId(DEFAULT_DISPLAY_ID);
             final ActivityManagerState.ActivityStack frontStack =
                     mAmWmState.getAmState().getStackById(frontStackId);
             assertEquals("Launched activity must be on the primary display and resumed",
-                    getActivityComponentName(NON_RESIZEABLE_ACTIVITY_NAME),
+                    getActivityName(NON_RESIZEABLE_ACTIVITY),
                     frontStack.mResumedActivity);
             mAmWmState.assertFocusedStack("Focus must be on the primary display", frontStackId);
             mAmWmState.assertDoesNotContainStack("Must not contain docked stack.",
@@ -190,19 +197,19 @@
             // Create new virtual display.
             final ActivityDisplay newDisplay = virtualDisplaySession.createDisplay();
             // Launch a non-resizeable activity on a primary display.
-            launchActivityInNewTask(NON_RESIZEABLE_ACTIVITY_NAME);
+            launchActivityInNewTask(NON_RESIZEABLE_ACTIVITY);
             // Launch a resizeable activity on new secondary display to create a new stack there.
-            launchActivityOnDisplay(RESIZEABLE_ACTIVITY_NAME, newDisplay.mId);
+            launchActivityOnDisplay(RESIZEABLE_ACTIVITY, newDisplay.mId);
             final int externalFrontStackId = mAmWmState.getAmState()
                     .getFrontStackId(newDisplay.mId);
 
             // Try to move the non-resizeable activity to new secondary display.
-            moveActivityToStack(NON_RESIZEABLE_ACTIVITY_NAME, externalFrontStackId);
-            mAmWmState.computeState(new WaitForValidActivityState(NON_RESIZEABLE_ACTIVITY_NAME));
+            moveActivityToStack(NON_RESIZEABLE_ACTIVITY, externalFrontStackId);
+            mAmWmState.computeState(NON_RESIZEABLE_ACTIVITY);
 
             mAmWmState.assertFocusedActivity(
                     "Activity launched on secondary display must be focused",
-                    RESIZEABLE_ACTIVITY_NAME);
+                    RESIZEABLE_ACTIVITY);
 
             // Check that activity is in the same stack
             final int defaultFrontStackId = mAmWmState.getAmState().getFrontStackId(
@@ -210,7 +217,7 @@
             final ActivityManagerState.ActivityStack defaultFrontStack =
                     mAmWmState.getAmState().getStackById(defaultFrontStackId);
             assertEquals("Launched activity must be on the primary display and resumed",
-                    getActivityComponentName(NON_RESIZEABLE_ACTIVITY_NAME),
+                    getActivityName(NON_RESIZEABLE_ACTIVITY),
                     defaultFrontStack.getTopTask().mRealActivity);
             mAmWmState.assertFocusedStack("Focus must remain on the secondary display",
                     externalFrontStackId);
@@ -239,21 +246,22 @@
             ActivityManagerState.ActivityStack frontStack =
                     mAmWmState.getAmState().getStackById(frontStackId);
             assertEquals("Launched activity must be on the secondary display and resumed",
-                    getActivityComponentName(BROADCAST_RECEIVER_ACTIVITY),
+                    getActivityName(BROADCAST_RECEIVER_ACTIVITY),
                     frontStack.mResumedActivity);
             mAmWmState.assertFocusedStack("Focus must be on the secondary display", frontStackId);
 
             // Launch non-resizeable activity from secondary display.
-            executeShellCommand("am broadcast -a trigger_broadcast --ez launch_activity true "
-                    + "--ez new_task true --es target_activity " + NON_RESIZEABLE_ACTIVITY_NAME);
-            mAmWmState.computeState(new WaitForValidActivityState(NON_RESIZEABLE_ACTIVITY_NAME));
+            executeShellCommand("am broadcast -a trigger_broadcast --ez " + KEY_LAUNCH_ACTIVITY
+                    + " true --ez " + KEY_NEW_TASK + " true --es " + KEY_TARGET_ACTIVITY + " "
+                    + getSimpleClassName(NON_RESIZEABLE_ACTIVITY));
+            mAmWmState.computeState(NON_RESIZEABLE_ACTIVITY);
 
             // Check that non-resizeable activity is on the secondary display, because of the
             // resizeable root of the task.
             frontStackId = mAmWmState.getAmState().getFrontStackId(newDisplay.mId);
             frontStack = mAmWmState.getAmState().getStackById(frontStackId);
             assertEquals("Launched activity must be on the primary display and resumed",
-                    getActivityComponentName(NON_RESIZEABLE_ACTIVITY_NAME),
+                    getActivityName(NON_RESIZEABLE_ACTIVITY),
                     frontStack.mResumedActivity);
             mAmWmState.assertFocusedStack("Focus must be on the primary display", frontStackId);
         }
@@ -280,12 +288,12 @@
             ActivityManagerState.ActivityStack frontStack =
                     mAmWmState.getAmState().getStackById(frontStackId);
             assertEquals("Launched activity must be on the secondary display and resumed",
-                    getActivityComponentName(LAUNCHING_ACTIVITY),
+                    getActivityName(LAUNCHING_ACTIVITY),
                     frontStack.mResumedActivity);
             mAmWmState.assertFocusedStack("Focus must be on the secondary display", frontStackId);
 
             // Launch non-resizeable activity from secondary display.
-            getLaunchActivityBuilder().setTargetActivityName(NON_RESIZEABLE_ACTIVITY_NAME)
+            getLaunchActivityBuilder().setTargetActivity(NON_RESIZEABLE_ACTIVITY)
                     .setNewTask(true).setMultipleTask(true).execute();
 
             // Check that non-resizeable activity is on the primary display.
@@ -294,7 +302,7 @@
             assertFalse("Launched activity must be on a different display",
                     newDisplay.mId == frontStack.mDisplayId);
             assertEquals("Launched activity must be resumed",
-                    getActivityComponentName(NON_RESIZEABLE_ACTIVITY_NAME),
+                    getActivityName(NON_RESIZEABLE_ACTIVITY),
                     frontStack.mResumedActivity);
             mAmWmState.assertFocusedStack("Focus must be on a just launched activity",
                     frontStackId);
@@ -323,10 +331,9 @@
 
             assertSecurityException("ActivityLauncher", logSeparator);
 
-            mAmWmState.computeState(new WaitForValidActivityState(TEST_ACTIVITY_NAME));
+            mAmWmState.computeState(TEST_ACTIVITY);
             assertFalse("Restricted activity must not be launched",
-                    mAmWmState.getAmState().containsActivity(
-                            getActivityComponentName(TEST_ACTIVITY_NAME)));
+                    mAmWmState.getAmState().containsActivity(TEST_ACTIVITY));
         }
     }
 
@@ -347,7 +354,7 @@
                     .setTargetActivity(TEST_ACTIVITY)
                     .execute();
 
-            mAmWmState.waitForValidState(TEST_ACTIVITY_NAME);
+            mAmWmState.waitForValidState(TEST_ACTIVITY);
 
             final int externalFocusedStackId = mAmWmState.getAmState().getFocusedStackId();
             final ActivityManagerState.ActivityStack focusedStack =
@@ -356,7 +363,7 @@
                     focusedStack.mDisplayId);
 
             mAmWmState.assertFocusedActivity("Focus must be on newly launched app",
-                    TEST_ACTIVITY_NAME);
+                    TEST_ACTIVITY);
             assertEquals("Activity launched by owner must be on external display",
                     externalFocusedStackId, mAmWmState.getAmState().getFocusedStackId());
         }
@@ -375,16 +382,16 @@
             final ActivityDisplay newDisplay = virtualDisplaySession.createDisplay();
 
             // Launch activity on new secondary display.
-            launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mId);
-            mAmWmState.computeState(new WaitForValidActivityState(TEST_ACTIVITY_NAME));
+            launchActivityOnDisplay(TEST_ACTIVITY, newDisplay.mId);
+            mAmWmState.computeState(TEST_ACTIVITY);
 
             mAmWmState.assertFocusedActivity(
                     "Activity launched on secondary display must be focused",
-                    TEST_ACTIVITY_NAME);
+                    TEST_ACTIVITY);
 
             // Launch second activity without specifying display.
             launchActivity(LAUNCHING_ACTIVITY);
-            mAmWmState.computeState(new WaitForValidActivityState(LAUNCHING_ACTIVITY));
+            mAmWmState.computeState(LAUNCHING_ACTIVITY);
 
             // Check that activity is launched in focused stack on primary display.
             mAmWmState.assertFocusedActivity("Launched activity must be focused",
@@ -393,7 +400,7 @@
             final ActivityManagerState.ActivityStack frontStack
                     = mAmWmState.getAmState().getStackById(frontStackId);
             assertEquals("Launched activity must be resumed in front stack",
-                    getActivityComponentName(LAUNCHING_ACTIVITY), frontStack.mResumedActivity);
+                    getActivityName(LAUNCHING_ACTIVITY), frontStack.mResumedActivity);
             assertEquals("Front stack must be on primary display",
                     DEFAULT_DISPLAY_ID, frontStack.mDisplayId);
         }
@@ -421,17 +428,17 @@
                     LAUNCHING_ACTIVITY);
 
             // Launch second activity from app on secondary display without specifying display id.
-            getLaunchActivityBuilder().setTargetActivityName(TEST_ACTIVITY_NAME).execute();
-            mAmWmState.computeState(new WaitForValidActivityState(TEST_ACTIVITY_NAME));
+            getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY).execute();
+            mAmWmState.computeState(TEST_ACTIVITY);
 
             // Check that activity is launched in focused stack on external display.
             mAmWmState.assertFocusedActivity("Launched activity must be focused",
-                    TEST_ACTIVITY_NAME);
+                    TEST_ACTIVITY);
             final int frontStackId = mAmWmState.getAmState().getFrontStackId(newDisplay.mId);
             final ActivityManagerState.ActivityStack frontStack
                     = mAmWmState.getAmState().getStackById(frontStackId);
             assertEquals("Launched activity must be resumed in front stack",
-                    getActivityComponentName(TEST_ACTIVITY_NAME), frontStack.mResumedActivity);
+                    getActivityName(TEST_ACTIVITY), frontStack.mResumedActivity);
         }
     }
 
@@ -454,17 +461,17 @@
                     LAUNCHING_ACTIVITY);
 
             // Launch second activity from app on secondary display without specifying display id.
-            getLaunchActivityBuilder().setTargetActivityName(TEST_ACTIVITY_NAME).execute();
-            mAmWmState.computeState(TEST_ACTIVITY_NAME);
+            getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY).execute();
+            mAmWmState.computeState(TEST_ACTIVITY);
 
             // Check that activity is launched in focused stack on external display.
             mAmWmState.assertFocusedActivity("Launched activity must be focused",
-                    TEST_ACTIVITY_NAME);
+                    TEST_ACTIVITY);
             final int frontStackId = mAmWmState.getAmState().getFrontStackId(newDisplay.mId);
             final ActivityManagerState.ActivityStack frontStack = mAmWmState.getAmState()
                     .getStackById(frontStackId);
             assertEquals("Launched activity must be resumed in front stack",
-                    getActivityComponentName(TEST_ACTIVITY_NAME), frontStack.mResumedActivity);
+                    getActivityName(TEST_ACTIVITY), frontStack.mResumedActivity);
         }
     }
 
@@ -491,7 +498,7 @@
                     .setTargetActivity(SECOND_ACTIVITY)
                     .setDisplayId(newDisplay.mId)
                     .execute();
-            mAmWmState.computeState(TEST_ACTIVITY_NAME);
+            mAmWmState.computeState(TEST_ACTIVITY);
 
             // Check that activity is launched in focused stack on external display.
             mAmWmState.assertFocusedActivity("Launched activity must be focused", SECOND_ACTIVITY);
@@ -508,7 +515,7 @@
                     .setDisplayId(newDisplay.mId)
                     .setTargetActivity(THIRD_ACTIVITY)
                     .execute();
-            mAmWmState.waitForValidState(new WaitForValidActivityState(THIRD_ACTIVITY));
+            mAmWmState.waitForValidState(THIRD_ACTIVITY);
 
             // Check that activity is launched in focused stack on external display.
             mAmWmState.assertFocusedActivity("Launched activity must be focused", THIRD_ACTIVITY);
@@ -563,19 +570,19 @@
                     .createDisplay();
 
             // Launch activity on secondary display from the app on primary display.
-            getLaunchActivityBuilder().setTargetActivityName(TEST_ACTIVITY_NAME)
+            getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY)
                     .setDisplayId(newDisplay.mId).execute();
 
             // Check that activity is launched on external display.
-            mAmWmState.computeState(new WaitForValidActivityState(TEST_ACTIVITY_NAME));
+            mAmWmState.computeState(TEST_ACTIVITY);
             mAmWmState.assertFocusedActivity(
                     "Activity launched on secondary display must be focused",
-                    TEST_ACTIVITY_NAME);
+                    TEST_ACTIVITY);
             final int frontStackId = mAmWmState.getAmState().getFrontStackId(newDisplay.mId);
             final ActivityManagerState.ActivityStack frontStack =
                     mAmWmState.getAmState().getStackById(frontStackId);
             assertEquals("Launched activity must be resumed in front stack",
-                    getActivityComponentName(TEST_ACTIVITY_NAME), frontStack.mResumedActivity);
+                    getActivityName(TEST_ACTIVITY), frontStack.mResumedActivity);
         }
     }
 
@@ -595,16 +602,16 @@
             mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
 
             // Launch activity on new secondary display.
-            launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mId);
-            mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true /* visible */);
+            launchActivityOnDisplay(TEST_ACTIVITY, newDisplay.mId);
+            mAmWmState.assertVisibility(TEST_ACTIVITY, true /* visible */);
             mAmWmState.assertVisibility(VIRTUAL_DISPLAY_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(RESIZEABLE_ACTIVITY_NAME);
-            mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true /* visible */);
-            mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY_NAME, true /* visible */);
+            getLaunchActivityBuilder().setTargetActivity(RESIZEABLE_ACTIVITY).execute();
+            mAmWmState.waitForValidState(RESIZEABLE_ACTIVITY);
+            mAmWmState.assertVisibility(TEST_ACTIVITY, true /* visible */);
+            mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY, true /* visible */);
         }
     }
 
@@ -628,18 +635,18 @@
                     focusedStack.mDisplayId);
 
             // Launch activity on new secondary display.
-            launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mId);
+            launchActivityOnDisplay(TEST_ACTIVITY, newDisplay.mId);
             mAmWmState.assertFocusedActivity("Focus must be on secondary display",
-                    TEST_ACTIVITY_NAME);
+                    TEST_ACTIVITY);
             int focusedStackId = mAmWmState.getAmState().getFocusedStackId();
             focusedStack = mAmWmState.getAmState().getStackById(focusedStackId);
             assertEquals("Focused stack must be on secondary display",
                     newDisplay.mId, focusedStack.mDisplayId);
 
             // Move activity from secondary display to primary.
-            moveActivityToStack(TEST_ACTIVITY_NAME, defaultDisplayStackId);
+            moveActivityToStack(TEST_ACTIVITY, defaultDisplayStackId);
             mAmWmState.waitForFocusedStack(defaultDisplayStackId);
-            mAmWmState.assertFocusedActivity("Focus must be on moved activity", TEST_ACTIVITY_NAME);
+            mAmWmState.assertFocusedActivity("Focus must be on moved activity", TEST_ACTIVITY);
             focusedStackId = mAmWmState.getAmState().getFocusedStackId();
             focusedStack = mAmWmState.getAmState().getStackById(focusedStackId);
             assertEquals("Focus must return to primary display", DEFAULT_DISPLAY_ID,
@@ -676,7 +683,9 @@
         assumeTrue(supportsSplitScreenMultiWindow());
 
         // Setup split-screen.
-        launchActivitiesInSplitScreen(TEST_ACTIVITY_NAME, LAUNCHING_ACTIVITY);
+        launchActivitiesInSplitScreen(
+                getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY),
+                getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY));
         mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
 
         tryCreatingAndRemovingDisplayWithActivity(true /* splitScreen */,
@@ -720,9 +729,9 @@
             }
 
             // Launch activity on new secondary display.
-            launchActivityOnDisplay(RESIZEABLE_ACTIVITY_NAME, newDisplay.mId);
+            launchActivityOnDisplay(RESIZEABLE_ACTIVITY, newDisplay.mId);
             mAmWmState.assertFocusedActivity("Focus must be on secondary display",
-                    RESIZEABLE_ACTIVITY_NAME);
+                    RESIZEABLE_ACTIVITY);
             final int frontStackId = mAmWmState.getAmState().getFrontStackId(newDisplay.mId);
             mAmWmState.assertFocusedStack("Focus must be on secondary display", frontStackId);
 
@@ -731,20 +740,22 @@
         }
 
         mAmWmState.computeState(true);
-        assertActivityLifecycle(RESIZEABLE_ACTIVITY_NAME, false /* relaunched */, logSeparator);
-        mAmWmState.waitForValidState(RESIZEABLE_ACTIVITY_NAME, windowingMode,
-                ACTIVITY_TYPE_STANDARD);
+        assertActivityLifecycle(RESIZEABLE_ACTIVITY, false /* relaunched */, logSeparator);
+        mAmWmState.waitForValidState(new WaitForValidActivityState.Builder(RESIZEABLE_ACTIVITY)
+                .setWindowingMode(windowingMode)
+                .setActivityType(ACTIVITY_TYPE_STANDARD)
+                .build());
         mAmWmState.assertSanity();
         mAmWmState.assertValidBounds(true /* compareTaskAndStackBounds */);
 
         // Check if the focus is switched back to primary display.
-        mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY_NAME, true /* visible */);
+        mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY, true /* visible */);
         mAmWmState.assertFocusedStack(
                 "Default stack on primary display must be focused after display removed",
                 windowingMode, ACTIVITY_TYPE_STANDARD);
         mAmWmState.assertFocusedActivity(
                 "Focus must be switched back to activity on primary display",
-                RESIZEABLE_ACTIVITY_NAME);
+                RESIZEABLE_ACTIVITY);
     }
 
     /**
@@ -791,23 +802,23 @@
             // Create new virtual display.
             final ActivityDisplay newDisplay = virtualDisplaySession.createDisplay();
 
-            mAmWmState.computeState(new WaitForValidActivityState(VIRTUAL_DISPLAY_ACTIVITY));
+            mAmWmState.computeState(VIRTUAL_DISPLAY_ACTIVITY);
             mAmWmState.assertFocusedActivity("Focus must be switched back to primary display",
                     VIRTUAL_DISPLAY_ACTIVITY);
 
-            launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mId);
+            launchActivityOnDisplay(TEST_ACTIVITY, newDisplay.mId);
 
-            mAmWmState.computeState(new WaitForValidActivityState(TEST_ACTIVITY_NAME));
+            mAmWmState.computeState(TEST_ACTIVITY);
             mAmWmState.assertFocusedActivity(
                     "Activity launched on secondary display must be focused",
-                    TEST_ACTIVITY_NAME);
+                    TEST_ACTIVITY);
 
             final ReportedDisplayMetrics displayMetrics = getDisplayMetrics();
             final int width = displayMetrics.getSize().getWidth();
             final int height = displayMetrics.getSize().getHeight();
             executeShellCommand("input tap " + (width / 2) + " " + (height / 2));
 
-            mAmWmState.computeState(new WaitForValidActivityState(VIRTUAL_DISPLAY_ACTIVITY));
+            mAmWmState.computeState(VIRTUAL_DISPLAY_ACTIVITY);
             mAmWmState.assertFocusedActivity("Focus must be switched back to primary display",
                     VIRTUAL_DISPLAY_ACTIVITY);
         }
@@ -829,9 +840,9 @@
                     focusedStack.mDisplayId);
 
             // Launch activity on new secondary display.
-            launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mId);
+            launchActivityOnDisplay(TEST_ACTIVITY, newDisplay.mId);
             mAmWmState.assertFocusedActivity("Focus must be on secondary display",
-                    TEST_ACTIVITY_NAME);
+                    TEST_ACTIVITY);
             final int externalFocusedStackId = mAmWmState.getAmState().getFocusedStackId();
             focusedStack = mAmWmState.getAmState().getStackById(externalFocusedStackId);
             assertEquals("Focused stack must be on secondary display", newDisplay.mId,
@@ -843,7 +854,7 @@
                             + " --display " + newDisplay.mId;
             executeShellCommand(startCmd);
 
-            mAmWmState.waitForValidState(new WaitForValidActivityState(SECOND_ACTIVITY));
+            mAmWmState.waitForValidState(SECOND_ACTIVITY);
             mAmWmState.assertFocusedActivity(
                     "Focus must be on newly launched app", SECOND_ACTIVITY);
             assertEquals("Activity launched by system must be on external display",
@@ -864,7 +875,7 @@
                     + " --display " + newDisplay.mId;
             executeShellCommand(startCmd);
 
-            mAmWmState.waitForValidState(new WaitForValidActivityState(SECOND_ACTIVITY));
+            mAmWmState.waitForValidState(SECOND_ACTIVITY);
             mAmWmState.assertFocusedActivity(
                     "Focus must be on newly launched app", SECOND_ACTIVITY);
             final int externalFocusedStackId = mAmWmState.getAmState().getFocusedStackId();
@@ -882,7 +893,7 @@
                     .setTargetActivity(THIRD_ACTIVITY)
                     .execute();
 
-            mAmWmState.waitForValidState(new WaitForValidActivityState(THIRD_ACTIVITY));
+            mAmWmState.waitForValidState(THIRD_ACTIVITY);
             mAmWmState.assertFocusedActivity("Focus must be on newly launched app", THIRD_ACTIVITY);
             assertEquals("Activity launched by app on secondary display must be on that display",
                     externalFocusedStackId, mAmWmState.getAmState().getFocusedStackId());
@@ -897,14 +908,14 @@
                     .createDisplay();
 
             launchActivityOnDisplay(LAUNCHING_ACTIVITY, newDisplay.mId);
-            mAmWmState.computeState(new WaitForValidActivityState(LAUNCHING_ACTIVITY));
+            mAmWmState.computeState(LAUNCHING_ACTIVITY);
 
             // Check that the first activity is launched onto the secondary display
             final int frontStackId = mAmWmState.getAmState().getFrontStackId(newDisplay.mId);
             ActivityManagerState.ActivityStack frontStack = mAmWmState.getAmState().getStackById(
                     frontStackId);
             assertEquals("Activity launched on secondary display must be resumed",
-                    getActivityComponentName(LAUNCHING_ACTIVITY),
+                    getActivityName(LAUNCHING_ACTIVITY),
                     frontStack.mResumedActivity);
             mAmWmState.assertFocusedStack("Focus must be on secondary display", frontStackId);
 
@@ -942,7 +953,7 @@
                     + " --display " + newDisplay.mId;
             executeShellCommand(startCmd);
 
-            mAmWmState.waitForValidState(new WaitForValidActivityState(SECOND_ACTIVITY));
+            mAmWmState.waitForValidState(SECOND_ACTIVITY);
             mAmWmState.assertFocusedActivity(
                     "Focus must be on newly launched app", SECOND_ACTIVITY);
             final int externalFocusedStackId = mAmWmState.getAmState().getFocusedStackId();
@@ -958,9 +969,9 @@
                     .setDisplayId(newDisplay.mId)
                     .execute();
 
-            mAmWmState.waitForValidState(TEST_ACTIVITY_NAME);
+            mAmWmState.waitForValidState(TEST_ACTIVITY);
             mAmWmState.assertFocusedActivity("Focus must be on newly launched app",
-                    TEST_ACTIVITY_NAME);
+                    TEST_ACTIVITY);
             assertEquals("Activity launched by owner must be on external display",
                     externalFocusedStackId, mAmWmState.getAmState().getFocusedStackId());
         }
@@ -985,9 +996,9 @@
                     focusedStack.mDisplayId);
 
             // Launch activity on new secondary display.
-            launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mId);
+            launchActivityOnDisplay(TEST_ACTIVITY, newDisplay.mId);
             mAmWmState.assertFocusedActivity("Focus must be on secondary display",
-                    TEST_ACTIVITY_NAME);
+                    TEST_ACTIVITY);
             final int externalFocusedStackId = mAmWmState.getAmState().getFocusedStackId();
             focusedStack = mAmWmState.getAmState().getStackById(externalFocusedStackId);
             assertEquals("Focused stack must be on secondary display", newDisplay.mId,
@@ -1005,9 +1016,8 @@
 
             assertSecurityException("ActivityLauncher", logSeparator);
 
-            mAmWmState.waitForValidState(false /* compareTaskAndStackBounds */, componentName,
-                    new WaitForValidActivityState(TEST_ACTIVITY_NAME));
-            mAmWmState.assertFocusedActivity("Focus must be on first activity", TEST_ACTIVITY_NAME);
+            mAmWmState.waitForValidState(TEST_ACTIVITY);
+            mAmWmState.assertFocusedActivity("Focus must be on first activity", TEST_ACTIVITY);
             assertEquals("Focused stack must be on secondary display's stack",
                     externalFocusedStackId, mAmWmState.getAmState().getFocusedStackId());
         }
@@ -1015,26 +1025,22 @@
 
     private void assertSecurityException(String component, LogSeparator logSeparator)
             throws Exception {
-        int tries = 0;
-        boolean match = false;
         final Pattern pattern = Pattern.compile(".*SecurityException launching activity.*");
-        while (tries < 5 && !match) {
+        for (int retry = 1; retry <= 5; retry++) {
             String[] logs = getDeviceLogsForComponents(logSeparator, component);
             for (String line : logs) {
                 Matcher m = pattern.matcher(line);
                 if (m.matches()) {
-                    match = true;
-                    break;
+                    return;
                 }
             }
-            tries++;
+            logAlways("***Waiting for SecurityException for " + component + " ... retry=" + retry);
             try {
                 Thread.sleep(500);
             } catch (InterruptedException e) {
             }
         }
-
-        assertTrue("Expected exception not found", match);
+        fail("Expected exception for " + component + " not found");
     }
 
     /**
@@ -1069,45 +1075,41 @@
             mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
 
             // Launch activities on new secondary display.
-            launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mId);
-            mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true /* visible */);
+            launchActivityOnDisplay(TEST_ACTIVITY, newDisplay.mId);
+            mAmWmState.assertVisibility(TEST_ACTIVITY, true /* visible */);
             mAmWmState.assertFocusedActivity("Launched activity must be focused",
-                    TEST_ACTIVITY_NAME);
-            launchActivityOnDisplay(RESIZEABLE_ACTIVITY_NAME, newDisplay.mId);
-            mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY_NAME, true /* visible */);
+                    TEST_ACTIVITY);
+            launchActivityOnDisplay(RESIZEABLE_ACTIVITY, newDisplay.mId);
+            mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY, true /* visible */);
             mAmWmState.assertFocusedActivity("Launched activity must be focused",
-                    RESIZEABLE_ACTIVITY_NAME);
+                    RESIZEABLE_ACTIVITY);
 
             // Destroy the display and check if activities are removed from system.
             logSeparator = clearLogcat();
         }
 
-        final String activityName1 = getActivityComponentName(TEST_ACTIVITY_NAME);
-        final String activityName2 = getActivityComponentName(RESIZEABLE_ACTIVITY_NAME);
-        final String windowName1 = getActivityWindowName(TEST_ACTIVITY_NAME);
-        final String windowName2 = getActivityWindowName(RESIZEABLE_ACTIVITY_NAME);
         mAmWmState.waitForWithAmState(
-                (state) -> !state.containsActivity(activityName1)
-                        && !state.containsActivity(activityName2),
+                (state) -> !state.containsActivity(TEST_ACTIVITY)
+                        && !state.containsActivity(RESIZEABLE_ACTIVITY),
                 "Waiting for activity to be removed");
         mAmWmState.waitForWithWmState(
-                (state) -> !state.containsWindow(windowName1)
-                        && !state.containsWindow(windowName2),
+                (state) -> !state.containsWindow(getWindowName(TEST_ACTIVITY))
+                        && !state.containsWindow(getWindowName(RESIZEABLE_ACTIVITY)),
                 "Waiting for activity window to be gone");
 
         // Check AM state.
         assertFalse("Activity from removed display must be destroyed",
-                mAmWmState.getAmState().containsActivity(activityName1));
+                mAmWmState.getAmState().containsActivity(TEST_ACTIVITY));
         assertFalse("Activity from removed display must be destroyed",
-                mAmWmState.getAmState().containsActivity(activityName2));
+                mAmWmState.getAmState().containsActivity(RESIZEABLE_ACTIVITY));
         // Check WM state.
         assertFalse("Activity windows from removed display must be destroyed",
-                mAmWmState.getWmState().containsWindow(windowName1));
+                mAmWmState.getWmState().containsWindow(getWindowName(TEST_ACTIVITY)));
         assertFalse("Activity windows from removed display must be destroyed",
-                mAmWmState.getWmState().containsWindow(windowName2));
+                mAmWmState.getWmState().containsWindow(getWindowName(RESIZEABLE_ACTIVITY)));
         // Check activity logs.
-        assertActivityDestroyed(TEST_ACTIVITY_NAME, logSeparator);
-        assertActivityDestroyed(RESIZEABLE_ACTIVITY_NAME, logSeparator);
+        assertActivityDestroyed(TEST_ACTIVITY, logSeparator);
+        assertActivityDestroyed(RESIZEABLE_ACTIVITY, logSeparator);
     }
 
     /**
@@ -1123,15 +1125,14 @@
 
             // Launch a resizeable activity on new secondary display.
             final LogSeparator initialLogSeparator = clearLogcat();
-            launchActivityOnDisplay(RESIZEABLE_ACTIVITY_NAME, newDisplay.mId);
-            mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY_NAME, true /* visible */);
+            launchActivityOnDisplay(RESIZEABLE_ACTIVITY, newDisplay.mId);
+            mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY, true /* visible */);
             mAmWmState.assertFocusedActivity("Launched activity must be focused",
-                    RESIZEABLE_ACTIVITY_NAME);
+                    RESIZEABLE_ACTIVITY);
 
             // Grab reported sizes and compute new with slight size change.
             final ReportedSizes initialSize = getLastReportedSizesForActivity(
-                    RESIZEABLE_ACTIVITY_NAME,
-                    initialLogSeparator);
+                    RESIZEABLE_ACTIVITY, initialLogSeparator);
 
             // Resize the docked stack, so that activity with virtual display will also be resized.
             final LogSeparator logSeparator = clearLogcat();
@@ -1139,8 +1140,8 @@
 
             mAmWmState.waitForWithAmState(amState -> {
                 try {
-                    return readConfigChangeNumber(RESIZEABLE_ACTIVITY_NAME, logSeparator) == 1
-                            && amState.hasActivityState(RESIZEABLE_ACTIVITY_NAME, STATE_RESUMED);
+                    return readConfigChangeNumber(RESIZEABLE_ACTIVITY, logSeparator) == 1
+                            && amState.hasActivityState(RESIZEABLE_ACTIVITY, STATE_RESUMED);
                 } catch (Exception e) {
                     logE("Error waiting for valid state: " + e.getMessage());
                     return false;
@@ -1148,18 +1149,17 @@
             }, "Wait for the configuration change to happen and for activity to be resumed.");
 
             mAmWmState.computeState(false /* compareTaskAndStackBounds */,
-                    new WaitForValidActivityState(RESIZEABLE_ACTIVITY_NAME),
+                    new WaitForValidActivityState(RESIZEABLE_ACTIVITY),
                     new WaitForValidActivityState(VIRTUAL_DISPLAY_ACTIVITY));
             mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true);
-            mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY_NAME, true);
+            mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY, true);
 
             // Check if activity in virtual display was resized properly.
-            assertRelaunchOrConfigChanged(RESIZEABLE_ACTIVITY_NAME, 0 /* numRelaunch */,
+            assertRelaunchOrConfigChanged(RESIZEABLE_ACTIVITY, 0 /* numRelaunch */,
                     1 /* numConfigChange */, logSeparator);
 
             final ReportedSizes updatedSize = getLastReportedSizesForActivity(
-                    RESIZEABLE_ACTIVITY_NAME,
-                    logSeparator);
+                    RESIZEABLE_ACTIVITY, logSeparator);
             assertTrue(updatedSize.widthDp <= initialSize.widthDp);
             assertTrue(updatedSize.heightDp <= initialSize.heightDp);
             assertTrue(updatedSize.displayWidth == initialSize.displayWidth / 2);
@@ -1168,7 +1168,7 @@
     }
 
     /** Read the number of configuration changes sent to activity from logs. */
-    private int readConfigChangeNumber(String activityName, LogSeparator logSeparator)
+    private int readConfigChangeNumber(ComponentName activityName, LogSeparator logSeparator)
             throws Exception {
         return (new ActivityLifecycleCounts(activityName, logSeparator)).mConfigurationChangedCount;
     }
@@ -1188,8 +1188,8 @@
             mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
             // Launch something to that display so that a new stack is created. We need this to be
             // able to compare task numbers in stacks later.
-            launchActivityOnDisplay(RESIZEABLE_ACTIVITY_NAME, newDisplay.mId);
-            mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY_NAME, true /* visible */);
+            launchActivityOnDisplay(RESIZEABLE_ACTIVITY, newDisplay.mId);
+            mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY, true /* visible */);
 
             final int stackNum = mAmWmState.getAmState().getDisplay(DEFAULT_DISPLAY_ID)
                     .mStacks.size();
@@ -1202,8 +1202,7 @@
             // {@link Intent#FLAG_ACTIVITY_NEW_TASK} and {@link Intent#FLAG_ACTIVITY_MULTIPLE_TASK}
             // when launching on some specific display. We don't do it here as we want an existing
             // task to be used.
-            final String launchCommand = "am start -n " + getActivityComponentName(
-                    LAUNCHING_ACTIVITY)
+            final String launchCommand = "am start -n " + getActivityName(LAUNCHING_ACTIVITY)
                     + " --display " + newDisplay.mId;
             executeShellCommand(launchCommand);
             mAmWmState.waitForActivityState(LAUNCHING_ACTIVITY, STATE_RESUMED);
@@ -1211,13 +1210,14 @@
             // Check that activity is brought to front.
             mAmWmState.assertFocusedActivity("Existing task must be brought to front",
                     LAUNCHING_ACTIVITY);
-            mAmWmState.assertResumedActivity("Existing task must be resumed", LAUNCHING_ACTIVITY);
+            mAmWmState.assertResumedActivity("Existing task must be resumed",
+                    LAUNCHING_ACTIVITY);
 
             // Check that activity is on the right display.
             final ActivityManagerState.ActivityStack firstFrontStack =
                     mAmWmState.getAmState().getStackById(frontStackId);
             assertEquals("Activity must be moved to the secondary display",
-                    getActivityComponentName(LAUNCHING_ACTIVITY), firstFrontStack.mResumedActivity);
+                    getActivityName(LAUNCHING_ACTIVITY), firstFrontStack.mResumedActivity);
             mAmWmState.assertFocusedStack("Focus must be on secondary display", frontStackId);
 
             // Check that task has moved from primary display to secondary.
@@ -1254,8 +1254,7 @@
             // {@link Intent#FLAG_ACTIVITY_NEW_TASK} and {@link Intent#FLAG_ACTIVITY_MULTIPLE_TASK}
             // when launching on some specific display. We don't do it here as we want an existing
             // task to be used.
-            final String launchCommand = "am start -n " + getActivityComponentName(
-                    LAUNCHING_ACTIVITY)
+            final String launchCommand = "am start -n " + getActivityName(LAUNCHING_ACTIVITY)
                     + " --display " + newDisplay.mId;
             executeShellCommand(launchCommand);
             mAmWmState.waitForActivityState(LAUNCHING_ACTIVITY, STATE_RESUMED);
@@ -1263,14 +1262,15 @@
             // Check that activity is brought to front.
             mAmWmState.assertFocusedActivity("Existing task must be brought to front",
                     LAUNCHING_ACTIVITY);
-            mAmWmState.assertResumedActivity("Existing task must be resumed", LAUNCHING_ACTIVITY);
+            mAmWmState.assertResumedActivity("Existing task must be resumed",
+                    LAUNCHING_ACTIVITY);
 
             // Check that activity is on the right display.
             final int frontStackId = mAmWmState.getAmState().getFrontStackId(newDisplay.mId);
             final ActivityManagerState.ActivityStack firstFrontStack =
                     mAmWmState.getAmState().getStackById(frontStackId);
             assertEquals("Activity must be moved to the secondary display",
-                    getActivityComponentName(LAUNCHING_ACTIVITY), firstFrontStack.mResumedActivity);
+                    getActivityName(LAUNCHING_ACTIVITY), firstFrontStack.mResumedActivity);
             mAmWmState.assertFocusedStack("Focus must be on secondary display", frontStackId);
 
             // Check that task has moved from primary display to secondary.
@@ -1294,30 +1294,30 @@
 
             // Launch activity on new secondary display.
             LogSeparator logSeparator = clearLogcat();
-            launchActivityOnDisplay(RESIZEABLE_ACTIVITY_NAME, newDisplay.mId);
+            launchActivityOnDisplay(RESIZEABLE_ACTIVITY, newDisplay.mId);
             mAmWmState.assertFocusedActivity("Focus must be on secondary display",
-                    RESIZEABLE_ACTIVITY_NAME);
+                    RESIZEABLE_ACTIVITY);
             final ReportedSizes initialSizes = getLastReportedSizesForActivity(
-                    RESIZEABLE_ACTIVITY_NAME, logSeparator);
+                    RESIZEABLE_ACTIVITY, logSeparator);
             assertNotNull("Test activity must have reported initial sizes on launch", initialSizes);
 
             try (final RotationSession rotationSession = new RotationSession()) {
                 // Rotate primary display and check that activity on secondary display is not
                 // affected.
 
-                rotateAndCheckSameSizes(rotationSession, RESIZEABLE_ACTIVITY_NAME);
+                rotateAndCheckSameSizes(rotationSession, RESIZEABLE_ACTIVITY);
 
                 // Launch activity to secondary display when primary one is rotated.
                 final int initialRotation = mAmWmState.getWmState().getRotation();
                 rotationSession.set((initialRotation + 1) % 4);
 
                 logSeparator = clearLogcat();
-                launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mId);
-                mAmWmState.waitForActivityState(TEST_ACTIVITY_NAME, STATE_RESUMED);
+                launchActivityOnDisplay(TEST_ACTIVITY, newDisplay.mId);
+                mAmWmState.waitForActivityState(TEST_ACTIVITY, STATE_RESUMED);
                 mAmWmState.assertFocusedActivity("Focus must be on secondary display",
-                        TEST_ACTIVITY_NAME);
+                        TEST_ACTIVITY);
                 final ReportedSizes testActivitySizes = getLastReportedSizesForActivity(
-                        TEST_ACTIVITY_NAME, logSeparator);
+                        TEST_ACTIVITY, logSeparator);
                 assertEquals(
                         "Sizes of secondary display must not change after rotation of primary "
                                 + "display",
@@ -1326,8 +1326,8 @@
         }
     }
 
-    private void rotateAndCheckSameSizes(RotationSession rotationSession, String activityName)
-            throws Exception {
+    private void rotateAndCheckSameSizes(
+            RotationSession rotationSession, ComponentName activityName) throws Exception {
         for (int rotation = 3; rotation >= 0; --rotation) {
             final LogSeparator logSeparator = clearLogcat();
             rotationSession.set(rotation);
@@ -1347,17 +1347,17 @@
             final ActivityDisplay newDisplay = virtualDisplaySession.createDisplay();
 
             launchActivityOnDisplay(LAUNCHING_ACTIVITY, newDisplay.mId);
-            mAmWmState.computeState(new WaitForValidActivityState(LAUNCHING_ACTIVITY));
+            mAmWmState.computeState(LAUNCHING_ACTIVITY);
 
             // Check that activity is on the secondary display.
             final int frontStackId = mAmWmState.getAmState().getFrontStackId(newDisplay.mId);
             final ActivityManagerState.ActivityStack firstFrontStack =
                     mAmWmState.getAmState().getStackById(frontStackId);
             assertEquals("Activity launched on secondary display must be resumed",
-                    getActivityComponentName(LAUNCHING_ACTIVITY), firstFrontStack.mResumedActivity);
+                    getActivityName(LAUNCHING_ACTIVITY), firstFrontStack.mResumedActivity);
             mAmWmState.assertFocusedStack("Focus must be on secondary display", frontStackId);
 
-            executeShellCommand("am start -n " + getActivityComponentName(ALT_LAUNCHING_ACTIVITY));
+            executeShellCommand("am start -n " + getActivityName(ALT_LAUNCHING_ACTIVITY));
             mAmWmState.waitForValidState(false /* compareTaskAndStackBounds */, componentName,
                     new WaitForValidActivityState(ALT_LAUNCHING_ACTIVITY));
 
@@ -1368,12 +1368,12 @@
             final ActivityManagerState.ActivityStack defaultDisplayFrontStack =
                     mAmWmState.getAmState().getStackById(defaultDisplayFrontStackId);
             assertEquals("Activity launched on default display must be resumed",
-                    getActivityComponentName(ALT_LAUNCHING_ACTIVITY),
+                    getActivityName(ALT_LAUNCHING_ACTIVITY),
                     defaultDisplayFrontStack.mResumedActivity);
             mAmWmState.assertFocusedStack("Focus must be on primary display",
                     defaultDisplayFrontStackId);
 
-            executeShellCommand("am start -n " + getActivityComponentName(LAUNCHING_ACTIVITY));
+            executeShellCommand("am start -n " + getActivityName(LAUNCHING_ACTIVITY));
             mAmWmState.waitForFocusedStack(frontStackId);
 
             // Check that the third intent is redirected to the first task due to the root
@@ -1381,7 +1381,7 @@
             final ActivityManagerState.ActivityStack secondFrontStack
                     = mAmWmState.getAmState().getStackById(frontStackId);
             assertEquals("Activity launched on secondary display must be resumed",
-                    getActivityComponentName(LAUNCHING_ACTIVITY),
+                    getActivityName(LAUNCHING_ACTIVITY),
                     secondFrontStack.mResumedActivity);
             mAmWmState.assertFocusedStack("Focus must be on primary display", frontStackId);
             assertEquals("Focused stack must only contain 1 task",
@@ -1406,15 +1406,14 @@
             final ActivityManagerState.ActivityStack firstFrontStack =
                     mAmWmState.getAmState().getStackById(frontStackId);
             assertEquals("Activity launched on secondary display must be resumed",
-                    getActivityComponentName(LAUNCHING_ACTIVITY), firstFrontStack.mResumedActivity);
+                    getActivityName(LAUNCHING_ACTIVITY), firstFrontStack.mResumedActivity);
             mAmWmState.assertFocusedStack("Focus must be on secondary display", frontStackId);
 
             // We don't want FLAG_ACTIVITY_MULTIPLE_TASK, so we can't use launchActivityOnDisplay
-            executeShellCommand("am start -n "
-                    + getActivityComponentName(ALT_LAUNCHING_ACTIVITY)
+            executeShellCommand("am start -n " + getActivityName(ALT_LAUNCHING_ACTIVITY)
                     + " -f 0x10000000" // FLAG_ACTIVITY_NEW_TASK
                     + " --display " + newDisplay.mId);
-            mAmWmState.computeState(new WaitForValidActivityState(ALT_LAUNCHING_ACTIVITY));
+            mAmWmState.computeState(ALT_LAUNCHING_ACTIVITY);
 
             // Check that second activity gets launched into the affinity matching
             // task on the secondary display
@@ -1423,7 +1422,7 @@
             final ActivityManagerState.ActivityStack secondFrontStack =
                     mAmWmState.getAmState().getStackById(secondFrontStackId);
             assertEquals("Activity launched on secondary display must be resumed",
-                    getActivityComponentName(ALT_LAUNCHING_ACTIVITY),
+                    getActivityName(ALT_LAUNCHING_ACTIVITY),
                     secondFrontStack.mResumedActivity);
             mAmWmState.assertFocusedStack("Focus must be on secondary display",
                     secondFrontStackId);
@@ -1445,32 +1444,32 @@
                     .createDisplay();
 
             launchActivityOnDisplay(BROADCAST_RECEIVER_ACTIVITY, newDisplay.mId);
-            mAmWmState.computeState(new WaitForValidActivityState(BROADCAST_RECEIVER_ACTIVITY));
+            mAmWmState.computeState(BROADCAST_RECEIVER_ACTIVITY);
 
             // Check that the first activity is launched onto the secondary display
             final int frontStackId = mAmWmState.getAmState().getFrontStackId(newDisplay.mId);
             final ActivityManagerState.ActivityStack firstFrontStack =
                     mAmWmState.getAmState().getStackById(frontStackId);
             assertEquals("Activity launched on secondary display must be resumed",
-                    getActivityComponentName(BROADCAST_RECEIVER_ACTIVITY),
+                    getActivityName(BROADCAST_RECEIVER_ACTIVITY),
                     firstFrontStack.mResumedActivity);
             mAmWmState.assertFocusedStack("Focus must be on secondary display", frontStackId);
 
-            executeShellCommand("am start -n " + getActivityComponentName(TEST_ACTIVITY_NAME));
-            mAmWmState.waitForValidState(false /* compareTaskAndStackBounds */, componentName,
-                    new WaitForValidActivityState(TEST_ACTIVITY_NAME));
+            executeShellCommand("am start -n " + getActivityName(TEST_ACTIVITY));
+            mAmWmState.waitForValidState(TEST_ACTIVITY);
 
             // 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), focusedStack.mResumedActivity);
+                    getActivityName(TEST_ACTIVITY), 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);
+            executeShellCommand("am broadcast -a trigger_broadcast --ez " + KEY_LAUNCH_ACTIVITY
+                    + " true --ez " + KEY_NEW_TASK + " true --es " + KEY_TARGET_ACTIVITY + " "
+                    + LAUNCHING_ACTIVITY);
 
             // Check that the third activity ends up in a new task in the same stack as the
             // first activity
@@ -1480,7 +1479,7 @@
             final ActivityManagerState.ActivityStack secondFrontStack =
                     mAmWmState.getAmState().getStackById(frontStackId);
             assertEquals("Activity must be launched on secondary display",
-                    getActivityComponentName(LAUNCHING_ACTIVITY),
+                    getActivityName(LAUNCHING_ACTIVITY),
                     secondFrontStack.mResumedActivity);
             assertEquals("Secondary display must contain 2 tasks",
                     2, secondFrontStack.getTasks().size());
@@ -1495,18 +1494,18 @@
         try (final VirtualDisplaySession virtualDisplaySession = new VirtualDisplaySession()) {
             // Create new virtual display and immediately launch an activity on it.
             final ActivityDisplay newDisplay = virtualDisplaySession
-                    .setLaunchActivity(TEST_ACTIVITY_NAME)
+                    .setLaunchActivity(TEST_ACTIVITY)
                     .createDisplay();
 
             // Check that activity is launched and placed correctly.
-            mAmWmState.waitForActivityState(TEST_ACTIVITY_NAME, STATE_RESUMED);
+            mAmWmState.waitForActivityState(TEST_ACTIVITY, STATE_RESUMED);
             mAmWmState.assertResumedActivity("Test activity must be launched on a new display",
-                    TEST_ACTIVITY_NAME);
+                    TEST_ACTIVITY);
             final int frontStackId = mAmWmState.getAmState().getFrontStackId(newDisplay.mId);
             final ActivityManagerState.ActivityStack firstFrontStack =
                     mAmWmState.getAmState().getStackById(frontStackId);
             assertEquals("Activity launched on secondary display must be resumed",
-                    getActivityComponentName(TEST_ACTIVITY_NAME), firstFrontStack.mResumedActivity);
+                    getActivityName(TEST_ACTIVITY), firstFrontStack.mResumedActivity);
             mAmWmState.assertFocusedStack("Focus must be on secondary display", frontStackId);
         }
     }
@@ -1518,8 +1517,8 @@
     @Test
     public void testExternalDisplayActivityTurnPrimaryOff() throws Exception {
         // Launch something on the primary display so we know there is a resumed activity there
-        launchActivity(RESIZEABLE_ACTIVITY_NAME);
-        waitAndAssertActivityResumed(RESIZEABLE_ACTIVITY_NAME, DEFAULT_DISPLAY_ID,
+        launchActivity(RESIZEABLE_ACTIVITY);
+        waitAndAssertActivityResumed(RESIZEABLE_ACTIVITY, DEFAULT_DISPLAY_ID,
                 "Activity launched on primary display must be resumed");
 
         try (final ExternalDisplaySession externalDisplaySession = new ExternalDisplaySession();
@@ -1528,19 +1527,19 @@
             final ActivityDisplay newDisplay =
                     externalDisplaySession.createVirtualDisplay(true /* showContentWhenLocked */);
 
-            launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mId);
+            launchActivityOnDisplay(TEST_ACTIVITY, newDisplay.mId);
 
             // Check that the activity is launched onto the external display
-            waitAndAssertActivityResumed(TEST_ACTIVITY_NAME, newDisplay.mId,
+            waitAndAssertActivityResumed(TEST_ACTIVITY, newDisplay.mId,
                     "Activity launched on external display must be resumed");
 
             displayStateSession.turnScreenOff();
 
             // Wait for the fullscreen stack to start sleeping, and then make sure the
             // test activity is still resumed.
-            waitAndAssertActivityStopped(RESIZEABLE_ACTIVITY_NAME,
+            waitAndAssertActivityStopped(RESIZEABLE_ACTIVITY,
                     "Activity launched on primary display must be stopped after turning off");
-            waitAndAssertActivityResumed(TEST_ACTIVITY_NAME, newDisplay.mId,
+            waitAndAssertActivityResumed(TEST_ACTIVITY, newDisplay.mId,
                     "Activity launched on external display must be resumed");
         }
     }
@@ -1552,8 +1551,8 @@
     @Test
     public void testLaunchExternalDisplayActivityWhilePrimaryOff() throws Exception {
         // Launch something on the primary display so we know there is a resumed activity there
-        launchActivity(RESIZEABLE_ACTIVITY_NAME);
-        waitAndAssertActivityResumed(RESIZEABLE_ACTIVITY_NAME, DEFAULT_DISPLAY_ID,
+        launchActivity(RESIZEABLE_ACTIVITY);
+        waitAndAssertActivityResumed(RESIZEABLE_ACTIVITY, DEFAULT_DISPLAY_ID,
                 "Activity launched on primary display must be resumed");
 
         try (final PrimaryDisplayStateSession displayStateSession =
@@ -1562,7 +1561,7 @@
             displayStateSession.turnScreenOff();
 
             // Make sure there is no resumed activity when the primary display is off
-            waitAndAssertActivityStopped(RESIZEABLE_ACTIVITY_NAME,
+            waitAndAssertActivityStopped(RESIZEABLE_ACTIVITY,
                     "Activity launched on primary display must be stopped after turning off");
             assertEquals("Unexpected resumed activity",
                     0, mAmWmState.getAmState().getResumedActivitiesCount());
@@ -1570,10 +1569,10 @@
             final ActivityDisplay newDisplay =
                     externalDisplaySession.createVirtualDisplay(true /* showContentWhenLocked */);
 
-            launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mId);
+            launchActivityOnDisplay(TEST_ACTIVITY, newDisplay.mId);
 
             // Check that the test activity is resumed on the external display
-            waitAndAssertActivityResumed(TEST_ACTIVITY_NAME, newDisplay.mId,
+            waitAndAssertActivityResumed(TEST_ACTIVITY, newDisplay.mId,
                     "Activity launched on external display must be resumed");
         }
     }
@@ -1587,22 +1586,22 @@
             final ActivityDisplay newDisplay =
                     externalDisplaySession.createVirtualDisplay(false /* showContentWhenLocked */);
 
-            launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mId);
+            launchActivityOnDisplay(TEST_ACTIVITY, newDisplay.mId);
 
             // Check that the test activity is resumed on the external display
-            waitAndAssertActivityResumed(TEST_ACTIVITY_NAME, newDisplay.mId,
+            waitAndAssertActivityResumed(TEST_ACTIVITY, newDisplay.mId,
                     "Activity launched on external display must be resumed");
 
             externalDisplaySession.turnDisplayOff();
 
             // Check that turning off the external display stops the activity
-            waitAndAssertActivityStopped(TEST_ACTIVITY_NAME,
+            waitAndAssertActivityStopped(TEST_ACTIVITY,
                     "Activity launched on external display must be stopped after turning off");
 
             externalDisplaySession.turnDisplayOn();
 
             // Check that turning on the external display resumes the activity
-            waitAndAssertActivityResumed(TEST_ACTIVITY_NAME, newDisplay.mId,
+            waitAndAssertActivityResumed(TEST_ACTIVITY, newDisplay.mId,
                     "Activity launched on external display must be resumed");
         }
     }
@@ -1614,8 +1613,8 @@
     @Test
     public void testStackFocusSwitchOnTouchEventAfterKeyguard() throws Exception {
         // Launch something on the primary display so we know there is a resumed activity there
-        launchActivity(RESIZEABLE_ACTIVITY_NAME);
-        waitAndAssertActivityResumed(RESIZEABLE_ACTIVITY_NAME, DEFAULT_DISPLAY_ID,
+        launchActivity(RESIZEABLE_ACTIVITY);
+        waitAndAssertActivityResumed(RESIZEABLE_ACTIVITY, DEFAULT_DISPLAY_ID,
                 "Activity launched on primary display must be resumed");
 
         try (final LockScreenSession lockScreenSession = new LockScreenSession();
@@ -1623,7 +1622,7 @@
             lockScreenSession.sleepDevice();
 
             // Make sure there is no resumed activity when the primary display is off
-            waitAndAssertActivityStopped(RESIZEABLE_ACTIVITY_NAME,
+            waitAndAssertActivityStopped(RESIZEABLE_ACTIVITY,
                     "Activity launched on primary display must be stopped after turning off");
             assertEquals("Unexpected resumed activity",
                     0, mAmWmState.getAmState().getResumedActivitiesCount());
@@ -1631,47 +1630,48 @@
             final ActivityDisplay newDisplay =
                     externalDisplaySession.createVirtualDisplay(true /* showContentWhenLocked */);
 
-            launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mId);
+            launchActivityOnDisplay(TEST_ACTIVITY, newDisplay.mId);
 
             // Check that the test activity is resumed on the external display
-            waitAndAssertActivityResumed(TEST_ACTIVITY_NAME, newDisplay.mId,
+            waitAndAssertActivityResumed(TEST_ACTIVITY, newDisplay.mId,
                     "Activity launched on external display must be resumed");
 
             // Unlock the device and tap on the middle of the primary display
             lockScreenSession.wakeUpDevice();
             executeShellCommand("wm dismiss-keyguard");
             mAmWmState.waitForKeyguardGone();
-            mAmWmState.waitForValidState(new WaitForValidActivityState(TEST_ACTIVITY_NAME));
+            mAmWmState.waitForValidState(TEST_ACTIVITY);
             final ReportedDisplayMetrics displayMetrics = getDisplayMetrics();
             final int width = displayMetrics.getSize().getWidth();
             final int height = displayMetrics.getSize().getHeight();
             executeShellCommand("input tap " + (width / 2) + " " + (height / 2));
 
             // Check that the activity on the primary display is resumed
-            waitAndAssertActivityResumed(RESIZEABLE_ACTIVITY_NAME, DEFAULT_DISPLAY_ID,
+            waitAndAssertActivityResumed(RESIZEABLE_ACTIVITY, DEFAULT_DISPLAY_ID,
                     "Activity launched on primary display must be resumed");
             assertEquals("Unexpected resumed activity",
                     1, mAmWmState.getAmState().getResumedActivitiesCount());
         }
     }
 
-    private void waitAndAssertActivityResumed(String activityName, int displayId, String message)
-            throws Exception {
+    private void waitAndAssertActivityResumed(
+            ComponentName activityName, int displayId, String message) throws Exception {
         mAmWmState.waitForActivityState(activityName, STATE_RESUMED);
 
-        final String fullActivityName = getActivityComponentName(activityName);
-        assertEquals(message, fullActivityName, mAmWmState.getAmState().getResumedActivity());
+        assertEquals(message,
+                getActivityName(activityName), mAmWmState.getAmState().getResumedActivity());
         final int frontStackId = mAmWmState.getAmState().getFrontStackId(displayId);
         ActivityManagerState.ActivityStack firstFrontStack =
                 mAmWmState.getAmState().getStackById(frontStackId);
-        assertEquals(message, fullActivityName, firstFrontStack.mResumedActivity);
+        assertEquals(message,
+                getActivityName(activityName), firstFrontStack.mResumedActivity);
         assertTrue(message,
                 mAmWmState.getAmState().hasActivityState(activityName, STATE_RESUMED));
         mAmWmState.assertFocusedStack("Focus must be on external display", frontStackId);
         mAmWmState.assertVisibility(activityName, true /* visible */);
     }
 
-    private void waitAndAssertActivityStopped(String activityName, String message)
+    private void waitAndAssertActivityStopped(ComponentName activityName, String message)
             throws Exception {
         mAmWmState.waitForActivityState(activityName, STATE_STOPPED);
 
@@ -1688,26 +1688,25 @@
              final LockScreenSession lockScreenSession = new LockScreenSession()) {
             lockScreenSession.setLockCredential();
 
-            launchActivity(TEST_ACTIVITY_NAME);
+            launchActivity(TEST_ACTIVITY);
 
             final ActivityDisplay newDisplay =
                     externalDisplaySession.createVirtualDisplay(false /* showContentWhenLocked */);
-            launchActivityOnDisplay(SHOW_WHEN_LOCKED_ATTR_ACTIVITY_NAME, newDisplay.mId);
+            launchActivityOnDisplay(SHOW_WHEN_LOCKED_ATTR_ACTIVITY, newDisplay.mId);
 
             lockScreenSession.gotoKeyguard();
-            mAmWmState.waitForKeyguardShowingAndNotOccluded();
 
-            mAmWmState.waitForActivityState(TEST_ACTIVITY_NAME, STATE_STOPPED);
-            mAmWmState.waitForActivityState(SHOW_WHEN_LOCKED_ATTR_ACTIVITY_NAME, STATE_RESUMED);
+            mAmWmState.waitForActivityState(TEST_ACTIVITY, STATE_STOPPED);
+            mAmWmState.waitForActivityState(SHOW_WHEN_LOCKED_ATTR_ACTIVITY, STATE_RESUMED);
 
-            mAmWmState.computeState(SHOW_WHEN_LOCKED_ATTR_ACTIVITY_NAME);
+            mAmWmState.computeState(SHOW_WHEN_LOCKED_ATTR_ACTIVITY);
             assertTrue("Expected resumed activity on secondary display", mAmWmState.getAmState()
-                    .hasActivityState(SHOW_WHEN_LOCKED_ATTR_ACTIVITY_NAME, STATE_RESUMED));
+                    .hasActivityState(SHOW_WHEN_LOCKED_ATTR_ACTIVITY, STATE_RESUMED));
         }
     }
 
     /** Assert that component received onMovedToDisplay and onConfigurationChanged callbacks. */
-    private void assertMovedToDisplay(String componentName, LogSeparator logSeparator)
+    private void assertMovedToDisplay(ComponentName componentName, LogSeparator logSeparator)
             throws Exception {
         final ActivityLifecycleCounts lifecycleCounts
                 = new ActivityLifecycleCounts(componentName, logSeparator);
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerPinnedStackTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerPinnedStackTests.java
index 7a28d9a..6a2f9ee 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerPinnedStackTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerPinnedStackTests.java
@@ -27,7 +27,7 @@
 import static android.server.am.ActivityManagerState.STATE_RESUMED;
 import static android.server.am.ActivityManagerState.STATE_STOPPED;
 import static android.server.am.Components.TestActivity.TEST_ACTIVITY_ACTION_FINISH_SELF;
-import static android.view.KeyEvent.KEYCODE_WINDOW;
+import static android.server.am.UiDeviceUtils.pressWindowButton;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -1036,29 +1036,29 @@
 
         launchActivity(PIP_ACTIVITY, EXTRA_ENTER_PIP, "true");
         launchActivitiesInSplitScreen(
-                getLaunchActivityBuilder().setTargetActivityName(LAUNCHING_ACTIVITY),
+                getLaunchActivityBuilder().setTargetActivityName(LAUNCHING_ACTIVITY_NAME),
                 getLaunchActivityBuilder().setTargetActivityName(TEST_ACTIVITY).setRandomData(true)
                         .setMultipleTask(false)
         );
         mAmWmState.assertVisibility(PIP_ACTIVITY, true);
-        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true);
+        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY_NAME, true);
         mAmWmState.assertVisibility(TEST_ACTIVITY, true);
 
         // Launch the activities again to take focus and make sure nothing is hidden
         launchActivitiesInSplitScreen(
-                getLaunchActivityBuilder().setTargetActivityName(LAUNCHING_ACTIVITY),
+                getLaunchActivityBuilder().setTargetActivityName(LAUNCHING_ACTIVITY_NAME),
                 getLaunchActivityBuilder().setTargetActivityName(TEST_ACTIVITY).setRandomData(true)
                         .setMultipleTask(false)
         );
-        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true);
+        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY_NAME, true);
         mAmWmState.assertVisibility(TEST_ACTIVITY, true);
 
         // Go to recents to make sure that fullscreen stack is invisible
         // Some devices do not support recents or implement it differently (instead of using a
         // separate stack id or as an activity), for those cases the visibility asserts will be
         // ignored
-        pressAppSwitchButton();
-        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true);
+        pressAppSwitchButtonAndWaitForRecents();
+        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY_NAME, true);
         mAmWmState.assertVisibility(TEST_ACTIVITY, false);
     }
 
@@ -1493,13 +1493,6 @@
     }
 
     /**
-     * Triggers the window keycode.
-     */
-    private void pressWindowButton() throws Exception {
-        mDevice.pressKeyCode(KEYCODE_WINDOW);
-    }
-
-    /**
      * TODO: Improve tests check to actually check that apps are not interactive instead of checking
      *       if the stack is focused.
      */
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerReplaceWindowTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerReplaceWindowTests.java
index 233bad6..0ef9364 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerReplaceWindowTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerReplaceWindowTests.java
@@ -17,17 +17,23 @@
 package android.server.am;
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.server.am.ComponentNameUtils.getWindowName;
+import static android.server.am.Components.NO_RELAUNCH_ACTIVITY;
+import static android.server.am.Components.SLOW_CREATE_ACTIVITY;
 import static android.server.am.StateLogger.log;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assume.assumeTrue;
 
-import junit.framework.Assert;
+import android.content.ComponentName;
+import android.os.SystemClock;
 
 import org.junit.Before;
 import org.junit.Test;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Build/Install/Run:
@@ -35,11 +41,6 @@
  */
 public class ActivityManagerReplaceWindowTests extends ActivityManagerTestBase {
 
-    private static final String SLOW_CREATE_ACTIVITY_NAME = "SlowCreateActivity";
-    private static final String NO_RELAUNCH_ACTIVITY_NAME = "NoRelaunchActivity";
-
-    private List<String> mTempWindowTokens = new ArrayList();
-
     @Before
     @Override
     public void setUp() throws Exception {
@@ -59,20 +60,18 @@
     }
 
     private void testReplaceWindow_Dock(boolean relaunch) throws Exception {
-        final String activityName =
-                relaunch ? SLOW_CREATE_ACTIVITY_NAME : NO_RELAUNCH_ACTIVITY_NAME;
-        final String windowName = getActivityWindowName(activityName);
+        final ComponentName activityName = relaunch ? SLOW_CREATE_ACTIVITY : NO_RELAUNCH_ACTIVITY;
+        final String windowName = getWindowName(activityName);
         final String amStartCmd = getAmStartCmd(activityName);
 
         executeShellCommand(amStartCmd);
 
-        // Sleep 2 seconds, then check if the window is started properly.
-        // SlowCreateActivity will do a sleep inside its onCreate() to simulate a
-        // slow-starting app. So instead of relying on WindowManagerState's
-        // retrying mechanism, we do an explicit sleep to avoid excess spews
-        // from WindowManagerState.
-        if (SLOW_CREATE_ACTIVITY_NAME.equals(activityName)) {
-            Thread.sleep(2000);
+        // Sleep 2 seconds, then check if the window is started properly. SlowCreateActivity
+        // will do a sleep inside its onCreate() to simulate a slow-starting app. So instead of
+        // relying on WindowManagerState's retrying mechanism, we do an explicit sleep to avoid
+        // excess spews from WindowManagerState.
+        if (relaunch) {
+            SystemClock.sleep(TimeUnit.SECONDS.toMillis(2));
         }
 
         log("==========Before Docking========");
@@ -82,26 +81,26 @@
         setActivityTaskWindowingMode(activityName, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
 
         // Sleep 5 seconds, then check if the window is replaced properly.
-        Thread.sleep(5000);
+        SystemClock.sleep(TimeUnit.SECONDS.toMillis(5));
 
         log("==========After Docking========");
         final String newToken = getWindowToken(windowName, activityName);
 
         // For both relaunch and not relaunch case, we'd like the window to be kept.
-        Assert.assertEquals("Window replaced while docking.", oldToken, newToken);
+        assertEquals("Window replaced while docking.", oldToken, newToken);
     }
 
-    private String getWindowToken(String windowName, String activityName)
-            throws Exception {
-        mAmWmState.computeState(new WaitForValidActivityState.Builder(activityName).build());
+    private String getWindowToken(String windowName, ComponentName activityName) throws Exception {
+        mAmWmState.computeState(activityName);
 
         mAmWmState.assertVisibility(activityName, true);
 
-        mAmWmState.getWmState().getMatchingWindowTokens(windowName, mTempWindowTokens);
+        final List<String> windowTokens = new ArrayList<>();
+        mAmWmState.getWmState().getMatchingWindowTokens(windowName, windowTokens);
 
-        Assert.assertEquals("Should have exactly one window for the activity.",
-                1, mTempWindowTokens.size());
+        assertEquals("Should have exactly one window for the activity.",
+                1, windowTokens.size());
 
-        return mTempWindowTokens.get(0);
+        return windowTokens.get(0);
     }
 }
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java
index a3ab768..b8885ac 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java
@@ -26,20 +26,31 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.server.am.Components.DOCKED_ACTIVITY;
+import static android.server.am.Components.LAUNCHING_ACTIVITY;
+import static android.server.am.Components.NON_RESIZEABLE_ACTIVITY;
+import static android.server.am.Components.NO_RELAUNCH_ACTIVITY;
+import static android.server.am.Components.SINGLE_INSTANCE_ACTIVITY;
+import static android.server.am.Components.SINGLE_TASK_ACTIVITY;
+import static android.server.am.Components.TEST_ACTIVITY;
 import static android.server.am.Components.TestActivity.TEST_ACTIVITY_ACTION_FINISH_SELF;
+import static android.server.am.UiDeviceUtils.pressHomeButton;
 import static android.server.am.WindowManagerState.TRANSIT_WALLPAPER_OPEN;
 import static android.view.Surface.ROTATION_0;
 import static android.view.Surface.ROTATION_180;
 import static android.view.Surface.ROTATION_270;
 import static android.view.Surface.ROTATION_90;
 
+import static org.hamcrest.Matchers.lessThan;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
+import android.content.ComponentName;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 import android.support.test.filters.FlakyTest;
@@ -53,13 +64,6 @@
  */
 public class ActivityManagerSplitScreenTests extends ActivityManagerTestBase {
 
-    private static final String TEST_ACTIVITY_NAME = "TestActivity";
-    private static final String NON_RESIZEABLE_ACTIVITY_NAME = "NonResizeableActivity";
-    private static final String DOCKED_ACTIVITY_NAME = "DockedActivity";
-    private static final String NO_RELAUNCH_ACTIVITY_NAME = "NoRelaunchActivity";
-    private static final String SINGLE_INSTANCE_ACTIVITY_NAME = "SingleInstanceActivity";
-    private static final String SINGLE_TASK_ACTIVITY_NAME = "SingleTaskActivity";
-
     private static final int TASK_SIZE = 600;
     private static final int STACK_SIZE = 300;
 
@@ -83,8 +87,8 @@
     @Presubmit
     @FlakyTest(bugId = 71792393)
     public void testStackList() throws Exception {
-        launchActivity(TEST_ACTIVITY_NAME);
-        mAmWmState.computeState(new String[] {TEST_ACTIVITY_NAME});
+        launchActivity(TEST_ACTIVITY);
+        mAmWmState.computeState(TEST_ACTIVITY);
         mAmWmState.assertContainsStack("Must contain home stack.",
                 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME);
         mAmWmState.assertContainsStack("Must contain fullscreen stack.",
@@ -96,7 +100,7 @@
     @Test
     @Presubmit
     public void testDockActivity() throws Exception {
-        launchActivityInSplitScreenWithRecents(TEST_ACTIVITY_NAME);
+        launchActivityInSplitScreenWithRecents(TEST_ACTIVITY);
         mAmWmState.assertContainsStack("Must contain home stack.",
                 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME);
         mAmWmState.assertContainsStack("Must contain docked stack.",
@@ -106,7 +110,7 @@
     @Test
     @Presubmit
     public void testNonResizeableNotDocked() throws Exception {
-        launchActivityInSplitScreenWithRecents(NON_RESIZEABLE_ACTIVITY_NAME);
+        launchActivityInSplitScreenWithRecents(NON_RESIZEABLE_ACTIVITY);
 
         mAmWmState.assertContainsStack("Must contain home stack.",
                 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME);
@@ -119,7 +123,9 @@
     @Test
     @Presubmit
     public void testLaunchToSide() throws Exception {
-        launchActivitiesInSplitScreen(LAUNCHING_ACTIVITY, TEST_ACTIVITY_NAME);
+        launchActivitiesInSplitScreen(
+                getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
+                getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
         mAmWmState.assertContainsStack("Must contain fullscreen stack.",
                 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
         mAmWmState.assertContainsStack("Must contain docked stack.",
@@ -130,7 +136,9 @@
     @Presubmit
     public void testLaunchToSideMultiWindowCallbacks() throws Exception {
         // Launch two activities in split-screen mode.
-        launchActivitiesInSplitScreen(LAUNCHING_ACTIVITY, TEST_ACTIVITY_NAME);
+        launchActivitiesInSplitScreen(
+                getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
+                getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
         mAmWmState.assertContainsStack("Must contain fullscreen stack.",
                 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
         mAmWmState.assertContainsStack("Must contain docked stack.",
@@ -140,7 +148,7 @@
         final LogSeparator logSeparator = clearLogcat();
         removeStacksInWindowingModes(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
         final ActivityLifecycleCounts lifecycleCounts = waitForOnMultiWindowModeChanged(
-                TEST_ACTIVITY_NAME, logSeparator);
+                TEST_ACTIVITY, logSeparator);
         assertEquals(1, lifecycleCounts.mMultiWindowModeChangedCount);
     }
 
@@ -148,25 +156,25 @@
     @Presubmit
     @FlakyTest(bugId = 72956284)
     public void testNoUserLeaveHintOnMultiWindowModeChanged() throws Exception {
-        launchActivity(TEST_ACTIVITY_NAME, WINDOWING_MODE_FULLSCREEN);
+        launchActivity(TEST_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
 
         // Move to docked stack.
         LogSeparator logSeparator = clearLogcat();
-        setActivityTaskWindowingMode(TEST_ACTIVITY_NAME, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+        setActivityTaskWindowingMode(TEST_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
         ActivityLifecycleCounts lifecycleCounts = waitForOnMultiWindowModeChanged(
-                TEST_ACTIVITY_NAME, logSeparator);
+                TEST_ACTIVITY, logSeparator);
         assertEquals("mMultiWindowModeChangedCount",
                 1, lifecycleCounts.mMultiWindowModeChangedCount);
         assertEquals("mUserLeaveHintCount", 0, lifecycleCounts.mUserLeaveHintCount);
 
         // Make sure docked stack is focused. This way when we dismiss it later fullscreen stack
         // will come up.
-        launchActivity(TEST_ACTIVITY_NAME, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+        launchActivity(TEST_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
 
         // Move activity back to fullscreen stack.
         logSeparator = clearLogcat();
-        setActivityTaskWindowingMode(TEST_ACTIVITY_NAME, WINDOWING_MODE_FULLSCREEN);
-        lifecycleCounts = waitForOnMultiWindowModeChanged(TEST_ACTIVITY_NAME, logSeparator);
+        setActivityTaskWindowingMode(TEST_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
+        lifecycleCounts = waitForOnMultiWindowModeChanged(TEST_ACTIVITY, logSeparator);
         assertEquals("mMultiWindowModeChangedCount",
                 1, lifecycleCounts.mMultiWindowModeChangedCount);
         assertEquals("mUserLeaveHintCount", 0, lifecycleCounts.mUserLeaveHintCount);
@@ -175,26 +183,27 @@
     @Test
     @Presubmit
     public void testLaunchToSideAndBringToFront() throws Exception {
-        launchActivitiesInSplitScreen(LAUNCHING_ACTIVITY, TEST_ACTIVITY_NAME);
+        launchActivitiesInSplitScreen(
+                getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
+                getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
 
         int taskNumberInitial = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
                 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
         mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
-                TEST_ACTIVITY_NAME);
+                TEST_ACTIVITY);
 
         // Launch another activity to side to cover first one.
-        launchActivity(
-                NO_RELAUNCH_ACTIVITY_NAME, WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
+        launchActivity(NO_RELAUNCH_ACTIVITY, WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
         int taskNumberCovered = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
                 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
         assertEquals("Fullscreen stack must have one task added.",
                 taskNumberInitial + 1, taskNumberCovered);
         mAmWmState.assertFocusedActivity("Launched to side covering activity must be in front.",
-                NO_RELAUNCH_ACTIVITY_NAME);
+                NO_RELAUNCH_ACTIVITY);
 
         // Launch activity that was first launched to side. It should be brought to front.
         getLaunchActivityBuilder()
-                .setTargetActivityName(TEST_ACTIVITY_NAME)
+                .setTargetActivity(TEST_ACTIVITY)
                 .setToSide(true)
                 .setWaitForLaunched(true)
                 .execute();
@@ -203,58 +212,59 @@
         assertEquals("Task number in fullscreen stack must remain the same.",
                 taskNumberCovered, taskNumberFinal);
         mAmWmState.assertFocusedActivity("Launched to side covering activity must be in front.",
-                TEST_ACTIVITY_NAME);
+                TEST_ACTIVITY);
     }
 
     @Test
     @Presubmit
     @FlakyTest(bugId = 71792393)
     public void testLaunchToSideMultiple() throws Exception {
-        launchActivitiesInSplitScreen(LAUNCHING_ACTIVITY, TEST_ACTIVITY_NAME);
+        launchActivitiesInSplitScreen(
+                getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
+                getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
 
         int taskNumberInitial = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
                 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
         assertNotNull("Launched to side activity must be in fullscreen stack.",
-                mAmWmState.getAmState().getTaskByActivityName(
-                        TEST_ACTIVITY_NAME, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));
+                mAmWmState.getAmState().getTaskByActivity(
+                        TEST_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));
 
         // Try to launch to side same activity again.
         getLaunchActivityBuilder().setToSide(true).execute();
-        final String[] waitForActivitiesVisible =
-                new String[] {TEST_ACTIVITY_NAME, LAUNCHING_ACTIVITY};
-        mAmWmState.computeState(waitForActivitiesVisible);
+        mAmWmState.computeState(TEST_ACTIVITY, LAUNCHING_ACTIVITY);
         int taskNumberFinal = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
                 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
         assertEquals("Task number mustn't change.", taskNumberInitial, taskNumberFinal);
         mAmWmState.assertFocusedActivity("Launched to side activity must remain in front.",
-                TEST_ACTIVITY_NAME);
+                TEST_ACTIVITY);
         assertNotNull("Launched to side activity must remain in fullscreen stack.",
-                mAmWmState.getAmState().getTaskByActivityName(
-                        TEST_ACTIVITY_NAME, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));
+                mAmWmState.getAmState().getTaskByActivity(
+                        TEST_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));
     }
 
     @Test
     @Presubmit
+    @FlakyTest(bugId = 73808815)
     public void testLaunchToSideSingleInstance() throws Exception {
-        launchTargetToSide(SINGLE_INSTANCE_ACTIVITY_NAME, false);
+        launchTargetToSide(SINGLE_INSTANCE_ACTIVITY, false);
     }
 
     @Test
     public void testLaunchToSideSingleTask() throws Exception {
-        launchTargetToSide(SINGLE_TASK_ACTIVITY_NAME, false);
+        launchTargetToSide(SINGLE_TASK_ACTIVITY, false);
     }
 
     @Presubmit
     @FlakyTest(bugId = 71792393)
     @Test
     public void testLaunchToSideMultipleWithDifferentIntent() throws Exception {
-        launchTargetToSide(TEST_ACTIVITY_NAME, true);
+        launchTargetToSide(TEST_ACTIVITY, true);
     }
 
-    private void launchTargetToSide(String targetActivityName, boolean taskCountMustIncrement)
-            throws Exception {
+    private void launchTargetToSide(ComponentName targetActivityName,
+            boolean taskCountMustIncrement) throws Exception {
         final LaunchActivityBuilder targetActivityLauncher = getLaunchActivityBuilder()
-                .setTargetActivityName(targetActivityName)
+                .setTargetActivity(targetActivityName)
                 .setToSide(true)
                 .setRandomData(true)
                 .setMultipleTask(false);
@@ -263,27 +273,21 @@
         // the target being launched directly. Options such as LaunchActivityBuilder#setRandomData
         // are not respected.
         launchActivitiesInSplitScreen(
-                getLaunchActivityBuilder().setTargetActivityName(LAUNCHING_ACTIVITY),
+                getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
                 targetActivityLauncher);
 
-        final WaitForValidActivityState[] waitForActivitiesVisible =
-                new WaitForValidActivityState[] {
-                    new WaitForValidActivityState.Builder(targetActivityName).build(),
-                    new WaitForValidActivityState.Builder(LAUNCHING_ACTIVITY).build()
-                };
-
-        mAmWmState.computeState(waitForActivitiesVisible);
+        mAmWmState.computeState(targetActivityName, LAUNCHING_ACTIVITY);
         mAmWmState.assertContainsStack("Must contain fullscreen stack.",
                 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
         int taskNumberInitial = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
                 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
         assertNotNull("Launched to side activity must be in fullscreen stack.",
-                mAmWmState.getAmState().getTaskByActivityName(
+                mAmWmState.getAmState().getTaskByActivity(
                         targetActivityName, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));
 
         // Try to launch to side same activity again with different data.
         targetActivityLauncher.execute();
-        mAmWmState.computeState(waitForActivitiesVisible);
+        mAmWmState.computeState(targetActivityName, LAUNCHING_ACTIVITY);
         int taskNumberSecondLaunch = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
                 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
         if (taskCountMustIncrement) {
@@ -296,14 +300,14 @@
         mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
                 targetActivityName);
         assertNotNull("Launched to side activity must be launched in fullscreen stack.",
-                mAmWmState.getAmState().getTaskByActivityName(
+                mAmWmState.getAmState().getTaskByActivity(
                         targetActivityName, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));
 
         // Try to launch to side same activity again with different random data. Note that null
         // cannot be used here, since the first instance of TestActivity is launched with no data
         // in order to launch into split screen.
         targetActivityLauncher.execute();
-        mAmWmState.computeState(waitForActivitiesVisible);
+        mAmWmState.computeState(targetActivityName, LAUNCHING_ACTIVITY);
         int taskNumberFinal = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
                 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
         if (taskCountMustIncrement) {
@@ -316,39 +320,41 @@
         mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
                 targetActivityName);
         assertNotNull("Launched to side activity must be launched in fullscreen stack.",
-                mAmWmState.getAmState().getTaskByActivityName(
+                mAmWmState.getAmState().getTaskByActivity(
                         targetActivityName, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));
     }
 
     @Presubmit
     @Test
     public void testLaunchToSideMultipleWithFlag() throws Exception {
-        launchActivitiesInSplitScreen(LAUNCHING_ACTIVITY, TEST_ACTIVITY_NAME);
+        launchActivitiesInSplitScreen(
+                getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
+                getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
         int taskNumberInitial = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
                 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
         assertNotNull("Launched to side activity must be in fullscreen stack.",
-                mAmWmState.getAmState().getTaskByActivityName(
-                        TEST_ACTIVITY_NAME, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));
+                mAmWmState.getAmState().getTaskByActivity(
+                        TEST_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));
 
         // Try to launch to side same activity again, but with Intent#FLAG_ACTIVITY_MULTIPLE_TASK.
         getLaunchActivityBuilder().setToSide(true).setMultipleTask(true).execute();
-        final String[] waitForActivitiesVisible =
-                new String[] {LAUNCHING_ACTIVITY, TEST_ACTIVITY_NAME};
-        mAmWmState.computeState(waitForActivitiesVisible);
+        mAmWmState.computeState(LAUNCHING_ACTIVITY, TEST_ACTIVITY);
         int taskNumberFinal = mAmWmState.getAmState().getStandardTaskCountByWindowingMode(
                 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
         assertEquals("Task number must be incremented.", taskNumberInitial + 1,
                 taskNumberFinal);
         mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
-                TEST_ACTIVITY_NAME);
+                TEST_ACTIVITY);
         assertNotNull("Launched to side activity must remain in fullscreen stack.",
-                mAmWmState.getAmState().getTaskByActivityName(
-                        TEST_ACTIVITY_NAME, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));
+                mAmWmState.getAmState().getTaskByActivity(
+                        TEST_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY));
     }
 
     @Test
     public void testRotationWhenDocked() throws Exception {
-        launchActivitiesInSplitScreen(LAUNCHING_ACTIVITY, TEST_ACTIVITY_NAME);
+        launchActivitiesInSplitScreen(
+                getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
+                getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
         mAmWmState.assertContainsStack("Must contain fullscreen stack.",
                 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
         mAmWmState.assertContainsStack("Must contain docked stack.",
@@ -356,40 +362,38 @@
 
         // Rotate device single steps (90°) 0-1-2-3.
         // Each time we compute the state we implicitly assert valid bounds.
-        String[] waitForActivitiesVisible =
-            new String[] {LAUNCHING_ACTIVITY, TEST_ACTIVITY_NAME};
         try (final RotationSession rotationSession = new RotationSession()) {
             for (int i = 0; i < 4; i++) {
                 rotationSession.set(i);
-                mAmWmState.computeState(waitForActivitiesVisible);
+                mAmWmState.computeState(LAUNCHING_ACTIVITY, TEST_ACTIVITY);
             }
             // Double steps (180°) We ended the single step at 3. So, we jump directly to 1 for
             // double step. So, we are testing 3-1-3 for one side and 0-2-0 for the other side.
             rotationSession.set(ROTATION_90);
-            mAmWmState.computeState(waitForActivitiesVisible);
+            mAmWmState.computeState(LAUNCHING_ACTIVITY, TEST_ACTIVITY);
             rotationSession.set(ROTATION_270);
-            mAmWmState.computeState(waitForActivitiesVisible);
+            mAmWmState.computeState(LAUNCHING_ACTIVITY, TEST_ACTIVITY);
             rotationSession.set(ROTATION_0);
-            mAmWmState.computeState(waitForActivitiesVisible);
+            mAmWmState.computeState(LAUNCHING_ACTIVITY, TEST_ACTIVITY);
             rotationSession.set(ROTATION_180);
-            mAmWmState.computeState(waitForActivitiesVisible);
+            mAmWmState.computeState(LAUNCHING_ACTIVITY, TEST_ACTIVITY);
             rotationSession.set(ROTATION_0);
-            mAmWmState.computeState(waitForActivitiesVisible);
+            mAmWmState.computeState(LAUNCHING_ACTIVITY, TEST_ACTIVITY);
         }
     }
 
     @Test
     @Presubmit
     public void testRotationWhenDockedWhileLocked() throws Exception {
-        launchActivitiesInSplitScreen(LAUNCHING_ACTIVITY, TEST_ACTIVITY_NAME);
+        launchActivitiesInSplitScreen(
+                getLaunchActivityBuilder().setTargetActivity(LAUNCHING_ACTIVITY),
+                getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
         mAmWmState.assertSanity();
         mAmWmState.assertContainsStack("Must contain fullscreen stack.",
                 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
         mAmWmState.assertContainsStack("Must contain docked stack.",
                 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
 
-        String[] waitForActivitiesVisible =
-                new String[] {LAUNCHING_ACTIVITY, TEST_ACTIVITY_NAME};
         try (final RotationSession rotationSession = new RotationSession();
              final LockScreenSession lockScreenSession = new LockScreenSession()) {
             for (int i = 0; i < 4; i++) {
@@ -397,7 +401,7 @@
                 rotationSession.set(i);
                 lockScreenSession.wakeUpDevice()
                         .unlockDevice();
-                mAmWmState.computeState(waitForActivitiesVisible);
+                mAmWmState.computeState(LAUNCHING_ACTIVITY, TEST_ACTIVITY);
             }
         }
     }
@@ -407,11 +411,11 @@
         try (final RotationSession rotationSession = new RotationSession()) {
             for (int i = 0; i < 2; i++) {
                 rotationSession.set(i);
-                launchActivityInDockStackAndMinimize(TEST_ACTIVITY_NAME);
+                launchActivityInDockStackAndMinimize(TEST_ACTIVITY);
                 if (!mAmWmState.isScreenPortrait() && isTablet()) {
                     // Test minimize to the right only on tablets in landscape
                     removeStacksWithActivityTypes(ALL_ACTIVITY_TYPE_BUT_HOME);
-                    launchActivityInDockStackAndMinimize(TEST_ACTIVITY_NAME,
+                    launchActivityInDockStackAndMinimize(TEST_ACTIVITY,
                             SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT);
                 }
                 removeStacksWithActivityTypes(ALL_ACTIVITY_TYPE_BUT_HOME);
@@ -422,30 +426,29 @@
     @Test
     @Presubmit
     public void testRotationWhileDockMinimized() throws Exception {
-        launchActivityInDockStackAndMinimize(TEST_ACTIVITY_NAME);
+        launchActivityInDockStackAndMinimize(TEST_ACTIVITY);
 
         // Rotate device single steps (90°) 0-1-2-3.
         // Each time we compute the state we implicitly assert valid bounds in minimized mode.
-        String[] waitForActivitiesVisible = new String[] {TEST_ACTIVITY_NAME};
         try (final RotationSession rotationSession = new RotationSession()) {
             for (int i = 0; i < 4; i++) {
                 rotationSession.set(i);
-                mAmWmState.computeState(waitForActivitiesVisible);
+                mAmWmState.computeState(TEST_ACTIVITY);
             }
 
             // Double steps (180°) We ended the single step at 3. So, we jump directly to 1 for
             // double step. So, we are testing 3-1-3 for one side and 0-2-0 for the other side in
             // minimized mode.
             rotationSession.set(ROTATION_90);
-            mAmWmState.computeState(waitForActivitiesVisible);
+            mAmWmState.computeState(TEST_ACTIVITY);
             rotationSession.set(ROTATION_270);
-            mAmWmState.computeState(waitForActivitiesVisible);
+            mAmWmState.computeState(TEST_ACTIVITY);
             rotationSession.set(ROTATION_0);
-            mAmWmState.computeState(waitForActivitiesVisible);
+            mAmWmState.computeState(TEST_ACTIVITY);
             rotationSession.set(ROTATION_180);
-            mAmWmState.computeState(waitForActivitiesVisible);
+            mAmWmState.computeState(TEST_ACTIVITY);
             rotationSession.set(ROTATION_0);
-            mAmWmState.computeState(waitForActivitiesVisible);
+            mAmWmState.computeState(TEST_ACTIVITY);
         }
     }
 
@@ -456,22 +459,23 @@
         try (final RotationSession rotationSession = new RotationSession()) {
             for (int i = 0; i < 4; i++) {
                 rotationSession.set(i);
-                launchActivityInDockStackAndMinimize(DOCKED_ACTIVITY_NAME);
+                launchActivityInDockStackAndMinimize(DOCKED_ACTIVITY);
 
                 // Unminimize the docked stack
-                pressAppSwitchButton();
+                pressAppSwitchButtonAndWaitForRecents();
                 waitForDockNotMinimized();
                 assertDockNotMinimized();
 
                 // Dismiss the dock stack
-                launchActivity(TEST_ACTIVITY_NAME,
+                launchActivity(TEST_ACTIVITY,
                         WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
-                setActivityTaskWindowingMode(DOCKED_ACTIVITY_NAME,
+                setActivityTaskWindowingMode(DOCKED_ACTIVITY,
                         WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
-                mAmWmState.computeState(new String[]{DOCKED_ACTIVITY_NAME});
+                mAmWmState.computeState(DOCKED_ACTIVITY);
 
                 // Go home and check the app transition
-                assertNotSame(TRANSIT_WALLPAPER_OPEN, mAmWmState.getWmState().getLastTransition());
+                assertNotEquals(
+                        TRANSIT_WALLPAPER_OPEN, mAmWmState.getWmState().getLastTransition());
                 pressHomeButton();
                 mAmWmState.computeState(true);
                 assertEquals(TRANSIT_WALLPAPER_OPEN, mAmWmState.getWmState().getLastTransition());
@@ -479,55 +483,58 @@
         }
     }
 
+    @FlakyTest(bugId = 73813034)
     @Test
     @Presubmit
     public void testFinishDockActivityWhileMinimized() throws Exception {
-        launchActivityInDockStackAndMinimize(TEST_ACTIVITY_NAME);
+        launchActivityInDockStackAndMinimize(TEST_ACTIVITY);
 
         executeShellCommand("am broadcast -a " + TEST_ACTIVITY_ACTION_FINISH_SELF);
         waitForDockNotMinimized();
-        mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, false);
+        mAmWmState.assertVisibility(TEST_ACTIVITY, false);
         assertDockNotMinimized();
     }
 
     @Test
     @Presubmit
     public void testDockedStackToMinimizeWhenUnlocked() throws Exception {
-        launchActivityInSplitScreenWithRecents(TEST_ACTIVITY_NAME);
-        mAmWmState.computeState(new WaitForValidActivityState(TEST_ACTIVITY_NAME));
+        launchActivityInSplitScreenWithRecents(TEST_ACTIVITY);
+        mAmWmState.computeState(TEST_ACTIVITY);
         try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
             lockScreenSession.sleepDevice()
                     .wakeUpDevice()
                     .unlockDevice();
-            mAmWmState.computeState(new WaitForValidActivityState(TEST_ACTIVITY_NAME));
+            mAmWmState.computeState(TEST_ACTIVITY);
             assertDockMinimized();
         }
     }
 
     @Test
     public void testMinimizedStateWhenUnlockedAndUnMinimized() throws Exception {
-        launchActivityInDockStackAndMinimize(TEST_ACTIVITY_NAME);
+        launchActivityInDockStackAndMinimize(TEST_ACTIVITY);
 
         try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
             lockScreenSession.sleepDevice()
                     .wakeUpDevice()
                     .unlockDevice();
-            mAmWmState.computeState(new WaitForValidActivityState(TEST_ACTIVITY_NAME));
+            mAmWmState.computeState(TEST_ACTIVITY);
 
             // Unminimized back to splitscreen
-            pressAppSwitchButton();
-            mAmWmState.computeState(new WaitForValidActivityState(TEST_ACTIVITY_NAME));
+            pressAppSwitchButtonAndWaitForRecents();
+            mAmWmState.computeState(TEST_ACTIVITY);
         }
     }
 
     @Test
     @Presubmit
     public void testResizeDockedStack() throws Exception {
-        launchActivitiesInSplitScreen(DOCKED_ACTIVITY_NAME, TEST_ACTIVITY_NAME);
+        launchActivitiesInSplitScreen(
+                getLaunchActivityBuilder().setTargetActivity(DOCKED_ACTIVITY),
+                getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
         resizeDockedStack(STACK_SIZE, STACK_SIZE, TASK_SIZE, TASK_SIZE);
         mAmWmState.computeState(false /* compareTaskAndStackBounds */,
-                new WaitForValidActivityState.Builder(TEST_ACTIVITY_NAME).build(),
-                new WaitForValidActivityState.Builder(DOCKED_ACTIVITY_NAME).build());
+                new WaitForValidActivityState(TEST_ACTIVITY),
+                new WaitForValidActivityState(DOCKED_ACTIVITY));
         mAmWmState.assertContainsStack("Must contain secondary split-screen stack.",
                 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD);
         mAmWmState.assertContainsStack("Must contain primary split-screen stack.",
@@ -535,46 +542,41 @@
         assertEquals(new Rect(0, 0, STACK_SIZE, STACK_SIZE),
                 mAmWmState.getAmState().getStandardStackByWindowingMode(
                         WINDOWING_MODE_SPLIT_SCREEN_PRIMARY).getBounds());
-        mAmWmState.assertDockedTaskBounds(TASK_SIZE, TASK_SIZE, DOCKED_ACTIVITY_NAME);
-        mAmWmState.assertVisibility(DOCKED_ACTIVITY_NAME, true);
-        mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true);
+        mAmWmState.assertDockedTaskBounds(TASK_SIZE, TASK_SIZE, DOCKED_ACTIVITY);
+        mAmWmState.assertVisibility(DOCKED_ACTIVITY, true);
+        mAmWmState.assertVisibility(TEST_ACTIVITY, true);
     }
 
     @Test
     public void testActivityLifeCycleOnResizeDockedStack() throws Exception {
-        final WaitForValidActivityState[] waitTestActivityName =
-                new WaitForValidActivityState[] {new WaitForValidActivityState.Builder(
-                        TEST_ACTIVITY_NAME).build()};
-        launchActivity(TEST_ACTIVITY_NAME);
-        mAmWmState.computeState(waitTestActivityName);
+        launchActivity(TEST_ACTIVITY);
+        mAmWmState.computeState(TEST_ACTIVITY);
         final Rect fullScreenBounds = mAmWmState.getWmState().getStandardStackByWindowingMode(
                 WINDOWING_MODE_FULLSCREEN).getBounds();
 
-        setActivityTaskWindowingMode(TEST_ACTIVITY_NAME, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
-        mAmWmState.computeState(waitTestActivityName);
-        launchActivity(NO_RELAUNCH_ACTIVITY_NAME,
-                WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
+        setActivityTaskWindowingMode(TEST_ACTIVITY, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+        mAmWmState.computeState(TEST_ACTIVITY);
+        launchActivity(NO_RELAUNCH_ACTIVITY, WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
 
-        mAmWmState.computeState(new WaitForValidActivityState.Builder(TEST_ACTIVITY_NAME).build(),
-                new WaitForValidActivityState.Builder(NO_RELAUNCH_ACTIVITY_NAME).build());
+        mAmWmState.computeState(TEST_ACTIVITY, NO_RELAUNCH_ACTIVITY);
         final Rect initialDockBounds = mAmWmState.getWmState().getStandardStackByWindowingMode(
                 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) .getBounds();
 
         final LogSeparator logSeparator = clearLogcat();
 
         Rect newBounds = computeNewDockBounds(fullScreenBounds, initialDockBounds, true);
-        resizeDockedStack(newBounds.width(), newBounds.height(), newBounds.width(), newBounds.height());
-        mAmWmState.computeState(new WaitForValidActivityState.Builder(TEST_ACTIVITY_NAME).build(),
-                new WaitForValidActivityState.Builder(NO_RELAUNCH_ACTIVITY_NAME).build());
+        resizeDockedStack(
+                newBounds.width(), newBounds.height(), newBounds.width(), newBounds.height());
+        mAmWmState.computeState(TEST_ACTIVITY, NO_RELAUNCH_ACTIVITY);
 
         // We resize twice to make sure we cross an orientation change threshold for both
         // activities.
         newBounds = computeNewDockBounds(fullScreenBounds, initialDockBounds, false);
-        resizeDockedStack(newBounds.width(), newBounds.height(), newBounds.width(), newBounds.height());
-        mAmWmState.computeState(new WaitForValidActivityState.Builder(TEST_ACTIVITY_NAME).build(),
-                new WaitForValidActivityState.Builder(NO_RELAUNCH_ACTIVITY_NAME).build());
-        assertActivityLifecycle(TEST_ACTIVITY_NAME, true /* relaunched */, logSeparator);
-        assertActivityLifecycle(NO_RELAUNCH_ACTIVITY_NAME, false /* relaunched */, logSeparator);
+        resizeDockedStack(
+                newBounds.width(), newBounds.height(), newBounds.width(), newBounds.height());
+        mAmWmState.computeState(TEST_ACTIVITY, NO_RELAUNCH_ACTIVITY);
+        assertActivityLifecycle(TEST_ACTIVITY, true /* relaunched */, logSeparator);
+        assertActivityLifecycle(NO_RELAUNCH_ACTIVITY, false /* relaunched */, logSeparator);
     }
 
     private Rect computeNewDockBounds(
@@ -597,41 +599,44 @@
     @Test
     @Presubmit
     public void testStackListOrderLaunchDockedActivity() throws Exception {
-        launchActivityInSplitScreenWithRecents(TEST_ACTIVITY_NAME);
+        launchActivityInSplitScreenWithRecents(TEST_ACTIVITY);
 
         final int homeStackIndex = mAmWmState.getStackIndexByActivityType(ACTIVITY_TYPE_HOME);
         final int recentsStackIndex = mAmWmState.getStackIndexByActivityType(ACTIVITY_TYPE_RECENTS);
-        assertTrue("Recents stack should be on top of home stack",
-                recentsStackIndex < homeStackIndex);
+        assertThat("Recents stack should be on top of home stack",
+                recentsStackIndex, lessThan(homeStackIndex));
     }
 
     @Test
     @Presubmit
     public void testStackListOrderOnSplitScreenDismissed() throws Exception {
-        launchActivitiesInSplitScreen(DOCKED_ACTIVITY_NAME, TEST_ACTIVITY_NAME);
+        launchActivitiesInSplitScreen(
+                getLaunchActivityBuilder().setTargetActivity(DOCKED_ACTIVITY),
+                getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
 
-        setActivityTaskWindowingMode(DOCKED_ACTIVITY_NAME, WINDOWING_MODE_FULLSCREEN);
-        mAmWmState.computeState(new WaitForValidActivityState.Builder(
-                DOCKED_ACTIVITY_NAME).setWindowingMode(WINDOWING_MODE_FULLSCREEN).build());
+        setActivityTaskWindowingMode(DOCKED_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
+        mAmWmState.computeState(new WaitForValidActivityState.Builder(DOCKED_ACTIVITY)
+                .setWindowingMode(WINDOWING_MODE_FULLSCREEN)
+                .build());
 
         final int homeStackIndex = mAmWmState.getStackIndexByActivityType(ACTIVITY_TYPE_HOME);
         final int prevSplitScreenPrimaryIndex =
-                mAmWmState.getAmState().getStackIndexByActivityName(DOCKED_ACTIVITY_NAME);
+                mAmWmState.getAmState().getStackIndexByActivity(DOCKED_ACTIVITY);
         final int prevSplitScreenSecondaryIndex =
-                mAmWmState.getAmState().getStackIndexByActivityName(TEST_ACTIVITY_NAME);
+                mAmWmState.getAmState().getStackIndexByActivity(TEST_ACTIVITY);
 
         final int expectedHomeStackIndex =
                 (prevSplitScreenPrimaryIndex > prevSplitScreenSecondaryIndex
                         ? prevSplitScreenPrimaryIndex : prevSplitScreenSecondaryIndex) - 1;
-        assertTrue("Home stack needs to be directly behind the top stack",
-                expectedHomeStackIndex == homeStackIndex);
+        assertEquals("Home stack needs to be directly behind the top stack",
+                expectedHomeStackIndex, homeStackIndex);
     }
 
-    private void launchActivityInDockStackAndMinimize(String activityName) throws Exception {
+    private void launchActivityInDockStackAndMinimize(ComponentName activityName) throws Exception {
         launchActivityInDockStackAndMinimize(activityName, SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT);
     }
 
-    private void launchActivityInDockStackAndMinimize(String activityName, int createMode)
+    private void launchActivityInDockStackAndMinimize(ComponentName activityName, int createMode)
             throws Exception {
         launchActivityInSplitScreenWithRecents(activityName, createMode);
         pressHomeButton();
@@ -645,7 +650,7 @@
     private void waitForAndAssertDockMinimized() throws Exception {
         waitForDockMinimized();
         assertDockMinimized();
-        mAmWmState.computeState(new WaitForValidActivityState.Builder(TEST_ACTIVITY_NAME).build());
+        mAmWmState.computeState(TEST_ACTIVITY);
         mAmWmState.assertContainsStack("Must contain docked stack.",
                 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
         mAmWmState.assertFocusedStack("Home activity should be focused in minimized mode",
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerTransitionSelectionTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerTransitionSelectionTests.java
index fe05359..925f9a4 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerTransitionSelectionTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerTransitionSelectionTests.java
@@ -16,6 +16,9 @@
 
 package android.server.am;
 
+import static android.server.am.Components.BOTTOM_ACTIVITY;
+import static android.server.am.Components.TOP_ACTIVITY;
+import static android.server.am.Components.TRANSLUCENT_TOP_ACTIVITY;
 import static android.server.am.WindowManagerState.TRANSIT_ACTIVITY_CLOSE;
 import static android.server.am.WindowManagerState.TRANSIT_ACTIVITY_OPEN;
 import static android.server.am.WindowManagerState.TRANSIT_TASK_CLOSE;
@@ -27,6 +30,7 @@
 
 import static org.junit.Assert.assertEquals;
 
+import android.content.ComponentName;
 import android.platform.test.annotations.Presubmit;
 import android.support.test.filters.FlakyTest;
 
@@ -48,12 +52,6 @@
 @FlakyTest(bugId = 71792333)
 public class ActivityManagerTransitionSelectionTests extends ActivityManagerTestBase {
 
-    private static final String BOTTOM_ACTIVITY_NAME = "BottomActivity";
-    private static final String TOP_ACTIVITY_NAME = "TopActivity";
-    private static final String TRANSLUCENT_TOP_ACTIVITY_NAME = "TranslucentTopActivity";
-
-    //------------------------------------------------------------------------//
-
     // Test activity open/close under normal timing
     @Test
     public void testOpenActivity_NeitherWallpaper() throws Exception {
@@ -225,40 +223,46 @@
         testTransitionSelection(true /*testOpen*/, false /*testNewTask*/,
                 bottomWallpaper, topWallpaper, false /*topTranslucent*/, slowStop, expectedTransit);
     }
+
     private void testCloseActivity(boolean bottomWallpaper,
             boolean topWallpaper, boolean slowStop, String expectedTransit) throws Exception {
         testTransitionSelection(false /*testOpen*/, false /*testNewTask*/,
                 bottomWallpaper, topWallpaper, false /*topTranslucent*/, slowStop, expectedTransit);
     }
+
     private void testOpenTask(boolean bottomWallpaper,
             boolean topWallpaper, boolean slowStop, String expectedTransit) throws Exception {
         testTransitionSelection(true /*testOpen*/, true /*testNewTask*/,
                 bottomWallpaper, topWallpaper, false /*topTranslucent*/, slowStop, expectedTransit);
     }
+
     private void testCloseTask(boolean bottomWallpaper,
             boolean topWallpaper, boolean slowStop, String expectedTransit) throws Exception {
         testTransitionSelection(false /*testOpen*/, true /*testNewTask*/,
                 bottomWallpaper, topWallpaper, false /*topTranslucent*/, slowStop, expectedTransit);
     }
+
     private void testCloseActivityTranslucent(boolean bottomWallpaper,
             boolean topWallpaper, String expectedTransit) throws Exception {
         testTransitionSelection(false /*testOpen*/, false /*testNewTask*/,
                 bottomWallpaper, topWallpaper, true /*topTranslucent*/,
                 false /*slowStop*/, expectedTransit);
     }
+
     private void testCloseTaskTranslucent(boolean bottomWallpaper,
             boolean topWallpaper, String expectedTransit) throws Exception {
         testTransitionSelection(false /*testOpen*/, true /*testNewTask*/,
                 bottomWallpaper, topWallpaper, true /*topTranslucent*/,
                 false /*slowStop*/, expectedTransit);
     }
+
     //------------------------------------------------------------------------//
 
     private void testTransitionSelection(
             boolean testOpen, boolean testNewTask,
             boolean bottomWallpaper, boolean topWallpaper, boolean topTranslucent,
             boolean testSlowStop, String expectedTransit) throws Exception {
-        String bottomStartCmd = getAmStartCmd(BOTTOM_ACTIVITY_NAME);
+        String bottomStartCmd = getAmStartCmd(BOTTOM_ACTIVITY);
         if (bottomWallpaper) {
             bottomStartCmd += " --ez USE_WALLPAPER true";
         }
@@ -267,11 +271,10 @@
         }
         executeShellCommand(bottomStartCmd);
 
-        mAmWmState.computeState(new WaitForValidActivityState(BOTTOM_ACTIVITY_NAME));
+        mAmWmState.computeState(BOTTOM_ACTIVITY);
 
-        final String topActivityName = topTranslucent ?
-                TRANSLUCENT_TOP_ACTIVITY_NAME : TOP_ACTIVITY_NAME;
-        String topStartCmd = getAmStartCmd(topActivityName);
+        final ComponentName topActivity = topTranslucent ? TRANSLUCENT_TOP_ACTIVITY : TOP_ACTIVITY;
+        String topStartCmd = getAmStartCmd(topActivity);
         if (testNewTask) {
             topStartCmd += " -f 0x18000000";
         }
@@ -285,9 +288,9 @@
 
         Thread.sleep(5000);
         if (testOpen) {
-            mAmWmState.computeState(new WaitForValidActivityState(topActivityName));
+            mAmWmState.computeState(topActivity);
         } else {
-            mAmWmState.computeState(new WaitForValidActivityState(BOTTOM_ACTIVITY_NAME));
+            mAmWmState.computeState(BOTTOM_ACTIVITY);
         }
 
         assertEquals("Picked wrong transition", expectedTransit,
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerVrDisplayTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerVrDisplayTests.java
index 3c0a584..82576e8 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerVrDisplayTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerVrDisplayTests.java
@@ -17,6 +17,11 @@
 package android.server.am;
 
 import static android.server.am.ActivityAndWindowManagersState.DEFAULT_DISPLAY_ID;
+import static android.server.am.ComponentNameUtils.getActivityName;
+import static android.server.am.Components.ALT_LAUNCHING_ACTIVITY;
+import static android.server.am.Components.LAUNCHING_ACTIVITY;
+import static android.server.am.Components.RESIZEABLE_ACTIVITY;
+import static android.server.am.Components.VR_TEST_ACTIVITY;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
@@ -34,8 +39,6 @@
  *     atest CtsActivityManagerDeviceTestCases:ActivityManagerVrDisplayTests
  */
 public class ActivityManagerVrDisplayTests extends ActivityManagerDisplayTestBase {
-    private static final String RESIZEABLE_ACTIVITY_NAME = "ResizeableActivity";
-    private static final String VR_TEST_ACTIVITY_NAME = "VrTestActivity";
     private static final int VR_VIRTUAL_DISPLAY_WIDTH = 700;
     private static final int VR_VIRTUAL_DISPLAY_HEIGHT = 900;
     private static final int VR_VIRTUAL_DISPLAY_DPI = 320;
@@ -74,13 +77,13 @@
             vrModeSession.enablePersistentVrMode();
 
             // Launch the VR activity.
-            launchActivity(VR_TEST_ACTIVITY_NAME);
-            mAmWmState.computeState(new WaitForValidActivityState(VR_TEST_ACTIVITY_NAME));
-            mAmWmState.assertVisibility(VR_TEST_ACTIVITY_NAME, true /* visible */);
+            launchActivity(VR_TEST_ACTIVITY);
+            mAmWmState.computeState(VR_TEST_ACTIVITY);
+            mAmWmState.assertVisibility(VR_TEST_ACTIVITY, true /* visible */);
 
             // Launch the non-VR 2D activity and check where it ends up.
             launchActivity(LAUNCHING_ACTIVITY);
-            mAmWmState.computeState(new WaitForValidActivityState(LAUNCHING_ACTIVITY));
+            mAmWmState.computeState(LAUNCHING_ACTIVITY);
 
             // Ensure that the subsequent activity is visible
             mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
@@ -92,7 +95,7 @@
             final ActivityManagerState.ActivityStack focusedStack
                     = mAmWmState.getAmState().getStackById(focusedStackId);
             assertEquals("Launched activity must be resumed in focused stack",
-                    getActivityComponentName(LAUNCHING_ACTIVITY), focusedStack.mResumedActivity);
+                    getActivityName(LAUNCHING_ACTIVITY), focusedStack.mResumedActivity);
 
             // Check if the launch activity is in Vr virtual display id.
             final List<ActivityDisplay> reportedDisplays = getDisplaysStates();
@@ -121,13 +124,13 @@
             vrModeSession.enablePersistentVrMode();
 
             // Launch the VR activity.
-            launchActivity(VR_TEST_ACTIVITY_NAME);
-            mAmWmState.computeState(new WaitForValidActivityState(VR_TEST_ACTIVITY_NAME));
-            mAmWmState.assertVisibility(VR_TEST_ACTIVITY_NAME, true /* visible */);
+            launchActivity(VR_TEST_ACTIVITY);
+            mAmWmState.computeState(VR_TEST_ACTIVITY);
+            mAmWmState.assertVisibility(VR_TEST_ACTIVITY, true /* visible */);
 
             // Re-launch the non-VR 2D activity and check where it ends up.
             launchActivity(LAUNCHING_ACTIVITY);
-            mAmWmState.computeState(new WaitForValidActivityState(LAUNCHING_ACTIVITY));
+            mAmWmState.computeState(LAUNCHING_ACTIVITY);
 
             // Ensure that the subsequent activity is visible
             mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
@@ -139,7 +142,7 @@
             final ActivityManagerState.ActivityStack focusedStack
                     = mAmWmState.getAmState().getStackById(focusedStackId);
             assertEquals("Launched activity must be resumed in focused stack",
-                    getActivityComponentName(LAUNCHING_ACTIVITY), focusedStack.mResumedActivity);
+                    getActivityName(LAUNCHING_ACTIVITY), focusedStack.mResumedActivity);
 
             // Check if the launch activity is in Vr virtual display id.
             final List<ActivityDisplay> reportedDisplays = getDisplaysStates();
@@ -165,13 +168,13 @@
             vrModeSession.enablePersistentVrMode();
 
             // Launch the VR activity.
-            launchActivity(VR_TEST_ACTIVITY_NAME);
-            mAmWmState.computeState(new WaitForValidActivityState(VR_TEST_ACTIVITY_NAME));
-            mAmWmState.assertVisibility(VR_TEST_ACTIVITY_NAME, true /* visible */);
+            launchActivity(VR_TEST_ACTIVITY);
+            mAmWmState.computeState(VR_TEST_ACTIVITY);
+            mAmWmState.assertVisibility(VR_TEST_ACTIVITY, true /* visible */);
 
             // Launch the non-VR 2D activity and check where it ends up.
             launchActivity(ALT_LAUNCHING_ACTIVITY);
-            mAmWmState.computeState(new WaitForValidActivityState(ALT_LAUNCHING_ACTIVITY));
+            mAmWmState.computeState(ALT_LAUNCHING_ACTIVITY);
 
             // Ensure that the subsequent activity is visible
             mAmWmState.assertVisibility(ALT_LAUNCHING_ACTIVITY, true /* visible */);
@@ -183,7 +186,7 @@
             final ActivityManagerState.ActivityStack focusedStack
                     = mAmWmState.getAmState().getStackById(focusedStackId);
             assertEquals("Launched activity must be resumed in focused stack",
-                    getActivityComponentName(ALT_LAUNCHING_ACTIVITY),
+                    getActivityName(ALT_LAUNCHING_ACTIVITY),
                     focusedStack.mResumedActivity);
 
             // Check if the launch activity is in Vr virtual display id.
@@ -209,20 +212,19 @@
         }
 
         // Launch the non-VR 2D activity and check where it ends up.
-        launchActivity(RESIZEABLE_ACTIVITY_NAME);
-        mAmWmState.computeState(new WaitForValidActivityState(RESIZEABLE_ACTIVITY_NAME));
+        launchActivity(RESIZEABLE_ACTIVITY);
+        mAmWmState.computeState(RESIZEABLE_ACTIVITY);
 
         // Ensure that the subsequent activity is visible
-        mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY_NAME, true /* visible */);
+        mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY, true /* visible */);
 
         // Check that activity is launched in focused stack on primary display.
-        mAmWmState.assertFocusedActivity("Launched activity must be focused",
-                RESIZEABLE_ACTIVITY_NAME);
+        mAmWmState.assertFocusedActivity("Launched activity must be focused", RESIZEABLE_ACTIVITY);
         final int frontStackId = mAmWmState.getAmState().getFrontStackId(DEFAULT_DISPLAY_ID);
         final ActivityManagerState.ActivityStack frontStack
                 = mAmWmState.getAmState().getStackById(frontStackId);
         assertEquals("Launched activity must be resumed in front stack",
-                getActivityComponentName(RESIZEABLE_ACTIVITY_NAME), frontStack.mResumedActivity);
+                getActivityName(RESIZEABLE_ACTIVITY), frontStack.mResumedActivity);
         assertEquals("Front stack must be on primary display",
                 DEFAULT_DISPLAY_ID, frontStack.mDisplayId);
     }
diff --git a/tests/framework/base/activitymanager/src/android/server/am/AnimationBackgroundTests.java b/tests/framework/base/activitymanager/src/android/server/am/AnimationBackgroundTests.java
index fd8ed2f..c8e3fa1 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/AnimationBackgroundTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/AnimationBackgroundTests.java
@@ -16,15 +16,16 @@
 
 package android.server.am;
 
-
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.server.am.Components.ANIMATION_TEST_ACTIVITY;
+import static android.server.am.Components.LAUNCHING_ACTIVITY;
+import static android.view.Display.DEFAULT_DISPLAY;
+
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 import org.junit.Test;
 
-import static android.server.am.ActivityAndWindowManagersState.DEFAULT_DISPLAY_ID;
-
 /**
  * Build/Install/Run:
  *     atest CtsActivityManagerDeviceTestCases:AnimationBackgroundTests
@@ -33,9 +34,9 @@
 
     @Test
     public void testAnimationBackground_duringAnimation() throws Exception {
-        launchActivityOnDisplay(LAUNCHING_ACTIVITY, DEFAULT_DISPLAY_ID);
+        launchActivityOnDisplay(LAUNCHING_ACTIVITY, DEFAULT_DISPLAY);
         getLaunchActivityBuilder()
-                .setTargetActivityName("AnimationTestActivity")
+                .setTargetActivity(ANIMATION_TEST_ACTIVITY)
                 .setWaitForLaunched(false)
                 .execute();
 
@@ -51,9 +52,9 @@
 
     @Test
     public void testAnimationBackground_gone() throws Exception {
-        launchActivityOnDisplay(LAUNCHING_ACTIVITY, DEFAULT_DISPLAY_ID);
-        getLaunchActivityBuilder().setTargetActivityName("AnimationTestActivity").execute();
-        mAmWmState.computeState(new WaitForValidActivityState.Builder("AnimationTestActivity").build());
+        launchActivityOnDisplay(LAUNCHING_ACTIVITY, DEFAULT_DISPLAY);
+        getLaunchActivityBuilder().setTargetActivity(ANIMATION_TEST_ACTIVITY).execute();
+        mAmWmState.computeState(ANIMATION_TEST_ACTIVITY);
         assertFalse("window animation background needs to be gone", mAmWmState.getWmState()
                 .getStandardStackByWindowingMode(WINDOWING_MODE_FULLSCREEN)
                 .isWindowAnimationBackgroundSurfaceShowing());
diff --git a/tests/framework/base/activitymanager/src/android/server/am/DeprecatedTargetSdkTest.java b/tests/framework/base/activitymanager/src/android/server/am/DeprecatedTargetSdkTest.java
index 42edc5f..167ba4b 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/DeprecatedTargetSdkTest.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/DeprecatedTargetSdkTest.java
@@ -16,8 +16,13 @@
 
 package android.server.am;
 
+import static android.server.am.ComponentNameUtils.getWindowName;
+import static android.server.am.UiDeviceUtils.pressBackButton;
+import static android.server.am.deprecatedsdk.Components.MAIN_ACTIVITY;
+
 import static org.junit.Assert.assertTrue;
 
+import android.content.ComponentName;
 import android.support.test.runner.AndroidJUnit4;
 
 import org.junit.After;
@@ -32,11 +37,10 @@
  */
 @RunWith(AndroidJUnit4.class)
 public class DeprecatedTargetSdkTest extends ActivityManagerTestBase {
-    private static final String AM_START_COMMAND = "am start -n %s/%s.%s";
-    private static final String AM_FORCE_STOP = "am force-stop %s";
 
-    private static final int ACTIVITY_TIMEOUT_MILLIS = 1000;
-    private static final int WINDOW_TIMEOUT_MILLIS = 1000;
+    /** @see com.android.server.am.DeprecatedTargetSdkVersionDialog */
+    private static final String DEPRECATED_TARGET_SDK_VERSION_DIALOG =
+            "DeprecatedTargetSdkVersionDialog";
 
     @After
     @Override
@@ -44,49 +48,31 @@
         super.tearDown();
 
         // Ensure app process is stopped.
-        forceStopPackage("android.server.am.deprecatedsdk");
-        forceStopPackage("android.server.am");
+        stopTestPackage(MAIN_ACTIVITY);
     }
 
     @Test
     public void testCompatibilityDialog() throws Exception {
         // Launch target app.
-        startActivity("android.server.am.deprecatedsdk", "MainActivity");
-        verifyWindowDisplayed("MainActivity", ACTIVITY_TIMEOUT_MILLIS);
-        verifyWindowDisplayed("DeprecatedTargetSdkVersionDialog", WINDOW_TIMEOUT_MILLIS);
+        launchActivity(MAIN_ACTIVITY);
+        assertActivityDisplayed(MAIN_ACTIVITY);
+        assertWindowDisplayed(DEPRECATED_TARGET_SDK_VERSION_DIALOG);
 
         // Go back to dismiss the warning dialog.
-        executeShellCommand("input keyevent 4");
+        pressBackButton();
 
         // Go back again to formally stop the app. If we just kill the process, it'll attempt to
         // resume rather than starting from scratch (as far as ActivityStack is concerned) and it
         // won't invoke the warning dialog.
-        executeShellCommand("input keyevent 4");
+        pressBackButton();
     }
 
-    private void forceStopPackage(String packageName) {
-        final String forceStopCmd = String.format(AM_FORCE_STOP, packageName);
-        executeShellCommand(forceStopCmd);
+    private void assertActivityDisplayed(final ComponentName activityName) throws Exception {
+        assertWindowDisplayed(getWindowName(activityName));
     }
 
-    private void startActivity(String packageName, String activityName){
-        executeShellCommand(getStartCommand(packageName, activityName));
-    }
-
-    private String getStartCommand(String packageName, String activityName) {
-        return String.format(AM_START_COMMAND, packageName, packageName, activityName);
-    }
-
-    private void verifyWindowDisplayed(String windowName, long timeoutMillis) {
-        boolean success = false;
-
-        // Verify that compatibility dialog is shown within 1000ms.
-        final long timeoutTimeMillis = System.currentTimeMillis() + timeoutMillis;
-        while (!success && System.currentTimeMillis() < timeoutTimeMillis) {
-            final String output = executeShellCommand("dumpsys window");
-            success = output.contains(windowName);
-        }
-
-        assertTrue(windowName + " was not displayed", success);
+    private void assertWindowDisplayed(final String windowName) throws Exception {
+        mAmWmState.waitForValidState(WaitForValidActivityState.forWindow(windowName));
+        assertTrue(windowName + "is visible", mAmWmState.getWmState().isWindowVisible(windowName));
     }
 }
diff --git a/tests/framework/base/activitymanager/src/android/server/am/DisplaySizeTest.java b/tests/framework/base/activitymanager/src/android/server/am/DisplaySizeTest.java
index ee1dc1e..58c5048 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/DisplaySizeTest.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/DisplaySizeTest.java
@@ -19,6 +19,7 @@
 import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
 import static android.server.am.ComponentNameUtils.getActivityName;
 import static android.server.am.ComponentNameUtils.getWindowName;
+import static android.server.am.UiDeviceUtils.pressBackButton;
 import static android.server.am.displaysize.Components.SMALLEST_WIDTH_ACTIVITY;
 
 import static org.junit.Assert.assertTrue;
diff --git a/tests/framework/base/activitymanager/src/android/server/am/KeyguardLockedTests.java b/tests/framework/base/activitymanager/src/android/server/am/KeyguardLockedTests.java
index 1eadf59..ecdb6e8 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/KeyguardLockedTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/KeyguardLockedTests.java
@@ -18,12 +18,12 @@
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.server.am.UiDeviceUtils.pressBackButton;
+
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
-import android.app.KeyguardManager;
-
 import org.junit.Before;
 import org.junit.Test;
 
@@ -55,7 +55,6 @@
             assertTrue(mKeyguardManager.isDeviceLocked());
             assertTrue(mKeyguardManager.isDeviceSecure());
             assertTrue(mKeyguardManager.isKeyguardSecure());
-            mAmWmState.waitForKeyguardShowingAndNotOccluded();
             mAmWmState.assertKeyguardShowingAndNotOccluded();
             lockScreenSession.unlockDevice()
                     .enterAndConfirmLockCredential();
@@ -71,7 +70,6 @@
         try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
             lockScreenSession.setLockCredential()
                     .gotoKeyguard();
-            mAmWmState.waitForKeyguardShowingAndNotOccluded();
             mAmWmState.assertKeyguardShowingAndNotOccluded();
             launchActivity("DismissKeyguardActivity");
             lockScreenSession.enterAndConfirmLockCredential();
@@ -86,7 +84,6 @@
         try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
             lockScreenSession.setLockCredential()
                     .gotoKeyguard();
-            mAmWmState.waitForKeyguardShowingAndNotOccluded();
             mAmWmState.assertKeyguardShowingAndNotOccluded();
             launchActivity(SHOW_WHEN_LOCKED_ACTIVITY);
             mAmWmState.computeState(new WaitForValidActivityState(SHOW_WHEN_LOCKED_ACTIVITY));
@@ -105,7 +102,6 @@
         try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
             lockScreenSession.setLockCredential()
                     .gotoKeyguard();
-            mAmWmState.waitForKeyguardShowingAndNotOccluded();
             mAmWmState.assertKeyguardShowingAndNotOccluded();
             launchActivity(SHOW_WHEN_LOCKED_ACTIVITY);
             mAmWmState.computeState(new WaitForValidActivityState(SHOW_WHEN_LOCKED_ACTIVITY));
@@ -161,7 +157,6 @@
         try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
             lockScreenSession.setLockCredential()
                     .gotoKeyguard();
-            mAmWmState.waitForKeyguardShowingAndNotOccluded();
             assertTrue(mAmWmState.getAmState().getKeyguardControllerState().keyguardShowing);
 
             // Enter PiP on an activity on top of the keyguard, and ensure that it prompts the user
@@ -202,7 +197,6 @@
 
             lockScreenSession.gotoKeyguard();
             mAmWmState.computeState(true);
-            mAmWmState.waitForKeyguardShowingAndOccluded();
             mAmWmState.assertKeyguardShowingAndOccluded();
             mAmWmState.assertVisibility(SHOW_WHEN_LOCKED_ACTIVITY, true);
             mAmWmState.assertVisibility(PIP_ACTIVITY, false);
@@ -223,7 +217,6 @@
             mAmWmState.assertVisibility(PIP_ACTIVITY, true);
 
             lockScreenSession.gotoKeyguard();
-            mAmWmState.waitForKeyguardShowingAndNotOccluded();
             mAmWmState.assertKeyguardShowingAndNotOccluded();
             mAmWmState.assertVisibility(PIP_ACTIVITY, false);
         }
diff --git a/tests/framework/base/activitymanager/src/android/server/am/KeyguardTests.java b/tests/framework/base/activitymanager/src/android/server/am/KeyguardTests.java
index 1024bc3..12ac93c 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/KeyguardTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/KeyguardTests.java
@@ -18,6 +18,7 @@
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.server.am.UiDeviceUtils.pressHomeButton;
 import static android.view.Surface.ROTATION_90;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 
@@ -177,7 +178,7 @@
 
         try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
             launchActivitiesInSplitScreen(
-                    getLaunchActivityBuilder().setTargetActivityName(LAUNCHING_ACTIVITY),
+                    getLaunchActivityBuilder().setTargetActivityName(LAUNCHING_ACTIVITY_NAME),
                     getLaunchActivityBuilder().setTargetActivityName("ShowWhenLockedActivity")
                             .setRandomData(true)
                             .setMultipleTask(false)
@@ -292,7 +293,6 @@
         try (final LockScreenSession lockScreenSession = new LockScreenSession();
              final RotationSession rotationSession = new RotationSession()) {
             lockScreenSession.gotoKeyguard();
-            mAmWmState.waitForKeyguardShowingAndNotOccluded();
             mAmWmState.assertKeyguardShowingAndNotOccluded();
             executeShellCommand(getAmStartCmd("ShowWhenLockedActivity"));
             mAmWmState.computeState(new WaitForValidActivityState("ShowWhenLockedActivity"));
@@ -358,7 +358,6 @@
         try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
             final LogSeparator logSeparator = clearLogcat();
             lockScreenSession.gotoKeyguard();
-            mAmWmState.waitForKeyguardShowingAndNotOccluded();
             mAmWmState.assertKeyguardShowingAndNotOccluded();
             launchActivity("ShowWhenLockedAttrActivity");
             mAmWmState.computeState(new WaitForValidActivityState("ShowWhenLockedAttrActivity"));
diff --git a/tests/framework/base/activitymanager/src/android/server/am/PrereleaseSdkTest.java b/tests/framework/base/activitymanager/src/android/server/am/PrereleaseSdkTest.java
index 54d9b5c..027f805 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/PrereleaseSdkTest.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/PrereleaseSdkTest.java
@@ -16,6 +16,8 @@
 
 package android.server.am;
 
+import static android.server.am.UiDeviceUtils.pressBackButton;
+
 import static org.junit.Assert.assertTrue;
 
 import org.junit.After;
diff --git a/tests/framework/base/activitymanager/src/android/server/am/StartActivityTests.java b/tests/framework/base/activitymanager/src/android/server/am/StartActivityTests.java
index 788267d..bcab43f 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/StartActivityTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/StartActivityTests.java
@@ -16,6 +16,7 @@
 
 package android.server.am;
 
+import static android.server.am.Components.TEST_ACTIVITY;
 import static android.server.am.app27.Components.SDK_27_LAUNCHING_ACTIVITY;
 
 import static org.junit.Assert.assertFalse;
@@ -37,10 +38,6 @@
 @Presubmit
 @FlakyTest
 public class StartActivityTests extends ActivityManagerTestBase {
-    private static final String SDK_CURRENT_PACKAGE = "android.server.am";
-
-    private static final ComponentName TEST_ACTIVITY = ComponentName.createRelative(
-            SDK_CURRENT_PACKAGE, ".TestActivity");
 
     @Rule
     public final ActivityTestRule<TestActivity2> mTestActivity2Rule =
diff --git a/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleClientTestBase.java b/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleClientTestBase.java
index a5673a6..421b542 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleClientTestBase.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleClientTestBase.java
@@ -24,6 +24,9 @@
     final ActivityTestRule mSecondActivityTestRule = new ActivityTestRule(SecondActivity.class,
             true /* initialTouchMode */, false /* launchActivity */);
 
+    final ActivityTestRule mTranslucentActivityTestRule = new ActivityTestRule(
+            TranslucentActivity.class, true /* initialTouchMode */, false /* launchActivity */);
+
     private final ActivityLifecycleMonitor mLifecycleMonitor = ActivityLifecycleMonitorRegistry
             .getInstance();
     private LifecycleLog mLifecycleLog;
@@ -80,4 +83,8 @@
     // Test activity
     public static class SecondActivity extends Activity {
     }
+
+    // Translucent test activity
+    public static class TranslucentActivity extends Activity {
+    }
 }
diff --git a/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleTests.java b/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleTests.java
index b785b6b..0ed41bf 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleTests.java
@@ -1,8 +1,17 @@
 package android.server.am.lifecycle;
 
+import static android.support.test.runner.lifecycle.Stage.CREATED;
 import static android.support.test.runner.lifecycle.Stage.DESTROYED;
+import static android.support.test.runner.lifecycle.Stage.PAUSED;
+import static android.support.test.runner.lifecycle.Stage.PRE_ON_CREATE;
 import static android.support.test.runner.lifecycle.Stage.RESUMED;
+import static android.support.test.runner.lifecycle.Stage.STARTED;
 import static android.support.test.runner.lifecycle.Stage.STOPPED;
+import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_180;
+import static android.view.Surface.ROTATION_270;
+import static android.view.Surface.ROTATION_90;
+import static org.junit.Assert.fail;
 
 import android.app.Activity;
 import android.content.Intent;
@@ -15,6 +24,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.Arrays;
+
 /**
  * Build/Install/Run:
  *     atest CtsActivityManagerDeviceTestCases:ActivityLifecycleTests
@@ -60,7 +71,7 @@
 
     @FlakyTest(bugId = 72956507)
     @Test
-    public void testRelaunch() throws Exception {
+    public void testRelaunchResumed() throws Exception {
         final Activity activity = mFirstActivityTestRule.launchActivity(new Intent());
         waitAndAssertActivityStates(state(activity, RESUMED));
 
@@ -68,6 +79,89 @@
         InstrumentationRegistry.getInstrumentation().runOnMainSync(activity::recreate);
         waitAndAssertActivityStates(state(activity, RESUMED));
 
-        LifecycleVerifier.assertRelaunchSequence(FirstActivity.class, getLifecycleLog());
+        LifecycleVerifier.assertRelaunchSequence(FirstActivity.class, getLifecycleLog(), RESUMED);
+    }
+
+    @FlakyTest(bugId = 72956507)
+    @Test
+    public void testRelaunchPaused() throws Exception {
+        final Activity pausedActivity = mFirstActivityTestRule.launchActivity(new Intent());
+        final Activity topTranslucentActivity =
+                mTranslucentActivityTestRule.launchActivity(new Intent());
+
+        waitAndAssertActivityStates(state(pausedActivity, PAUSED),
+                state(topTranslucentActivity, RESUMED));
+
+        getLifecycleLog().clear();
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(pausedActivity::recreate);
+        waitAndAssertActivityStates(state(pausedActivity, PAUSED));
+
+        LifecycleVerifier.assertRelaunchSequence(FirstActivity.class, getLifecycleLog(), PAUSED);
+    }
+
+    @FlakyTest(bugId = 72956507)
+    @Test
+    public void testRelaunchStopped() throws Exception {
+        final Activity stoppedActivity = mFirstActivityTestRule.launchActivity(new Intent());
+        final Activity topActivity = mSecondActivityTestRule.launchActivity(new Intent());
+
+        waitAndAssertActivityStates(state(stoppedActivity, STOPPED), state(topActivity, RESUMED));
+
+        getLifecycleLog().clear();
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(stoppedActivity::recreate);
+        waitAndAssertActivityStates(state(stoppedActivity, STOPPED));
+
+        LifecycleVerifier.assertRelaunchSequence(FirstActivity.class, getLifecycleLog(), STOPPED);
+    }
+
+    @FlakyTest(bugId = 72956507)
+    @Test
+    public void testRelaunchConfigurationChangedWhileBecomingVisible() throws Exception {
+        final Activity becomingVisibleActivity = mFirstActivityTestRule.launchActivity(new Intent());
+        final Activity translucentActivity =
+                mTranslucentActivityTestRule.launchActivity(new Intent());
+        final Activity topOpaqueActivity = mSecondActivityTestRule.launchActivity(new Intent());
+
+        waitAndAssertActivityStates(state(becomingVisibleActivity, STOPPED),
+                state(translucentActivity, STOPPED), state(topOpaqueActivity, RESUMED));
+
+        getLifecycleLog().clear();
+        try (final RotationSession rotationSession = new RotationSession()) {
+            final int current = rotationSession.get();
+            // Set new rotation to cause a configuration change.
+            switch (current) {
+                case ROTATION_0:
+                case ROTATION_180:
+                    rotationSession.set(ROTATION_90);
+                    break;
+                case ROTATION_90:
+                case ROTATION_270:
+                    rotationSession.set(ROTATION_0);
+                    break;
+                default:
+                    fail("Unknown rotation:" + current);
+            }
+
+            // Assert that the top activity was relaunched.
+            waitAndAssertActivityStates(state(topOpaqueActivity, RESUMED));
+            LifecycleVerifier.assertRelaunchSequence(
+                    SecondActivity.class, getLifecycleLog(), RESUMED);
+
+            // Finish the top activity
+            getLifecycleLog().clear();
+            mSecondActivityTestRule.finishActivity();
+
+            // Assert that the translucent activity and the activity visible behind it were
+            // relaunched.
+            waitAndAssertActivityStates(state(becomingVisibleActivity, PAUSED),
+                    state(translucentActivity, RESUMED));
+
+            LifecycleVerifier.assertSequence(FirstActivity.class, getLifecycleLog(),
+                    Arrays.asList(DESTROYED, PRE_ON_CREATE, CREATED, STARTED, RESUMED, PAUSED),
+                    "becomingVisiblePaused");
+            LifecycleVerifier.assertSequence(TranslucentActivity.class, getLifecycleLog(),
+                    Arrays.asList(DESTROYED, PRE_ON_CREATE, CREATED, STARTED, RESUMED),
+                    "becomingVisibleResumed");
+        }
     }
 }
diff --git a/tests/framework/base/activitymanager/src/android/server/am/lifecycle/LifecycleVerifier.java b/tests/framework/base/activitymanager/src/android/server/am/lifecycle/LifecycleVerifier.java
index bbb3ad8..9a966f3 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/lifecycle/LifecycleVerifier.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/lifecycle/LifecycleVerifier.java
@@ -71,13 +71,27 @@
     }
 
     static void assertRelaunchSequence(Class<? extends Activity> activityClass,
-            LifecycleLog lifecycleLog) {
+            LifecycleLog lifecycleLog, Stage startState) {
+        final List<Stage> expectedTransitions;
+        if (startState == PAUSED) {
+            expectedTransitions = Arrays.asList(
+                    STOPPED, DESTROYED, PRE_ON_CREATE, CREATED, STARTED, RESUMED, PAUSED);
+        } else if (startState == STOPPED) {
+            expectedTransitions = Arrays.asList(
+                    DESTROYED, PRE_ON_CREATE, CREATED, STARTED, RESUMED, PAUSED, STOPPED);
+        } else {
+            expectedTransitions = Arrays.asList(
+                    PAUSED, STOPPED, DESTROYED, PRE_ON_CREATE, CREATED, STARTED, RESUMED);
+        }
+        assertSequence(activityClass, lifecycleLog, expectedTransitions, "relaunch");
+    }
+
+    static void assertSequence(Class<? extends Activity> activityClass,
+            LifecycleLog lifecycleLog, List<Stage> expectedTransitions, String transition) {
         final List<Stage> observedTransitions = lifecycleLog.getActivityLog(activityClass);
         log("Observed sequence: " + observedTransitions);
-        final String errorMessage = errorDuringTransition(activityClass, "relaunch");
+        final String errorMessage = errorDuringTransition(activityClass, transition);
 
-        final List<Stage> expectedTransitions =
-                Arrays.asList(PAUSED, STOPPED, DESTROYED, PRE_ON_CREATE, CREATED, STARTED, RESUMED);
         assertEquals(errorMessage, expectedTransitions, observedTransitions);
     }
 
diff --git a/tests/framework/base/activitymanager/util/src/android/server/am/ActivityAndWindowManagersState.java b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityAndWindowManagersState.java
index 0095033..4fd76a3 100644
--- a/tests/framework/base/activitymanager/util/src/android/server/am/ActivityAndWindowManagersState.java
+++ b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityAndWindowManagersState.java
@@ -31,11 +31,14 @@
 import static android.server.am.StateLogger.logAlways;
 import static android.server.am.StateLogger.logE;
 
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.lessThan;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
@@ -79,14 +82,6 @@
     private ActivityManagerState mAmState = new ActivityManagerState();
     private WindowManagerState mWmState = new WindowManagerState();
 
-    /** TODO(b/73349193): Use {@link #computeState(ComponentName...)} instead. */
-    @Deprecated
-    public void computeState(String... simpleActivityNames) throws Exception {
-        computeState(true, Arrays.stream(simpleActivityNames)
-                .map(WaitForValidActivityState::new)
-                .toArray(WaitForValidActivityState[]::new));
-    }
-
     /**
      * Compute AM and WM state of device, check sanity and bounds.
      * WM state will include only visible windows, stack and task bounds will be compared.
@@ -146,22 +141,7 @@
         waitForValidState(false /* compareTaskAndStackBounds */, waitForActivityVisible);
     }
 
-    /**
-     * Wait for the activity to appear in proper stack and for valid state in AM and WM.
-     * TODO(b/73349193): Use {@link #waitForValidState(WaitForValidActivityState...)} instead.
-     *
-     * @param simpleActivityName name of activity to wait for.
-     * @param stackId                id of the stack where provided activity should be found.
-     */
-    @Deprecated
-    void waitForValidState(String simpleActivityName, int stackId) throws Exception {
-        waitForValidState(false /* compareTaskAndStackBounds */,
-                new WaitForValidActivityState.Builder(simpleActivityName)
-                        .setStackId(stackId)
-                        .build());
-    }
-
-    /** TODO(b/73349193): Use {@link #waitForValidState(WaitForValidActivityState...)} instead. */
+    // TODO(b/73349193): Use {@link #waitForValidState(WaitForValidActivityState...)} instead.
     @Deprecated
     void waitForValidState(String simpleActivityName, int windowingMode, int activityType)
             throws Exception {
@@ -342,7 +322,7 @@
                 "***Waiting for Activity State: " + activityState);
     }
 
-    /** TODO(b/73349193): Use {@link #waitForActivityState(ComponentName, String)} instead. */
+    // TODO(b/73349193): Use {@link #waitForActivityState(ComponentName, String)} instead.
     @Deprecated
     void waitForActivityState(String activityName, String activityState)
             throws Exception {
@@ -588,7 +568,7 @@
     }
 
     void assertSanity() throws Exception {
-        assertTrue("Must have stacks", mAmState.getStackCount() > 0);
+        assertThat("Must have stacks", mAmState.getStackCount(), greaterThan(0));
         if (!mAmState.getKeyguardControllerState().keyguardShowing) {
             assertEquals("There should be one and only one resumed activity in the system.",
                     1, mAmState.getResumedActivitiesCount());
@@ -612,12 +592,6 @@
         assertTrue(msg, mWmState.containsStack(windowingMode, activityType));
     }
 
-    @Deprecated
-    void assertDoesNotContainStack(String msg, int stackId) throws Exception {
-        assertFalse(msg, mAmState.containsStack(stackId));
-        assertFalse(msg, mWmState.containsStack(stackId));
-    }
-
     void assertDoesNotContainStack(String msg, int windowingMode, int activityType)
             throws Exception {
         assertFalse(msg, mAmState.containsStack(windowingMode, activityType));
@@ -687,13 +661,6 @@
         assertEquals(msg, getActivityName(activityName), mAmState.getResumedActivity());
     }
 
-    /** TODO(b/73349193): Use {@link #assertResumedActivity(String, ComponentName)} instead. */
-    @Deprecated
-    void assertResumedActivity(String msg, String activityName) throws Exception {
-        final String componentName = getActivityComponentName(activityName);
-        assertEquals(msg, componentName, mAmState.getResumedActivity());
-    }
-
     void assertNotResumedActivity(String msg, String activityName) throws Exception {
         final String componentName = getActivityComponentName(activityName);
         if (mAmState.getResumedActivity().equals(componentName)) {
@@ -715,7 +682,7 @@
         assertEquals(msg, windowName, mWmState.getFrontWindow());
     }
 
-    /** TODO(b/73349193): Use {@link #assertVisibility(ComponentName, boolean)} instead. */
+    // TODO(b/73349193): Use {@link #assertVisibility(ComponentName, boolean)} instead.
     @Deprecated
     public void assertVisibility(String activityName, boolean visible) {
         final String activityComponentName = getActivityComponentName(activityName);
@@ -732,14 +699,10 @@
         final boolean activityVisible = mAmState.isActivityVisible(activityComponentName);
         final boolean windowVisible = mWmState.isWindowVisible(windowName);
 
-        if (visible) {
-            assertTrue("Activity=" + activityComponentName + " must be visible.", activityVisible);
-            assertTrue("Window=" + windowName + " must be visible.", windowVisible);
-        } else {
-            assertFalse("Activity=" + activityComponentName + " must NOT be visible.",
-                    activityVisible);
-            assertFalse("Window=" + windowName + " must NOT be visible.", windowVisible);
-        }
+        assertEquals("Activity=" + activityComponentName + " must" + (visible ? "" : " NOT")
+                + " be visible.", visible, activityVisible);
+        assertEquals("Window=" + windowName + " must" + (visible ? "" : " NOT") + " be visible.",
+                visible, windowVisible);
     }
 
     void assertHomeActivityVisible(boolean visible) {
@@ -843,7 +806,7 @@
     /**
      * Check task bounds when docked to top/left.
      */
-    void assertDockedTaskBounds(int taskWidth, int taskHeight, String activityName) {
+    void assertDockedTaskBounds(int taskWidth, int taskHeight, ComponentName activityName) {
         // Task size can be affected by default minimal size.
         int defaultMinimalTaskSize = defaultMinimalTaskSize(
                 mAmState.getStandardStackByWindowingMode(
@@ -852,7 +815,7 @@
         int targetHeight = Math.max(taskHeight, defaultMinimalTaskSize);
 
         assertEquals(new Rect(0, 0, targetWidth, targetHeight),
-                mAmState.getTaskByActivityName(activityName).getBounds());
+                mAmState.getTaskByActivity(activityName).getBounds());
     }
 
     void assertValidBounds(boolean compareTaskAndStackBounds) {
@@ -958,16 +921,16 @@
                                 assertEquals("Task width must be equal to stack width taskId="
                                                 + taskId + ", stackId=" + stackId,
                                         aStackBounds.width(), wTaskBounds.width());
-                                assertTrue("Task height must be greater than stack height "
+                                assertThat("Task height must be greater than stack height "
                                                 + "taskId=" + taskId + ", stackId=" + stackId,
-                                        aStackBounds.height() < wTaskBounds.height());
+                                        aStackBounds.height(), lessThan(wTaskBounds.height()));
                                 assertEquals("Task and stack x position must be equal taskId="
                                                 + taskId + ", stackId=" + stackId,
                                         wTaskBounds.left, wStackBounds.left);
                             } else {
-                                assertTrue("Task width must be greater than stack width taskId="
+                                assertThat("Task width must be greater than stack width taskId="
                                                 + taskId + ", stackId=" + stackId,
-                                        aStackBounds.width() < wTaskBounds.width());
+                                        aStackBounds.width(), lessThan(wTaskBounds.width()));
                                 assertEquals("Task height must be equal to stack height taskId="
                                                 + taskId + ", stackId=" + stackId,
                                         aStackBounds.height(), wTaskBounds.height());
diff --git a/tests/framework/base/activitymanager/util/src/android/server/am/ActivityLauncher.java b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityLauncher.java
new file mode 100644
index 0000000..1be32de
--- /dev/null
+++ b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityLauncher.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.server.am;
+
+import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
+import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
+
+import android.app.ActivityOptions;
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+
+/** Utility class which contains common code for launching activities. */
+public class ActivityLauncher {
+    private static final String TAG = ActivityLauncher.class.getSimpleName();
+
+    /** Key for boolean extra, indicates whether it should launch an activity. */
+    public static final String KEY_LAUNCH_ACTIVITY = "launch_activity";
+    /**
+     * Key for boolean extra, indicates whether it the activity should be launched to side in
+     * split-screen.
+     */
+    public static final String KEY_LAUNCH_TO_SIDE = "launch_to_the_side";
+    /**
+     * Key for boolean extra, indicates if launch intent should include random data to be different
+     * from other launch intents.
+     */
+    public static final String KEY_RANDOM_DATA = "random_data";
+    /**
+     * Key for boolean extra, indicates if launch intent should have
+     * {@link Intent#FLAG_ACTIVITY_NEW_TASK}.
+     */
+    public static final String KEY_NEW_TASK = "new_task";
+    /**
+     * Key for boolean extra, indicates if launch intent should have
+     * {@link Intent#FLAG_ACTIVITY_MULTIPLE_TASK}.
+     */
+    public static final String KEY_MULTIPLE_TASK = "multiple_task";
+    /**
+     * Key for boolean extra, indicates if launch intent should have
+     * {@link Intent#FLAG_ACTIVITY_REORDER_TO_FRONT}.
+     */
+    public static final String KEY_REORDER_TO_FRONT = "reorder_to_front";
+    /**
+     * Key for string extra with string representation of target component.
+     */
+    public static final String KEY_TARGET_COMPONENT = "target_component";
+    /**
+     * Key for string extra with target activity name.
+     */
+    public static final String KEY_TARGET_ACTIVITY = "target_activity";
+    /**
+     * Key for string extra with target package name. If {@link #KEY_TARGET_ACTIVITY} is provided
+     * and this extra is not, then current application's package name will be used.
+     */
+    public static final String KEY_TARGET_PACKAGE = "target_package";
+    /**
+     * Key for int extra with target display id where the activity should be launched. Adding this
+     * automatically applies {@link Intent#FLAG_ACTIVITY_NEW_TASK} and
+     * {@link Intent#FLAG_ACTIVITY_MULTIPLE_TASK} to the intent.
+     */
+    public static final String KEY_DISPLAY_ID = "display_id";
+    /**
+     * Key for boolean extra, indicates if launch should be done from application context of the one
+     * passed in {@link #launchActivityFromExtras(Context, Bundle)}.
+     */
+    public static final String KEY_USE_APPLICATION_CONTEXT = "use_application_context";
+    /**
+     * Key for boolean extra, indicates if instrumentation context will be used for launch. This
+     * means that {@link PendingIntent} should be used instead of a regular one, because application
+     * switch will not be allowed otherwise.
+     */
+    public static final String KEY_USE_INSTRUMENTATION = "use_instrumentation";
+    /**
+     * Key for boolean extra, indicates if any exceptions thrown during launch other then
+     * {@link SecurityException} should be suppressed. A {@link SecurityException} is never thrown,
+     * it's always written to logs.
+     */
+    public static final String KEY_SUPPRESS_EXCEPTIONS = "suppress_exceptions";
+
+
+    /** Perform an activity launch configured by provided extras. */
+    public static void launchActivityFromExtras(final Context context, Bundle extras) {
+        if (extras == null || !extras.getBoolean(KEY_LAUNCH_ACTIVITY)) {
+            return;
+        }
+
+        Log.i(TAG, "launchActivityFromExtras: extras=" + extras);
+
+        final Intent newIntent = new Intent();
+        final String targetComponent = extras.getString(KEY_TARGET_COMPONENT);
+        final String targetActivity = extras.getString(KEY_TARGET_ACTIVITY);
+        if (!TextUtils.isEmpty(targetComponent)) {
+            newIntent.setComponent(ComponentName.unflattenFromString(targetComponent));
+        } else if (targetActivity != null) {
+            final String extraPackageName = extras.getString(KEY_TARGET_PACKAGE);
+            final String packageName = extraPackageName != null ? extraPackageName
+                    : context.getApplicationContext().getPackageName();
+            newIntent.setComponent(new ComponentName(packageName,
+                    packageName + "." + targetActivity));
+        } else {
+            newIntent.setComponent(new ComponentName("android.server.am",
+                    "android.server.am.TestActivity"));
+        }
+
+        if (extras.getBoolean(KEY_LAUNCH_TO_SIDE)) {
+            newIntent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_LAUNCH_ADJACENT);
+            if (extras.getBoolean(KEY_RANDOM_DATA)) {
+                final Uri data = new Uri.Builder()
+                        .path(String.valueOf(System.currentTimeMillis()))
+                        .build();
+                newIntent.setData(data);
+            }
+        }
+        if (extras.getBoolean(KEY_MULTIPLE_TASK)) {
+            newIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
+        }
+        if (extras.getBoolean(KEY_NEW_TASK)) {
+            newIntent.addFlags(FLAG_ACTIVITY_NEW_TASK);
+        }
+
+        if (extras.getBoolean(KEY_REORDER_TO_FRONT)) {
+            newIntent.addFlags(FLAG_ACTIVITY_REORDER_TO_FRONT);
+        }
+
+        ActivityOptions options = null;
+        final int displayId = extras.getInt(KEY_DISPLAY_ID, -1);
+        if (displayId != -1) {
+            options = ActivityOptions.makeBasic();
+            options.setLaunchDisplayId(displayId);
+            newIntent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK);
+        }
+        final Bundle optionsBundle = options != null ? options.toBundle() : null;
+
+        final Context launchContext = extras.getBoolean(KEY_USE_APPLICATION_CONTEXT) ?
+                context.getApplicationContext() : context;
+
+        try {
+            if (extras.getBoolean(KEY_USE_INSTRUMENTATION)) {
+                // Using PendingIntent for Instrumentation launches, because otherwise we won't
+                // be allowed to switch the current activity with ours with different uid.
+                // android.permission.STOP_APP_SWITCHES is needed to do this directly.
+                final PendingIntent pendingIntent = PendingIntent.getActivity(launchContext, 0,
+                        newIntent, 0, optionsBundle);
+                pendingIntent.send();
+            } else {
+                launchContext.startActivity(newIntent, optionsBundle);
+            }
+        } catch (SecurityException e) {
+            Log.e(TAG, "SecurityException launching activity");
+        } catch (PendingIntent.CanceledException e) {
+            if (extras.getBoolean(KEY_SUPPRESS_EXCEPTIONS)) {
+                Log.e(TAG, "Exception launching activity with pending intent");
+            } else {
+                throw new RuntimeException(e);
+            }
+            Log.e(TAG, "SecurityException launching activity");
+        } catch (Exception e) {
+            if (extras.getBoolean(KEY_SUPPRESS_EXCEPTIONS)) {
+                Log.e(TAG, "Exception launching activity");
+            } else {
+                throw e;
+            }
+        }
+    }
+}
diff --git a/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerState.java b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerState.java
index 4ff510b..345365f 100644
--- a/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerState.java
+++ b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerState.java
@@ -300,8 +300,8 @@
     }
 
     /** Get the stack position on its display. */
-    int getStackIndexByActivityName(String activityName) {
-        final String fullName = getActivityComponentName(activityName);
+    int getStackIndexByActivity(ComponentName activityName) {
+        final String fullName = getActivityName(activityName);
 
         for (ActivityDisplay display : mDisplays) {
             for (int i = display.mStacks.size() - 1; i >= 0; --i) {
@@ -498,10 +498,8 @@
                 getActivityComponentName(activityName), WINDOWING_MODE_UNDEFINED);
     }
 
-    /** TODO(b/73349193): Add getTaskByActicityOfWidowingMode(Component, int). */
-    @Deprecated
-    ActivityTask getTaskByActivityName(String activityName, int windowingMode) {
-        return getTaskByActivityInternal(getActivityComponentName(activityName), windowingMode);
+    ActivityTask getTaskByActivity(ComponentName activityName, int windowingMode) {
+        return getTaskByActivityInternal(getActivityName(activityName), windowingMode);
     }
 
     private ActivityTask getTaskByActivityInternal(String fullName, int windowingMode) {
diff --git a/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerTestBase.java b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerTestBase.java
index 4813ac6..4e39e2a 100644
--- a/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerTestBase.java
+++ b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerTestBase.java
@@ -33,6 +33,20 @@
 import static android.content.pm.PackageManager.FEATURE_SCREEN_PORTRAIT;
 import static android.content.pm.PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE;
 import static android.content.pm.PackageManager.FEATURE_WATCH;
+import static android.server.am.ActivityLauncher.KEY_DISPLAY_ID;
+import static android.server.am.ActivityLauncher.KEY_LAUNCH_ACTIVITY;
+import static android.server.am.ActivityLauncher.KEY_LAUNCH_TO_SIDE;
+import static android.server.am.ActivityLauncher.KEY_MULTIPLE_TASK;
+import static android.server.am.ActivityLauncher.KEY_NEW_TASK;
+import static android.server.am.ActivityLauncher.KEY_RANDOM_DATA;
+import static android.server.am.ActivityLauncher.KEY_REORDER_TO_FRONT;
+import static android.server.am.ActivityLauncher.KEY_SUPPRESS_EXCEPTIONS;
+import static android.server.am.ActivityLauncher.KEY_TARGET_ACTIVITY;
+import static android.server.am.ActivityLauncher.KEY_TARGET_COMPONENT;
+import static android.server.am.ActivityLauncher.KEY_TARGET_PACKAGE;
+import static android.server.am.ActivityLauncher.KEY_USE_APPLICATION_CONTEXT;
+import static android.server.am.ActivityLauncher.KEY_USE_INSTRUMENTATION;
+import static android.server.am.ActivityLauncher.launchActivityFromExtras;
 import static android.server.am.ComponentNameUtils.getActivityName;
 import static android.server.am.ComponentNameUtils.getLogTag;
 import static android.server.am.ComponentNameUtils.getSimpleClassName;
@@ -40,10 +54,14 @@
 import static android.server.am.StateLogger.log;
 import static android.server.am.StateLogger.logAlways;
 import static android.server.am.StateLogger.logE;
-import static android.view.KeyEvent.KEYCODE_APP_SWITCH;
-import static android.view.KeyEvent.KEYCODE_MENU;
-import static android.view.KeyEvent.KEYCODE_SLEEP;
-import static android.view.KeyEvent.KEYCODE_WAKEUP;
+import static android.server.am.UiDeviceUtils.pressAppSwitchButton;
+import static android.server.am.UiDeviceUtils.pressBackButton;
+import static android.server.am.UiDeviceUtils.pressEnterButton;
+import static android.server.am.UiDeviceUtils.pressHomeButton;
+import static android.server.am.UiDeviceUtils.pressSleepButton;
+import static android.server.am.UiDeviceUtils.pressUnlockButton;
+import static android.server.am.UiDeviceUtils.pressWakeupButton;
+import static android.server.am.UiDeviceUtils.waitForDeviceIdle;
 
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
@@ -51,18 +69,17 @@
 import static java.lang.Integer.toHexString;
 
 import android.app.ActivityManager;
-import android.app.KeyguardManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.graphics.Bitmap;
+import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
-import android.os.PowerManager;
+import android.os.SystemClock;
 import android.provider.Settings;
 import android.server.am.settings.SettingsSession;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.test.InstrumentationRegistry;
-import android.support.test.uiautomator.UiDevice;
 import android.view.Display;
 
 import com.android.compatibility.common.util.SystemUtil;
@@ -82,7 +99,6 @@
 import java.util.Map;
 import java.util.UUID;
 import java.util.concurrent.TimeUnit;
-import java.util.function.BooleanSupplier;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
@@ -114,9 +130,8 @@
     private static final String AM_MOVE_TOP_ACTIVITY_TO_PINNED_STACK_COMMAND_FORMAT =
             "am stack move-top-activity-to-pinned-stack %1d 0 0 500 500";
 
-    static final String LAUNCHING_ACTIVITY = "LaunchingActivity";
-    static final String ALT_LAUNCHING_ACTIVITY = "AltLaunchingActivity";
-    static final String BROADCAST_RECEIVER_ACTIVITY = "BroadcastReceiverActivity";
+    // TODO(b/73349193): Remove this.
+    static final String LAUNCHING_ACTIVITY_NAME = "LaunchingActivity";
 
     /** Broadcast shell command for finishing {@link BroadcastReceiverActivity}. */
     static final String FINISH_ACTIVITY_BROADCAST
@@ -151,9 +166,8 @@
 
     protected Context mContext;
     protected ActivityManager mAm;
-    protected UiDevice mDevice;
 
-    /** TODO(b/73349193): Use {@link #getAmStartCmd(ComponentName, String...)} instead. */
+    // TODO(b/73349193): Use {@link #getAmStartCmd(ComponentName, String...)} instead.
     @Deprecated
     protected static String getAmStartCmd(final String activityName) {
         return "am start -n " + getActivityComponentName(activityName);
@@ -169,7 +183,7 @@
         return getAmStartCmdInternal(getActivityName(activityName), keyValuePairs);
     }
 
-    /** TODO(b/73349193): Use {@link #getAmStartCmd(ComponentName, String...)} instead. */
+    // TODO(b/73349193): Use {@link #getAmStartCmd(ComponentName, String...)} instead.
     @Deprecated
     protected static String getAmStartCmd(final String activityName,
             final String... keyValuePairs) {
@@ -204,7 +218,7 @@
         return getAmStartCmdInternal(getActivityName(activityName), displayId, keyValuePair);
     }
 
-    /** TODO(b/73349193): Use {@link #getAmStartCmd(ComponentName, String...)} instead. */
+    // TODO(b/73349193): Use {@link #getAmStartCmd(ComponentName, String...)} instead.
     @Deprecated
     protected static String getAmStartCmd(final String activityName, final int displayId,
             final String... keyValuePair) {
@@ -224,6 +238,12 @@
                 keyValuePairs);
     }
 
+    protected static String getAmStartCmdInNewTask(final ComponentName activityName) {
+        return "am start -n " + getActivityName(activityName) + " -f 0x18000000";
+    }
+
+    /** TODO(b/73349193): Use {@link #getAmStartCmdInNewTask(ComponentName)} instead. */
+    @Deprecated
     protected static String getAmStartCmdInNewTask(final String activityName) {
         return "am start -n " + getActivityComponentName(activityName) + " -f 0x18000000";
     }
@@ -308,7 +328,6 @@
     public void setUp() throws Exception {
         mContext = InstrumentationRegistry.getContext();
         mAm = mContext.getSystemService(ActivityManager.class);
-        mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
         setDefaultComponentName();
         executeShellCommand("pm grant " + mContext.getPackageName()
                 + " android.permission.MANAGE_ACTIVITY_STACKS");
@@ -369,23 +388,13 @@
         return InstrumentationRegistry.getInstrumentation().getUiAutomation().takeScreenshot();
     }
 
-    /** TODO(b/73349193): Remove this method. */
-    @Deprecated
-    protected void launchActivityInComponent(final String componentName,
-            final String targetActivityName, final String... keyValuePairs) throws Exception {
-        final String originalComponentName = ActivityManagerTestBase.componentName;
-        setComponentName(componentName);
-        launchActivity(targetActivityName, keyValuePairs);
-        setComponentName(originalComponentName);
-    }
-
     protected void launchActivity(final ComponentName activityName, final String... keyValuePairs)
             throws Exception {
         executeShellCommand(getAmStartCmd(activityName, keyValuePairs));
         mAmWmState.waitForValidState(new WaitForValidActivityState(activityName));
     }
 
-    /** TODO(b/73349193): Use {@link #launchActivity(ComponentName, String...)} instead. */
+    // TODO(b/73349193): Use {@link #launchActivity(ComponentName, String...)} instead.
     @Deprecated
     protected void launchActivity(final String targetActivityName, final String... keyValuePairs)
             throws Exception {
@@ -398,17 +407,9 @@
         executeShellCommand(getAmStartCmd(targetActivityName, keyValuePairs));
     }
 
-    /** TODO(b/73349193): Use {@link #launchActivity(ComponentName, String...)} instead. */
-    @Deprecated
-    protected void launchActivityNoWait(final String targetActivityName,
-            final String... keyValuePairs) throws Exception {
-        executeShellCommand(getAmStartCmd(targetActivityName, keyValuePairs));
-    }
-
-    @Deprecated
-    protected void launchActivityInNewTask(final String targetActivityName) throws Exception {
-        executeShellCommand(getAmStartCmdInNewTask(targetActivityName));
-        mAmWmState.waitForValidState(targetActivityName);
+    protected void launchActivityInNewTask(final ComponentName activityName) throws Exception {
+        executeShellCommand(getAmStartCmdInNewTask(activityName));
+        mAmWmState.waitForValidState(activityName);
     }
 
     /**
@@ -460,7 +461,7 @@
                 .build());
     }
 
-    /** TODO(b/73349193): Use {@link #launchActivity(ComponentName, int, String...)} instead. */
+    // TODO(b/73349193): Use {@link #launchActivity(ComponentName, int, String...)} instead.
     @Deprecated
     protected void launchActivity(String activityName, int windowingMode,
             final String... keyValuePairs) throws Exception {
@@ -478,7 +479,7 @@
         mAmWmState.waitForValidState(new WaitForValidActivityState(targetActivityName));
     }
 
-    /** TODO(b/73349193): Use {@link #launchActivityOnDisplay(ComponentName, int, String...)} */
+    // TODO(b/73349193): Use {@link #launchActivityOnDisplay(ComponentName, int, String...)}
     @Deprecated
     protected void launchActivityOnDisplay(String targetActivityName, int displayId,
             String... keyValuePairs) throws Exception {
@@ -491,51 +492,37 @@
      * Launches {@param  activityName} into split-screen primary windowing mode and also makes
      * the recents activity visible to the side of it.
      */
-    protected void launchActivityInSplitScreenWithRecents(String activityName) throws Exception {
+    protected void launchActivityInSplitScreenWithRecents(
+            ComponentName activityName) throws Exception {
         launchActivityInSplitScreenWithRecents(activityName, SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT);
     }
 
-    protected void launchActivityInSplitScreenWithRecents(String activityName, int createMode)
-            throws Exception {
+    protected void launchActivityInSplitScreenWithRecents(
+            ComponentName activityName, int createMode) throws Exception {
         launchActivity(activityName);
-        final int taskId = mAmWmState.getAmState().getTaskByActivityName(activityName).mTaskId;
+        final int taskId = mAmWmState.getAmState().getTaskByActivity(activityName).mTaskId;
         mAm.setTaskWindowingModeSplitScreenPrimary(taskId, createMode, true /* onTop */,
                 false /* animate */, null /* initialBounds */, true /* showRecents */);
 
-        mAmWmState.waitForValidState(activityName,
-                WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
+        mAmWmState.waitForValidState(
+                new WaitForValidActivityState.Builder(activityName)
+                        .setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)
+                        .setActivityType(ACTIVITY_TYPE_STANDARD)
+                        .build());
         mAmWmState.waitForRecentsActivityVisible();
     }
 
     /**
-     * TODO(b/73349193): Use
-     * {@link #launchActivitiesInSplitScreen(LaunchActivityBuilder, LaunchActivityBuilder)
-     */
-    @Deprecated
-    protected void launchActivitiesInSplitScreen(String primaryActivity, String secondaryActivity)
-            throws Exception {
-        launchActivitiesInSplitScreen(
-                getLaunchActivityBuilder().setTargetActivityName(primaryActivity),
-                getLaunchActivityBuilder().setTargetActivityName(secondaryActivity));
-    }
-
-    /**
      * Launches {@param primaryActivity} into split-screen primary windowing mode
      * and {@param secondaryActivity} to the side in split-screen secondary windowing mode.
      */
     protected void launchActivitiesInSplitScreen(LaunchActivityBuilder primaryActivity,
             LaunchActivityBuilder secondaryActivity) throws Exception {
         // Launch split-screen primary.
-        String tmpLaunchingActivityName = primaryActivity.mLaunchingActivityName;
         primaryActivity
-                // TODO(b/70618153): Work around issues with the activity launch builder where
-                // launching activity doesn't work. We don't really need launching activity in this
-                // case and should probably change activity launcher to work without a launching
-                // activity.
-                .setLaunchingActivityName(primaryActivity.mTargetActivityName)
+                .setUseInstrumentation()
                 .setWaitForLaunched(true)
                 .execute();
-        primaryActivity.setLaunchingActivityName(tmpLaunchingActivityName);
 
         final int taskId = mAmWmState.getAmState().getTaskByActivityName(
                 primaryActivity.mTargetActivityName).mTaskId;
@@ -545,17 +532,13 @@
         mAmWmState.waitForRecentsActivityVisible();
 
         // Launch split-screen secondary
-        tmpLaunchingActivityName = secondaryActivity.mLaunchingActivityName;
+        // Recents become focused, so we can just launch new task in focused stack
         secondaryActivity
-                // TODO(b/70618153): Work around issues with the activity launch builder where
-                // launching activity doesn't work. We don't really need launching activity in this
-                // case and should probably change activity launcher to work without a launching
-                // activity.
-                .setLaunchingActivityName(secondaryActivity.mTargetActivityName)
+                .setUseInstrumentation()
                 .setWaitForLaunched(true)
-                .setToSide(true)
+                .setNewTask(true)
+                .setMultipleTask(true)
                 .execute();
-        secondaryActivity.setLaunchingActivityName(tmpLaunchingActivityName);
     }
 
     protected void setActivityTaskWindowingMode(final ComponentName activityName,
@@ -568,7 +551,7 @@
                 .build());
     }
 
-    /** TODO(b/73349193): Use {@link #setActivityTaskWindowingMode(ComponentName, int)} instead. */
+    // TODO(b/73349193): Use {@link #setActivityTaskWindowingMode(ComponentName, int)} instead.
     @Deprecated
     protected void setActivityTaskWindowingMode(String activityName, int windowingMode)
             throws Exception {
@@ -577,17 +560,24 @@
         mAmWmState.waitForValidState(activityName, windowingMode, ACTIVITY_TYPE_STANDARD);
     }
 
-    protected void moveActivityToStack(String activityName, int stackId) throws Exception {
+    protected void moveActivityToStack(ComponentName activityName, int stackId) throws Exception {
         final int taskId = getActivityTaskId(activityName);
         final String cmd = AM_MOVE_TASK + taskId + " " + stackId + " true";
         executeShellCommand(cmd);
 
-        mAmWmState.waitForValidState(activityName, stackId);
+        mAmWmState.waitForValidState(new WaitForValidActivityState.Builder(activityName)
+                .setStackId(stackId)
+                .build());
     }
 
-    protected void resizeActivityTask(String activityName, int left, int top, int right, int bottom)
+    protected void resizeActivityTask(
+            ComponentName activityName, int left, int top, int right, int bottom)
             throws Exception {
-        final int taskId = getActivityTaskId(activityName);
+        resizeActivityTask(getActivityTaskId(activityName), left, top, right, bottom);
+    }
+
+    private void resizeActivityTask(int taskId, int left, int top, int right, int bottom)
+            throws Exception {
         final String cmd = "am task resize "
                 + taskId + " " + left + " " + top + " " + right + " " + bottom;
         executeShellCommand(cmd);
@@ -606,57 +596,12 @@
                 stackTop, stackWidth, stackHeight));
     }
 
-    protected void pressHomeButton() {
-        mDevice.pressHome();
-    }
-
-    protected void pressBackButton() {
-        mDevice.pressBack();
-    }
-
-    protected void pressAppSwitchButton() throws Exception {
-        mDevice.pressKeyCode(KEYCODE_APP_SWITCH);
+    protected void pressAppSwitchButtonAndWaitForRecents() throws Exception {
+        pressAppSwitchButton();
         mAmWmState.waitForRecentsActivityVisible();
         mAmWmState.waitForAppTransitionIdle();
     }
 
-    protected void pressWakeupButton() {
-        final PowerManager pm = mContext.getSystemService(PowerManager.class);
-        retryPressKeyCode(KEYCODE_WAKEUP, () -> pm != null && pm.isInteractive(),
-                "***Waiting for device wakeup...");
-    }
-
-    protected void pressUnlockButton() {
-        final KeyguardManager kgm = mContext.getSystemService(KeyguardManager.class);
-        retryPressKeyCode(KEYCODE_MENU, () -> kgm != null && !kgm.isKeyguardLocked(),
-                "***Waiting for device unlock...");
-    }
-
-    protected void pressSleepButton() {
-        final PowerManager pm = mContext.getSystemService(PowerManager.class);
-        retryPressKeyCode(KEYCODE_SLEEP, () -> pm != null && !pm.isInteractive(),
-                "***Waiting for device sleep...");
-    }
-
-    private void retryPressKeyCode(int keyCode, BooleanSupplier waitFor, String msg) {
-        int retry = 1;
-        do {
-            mDevice.pressKeyCode(keyCode);
-            if (waitFor.getAsBoolean()) {
-                return;
-            }
-            logAlways(msg + " retry=" + retry);
-            try {
-                Thread.sleep(50);
-            } catch (InterruptedException e) {
-                logE("Sleep interrupted: " + msg, e);
-            }
-        } while (retry++ < 5);
-        if (!waitFor.getAsBoolean()) {
-            logE(msg + " FAILED");
-        }
-    }
-
     // Utility method for debugging, not used directly here, but useful, so kept around.
     protected void printStacksAndTasks() {
         String output = executeShellCommand(AM_STACK_LIST);
@@ -670,7 +615,7 @@
         return getWindowTaskId(getWindowName(activityName));
     }
 
-    /** TODO(b/73349193): Use {@link #getActivityTaskId(ComponentName)} instead. */
+    // TODO(b/73349193): Use {@link #getActivityTaskId(ComponentName)} instead.
     @Deprecated
     protected int getActivityTaskId(final String activityName) {
         return getWindowTaskId(getActivityWindowName(activityName));
@@ -848,10 +793,10 @@
         }
 
         public LockScreenSession enterAndConfirmLockCredential() throws Exception {
-            mDevice.waitForIdle(3000);
+            waitForDeviceIdle(3000);
 
             runCommandAndPrintOutput("input text " + LOCK_CREDENTIAL);
-            mDevice.pressEnter();
+            pressEnterButton();
             return this;
         }
 
@@ -869,12 +814,7 @@
             pressSleepButton();
             for (int retry = 1; isDisplayOn() && retry <= 5; retry++) {
                 logAlways("***Waiting for display to turn off... retry=" + retry);
-                try {
-                    Thread.sleep(1000);
-                } catch (InterruptedException e) {
-                    logAlways(e.toString());
-                    // Well I guess we are not waiting...
-                }
+                SystemClock.sleep(TimeUnit.SECONDS.toMillis(1));
             }
             return this;
         }
@@ -939,7 +879,7 @@
     protected class RotationSession extends SettingsSession<Integer> {
         private final SettingsSession<Integer> mUserRotation;
 
-        RotationSession() throws Exception {
+        public RotationSession() throws Exception {
             // Save accelerometer_rotation preference.
             super(Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION),
                     Settings.System::getInt, Settings.System::putInt);
@@ -1066,11 +1006,7 @@
                     return;
                 }
                 logAlways(waitingMessage + ": " + resultString);
-                try {
-                    Thread.sleep(RETRY_INTERVAL);
-                } catch (InterruptedException e) {
-                    logE(waitingMessage + ": interrupted", e);
-                }
+                SystemClock.sleep(RETRY_INTERVAL);
             }
             fail(resultString);
         }
@@ -1122,36 +1058,37 @@
         }
     }
 
-    void assertActivityLifecycle(
-            String activityName, boolean relaunched, LogSeparator logSeparator) {
+    void assertActivityLifecycle(ComponentName activityName, boolean relaunched,
+            LogSeparator logSeparator) {
+        final String logTag = getLogTag(activityName);
         new RetryValidator() {
 
             @Nullable
             @Override
             protected String validate() {
                 final ActivityLifecycleCounts lifecycleCounts =
-                        new ActivityLifecycleCounts(activityName, logSeparator);
+                        new ActivityLifecycleCounts(logTag, logSeparator);
                 if (relaunched) {
                     if (lifecycleCounts.mDestroyCount < 1) {
-                        return activityName + " must have been destroyed. mDestroyCount="
+                        return logTag + " must have been destroyed. mDestroyCount="
                                 + lifecycleCounts.mDestroyCount;
                     }
                     if (lifecycleCounts.mCreateCount < 1) {
-                        return activityName + " must have been (re)created. mCreateCount="
+                        return logTag + " must have been (re)created. mCreateCount="
                                 + lifecycleCounts.mCreateCount;
                     }
                     return null;
                 }
                 if (lifecycleCounts.mDestroyCount > 0) {
-                    return activityName + " must *NOT* have been destroyed. mDestroyCount="
+                    return logTag + " must *NOT* have been destroyed. mDestroyCount="
                             + lifecycleCounts.mDestroyCount;
                 }
                 if (lifecycleCounts.mCreateCount > 0) {
-                    return activityName + " must *NOT* have been (re)created. mCreateCount="
+                    return logTag + " must *NOT* have been (re)created. mCreateCount="
                             + lifecycleCounts.mCreateCount;
                 }
                 if (lifecycleCounts.mConfigurationChangedCount < 1) {
-                    return activityName + " must have received configuration changed. "
+                    return logTag + " must have received configuration changed. "
                             + "mConfigurationChangedCount="
                             + lifecycleCounts.mConfigurationChangedCount;
                 }
@@ -1160,23 +1097,24 @@
         }.assertValidator("***Waiting for valid lifecycle state");
     }
 
-    protected void assertRelaunchOrConfigChanged(String activityName, int numRelaunch,
+    protected void assertRelaunchOrConfigChanged(ComponentName activityName, int numRelaunch,
             int numConfigChange, LogSeparator logSeparator) {
+        final String logTag = getLogTag(activityName);
         new RetryValidator() {
 
             @Nullable
             @Override
             protected String validate() {
                 final ActivityLifecycleCounts lifecycleCounts =
-                        new ActivityLifecycleCounts(activityName, logSeparator);
+                        new ActivityLifecycleCounts(logTag, logSeparator);
                 if (lifecycleCounts.mDestroyCount != numRelaunch) {
-                    return activityName + " has been destroyed " + lifecycleCounts.mDestroyCount
+                    return logTag + " has been destroyed " + lifecycleCounts.mDestroyCount
                             + " time(s), expecting " + numRelaunch;
                 } else if (lifecycleCounts.mCreateCount != numRelaunch) {
-                    return activityName + " has been (re)created " + lifecycleCounts.mCreateCount
+                    return logTag + " has been (re)created " + lifecycleCounts.mCreateCount
                             + " time(s), expecting " + numRelaunch;
                 } else if (lifecycleCounts.mConfigurationChangedCount != numConfigChange) {
-                    return activityName + " has received "
+                    return logTag + " has received "
                             + lifecycleCounts.mConfigurationChangedCount
                             + " onConfigurationChanged() calls, expecting " + numConfigChange;
                 }
@@ -1185,7 +1123,7 @@
         }.assertValidator("***Waiting for relaunch or config changed");
     }
 
-    protected void assertActivityDestroyed(String activityName, LogSeparator logSeparator) {
+    protected void assertActivityDestroyed(ComponentName activityName, LogSeparator logSeparator) {
         new RetryValidator() {
 
             @Nullable
@@ -1195,13 +1133,16 @@
                         new ActivityLifecycleCounts(activityName, logSeparator);
 
                 if (lifecycleCounts.mDestroyCount != 1) {
-                    return activityName + " has been destroyed " + lifecycleCounts.mDestroyCount
+                    return getActivityName(activityName) + " has been destroyed "
+                            + lifecycleCounts.mDestroyCount
                             + " time(s), expecting single destruction.";
-                } else if (lifecycleCounts.mCreateCount != 0) {
-                    return activityName + " has been (re)created " + lifecycleCounts.mCreateCount
-                            + " time(s), not expecting any.";
-                } else if (lifecycleCounts.mConfigurationChangedCount != 0) {
-                    return activityName + " has received "
+                }
+                if (lifecycleCounts.mCreateCount != 0) {
+                    return getActivityName(activityName) + " has been (re)created "
+                            + lifecycleCounts.mCreateCount + " time(s), not expecting any.";
+                }
+                if (lifecycleCounts.mConfigurationChangedCount != 0) {
+                    return getActivityName(activityName) + " has received "
                             + lifecycleCounts.mConfigurationChangedCount
                             + " onConfigurationChanged() calls, not expecting any.";
                 }
@@ -1214,7 +1155,7 @@
         assertSingleLaunch(getLogTag(activityName), logSeparator);
     }
 
-    /** TODO(b/73349193): Use {@link #assertSingleLaunch(ComponentName, LogSeparator)} instead. */
+    // TODO(b/73349193): Use {@link #assertSingleLaunch(ComponentName, LogSeparator)} instead.
     @Deprecated
     void assertSingleLaunch(String logTag, LogSeparator logSeparator) {
         new ActivityLifecycleCountsValidator(logTag, logSeparator, 1 /* createCount */,
@@ -1224,10 +1165,10 @@
     }
 
     void assertSingleLaunchAndStop(ComponentName activityName, LogSeparator logSeparator) {
-        assertSingleStartAndStop(getLogTag(activityName), logSeparator);
+        assertSingleLaunchAndStop(getLogTag(activityName), logSeparator);
     }
 
-    /** TODO(b/73349193): Use {@link #assertSingleLaunchAndStop(ComponentName, LogSeparator)}. */
+    // TODO(b/73349193): Use {@link #assertSingleLaunchAndStop(ComponentName, LogSeparator)}.
     @Deprecated
     void assertSingleLaunchAndStop(String logTag, LogSeparator logSeparator) {
         new ActivityLifecycleCountsValidator(logTag, logSeparator, 1 /* createCount */,
@@ -1240,7 +1181,7 @@
         assertSingleStartAndStop(getLogTag(activityName), logSeparator);
     }
 
-    /** TODO(b/73349193): Use {@link #assertSingleStartAndStop(ComponentName, LogSeparator)}. */
+    // TODO(b/73349193): Use {@link #assertSingleStartAndStop(ComponentName, LogSeparator)}.
     @Deprecated
     void assertSingleStartAndStop(String logTag, LogSeparator logSeparator) {
         new ActivityLifecycleCountsValidator(logTag, logSeparator, 0 /* createCount */,
@@ -1250,15 +1191,9 @@
     }
 
     void assertSingleStart(ComponentName activityName, LogSeparator logSeparator) {
-        assertSingleStart(getLogTag(activityName), logSeparator);
-    }
-
-    /** TODO(b/73349193): Use {@link #assertSingleStart(ComponentName, LogSeparator)} instead. */
-    @Deprecated
-    void assertSingleStart(String logTag, LogSeparator logSeparator) {
-        new ActivityLifecycleCountsValidator(logTag, logSeparator, 0 /* createCount */,
-                1 /* startCount */, 1 /* resumeCount */, 0 /* pauseCount */, 0 /* stopCount */,
-                0 /* destroyCount */)
+        new ActivityLifecycleCountsValidator(getLogTag(activityName), logSeparator,
+                0 /* createCount */, 1 /* startCount */, 1 /* resumeCount */, 0 /* pauseCount */,
+                0 /* stopCount */, 0 /* destroyCount */)
                 .assertValidator("***Waiting for activity start and resume");
     }
 
@@ -1326,28 +1261,30 @@
         }
     }
 
-    ReportedSizes getLastReportedSizesForActivity(String activityName, LogSeparator logSeparator) {
-        int retriesLeft = 5;
-        ReportedSizes result;
-        do {
-            result = readLastReportedSizes(activityName, logSeparator);
-            if (result == null) {
-                log("***Waiting for sizes to be reported...");
-                try {
-                    Thread.sleep(1000);
-                } catch (InterruptedException e) {
-                    log(e.toString());
-                    // Well I guess we are not waiting...
-                }
-            } else {
-                break;
-            }
-        } while (retriesLeft-- > 0);
-        return result;
+    @Nullable
+    ReportedSizes getLastReportedSizesForActivity(
+            ComponentName activityName, LogSeparator logSeparator) {
+        return getLastReportedSizesForActivity(getLogTag(activityName), logSeparator);
     }
 
-    private ReportedSizes readLastReportedSizes(String activityName, LogSeparator logSeparator) {
-        final String[] lines = getDeviceLogsForComponents(logSeparator, activityName);
+    // TODO(b/73349193): Use {@link #getLastReportedSizesForActivity(ComponentName, LogSeparator)}.
+    @Deprecated
+    @Nullable
+    ReportedSizes getLastReportedSizesForActivity(String activityName, LogSeparator logSeparator) {
+        for (int retry = 1; retry <= 5; retry++ ) {
+            final ReportedSizes result = readLastReportedSizes(logSeparator, activityName);
+            if (result != null) {
+                return result;
+            }
+            logAlways("***Waiting for sizes to be reported... retry=" + retry);
+            SystemClock.sleep(1000);
+        }
+        logE("***Waiting for activity size failed: activityName=" + activityName);
+        return null;
+    }
+
+    private ReportedSizes readLastReportedSizes(LogSeparator logSeparator, String logTag) {
+        final String[] lines = getDeviceLogsForComponents(logSeparator, logTag);
         for (int i = lines.length - 1; i >= 0; i--) {
             final String line = lines[i].trim();
             final Matcher matcher = sNewConfigPattern.matcher(line);
@@ -1369,26 +1306,19 @@
     }
 
     /** Waits for at least one onMultiWindowModeChanged event. */
-    ActivityLifecycleCounts waitForOnMultiWindowModeChanged(
-            String activityName, LogSeparator logSeparator) {
-        int retriesLeft = 5;
+    ActivityLifecycleCounts waitForOnMultiWindowModeChanged(ComponentName activityName,
+            LogSeparator logSeparator) {
+        int retry = 1;
         ActivityLifecycleCounts result;
         do {
             result = new ActivityLifecycleCounts(activityName, logSeparator);
-            if (result.mMultiWindowModeChangedCount < 1) {
-                log("***waitForOnMultiWindowModeChanged...");
-                try {
-                    Thread.sleep(1000);
-                } catch (InterruptedException e) {
-                    log(e.toString());
-                    // Well I guess we are not waiting...
-                }
-            } else {
-                break;
+            if (result.mMultiWindowModeChangedCount >= 1) {
+                return result;
             }
-        } while (retriesLeft-- > 0);
+            logAlways("***waitForOnMultiWindowModeChanged... retry=" + retry);
+            SystemClock.sleep(TimeUnit.SECONDS.toMillis(1));
+        } while (retry++ <= 5);
         return result;
-
     }
 
     // TODO: Now that our test are device side, we can convert these to a more direct communication
@@ -1414,6 +1344,8 @@
             this(getLogTag(componentName), logSeparator);
         }
 
+        // TODO(b/73349193): Use {@link ActivityLifecycleCounts(ComponentName, LogSeparator)}.
+        @Deprecated
         ActivityLifecycleCounts(String logTag, LogSeparator logSeparator) {
             int lineIndex = 0;
             waitForIdle();
@@ -1525,7 +1457,7 @@
         private boolean mMultipleTask;
         private int mDisplayId = INVALID_DISPLAY_ID;
         // A proxy activity that launches other activities including mTargetActivityName
-        private String mLaunchingActivityName = LAUNCHING_ACTIVITY;
+        private String mLaunchingActivityName = LAUNCHING_ACTIVITY_NAME;
         private ComponentName mLaunchingActivity;
         private boolean mReorderToFront;
         private boolean mWaitForLaunched;
@@ -1535,6 +1467,11 @@
         private String mBroadcastReceiverPackage;
         private String mBroadcastReceiverAction;
 
+        private enum LauncherType {
+            INSTRUMENTATION, LAUNCHING_ACTIVITY, BROADCAST_RECEIVER
+        }
+        private LauncherType mLauncherType = LauncherType.LAUNCHING_ACTIVITY;
+
         public LaunchActivityBuilder(ActivityAndWindowManagersState amWmState) {
             mAmWmState = amWmState;
             mWaitForLaunched = true;
@@ -1578,34 +1515,29 @@
             return this;
         }
 
-        /** TODO(b/73349193): Use {@link #setTargetActivity(ComponentName)} instead. */
+        // TODO(b/73349193): Use {@link #setTargetActivity(ComponentName)} instead.
         @Deprecated
         public LaunchActivityBuilder setTargetActivityName(String name) {
             mTargetActivityName = name;
             return this;
         }
 
-        /** TODO(b/73349193): Use {@link #setTargetActivity(ComponentName)} instead. */
-        @Deprecated
-        public LaunchActivityBuilder setTargetPackage(String pkg) {
-            mTargetPackage = pkg;
-            return this;
-        }
-
         public LaunchActivityBuilder setDisplayId(int id) {
             mDisplayId = id;
             return this;
         }
 
-        /** TODO(b/73349193): Use {@link #setLaunchingActivity(ComponentName)} instead. */
+        // TODO(b/73349193): Use {@link #setLaunchingActivity(ComponentName)} instead.
         @Deprecated
         public LaunchActivityBuilder setLaunchingActivityName(String name) {
             mLaunchingActivityName = name;
+            mLauncherType = LauncherType.LAUNCHING_ACTIVITY;
             return this;
         }
 
         public LaunchActivityBuilder setLaunchingActivity(ComponentName component) {
             mLaunchingActivity = component;
+            mLauncherType = LauncherType.LAUNCHING_ACTIVITY;
             return this;
         }
 
@@ -1614,11 +1546,21 @@
             return this;
         }
 
-        /** Use broadcast receiver instead of launching activity. */
+        /** Use broadcast receiver as a launchpad for activities. */
         public LaunchActivityBuilder setUseBroadcastReceiver(final ComponentName broadcastReceiver,
                 final String broadcastAction) {
             mBroadcastReceiverPackage = broadcastReceiver.getPackageName();
             mBroadcastReceiverAction = broadcastAction;
+            mLauncherType = LauncherType.BROADCAST_RECEIVER;
+            return this;
+        }
+
+        /** Use {@link android.app.Instrumentation} as a launchpad for activities. */
+        public LaunchActivityBuilder setUseInstrumentation() {
+            mLauncherType = LauncherType.INSTRUMENTATION;
+            // Calling startActivity() from outside of an Activity context requires the
+            // FLAG_ACTIVITY_NEW_TASK flag.
+            setNewTask(true);
             return this;
         }
 
@@ -1628,6 +1570,44 @@
         }
 
         public void execute() throws Exception {
+            switch (mLauncherType) {
+                case INSTRUMENTATION:
+                    launchUsingInstrumentation();
+                    break;
+                case LAUNCHING_ACTIVITY:
+                case BROADCAST_RECEIVER:
+                    launchUsingShellCommand();
+            }
+
+            if (mWaitForLaunched) {
+                mAmWmState.waitForValidState(false /* compareTaskAndStackBounds */, mTargetPackage,
+                        new WaitForValidActivityState.Builder(mTargetActivityName).build());
+            }
+        }
+
+        /** Launch an activity using instrumentation. */
+        private void launchUsingInstrumentation() {
+            final Bundle b = new Bundle();
+            b.putBoolean(KEY_USE_INSTRUMENTATION, true);
+            b.putBoolean(KEY_LAUNCH_ACTIVITY, true);
+            b.putBoolean(KEY_LAUNCH_TO_SIDE, mToSide);
+            b.putBoolean(KEY_RANDOM_DATA, mRandomData);
+            b.putBoolean(KEY_NEW_TASK, mNewTask);
+            b.putBoolean(KEY_MULTIPLE_TASK, mMultipleTask);
+            b.putBoolean(KEY_REORDER_TO_FRONT, mReorderToFront);
+            b.putString(KEY_TARGET_ACTIVITY, mTargetActivityName);
+            b.putString(KEY_TARGET_PACKAGE, mTargetPackage);
+            b.putInt(KEY_DISPLAY_ID, mDisplayId);
+            b.putBoolean(KEY_USE_APPLICATION_CONTEXT, mUseApplicationContext);
+            b.putString(KEY_TARGET_COMPONENT, mComponent != null ? getActivityName(mComponent)
+                    : null);
+            b.putBoolean(KEY_SUPPRESS_EXCEPTIONS, mSuppressExceptions);
+            final Context context = InstrumentationRegistry.getContext();
+            launchActivityFromExtras(context, b);
+        }
+
+        /** Build and execute a shell command to launch an activity. */
+        private void launchUsingShellCommand() {
             StringBuilder commandBuilder = new StringBuilder();
             if (mBroadcastReceiverPackage != null && mBroadcastReceiverAction != null) {
                 // Use broadcast receiver to launch the target.
@@ -1646,51 +1626,47 @@
             }
 
             // Add a flag to ensure we actually mean to launch an activity.
-            commandBuilder.append(" --ez launch_activity true");
+            commandBuilder.append(" --ez " + KEY_LAUNCH_ACTIVITY + " true");
 
             if (mToSide) {
-                commandBuilder.append(" --ez launch_to_the_side true");
+                commandBuilder.append(" --ez " + KEY_LAUNCH_TO_SIDE + " true");
             }
             if (mRandomData) {
-                commandBuilder.append(" --ez random_data true");
+                commandBuilder.append(" --ez " + KEY_RANDOM_DATA + " true");
             }
             if (mNewTask) {
-                commandBuilder.append(" --ez new_task true");
+                commandBuilder.append(" --ez " + KEY_NEW_TASK + " true");
             }
             if (mMultipleTask) {
-                commandBuilder.append(" --ez multiple_task true");
+                commandBuilder.append(" --ez " + KEY_MULTIPLE_TASK + " true");
             }
             if (mReorderToFront) {
-                commandBuilder.append(" --ez reorder_to_front true");
+                commandBuilder.append(" --ez " + KEY_REORDER_TO_FRONT + " true");
             }
             if (mTargetActivityName != null) {
-                commandBuilder.append(" --es target_activity ").append(mTargetActivityName);
-                commandBuilder.append(" --es package_name ").append(mTargetPackage);
+                commandBuilder.append(" --es " + KEY_TARGET_ACTIVITY + " ")
+                        .append(mTargetActivityName);
+                commandBuilder.append(" --es " + KEY_TARGET_PACKAGE + " ").append(mTargetPackage);
             }
             if (mDisplayId != INVALID_DISPLAY_ID) {
-                commandBuilder.append(" --ei display_id ").append(mDisplayId);
+                commandBuilder.append(" --ei " + KEY_DISPLAY_ID + " ").append(mDisplayId);
             }
 
             if (mUseApplicationContext) {
-                commandBuilder.append(" --ez use_application_context true");
+                commandBuilder.append(" --ez " + KEY_USE_APPLICATION_CONTEXT + " true");
             }
 
             if (mComponent != null) {
                 // {@link ActivityLauncher} parses this extra string by
                 // {@link ComponentName#unflattenFromString(String)}.
-                commandBuilder.append(" --es target_component ")
+                commandBuilder.append(" --es " + KEY_TARGET_COMPONENT + " ")
                         .append(getActivityName(mComponent));
             }
 
             if (mSuppressExceptions) {
-                commandBuilder.append(" --ez suppress_exceptions true");
+                commandBuilder.append(" --ez " + KEY_SUPPRESS_EXCEPTIONS + " true");
             }
             executeShellCommand(commandBuilder.toString());
-
-            if (mWaitForLaunched) {
-                mAmWmState.waitForValidState(false /* compareTaskAndStackBounds */, mTargetPackage,
-                        new WaitForValidActivityState.Builder(mTargetActivityName).build());
-            }
         }
     }
 }
diff --git a/tests/framework/base/activitymanager/util/src/android/server/am/UiDeviceUtils.java b/tests/framework/base/activitymanager/util/src/android/server/am/UiDeviceUtils.java
new file mode 100644
index 0000000..4b364b8
--- /dev/null
+++ b/tests/framework/base/activitymanager/util/src/android/server/am/UiDeviceUtils.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.am;
+
+import static android.server.am.StateLogger.logE;
+import static android.support.test.InstrumentationRegistry.getContext;
+import static android.view.KeyEvent.KEYCODE_APP_SWITCH;
+import static android.view.KeyEvent.KEYCODE_MENU;
+import static android.view.KeyEvent.KEYCODE_SLEEP;
+import static android.view.KeyEvent.KEYCODE_WAKEUP;
+import static android.view.KeyEvent.KEYCODE_WINDOW;
+
+import android.app.KeyguardManager;
+import android.graphics.Point;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.uiautomator.UiDevice;
+import android.util.Log;
+import android.view.KeyEvent;
+
+import java.util.function.BooleanSupplier;
+
+/**
+ * Helper class to interact with {@link UiDevice}.
+ *
+ * All references to {@link UiDevice} and {@link KeyEvent} should be here for easy debugging.
+ */
+public class UiDeviceUtils {
+
+    private static final String TAG = "UiDeviceUtils";
+    private static final boolean DEBUG = false;
+
+    static void waitForDeviceIdle(long timeout) {
+        if (DEBUG) Log.d(TAG, "waitForDeviceIdle: timeout=" + timeout);
+        getDevice().waitForIdle(timeout);
+    }
+
+    public static void wakeUpDevice() throws RemoteException {
+        if (DEBUG) Log.d(TAG, "wakeUpDevice");
+        getDevice().wakeUp();
+    }
+
+    public static void dragPointer(Point from, Point to, int steps) {
+        if (DEBUG) Log.d(TAG, "dragPointer: from=" + from + " to=" + to + " steps=" + steps);
+        getDevice().drag(from.x, from.y, to.x, to.y, steps);
+    }
+
+    static void pressEnterButton() {
+        if (DEBUG) Log.d(TAG, "pressEnterButton");
+        getDevice().pressEnter();
+    }
+
+    static void pressHomeButton() {
+        if (DEBUG) Log.d(TAG, "pressHomeButton");
+        getDevice().pressHome();
+    }
+
+    static void pressBackButton() {
+        if (DEBUG) Log.d(TAG, "pressBackButton");
+        getDevice().pressBack();
+    }
+
+    public static void pressMenuButton() {
+        if (DEBUG) Log.d(TAG, "pressMenuButton");
+        getDevice().pressMenu();
+    }
+
+    static void pressSleepButton() {
+        if (DEBUG) Log.d(TAG, "pressSleepButton");
+        final PowerManager pm = getContext().getSystemService(PowerManager.class);
+        retryPressKeyCode(KEYCODE_SLEEP, () -> pm != null && !pm.isInteractive(),
+                "***Waiting for device sleep...");
+    }
+
+    static void pressWakeupButton() {
+        if (DEBUG) Log.d(TAG, "pressWakeupButton");
+        final PowerManager pm = getContext().getSystemService(PowerManager.class);
+        retryPressKeyCode(KEYCODE_WAKEUP, () -> pm != null && pm.isInteractive(),
+                "***Waiting for device wakeup...");
+    }
+
+    static void pressUnlockButton() {
+        if (DEBUG) Log.d(TAG, "pressUnlockButton");
+        final KeyguardManager kgm = getContext().getSystemService(KeyguardManager.class);
+        retryPressKeyCode(KEYCODE_MENU, () -> kgm != null && !kgm.isKeyguardLocked(),
+                "***Waiting for device unlock...");
+    }
+
+    static void pressWindowButton() {
+        if (DEBUG) Log.d(TAG, "pressWindowButton");
+        pressKeyCode(KEYCODE_WINDOW);
+    }
+
+    static void pressAppSwitchButton() {
+        if (DEBUG) Log.d(TAG, "pressAppSwitchButton");
+        pressKeyCode(KEYCODE_APP_SWITCH);
+    }
+
+    private static void retryPressKeyCode(int keyCode, BooleanSupplier waitFor, String msg) {
+        int retry = 1;
+        do {
+            pressKeyCode(keyCode);
+            if (waitFor.getAsBoolean()) {
+                return;
+            }
+            Log.d(TAG, msg + " retry=" + retry);
+            try {
+                Thread.sleep(50);
+            } catch (InterruptedException e) {
+                logE("Sleep interrupted: " + msg, e);
+            }
+        } while (retry++ < 5);
+        if (!waitFor.getAsBoolean()) {
+            logE(msg + " FAILED");
+        }
+    }
+
+    private static void pressKeyCode(int keyCode) {
+        getDevice().pressKeyCode(keyCode);
+    }
+
+    private static UiDevice getDevice() {
+        return UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+    }
+}
diff --git a/tests/framework/base/windowmanager/frametestapp/src/android/server/wm/frametestapp/DialogTestActivity.java b/tests/framework/base/windowmanager/frametestapp/src/android/server/wm/frametestapp/DialogTestActivity.java
index e303f66..8410a8f 100644
--- a/tests/framework/base/windowmanager/frametestapp/src/android/server/wm/frametestapp/DialogTestActivity.java
+++ b/tests/framework/base/windowmanager/frametestapp/src/android/server/wm/frametestapp/DialogTestActivity.java
@@ -19,15 +19,11 @@
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.content.Intent;
-import android.graphics.Rect;
-import android.os.Bundle;
 import android.view.Gravity;
-import android.view.View;
 import android.view.Window;
-import android.view.WindowInsets;
 import android.view.WindowManager;
 
-public class DialogTestActivity extends Activity implements View.OnApplyWindowInsetsListener{
+public class DialogTestActivity extends Activity {
 
     private static final String DIALOG_WINDOW_NAME = "TestDialog";
 
@@ -39,28 +35,16 @@
 
     private AlertDialog mDialog;
 
-    private Rect mOutsets = new Rect();
-
-    protected void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-        View content = new View(this);
-        content.setOnApplyWindowInsetsListener(this);
-        setContentView(content);
-    }
-
     @Override
     protected void onStop() {
         super.onStop();
         mDialog.dismiss();
     }
 
-    public WindowInsets onApplyWindowInsets(View v, WindowInsets in) {
-        if (in.isRound()) {
-            mOutsets = new Rect(in.getSystemWindowInsetLeft(), in.getSystemWindowInsetTop(),
-                    in.getSystemWindowInsetRight(), in.getSystemWindowInsetBottom());
-        }
+    @Override
+    protected void onResume() {
+        super.onResume();
         setupTest(getIntent());
-        return in;
     }
 
     private void setupTest(Intent intent) {
@@ -141,23 +125,23 @@
 
     private void testExplicitSize() {
         doLayoutParamTest((WindowManager.LayoutParams params) -> {
-            params.width = 200 - mOutsets.left - mOutsets.right;
-            params.height = 200 - mOutsets.bottom - mOutsets.top;
+            params.width = 200;
+            params.height = 200;
         });
     }
 
     private void testExplicitSizeTopLeftGravity() {
         doLayoutParamTest((WindowManager.LayoutParams params) -> {
-            params.width = 200 - mOutsets.left - mOutsets.right;
-            params.height = 200 - mOutsets.bottom - mOutsets.top;
+            params.width = 200;
+            params.height = 200;
             params.gravity = Gravity.TOP | Gravity.LEFT;
         });
     }
 
     private void testExplicitSizeBottomRightGravity() {
         doLayoutParamTest((WindowManager.LayoutParams params) -> {
-            params.width = 200 - mOutsets.left - mOutsets.right;
-            params.height = 200 - mOutsets.bottom - mOutsets.top;
+            params.width = 200;
+            params.height = 200;
             params.gravity = Gravity.BOTTOM | Gravity.RIGHT;
         });
     }
@@ -182,6 +166,8 @@
         doLayoutParamTest((WindowManager.LayoutParams params) -> {
             params.width = WindowManager.LayoutParams.MATCH_PARENT;
             params.height = WindowManager.LayoutParams.MATCH_PARENT;
+            params.x = 100;
+            params.y = 100;
         });
     }
 
@@ -191,6 +177,8 @@
             params.height = WindowManager.LayoutParams.MATCH_PARENT;
             params.gravity = Gravity.LEFT | Gravity.TOP;
             params.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
+            params.x = 100;
+            params.y = 100;
         });
     }
 
@@ -204,9 +192,9 @@
         doLayoutParamTest((WindowManager.LayoutParams params) -> {
             params.gravity = Gravity.LEFT | Gravity.TOP;
             params.horizontalMargin = .25f;
-            params.verticalMargin = .25f;
-            params.width = 200 - mOutsets.left - mOutsets.right;
-            params.height = 200 - mOutsets.bottom - mOutsets.top;
+            params.verticalMargin = .35f;
+            params.width = 200;
+            params.height = 200;
             params.x = 0;
             params.y = 0;
         });
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/CrossAppDragAndDropTests.java b/tests/framework/base/windowmanager/src/android/server/wm/CrossAppDragAndDropTests.java
index 14c0179..2ab39e7 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/CrossAppDragAndDropTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/CrossAppDragAndDropTests.java
@@ -23,6 +23,9 @@
 import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
 import static android.server.am.ActivityManagerTestBase.executeShellCommand;
 import static android.server.am.StateLogger.log;
+import static android.server.am.UiDeviceUtils.dragPointer;
+import static android.server.am.UiDeviceUtils.pressMenuButton;
+import static android.server.am.UiDeviceUtils.wakeUpDevice;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
@@ -37,8 +40,6 @@
 import android.os.SystemClock;
 import android.platform.test.annotations.Presubmit;
 import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.FlakyTest;
-import android.support.test.uiautomator.UiDevice;
 import android.util.Log;
 
 import org.junit.After;
@@ -117,7 +118,6 @@
 
     protected Context mContext;
     protected ActivityManager mAm;
-    private UiDevice mDevice;
 
     private Map<String, String> mSourceResults;
     private Map<String, String> mTargetResults;
@@ -140,7 +140,6 @@
 
         mContext = InstrumentationRegistry.getContext();
         mAm = mContext.getSystemService(ActivityManager.class);
-        mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
 
         mSourcePackageName = SOURCE_PACKAGE_NAME;
         mTargetPackageName = TARGET_PACKAGE_NAME;
@@ -249,7 +248,7 @@
     }
 
     private void injectInput(Point from, Point to, int steps) throws Exception {
-        mDevice.drag(from.x, from.y, to.x, to.y, steps);
+        dragPointer(from, to, steps);
     }
 
     private String findTaskInfo(String name) {
@@ -327,12 +326,12 @@
     private void unlockDevice() {
         // Wake up the device, if necessary.
         try {
-            mDevice.wakeUp();
+            wakeUpDevice();
         } catch (RemoteException e) {
             throw new RuntimeException(e);
         }
         // Unlock the screen.
-        mDevice.pressMenu();
+        pressMenuButton();
     }
 
     private void assertDropResult(String sourceMode, String targetMode, String expectedDropResult)
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeEvent.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeEvent.java
index 7c605f4..b9126ab 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeEvent.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeEvent.java
@@ -16,19 +16,53 @@
 
 package com.android.cts.mockime;
 
+import android.inputmethodservice.AbstractInputMethodService;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
+import android.view.View;
 
 /**
  * An immutable object that stores event happened in the {@link MockIme}.
  */
 public final class ImeEvent {
 
+    private enum ReturnType {
+        Null,
+        KnownUnsupportedType,
+        Boolean,
+    }
+
+    private static ReturnType getReturnTypeFromObject(@Nullable Object object) {
+        if (object == null) {
+            return ReturnType.Null;
+        }
+        if (object instanceof AbstractInputMethodService.AbstractInputMethodImpl) {
+            return ReturnType.KnownUnsupportedType;
+        }
+        if (object instanceof View) {
+            return ReturnType.KnownUnsupportedType;
+        }
+        if (object instanceof Boolean) {
+            return ReturnType.Boolean;
+        }
+        throw new UnsupportedOperationException("Unsupported return type=" + object);
+    }
+
     ImeEvent(@NonNull String eventName, int nestLevel, @NonNull String threadName, int threadId,
             boolean isMainThread, long enterTimestamp, long exitTimestamp, long enterWallTime,
             long exitWallTime, @NonNull ImeState enterState, @Nullable ImeState exitState,
-            @NonNull Bundle arguments) {
+            @NonNull Bundle arguments, @Nullable Object returnValue) {
+        this(eventName, nestLevel, threadName, threadId, isMainThread, enterTimestamp,
+                exitTimestamp, enterWallTime, exitWallTime, enterState, exitState, arguments,
+                returnValue, getReturnTypeFromObject(returnValue));
+    }
+
+    private ImeEvent(@NonNull String eventName, int nestLevel, @NonNull String threadName,
+            int threadId, boolean isMainThread, long enterTimestamp, long exitTimestamp,
+            long enterWallTime, long exitWallTime, @NonNull ImeState enterState,
+            @Nullable ImeState exitState, @NonNull Bundle arguments, @Nullable Object returnValue,
+            @NonNull ReturnType returnType) {
         mEventName = eventName;
         mNestLevel = nestLevel;
         mThreadName = threadName;
@@ -41,6 +75,8 @@
         mEnterState = enterState;
         mExitState = exitState;
         mArguments = arguments;
+        mReturnValue = returnValue;
+        mReturnType = returnType;
     }
 
     @NonNull
@@ -58,6 +94,7 @@
         bundle.putBundle("mEnterState", mEnterState.toBundle());
         bundle.putBundle("mExitState", mExitState != null ? mExitState.toBundle() : null);
         bundle.putBundle("mArguments", mArguments);
+        bundle.putString("mReturnType", mReturnType.name());
         return bundle;
     }
 
@@ -75,9 +112,22 @@
         final ImeState enterState = ImeState.fromBundle(bundle.getBundle("mEnterState"));
         final ImeState exitState = ImeState.fromBundle(bundle.getBundle("mExitState"));
         final Bundle arguments = bundle.getBundle("mArguments");
+        final Object result;
+        final ReturnType returnType = ReturnType.valueOf(bundle.getString("mReturnType"));
+        switch (returnType) {
+            case Null:
+            case KnownUnsupportedType:
+                result = null;
+                break;
+            case Boolean:
+                result = bundle.getBoolean("mReturnValue");
+                break;
+            default:
+                throw new UnsupportedOperationException("Unsupported type=" + returnType);
+        }
         return new ImeEvent(eventName, nestLevel, threadName,
                 threadId, isMainThread, enterTimestamp, exitTimestamp, enterWallTime, exitWallTime,
-                enterState, exitState, arguments);
+                enterState, exitState, arguments, result, returnType);
     }
 
     /**
@@ -183,6 +233,22 @@
     }
 
     /**
+     * @return result value of this event.
+     * @throws NullPointerException if the return value is {@code null}
+     * @throws ClassCastException if the return value is non-{@code null} object that is different
+     *                            from {@link Boolean}
+     */
+    public boolean getReturnBooleanValue() {
+        if (mReturnType == ReturnType.Null) {
+            throw new NullPointerException();
+        }
+        if (mReturnType != ReturnType.Boolean) {
+            throw new ClassCastException();
+        }
+        return (Boolean) mReturnValue;
+    }
+
+    /**
      * @return {@code true} if the event is issued when the event starts, not when the event
      * finishes.
      */
@@ -207,4 +273,8 @@
     private final ImeState mExitState;
     @NonNull
     private final Bundle mArguments;
+    @Nullable
+    private final Object mReturnValue;
+    @NonNull
+    private final ReturnType mReturnType;
 }
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
index 7196f5b..ac46df3 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
@@ -46,6 +46,7 @@
 import android.util.Log;
 import android.util.TypedValue;
 import android.view.Gravity;
+import android.view.KeyEvent;
 import android.view.View;
 import android.view.Window;
 import android.view.WindowInsets;
@@ -410,6 +411,11 @@
         getTracer().onFinishInput(() -> super.onFinishInput());
     }
 
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        return getTracer().onKeyDown(keyCode, event, () -> super.onKeyDown(keyCode, event));
+    }
+
     @CallSuper
     public boolean onEvaluateInputViewShown() {
         return getTracer().onEvaluateInputViewShown(() -> {
@@ -544,7 +550,7 @@
             // Send enter event
             sendEventInternal(new ImeEvent(eventName, nestLevel, mThreadName,
                     mThreadId, mIsMainThread, enterTimestamp, 0, enterWallTime,
-                    0, enterState, null, arguments));
+                    0, enterState, null, arguments, null));
             ++mNestLevel;
             T result;
             try {
@@ -558,7 +564,7 @@
             // Send exit event
             sendEventInternal(new ImeEvent(eventName, nestLevel, mThreadName,
                     mThreadId, mIsMainThread, enterTimestamp, exitTimestamp, enterWallTime,
-                    exitWallTime, enterState, exitState, arguments));
+                    exitWallTime, enterState, exitState, arguments, result));
             return result;
         }
 
@@ -612,6 +618,13 @@
             recordEventInternal("onFinishInput", runnable);
         }
 
+        public boolean onKeyDown(int keyCode, KeyEvent event, @NonNull BooleanSupplier supplier) {
+            final Bundle arguments = new Bundle();
+            arguments.putInt("keyCode", keyCode);
+            arguments.putParcelable("event", event);
+            return recordEventInternal("onKeyDown", supplier::getAsBoolean, arguments);
+        }
+
         public boolean onShowInputRequested(int flags, boolean configChange,
                 @NonNull BooleanSupplier supplier) {
             final Bundle arguments = new Bundle();
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerTest.java
index 695e4a5..50da9f2 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerTest.java
@@ -18,45 +18,40 @@
 
 import static android.content.Intent.ACTION_CLOSE_SYSTEM_DIALOGS;
 import static android.content.Intent.FLAG_RECEIVER_FOREGROUND;
+import static android.view.inputmethod.cts.util.TestUtils.runOnMainSync;
 import static android.view.inputmethod.cts.util.TestUtils.waitOnMainUntil;
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeTrue;
 
 import android.app.Instrumentation;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.PackageManager;
 import android.support.annotation.NonNull;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
-import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
 import android.text.TextUtils;
-import android.view.KeyEvent;
 import android.view.View;
-import android.view.Window;
-import android.view.inputmethod.BaseInputConnection;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.view.inputmethod.InputMethodSubtype;
 import android.view.inputmethod.cts.util.TestActivity;
 import android.widget.EditText;
+import android.widget.LinearLayout;
 import android.widget.LinearLayout.LayoutParams;
 
-import com.android.compatibility.common.util.PollingCheck;
-
-import org.junit.After;
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import java.util.List;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Collectors;
 
 @MediumTest
@@ -67,10 +62,6 @@
     private Context mContext;
     private InputMethodManager mImManager;
 
-    @Rule
-    public ActivityTestRule<InputMethodCtsActivity> mActivityRule =
-            new ActivityTestRule<>(InputMethodCtsActivity.class);
-
     @Before
     public void setup() {
         mInstrumentation = InstrumentationRegistry.getInstrumentation();
@@ -78,40 +69,55 @@
         mImManager = mContext.getSystemService(InputMethodManager.class);
     }
 
-    @After
-    public void teardown() {
-        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
+    @Test
+    public void testIsActive() throws Throwable {
+        final AtomicReference<EditText> focusedEditTextRef = new AtomicReference<>();
+        final AtomicReference<EditText> nonFocusedEditTextRef = new AtomicReference<>();
+        TestActivity.startSync(activity -> {
+            final LinearLayout layout = new LinearLayout(activity);
+            layout.setOrientation(LinearLayout.VERTICAL);
+
+            final EditText focusedEditText = new EditText(activity);
+            layout.addView(focusedEditText);
+            focusedEditTextRef.set(focusedEditText);
+            focusedEditText.requestFocus();
+
+            final EditText nonFocusedEditText = new EditText(activity);
+            layout.addView(nonFocusedEditText);
+            nonFocusedEditTextRef.set(nonFocusedEditText);
+
+            return layout;
+        });
+        waitOnMainUntil(() -> mImManager.isActive(), TIMEOUT);
+        assertTrue(mImManager.isAcceptingText());
+        assertTrue(mImManager.isActive(focusedEditTextRef.get()));
+        assertFalse(mImManager.isActive(nonFocusedEditTextRef.get()));
     }
 
     @Test
-    public void testInputMethodManager() throws Throwable {
-        final InputMethodCtsActivity activity = mActivityRule.getActivity();
-        assumeTrue(mContext.getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_INPUT_METHODS));
+    public void testIsAcceptingText() throws Throwable {
+        final AtomicReference<EditText> focusedFakeEditTextRef = new AtomicReference<>();
+        TestActivity.startSync(activity -> {
+            final LinearLayout layout = new LinearLayout(activity);
+            layout.setOrientation(LinearLayout.VERTICAL);
 
-        Window window = activity.getWindow();
-        final EditText view = window.findViewById(R.id.entry);
-
-        PollingCheck.waitFor(1000, view::hasWindowFocus);
-
-        mActivityRule.runOnUiThread(view::requestFocus);
-        mInstrumentation.waitForIdleSync();
-        assertTrue(view.isFocused());
-
-        BaseInputConnection connection = new BaseInputConnection(view, false);
-
-        PollingCheck.waitFor(mImManager::isActive);
-
-        assertTrue(mImManager.isAcceptingText());
-        assertTrue(mImManager.isActive(view));
-
-        assertFalse(mImManager.isFullscreenMode());
-        connection.reportFullscreenMode(true);
-        // Only IMEs are allowed to report full-screen mode.  Calling this method from the
-        // application should have no effect.
-        assertFalse(mImManager.isFullscreenMode());
-
-        mInstrumentation.waitForIdleSync();
+            final EditText focusedFakeEditText = new EditText(activity) {
+                @Override
+                public InputConnection onCreateInputConnection(EditorInfo info) {
+                    super.onCreateInputConnection(info);
+                    return null;
+                }
+            };
+            layout.addView(focusedFakeEditText);
+            focusedFakeEditTextRef.set(focusedFakeEditText);
+            focusedFakeEditText.requestFocus();
+            return layout;
+        });
+        waitOnMainUntil(() -> mImManager.isActive(), TIMEOUT);
+        assertTrue(mImManager.isActive(focusedFakeEditTextRef.get()));
+        assertFalse("InputMethodManager#isAcceptingText() must return false "
+                + "if target View returns null from onCreateInputConnection().",
+                mImManager.isAcceptingText());
     }
 
     @Test
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
index 3c9f838..0754e7f 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
@@ -18,23 +18,30 @@
 
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE;
+import static android.view.inputmethod.cts.util.TestUtils.getOnMainSync;
 import static android.view.inputmethod.cts.util.TestUtils.waitOnMainUntil;
 
+import static com.android.cts.mockime.ImeEventStreamTestUtils.expectCommand;
 import static com.android.cts.mockime.ImeEventStreamTestUtils.expectEvent;
 import static com.android.cts.mockime.ImeEventStreamTestUtils.notExpectEvent;
-import static com.android.cts.mockime.ImeEventStreamTestUtils.waitForInputViewLayoutStable;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
 
 import android.app.Instrumentation;
 import android.inputmethodservice.InputMethodService;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
 import android.support.test.runner.AndroidJUnit4;
+import android.text.TextUtils;
 import android.view.KeyEvent;
 import android.view.inputmethod.cts.util.EndToEndImeTestBase;
 import android.view.inputmethod.cts.util.TestActivity;
 import android.widget.EditText;
 import android.widget.LinearLayout;
 
+import com.android.cts.mockime.ImeCommand;
+import com.android.cts.mockime.ImeEvent;
 import com.android.cts.mockime.ImeEventStream;
 import com.android.cts.mockime.ImeSettings;
 import com.android.cts.mockime.MockImeSession;
@@ -44,6 +51,8 @@
 import org.junit.runner.RunWith;
 
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.function.Predicate;
 
 /**
  * Tests for {@link InputMethodService} methods.
@@ -52,10 +61,27 @@
 @RunWith(AndroidJUnit4.class)
 public class InputMethodServiceTest extends EndToEndImeTestBase {
     private static final long TIMEOUT = TimeUnit.SECONDS.toMillis(5);
-    private static final long LAYOUT_STABLE_THRESHOLD = TimeUnit.SECONDS.toMillis(3);
+    private static final long EXPECTED_TIMEOUT = TimeUnit.SECONDS.toMillis(2);
 
     private Instrumentation mInstrumentation;
 
+    private static Predicate<ImeEvent> backKeyDownMatcher(boolean expectedReturnValue) {
+        return event -> {
+            if (!event.isEnterEvent()) {
+                // Skip enter event since we are interested in the return value.
+                return false;
+            }
+            if (!TextUtils.equals("onKeyDown", event.getEventName())) {
+                return false;
+            }
+            final int keyCode = event.getArguments().getInt("keyCode");
+            if (keyCode != KeyEvent.KEYCODE_BACK) {
+                return false;
+            }
+            return event.getReturnBooleanValue() == expectedReturnValue;
+        };
+    }
+
     @Before
     public void setup() {
         mInstrumentation = InstrumentationRegistry.getInstrumentation();
@@ -87,16 +113,30 @@
             final TestActivity testActivity = createTestActivity(SOFT_INPUT_STATE_ALWAYS_VISIBLE);
             expectEvent(stream, event -> "onStartInputView".equals(event.getEventName()), TIMEOUT);
 
-            imeSession.callSetBackDisposition(InputMethodService.BACK_DISPOSITION_WILL_DISMISS);
-            waitForInputViewLayoutStable(stream, LAYOUT_STABLE_THRESHOLD);
+            final ImeCommand command = imeSession.callSetBackDisposition(
+                    InputMethodService.BACK_DISPOSITION_WILL_DISMISS);
+            expectCommand(stream, command, TIMEOUT);
+
+            testActivity.setIgnoreBackKey(true);
+            assertEquals(0,
+                    (long) getOnMainSync(() -> testActivity.getOnBackPressedCallCount()));
             mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
 
+            // InputMethodService#onKeyDown() should handle back key event.
+            // TODO: Also check InputMethodService#requestHideSelf()
+            expectEvent(stream, backKeyDownMatcher(true), TIMEOUT);
+
             // keyboard will hide
             expectEvent(stream, event -> "hideSoftInput".equals(event.getEventName()), TIMEOUT);
 
-            // Activity should still be running since ime consumes the back key.
-            waitOnMainUntil(() -> !testActivity.isFinishing(), LAYOUT_STABLE_THRESHOLD,
-                    "Activity should not be finishing.");
+            // Make sure TestActivity#onBackPressed() is NOT called.
+            try {
+                waitOnMainUntil(() -> testActivity.getOnBackPressedCallCount() > 0,
+                        EXPECTED_TIMEOUT);
+                fail("Activity#onBackPressed() should not be called");
+            } catch (TimeoutException e){
+                // This is fine.  We actually expect timeout.
+            }
         }
     }
 
@@ -111,16 +151,25 @@
             final TestActivity testActivity = createTestActivity(SOFT_INPUT_STATE_ALWAYS_VISIBLE);
             expectEvent(stream, event -> "onStartInputView".equals(event.getEventName()), TIMEOUT);
 
-            imeSession.callSetBackDisposition(InputMethodService.BACK_DISPOSITION_WILL_NOT_DISMISS);
-            waitForInputViewLayoutStable(stream, LAYOUT_STABLE_THRESHOLD);
+            final ImeCommand command = imeSession.callSetBackDisposition(
+                    InputMethodService.BACK_DISPOSITION_WILL_NOT_DISMISS);
+            expectCommand(stream, command, TIMEOUT);
+
+            testActivity.setIgnoreBackKey(true);
+            assertEquals(0,
+                    (long) getOnMainSync(() -> testActivity.getOnBackPressedCallCount()));
             mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
 
-            // keyboard will hide.
-            expectEvent(stream, event -> "hideSoftInput".equals(event.getEventName()), TIMEOUT);
+            // InputMethodService#onKeyDown() will not handle back key event.
+            // TODO: Also check InputMethodService#requestHideSelf()
+            expectEvent(stream, backKeyDownMatcher(false), TIMEOUT);
 
-            // activity should've gone (or going) away since IME wont consume the back event.
-            waitOnMainUntil(() -> testActivity.isFinishing(), LAYOUT_STABLE_THRESHOLD,
-                    "Activity should be finishing or finished.");
+            // keyboard will not hide
+            notExpectEvent(stream, event -> "hideSoftInput".equals(event.getEventName()),
+                    EXPECTED_TIMEOUT);
+
+            // Activity#onBackPressed() should be called.
+            waitOnMainUntil(() -> testActivity.getOnBackPressedCallCount() > 0, TIMEOUT);
         }
     }
 
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/OnScreenPositionTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/OnScreenPositionTest.java
index 7e0998c..b320f88 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/OnScreenPositionTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/OnScreenPositionTest.java
@@ -65,6 +65,7 @@
             final EditText editText = new EditText(activity);
             editText.setPrivateImeOptions(TEST_MARKER);
             editText.setHint("editText");
+            editText.requestFocus();
             editTextRef.set(editText);
 
             layout.addView(editText);
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/TestActivity.java b/tests/inputmethod/src/android/view/inputmethod/cts/util/TestActivity.java
index e89934a..c98ab6f 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/util/TestActivity.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/util/TestActivity.java
@@ -19,10 +19,13 @@
 import android.app.Activity;
 import android.content.Intent;
 import android.os.Bundle;
+import android.support.annotation.AnyThread;
 import android.support.annotation.NonNull;
+import android.support.annotation.UiThread;
 import android.support.test.InstrumentationRegistry;
 import android.view.View;
 
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Function;
 
@@ -33,6 +36,32 @@
 
     private Function<TestActivity, View> mInitializer = null;
 
+    private AtomicBoolean mIgnoreBackKey = new AtomicBoolean();
+
+    private long mOnBackPressedCallCount;
+
+    /**
+     * Controls how {@link #onBackPressed()} behaves.
+     *
+     * <p>TODO: Use {@link android.app.AppComponentFactory} instead to customise the behavior of
+     * {@link TestActivity}.</p>
+     *
+     * @param ignore {@code true} when {@link TestActivity} should do nothing when
+     *               {@link #onBackPressed()} is called
+     */
+    @AnyThread
+    public void setIgnoreBackKey(boolean ignore) {
+        mIgnoreBackKey.set(ignore);
+    }
+
+    @UiThread
+    public long getOnBackPressedCallCount() {
+        return mOnBackPressedCallCount;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -43,6 +72,18 @@
     }
 
     /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onBackPressed() {
+        ++mOnBackPressedCallCount;
+        if (mIgnoreBackKey.get()) {
+            return;
+        }
+        super.onBackPressed();
+    }
+
+    /**
      * Launches {@link TestActivity} with the given initialization logic for content view.
      *
      * <p>As long as you are using {@link android.support.test.runner.AndroidJUnitRunner}, the test
diff --git a/tests/jank/Android.mk b/tests/jank/Android.mk
index d619003..df7aa54 100644
--- a/tests/jank/Android.mk
+++ b/tests/jank/Android.mk
@@ -23,6 +23,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsJankDeviceTestCases
+LOCAL_SDK_VERSION := current
 
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
diff --git a/tests/leanbackjank/Android.mk b/tests/leanbackjank/Android.mk
index 7f1177a..ab7eedc 100644
--- a/tests/leanbackjank/Android.mk
+++ b/tests/leanbackjank/Android.mk
@@ -24,6 +24,7 @@
         ./app/src/android/leanbackjank/app/IntentKeys.java
 
 LOCAL_PACKAGE_NAME := CtsLeanbackJankTestCases
+LOCAL_SDK_VERSION := current
 
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
diff --git a/tests/leanbackjank/app/Android.mk b/tests/leanbackjank/app/Android.mk
index 04c3d3f..6ef8e87 100644
--- a/tests/leanbackjank/app/Android.mk
+++ b/tests/leanbackjank/app/Android.mk
@@ -23,6 +23,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsLeanbackJankApp
+LOCAL_SDK_VERSION := current
 
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
diff --git a/tests/libcore/javautilcollections/Android.mk b/tests/libcore/javautilcollections/Android.mk
index e2bcef5..5a0bbb9 100644
--- a/tests/libcore/javautilcollections/Android.mk
+++ b/tests/libcore/javautilcollections/Android.mk
@@ -15,10 +15,22 @@
 LOCAL_PATH:= $(call my-dir)
 
 include $(CLEAR_VARS)
-LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \
-    guava-20.0-prebuilt:libs/guava-20.0.jar \
-    guava-testlib-20.0-prebuilt:libs/guava-testlib-20.0.jar
-include $(BUILD_MULTI_PREBUILT)
+LOCAL_MODULE := guava-20.0-prebuilt
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+LOCAL_SRC_FILES := libs/guava-20.0.jar
+LOCAL_UNINSTALLABLE_MODULE := true
+LOCAL_SDK_VERSION := current
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := guava-testlib-20.0-prebuilt
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+LOCAL_SRC_FILES := libs/guava-testlib-20.0.jar
+LOCAL_UNINSTALLABLE_MODULE := true
+LOCAL_SDK_VERSION := current
+include $(BUILD_PREBUILT)
 
 include $(CLEAR_VARS)
 LOCAL_MODULE_TAGS := tests
@@ -29,6 +41,7 @@
     guava-testlib-20.0-prebuilt
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_PACKAGE_NAME := CtsLibcoreJavaUtilCollectionsTestCases
+LOCAL_SDK_VERSION := current
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/libcore/jsr166/Android.mk b/tests/libcore/jsr166/Android.mk
index 9e11815..e355efd 100644
--- a/tests/libcore/jsr166/Android.mk
+++ b/tests/libcore/jsr166/Android.mk
@@ -17,6 +17,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_PACKAGE_NAME := CtsLibcoreJsr166TestCases
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     cts-core-test-runner \
diff --git a/tests/libcore/luni/Android.mk b/tests/libcore/luni/Android.mk
index 81b44d3..7dfcb61 100644
--- a/tests/libcore/luni/Android.mk
+++ b/tests/libcore/luni/Android.mk
@@ -17,6 +17,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_PACKAGE_NAME := CtsLibcoreTestCases
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     apache-harmony-tests \
diff --git a/tests/libcore/ojluni/Android.mk b/tests/libcore/ojluni/Android.mk
index 079638e..8354615 100644
--- a/tests/libcore/ojluni/Android.mk
+++ b/tests/libcore/ojluni/Android.mk
@@ -17,6 +17,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_PACKAGE_NAME := CtsLibcoreOjTestCases
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     core-ojtests-public
diff --git a/tests/libcore/okhttp/Android.mk b/tests/libcore/okhttp/Android.mk
index 91e9ef5..a706476 100644
--- a/tests/libcore/okhttp/Android.mk
+++ b/tests/libcore/okhttp/Android.mk
@@ -17,6 +17,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_PACKAGE_NAME := CtsLibcoreOkHttpTestCases
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     bouncycastle-nojarjar \
diff --git a/tests/libcore/runner/Android.mk b/tests/libcore/runner/Android.mk
index 6ef3c03..e70ad50 100644
--- a/tests/libcore/runner/Android.mk
+++ b/tests/libcore/runner/Android.mk
@@ -17,6 +17,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_PACKAGE_NAME := CtsLibcoreTestRunner
+LOCAL_SDK_VERSION := current
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     cts-core-test-runner
diff --git a/tests/libcore/wycheproof-bc/Android.mk b/tests/libcore/wycheproof-bc/Android.mk
index 801feac..61dc8c7 100644
--- a/tests/libcore/wycheproof-bc/Android.mk
+++ b/tests/libcore/wycheproof-bc/Android.mk
@@ -17,6 +17,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_PACKAGE_NAME := CtsLibcoreWycheproofBCTestCases
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     cts-core-test-runner \
diff --git a/tests/libcore/wycheproof/Android.mk b/tests/libcore/wycheproof/Android.mk
index 652e36c..015b49d 100644
--- a/tests/libcore/wycheproof/Android.mk
+++ b/tests/libcore/wycheproof/Android.mk
@@ -17,6 +17,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_PACKAGE_NAME := CtsLibcoreWycheproofConscryptTestCases
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     cts-core-test-runner \
diff --git a/tests/signature/api-check/Android.mk b/tests/signature/api-check/Android.mk
index 888ace3..9ee92c9 100644
--- a/tests/signature/api-check/Android.mk
+++ b/tests/signature/api-check/Android.mk
@@ -22,7 +22,7 @@
 # don't include this package in any target
 LOCAL_MODULE_TAGS := optional
 
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES := $(call all-java-files-under, src/java)
 
 LOCAL_MODULE := cts-api-signature-test
 
@@ -37,4 +37,13 @@
 
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
+include $(CLEAR_VARS)
+LOCAL_MODULE := libclassdescriptors
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := src/jni/classdescriptors.cpp
+LOCAL_HEADER_LIBRARIES := jni_headers libopenjdkjvmti_headers
+LOCAL_SDK_VERSION := current
+LOCAL_NDK_STL_VARIANT := c++_static
+include $(BUILD_SHARED_LIBRARY)
+
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/signature/api-check/android-test-base-27-api/AndroidManifest.xml b/tests/signature/api-check/android-test-base-27-api/AndroidManifest.xml
index 684872f..877e911 100644
--- a/tests/signature/api-check/android-test-base-27-api/AndroidManifest.xml
+++ b/tests/signature/api-check/android-test-base-27-api/AndroidManifest.xml
@@ -22,7 +22,7 @@
 
     <uses-sdk android:minSdkVersion="25" android:targetSdkVersion="27"/>
 
-    <application/>
+    <application android:debuggable="true"/>
 
     <instrumentation android:name="repackaged.android.test.InstrumentationTestRunner"
                      android:targetPackage="android.signature.cts.api.android_test_base_27"
diff --git a/tests/signature/api-check/android-test-mock-current-api/AndroidManifest.xml b/tests/signature/api-check/android-test-mock-current-api/AndroidManifest.xml
index 5c88521..f0fc8e1 100644
--- a/tests/signature/api-check/android-test-mock-current-api/AndroidManifest.xml
+++ b/tests/signature/api-check/android-test-mock-current-api/AndroidManifest.xml
@@ -20,7 +20,7 @@
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
 
-    <application>
+    <application android:debuggable="true">
         <uses-library android:name="android.test.mock"/>
     </application>
 
diff --git a/tests/signature/api-check/android-test-runner-current-api/AndroidManifest.xml b/tests/signature/api-check/android-test-runner-current-api/AndroidManifest.xml
index 61de501..f81665e 100644
--- a/tests/signature/api-check/android-test-runner-current-api/AndroidManifest.xml
+++ b/tests/signature/api-check/android-test-runner-current-api/AndroidManifest.xml
@@ -20,7 +20,7 @@
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
 
-    <application>
+    <application android:debuggable="true">
         <uses-library android:name="android.test.runner"/>
     </application>
 
diff --git a/tests/signature/api-check/apache-http-legacy-27-api/Android.mk b/tests/signature/api-check/apache-http-legacy-27-api/Android.mk
new file mode 100644
index 0000000..0f2161a
--- /dev/null
+++ b/tests/signature/api-check/apache-http-legacy-27-api/Android.mk
@@ -0,0 +1,25 @@
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsApacheHttpLegacy27ApiSignatureTestCases
+
+LOCAL_SIGNATURE_API_FILES := \
+    current.api \
+    apache-http-legacy-minus-current.api \
+
+include $(LOCAL_PATH)/../build_signature_apk.mk
diff --git a/tests/signature/api-check/apache-http-legacy-27-api/AndroidManifest.xml b/tests/signature/api-check/apache-http-legacy-27-api/AndroidManifest.xml
new file mode 100644
index 0000000..ae69f52
--- /dev/null
+++ b/tests/signature/api-check/apache-http-legacy-27-api/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android.signature.cts.api.apache_http_legacy_27">
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
+
+    <uses-sdk android:minSdkVersion="22" android:targetSdkVersion="27"/>
+
+    <application/>
+
+    <instrumentation android:name="repackaged.android.test.InstrumentationTestRunner"
+                     android:targetPackage="android.signature.cts.api.apache_http_legacy_27"
+                     android:label="Apache Http Legacy 27 API Signature Test"/>
+
+</manifest>
diff --git a/tests/signature/api-check/apache-http-legacy-27-api/AndroidTest.xml b/tests/signature/api-check/apache-http-legacy-27-api/AndroidTest.xml
new file mode 100644
index 0000000..3bbc90e
--- /dev/null
+++ b/tests/signature/api-check/apache-http-legacy-27-api/AndroidTest.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for CTS Apache Http Legacy 27 API Signature test cases">
+    <option name="test-suite-tag" value="cts" />
+    <option name="config-descriptor:metadata" key="component" value="systems" />
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="run-command" value="mkdir -p /data/local/tmp/signature-test" />
+        <option name="teardown-command" value="rm -rf /data/local/tmp/signature-test" />
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="push" value="current.api->/data/local/tmp/signature-test/current.api" />
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="push" value="apache-http-legacy-minus-current.api->/data/local/tmp/signature-test/apache-http-legacy-minus-current.api" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsApacheHttpLegacy27ApiSignatureTestCases.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.signature.cts.api.apache_http_legacy_27" />
+        <option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
+        <option name="class" value="android.signature.cts.api.SignatureTest" />
+        <option name="instrumentation-arg" key="base-api-files" value="current.api" />
+        <option name="instrumentation-arg" key="expected-api-files" value="apache-http-legacy-minus-current.api" />
+        <option name="runtime-hint" value="5s" />
+    </test>
+</configuration>
diff --git a/tests/signature/api-check/apache-http-legacy-current-api/Android.mk b/tests/signature/api-check/apache-http-legacy-current-api/Android.mk
index cf391bd..b382698 100644
--- a/tests/signature/api-check/apache-http-legacy-current-api/Android.mk
+++ b/tests/signature/api-check/apache-http-legacy-current-api/Android.mk
@@ -19,7 +19,6 @@
 LOCAL_PACKAGE_NAME := CtsApacheHttpLegacyCurrentApiSignatureTestCases
 
 LOCAL_SIGNATURE_API_FILES := \
-    current.api \
     apache-http-legacy-minus-current.api \
 
 include $(LOCAL_PATH)/../build_signature_apk.mk
diff --git a/tests/signature/api-check/apache-http-legacy-current-api/AndroidManifest.xml b/tests/signature/api-check/apache-http-legacy-current-api/AndroidManifest.xml
index eaf118b..f0fb7d8 100644
--- a/tests/signature/api-check/apache-http-legacy-current-api/AndroidManifest.xml
+++ b/tests/signature/api-check/apache-http-legacy-current-api/AndroidManifest.xml
@@ -20,7 +20,7 @@
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
 
-    <application/>
+    <application android:debuggable="true"/>
 
     <instrumentation android:name="repackaged.android.test.InstrumentationTestRunner"
                      android:targetPackage="android.signature.cts.api.apache_http_legacy_current"
diff --git a/tests/signature/api-check/apache-http-legacy-current-api/AndroidTest.xml b/tests/signature/api-check/apache-http-legacy-current-api/AndroidTest.xml
index 9002d39..418c881 100644
--- a/tests/signature/api-check/apache-http-legacy-current-api/AndroidTest.xml
+++ b/tests/signature/api-check/apache-http-legacy-current-api/AndroidTest.xml
@@ -21,9 +21,6 @@
         <option name="teardown-command" value="rm -rf /data/local/tmp/signature-test" />
     </target_preparer>
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
-        <option name="push" value="current.api->/data/local/tmp/signature-test/current.api" />
-    </target_preparer>
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
         <option name="push" value="apache-http-legacy-minus-current.api->/data/local/tmp/signature-test/apache-http-legacy-minus-current.api" />
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
@@ -34,8 +31,7 @@
         <option name="package" value="android.signature.cts.api.apache_http_legacy_current" />
         <option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
         <option name="class" value="android.signature.cts.api.SignatureTest" />
-        <option name="instrumentation-arg" key="base-api-files" value="current.api" />
-        <option name="instrumentation-arg" key="expected-api-files" value="apache-http-legacy-minus-current.api" />
+        <option name="instrumentation-arg" key="unexpected-api-files" value="apache-http-legacy-minus-current.api" />
         <option name="runtime-hint" value="5s" />
     </test>
 </configuration>
diff --git a/tests/signature/api-check/apache-http-legacy-uses-library-api/Android.mk b/tests/signature/api-check/apache-http-legacy-uses-library-api/Android.mk
new file mode 100644
index 0000000..1d801c5
--- /dev/null
+++ b/tests/signature/api-check/apache-http-legacy-uses-library-api/Android.mk
@@ -0,0 +1,25 @@
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsApacheHttpLegacyUsesLibraryApiSignatureTestCases
+
+LOCAL_SIGNATURE_API_FILES := \
+    current.api \
+    apache-http-legacy-minus-current.api \
+
+include $(LOCAL_PATH)/../build_signature_apk.mk
diff --git a/tests/signature/api-check/apache-http-legacy-uses-library-api/AndroidManifest.xml b/tests/signature/api-check/apache-http-legacy-uses-library-api/AndroidManifest.xml
new file mode 100644
index 0000000..f759c54
--- /dev/null
+++ b/tests/signature/api-check/apache-http-legacy-uses-library-api/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android.signature.cts.api.apache_http_legacy_uses_library">
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
+
+    <application>
+        <uses-library android:name="org.apache.http.legacy"/>
+    </application>
+
+    <instrumentation android:name="repackaged.android.test.InstrumentationTestRunner"
+                     android:targetPackage="android.signature.cts.api.apache_http_legacy_uses_library"
+                     android:label="Apache Http Legacy UsesLibrary API Signature Test"/>
+
+</manifest>
diff --git a/tests/signature/api-check/apache-http-legacy-uses-library-api/AndroidTest.xml b/tests/signature/api-check/apache-http-legacy-uses-library-api/AndroidTest.xml
new file mode 100644
index 0000000..bd2c566
--- /dev/null
+++ b/tests/signature/api-check/apache-http-legacy-uses-library-api/AndroidTest.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for CTS Apache Http Legacy UsesLibrary API Signature test cases">
+    <option name="test-suite-tag" value="cts" />
+    <option name="config-descriptor:metadata" key="component" value="systems" />
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="run-command" value="mkdir -p /data/local/tmp/signature-test" />
+        <option name="teardown-command" value="rm -rf /data/local/tmp/signature-test" />
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="push" value="current.api->/data/local/tmp/signature-test/current.api" />
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="push" value="apache-http-legacy-minus-current.api->/data/local/tmp/signature-test/apache-http-legacy-minus-current.api" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsApacheHttpLegacyUsesLibraryApiSignatureTestCases.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.signature.cts.api.apache_http_legacy_uses_library" />
+        <option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
+        <option name="class" value="android.signature.cts.api.SignatureTest" />
+        <option name="instrumentation-arg" key="base-api-files" value="current.api" />
+        <option name="instrumentation-arg" key="expected-api-files" value="apache-http-legacy-minus-current.api" />
+        <option name="runtime-hint" value="5s" />
+    </test>
+</configuration>
diff --git a/tests/signature/api-check/build_signature_apk.mk b/tests/signature/api-check/build_signature_apk.mk
index 3b0afd2..1bae842 100644
--- a/tests/signature/api-check/build_signature_apk.mk
+++ b/tests/signature/api-check/build_signature_apk.mk
@@ -21,7 +21,7 @@
 #         the list of api files needed
 
 # don't include this package in any target
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
@@ -30,9 +30,15 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := cts-api-signature-test
 
+LOCAL_JNI_SHARED_LIBRARIES := libclassdescriptors
+LOCAL_MULTILIB := both
+
 LOCAL_ADDITIONAL_DEPENDENCIES += \
     $(addprefix $(COMPATIBILITY_TESTCASES_OUT_cts)/,$(LOCAL_SIGNATURE_API_FILES))
 
+LOCAL_DEX_PREOPT := false
+LOCAL_PROGUARD_ENABLED := disabled
+
 include $(BUILD_CTS_PACKAGE)
 
 LOCAL_SIGNATURE_API_FILES :=
diff --git a/tests/signature/api-check/current-api/AndroidManifest.xml b/tests/signature/api-check/current-api/AndroidManifest.xml
index 7dc5730..d6f474b 100644
--- a/tests/signature/api-check/current-api/AndroidManifest.xml
+++ b/tests/signature/api-check/current-api/AndroidManifest.xml
@@ -20,7 +20,7 @@
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
 
-    <application/>
+    <application android:debuggable="true"/>
 
     <instrumentation android:name="repackaged.android.test.InstrumentationTestRunner"
                      android:targetPackage="android.signature.cts.api.current"
diff --git a/tests/signature/api-check/hidden-api/Android.mk b/tests/signature/api-check/hidden-api/Android.mk
new file mode 100644
index 0000000..25df1bc
--- /dev/null
+++ b/tests/signature/api-check/hidden-api/Android.mk
@@ -0,0 +1,43 @@
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := cts-hidden-api-blacklist
+LOCAL_MODULE_STEM := blacklist.api
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH = $(TARGET_OUT_DATA_ETC)
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+include $(BUILD_SYSTEM)/base_rules.mk
+$(eval $(call copy-one-file,$(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST),$(LOCAL_BUILT_MODULE)))
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libcts_hiddenapi
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := hidden-api.cpp
+LOCAL_CFLAGS := -Wall -Werror
+LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
+LOCAL_SDK_VERSION := current
+LOCAL_NDK_STL_VARIANT := c++_static
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_PACKAGE_NAME := CtsHiddenApiDiscoveryTestCases
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+LOCAL_MULTILIB := both
+LOCAL_SIGNATURE_API_FILES := blacklist.api
+LOCAL_JNI_SHARED_LIBRARIES := libcts_hiddenapi
+LOCAL_NDK_STL_VARIANT := c++_static
+include $(LOCAL_PATH)/../build_signature_apk.mk
diff --git a/tests/signature/api-check/hidden-api/AndroidManifest.xml b/tests/signature/api-check/hidden-api/AndroidManifest.xml
new file mode 100644
index 0000000..a68e11a
--- /dev/null
+++ b/tests/signature/api-check/hidden-api/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android.signature.cts.api.hidden">
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
+
+    <application/>
+
+    <instrumentation android:name="repackaged.android.test.InstrumentationTestRunner"
+                     android:targetPackage="android.signature.cts.api.hidden"
+                     android:label="Hidden API Signature Test"/>
+</manifest>
diff --git a/tests/signature/api-check/hidden-api/AndroidTest.xml b/tests/signature/api-check/hidden-api/AndroidTest.xml
new file mode 100644
index 0000000..df6d7ce
--- /dev/null
+++ b/tests/signature/api-check/hidden-api/AndroidTest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for CTS Hidden API Signature test cases">
+    <option name="test-suite-tag" value="cts" />
+    <option name="config-descriptor:metadata" key="component" value="systems" />
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="run-command" value="mkdir -p /data/local/tmp/signature-test" />
+        <option name="teardown-command" value="rm -rf /data/local/tmp/signature-test" />
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="push" value="blacklist.api->/data/local/tmp/signature-test/blacklist.api" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsHiddenApiDiscoveryTestCases.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.signature.cts.api.hidden" />
+        <option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
+        <option name="class" value="android.signature.cts.api.HiddenApiTest" />
+        <option name="instrumentation-arg" key="hidden-api-files" value="blacklist.api" />
+        <option name="runtime-hint" value="30s" />
+    </test>
+</configuration>
diff --git a/tests/signature/api-check/hidden-api/hidden-api.cpp b/tests/signature/api-check/hidden-api/hidden-api.cpp
new file mode 100644
index 0000000..fd2a94d
--- /dev/null
+++ b/tests/signature/api-check/hidden-api/hidden-api.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "jni.h"
+
+class ScopedUtfChars {
+ public:
+  ScopedUtfChars(JNIEnv* env, jstring s) : env_(env), string_(s) {
+    if (s == NULL) {
+      utf_chars_ = NULL;
+    } else {
+      utf_chars_ = env->GetStringUTFChars(s, NULL);
+    }
+  }
+
+  ~ScopedUtfChars() {
+    if (utf_chars_) {
+      env_->ReleaseStringUTFChars(string_, utf_chars_);
+    }
+  }
+
+  const char* c_str() const {
+    return utf_chars_;
+  }
+
+ private:
+  JNIEnv* env_;
+  jstring string_;
+  const char* utf_chars_;
+};
+
+extern "C" JNIEXPORT void JNICALL
+Java_android_signature_cts_api_HiddenApiTest_getField_1JNI(
+    JNIEnv* env, jclass, jclass klass, jstring name, jstring type) {
+  ScopedUtfChars utf_name(env, name);
+  ScopedUtfChars utf_type(env, type);
+  // Attempt to access the given instance field. It will succeed if it exists,
+  // and throw NoSuchFieldError if not.
+  env->GetFieldID(klass, utf_name.c_str(), utf_type.c_str());
+}
+
+extern "C" JNIEXPORT void JNICALL
+Java_android_signature_cts_api_HiddenApiTest_getStaticField_1JNI(
+    JNIEnv* env, jclass, jclass klass, jstring name, jstring type) {
+  ScopedUtfChars utf_name(env, name);
+  ScopedUtfChars utf_type(env, type);
+  // Attempt to access the given static field. It will succeed if it exists,
+  // and throw NoSuchFieldError if not.
+  env->GetStaticFieldID(klass, utf_name.c_str(), utf_type.c_str());
+}
+
+extern "C" JNIEXPORT void JNICALL
+Java_android_signature_cts_api_HiddenApiTest_getMethod_1JNI(
+    JNIEnv* env, jclass, jclass klass, jstring name, jstring signature) {
+  ScopedUtfChars utf_name(env, name);
+  ScopedUtfChars utf_signature(env, signature);
+  // Attempt to access the given instance method. It will succeed if it exists,
+  // and throw NoSuchMethodError if not.
+  env->GetMethodID(klass, utf_name.c_str(), utf_signature.c_str());
+}
+
+extern "C" JNIEXPORT void JNICALL
+Java_android_signature_cts_api_HiddenApiTest_getStaticMethod_1JNI(
+    JNIEnv* env, jclass, jclass klass, jstring name, jstring signature) {
+  ScopedUtfChars utf_name(env, name);
+  ScopedUtfChars utf_signature(env, signature);
+  // Attempt to access the given static method. It will succeed if it exists,
+  // and throw NoSuchMethodError if not.
+  env->GetStaticMethodID(klass, utf_name.c_str(), utf_signature.c_str());
+}
diff --git a/tests/signature/api-check/src/android/signature/cts/api/BootClassPathClassesProvider.java b/tests/signature/api-check/src/android/signature/cts/api/BootClassPathClassesProvider.java
deleted file mode 100644
index 02bd72e..0000000
--- a/tests/signature/api-check/src/android/signature/cts/api/BootClassPathClassesProvider.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.signature.cts.api;
-
-import android.signature.cts.ClassProvider;
-import dalvik.system.DexFile;
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.stream.Stream;
-
-@SuppressWarnings("deprecation")
-public class BootClassPathClassesProvider extends ClassProvider {
-    @Override
-    public Stream<Class<?>> getAllClasses() {
-        Stream.Builder<Class<?>> builder = Stream.builder();
-        for (String file : getBootJarPaths()) {
-            try {
-                DexFile dexFile = new DexFile(file);
-                Enumeration<String> entries = dexFile.entries();
-                while (entries.hasMoreElements()) {
-                    String className = entries.nextElement();
-                    Class<?> clazz = getClass(className);
-                    if (clazz != null) {
-                        builder.add(clazz);
-                    }
-                }
-            } catch (IOException e) {
-                throw new RuntimeException("Failed to parse dex in " + file, e);
-            } catch (ClassNotFoundException e) {
-                throw new RuntimeException("Error while loading class in " + file, e);
-            }
-        }
-        return builder.build();
-    }
-
-    private String[] getBootJarPaths() {
-        return System.getProperty("java.boot.class.path").split(":");
-    }
-}
\ No newline at end of file
diff --git a/tests/signature/api-check/src/android/signature/cts/api/HiddenApiTest.java b/tests/signature/api-check/src/android/signature/cts/api/HiddenApiTest.java
new file mode 100644
index 0000000..e1da5ac
--- /dev/null
+++ b/tests/signature/api-check/src/android/signature/cts/api/HiddenApiTest.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.signature.cts.api;
+
+import android.os.Bundle;
+import android.signature.cts.DexApiDocumentParser;
+import android.signature.cts.DexApiDocumentParser.DexField;
+import android.signature.cts.DexApiDocumentParser.DexMember;
+import android.signature.cts.DexApiDocumentParser.DexMethod;
+import android.signature.cts.FailureType;
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Stream;
+import java.text.ParseException;
+
+import static android.signature.cts.CurrentApi.API_FILE_DIRECTORY;
+
+/**
+ * Checks that it is not possible to access hidden APIs.
+ */
+public class HiddenApiTest extends AbstractApiTest {
+
+    private String[] hiddenApiFiles;
+
+    @Override
+    protected void initializeFromArgs(Bundle instrumentationArgs) throws Exception {
+        hiddenApiFiles = getCommaSeparatedList(instrumentationArgs, "hidden-api-files");
+    }
+
+    /**
+     * Tests that the device does not expose APIs on the provided lists of
+     * DEX signatures.
+     *
+     * Will check the entire API, and then report the complete list of failures
+     */
+    public void testSignature() {
+        System.loadLibrary("cts_hiddenapi");
+        runWithTestResultObserver(resultObserver -> {
+            parseDexApiFilesAsStream(hiddenApiFiles).forEach(dexMember -> {
+                checkSingleMember(dexMember, resultObserver);
+            });
+        });
+    }
+
+    /**
+     * Check that a DexMember cannot be discovered with reflection or JNI, and
+     * record results in the result
+     */
+    private void checkSingleMember(DexMember dexMember, TestResultObserver resultObserver) {
+        Class<?> klass = findClass(dexMember);
+        if (klass == null) {
+            // Class not found. Therefore its members are not visible.
+            return;
+        }
+
+        if (dexMember instanceof DexField) {
+            if (hasMatchingField_Reflection(klass, (DexField) dexMember)) {
+                resultObserver.notifyFailure(
+                        FailureType.EXTRA_FIELD,
+                        dexMember.toString(),
+                        "Hidden field accessible through reflection");
+            }
+            if (hasMatchingField_JNI(klass, (DexField) dexMember)) {
+                resultObserver.notifyFailure(
+                        FailureType.EXTRA_FIELD,
+                        dexMember.toString(),
+                        "Hidden field accessible through JNI");
+            }
+        } else if (dexMember instanceof DexMethod) {
+            if (hasMatchingMethod_Reflection(klass, (DexMethod) dexMember)) {
+                resultObserver.notifyFailure(
+                        FailureType.EXTRA_METHOD,
+                        dexMember.toString(),
+                        "Hidden method accessible through reflection");
+            }
+            if (hasMatchingMethod_JNI(klass, (DexMethod) dexMember)) {
+                resultObserver.notifyFailure(
+                        FailureType.EXTRA_METHOD,
+                        dexMember.toString(),
+                        "Hidden method accessible through JNI");
+            }
+        } else {
+            throw new IllegalStateException("Unexpected type of dex member");
+        }
+    }
+
+    private boolean typesMatch(Class<?>[] classes, List<String> typeNames) {
+        if (classes.length != typeNames.size()) {
+            return false;
+        }
+        for (int i = 0; i < classes.length; ++i) {
+            if (!classes[i].getTypeName().equals(typeNames.get(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private Class<?> findClass(DexMember dexMember) {
+        Class<?> klass = null;
+        try {
+            return Class.forName(dexMember.getJavaClassName());
+        } catch (ClassNotFoundException ex) {
+            return null;
+        }
+    }
+
+    private static boolean hasMatchingField_Reflection(Class<?> klass, DexField dexField) {
+        try {
+            klass.getDeclaredField(dexField.getName());
+            return true;
+        } catch (NoSuchFieldException ex) {
+            return false;
+        }
+    }
+
+    private static boolean hasMatchingField_JNI(Class<?> klass, DexField dexField) {
+        try {
+            getField_JNI(klass, dexField.getName(), dexField.getDexType());
+            return true;
+        } catch (NoSuchFieldError ex) {
+        }
+        try {
+            getStaticField_JNI(klass, dexField.getName(), dexField.getDexType());
+            return true;
+        } catch (NoSuchFieldError ex) {
+        }
+        return false;
+    }
+
+    private boolean hasMatchingMethod_Reflection(Class<?> klass, DexMethod dexMethod) {
+        List<String> methodParams = dexMethod.getJavaParameterTypes();
+
+        if (dexMethod.isConstructor()) {
+            for (Constructor constructor : klass.getDeclaredConstructors()) {
+                if (typesMatch(constructor.getParameterTypes(), methodParams)) {
+                    return true;
+                }
+            }
+        } else {
+            for (Method method : klass.getDeclaredMethods()) {
+                if (method.getName().equals(dexMethod.getName())
+                        && typesMatch(method.getParameterTypes(), methodParams)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private static boolean hasMatchingMethod_JNI(Class<?> klass, DexMethod dexMethod) {
+        try {
+            getMethod_JNI(klass, dexMethod.getName(), dexMethod.getDexSignature());
+            return true;
+        } catch (NoSuchMethodError ex) {
+        }
+        if (!dexMethod.isConstructor()) {
+            try {
+                getStaticMethod_JNI(klass, dexMethod.getName(), dexMethod.getDexSignature());
+                return true;
+            } catch (NoSuchMethodError ex) {
+            }
+        }
+        return false;
+    }
+
+    private static Stream<DexMember> parseDexApiFilesAsStream(String[] apiFiles) {
+        DexApiDocumentParser dexApiDocumentParser = new DexApiDocumentParser();
+        return Stream.of(apiFiles)
+                .map(name -> new File(API_FILE_DIRECTORY + "/" + name))
+                .flatMap(file -> readFile(file))
+                .flatMap(stream -> dexApiDocumentParser.parseAsStream(stream));
+    }
+
+    private static native boolean getField_JNI(Class<?> klass, String name, String type);
+    private static native boolean getStaticField_JNI(Class<?> klass, String name, String type);
+    private static native boolean getMethod_JNI(Class<?> klass, String name, String signature);
+    private static native boolean getStaticMethod_JNI(Class<?> klass, String name,
+            String signature);
+}
diff --git a/tests/signature/api-check/src/android/signature/cts/api/AbstractApiTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/AbstractApiTest.java
similarity index 100%
rename from tests/signature/api-check/src/android/signature/cts/api/AbstractApiTest.java
rename to tests/signature/api-check/src/java/android/signature/cts/api/AbstractApiTest.java
diff --git a/tests/signature/api-check/src/android/signature/cts/api/AnnotationTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/AnnotationTest.java
similarity index 100%
rename from tests/signature/api-check/src/android/signature/cts/api/AnnotationTest.java
rename to tests/signature/api-check/src/java/android/signature/cts/api/AnnotationTest.java
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/BootClassPathClassesProvider.java b/tests/signature/api-check/src/java/android/signature/cts/api/BootClassPathClassesProvider.java
new file mode 100644
index 0000000..95f46df
--- /dev/null
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/BootClassPathClassesProvider.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.signature.cts.api;
+
+import android.os.Debug;
+import android.signature.cts.ClassProvider;
+import dalvik.system.BaseDexClassLoader;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.stream.Stream;
+
+@SuppressWarnings("deprecation")
+public class BootClassPathClassesProvider extends ClassProvider {
+    private static boolean sJvmtiAttached = false;
+
+    @Override
+    public Stream<Class<?>> getAllClasses() {
+        if (!sJvmtiAttached) {
+            try {
+                Debug.attachJvmtiAgent(copyAgentToFile("classdescriptors").getAbsolutePath(), null,
+                        BootClassPathClassesProvider.class.getClassLoader());
+                sJvmtiAttached = true;
+                initialize();
+            } catch (Exception e) {
+                throw new RuntimeException("Error while attaching JVMTI agent", e);
+            }
+        }
+        return Arrays.stream(getClassloaderDescriptors(Object.class.getClassLoader()))
+                .map(descriptor -> {
+                    System.err.println("Class name = " + descriptor);
+                    String classname = descriptor.replace('/', '.');
+                    // omit L and ; at the front and at the end
+                    return classname.substring(1, classname.length() - 1);
+                })
+                .map(classname -> {
+                    try {
+                        return getClass(classname);
+                    } catch (ClassNotFoundException e) {
+                        throw new RuntimeException("Cannot load " + classname, e);
+                    }
+                });
+    }
+
+    private static File copyAgentToFile(String lib) throws Exception {
+        ClassLoader cl = BootClassPathClassesProvider.class.getClassLoader();
+
+        File copiedAgent = File.createTempFile("agent", ".so");
+        try (InputStream is = new FileInputStream(
+                ((BaseDexClassLoader) cl).findLibrary(lib))) {
+            try (OutputStream os = new FileOutputStream(copiedAgent)) {
+                byte[] buffer = new byte[64 * 1024];
+
+                while (true) {
+                    int numRead = is.read(buffer);
+                    if (numRead == -1) {
+                        break;
+                    }
+                    os.write(buffer, 0, numRead);
+                }
+            }
+        }
+        return copiedAgent;
+    }
+
+    private static native void initialize();
+
+    private static native String[] getClassloaderDescriptors(ClassLoader loader);
+}
diff --git a/tests/signature/api-check/src/android/signature/cts/api/SignatureTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java
similarity index 100%
rename from tests/signature/api-check/src/android/signature/cts/api/SignatureTest.java
rename to tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java
diff --git a/tests/signature/api-check/src/android/signature/cts/api/TestResultObserver.java b/tests/signature/api-check/src/java/android/signature/cts/api/TestResultObserver.java
similarity index 100%
rename from tests/signature/api-check/src/android/signature/cts/api/TestResultObserver.java
rename to tests/signature/api-check/src/java/android/signature/cts/api/TestResultObserver.java
diff --git a/tests/signature/api-check/src/jni/classdescriptors.cpp b/tests/signature/api-check/src/jni/classdescriptors.cpp
new file mode 100644
index 0000000..3da66f1
--- /dev/null
+++ b/tests/signature/api-check/src/jni/classdescriptors.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <jni.h>
+#include <jvmti.h>
+
+#include <string.h>
+
+namespace android {
+namespace signature {
+namespace cts {
+namespace api {
+
+static jvmtiEnv* jvmti_env;
+static jvmtiError (*get_descriptor_list)(jvmtiEnv* env, jobject loader, jint* cnt, char*** descs);
+
+template <typename T>
+static void Dealloc(T* t) {
+  jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(t));
+}
+
+template <typename T, typename ...Rest>
+static void Dealloc(T* t, Rest... rs) {
+  Dealloc(t);
+  Dealloc(rs...);
+}
+
+static void DeallocParams(jvmtiParamInfo* params, jint n_params) {
+  for (jint i = 0; i < n_params; i++) {
+    Dealloc(params[i].name);
+  }
+}
+
+static void Cleanup(char** data, jint cnt) {
+  for (jint i = 0; i < cnt; i++) {
+    Dealloc(data[i]);
+  }
+  Dealloc(data);
+}
+
+extern "C" JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM* vm,
+                                                 __attribute__((unused)) char* options,
+                                                 __attribute__((unused)) void* reserved) {
+  jint jvmError = vm->GetEnv(reinterpret_cast<void**>(&jvmti_env), JVMTI_VERSION_1_2);
+  if (jvmError != JNI_OK) {
+    return jvmError;
+  }
+  return JVMTI_ERROR_NONE;
+}
+
+extern "C" JNIEXPORT jobjectArray JNICALL Java_android_signature_cts_api_BootClassPathClassesProvider_getClassloaderDescriptors(
+    JNIEnv* env, jclass, jobject loader) {
+  if (get_descriptor_list == nullptr) {
+    jclass rt_exception = env->FindClass("java/lang/RuntimeException");
+    env->ThrowNew(rt_exception, "get_class_loader_class_descriptor extension is not ready.");
+    return nullptr;
+  }
+  char** classes = nullptr;
+  jint cnt = -1;
+  jvmtiError error = get_descriptor_list(jvmti_env, loader, &cnt, &classes);
+  if (error != JVMTI_ERROR_NONE) {
+    jclass rt_exception = env->FindClass("java/lang/RuntimeException");
+    env->ThrowNew(rt_exception, "Error while executing get_class_loader_class_descriptor.");
+    return nullptr;
+  }
+
+  jobjectArray arr = env->NewObjectArray(cnt, env->FindClass("java/lang/String"), nullptr);
+  if (env->ExceptionCheck()) {
+    Cleanup(classes, cnt);
+    return nullptr;
+  }
+
+  for (jint i = 0; i < cnt; i++) {
+    env->SetObjectArrayElement(arr, i, env->NewStringUTF(classes[i]));
+    if (env->ExceptionCheck()) {
+      Cleanup(classes, cnt);
+      return nullptr;
+    }
+  }
+  Cleanup(classes, cnt);
+  return arr;
+}
+
+extern "C" JNIEXPORT void JNICALL Java_android_signature_cts_api_BootClassPathClassesProvider_initialize(JNIEnv* env, jclass) {
+  jint functionInfosCount = 0;
+  jvmtiExtensionFunctionInfo* functionInfos = nullptr;
+
+  jvmtiError err = jvmti_env->GetExtensionFunctions(&functionInfosCount, &functionInfos);
+  if (err != JVMTI_ERROR_NONE) {
+    jclass rt_exception = env->FindClass("java/lang/RuntimeException");
+    env->ThrowNew(rt_exception, "Failed to get JVMTI extension APIs");
+    return;
+  }
+
+  for (jint i = 0; i < functionInfosCount; i++) {
+    jvmtiExtensionFunctionInfo* curInfo = &functionInfos[i];
+    if (strcmp("com.android.art.class.get_class_loader_class_descriptors", curInfo->id) == 0) {
+      get_descriptor_list = reinterpret_cast<jvmtiError (*)(jvmtiEnv*, jobject, jint*, char***)>(curInfo->func);
+    }
+    DeallocParams(curInfo->params, curInfo->param_count);
+    Dealloc(curInfo->id, curInfo->short_description, curInfo->params, curInfo->errors);
+  }
+  Dealloc(functionInfos);
+
+  if (get_descriptor_list == nullptr) {
+    jclass rt_exception = env->FindClass("java/lang/RuntimeException");
+    env->ThrowNew(rt_exception, "Failed to find get_class_loader_class_descriptors extension");
+    return;
+  }
+}
+
+}  // namespace api
+}  // namespace cts
+}  // namespace signature
+}  // namespace android
diff --git a/tests/signature/api-check/system-annotation/AndroidManifest.xml b/tests/signature/api-check/system-annotation/AndroidManifest.xml
index 55318ed..7753fb9 100644
--- a/tests/signature/api-check/system-annotation/AndroidManifest.xml
+++ b/tests/signature/api-check/system-annotation/AndroidManifest.xml
@@ -20,7 +20,7 @@
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
 
-    <application/>
+    <application android:debuggable="true"/>
 
     <instrumentation android:name="repackaged.android.test.InstrumentationTestRunner"
                      android:targetPackage="android.signature.cts.api.system_annotation"
diff --git a/tests/signature/api-check/system-api/AndroidTest.xml b/tests/signature/api-check/system-api/AndroidTest.xml
index 23254ae..5f70478 100644
--- a/tests/signature/api-check/system-api/AndroidTest.xml
+++ b/tests/signature/api-check/system-api/AndroidTest.xml
@@ -32,7 +32,7 @@
         <option name="test-file-name" value="CtsSystemApiSignatureTestCases.apk" />
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="android.signature.cts.api.systemt" />
+        <option name="package" value="android.signature.cts.api.system" />
         <option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
         <option name="class" value="android.signature.cts.api.SignatureTest" />
         <option name="instrumentation-arg" key="base-api-files" value="current.api" />
diff --git a/tests/signature/runSignatureTests.sh b/tests/signature/runSignatureTests.sh
index 8e2204d..1350297 100755
--- a/tests/signature/runSignatureTests.sh
+++ b/tests/signature/runSignatureTests.sh
@@ -16,9 +16,14 @@
 CtsAndroidTestMockCurrentApiSignatureTestCases
 CtsAndroidTestRunnerCurrentApiSignatureTestCases
 CtsAndroidTestBase27ApiSignatureTestCases
+
+CtsApacheHttpLegacy27ApiSignatureTestCases
 CtsApacheHttpLegacyCurrentApiSignatureTestCases
+CtsApacheHttpLegacyUsesLibraryApiSignatureTestCases
 
 CtsSystemApiAnnotationTestCases
+
+CtsHiddenApiDiscoveryTestCases
 "
 else
     PACKAGES=${1+"$@"}
diff --git a/tests/signature/src/android/signature/cts/DexApiDocumentParser.java b/tests/signature/src/android/signature/cts/DexApiDocumentParser.java
new file mode 100644
index 0000000..7cb60fb
--- /dev/null
+++ b/tests/signature/src/android/signature/cts/DexApiDocumentParser.java
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.signature.cts;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Spliterator;
+import java.util.function.Consumer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import java.text.ParseException;
+
+/**
+ * Parses an API definition given as a text file with DEX signatures of class
+ * members. Constructs a {@link DexApiDocumentParser.DexMember} for every class
+ * member.
+ *
+ * <p>The definition file is converted into a {@link Stream} of
+ * {@link DexApiDocumentParser.DexMember}.
+ */
+public class DexApiDocumentParser {
+
+    public Stream<DexMember> parseAsStream(InputStream inputStream) {
+        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
+        return StreamSupport.stream(new DexApiSpliterator(reader), false);
+    }
+
+    private static class DexApiSpliterator implements Spliterator<DexMember> {
+        private final BufferedReader mReader;
+        private int mLineNum;
+
+        private static final Pattern REGEX_CLASS = Pattern.compile("^L[^->]*;$");
+        private static final Pattern REGEX_FIELD = Pattern.compile("^(L[^->]*;)->(.*):(.*)$");
+        private static final Pattern REGEX_METHOD =
+                Pattern.compile("^(L[^->]*;)->(.*)\\((.*)\\)(.*)$");
+
+        DexApiSpliterator(BufferedReader reader) {
+            mReader = reader;
+            mLineNum = 0;
+        }
+
+        @Override
+        public boolean tryAdvance(Consumer<? super DexMember> action) {
+            DexMember nextMember = null;
+            try {
+                nextMember = next();
+            } catch (IOException | ParseException ex) {
+                throw new RuntimeException(ex);
+            }
+            if (nextMember == null) {
+                return false;
+            }
+            action.accept(nextMember);
+            return true;
+        }
+
+        @Override
+        public Spliterator<DexMember> trySplit() {
+            return null;
+        }
+
+        @Override
+        public long estimateSize() {
+            return Long.MAX_VALUE;
+        }
+
+        @Override
+        public int characteristics() {
+            return ORDERED | DISTINCT | NONNULL | IMMUTABLE;
+        }
+
+        /**
+         * Parses lines of DEX signatures from `mReader`. The following three
+         * line formats are supported:
+         * 1) [class descriptor]
+         *      - e.g. Lcom/example/MyClass;
+         *      - these lines are ignored
+         * 2) [class descriptor]->[field name]:[field type]
+         *      - e.g. Lcom/example/MyClass;->myField:I
+         *      - these lines are parsed as field signatures
+         * 3) [class descriptor]->[method name]([method parameter types])[method return type]
+         *      - e.g. Lcom/example/MyClass;->myMethod(Lfoo;Lbar;)J
+         *      - these lines are parsed as method signatures
+         */
+        private DexMember next() throws IOException, ParseException {
+            while (true) {
+                // Read the next line from the input.
+                String line = mReader.readLine();
+                if (line == null) {
+                    // End of stream.
+                    return null;
+                }
+
+                // Increment the line number.
+                mLineNum = mLineNum + 1;
+
+                // Match line against regex patterns.
+                Matcher matchClass = REGEX_CLASS.matcher(line);
+                Matcher matchField = REGEX_FIELD.matcher(line);
+                Matcher matchMethod = REGEX_METHOD.matcher(line);
+
+                // Check that *exactly* one pattern matches.
+                int matchCount = (matchClass.matches() ? 1 : 0) + (matchField.matches() ? 1 : 0) +
+                        (matchMethod.matches() ? 1 : 0);
+                if (matchCount == 0) {
+                    throw new ParseException("Could not parse: \"" + line + "\"", mLineNum);
+                } else if (matchCount > 1) {
+                    throw new ParseException("Ambiguous parse: \"" + line + "\"", mLineNum);
+                }
+
+                // Extract information from the line.
+                if (matchClass.matches()) {
+                    // We ignore lines describing a class because classes are
+                    // not being hidden.
+                } else if (matchField.matches()) {
+                    return new DexField(
+                            matchField.group(1), matchField.group(2), matchField.group(3));
+                } else if (matchMethod.matches()) {
+                    return new DexMethod(
+                            matchMethod.group(1),matchMethod.group(2),
+                            parseDexTypeList(matchMethod.group(3)), matchMethod.group(4));
+                } else {
+                    throw new IllegalStateException();
+                }
+            }
+        }
+
+        private List<String> parseDexTypeList(String typeSequence) throws ParseException {
+            List<String> list = new ArrayList<String>();
+            while (!typeSequence.isEmpty()) {
+                String type = firstDexTypeFromList(typeSequence);
+                list.add(type);
+                typeSequence = typeSequence.substring(type.length());
+            }
+            return list;
+        }
+
+        /**
+         * Returns the first dex type in `typeList` or throws a ParserException
+         * if a dex type is not recognized. The input is not changed.
+         */
+        private String firstDexTypeFromList(String typeList) throws ParseException {
+            String dexDimension = "";
+            while (typeList.startsWith("[")) {
+                dexDimension += "[";
+                typeList = typeList.substring(1);
+            }
+
+            String type = null;
+            if (typeList.startsWith("V")
+                    || typeList.startsWith("Z")
+                    || typeList.startsWith("B")
+                    || typeList.startsWith("C")
+                    || typeList.startsWith("S")
+                    || typeList.startsWith("I")
+                    || typeList.startsWith("J")
+                    || typeList.startsWith("F")
+                    || typeList.startsWith("D")) {
+                type = typeList.substring(0, 1);
+            } else if (typeList.startsWith("L") && typeList.indexOf(";") > 0) {
+                type = typeList.substring(0, typeList.indexOf(";") + 1);
+            } else {
+                throw new ParseException(
+                        "Unexpected dex type in \"" + typeList + "\"", mLineNum);
+            }
+
+            return dexDimension + type;
+        }
+    }
+
+    /**
+     * Represents one class member parsed from the reader of dex signatures.
+     */
+    public static abstract class DexMember {
+        private final String mName;
+        private final String mClassDescriptor;
+        private final String mType;
+
+        protected DexMember(String className, String name, String type) {
+            mName = name;
+            mClassDescriptor = className;
+            mType = type;
+        }
+
+        public String getName() {
+            return mName;
+        }
+
+        public String getDexClassName() {
+            return mClassDescriptor;
+        }
+
+        public String getJavaClassName() {
+            return dexToJavaType(mClassDescriptor);
+        }
+
+        public String getDexType() {
+            return mType;
+        }
+
+        public String getJavaType() {
+            return dexToJavaType(mType);
+        }
+
+        /**
+         * Converts `type` to a Java type.
+         */
+        protected static String dexToJavaType(String type) {
+            String javaDimension = "";
+            while (type.startsWith("[")) {
+                javaDimension += "[]";
+                type = type.substring(1);
+            }
+
+            String javaType = null;
+            if ("V".equals(type)) {
+                javaType = "void";
+            } else if ("Z".equals(type)) {
+                javaType = "boolean";
+            } else if ("B".equals(type)) {
+                javaType = "byte";
+            } else if ("C".equals(type)) {
+                javaType = "char";
+            } else if ("S".equals(type)) {
+                javaType = "short";
+            } else if ("I".equals(type)) {
+                javaType = "int";
+            } else if ("J".equals(type)) {
+                javaType = "long";
+            } else if ("F".equals(type)) {
+                javaType = "float";
+            } else if ("D".equals(type)) {
+                javaType = "double";
+            } else if (type.startsWith("L") && type.endsWith(";")) {
+                javaType = type.substring(1, type.length() - 1).replace('/', '.');
+            } else {
+                throw new IllegalStateException("Unexpected type " + type);
+            }
+
+            return javaType + javaDimension;
+        }
+    }
+
+    public static class DexField extends DexMember {
+        public DexField(String className, String name, String type) {
+            super(className, name, type);
+        }
+
+        @Override
+        public String toString() {
+            return getJavaType() + " " + getJavaClassName() + "." + getName();
+        }
+    }
+
+    public static class DexMethod extends DexMember {
+        private final List<String> mParamTypeList;
+
+        public DexMethod(String className, String name, List<String> paramTypeList,
+                String dexReturnType) {
+            super(className, name, dexReturnType);
+            mParamTypeList = paramTypeList;
+        }
+
+        public String getDexSignature() {
+            return "(" + String.join("", mParamTypeList) + ")" + getDexType();
+        }
+
+        public List<String> getJavaParameterTypes() {
+            return mParamTypeList
+                    .stream()
+                    .map(DexMember::dexToJavaType)
+                    .collect(Collectors.toList());
+        }
+
+        public boolean isConstructor() {
+            return "<init>".equals(getName()) && "V".equals(getDexType());
+        }
+
+        @Override
+        public String toString() {
+            return getJavaType() + " " + getJavaClassName() + "." + getName()
+                    + "(" + String.join(", ", getJavaParameterTypes()) + ")";
+        }
+    }
+}
diff --git a/tests/tests/alarmclock/service/src/android/alarmclock/service/MainInteractionSession.java b/tests/tests/alarmclock/service/src/android/alarmclock/service/MainInteractionSession.java
index 547203e..99c0b6f 100644
--- a/tests/tests/alarmclock/service/src/android/alarmclock/service/MainInteractionSession.java
+++ b/tests/tests/alarmclock/service/src/android/alarmclock/service/MainInteractionSession.java
@@ -90,7 +90,7 @@
 
             case SET_TIMER_FOR_DISMISSAL:
                 intent = new Intent(AlarmClock.ACTION_SET_TIMER);
-                intent.putExtra(AlarmClock.EXTRA_LENGTH, 10);
+                intent.putExtra(AlarmClock.EXTRA_LENGTH, 1);
                 break;
 
             case SNOOZE_ALARM:
diff --git a/tests/tests/alarmclock/src/android/alarmclock/cts/DismissTimerTest.java b/tests/tests/alarmclock/src/android/alarmclock/cts/DismissTimerTest.java
index dff8835..5951e65 100644
--- a/tests/tests/alarmclock/src/android/alarmclock/cts/DismissTimerTest.java
+++ b/tests/tests/alarmclock/src/android/alarmclock/cts/DismissTimerTest.java
@@ -1,11 +1,38 @@
 package android.alarmclock.cts;
 
 import android.alarmclock.common.Utils;
+import android.content.Context;
+import android.media.AudioManager;
 
 public class DismissTimerTest extends AlarmClockTestBase {
 
+    private int mSavedVolume;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        // The timer may ring between expiration and dismissal; silence this.
+        final AudioManager audioManager = (AudioManager) getInstrumentation().getTargetContext()
+                .getSystemService(Context.AUDIO_SERVICE);
+        mSavedVolume = audioManager.getStreamVolume(AudioManager.STREAM_ALARM);
+        audioManager.setStreamVolume(AudioManager.STREAM_ALARM, 0, 0);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        final AudioManager audioManager = (AudioManager) getInstrumentation().getTargetContext()
+                .getSystemService(Context.AUDIO_SERVICE);
+        audioManager.setStreamVolume(AudioManager.STREAM_ALARM, mSavedVolume, 0);
+    }
+
     public void testAll() throws Exception {
         assertEquals(Utils.COMPLETION_RESULT, runTest(Utils.TestcaseType.SET_TIMER_FOR_DISMISSAL));
+        try {
+            Thread.sleep(1500);
+        } catch (InterruptedException ignored) {
+        }
         assertEquals(Utils.COMPLETION_RESULT, runTest(Utils.TestcaseType.DISMISS_TIMER));
     }
 }
diff --git a/tests/tests/app.usage/Android.mk b/tests/tests/app.usage/Android.mk
index fa5c60e..3da4dd0 100644
--- a/tests/tests/app.usage/Android.mk
+++ b/tests/tests/app.usage/Android.mk
@@ -17,6 +17,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_PACKAGE_NAME := CtsUsageStatsTestCases
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 # don't include this package in any target
 LOCAL_MODULE_TAGS := optional
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
index 110534f..44beedb 100644
--- a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
+++ b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
@@ -16,7 +16,9 @@
 
 package android.app.usage.cts;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 import android.app.Activity;
 import android.app.AppOpsManager;
@@ -38,7 +40,6 @@
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.Until;
-import android.test.InstrumentationTestCase;
 import android.util.SparseLongArray;
 
 import org.junit.Before;
@@ -202,13 +203,23 @@
             UsageEvents.Event event = new UsageEvents.Event();
             assertTrue(events.getNextEvent(event));
             if (event.mEventType == UsageEvents.Event.STANDBY_BUCKET_CHANGED) {
-                found |= event.mBucket == UsageStatsManager.STANDBY_BUCKET_RARE;
+                found |= event.getStandbyBucket() == UsageStatsManager.STANDBY_BUCKET_RARE;
             }
         }
 
         assertTrue(found);
     }
 
+    @Test
+    public void testGetAppStandbyBuckets() throws Exception {
+        mUiDevice.executeShellCommand("am set-standby-bucket " + mTargetPackage + " rare");
+        Map<String, Integer> bucketMap = mUsageStatsManager.getAppStandbyBuckets();
+        assertTrue("No bucket data returned", bucketMap.size() > 0);
+        final int bucket = bucketMap.getOrDefault(mTargetPackage, -1);
+        assertEquals("Incorrect bucket returned for " + mTargetPackage, bucket,
+                UsageStatsManager.STANDBY_BUCKET_RARE);
+    }
+
     /**
      * We can't run this test because we are unable to change the system time.
      * It would be nice to add a shell command or other to allow the shell user
diff --git a/tests/tests/app/Android.mk b/tests/tests/app/Android.mk
index d087058..a77c038 100644
--- a/tests/tests/app/Android.mk
+++ b/tests/tests/app/Android.mk
@@ -17,6 +17,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_PACKAGE_NAME := CtsAndroidAppTestCases
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 # don't include this package in any target
 LOCAL_MODULE_TAGS := optional
diff --git a/tests/tests/appwidget/Android.mk b/tests/tests/appwidget/Android.mk
index da7194b..b6243fc 100644
--- a/tests/tests/appwidget/Android.mk
+++ b/tests/tests/appwidget/Android.mk
@@ -24,6 +24,7 @@
     $(call all-java-files-under, common/src)
 
 LOCAL_PACKAGE_NAME := CtsAppWidgetTestCases
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     mockito-target-minus-junit4 \
diff --git a/tests/tests/carrierapi/Android.mk b/tests/tests/carrierapi/Android.mk
index 8a64870..3adac15 100644
--- a/tests/tests/carrierapi/Android.mk
+++ b/tests/tests/carrierapi/Android.mk
@@ -30,6 +30,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsCarrierApiTestCases
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
diff --git a/tests/tests/content/Android.mk b/tests/tests/content/Android.mk
index 0bbbb02..39587eb 100644
--- a/tests/tests/content/Android.mk
+++ b/tests/tests/content/Android.mk
@@ -59,6 +59,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_MULTILIB := both
 LOCAL_PACKAGE_NAME := CtsContentTestCases
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
diff --git a/tests/tests/content/CtsSyncAccountAccessOtherCertTests/Android.mk b/tests/tests/content/CtsSyncAccountAccessOtherCertTests/Android.mk
index 14dd2c9..01df0b5 100644
--- a/tests/tests/content/CtsSyncAccountAccessOtherCertTests/Android.mk
+++ b/tests/tests/content/CtsSyncAccountAccessOtherCertTests/Android.mk
@@ -28,6 +28,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsSyncAccountAccessOtherCertTestCases
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey2
 
diff --git a/tests/tests/content/SyncAccountAccessStubs/Android.mk b/tests/tests/content/SyncAccountAccessStubs/Android.mk
index c0b6fa2..9f015a3 100644
--- a/tests/tests/content/SyncAccountAccessStubs/Android.mk
+++ b/tests/tests/content/SyncAccountAccessStubs/Android.mk
@@ -23,6 +23,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsSyncAccountAccessStubs
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
diff --git a/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java b/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java
index 1ba9753..2695fac 100644
--- a/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java
+++ b/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java
@@ -181,17 +181,6 @@
     }
 
     /**
-     * Test ACTION_SHOW_ASSISTED_DIALING_SETTINGS, it will display the assisted dialing preferences.
-     */
-    public void testShowAssistedDialingSettings() {
-        PackageManager packageManager = mContext.getPackageManager();
-        if (packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
-            Intent intent = new Intent(TelecomManager.ACTION_SHOW_ASSISTED_DIALING_SETTINGS);
-            assertCanBeHandled(intent);
-        }
-    }
-
-    /**
      * Test ACTION_SHOW_CALL_SETTINGS, it will display the call preferences.
      */
     public void testShowCallSettings() {
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java b/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
index 5140e69..edc7924 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
@@ -45,12 +45,12 @@
 public class PackageManagerTest extends AndroidTestCase {
     private PackageManager mPackageManager;
     private static final String PACKAGE_NAME = "android.content.cts";
-    private static final String CONTENT_PKG_NAME = "android.content.cts";
     private static final String ACTIVITY_ACTION_NAME = "android.intent.action.PMTEST";
     private static final String MAIN_ACTION_NAME = "android.intent.action.MAIN";
     private static final String SERVICE_ACTION_NAME =
                                 "android.content.pm.cts.activity.PMTEST_SERVICE";
-    private static final String PERMISSION_NAME = "android.permission.INTERNET";
+    private static final String GRANTED_PERMISSION_NAME = "android.permission.INTERNET";
+    private static final String NOT_GRANTED_PERMISSION_NAME = "android.permission.HARDWARE_TEST";
     private static final String ACTIVITY_NAME = "android.content.pm.cts.TestPmActivity";
     private static final String SERVICE_NAME = "android.content.pm.cts.TestPmService";
     private static final String RECEIVER_NAME = "android.content.pm.cts.PmTestReceiver";
@@ -230,7 +230,8 @@
         assertTrue(mPackageManager.getPackageGids(PACKAGE_NAME).length > 0);
 
         // Test getPermissionInfo
-        assertEquals(PERMISSION_NAME, mPackageManager.getPermissionInfo(PERMISSION_NAME, 0).name);
+        assertEquals(GRANTED_PERMISSION_NAME,
+                mPackageManager.getPermissionInfo(GRANTED_PERMISSION_NAME, 0).name);
 
         // Test getPermissionGroupInfo
         assertEquals(PERMISSIONGROUP_NAME, mPackageManager.getPermissionGroupInfo(
@@ -388,17 +389,6 @@
                 mPackageManager.getComponentEnabledSetting(componentName));
     }
 
-    public void testOpPermission() {
-        PermissionInfo permissionInfo = new PermissionInfo();
-        String permissionName = "android.content.cts.permission.TEST_DYNAMIC.ADD";
-        permissionInfo.name = permissionName;
-        permissionInfo.labelRes = R.string.permlab_testDynamic;
-        permissionInfo.nonLocalizedLabel = "Test Tree";
-
-        // TODO: Bug ID 1561181.
-        // Can't add permission in dynamic way
-    }
-
     public void testGetIcon() throws NameNotFoundException {
         assertNotNull(mPackageManager.getApplicationIcon(PACKAGE_NAME));
         assertNotNull(mPackageManager.getApplicationIcon(mPackageManager.getApplicationInfo(
@@ -415,11 +405,41 @@
         assertNotNull(mPackageManager.getDrawable(PACKAGE_NAME, iconRes, appInfo));
     }
 
-    public void testCheckMethods() {
+    public void testCheckSignaturesMatch() {
+        // Compare the signature of this package to another package installed by this test suite
+        // (see AndroidTest.xml). Their signatures must match.
         assertEquals(PackageManager.SIGNATURE_MATCH, mPackageManager.checkSignatures(PACKAGE_NAME,
-                CONTENT_PKG_NAME));
+                "com.android.cts.stub"));
+        // This package's signature should match its own signature.
+        assertEquals(PackageManager.SIGNATURE_MATCH, mPackageManager.checkSignatures(PACKAGE_NAME,
+                PACKAGE_NAME));
+    }
+
+    public void testCheckSignaturesNoMatch() {
+        // This test package's signature shouldn't match the system's signature.
+        assertEquals(PackageManager.SIGNATURE_NO_MATCH, mPackageManager.checkSignatures(
+                PACKAGE_NAME, "android"));
+    }
+
+    public void testCheckSignaturesUnknownPackage() {
+        assertEquals(PackageManager.SIGNATURE_UNKNOWN_PACKAGE, mPackageManager.checkSignatures(
+                PACKAGE_NAME, "this.package.does.not.exist"));
+    }
+
+    public void testCheckPermissionGranted() {
         assertEquals(PackageManager.PERMISSION_GRANTED,
-                mPackageManager.checkPermission(PERMISSION_NAME, PACKAGE_NAME));
+                mPackageManager.checkPermission(GRANTED_PERMISSION_NAME, PACKAGE_NAME));
+    }
+
+    public void testCheckPermissionNotGranted() {
+        assertEquals(PackageManager.PERMISSION_DENIED,
+                mPackageManager.checkPermission(NOT_GRANTED_PERMISSION_NAME, PACKAGE_NAME));
+    }
+
+    public void testCheckPermissionSystem() {
+        // Everything will be granted to the system.
+        assertEquals(PackageManager.PERMISSION_GRANTED,
+                mPackageManager.checkPermission(NOT_GRANTED_PERMISSION_NAME, "android"));
     }
 
     public void testResolveMethods() {
diff --git a/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java b/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java
index 78ce89a..144bdde 100644
--- a/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java
+++ b/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java
@@ -67,6 +67,7 @@
         allowedDensities.add(DisplayMetrics.DENSITY_360);
         allowedDensities.add(DisplayMetrics.DENSITY_400);
         allowedDensities.add(DisplayMetrics.DENSITY_420);
+        allowedDensities.add(DisplayMetrics.DENSITY_440);
         allowedDensities.add(DisplayMetrics.DENSITY_XXHIGH);
         allowedDensities.add(DisplayMetrics.DENSITY_560);
         allowedDensities.add(DisplayMetrics.DENSITY_XXXHIGH);
diff --git a/tests/tests/dreams/Android.mk b/tests/tests/dreams/Android.mk
index 11e4b21..f1a31d8 100644
--- a/tests/tests/dreams/Android.mk
+++ b/tests/tests/dreams/Android.mk
@@ -32,6 +32,7 @@
 
 # Need access to ServiceManager - see b/13307221
 #LOCAL_SDK_VERSION := current
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
diff --git a/tests/tests/graphics/res/drawable/animatedimagedrawable_automirrored.xml b/tests/tests/graphics/res/drawable/animatedimagedrawable_automirrored.xml
new file mode 100644
index 0000000..3d5b0cf
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/animatedimagedrawable_automirrored.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<animated-image xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/animated"
+    android:autoMirrored="true"
+    />
+
diff --git a/tests/tests/graphics/res/drawable/animatedimagedrawable_nosrc.xml b/tests/tests/graphics/res/drawable/animatedimagedrawable_nosrc.xml
new file mode 100644
index 0000000..0f7ac8f
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/animatedimagedrawable_nosrc.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<animated-image xmlns:android="http://schemas.android.com/apk/res/android"
+    />
+
diff --git a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
index 0d70947..1cc86a3 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
@@ -18,7 +18,6 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
@@ -39,7 +38,6 @@
 import android.graphics.Shader;
 import android.graphics.Typeface;
 import android.graphics.Xfermode;
-import android.graphics.fonts.FontVariationAxis;
 import android.os.LocaleList;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
@@ -1642,4 +1640,82 @@
         p.setElegantTextHeight(false);
         assertFalse(p.isElegantTextHeight());
     }
+
+    @Test
+    public void testEqualsForTextMeasurment() {
+        Paint p1 = new Paint();
+        Paint p2 = new Paint();
+
+        assertTrue(p1.equalsForTextMeasurement(p2));
+    }
+
+    @Test
+    public void testEqualsForTextMeasurment_textSize() {
+        Paint p1 = new Paint();
+        Paint p2 = new Paint();
+
+        p1.setTextSize(p2.getTextSize() * 2.0f);
+        assertFalse(p1.equalsForTextMeasurement(p2));
+        p1.setTextSize(p2.getTextSize());
+        assertTrue(p1.equalsForTextMeasurement(p2));
+    }
+
+    @Test
+    public void testEqualsForTextMeasurment_textSkew() {
+        Paint p1 = new Paint();
+        Paint p2 = new Paint();
+
+        p1.setTextSkewX(p2.getTextSkewX() + 2.0f);
+        assertFalse(p1.equalsForTextMeasurement(p2));
+        p1.setTextSkewX(p2.getTextSkewX());
+        assertTrue(p1.equalsForTextMeasurement(p2));
+    }
+
+    @Test
+    public void testEqualsForTextMeasurment_textScale() {
+        Paint p1 = new Paint();
+        Paint p2 = new Paint();
+
+        p1.setTextScaleX(p2.getTextScaleX() * 2.0f);
+        assertFalse(p1.equalsForTextMeasurement(p2));
+        p1.setTextScaleX(p2.getTextScaleX());
+        assertTrue(p1.equalsForTextMeasurement(p2));
+    }
+
+    @Test
+    public void testEqualsForTextMeasurment_letterSpacing() {
+        Paint p1 = new Paint();
+        Paint p2 = new Paint();
+
+        p1.setLetterSpacing(p2.getLetterSpacing() + 2.0f);
+        assertFalse(p1.equalsForTextMeasurement(p2));
+        p1.setLetterSpacing(p2.getLetterSpacing());
+        assertTrue(p1.equalsForTextMeasurement(p2));
+    }
+
+    @Test
+    public void testEqualsForTextMeasurment_localeList() {
+        Paint p1 = new Paint();
+        Paint p2 = new Paint();
+
+        LocaleList enUS = LocaleList.forLanguageTags("en-US");
+        LocaleList jaJP = LocaleList.forLanguageTags("ja-JP");
+        LocaleList differentLocale = p2.getTextLocales().equals(enUS) ? jaJP : enUS;
+        p1.setTextLocales(differentLocale);
+        assertFalse(p1.equalsForTextMeasurement(p2));
+        p1.setTextLocales(p2.getTextLocales());
+        assertTrue(p1.equalsForTextMeasurement(p2));
+    }
+
+    @Test
+    public void testEqualsForTextMeasurment_typeface() {
+        Paint p1 = new Paint();
+        Paint p2 = new Paint();
+
+        p1.setTypeface(Typeface.DEFAULT);
+        p2.setTypeface(Typeface.SERIF);
+        assertFalse(p1.equalsForTextMeasurement(p2));
+        p1.setTypeface(p2.getTypeface());
+        assertTrue(p1.equalsForTextMeasurement(p2));
+    }
 }
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedImageDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedImageDrawableTest.java
index 43aceb9..537b774 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedImageDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedImageDrawableTest.java
@@ -20,7 +20,6 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
@@ -29,17 +28,24 @@
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
 import android.graphics.ImageDecoder;
+import android.graphics.LightingColorFilter;
+import android.graphics.Paint;
 import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.cts.R;
 import android.graphics.drawable.AnimatedImageDrawable;
 import android.graphics.drawable.Drawable;
-import android.graphics.cts.R;
 import android.net.Uri;
 import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
 import android.widget.ImageView;
 
+import com.android.compatibility.common.util.BitmapUtils;
+
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -48,6 +54,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
+import java.util.function.BiFunction;
 
 @RunWith(AndroidJUnit4.class)
 public class AnimatedImageDrawableTest {
@@ -83,6 +90,11 @@
         mActivity = mActivityRule.getActivity();
     }
 
+    @Test
+    public void testEmptyConstructor() {
+        new AnimatedImageDrawable();
+    }
+
     private AnimatedImageDrawable createFromImageDecoder(int resId) {
         Uri uri = null;
         try {
@@ -333,12 +345,15 @@
     public void testLoopCounts() throws Throwable {
         for (int loopCount : new int[] { 3, 5, 7, 16 }) {
             AnimatedImageDrawable drawable = createFromImageDecoder(RES_ID);
+            assertEquals(AnimatedImageDrawable.LOOP_INFINITE, drawable.getLoopCount());
+
             Callback cb = new Callback(drawable);
             mActivityRule.runOnUiThread(() -> {
                 setContentView(drawable);
 
                 drawable.registerAnimationCallback(cb);
                 drawable.setLoopCount(loopCount);
+                assertEquals(loopCount, drawable.getLoopCount());
                 drawable.start();
             });
 
@@ -348,6 +363,9 @@
 
             cb.waitForEnd(DURATION * 2);
             cb.assertEnded(true);
+
+            drawable.setLoopCount(AnimatedImageDrawable.LOOP_INFINITE);
+            assertEquals(AnimatedImageDrawable.LOOP_INFINITE, drawable.getLoopCount());
         }
     }
 
@@ -377,6 +395,104 @@
     }
 
     @Test
+    public void testColorFilter() {
+        AnimatedImageDrawable drawable = createFromImageDecoder(RES_ID);
+
+        ColorFilter filter = new LightingColorFilter(0, Color.RED);
+        drawable.setColorFilter(filter);
+        assertEquals(filter, drawable.getColorFilter());
+
+        Bitmap actual = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
+                drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
+        {
+            Canvas canvas = new Canvas(actual);
+            drawable.draw(canvas);
+        }
+
+        for (int i = 0; i < actual.getWidth(); ++i) {
+            for (int j = 0; j < actual.getHeight(); ++j) {
+                int color = actual.getPixel(i, j);
+                // The LightingColorFilter does not affect the transparent pixels,
+                // so all pixels should either remain transparent or turn red.
+                if (color != Color.RED && color != Color.TRANSPARENT) {
+                    fail("pixel at " + i + ", " + j + " does not match expected. "
+                            + "expected: " + Color.RED + " OR " + Color.TRANSPARENT
+                            + " actual: " + color);
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testPostProcess() {
+        // Compare post processing a Rect in the middle of the (not-animating)
+        // image with drawing manually. They should be exactly the same.
+        BiFunction<Integer, Integer, Rect> rectCreator = (width, height) -> {
+            int quarterWidth  = width  / 4;
+            int quarterHeight = height / 4;
+            return new Rect(quarterWidth, quarterHeight,
+                    3 * quarterWidth, 3 * quarterHeight);
+        };
+
+        AnimatedImageDrawable drawable = createFromImageDecoder(RES_ID);
+        Bitmap expected = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
+                drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
+
+        Paint paint = new Paint();
+        paint.setColor(Color.RED);
+
+        {
+            Rect r = rectCreator.apply(drawable.getIntrinsicWidth(),
+                                       drawable.getIntrinsicHeight());
+            Canvas canvas = new Canvas(expected);
+            drawable.draw(canvas);
+
+            for (int i = r.left; i < r.right; ++i) {
+                for (int j = r.top; j < r.bottom; ++j) {
+                    assertNotEquals(Color.RED, expected.getPixel(i, j));
+                }
+            }
+
+            canvas.drawRect(r, paint);
+
+            for (int i = r.left; i < r.right; ++i) {
+                for (int j = r.top; j < r.bottom; ++j) {
+                    assertEquals(Color.RED, expected.getPixel(i, j));
+                }
+            }
+        }
+
+
+        AnimatedImageDrawable testDrawable = null;
+        Uri uri = null;
+        try {
+            uri = getAsResourceUri(RES_ID);
+            ImageDecoder.Source source = ImageDecoder.createSource(mContentResolver, uri);
+            Drawable dr = ImageDecoder.decodeDrawable(source, (decoder, info, src) -> {
+                decoder.setPostProcessor((canvas) -> {
+                    canvas.drawRect(rectCreator.apply(canvas.getWidth(),
+                                                      canvas.getHeight()), paint);
+                    return PixelFormat.TRANSLUCENT;
+                });
+            });
+            assertTrue(dr instanceof AnimatedImageDrawable);
+            testDrawable = (AnimatedImageDrawable) dr;
+        } catch (IOException e) {
+            fail("failed to create image from " + uri);
+        }
+
+        Bitmap actual = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
+                drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
+
+        {
+            Canvas canvas = new Canvas(actual);
+            testDrawable.draw(canvas);
+        }
+
+        BitmapUtils.compareBitmaps(expected, actual);
+    }
+
+    @Test
     public void testCreateFromXml() throws XmlPullParserException, IOException {
         XmlPullParser parser = mRes.getXml(R.drawable.animatedimagedrawable_tag);
         Drawable drawable = Drawable.createFromXml(mRes, parser);
@@ -399,4 +515,37 @@
         assertNotNull(drawable);
         assertTrue(drawable instanceof AnimatedImageDrawable);
     }
+
+    @Test(expected=XmlPullParserException.class)
+    public void testMissingSrcInflate() throws XmlPullParserException, IOException  {
+        XmlPullParser parser = mRes.getXml(R.drawable.animatedimagedrawable_nosrc);
+        Drawable drawable = Drawable.createFromXml(mRes, parser);
+    }
+
+    @Test
+    public void testAutoMirrored() {
+        AnimatedImageDrawable drawable = createFromImageDecoder(RES_ID);
+        assertFalse(drawable.isAutoMirrored());
+
+        drawable.setAutoMirrored(true);
+        assertTrue(drawable.isAutoMirrored());
+
+        drawable.setAutoMirrored(false);
+        assertFalse(drawable.isAutoMirrored());
+    }
+
+    @Test
+    public void testAutoMirroredFromXml() throws XmlPullParserException, IOException {
+        XmlPullParser parser = mRes.getXml(R.drawable.animatedimagedrawable_tag);
+        Drawable drawable = Drawable.createFromXml(mRes, parser);
+        assertNotNull(drawable);
+        assertTrue(drawable instanceof AnimatedImageDrawable);
+        assertFalse(drawable.isAutoMirrored());
+
+        parser = mRes.getXml(R.drawable.animatedimagedrawable_automirrored);
+        drawable = Drawable.createFromXml(mRes, parser);
+        assertNotNull(drawable);
+        assertTrue(drawable instanceof AnimatedImageDrawable);
+        assertTrue(drawable.isAutoMirrored());
+    }
 }
diff --git a/tests/tests/hardware/Android.mk b/tests/tests/hardware/Android.mk
index 3b6a0d1..4e8aaa7 100644
--- a/tests/tests/hardware/Android.mk
+++ b/tests/tests/hardware/Android.mk
@@ -41,6 +41,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsHardwareTestCases
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_CTS_PACKAGE)
 
diff --git a/tests/tests/keystore/Android.mk b/tests/tests/keystore/Android.mk
index 51c5d41..c741a04 100644
--- a/tests/tests/keystore/Android.mk
+++ b/tests/tests/keystore/Android.mk
@@ -48,6 +48,7 @@
 #
 # Uncomment when b/13282254 is fixed.
 # LOCAL_SDK_VERSION := current
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_JAVA_LIBRARIES += android.test.runner.stubs
 LOCAL_JAVA_LIBRARIES += android.test.base.stubs
 
diff --git a/tests/tests/libcorefileio/Android.mk b/tests/tests/libcorefileio/Android.mk
index 9d4345b..c56a3b7 100644
--- a/tests/tests/libcorefileio/Android.mk
+++ b/tests/tests/libcorefileio/Android.mk
@@ -28,6 +28,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsLibcoreFileIOTestCases
+LOCAL_SDK_VERSION := current
 
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
diff --git a/tests/tests/location2/Android.mk b/tests/tests/location2/Android.mk
index 326923f..d8b1ce4 100644
--- a/tests/tests/location2/Android.mk
+++ b/tests/tests/location2/Android.mk
@@ -33,6 +33,7 @@
 LOCAL_PACKAGE_NAME := CtsLocation2TestCases
 
 # uncomment when Location.EXTRA_NO_GPS_LOCATION is removed
-#LOCAL_SDK_VERSION := curren
+#LOCAL_SDK_VERSION := current
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/media/Android.mk b/tests/tests/media/Android.mk
index 0aab327..2491d44 100644
--- a/tests/tests/media/Android.mk
+++ b/tests/tests/media/Android.mk
@@ -72,6 +72,7 @@
 
 # This test uses private APIs
 #LOCAL_SDK_VERSION := current
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_JAVA_LIBRARIES += \
     org.apache.http.legacy \
diff --git a/tests/tests/media/src/android/media/cts/AudioManagerTest.java b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
index 5174db0..59e2361 100644
--- a/tests/tests/media/src/android/media/cts/AudioManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
@@ -787,6 +787,13 @@
         }
     }
 
+    public void testSetVoiceCallVolumeToZeroPermission() {
+        // Verify that only apps with MODIFY_PHONE_STATE can set VOICE_CALL_STREAM to 0
+        mAudioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, 0, 0);
+        assertTrue("MODIFY_PHONE_STATE is required in order to set voice call volume to 0",
+                    mAudioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL) != 0);
+    }
+
     public void testMuteFixedVolume() throws Exception {
         int[] streams = {
                 AudioManager.STREAM_VOICE_CALL,
diff --git a/tests/tests/media/src/android/media/cts/AudioRecordTest.java b/tests/tests/media/src/android/media/cts/AudioRecordTest.java
index 939d7ec..63b3356 100644
--- a/tests/tests/media/src/android/media/cts/AudioRecordTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioRecordTest.java
@@ -39,6 +39,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.testng.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
@@ -804,6 +805,34 @@
         }
     }
 
+    @Test
+    public void testVoiceCallAudioSourcePermissions() throws Exception {
+        if (!hasMicrophone()) {
+            return;
+        }
+
+        // Make sure that VOICE_CALL, VOICE_DOWNLINK and VOICE_UPLINK audio sources cannot
+        // be used by apps that don't have the CAPTURE_AUDIO_OUTPUT permissions
+        final int[] voiceCallAudioSources = new int [] {MediaRecorder.AudioSource.VOICE_CALL,
+            MediaRecorder.AudioSource.VOICE_DOWNLINK,
+            MediaRecorder.AudioSource.VOICE_UPLINK};
+
+        for (int source : voiceCallAudioSources) {
+            // AudioRecord.Builder should fail when trying to use
+            // one of the voice call audio sources.
+            assertThrows(UnsupportedOperationException.class,
+                            () -> {
+                                new AudioRecord.Builder()
+                                 .setAudioSource(source)
+                                 .setAudioFormat(new AudioFormat.Builder()
+                                         .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
+                                         .setSampleRate(8000)
+                                         .setChannelMask(AudioFormat.CHANNEL_IN_MONO)
+                                         .build())
+                                 .build(); });
+        }
+    }
+
     private void printMicrophoneInfo(MicrophoneInfo microphone) {
         Log.i(TAG, "deviceId:" + microphone.getDescription());
         Log.i(TAG, "portId:" + microphone.getId());
diff --git a/tests/tests/media/src/android/media/cts/RoutingTest.java b/tests/tests/media/src/android/media/cts/RoutingTest.java
index ddb534a..2afad1e 100644
--- a/tests/tests/media/src/android/media/cts/RoutingTest.java
+++ b/tests/tests/media/src/android/media/cts/RoutingTest.java
@@ -136,6 +136,66 @@
         audioTrack.release();
     }
 
+    public void test_audioTrack_incallMusicRoutingPermissions() {
+        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT)) {
+            // Can't do it so skip this test
+            return;
+        }
+
+        // only apps with MODIFY_PHONE_STATE permission can route playback
+        // to the uplink stream during a phone call, so this test makes sure that
+        // audio is re-routed to default device when the permission is missing
+
+        AudioDeviceInfo telephonyDevice = getTelephonyDeviceAndSetInCommunicationMode();
+        if (telephonyDevice == null) {
+            // Can't do it so skip this test
+            return;
+        }
+
+        AudioTrack audioTrack = null;
+
+        try {
+            audioTrack = allocAudioTrack();
+            assertNotNull(audioTrack);
+
+            audioTrack.setPreferredDevice(telephonyDevice);
+            assertEquals(AudioDeviceInfo.TYPE_TELEPHONY, audioTrack.getPreferredDevice().getType());
+
+            audioTrack.play();
+            assertTrue(audioTrack.getRoutedDevice().getType() != AudioDeviceInfo.TYPE_TELEPHONY);
+
+        } finally {
+            if (audioTrack != null) {
+                audioTrack.stop();
+                audioTrack.release();
+            }
+            mAudioManager.setMode(AudioManager.MODE_NORMAL);
+        }
+    }
+
+    private AudioDeviceInfo getTelephonyDeviceAndSetInCommunicationMode() {
+        // get the output device for telephony
+        AudioDeviceInfo telephonyDevice = null;
+        AudioDeviceInfo[] deviceList = mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
+        for (int index = 0; index < deviceList.length; index++) {
+            if (deviceList[index].getType() == AudioDeviceInfo.TYPE_TELEPHONY) {
+                telephonyDevice = deviceList[index];
+            }
+        }
+
+        if (telephonyDevice == null) {
+            return null;
+        }
+
+        // simulate an in call state using MODE_IN_COMMUNICATION since
+        // AudioManager.setMode requires MODIFY_PHONE_STATE permission
+        // for setMode with MODE_IN_CALL.
+        mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
+        assertEquals(AudioManager.MODE_IN_COMMUNICATION, mAudioManager.getMode());
+
+        return telephonyDevice;
+    }
+
     /*
      * tests if the Looper for the current thread has been prepared,
      * If not, it makes one, prepares it and returns it.
@@ -634,6 +694,43 @@
         mediaPlayer.release();
     }
 
+    public void test_mediaPlayer_incallMusicRoutingPermissions() {
+        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT)) {
+            // Can't do it so skip this test
+            return;
+        }
+
+        // only apps with MODIFY_PHONE_STATE permission can route playback
+        // to the uplink stream during a phone call, so this test makes sure that
+        // audio is re-routed to default device when the permission is missing
+
+        AudioDeviceInfo telephonyDevice = getTelephonyDeviceAndSetInCommunicationMode();
+        if (telephonyDevice == null) {
+            // Can't do it so skip this test
+            return;
+        }
+
+        MediaPlayer mediaPlayer = null;
+
+        try {
+            mediaPlayer = allocMediaPlayer();
+
+            mediaPlayer.setPreferredDevice(telephonyDevice);
+            assertEquals(AudioDeviceInfo.TYPE_TELEPHONY, mediaPlayer.getPreferredDevice().getType());
+
+            // Sleep for 1s to ensure the output device open
+            SystemClock.sleep(1000);
+            assertTrue(mediaPlayer.getRoutedDevice().getType() != AudioDeviceInfo.TYPE_TELEPHONY);
+
+        } finally {
+            if (mediaPlayer != null) {
+                mediaPlayer.stop();
+                mediaPlayer.release();
+            }
+            mAudioManager.setMode(AudioManager.MODE_NORMAL);
+        }
+    }
+
     private MediaRecorder allocMediaRecorder() throws Exception {
         final String outputPath = new File(Environment.getExternalStorageDirectory(),
             "record.out").getAbsolutePath();
diff --git a/tests/tests/net/Android.mk b/tests/tests/net/Android.mk
index e348406..e67bb8f 100644
--- a/tests/tests/net/Android.mk
+++ b/tests/tests/net/Android.mk
@@ -49,6 +49,7 @@
 
 # uncomment when b/13249961 is fixed
 #LOCAL_SDK_VERSION := current
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
diff --git a/tests/tests/os/Android.mk b/tests/tests/os/Android.mk
index 274bc06..9cd0b87 100644
--- a/tests/tests/os/Android.mk
+++ b/tests/tests/os/Android.mk
@@ -49,6 +49,7 @@
 
 # uncomment when b/13282254 is fixed
 #LOCAL_SDK_VERSION := current
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_JAVA_LIBRARIES += android.test.runner.stubs
 LOCAL_JAVA_LIBRARIES += android.test.base.stubs
 
diff --git a/tests/tests/permission/Android.mk b/tests/tests/permission/Android.mk
index 171283e..1a4eec6 100644
--- a/tests/tests/permission/Android.mk
+++ b/tests/tests/permission/Android.mk
@@ -43,6 +43,7 @@
 
 # uncomment when b/13249777 is fixed
 #LOCAL_SDK_VERSION := current
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_JAVA_LIBRARIES += android.test.runner.stubs
 LOCAL_JAVA_LIBRARIES += android.test.base.stubs
 
diff --git a/tests/tests/permission/src/android/permission/cts/AppOpsTest.java b/tests/tests/permission/src/android/permission/cts/AppOpsTest.java
index 970ada7..7285fd0 100644
--- a/tests/tests/permission/src/android/permission/cts/AppOpsTest.java
+++ b/tests/tests/permission/src/android/permission/cts/AppOpsTest.java
@@ -27,8 +27,14 @@
 import static com.android.compatibility.common.util.AppOpsUtils.rejectedOperationLogged;
 import static com.android.compatibility.common.util.AppOpsUtils.setOpMode;
 
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
 import android.Manifest.permission;
 import android.app.AppOpsManager;
+import android.app.AppOpsManager.OnOpChangedListener;
 import android.content.Context;
 import android.os.Process;
 import android.test.InstrumentationTestCase;
@@ -159,12 +165,12 @@
         }
     }
 
-    public void testCheckPackagePassesTest() throws Exception {
+    public void testCheckPackagePassesCheck() throws Exception {
         mAppOps.checkPackage(mMyUid, mOpPackageName);
         mAppOps.checkPackage(Process.SYSTEM_UID, "android");
     }
 
-    public void testCheckPackageDoesntPassTest() throws Exception {
+    public void testCheckPackageDoesntPassCheck() throws Exception {
         try {
             // Package name doesn't match UID.
             mAppOps.checkPackage(Process.SYSTEM_UID, mOpPackageName);
@@ -187,6 +193,41 @@
         }
     }
 
+    public void testWatchingMode() throws Exception {
+        OnOpChangedListener watcher = mock(OnOpChangedListener.class);
+        try {
+            setOpMode(mOpPackageName, OPSTR_READ_SMS, MODE_ALLOWED);
+
+            mAppOps.startWatchingMode(OPSTR_READ_SMS, mOpPackageName, watcher);
+
+            // Make a change to the app op's mode.
+            reset(watcher);
+            setOpMode(mOpPackageName, OPSTR_READ_SMS, MODE_ERRORED);
+            verify(watcher).onOpChanged(OPSTR_READ_SMS, mOpPackageName);
+
+            // Make another change to the app op's mode.
+            reset(watcher);
+            setOpMode(mOpPackageName, OPSTR_READ_SMS, MODE_ALLOWED);
+            verify(watcher).onOpChanged(OPSTR_READ_SMS, mOpPackageName);
+
+            // Set mode to the same value as before - expect no call to the listener.
+            reset(watcher);
+            setOpMode(mOpPackageName, OPSTR_READ_SMS, MODE_ALLOWED);
+            verifyZeroInteractions(watcher);
+
+            mAppOps.stopWatchingMode(watcher);
+
+            // Make a change to the app op's mode. Since we already stopped watching the mode, the
+            // listener shouldn't be called.
+            reset(watcher);
+            setOpMode(mOpPackageName, OPSTR_READ_SMS, MODE_ERRORED);
+            verifyZeroInteractions(watcher);
+        } finally {
+            // Clean up registered watcher.
+            mAppOps.stopWatchingMode(watcher);
+        }
+    }
+
     @SmallTest
     public void testAllOpsHaveOpString() {
         Set<String> opStrs = new HashSet<>();
diff --git a/tests/tests/permission2/Android.mk b/tests/tests/permission2/Android.mk
index d1190a3..3df1bc9 100755
--- a/tests/tests/permission2/Android.mk
+++ b/tests/tests/permission2/Android.mk
@@ -24,7 +24,7 @@
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
-LOCAL_JAVA_LIBRARIES := telephony-common android.test.base.stubs
+LOCAL_JAVA_LIBRARIES := android.test.base.stubs
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
 	compatibility-device-util \
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index 8bf4467..7cf9971 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -53,6 +53,7 @@
     <protected-broadcast android:name="android.intent.action.UID_REMOVED" />
     <protected-broadcast android:name="android.intent.action.QUERY_PACKAGE_RESTART" />
     <protected-broadcast android:name="android.intent.action.CONFIGURATION_CHANGED" />
+    <protected-broadcast android:name="android.intent.action.SPLIT_CONFIGURATION_CHANGED" />
     <protected-broadcast android:name="android.intent.action.LOCALE_CHANGED" />
     <protected-broadcast android:name="android.intent.action.BATTERY_CHANGED" />
     <protected-broadcast android:name="android.intent.action.BATTERY_LOW" />
@@ -159,6 +160,8 @@
     <protected-broadcast
         android:name="android.bluetooth.headset.action.HF_INDICATORS_VALUE_CHANGED" />
     <protected-broadcast
+        android:name="android.bluetooth.headset.profile.action.ACTIVE_DEVICE_CHANGED" />
+    <protected-broadcast
         android:name="android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
         android:name="android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED" />
@@ -171,8 +174,14 @@
     <protected-broadcast
         android:name="android.bluetooth.headsetclient.profile.action.LAST_VTAG" />
     <protected-broadcast
+        android:name="android.bluetooth.hearingaid.profile.action.CONNECTION_STATE_CHANGED" />
+    <protected-broadcast
+        android:name="android.bluetooth.hearingaid.profile.action.PLAYING_STATE_CHANGED" />
+    <protected-broadcast
         android:name="android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
+        android:name="android.bluetooth.a2dp.profile.action.ACTIVE_DEVICE_CHANGED" />
+    <protected-broadcast
         android:name="android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED" />
     <protected-broadcast
         android:name="android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED" />
@@ -319,10 +328,15 @@
     <protected-broadcast android:name="com.android.server.usb.ACTION_OPEN_IN_APPS" />
     <protected-broadcast android:name="com.android.server.am.DELETE_DUMPHEAP" />
     <protected-broadcast android:name="com.android.server.net.action.SNOOZE_WARNING" />
+    <protected-broadcast android:name="com.android.server.net.action.SNOOZE_RAPID" />
     <protected-broadcast android:name="com.android.server.wifi.ConnectToNetworkNotification.USER_DISMISSED_NOTIFICATION" />
     <protected-broadcast android:name="com.android.server.wifi.ConnectToNetworkNotification.CONNECT_TO_NETWORK" />
     <protected-broadcast android:name="com.android.server.wifi.ConnectToNetworkNotification.PICK_WIFI_NETWORK" />
     <protected-broadcast android:name="com.android.server.wifi.ConnectToNetworkNotification.PICK_NETWORK_AFTER_FAILURE" />
+    <protected-broadcast android:name="com.android.server.wifi.wakeup.DISMISS_NOTIFICATION" />
+    <protected-broadcast android:name="com.android.server.wifi.wakeup.OPEN_WIFI_PREFERENCES" />
+    <protected-broadcast android:name="com.android.server.wifi.wakeup.OPEN_WIFI_SETTINGS" />
+    <protected-broadcast android:name="com.android.server.wifi.wakeup.TURN_OFF_WIFI_WAKE" />
     <protected-broadcast android:name="android.net.wifi.WIFI_STATE_CHANGED" />
     <protected-broadcast android:name="android.net.wifi.WIFI_AP_STATE_CHANGED" />
     <protected-broadcast android:name="android.net.wifi.WIFI_CREDENTIAL_CHANGED" />
@@ -506,6 +520,7 @@
     <protected-broadcast android:name="android.os.action.ACTION_EFFECTS_SUPPRESSOR_CHANGED" />
     <protected-broadcast android:name="android.app.action.NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED" />
     <protected-broadcast android:name="android.app.action.NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED" />
+    <protected-broadcast android:name="android.app.action.APP_BLOCK_STATE_CHANGED" />
 
     <protected-broadcast android:name="android.permission.GET_APP_GRANTED_URI_PERMISSIONS" />
     <protected-broadcast android:name="android.permission.CLEAR_APP_GRANTED_URI_PERMISSIONS" />
@@ -550,8 +565,6 @@
     <protected-broadcast android:name="android.intent.action.DEVICE_LOCKED_CHANGED" />
 
     <!-- Added in O -->
-    <!-- TODO: temporary broadcast used by AutoFillManagerServiceImpl; will be removed -->
-    <protected-broadcast android:name="com.android.internal.autofill.action.REQUEST_AUTOFILL" />
     <protected-broadcast android:name="android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED" />
     <protected-broadcast android:name="com.android.server.wm.ACTION_REVOKE_SYSTEM_ALERT_WINDOW_PERMISSION" />
     <protected-broadcast android:name="android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED" />
@@ -564,8 +577,20 @@
     <protected-broadcast android:name="android.media.tv.action.CHANNEL_BROWSABLE_REQUESTED" />
     <protected-broadcast android:name="com.android.server.InputMethodManagerService.SHOW_INPUT_METHOD_PICKER" />
 
+    <!-- Time zone rules update intents fired by the system server -->
+    <protected-broadcast android:name="com.android.intent.action.timezone.RULES_UPDATE_OPERATION" />
+    <protected-broadcast android:name="com.android.intent.action.timezone.TRIGGER_RULES_UPDATE_CHECK" />
+
     <!-- Made protected in P (was introduced in JB-MR2) -->
     <protected-broadcast android:name="android.intent.action.GET_RESTRICTION_ENTRIES" />
+    <protected-broadcast android:name="android.telephony.euicc.action.OTA_STATUS_CHANGED" />
+
+    <!-- Added in P -->
+    <protected-broadcast android:name="android.app.action.PROFILE_OWNER_CHANGED" />
+    <protected-broadcast android:name="android.app.action.TRANSFER_OWNERSHIP_COMPLETE" />
+    <protected-broadcast android:name="android.app.action.AFFILIATED_PROFILE_TRANSFER_OWNERSHIP_COMPLETE" />
+    <protected-broadcast android:name="android.app.action.DATA_SHARING_RESTRICTION_CHANGED" />
+    <protected-broadcast android:name="android.app.action.STATSD_STARTED" />
 
     <!-- ====================================================================== -->
     <!--                          RUNTIME PERMISSIONS                           -->
@@ -957,6 +982,23 @@
                 android:description="@string/permdesc_manageOwnCalls"
                 android:protectionLevel="normal" />
 
+    <!-- Allows a calling app to continue a call which was started in another app.  An example is a
+         video calling app that wants to continue a voice call on the user's mobile network.<p>
+         When the handover of a call from one app to another takes place, there are two devices
+         which are involved in the handover; the initiating and receiving devices.  The initiating
+         device is where the request to handover the call was started, and the receiving device is
+         where the handover request is confirmed by the other party.<p>
+         This permission protects access to the
+         {@link android.telecom.TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} which
+         the receiving side of the handover uses to accept a handover.
+         <p>Protection level: dangerous
+    -->
+    <permission android:name="android.permission.ACCEPT_HANDOVER"
+                android:permissionGroup="android.permission-group.PHONE"
+                android.label="@string/permlab_acceptHandover"
+                android:description="@string/permdesc_acceptHandovers"
+                android:protectionLevel="dangerous" />
+
     <!-- ====================================================================== -->
     <!-- Permissions for accessing the device microphone                        -->
     <!-- ====================================================================== -->
@@ -1378,6 +1420,12 @@
     <permission android:name="android.permission.MANAGE_LOWPAN_INTERFACES"
         android:protectionLevel="signature|privileged" />
 
+    <!-- @hide Allows internal management of Wi-Fi connectivity state when on
+         permission review mode.
+         <p>Not for use by third-party applications. -->
+    <permission android:name="android.permission.MANAGE_WIFI_WHEN_PERMISSION_REVIEW_REQUIRED"
+        android:protectionLevel="signature" />
+
     <!-- ======================================= -->
     <!-- Permissions for short range, peripheral networks -->
     <!-- ======================================= -->
@@ -1425,6 +1473,12 @@
         android:label="@string/permlab_nfc"
         android:protectionLevel="normal" />
 
+    <!-- Allows applications to receive NFC transaction events.
+         <p>Protection level: normal
+    -->
+    <permission android:name="android.permission.NFC_TRANSACTION_EVENT"
+        android:protectionLevel="normal" />
+
     <!-- @SystemApi Allows an internal user to use privileged ConnectivityManager APIs.
          @hide -->
     <permission android:name="android.permission.CONNECTIVITY_INTERNAL"
@@ -1455,6 +1509,11 @@
     <permission android:name="android.permission.NFC_HANDOVER_STATUS"
         android:protectionLevel="signature|privileged" />
 
+    <!-- @hide Allows internal management of Bluetooth state when on permission review mode.
+         <p>Not for use by third-party applications. -->
+    <permission android:name="android.permission.MANAGE_BLUETOOTH_WHEN_PERMISSION_REVIEW_REQUIRED"
+        android:protectionLevel="signature" />
+
     <!-- ================================== -->
     <!-- Permissions for accessing accounts -->
     <!-- ================================== -->
@@ -1739,15 +1798,39 @@
     <permission android:name="android.permission.SEND_EMBMS_INTENTS"
         android:protectionLevel="signature|privileged" />
 
+
+    <!-- Allows internal management of the sensor framework
+         @hide -->
+    <permission android:name="android.permission.MANAGE_SENSORS"
+        android:protectionLevel="signature" />
+
     <!-- Must be required by an ImsService to ensure that only the
          system can bind to it.
-         <p>Protection level: signature|privileged
+         <p>Protection level: signature|privileged|vendorPrivileged
          @SystemApi
          @hide
     -->
     <permission android:name="android.permission.BIND_IMS_SERVICE"
         android:protectionLevel="signature|privileged|vendorPrivileged" />
 
+    <!-- Must be required by a telephony data service to ensure that only the
+         system can bind to it.
+         <p>Protection level: signature
+         @SystemApi
+         @hide
+    -->
+    <permission android:name="android.permission.BIND_TELEPHONY_DATA_SERVICE"
+        android:protectionLevel="signature" />
+
+    <!-- Must be required by a NetworkService to ensure that only the
+         system can bind to it.
+         <p>Protection level: signature
+         @SystemApi
+         @hide
+    -->
+    <permission android:name="android.permission.BIND_TELEPHONY_NETWORK_SERVICE"
+                android:protectionLevel="signature" />
+
     <!-- @SystemApi Allows an application to manage embedded subscriptions (those on a eUICC)
          through EuiccManager APIs.
          <p>Protection level: signature|privileged|development
@@ -2300,6 +2383,11 @@
     <permission android:name="android.permission.RECOVERY"
         android:protectionLevel="signature|privileged" />
 
+    <!-- @SystemApi Allows an application to read system update info.
+         @hide -->
+    <permission android:name="android.permission.READ_SYSTEM_UPDATE_INFO"
+        android:protectionLevel="signature" />
+
     <!-- Allows the system to bind to an application's task services
          @hide -->
     <permission android:name="android.permission.BIND_JOB_SERVICE"
@@ -2675,6 +2763,30 @@
     <permission android:name="android.permission.BIND_AUTOFILL_SERVICE"
         android:protectionLevel="signature" />
 
+   <!-- Alternative version of android.permission.BIND_AUTOFILL_FIELD_CLASSIFICATION_SERVICE.
+        This permission was renamed during the O previews but it was supported on the final O
+        release, so we need to carry it over.
+        <p>Protection level: signature
+        @hide
+    -->
+    <permission android:name="android.permission.BIND_AUTOFILL"
+        android:protectionLevel="signature" />
+
+    <!-- Must be required by an {@link android.service.autofill.AutofillFieldClassificationService}
+         to ensure that only the system can bind to it.
+         @hide This is not a third-party API (intended for OEMs and system apps).
+    -->
+    <permission android:name="android.permission.BIND_AUTOFILL_FIELD_CLASSIFICATION_SERVICE"
+                android:protectionLevel="signature" />
+
+    <!-- Must be required by a android.service.textclassifier.TextClassifierService,
+         to ensure that only the system can bind to it.
+         @SystemApi @hide This is not a third-party API (intended for OEMs and system apps).
+         <p>Protection level: signature
+    -->
+    <permission android:name="android.permission.BIND_TEXTCLASSIFIER_SERVICE"
+                android:protectionLevel="signature" />
+
     <!-- Must be required by hotword enrollment application,
          to ensure that only the system can interact with it.
          @hide <p>Not for use by third-party applications.</p> -->
@@ -2823,6 +2935,14 @@
     <permission android:name="android.permission.INSTALL_SELF_UPDATES"
         android:protectionLevel="signature|privileged" />
 
+    <!-- @SystemApi Allows an application to install updates. This is a limited version
+         of {@link android.Manifest.permission#INSTALL_PACKAGES}.
+        <p>Not for use by third-party applications.
+        @hide
+    -->
+    <permission android:name="android.permission.INSTALL_PACKAGE_UPDATES"
+        android:protectionLevel="signature|privileged" />
+
     <!-- @SystemApi Allows an application to clear user data.
          <p>Not for use by third-party applications
          @hide
@@ -2855,11 +2975,16 @@
     <permission android:name="android.permission.MANAGE_SCOPED_ACCESS_DIRECTORY_PERMISSIONS"
         android:protectionLevel="signature" />
 
-    <!-- @SystemApi Allows an application to delete cache files.
-    <p>Not for use by third-party applications. -->
+    <!-- @SystemApi Old permission for deleting an app's cache files, no longer used,
+         but signals for us to quietly ignore calls instead of throwing an exception. -->
     <permission android:name="android.permission.DELETE_CACHE_FILES"
         android:protectionLevel="signature|privileged" />
 
+    <!-- Allows an application to delete cache files.
+         @hide -->
+    <permission android:name="android.permission.INTERNAL_DELETE_CACHE_FILES"
+        android:protectionLevel="signature" />
+
     <!-- @SystemApi Allows an application to delete packages.
          <p>Not for use by third-party applications.
          <p>Starting in {@link android.os.Build.VERSION_CODES#N}, user confirmation is requested
@@ -2949,6 +3074,13 @@
     <permission android:name="android.permission.BRIGHTNESS_SLIDER_USAGE"
         android:protectionLevel="signature|privileged|development" />
 
+    <!-- Allows an application to collect ambient light stats.
+         <p>Not for use by third party applications.</p>
+         TODO: Make a system API
+         @hide -->
+    <permission android:name="android.permission.ACCESS_AMBIENT_LIGHT_STATS"
+        android:protectionLevel="signature|privileged|development" />
+
     <!-- Allows an application to modify the display brightness configuration
          @hide
          @SystemApi -->
@@ -3177,10 +3309,14 @@
     <permission android:name="android.permission.BIND_APPWIDGET"
         android:protectionLevel="signature|privileged" />
 
+    <!-- @hide Allows sysui to manage user grants of slice permissions. -->
+    <permission android:name="android.permission.MANAGE_SLICE_PERMISSIONS"
+        android:protectionLevel="signature" />
+
     <!-- Allows an application to bind app's slices and get their
          content. This content will be surfaced to the
          user and not to leave the device.
-         <p>Not for use by third-party applications. -->
+         <p>Not for use by third-party applications.-->
     <permission android:name="android.permission.BIND_SLICE"
         android:protectionLevel="signature|privileged|development" />
 
@@ -3674,20 +3810,41 @@
     <permission android:name="android.permission.INSTANT_APP_FOREGROUND_SERVICE"
         android:protectionLevel="signature|development|instant|appop" />
 
-    <!-- @hide Allows system components to access all app shortcuts. -->
+    <!-- @SystemApi Allows to access all app shortcuts.
+         @hide -->
     <permission android:name="android.permission.ACCESS_SHORTCUTS"
-        android:protectionLevel="signature" />
+        android:protectionLevel="signature|textClassifier" />
+
+    <!-- @SystemApi Allows unlimited calls to shortcut mutation APIs.
+         @hide -->
+    <permission android:name="android.permission.UNLIMITED_SHORTCUTS_API_CALLS"
+        android:protectionLevel="signature|textClassifier" />
 
     <!-- @SystemApi Allows an application to read the runtime profiles of other apps.
          @hide <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.READ_RUNTIME_PROFILES"
                 android:protectionLevel="signature|privileged" />
 
+    <!-- @hide Allows audio policy management. -->
+    <permission android:name="android.permission.MANAGE_AUDIO_POLICY"
+        android:protectionLevel="signature" />
+
     <!-- @SystemApi Allows an application to turn on / off quiet mode.
          @hide <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.MODIFY_QUIET_MODE"
                 android:protectionLevel="signature|privileged" />
 
+    <!-- Allows internal management of the camera framework
+         @hide -->
+    <permission android:name="android.permission.MANAGE_CAMERA"
+        android:protectionLevel="signature" />
+
+    <!-- Allows an application to control remote animations. See
+         {@link ActivityOptions#makeRemoteAnimation}
+         @hide <p>Not for use by third-party applications. -->
+    <permission android:name="android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS"
+        android:protectionLevel="signature|privileged" />
+
     <application android:process="system"
                  android:persistent="true"
                  android:hasCode="false"
@@ -3736,6 +3893,7 @@
                 android:excludeFromRecents="true"
                 android:label="@string/user_owner_label"
                 android:exported="true"
+                android:visibleToInstantApps="true"
                 >
         </activity>
         <activity-alias android:name="com.android.internal.app.ForwardIntentToParent"
@@ -3881,6 +4039,14 @@
                   android:excludeFromRecents="true">
         </activity>
 
+        <activity android:name="com.android.internal.app.HarmfulAppWarningActivity"
+                  android:theme="@style/Theme.DeviceDefault.Light.Dialog.Alert"
+                  android:excludeFromRecents="true"
+                  android:process=":ui"
+                  android:label="@string/harmful_app_warning_title"
+                  android:exported="false">
+        </activity>
+
         <receiver android:name="com.android.server.BootReceiver"
                 android:systemUserOnly="true">
             <intent-filter android:priority="1000">
@@ -3960,6 +4126,14 @@
             </intent-filter>
         </receiver>
 
+        <receiver android:name="com.android.server.updates.CarrierIdInstallReceiver"
+                  android:permission="android.permission.UPDATE_CONFIG">
+            <intent-filter>
+                <action android:name="com.android.internal.intent.action.UPDATE_CARRIER_ID_DB" />
+                <data android:scheme="content" android:host="*" android:mimeType="*/*" />
+            </intent-filter>
+        </receiver>
+
         <receiver android:name="com.android.server.MasterClearReceiver"
             android:permission="android.permission.MASTER_CLEAR">
             <intent-filter
@@ -4048,6 +4222,16 @@
         <service android:name="com.android.server.display.BrightnessIdleJob"
                  android:permission="android.permission.BIND_JOB_SERVICE" >
         </service>
+
+        <service
+                android:name="com.android.server.autofill.AutofillCompatAccessibilityService"
+                android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
+                android:exported="true">
+            <meta-data
+                    android:name="android.accessibilityservice"
+                    android:resource="@xml/autofill_compat_accessibility_service" />
+        </service>
+
 </application>
 
 </manifest>
diff --git a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
index 68b0b84..4b8aedfc 100644
--- a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
+++ b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
@@ -117,10 +117,8 @@
             }
 
             // OEMs cannot change permission protection flags
-            final int expectedProtectionFlags = expectedPermission.protectionLevel
-                    & PermissionInfo.PROTECTION_MASK_FLAGS;
-            final int declaredProtectionFlags = declaredPermission.protectionLevel
-                    & PermissionInfo.PROTECTION_MASK_FLAGS;
+            final int expectedProtectionFlags = expectedPermission.getProtectionFlags();
+            final int declaredProtectionFlags = declaredPermission.getProtectionFlags();
             if (expectedProtectionFlags != declaredProtectionFlags) {
                 offendingList.add(
                         String.format(
@@ -262,6 +260,9 @@
                 case "setup": {
                     protectionLevel |= PermissionInfo.PROTECTION_FLAG_SETUP;
                 } break;
+                case "textClassifier": {
+                    protectionLevel |= PermissionInfo.PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER;
+                } break;
                 case "instant": {
                     protectionLevel |= PermissionInfo.PROTECTION_FLAG_INSTANT;
                 } break;
diff --git a/tests/tests/proto/Android.mk b/tests/tests/proto/Android.mk
index 37faee6..595df7c 100644
--- a/tests/tests/proto/Android.mk
+++ b/tests/tests/proto/Android.mk
@@ -33,6 +33,7 @@
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
 #LOCAL_SDK_VERSION := current
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_JAVA_LIBRARIES += android.test.runner.stubs
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
diff --git a/tests/tests/provider/Android.mk b/tests/tests/provider/Android.mk
index 648c9852..df178c7 100644
--- a/tests/tests/provider/Android.mk
+++ b/tests/tests/provider/Android.mk
@@ -42,5 +42,6 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsProviderTestCases
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/security/Android.mk b/tests/tests/security/Android.mk
index f9763e1..3368526 100644
--- a/tests/tests/security/Android.mk
+++ b/tests/tests/security/Android.mk
@@ -52,6 +52,7 @@
 LOCAL_PACKAGE_NAME := CtsSecurityTestCases
 
 #LOCAL_SDK_VERSION := current
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
diff --git a/tests/tests/security/jni/Android.mk b/tests/tests/security/jni/Android.mk
index 4fefdab..cddcd76 100644
--- a/tests/tests/security/jni/Android.mk
+++ b/tests/tests/security/jni/Android.mk
@@ -40,7 +40,15 @@
 		libc++ \
 		libpcre2 \
 		libpackagelistparser \
-
+		libpowermanager \
+		libbase \
+		libunwind \
+		libhardware \
+		libsync \
+		libcamera_metadata \
+		libspeexresampler \
+		liblzma \
+		libstagefright_foundation
 
 LOCAL_C_INCLUDES += ndk/sources/cpufeatures
 LOCAL_STATIC_LIBRARIES := cpufeatures
diff --git a/tests/tests/security/res/raw/bug_36592202.ogg b/tests/tests/security/res/raw/bug_36592202.ogg
new file mode 100755
index 0000000..868e630
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_36592202.ogg
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_38448381.mp4 b/tests/tests/security/res/raw/bug_38448381.mp4
new file mode 100755
index 0000000..831cc74
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_38448381.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_38487564.mp4 b/tests/tests/security/res/raw/bug_38487564.mp4
new file mode 100755
index 0000000..01984447
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_38487564.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_63121644.mp4 b/tests/tests/security/res/raw/bug_63121644.mp4
new file mode 100755
index 0000000..bf932ac8
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_63121644.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_65398821.mp4 b/tests/tests/security/res/raw/bug_65398821.mp4
new file mode 100755
index 0000000..bfc700d
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_65398821.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_65735716_avc.mp4 b/tests/tests/security/res/raw/bug_65735716_avc.mp4
new file mode 100755
index 0000000..39e2c2a
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_65735716_avc.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2016_6764.mp4 b/tests/tests/security/res/raw/cve_2016_6764.mp4
new file mode 100644
index 0000000..46c1214
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2016_6764.mp4
Binary files differ
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index 9a0ea06..6af1d56 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -51,6 +51,8 @@
 import java.io.InputStream;
 import java.net.URL;
 import java.nio.ByteBuffer;
+import java.io.FileOutputStream;
+import java.io.File;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.concurrent.locks.Condition;
@@ -281,6 +283,11 @@
      ***********************************************************/
 
     @SecurityTest
+    public void testStagefright_bug_38448381() throws Exception {
+        doStagefrightTest(R.raw.bug_38448381);
+    }
+
+    @SecurityTest
     public void testStagefright_bug_70897454() throws Exception {
         doStagefrightTestRawBlob(R.raw.b70897454_avc, "video/avc", 320, 420);
     }
@@ -296,6 +303,11 @@
     }
 
     @SecurityTest
+    public void testStagefright_bug_65735716() throws Exception {
+        doStagefrightTestRawBlob(R.raw.bug_65735716_avc, "video/avc", 320, 240);
+    }
+
+    @SecurityTest
     public void testStagefright_bug_65717533() throws Exception {
         doStagefrightTest(R.raw.bug_65717533_header_corrupt);
     }
@@ -311,11 +323,21 @@
     }
 
     @SecurityTest
+    public void testStagefright_bug_38487564() throws Exception {
+        doStagefrightTest(R.raw.bug_38487564, (4 * 60 * 1000));
+    }
+
+    @SecurityTest
     public void testStagefright_cve_2016_0842() throws Exception {
         doStagefrightTest(R.raw.cve_2016_0842);
     }
 
     @SecurityTest
+    public void testStagefright_bug_63121644() throws Exception {
+        doStagefrightTest(R.raw.bug_63121644);
+    }
+
+    @SecurityTest
     public void testStagefright_cve_2016_6712() throws Exception {
         doStagefrightTest(R.raw.cve_2016_6712);
     }
@@ -346,11 +368,66 @@
     }
 
     @SecurityTest
+    public void testStagefright_bug_65398821() throws Exception {
+        doStagefrightTest(R.raw.bug_65398821, ( 4 * 60 * 1000 ) );
+    }
+
+    @SecurityTest
     public void testStagefright_cve_2015_3869() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3869);
     }
 
     @SecurityTest
+    public void testStagefright_bug_36592202() throws Exception {
+        Resources resources = getInstrumentation().getContext().getResources();
+        AssetFileDescriptor fd = resources.openRawResourceFd(R.raw.bug_36592202);
+        int page_size = 25627;
+        byte [] blob = new byte[page_size];
+
+        // 127 bytes read and  25500 zeros constitute one Ogg page
+        FileInputStream fis = fd.createInputStream();
+        int numRead = fis.read(blob);
+        fis.close();
+
+        // Creating temp file
+        final File tempFile = File.createTempFile("poc_tmp", ".ogg", null);
+
+        try {
+            final FileOutputStream tempFos = new FileOutputStream(tempFile.getAbsolutePath());
+            int bytesWritten = 0;
+            // Repeat data till size is ~1 GB
+            for (int i = 0; i < 50000; i++) {
+                tempFos.write(blob);
+                bytesWritten += page_size;
+            }
+            tempFos.close();
+
+            final int fileSize = bytesWritten;
+            int timeout = (10 * 60 * 1000);
+
+            runWithTimeout(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        doStagefrightTestMediaCodec(tempFile.getAbsolutePath());
+                    } catch (Exception | AssertionError  e) {
+                        if (!tempFile.delete()) {
+                            Log.e(TAG, "Failed to delete temporary PoC file");
+                        }
+                        fail("Operation was not successful");
+                    }
+                }
+            }, timeout);
+        } catch (Exception e) {
+            fail("Failed to test b/36592202");
+        } finally {
+            if (!tempFile.delete()) {
+                Log.e(TAG, "Failed to delete temporary PoC file");
+            }
+        }
+    }
+
+    @SecurityTest
     public void testStagefright_bug_32322258() throws Exception {
         doStagefrightTest(R.raw.bug_32322258);
     }
@@ -449,6 +526,11 @@
      ***********************************************************/
 
     @SecurityTest
+    public void testStagefright_cve_2016_6764() throws Exception {
+        doStagefrightTest(R.raw.cve_2016_6764);
+    }
+
+    @SecurityTest
     public void testStagefright_cve_2017_13214() throws Exception {
         doStagefrightTest(R.raw.cve_2017_13214);
     }
diff --git a/tests/tests/selinux/selinuxTargetSdk25/Android.mk b/tests/tests/selinux/selinuxTargetSdk25/Android.mk
index b13e613..15ec6e2 100755
--- a/tests/tests/selinux/selinuxTargetSdk25/Android.mk
+++ b/tests/tests/selinux/selinuxTargetSdk25/Android.mk
@@ -22,9 +22,8 @@
 LOCAL_STATIC_JAVA_LIBRARIES := \
     ctstestrunner \
     compatibility-device-util \
-    legacy-android-test \
 
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs
+LOCAL_JAVA_LIBRARIES := android.test.base.stubs android.test.runner.stubs
 
 LOCAL_JNI_SHARED_LIBRARIES := \
     libc++ \
@@ -39,6 +38,7 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src common)
 LOCAL_PACKAGE_NAME := CtsSelinuxTargetSdk25TestCases
+LOCAL_SDK_VERSION := current
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 include $(BUILD_CTS_PACKAGE)
 
diff --git a/tests/tests/selinux/selinuxTargetSdk27/Android.mk b/tests/tests/selinux/selinuxTargetSdk27/Android.mk
index 6de5250..e0e493e 100755
--- a/tests/tests/selinux/selinuxTargetSdk27/Android.mk
+++ b/tests/tests/selinux/selinuxTargetSdk27/Android.mk
@@ -22,9 +22,8 @@
 LOCAL_STATIC_JAVA_LIBRARIES := \
     ctstestrunner \
     compatibility-device-util \
-    legacy-android-test \
 
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs
+LOCAL_JAVA_LIBRARIES := android.test.base.stubs android.test.runner.stubs
 
 LOCAL_JNI_SHARED_LIBRARIES := \
     libc++ \
@@ -39,6 +38,7 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src common)
 LOCAL_PACKAGE_NAME := CtsSelinuxTargetSdk27TestCases
+LOCAL_SDK_VERSION := current
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 include $(BUILD_CTS_PACKAGE)
 
diff --git a/tests/tests/selinux/selinuxTargetSdkCurrent/Android.mk b/tests/tests/selinux/selinuxTargetSdkCurrent/Android.mk
index 6c515f2..698d1ef 100755
--- a/tests/tests/selinux/selinuxTargetSdkCurrent/Android.mk
+++ b/tests/tests/selinux/selinuxTargetSdkCurrent/Android.mk
@@ -22,9 +22,8 @@
 LOCAL_STATIC_JAVA_LIBRARIES := \
     ctstestrunner \
     compatibility-device-util \
-    legacy-android-test \
 
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs
+LOCAL_JAVA_LIBRARIES := android.test.base.stubs android.test.runner.stubs
 
 LOCAL_JNI_SHARED_LIBRARIES := \
     libc++ \
@@ -39,6 +38,7 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src common)
 LOCAL_PACKAGE_NAME := CtsSelinuxTargetSdkCurrentTestCases
+LOCAL_SDK_VERSION := current
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 include $(BUILD_CTS_PACKAGE)
 
diff --git a/tests/tests/slice/Android.mk b/tests/tests/slice/Android.mk
index 4410b74..c56f74c 100644
--- a/tests/tests/slice/Android.mk
+++ b/tests/tests/slice/Android.mk
@@ -38,6 +38,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsSliceTestCases
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_CTS_PACKAGE)
 
diff --git a/tests/tests/speech/Android.mk b/tests/tests/speech/Android.mk
index 147b137..7fb9124 100755
--- a/tests/tests/speech/Android.mk
+++ b/tests/tests/speech/Android.mk
@@ -36,5 +36,6 @@
 
 # Needed for testing O API
 #LOCAL_SDK_VERSION := test_current
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/systemui/Android.mk b/tests/tests/systemui/Android.mk
index 4d96171..2c07248 100644
--- a/tests/tests/systemui/Android.mk
+++ b/tests/tests/systemui/Android.mk
@@ -34,5 +34,6 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsSystemUiTestCases
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/telecom/src/android/telecom/cts/CtsConnectionService.java b/tests/tests/telecom/src/android/telecom/cts/CtsConnectionService.java
index d93d431..c9e0c56 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CtsConnectionService.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CtsConnectionService.java
@@ -211,7 +211,6 @@
     }
 
     public static boolean waitForUnBinding() {
-        sServiceUnBoundLatch = TestUtils.waitForLock(sServiceUnBoundLatch);
-        return sServiceUnBoundLatch != null;
+        return TestUtils.waitForLatchCountDown(sServiceUnBoundLatch);
     }
 }
diff --git a/tests/tests/telecom/src/android/telecom/cts/CtsSelfManagedConnectionService.java b/tests/tests/telecom/src/android/telecom/cts/CtsSelfManagedConnectionService.java
index b057648..e6070ce 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CtsSelfManagedConnectionService.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CtsSelfManagedConnectionService.java
@@ -198,7 +198,7 @@
      *      timeout expired without the lock being released.
      */
     public boolean waitForUpdate(int lock) {
-        mLocks[lock] = waitForLock(mLocks[lock]);
+        mLocks[lock] = TestUtils.waitForLock(mLocks[lock]);
         return mLocks[lock] != null;
     }
 
@@ -207,31 +207,7 @@
      * @return {@code true} if binding happened within the time limit, or {@code false} otherwise.
      */
     public static boolean waitForBinding() {
-        sBindingLock = waitForLock(sBindingLock);
-        return sBindingLock != null;
-    }
-
-    /**
-     * Given a {@link CountDownLatch}, wait for the latch to reach zero for 5 seconds.  If the lock
-     * was released, return a new instance.  Otherwise, return null to indicate that the timeout
-     * expired without the lock being released.
-     *
-     * @param lock The lock to wait on.
-     * @return {@code true} if the lock was released, and {@code false} if it failed to be released.
-     */
-    private static CountDownLatch waitForLock(CountDownLatch lock) {
-        boolean success;
-        try {
-            success = lock.await(5000, TimeUnit.MILLISECONDS);
-        } catch (InterruptedException ie) {
-            return null;
-        }
-
-        if (success) {
-            return new CountDownLatch(1);
-        } else {
-            return null;
-        }
+        return TestUtils.waitForLatchCountDown(sBindingLock);
     }
 
     public TestUtils.InvokeCounter getOnCreateIncomingHandoverConnectionCounter() {
diff --git a/tests/tests/telecom/src/android/telecom/cts/TestUtils.java b/tests/tests/telecom/src/android/telecom/cts/TestUtils.java
index 3980f7f..31000de 100644
--- a/tests/tests/telecom/src/android/telecom/cts/TestUtils.java
+++ b/tests/tests/telecom/src/android/telecom/cts/TestUtils.java
@@ -255,17 +255,36 @@
         }
     }
 
-    public static CountDownLatch waitForLock(CountDownLatch lock) {
-        boolean success;
-        try {
-            if (lock == null) {
-                return null;
-            }
-            success = lock.await(5000, TimeUnit.MILLISECONDS);
-        } catch (InterruptedException ie) {
-            return null;
+    /**
+     * Waits for the {@link CountDownLatch} to count down to 0 and then returns without reseting
+     * the latch.
+     * @param lock the latch that the system will wait on.
+     * @return true if the latch was released successfully, false if the latch timed out before
+     * resetting.
+     */
+    public static boolean waitForLatchCountDown(CountDownLatch lock) {
+        if (lock == null) {
+            return false;
         }
 
+        boolean success;
+        try {
+            success = lock.await(5000, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException ie) {
+            return false;
+        }
+
+        return success;
+    }
+
+    /**
+     * Waits for the {@link CountDownLatch} to count down to 0 and then returns a new reset latch.
+     * @param lock The lock that will await a countDown to 0.
+     * @return a new reset {@link CountDownLatch} if the lock successfully counted down to 0 or
+     * null if the operation timed out.
+     */
+    public static CountDownLatch waitForLock(CountDownLatch lock) {
+        boolean success = waitForLatchCountDown(lock);
         if (success) {
             return new CountDownLatch(1);
         } else {
diff --git a/tests/tests/telephony/Android.mk b/tests/tests/telephony/Android.mk
index 4d6922b..f19dbb5 100644
--- a/tests/tests/telephony/Android.mk
+++ b/tests/tests/telephony/Android.mk
@@ -43,6 +43,7 @@
 
 # uncomment when b/13250611 is fixed
 #LOCAL_SDK_VERSION := current
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_JAVA_LIBRARIES += android.test.runner.stubs
 LOCAL_JAVA_LIBRARIES += android.test.base.stubs
 
diff --git a/tests/tests/telephony/src/android/telephony/cts/ServiceStateTest.java b/tests/tests/telephony/src/android/telephony/cts/ServiceStateTest.java
index 59a44ed..8b92826 100644
--- a/tests/tests/telephony/src/android/telephony/cts/ServiceStateTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/ServiceStateTest.java
@@ -23,6 +23,8 @@
     private static final String OPERATOR_ALPHA_LONG = "CtsOperatorLong";
     private static final String OPERATOR_ALPHA_SHORT = "CtsOp";
     private static final String OPERATOR_NUMERIC = "02871";
+    private static final int SYSTEM_ID = 123;
+    private static final int NETWORK_ID = 456;
 
     public void testServiceState() {
         ServiceState serviceState = new ServiceState();
@@ -53,6 +55,10 @@
         assertEquals(OPERATOR_ALPHA_SHORT, serviceState.getOperatorAlphaShort());
         assertEquals(OPERATOR_NUMERIC, serviceState.getOperatorNumeric());
 
+        serviceState.setSystemAndNetworkId(SYSTEM_ID, NETWORK_ID);
+        assertEquals(SYSTEM_ID, serviceState.getSystemId());
+        assertEquals(NETWORK_ID, serviceState.getNetworkId());
+
         assertTrue(serviceState.hashCode() > 0);
         assertNotNull(serviceState.toString());
 
diff --git a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadFlowTest.java b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadFlowTest.java
index 5089381..e6a97ed 100644
--- a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadFlowTest.java
+++ b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadFlowTest.java
@@ -21,6 +21,7 @@
 import android.os.Bundle;
 import android.telephony.MbmsDownloadSession;
 import android.telephony.cts.embmstestapp.CtsDownloadService;
+import android.telephony.mbms.DownloadRequest;
 import android.telephony.mbms.MbmsDownloadReceiver;
 
 import java.io.File;
@@ -29,14 +30,16 @@
 
 public class MbmsDownloadFlowTest extends MbmsDownloadTestBase {
     private File tempFileRootDir;
-    private String tempFileRootDirPath;
+    private DownloadRequest testDownloadRequest;
 
     @Override
     public void setUp() throws Exception {
         super.setUp();
+        testDownloadRequest = downloadRequestTemplate
+                .setAppIntent(new Intent(MbmsDownloadReceiverTest.APP_INTENT_ACTION))
+                .build();
         tempFileRootDir = new File(mContext.getFilesDir(), "CtsTestDir");
         tempFileRootDir.mkdir();
-        tempFileRootDirPath = tempFileRootDir.getCanonicalPath();
         mDownloadSession.setTempFileRootDirectory(tempFileRootDir);
     }
 
@@ -49,15 +52,15 @@
 
     public void testFileDownloadFlow() throws Exception {
         MbmsDownloadReceiverTest.AppIntentCapture captor =
-                new MbmsDownloadReceiverTest.AppIntentCapture(mContext, mCallbackHandler);
-        mDownloadSession.download(MbmsDownloadReceiverTest.TEST_DOWNLOAD_REQUEST);
+                new MbmsDownloadReceiverTest.AppIntentCapture(mContext, mHandler);
+        mDownloadSession.download(testDownloadRequest);
         mMiddlewareControl.actuallyStartDownloadFlow();
         Intent downloadDoneIntent = captor.getIntent();
 
         assertEquals(MbmsDownloadReceiverTest.APP_INTENT_ACTION, downloadDoneIntent.getAction());
         assertEquals(MbmsDownloadSession.RESULT_SUCCESSFUL,
                 downloadDoneIntent.getIntExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_RESULT, -1));
-        assertEquals(MbmsDownloadReceiverTest.TEST_DOWNLOAD_REQUEST,
+        assertEquals(testDownloadRequest,
                 downloadDoneIntent.getParcelableExtra(
                         MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_REQUEST));
         assertEquals(CtsDownloadService.FILE_INFO,
diff --git a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadReceiverTest.java b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadReceiverTest.java
index 0d88f13..8232271 100644
--- a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadReceiverTest.java
+++ b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadReceiverTest.java
@@ -47,9 +47,6 @@
 
     public static final String APP_INTENT_ACTION =
             "android.telephony.embms.cts.ACTION_TEST_DOWNLOAD_COMPLETE";
-    public static final DownloadRequest TEST_DOWNLOAD_REQUEST = DOWNLOAD_REQUEST_TEMPLATE
-            .setAppIntent(new Intent(APP_INTENT_ACTION))
-            .build();
 
     public static class AppIntentCapture {
         private final BlockingQueue<Intent> mReceivedIntent = new LinkedBlockingQueue<>();
@@ -82,10 +79,14 @@
     private MbmsDownloadReceiver mReceiver;
     private File tempFileRootDir;
     private String tempFileRootDirPath;
+    private DownloadRequest testDownloadRequest;
 
     @Override
     public void setUp() throws Exception {
         super.setUp();
+        testDownloadRequest = downloadRequestTemplate
+                .setAppIntent(new Intent(APP_INTENT_ACTION))
+                .build();
         mReceiver = new MbmsDownloadReceiver();
         IntentFilter filter = new IntentFilter();
         filter.addAction(VendorUtils.ACTION_DOWNLOAD_RESULT_INTERNAL);
@@ -140,9 +141,9 @@
         intentForReceiverTest.putExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_RESULT,
                 MbmsDownloadSession.RESULT_CANCELLED);
         intentForReceiverTest.putExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_REQUEST,
-                TEST_DOWNLOAD_REQUEST);
+                testDownloadRequest);
 
-        AppIntentCapture intentCaptor = new AppIntentCapture(mContext, mCallbackHandler);
+        AppIntentCapture intentCaptor = new AppIntentCapture(mContext, mHandler);
 
         sendBroadcastAndValidate(intentForReceiverTest, MbmsDownloadReceiver.RESULT_OK);
         Intent receivedIntent = intentCaptor.getIntent();
@@ -150,7 +151,7 @@
         assertEquals(MbmsDownloadSession.RESULT_CANCELLED,
                 receivedIntent.getIntExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_RESULT, -1));
 
-        assertEquals(TEST_DOWNLOAD_REQUEST,
+        assertEquals(testDownloadRequest,
                 receivedIntent.getParcelableExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_REQUEST));
     }
 
@@ -162,7 +163,7 @@
         intentForReceiverTest.putExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_RESULT,
                 MbmsDownloadSession.RESULT_SUCCESSFUL);
         intentForReceiverTest.putExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_REQUEST,
-                TEST_DOWNLOAD_REQUEST);
+                testDownloadRequest);
         intentForReceiverTest.putExtra(MbmsDownloadSession.EXTRA_MBMS_FILE_INFO,
                 CtsDownloadService.FILE_INFO);
         intentForReceiverTest.putExtra(VendorUtils.EXTRA_FINAL_URI,
@@ -230,7 +231,7 @@
                         receivedExtras.add(getResultExtras(true));
                         receivedCode.add(getResultCode());
                     }
-                }, mCallbackHandler, -1, null, null);
+                }, mHandler, -1, null, null);
 
         try {
             assertEquals(expectedCode,
diff --git a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadSessionTest.java b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadSessionTest.java
index 29e70bb..5e70828 100644
--- a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadSessionTest.java
+++ b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadSessionTest.java
@@ -33,7 +33,7 @@
     public void testDuplicateSession() throws Exception {
         try {
             MbmsDownloadSession failure = MbmsDownloadSession.create(
-                    mContext, mCallback, mCallbackHandler);
+                    mContext, mCallbackExecutor, mCallback);
             fail("Duplicate create should've thrown an exception");
         } catch (IllegalStateException e) {
             // Succeed
@@ -139,7 +139,7 @@
     }
 
     public void testResetDownloadKnowledge() throws Exception {
-        DownloadRequest request = DOWNLOAD_REQUEST_TEMPLATE.build();
+        DownloadRequest request = downloadRequestTemplate.build();
         mDownloadSession.resetDownloadKnowledge(request);
 
         List<Bundle> resetDownloadKnowledgeCalls =
@@ -150,7 +150,7 @@
     }
 
     public void testGetDownloadStatus() throws Exception {
-        DownloadRequest request = DOWNLOAD_REQUEST_TEMPLATE.build();
+        DownloadRequest request = downloadRequestTemplate.build();
         mDownloadSession.requestDownloadState(request, CtsDownloadService.FILE_INFO);
 
         List<Bundle> getDownloadStatusCalls =
@@ -163,7 +163,7 @@
     }
 
     public void testCancelDownload() throws Exception {
-        DownloadRequest request = DOWNLOAD_REQUEST_TEMPLATE.build();
+        DownloadRequest request = downloadRequestTemplate.build();
         mDownloadSession.cancelDownload(request);
 
         List<Bundle> cancelDownloadCalls =
@@ -174,7 +174,11 @@
     }
 
     public void testListPendingDownloads() throws Exception {
-        DownloadRequest request = DOWNLOAD_REQUEST_TEMPLATE.setAppIntent(new Intent()).build();
+        File tempFileRootDir = new File(mContext.getFilesDir(), "CtsTestDir");
+        tempFileRootDir.mkdir();
+        mDownloadSession.setTempFileRootDirectory(tempFileRootDir);
+
+        DownloadRequest request = downloadRequestTemplate.setAppIntent(new Intent()).build();
         mDownloadSession.download(request);
 
         List<DownloadRequest> downloads = mDownloadSession.listPendingDownloads();
@@ -194,14 +198,12 @@
         assertNotSame(mDownloadSession.getTempFileRootDirectory(), tempFileDirName);
     }
 
-    public void testDownloadRequestOpacity() throws Exception {
+    public void testDownloadRequestSerialization() throws Exception {
         Intent intent = new Intent("sample_intent_action");
-        DownloadRequest request = DOWNLOAD_REQUEST_TEMPLATE.setAppIntent(intent).build();
-        DownloadRequest newRequest = new DownloadRequest.Builder(request.getSourceUri())
-                .setServiceId(request.getFileServiceId())
-                .setSubscriptionId(request.getSubscriptionId())
-                .setOpaqueData(request.getOpaqueData())
-                .build();
+        DownloadRequest request = downloadRequestTemplate.setAppIntent(intent).build();
+        DownloadRequest newRequest =
+                DownloadRequest.Builder.fromSerializedRequest(request.toByteArray())
+                        .build();
         assertEquals(request, newRequest);
     }
 
diff --git a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadStateCallbackTest.java b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadStateCallbackTest.java
index a5cc2d0..c01de7c 100644
--- a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadStateCallbackTest.java
+++ b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadStateCallbackTest.java
@@ -83,8 +83,8 @@
     public void testFullCallback() throws Exception {
         int sampleInt = 10;
         TestDSCallback callback = new TestDSCallback(DownloadStateCallback.ALL_UPDATES);
-        DownloadRequest request = DOWNLOAD_REQUEST_TEMPLATE.build();
-        mDownloadSession.registerStateCallback(request, callback, mCallbackHandler);
+        DownloadRequest request = downloadRequestTemplate.build();
+        mDownloadSession.registerStateCallback(request, mCallbackExecutor, callback);
         mMiddlewareControl.fireOnProgressUpdated(request, CtsDownloadService.FILE_INFO,
                 sampleInt, sampleInt, sampleInt, sampleInt);
         SomeArgs progressArgs = callback.waitOnProgressUpdated(ASYNC_TIMEOUT);
@@ -104,8 +104,8 @@
 
     public void testDeregistration() throws Exception {
         TestDSCallback callback = new TestDSCallback(DownloadStateCallback.ALL_UPDATES);
-        DownloadRequest request = DOWNLOAD_REQUEST_TEMPLATE.build();
-        mDownloadSession.registerStateCallback(request, callback, mCallbackHandler);
+        DownloadRequest request = downloadRequestTemplate.build();
+        mDownloadSession.registerStateCallback(request, mCallbackExecutor, callback);
         mDownloadSession.unregisterStateCallback(request, callback);
 
         mMiddlewareControl.fireOnStateUpdated(null, null, 0);
@@ -116,8 +116,8 @@
 
     public void testCallbackFiltering1() throws Exception {
         TestDSCallback callback = new TestDSCallback(DownloadStateCallback.PROGRESS_UPDATES);
-        DownloadRequest request = DOWNLOAD_REQUEST_TEMPLATE.build();
-        mDownloadSession.registerStateCallback(request, callback, mCallbackHandler);
+        DownloadRequest request = downloadRequestTemplate.build();
+        mDownloadSession.registerStateCallback(request, mCallbackExecutor, callback);
 
         mMiddlewareControl.fireOnStateUpdated(null, null, 0);
         assertNull(callback.waitOnStateUpdated(SHORT_TIMEOUT));
@@ -127,8 +127,8 @@
 
     public void testCallbackFiltering2() throws Exception {
         TestDSCallback callback = new TestDSCallback(DownloadStateCallback.STATE_UPDATES);
-        DownloadRequest request = DOWNLOAD_REQUEST_TEMPLATE.build();
-        mDownloadSession.registerStateCallback(request, callback, mCallbackHandler);
+        DownloadRequest request = downloadRequestTemplate.build();
+        mDownloadSession.registerStateCallback(request, mCallbackExecutor, callback);
 
         mMiddlewareControl.fireOnStateUpdated(null, null, 0);
         assertNotNull(callback.waitOnStateUpdated(SHORT_TIMEOUT));
diff --git a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadTestBase.java b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadTestBase.java
index 9da5f04..bde9de6 100644
--- a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadTestBase.java
+++ b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsDownloadTestBase.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -41,6 +42,7 @@
 import java.util.List;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
@@ -107,13 +109,12 @@
         }
     }
 
-    static final DownloadRequest.Builder DOWNLOAD_REQUEST_TEMPLATE =
-            new DownloadRequest.Builder(CtsDownloadService.DOWNLOAD_SOURCE_URI)
-                    .setServiceInfo(CtsDownloadService.FILE_SERVICE_INFO);
+    DownloadRequest.Builder downloadRequestTemplate;
 
     Context mContext;
     HandlerThread mHandlerThread;
-    Handler mCallbackHandler;
+    Handler mHandler;
+    Executor mCallbackExecutor;
     ICtsDownloadMiddlewareControl mMiddlewareControl;
     MbmsDownloadSession mDownloadSession;
     TestCallback mCallback = new TestCallback();
@@ -123,8 +124,16 @@
         mContext = getInstrumentation().getContext();
         mHandlerThread = new HandlerThread("EmbmsCtsTestWorker");
         mHandlerThread.start();
-        mCallbackHandler = new Handler(mHandlerThread.getLooper());
+        mHandler = new Handler(mHandlerThread.getLooper());
+        mCallbackExecutor = mHandler::post;
         mCallback = new TestCallback();
+
+        File destinationDirectory = new File(mContext.getFilesDir(), "downloads");
+        destinationDirectory.mkdirs();
+        Uri destinationDirectoryUri = Uri.fromFile(destinationDirectory);
+        downloadRequestTemplate = new DownloadRequest.Builder(
+                CtsDownloadService.DOWNLOAD_SOURCE_URI, destinationDirectoryUri)
+                .setServiceInfo(CtsDownloadService.FILE_SERVICE_INFO);
         getControlBinder();
         setupDownloadSession();
     }
@@ -138,7 +147,7 @@
 
     private void setupDownloadSession() throws Exception {
         mDownloadSession = MbmsDownloadSession.create(
-                mContext, mCallback, mCallbackHandler);
+                mContext, mCallbackExecutor, mCallback);
         assertNotNull(mDownloadSession);
         assertTrue(mCallback.waitOnMiddlewareReady());
         assertEquals(0, mCallback.getNumErrorCalls());
diff --git a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingServiceTest.java b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingServiceTest.java
index 42e5618..835a6e4 100644
--- a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingServiceTest.java
+++ b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingServiceTest.java
@@ -127,7 +127,7 @@
     public void testStartStreaming() throws Exception {
         StreamingService streamingService = mStreamingSession.startStreaming(
                 CtsStreamingService .STREAMING_SERVICE_INFO,
-                mStreamingServiceCallback, mCallbackHandler);
+                mCallbackExecutor, mStreamingServiceCallback);
         assertNotNull(streamingService);
         assertEquals(CtsStreamingService.STREAMING_SERVICE_INFO, streamingService.getInfo());
 
@@ -145,7 +145,7 @@
     public void testGetPlaybackUri() throws Exception {
         StreamingService streamingService = mStreamingSession.startStreaming(
                 CtsStreamingService .STREAMING_SERVICE_INFO,
-                mStreamingServiceCallback, mCallbackHandler);
+                mCallbackExecutor, mStreamingServiceCallback);
         assertEquals(CtsStreamingService.STREAMING_URI, streamingService.getPlaybackUri());
 
         List<List<Object>> getPlaybackUriCalls =
@@ -158,8 +158,8 @@
     public void testStopStreaming() throws Exception {
         StreamingService streamingService = mStreamingSession.startStreaming(
                 CtsStreamingService .STREAMING_SERVICE_INFO,
-                mStreamingServiceCallback, mCallbackHandler);
-        streamingService.stopStreaming();
+                mCallbackExecutor, mStreamingServiceCallback);
+        streamingService.close();
         List<List<Object>> stopStreamingCalls =
                 getMiddlewareCalls(CtsStreamingService.METHOD_STOP_STREAMING);
         assertEquals(1, stopStreamingCalls.size());
@@ -170,7 +170,7 @@
     public void testStreamingCallbacks() throws Exception {
         mStreamingSession.startStreaming(
                 CtsStreamingService .STREAMING_SERVICE_INFO,
-                mStreamingServiceCallback, mCallbackHandler);
+                mCallbackExecutor, mStreamingServiceCallback);
 
         mMiddlewareControl.fireErrorOnStream(
                 MbmsErrors.StreamingErrors.ERROR_UNABLE_TO_START_SERVICE, "");
@@ -194,7 +194,7 @@
         mMiddlewareControl.forceErrorCode(
                 MbmsErrors.GeneralErrors.ERROR_MIDDLEWARE_TEMPORARILY_UNAVAILABLE);
         mStreamingSession.startStreaming(CtsStreamingService.STREAMING_SERVICE_INFO,
-                mStreamingServiceCallback, mCallbackHandler);
+                mCallbackExecutor, mStreamingServiceCallback);
         assertEquals(MbmsErrors.GeneralErrors.ERROR_MIDDLEWARE_TEMPORARILY_UNAVAILABLE,
                 mCallback.waitOnError().arg1);
     }
diff --git a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingSessionTest.java b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingSessionTest.java
index 92b3fc9..0aeb734 100644
--- a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingSessionTest.java
+++ b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingSessionTest.java
@@ -29,7 +29,7 @@
     public void testDuplicateSession() throws Exception {
         try {
             MbmsStreamingSession failure = MbmsStreamingSession.create(
-                    mContext, mCallback, mCallbackHandler);
+                    mContext, mCallbackExecutor, mCallback);
             fail("Duplicate create should've thrown an exception");
         } catch (IllegalStateException e) {
             // Succeed
diff --git a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingTestBase.java b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingTestBase.java
index e170998..e4bb27b 100644
--- a/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingTestBase.java
+++ b/tests/tests/telephony/src/android/telephony/embms/cts/MbmsStreamingTestBase.java
@@ -21,6 +21,7 @@
 import java.util.List;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
@@ -87,7 +88,7 @@
 
     Context mContext;
     HandlerThread mHandlerThread;
-    Handler mCallbackHandler;
+    Executor mCallbackExecutor;
     ICtsStreamingMiddlewareControl mMiddlewareControl;
     MbmsStreamingSession mStreamingSession;
     TestCallback mCallback = new TestCallback();
@@ -97,7 +98,7 @@
         mContext = getInstrumentation().getContext();
         mHandlerThread = new HandlerThread("EmbmsCtsTestWorker");
         mHandlerThread.start();
-        mCallbackHandler = new Handler(mHandlerThread.getLooper());
+        mCallbackExecutor = (new Handler(mHandlerThread.getLooper()))::post;
         mCallback = new TestCallback();
         getControlBinder();
         setupStreamingSession();
@@ -112,7 +113,7 @@
 
     private void setupStreamingSession() throws Exception {
         mStreamingSession = MbmsStreamingSession.create(
-                mContext, mCallback, mCallbackHandler);
+                mContext, mCallbackExecutor, mCallback);
         assertNotNull(mStreamingSession);
         assertTrue(mCallback.waitOnMiddlewareReady());
         assertEquals(0, mCallback.getNumErrorCalls());
diff --git a/tests/tests/telephony2/Android.mk b/tests/tests/telephony2/Android.mk
index c755c2a..b86cae1 100644
--- a/tests/tests/telephony2/Android.mk
+++ b/tests/tests/telephony2/Android.mk
@@ -29,6 +29,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsTelephony2TestCases
+LOCAL_SDK_VERSION := current
 
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
diff --git a/tests/tests/text/src/android/text/cts/MeasuredTextTest.java b/tests/tests/text/src/android/text/cts/MeasuredTextTest.java
deleted file mode 100644
index 0ecd284..0000000
--- a/tests/tests/text/src/android/text/cts/MeasuredTextTest.java
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * 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.text.cts;
-
-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 static org.junit.Assert.fail;
-
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.text.Layout;
-import android.text.MeasuredText;
-import android.text.SpannableStringBuilder;
-import android.text.Spanned;
-import android.text.TextDirectionHeuristic;
-import android.text.TextDirectionHeuristics;
-import android.text.TextPaint;
-import android.text.style.LocaleSpan;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.Locale;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class MeasuredTextTest {
-
-    private static final CharSequence NULL_CHAR_SEQUENCE = null;
-    private static final String STRING = "Hello, World!";
-    private static final String MULTIPARA_STRING = "Hello,\nWorld!";
-
-    private static final int SPAN_START = 3;
-    private static final int SPAN_END = 7;
-    private static final LocaleSpan SPAN = new LocaleSpan(Locale.US);
-    private static final Spanned SPANNED;
-    static {
-        final SpannableStringBuilder ssb = new SpannableStringBuilder(STRING);
-        ssb.setSpan(SPAN, SPAN_START, SPAN_END, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
-        SPANNED = ssb;
-    }
-
-    private static final TextPaint PAINT = new TextPaint();
-
-    private static final TextDirectionHeuristic LTR = TextDirectionHeuristics.LTR;
-
-    @Test
-    public void testBuilder() {
-        assertNotNull(new MeasuredText.Builder(STRING, PAINT)
-                .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
-                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE).build());
-        assertNotNull(new MeasuredText.Builder(SPANNED, PAINT)
-                .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
-                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE).build());
-    }
-
-    @Test
-    public void testBuilder_withNull() {
-        try {
-            new MeasuredText.Builder(NULL_CHAR_SEQUENCE, PAINT);
-            fail();
-        } catch (NullPointerException e) {
-            // pass
-        }
-        try {
-            new MeasuredText.Builder(STRING, null);
-            fail();
-        } catch (NullPointerException e) {
-            // pass
-        }
-        try {
-            new MeasuredText.Builder(STRING, PAINT).setTextDirection(null);
-            fail();
-        } catch (NullPointerException e) {
-            // pass
-        }
-    }
-
-    @Test
-    public void testBuilder_setRange() {
-        assertNotNull(new MeasuredText.Builder(STRING, PAINT).setRange(0, STRING.length()).build());
-        assertNotNull(new MeasuredText.Builder(STRING, PAINT)
-                .setRange(1, STRING.length() - 1).build());
-        assertNotNull(new MeasuredText.Builder(SPANNED, PAINT)
-                .setRange(0, SPANNED.length()).build());
-        assertNotNull(new MeasuredText.Builder(SPANNED, PAINT)
-                .setRange(1, SPANNED.length() - 1).build());
-        try {
-            new MeasuredText.Builder(STRING, PAINT).setRange(-1, -1);
-            fail();
-        } catch (IllegalArgumentException e) {
-            // pass
-        }
-        try {
-            new MeasuredText.Builder(STRING, PAINT).setRange(100000, 100000);
-            fail();
-        } catch (IllegalArgumentException e) {
-            // pass
-        }
-        try {
-            new MeasuredText.Builder(STRING, PAINT).setRange(STRING.length() - 1, 0);
-            fail();
-        } catch (IllegalArgumentException e) {
-            // pass
-        }
-    }
-
-    @Test
-    public void testCharSequenceInteferface() {
-        final CharSequence s = new MeasuredText.Builder(STRING, PAINT).build();
-        assertEquals(STRING.length(), s.length());
-        assertEquals('H', s.charAt(0));
-        assertEquals('e', s.charAt(1));
-        assertEquals('l', s.charAt(2));
-        assertEquals('l', s.charAt(3));
-        assertEquals('o', s.charAt(4));
-        assertEquals(',', s.charAt(5));
-        assertEquals("Hello, World!", s.toString());
-
-        // Even measure the part of the text, the CharSequence interface still works for original
-        // text.
-        // TODO: Should this work like substring?
-        final CharSequence s2 = new MeasuredText.Builder(STRING, PAINT)
-                .setRange(7, STRING.length()).build();
-        assertEquals(STRING.length(), s2.length());
-        assertEquals('H', s2.charAt(0));
-        assertEquals('e', s2.charAt(1));
-        assertEquals('l', s2.charAt(2));
-        assertEquals('l', s2.charAt(3));
-        assertEquals('o', s2.charAt(4));
-        assertEquals(',', s2.charAt(5));
-        assertEquals("Hello, World!", s2.toString());
-
-        final CharSequence s3 = s.subSequence(0, 3);
-        assertEquals(3, s3.length());
-        assertEquals('H', s3.charAt(0));
-        assertEquals('e', s3.charAt(1));
-        assertEquals('l', s3.charAt(2));
-
-    }
-
-    @Test
-    public void testSpannedInterface_Spanned() {
-        final Spanned s = new MeasuredText.Builder(SPANNED, PAINT).build();
-        final LocaleSpan[] spans = s.getSpans(0, s.length(), LocaleSpan.class);
-        assertNotNull(spans);
-        assertEquals(1, spans.length);
-        assertEquals(SPAN, spans[0]);
-
-        assertEquals(SPAN_START, s.getSpanStart(SPAN));
-        assertEquals(SPAN_END, s.getSpanEnd(SPAN));
-        assertTrue((s.getSpanFlags(SPAN) & Spanned.SPAN_INCLUSIVE_EXCLUSIVE) != 0);
-
-        assertEquals(SPAN_START, s.nextSpanTransition(0, s.length(), LocaleSpan.class));
-        assertEquals(SPAN_END, s.nextSpanTransition(SPAN_START, s.length(), LocaleSpan.class));
-
-        final Spanned s2 = new MeasuredText.Builder(SPANNED, PAINT)
-                .setRange(7, SPANNED.length()).build();
-        final LocaleSpan[] spans2 = s2.getSpans(0, s2.length(), LocaleSpan.class);
-        assertNotNull(spans2);
-        assertEquals(1, spans2.length);
-        assertEquals(SPAN, spans2[0]);
-
-        assertEquals(SPAN_START, s2.getSpanStart(SPAN));
-        assertEquals(SPAN_END, s2.getSpanEnd(SPAN));
-        assertTrue((s2.getSpanFlags(SPAN) & Spanned.SPAN_INCLUSIVE_EXCLUSIVE) != 0);
-
-        assertEquals(SPAN_START, s2.nextSpanTransition(0, s2.length(), LocaleSpan.class));
-        assertEquals(SPAN_END, s2.nextSpanTransition(SPAN_START, s2.length(), LocaleSpan.class));
-    }
-
-    @Test
-    public void testSpannedInterface_String() {
-        final Spanned s = new MeasuredText.Builder(STRING, PAINT).build();
-        LocaleSpan[] spans = s.getSpans(0, s.length(), LocaleSpan.class);
-        assertNotNull(spans);
-        assertEquals(0, spans.length);
-
-        assertEquals(-1, s.getSpanStart(SPAN));
-        assertEquals(-1, s.getSpanEnd(SPAN));
-        assertEquals(0, s.getSpanFlags(SPAN));
-
-        assertEquals(s.length(), s.nextSpanTransition(0, s.length(), LocaleSpan.class));
-    }
-
-    @Test
-    public void testGetText() {
-        assertSame(STRING, new MeasuredText.Builder(STRING, PAINT).build().getText());
-        assertSame(SPANNED, new MeasuredText.Builder(SPANNED, PAINT).build().getText());
-
-        assertSame(STRING, new MeasuredText.Builder(STRING, PAINT)
-                .setRange(1, 5).build().getText());
-        assertSame(SPANNED, new MeasuredText.Builder(SPANNED, PAINT)
-                .setRange(1, 5).build().getText());
-    }
-
-    @Test
-    public void testGetStartEnd() {
-        assertEquals(0, new MeasuredText.Builder(STRING, PAINT).build().getStart());
-        assertEquals(STRING.length(), new MeasuredText.Builder(STRING, PAINT).build().getEnd());
-
-        assertEquals(1, new MeasuredText.Builder(STRING, PAINT).setRange(1, 5).build().getStart());
-        assertEquals(5, new MeasuredText.Builder(STRING, PAINT).setRange(1, 5).build().getEnd());
-
-        assertEquals(0, new MeasuredText.Builder(SPANNED, PAINT).build().getStart());
-        assertEquals(SPANNED.length(), new MeasuredText.Builder(SPANNED, PAINT).build().getEnd());
-
-        assertEquals(1, new MeasuredText.Builder(SPANNED, PAINT).setRange(1, 5).build().getStart());
-        assertEquals(5, new MeasuredText.Builder(SPANNED, PAINT).setRange(1, 5).build().getEnd());
-    }
-
-    @Test
-    public void testGetTextDir() {
-        assertSame(TextDirectionHeuristics.FIRSTSTRONG_LTR,
-                new MeasuredText.Builder(STRING, PAINT).build().getTextDir());
-        assertSame(TextDirectionHeuristics.LTR,
-                new MeasuredText.Builder(SPANNED, PAINT)
-                        .setTextDirection(TextDirectionHeuristics.LTR).build().getTextDir());
-    }
-
-    @Test
-    public void testGetPaint() {
-        // No Paint equality functions. Check only not null.
-        assertNotNull(new MeasuredText.Builder(STRING, PAINT).build().getPaint());
-        assertNotNull(new MeasuredText.Builder(SPANNED, PAINT).build().getPaint());
-    }
-
-    @Test
-    public void testGetBreakStrategy() {
-        assertEquals(Layout.BREAK_STRATEGY_HIGH_QUALITY,
-                new MeasuredText.Builder(STRING, PAINT).build().getBreakStrategy());
-        assertEquals(Layout.BREAK_STRATEGY_SIMPLE,
-                new MeasuredText.Builder(STRING, PAINT)
-                        .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE).build().getBreakStrategy());
-    }
-
-    @Test
-    public void testGetHyphenationFrequency() {
-        assertEquals(Layout.HYPHENATION_FREQUENCY_NORMAL,
-                new MeasuredText.Builder(STRING, PAINT).build().getHyphenationFrequency());
-        assertEquals(Layout.HYPHENATION_FREQUENCY_NONE,
-                new MeasuredText.Builder(STRING, PAINT)
-                        .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE).build()
-                                .getHyphenationFrequency());
-    }
-
-    @Test
-    public void testGetParagraphCount() {
-        final MeasuredText pm = new MeasuredText.Builder(STRING, PAINT).build();
-        assertEquals(1, pm.getParagraphCount());
-        assertEquals(0, pm.getParagraphStart(0));
-        assertEquals(STRING.length(), pm.getParagraphEnd(0));
-
-        final MeasuredText pm2 = new MeasuredText.Builder(STRING, PAINT).setRange(1, 9).build();
-        assertEquals(1, pm2.getParagraphCount());
-        assertEquals(1, pm2.getParagraphStart(0));
-        assertEquals(9, pm2.getParagraphEnd(0));
-
-        final MeasuredText pm3 = new MeasuredText.Builder(MULTIPARA_STRING, PAINT).build();
-        assertEquals(2, pm3.getParagraphCount());
-        assertEquals(0, pm3.getParagraphStart(0));
-        assertEquals(7, pm3.getParagraphEnd(0));
-        assertEquals(7, pm3.getParagraphStart(1));
-        assertEquals(pm3.length(), pm3.getParagraphEnd(1));
-
-        final MeasuredText pm4 = new MeasuredText.Builder(MULTIPARA_STRING, PAINT)
-                .setRange(1, 5).build();
-        assertEquals(1, pm4.getParagraphCount());
-        assertEquals(1, pm4.getParagraphStart(0));
-        assertEquals(5, pm4.getParagraphEnd(0));
-
-        final MeasuredText pm5 = new MeasuredText.Builder(MULTIPARA_STRING, PAINT)
-                .setRange(1, 9).build();
-        assertEquals(2, pm5.getParagraphCount());
-        assertEquals(1, pm5.getParagraphStart(0));
-        assertEquals(7, pm5.getParagraphEnd(0));
-        assertEquals(7, pm5.getParagraphStart(1));
-        assertEquals(9, pm5.getParagraphEnd(1));
-    }
-
-}
diff --git a/tests/tests/text/src/android/text/cts/PrecomputedTextTest.java b/tests/tests/text/src/android/text/cts/PrecomputedTextTest.java
new file mode 100644
index 0000000..8967d3a
--- /dev/null
+++ b/tests/tests/text/src/android/text/cts/PrecomputedTextTest.java
@@ -0,0 +1,246 @@
+/*
+ * 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.text.cts;
+
+import static android.text.TextDirectionHeuristics.LTR;
+import static android.text.TextDirectionHeuristics.RTL;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.text.Layout;
+import android.text.PrecomputedText;
+import android.text.PrecomputedText.Params;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
+import android.text.TextDirectionHeuristics;
+import android.text.TextPaint;
+import android.text.style.LocaleSpan;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Locale;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class PrecomputedTextTest {
+
+    private static final CharSequence NULL_CHAR_SEQUENCE = null;
+    private static final String STRING = "Hello, World!";
+    private static final String MULTIPARA_STRING = "Hello,\nWorld!";
+
+    private static final int SPAN_START = 3;
+    private static final int SPAN_END = 7;
+    private static final LocaleSpan SPAN = new LocaleSpan(Locale.US);
+    private static final Spanned SPANNED;
+    static {
+        final SpannableStringBuilder ssb = new SpannableStringBuilder(STRING);
+        ssb.setSpan(SPAN, SPAN_START, SPAN_END, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+        SPANNED = ssb;
+    }
+
+    private static final TextPaint PAINT = new TextPaint();
+
+    @Test
+    public void testParams_create() {
+        assertNotNull(new Params.Builder(PAINT).build());
+        assertNotNull(new Params.Builder(PAINT)
+                .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE).build());
+        assertNotNull(new Params.Builder(PAINT)
+                .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
+                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL).build());
+        assertNotNull(new Params.Builder(PAINT)
+                .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
+                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+                .setTextDirection(LTR).build());
+    }
+
+    @Test
+    public void testParams_SetGet() {
+        assertEquals(Layout.BREAK_STRATEGY_SIMPLE, new Params.Builder(PAINT)
+                .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE).build().getBreakStrategy());
+        assertEquals(Layout.HYPHENATION_FREQUENCY_NONE, new Params.Builder(PAINT)
+                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE).build()
+                        .getHyphenationFrequency());
+        assertEquals(RTL, new Params.Builder(PAINT).setTextDirection(RTL).build()
+                .getTextDirection());
+    }
+
+    @Test
+    public void testParams_GetDefaultValues() {
+        assertEquals(Layout.BREAK_STRATEGY_HIGH_QUALITY,
+                     new Params.Builder(PAINT).build().getBreakStrategy());
+        assertEquals(Layout.HYPHENATION_FREQUENCY_NORMAL,
+                     new Params.Builder(PAINT).build().getHyphenationFrequency());
+        assertEquals(TextDirectionHeuristics.FIRSTSTRONG_LTR,
+                     new Params.Builder(PAINT).build().getTextDirection());
+    }
+
+    @Test
+    public void testParams_equals() {
+        final Params base = new Params.Builder(PAINT)
+                .setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY)
+                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+                .setTextDirection(LTR).build();
+
+        assertFalse(base.equals(null));
+        assertTrue(base.equals(base));
+        assertFalse(base.equals(new Object()));
+
+        Params other = new Params.Builder(PAINT)
+                .setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY)
+                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+                .setTextDirection(LTR).build();
+        assertTrue(base.equals(other));
+        assertTrue(other.equals(base));
+        assertEquals(base.hashCode(), other.hashCode());
+
+        other = new Params.Builder(PAINT)
+                .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
+                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+                .setTextDirection(LTR).build();
+        assertFalse(base.equals(other));
+        assertFalse(other.equals(base));
+
+        other = new Params.Builder(PAINT)
+                .setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY)
+                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
+                .setTextDirection(LTR).build();
+        assertFalse(base.equals(other));
+        assertFalse(other.equals(base));
+
+
+        other = new Params.Builder(PAINT)
+                .setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY)
+                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+                .setTextDirection(RTL).build();
+        assertFalse(base.equals(other));
+        assertFalse(other.equals(base));
+
+
+        TextPaint anotherPaint = new TextPaint(PAINT);
+        anotherPaint.setTextSize(PAINT.getTextSize() * 2.0f);
+        other = new Params.Builder(anotherPaint)
+                .setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY)
+                .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+                .setTextDirection(LTR).build();
+        assertFalse(base.equals(other));
+        assertFalse(other.equals(base));
+
+    }
+
+    @Test
+    public void testCreate_withNull() {
+        final Params param = new Params.Builder(PAINT).build();
+        try {
+            PrecomputedText.create(NULL_CHAR_SEQUENCE, param);
+            fail();
+        } catch (NullPointerException e) {
+            // pass
+        }
+        try {
+            PrecomputedText.create(STRING, null);
+            fail();
+        } catch (NullPointerException e) {
+            // pass
+        }
+    }
+
+    @Test
+    public void testCharSequenceInteface() {
+        final Params param = new Params.Builder(PAINT).build();
+        final CharSequence s = PrecomputedText.create(STRING, param);
+        assertEquals(STRING.length(), s.length());
+        assertEquals('H', s.charAt(0));
+        assertEquals('e', s.charAt(1));
+        assertEquals('l', s.charAt(2));
+        assertEquals('l', s.charAt(3));
+        assertEquals('o', s.charAt(4));
+        assertEquals(',', s.charAt(5));
+        assertEquals("Hello, World!", s.toString());
+
+        final CharSequence s3 = s.subSequence(0, 3);
+        assertEquals(3, s3.length());
+        assertEquals('H', s3.charAt(0));
+        assertEquals('e', s3.charAt(1));
+        assertEquals('l', s3.charAt(2));
+
+    }
+
+    @Test
+    public void testSpannedInterface_Spanned() {
+        final Params param = new Params.Builder(PAINT).build();
+        final Spanned s = PrecomputedText.create(SPANNED, param);
+        final LocaleSpan[] spans = s.getSpans(0, s.length(), LocaleSpan.class);
+        assertNotNull(spans);
+        assertEquals(1, spans.length);
+        assertEquals(SPAN, spans[0]);
+
+        assertEquals(SPAN_START, s.getSpanStart(SPAN));
+        assertEquals(SPAN_END, s.getSpanEnd(SPAN));
+        assertTrue((s.getSpanFlags(SPAN) & Spanned.SPAN_INCLUSIVE_EXCLUSIVE) != 0);
+
+        assertEquals(SPAN_START, s.nextSpanTransition(0, s.length(), LocaleSpan.class));
+        assertEquals(SPAN_END, s.nextSpanTransition(SPAN_START, s.length(), LocaleSpan.class));
+    }
+
+    @Test
+    public void testSpannedInterface_String() {
+        final Params param = new Params.Builder(PAINT).build();
+        final Spanned s = PrecomputedText.create(STRING, param);
+        LocaleSpan[] spans = s.getSpans(0, s.length(), LocaleSpan.class);
+        assertNotNull(spans);
+        assertEquals(0, spans.length);
+
+        assertEquals(-1, s.getSpanStart(SPAN));
+        assertEquals(-1, s.getSpanEnd(SPAN));
+        assertEquals(0, s.getSpanFlags(SPAN));
+
+        assertEquals(s.length(), s.nextSpanTransition(0, s.length(), LocaleSpan.class));
+    }
+
+    @Test
+    public void testGetText() {
+        final Params param = new Params.Builder(PAINT).build();
+        assertEquals(STRING.toString(), PrecomputedText.create(STRING, param).getText().toString());
+        assertEquals(SPANNED.toString(),
+                PrecomputedText.create(SPANNED, param).getText().toString());
+    }
+
+    @Test
+    public void testGetParagraphCount() {
+        final Params param = new Params.Builder(PAINT).build();
+        final PrecomputedText pm = PrecomputedText.create(STRING, param);
+        assertEquals(1, pm.getParagraphCount());
+        assertEquals(0, pm.getParagraphStart(0));
+        assertEquals(STRING.length(), pm.getParagraphEnd(0));
+
+        final PrecomputedText pm1 = PrecomputedText.create(MULTIPARA_STRING, param);
+        assertEquals(2, pm1.getParagraphCount());
+        assertEquals(0, pm1.getParagraphStart(0));
+        assertEquals(7, pm1.getParagraphEnd(0));
+        assertEquals(7, pm1.getParagraphStart(1));
+        assertEquals(pm1.length(), pm1.getParagraphEnd(1));
+    }
+
+}
diff --git a/tests/tests/text/src/android/text/cts/StaticLayoutTest.java b/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
index fe05167..8113615 100644
--- a/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
+++ b/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
@@ -22,29 +22,29 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import android.content.res.ColorStateList;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Typeface;
+import android.os.LocaleList;
 import android.support.test.filters.SmallTest;
 import android.support.test.filters.Suppress;
 import android.support.test.runner.AndroidJUnit4;
 import android.text.Editable;
 import android.text.Layout;
 import android.text.Layout.Alignment;
-import android.text.MeasuredText;
+import android.text.PrecomputedText;
 import android.text.SpannableString;
 import android.text.SpannableStringBuilder;
 import android.text.Spanned;
 import android.text.SpannedString;
 import android.text.StaticLayout;
+import android.text.TextDirectionHeuristic;
 import android.text.TextDirectionHeuristics;
 import android.text.TextPaint;
 import android.text.TextUtils;
 import android.text.TextUtils.TruncateAt;
 import android.text.method.cts.EditorState;
 import android.text.style.StyleSpan;
-import android.text.style.TextAppearanceSpan;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -1283,31 +1283,186 @@
         return bmp;
     }
 
-    @Test
-    public void testPremeasured() {
-        final float wholeWidth = mDefaultPaint.measureText(LOREM_IPSUM);
+    private static String textPaintToString(TextPaint p) {
+        return "{"
+            + "mTextSize=" + p.getTextSize() + ", "
+            + "mTextSkewX=" + p.getTextSkewX() + ", "
+            + "mTextScaleX=" + p.getTextScaleX() + ", "
+            + "mLetterSpacing=" + p.getLetterSpacing() + ", "
+            + "mFlags=" + p.getFlags() + ", "
+            + "mTextLocales=" + p.getTextLocales() + ", "
+            + "mFontVariationSettings=" + p.getFontVariationSettings() + ", "
+            + "mTypeface=" + p.getTypeface() + ", "
+            + "mFontFeatureSettings=" + p.getFontFeatureSettings()
+            + "}";
+    }
+
+    private static String directionToString(TextDirectionHeuristic dir) {
+        if (dir == TextDirectionHeuristics.LTR) {
+            return "LTR";
+        } else if (dir == TextDirectionHeuristics.RTL) {
+            return "RTL";
+        } else if (dir == TextDirectionHeuristics.FIRSTSTRONG_LTR) {
+            return "FIRSTSTRONG_LTR";
+        } else if (dir == TextDirectionHeuristics.FIRSTSTRONG_RTL) {
+            return "FIRSTSTRONG_RTL";
+        } else if (dir == TextDirectionHeuristics.ANYRTL_LTR) {
+            return "ANYRTL_LTR";
+        } else {
+            throw new RuntimeException("Unknown Direction");
+        }
+    }
+
+    static class LayoutParam {
+        final int mStrategy;
+        final int mFrequency;
+        final TextPaint mPaint;
+        final TextDirectionHeuristic mDir;
+
+        LayoutParam(int strategy, int frequency, TextPaint paint, TextDirectionHeuristic dir) {
+            mStrategy = strategy;
+            mFrequency = frequency;
+            mPaint = new TextPaint(paint);
+            mDir = dir;
+        }
+
+        @Override
+        public String toString() {
+            return "{"
+                + "mStrategy=" + mStrategy + ", "
+                + "mFrequency=" + mFrequency + ", "
+                + "mPaint=" + textPaintToString(mPaint) + ", "
+                + "mDir=" + directionToString(mDir)
+                + "}";
+
+        }
+
+        Layout getLayout(CharSequence text, int width) {
+            return StaticLayout.Builder.obtain(text, 0, text.length(), mPaint, width)
+                .setBreakStrategy(mStrategy).setHyphenationFrequency(mFrequency)
+                .setTextDirection(mDir).build();
+        }
+
+        PrecomputedText getPrecomputedText(CharSequence text) {
+            PrecomputedText.Params param = new PrecomputedText.Params.Builder(mPaint)
+                    .setBreakStrategy(mStrategy)
+                    .setHyphenationFrequency(mFrequency)
+                    .setTextDirection(mDir).build();
+            return PrecomputedText.create(text, param);
+        }
+    };
+
+    void assertSameStaticLayout(CharSequence text, LayoutParam measuredTextParam,
+                                LayoutParam staticLayoutParam) {
+        String msg = "StaticLayout for " + staticLayoutParam + " with PrecomputedText"
+                + " created with " + measuredTextParam + " must output the same BMP.";
+
+        final float wholeWidth = mDefaultPaint.measureText(text.toString());
         final int lineWidth = (int) (wholeWidth / 10.0f);  // Make 10 lines per paragraph.
 
-        final ColorStateList textColor = ColorStateList.valueOf(0x88FF0000);
-        final TextAppearanceSpan span = new TextAppearanceSpan(
-                "serif", Typeface.BOLD, 64 /* text size */, textColor, textColor);
-        final SpannableStringBuilder ssb = new SpannableStringBuilder(
-                LOREM_IPSUM + "\n" + LOREM_IPSUM);
-        ssb.setSpan(span, 0, LOREM_IPSUM.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+        // Static layout parameter should be used for the final output.
+        final Layout expectedLayout = staticLayoutParam.getLayout(text, lineWidth);
 
-        final Layout layout = StaticLayout.Builder.obtain(ssb, 0, ssb.length(), mDefaultPaint,
-                lineWidth).build();
+        final PrecomputedText mt = measuredTextParam.getPrecomputedText(text);
+        final Layout resultLayout = StaticLayout.Builder.obtain(mt, 0, mt.length(),
+                staticLayoutParam.mPaint, lineWidth)
+                .setBreakStrategy(staticLayoutParam.mStrategy)
+                .setHyphenationFrequency(staticLayoutParam.mFrequency)
+                .setTextDirection(staticLayoutParam.mDir).build();
 
-        final MeasuredText premeasuredText = new MeasuredText.Builder(ssb, mDefaultPaint).build();
-        final Layout premLayout = StaticLayout.Builder.obtain(premeasuredText, 0,
-                premeasuredText.length(), mDefaultPaint, lineWidth)
-                .setTextDirection(TextDirectionHeuristics.FIRSTSTRONG_LTR).build();
+        assertEquals(msg, expectedLayout.getHeight(), resultLayout.getHeight(), 0.0f);
 
-        assertEquals(layout.getHeight(), premLayout.getHeight(), 0.0f);
+        final Bitmap expectedBMP = drawToBitmap(expectedLayout);
+        final Bitmap resultBMP = drawToBitmap(resultLayout);
 
-        final Bitmap bmp = drawToBitmap(layout);
-        final Bitmap premBmp = drawToBitmap(premLayout);
+        assertTrue(msg, resultBMP.sameAs(expectedBMP));
+    }
 
-        assertTrue(bmp.sameAs(premBmp));  // Need to be pixel perfect.
+    @Test
+    public void testPrecomputedText() {
+        int[] breaks = {
+            Layout.BREAK_STRATEGY_SIMPLE,
+            Layout.BREAK_STRATEGY_HIGH_QUALITY,
+            Layout.BREAK_STRATEGY_BALANCED,
+        };
+
+        int[] frequencies = {
+            Layout.HYPHENATION_FREQUENCY_NORMAL,
+            Layout.HYPHENATION_FREQUENCY_FULL,
+            Layout.HYPHENATION_FREQUENCY_NONE,
+        };
+
+        TextDirectionHeuristic[] dirs = {
+            TextDirectionHeuristics.LTR,
+            TextDirectionHeuristics.RTL,
+            TextDirectionHeuristics.FIRSTSTRONG_LTR,
+            TextDirectionHeuristics.FIRSTSTRONG_RTL,
+            TextDirectionHeuristics.ANYRTL_LTR,
+        };
+
+        float[] textSizes = {
+            8.0f, 16.0f, 32.0f
+        };
+
+        LocaleList[] locales = {
+            LocaleList.forLanguageTags("en-US"),
+            LocaleList.forLanguageTags("ja-JP"),
+            LocaleList.forLanguageTags("en-US,ja-JP"),
+        };
+
+        TextPaint paint = new TextPaint();
+
+        // If the PrecomputedText is created with the same argument of the StaticLayout, generate
+        // the same bitmap.
+        for (int b : breaks) {
+            for (int f : frequencies) {
+                for (TextDirectionHeuristic dir : dirs) {
+                    for (float textSize : textSizes) {
+                        for (LocaleList locale : locales) {
+                            paint.setTextSize(textSize);
+                            paint.setTextLocales(locale);
+
+                            assertSameStaticLayout(LOREM_IPSUM,
+                                    new LayoutParam(b, f, paint, dir),
+                                    new LayoutParam(b, f, paint, dir));
+                        }
+                    }
+                }
+            }
+        }
+
+        // If the parameters are different, the output of the static layout must be
+        // same bitmap.
+        for (int bi = 0; bi < breaks.length; bi++) {
+            for (int fi = 0; fi < frequencies.length; fi++) {
+                for (int diri = 0; diri < dirs.length; diri++) {
+                    for (int sizei = 0; sizei < textSizes.length; sizei++) {
+                        for (int localei = 0; localei < locales.length; localei++) {
+                            TextPaint p1 = new TextPaint();
+                            TextPaint p2 = new TextPaint();
+
+                            p1.setTextSize(textSizes[sizei]);
+                            p2.setTextSize(textSizes[(sizei + 1) % textSizes.length]);
+
+                            p1.setTextLocales(locales[localei]);
+                            p2.setTextLocales(locales[(localei + 1) % locales.length]);
+
+                            int b1 = breaks[bi];
+                            int b2 = breaks[(bi + 1) % breaks.length];
+
+                            int f1 = frequencies[fi];
+                            int f2 = frequencies[(fi + 1) % frequencies.length];
+
+                            TextDirectionHeuristic dir1 = dirs[diri];
+                            TextDirectionHeuristic dir2 = dirs[(diri + 1) % dirs.length];
+
+                            assertSameStaticLayout(LOREM_IPSUM,
+                                    new LayoutParam(b1, f1, p1, dir1),
+                                    new LayoutParam(b2, f2, p2, dir2));
+                        }
+                    }
+                }
+            }
+        }
     }
 }
diff --git a/tests/tests/toast/Android.mk b/tests/tests/toast/Android.mk
index 1ba7d79..99af898 100644
--- a/tests/tests/toast/Android.mk
+++ b/tests/tests/toast/Android.mk
@@ -28,6 +28,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsToastTestCases
+LOCAL_SDK_VERSION := current
 
 include $(BUILD_CTS_PACKAGE)
 
diff --git a/tests/tests/toastlegacy/Android.mk b/tests/tests/toastlegacy/Android.mk
index 335c539..217fe55 100644
--- a/tests/tests/toastlegacy/Android.mk
+++ b/tests/tests/toastlegacy/Android.mk
@@ -29,6 +29,7 @@
     ../toast/src/android/widget/toast/cts/BaseToastTest.java
 
 LOCAL_PACKAGE_NAME := CtsToastLegacyTestCases
+LOCAL_SDK_VERSION := current
 
 include $(BUILD_CTS_PACKAGE)
 
diff --git a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java
index 9d33a0a..a1ba898 100755
--- a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java
+++ b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java
@@ -25,6 +25,7 @@
 import android.content.Intent;
 import android.os.ParcelFileDescriptor;
 import android.os.SystemClock;
+import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
 import android.test.InstrumentationTestCase;
 import android.view.FrameStats;
@@ -61,6 +62,7 @@
         grantWriteSecureSettingsPermission(uiAutomation);
     }
 
+    @Presubmit
     public void testWindowContentFrameStats() throws Exception {
         Activity activity = null;
         try {
@@ -119,6 +121,7 @@
         }
     }
 
+    @Presubmit
     public void testWindowContentFrameStatsNoAnimation() throws Exception {
         Activity activity = null;
         try {
@@ -169,6 +172,7 @@
         }
     }
 
+    @Presubmit
     public void testWindowAnimationFrameStats() throws Exception {
         Activity firstActivity = null;
         Activity secondActivity = null;
@@ -265,6 +269,7 @@
         assertEquals(stats.getEndTimeNano(), FrameStats.UNDEFINED_TIME_NANO);
     }
 
+    @Presubmit
     public void testUsingUiAutomationAfterDestroy_shouldThrowException() {
         UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
         uiAutomation.destroy();
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java
index ee46601..abaf96e 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java
@@ -39,7 +39,7 @@
     @Test
     public void testScreenshot() {
         for (int i = 0 ; i < 500 ; i ++) {
-            takeScreenshot(new Point());
+            takeScreenshot(new TestPositionInfo(new Point(), new Point()));
             System.gc();
         }
     }
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java
index ae8f57e..7f588bd 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java
@@ -104,6 +104,17 @@
     }
 
     @Test
+    public void testLayerPaintXfermodeWithSoftware() {
+        createTest()
+                .addLayout(R.layout.simple_red_layout, (ViewInitializer) view -> {
+                    Paint paint = new Paint();
+                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
+                    view.setLayerType(View.LAYER_TYPE_SOFTWARE, paint);
+                }, true)
+                .runWithVerifier(new ColorVerifier(Color.TRANSPARENT));
+    }
+
+    @Test
     public void testLayerPaintColorFilter() {
         // Red, fully desaturated. Note that it's not 255/3 in each channel.
         // See ColorMatrix#setSaturation()
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SurfaceViewTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SurfaceViewTests.java
index 741c35c..2e1ce85 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SurfaceViewTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SurfaceViewTests.java
@@ -15,17 +15,13 @@
  */
 package android.uirendering.cts.testclasses;
 
-import com.android.compatibility.common.util.SynchronousPixelCopy;
-
 import android.animation.ObjectAnimator;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.Config;
 import android.graphics.Canvas;
 import android.graphics.Color;
-import android.graphics.Point;
 import android.graphics.Rect;
 import android.support.test.filters.LargeTest;
-import android.support.test.filters.MediumTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.uirendering.cts.R;
 import android.uirendering.cts.bitmapverifiers.ColorVerifier;
@@ -40,6 +36,8 @@
 import android.view.animation.LinearInterpolator;
 import android.widget.FrameLayout;
 
+import com.android.compatibility.common.util.SynchronousPixelCopy;
+
 import org.junit.Assert;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -111,9 +109,11 @@
                 mAnimator.cancel();
             }
         };
-        Screenshotter screenshotter = testOffset -> {
+        Screenshotter screenshotter = testPositionInfo -> {
             Bitmap source = getInstrumentation().getUiAutomation().takeScreenshot();
-            return Bitmap.createBitmap(source, testOffset.x, testOffset.y, TEST_WIDTH, TEST_HEIGHT);
+            return Bitmap.createBitmap(source,
+                    testPositionInfo.screenOffset.x, testPositionInfo.screenOffset.y,
+                    TEST_WIDTH, TEST_HEIGHT);
         };
         createTest()
                 .addLayout(R.layout.frame_layout, initializer, true)
@@ -131,7 +131,7 @@
         }
 
         @Override
-        public Bitmap takeScreenshot(Point point /* ignored */) {
+        public Bitmap takeScreenshot(TestPositionInfo testPositionInfo) {
             SynchronousPixelCopy copy = new SynchronousPixelCopy();
             Bitmap dest = Bitmap.createBitmap(
                     TEST_WIDTH, TEST_HEIGHT, Config.ARGB_8888);
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 99f2780..f94047d 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
@@ -118,26 +118,25 @@
         }
     }
 
-    public Bitmap takeScreenshot(Point testOffset) {
+    public Bitmap takeScreenshot(TestPositionInfo testPositionInfo) {
         if (mScreenshotter == null) {
             SynchronousPixelCopy copy = new SynchronousPixelCopy();
             Bitmap dest = Bitmap.createBitmap(
                     TEST_WIDTH, TEST_HEIGHT,
                     getActivity().getWindow().isWideColorGamut()
                             ? Config.RGBA_F16 : 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());
+            Rect srcRect = new Rect(0, 0, TEST_WIDTH, TEST_HEIGHT);
+            srcRect.offset(testPositionInfo.surfaceOffset.x, testPositionInfo.surfaceOffset.y);
+            Log.d(TAG, "capturing screenshot of " + srcRect.toShortString());
             int copyResult = copy.request(getActivity().getWindow(), srcRect, dest);
             Assert.assertEquals(PixelCopy.SUCCESS, copyResult);
             return dest;
         } else {
-            return mScreenshotter.takeScreenshot(testOffset);
+            return mScreenshotter.takeScreenshot(testPositionInfo);
         }
     }
-
-    protected Point runRenderSpec(TestCase testCase) {
-        Point testOffset = getActivity().enqueueRenderSpecAndWait(
+    protected TestPositionInfo runRenderSpec(TestCase testCase) {
+        TestPositionInfo testPositionInfo = getActivity().enqueueRenderSpecAndWait(
                 testCase.layoutID, testCase.canvasClient,
                 testCase.viewInitializer, testCase.useHardware, testCase.usePicture);
         testCase.wasTestRan = true;
@@ -148,15 +147,14 @@
                 throw new RuntimeException("readyFence didn't signal within 5 seconds");
             }
         }
-        return testOffset;
+        return testPositionInfo;
     }
 
     /**
      * Used to execute a specific part of a test and get the resultant bitmap
      */
     protected Bitmap captureRenderSpec(TestCase testCase) {
-        Point testOffset = runRenderSpec(testCase);
-        return takeScreenshot(testOffset);
+        return takeScreenshot(runRenderSpec(testCase));
     }
 
     protected TestCaseBuilder createTest() {
@@ -165,8 +163,28 @@
         return mTestCaseBuilder;
     }
 
+    public static class TestPositionInfo {
+        /**
+         * Position of capture area in surface space - use this offset for e.g.
+         * PixelCopy from a window's surface.
+         */
+        public final Point surfaceOffset;
+
+        /**
+         * Position of capture area in screen space - use this offset for e.g.
+         * {@code getInstrumentation().getUiAutomation().takeScreenshot()},
+         * since those screenshots are captured in screen space.
+         */
+        public final Point screenOffset;
+
+        public TestPositionInfo(Point surfaceOffset, Point screenOffset) {
+            this.surfaceOffset = surfaceOffset;
+            this.screenOffset = screenOffset;
+        }
+    }
+
     public interface Screenshotter {
-        Bitmap takeScreenshot(Point point);
+        Bitmap takeScreenshot(TestPositionInfo params);
     }
 
     /**
@@ -230,7 +248,7 @@
             }
 
             for (TestCase testCase : mTestCases) {
-                Point testOffset = runRenderSpec(testCase);
+                TestPositionInfo testPositionInfo = runRenderSpec(testCase);
 
                 for (int i = 0; i < VERIFY_ANIMATION_LOOP_COUNT; i++) {
                     try {
@@ -238,7 +256,7 @@
                     } catch (InterruptedException e) {
                         e.printStackTrace();
                     }
-                    Bitmap testCaseBitmap = takeScreenshot(testOffset);
+                    Bitmap testCaseBitmap = takeScreenshot(testPositionInfo);
                     mBitmapAsserter.assertBitmapIsVerified(testCaseBitmap, bitmapVerifier,
                             getName(), testCase.getDebugString());
                 }
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 48c4a95..b12390e 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java
@@ -47,7 +47,8 @@
     static final String EXTRA_WIDE_COLOR_GAMUT = "DrawActivity.WIDE_COLOR_GAMUT";
 
     private final static long TIME_OUT_MS = 10000;
-    private final Point mLock = new Point();
+    private final Object mLock = new Object();
+    private ActivityTestBase.TestPositionInfo mPositionInfo;
 
     private Handler mHandler;
     private View mView;
@@ -72,11 +73,11 @@
         return mOnTv;
     }
 
-    public Point enqueueRenderSpecAndWait(int layoutId, CanvasClient canvasClient,
-            @Nullable ViewInitializer viewInitializer, boolean useHardware, boolean usePicture) {
+    public ActivityTestBase.TestPositionInfo enqueueRenderSpecAndWait(int layoutId,
+            CanvasClient canvasClient, @Nullable ViewInitializer viewInitializer,
+            boolean useHardware, boolean usePicture) {
         ((RenderSpecHandler) mHandler).setViewInitializer(viewInitializer);
         int arg2 = (useHardware ? View.LAYER_TYPE_NONE : View.LAYER_TYPE_SOFTWARE);
-        Point point = new Point();
         synchronized (mLock) {
             if (canvasClient != null) {
                 mHandler.obtainMessage(RenderSpecHandler.CANVAS_MSG, usePicture ? 1 : 0,
@@ -87,12 +88,11 @@
 
             try {
                 mLock.wait(TIME_OUT_MS);
-                point.set(mLock.x, mLock.y);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
         }
-        return point;
+        return mPositionInfo;
     }
 
     public void reset() {
@@ -187,8 +187,6 @@
     }
 
     private class DrawCounterListener implements ViewTreeObserver.OnDrawListener {
-        private final int[] mLocationInWindow = new int[2];
-
         @Override
         public void onDraw() {
             long vsyncMillis = mView.getDrawingTime();
@@ -196,9 +194,14 @@
             mView.post(() -> mView.getViewTreeObserver().removeOnDrawListener(this));
 
             mDrawMonitor.notifyWhenDrawn(vsyncMillis, () -> {
+                final int[] location = new int[2];
+                mViewWrapper.getLocationInWindow(location);
+                Point surfaceOffset = new Point(location[0], location[1]);
+                mViewWrapper.getLocationOnScreen(location);
+                Point screenOffset = new Point(location[0], location[1]);
                 synchronized (mLock) {
-                    mViewWrapper.getLocationInWindow(mLocationInWindow);
-                    mLock.set(mLocationInWindow[0], mLocationInWindow[1]);
+                    mPositionInfo = new ActivityTestBase.TestPositionInfo(
+                            surfaceOffset, screenOffset);
                     mLock.notify();
                 }
             });
diff --git a/tests/tests/util/Android.mk b/tests/tests/util/Android.mk
index 4fa2a39..4dffce7 100644
--- a/tests/tests/util/Android.mk
+++ b/tests/tests/util/Android.mk
@@ -34,5 +34,6 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsUtilTestCases
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/view/Android.mk b/tests/tests/view/Android.mk
index 4538de3..e639b5c 100644
--- a/tests/tests/view/Android.mk
+++ b/tests/tests/view/Android.mk
@@ -42,6 +42,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsViewTestCases
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_CTS_PACKAGE)
 
diff --git a/tests/tests/view/AndroidManifest.xml b/tests/tests/view/AndroidManifest.xml
index 3b23811..e79a2e3 100644
--- a/tests/tests/view/AndroidManifest.xml
+++ b/tests/tests/view/AndroidManifest.xml
@@ -191,6 +191,13 @@
                   android:configChanges="orientation|screenSize"
                   android:colorMode="wideColorGamut" />
 
+        <activity android:name="android.view.cts.PixelCopyViewProducerDialogActivity"
+                  android:label="PixelCopyViewProducerDialogActivity"
+                  android:screenOrientation="portrait"
+                  android:rotationAnimation="jumpcut"
+                  android:theme="@android:style/Theme.Material.Dialog.NoActionBar"
+                  android:configChanges="orientation|screenSize" />
+
         <activity android:name="android.view.cts.FocusFinderCtsActivity"
                   android:screenOrientation="locked"
                   android:label="FocusFinderCtsActivity">
diff --git a/tests/tests/view/src/android/view/cts/PixelCopyTest.java b/tests/tests/view/src/android/view/cts/PixelCopyTest.java
index 0cbd0ca..2088b7c 100644
--- a/tests/tests/view/src/android/view/cts/PixelCopyTest.java
+++ b/tests/tests/view/src/android/view/cts/PixelCopyTest.java
@@ -83,6 +83,10 @@
                     PixelCopyWideGamutViewProducerActivity.class, false, false);
 
     @Rule
+    public ActivityTestRule<PixelCopyViewProducerDialogActivity> mDialogSourceActivityRule =
+            new ActivityTestRule<>(PixelCopyViewProducerDialogActivity.class, false, false);
+
+    @Rule
     public SurfaceTextureRule mSurfaceRule = new SurfaceTextureRule();
 
     private Instrumentation mInstrumentation;
@@ -458,6 +462,116 @@
         } while (activity.rotate());
     }
 
+    private Window waitForDialogProducerActivity() {
+        PixelCopyViewProducerActivity activity =
+                mDialogSourceActivityRule.launchActivity(null);
+        activity.waitForFirstDrawCompleted(3, TimeUnit.SECONDS);
+        return activity.getWindow();
+    }
+
+    private Rect makeDialogRect(int left, int top, int right, int bottom) {
+        Rect r = new Rect(left, top, right, bottom);
+        mDialogSourceActivityRule.getActivity().normalizedToSurface(r);
+        return r;
+    }
+
+    @Test
+    public void testDialogProducer() {
+        Bitmap bitmap;
+        Window window = waitForDialogProducerActivity();
+        PixelCopyViewProducerActivity activity = mDialogSourceActivityRule.getActivity();
+        do {
+            Rect src = makeDialogRect(0, 0, 100, 100);
+            bitmap = Bitmap.createBitmap(src.width(), src.height(), Config.ARGB_8888);
+            int result = mCopyHelper.request(window, src, bitmap);
+            assertEquals("Fullsize copy request failed", PixelCopy.SUCCESS, result);
+            assertEquals(Config.ARGB_8888, bitmap.getConfig());
+            assertBitmapQuadColor(bitmap,
+                    Color.RED, Color.GREEN, Color.BLUE, Color.BLACK);
+            assertBitmapEdgeColor(bitmap, Color.YELLOW);
+        } while (activity.rotate());
+    }
+
+    @Test
+    public void testDialogProducerCropTopLeft() {
+        Window window = waitForDialogProducerActivity();
+        Bitmap bitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
+        PixelCopyViewProducerActivity activity = mDialogSourceActivityRule.getActivity();
+        do {
+            int result = mCopyHelper.request(window, makeDialogRect(0, 0, 50, 50), bitmap);
+            assertEquals("Scaled copy request failed", PixelCopy.SUCCESS, result);
+            assertBitmapQuadColor(bitmap,
+                    Color.RED, Color.RED, Color.RED, Color.RED);
+        } while (activity.rotate());
+    }
+
+    @Test
+    public void testDialogProducerCropCenter() {
+        Window window = waitForDialogProducerActivity();
+        Bitmap bitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
+        PixelCopyViewProducerActivity activity = mDialogSourceActivityRule.getActivity();
+        do {
+            int result = mCopyHelper.request(window, makeDialogRect(25, 25, 75, 75), bitmap);
+            assertEquals("Scaled copy request failed", PixelCopy.SUCCESS, result);
+            assertBitmapQuadColor(bitmap,
+                    Color.RED, Color.GREEN, Color.BLUE, Color.BLACK);
+        } while (activity.rotate());
+    }
+
+    @Test
+    public void testDialogProducerCropBottomHalf() {
+        Window window = waitForDialogProducerActivity();
+        Bitmap bitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
+        PixelCopyViewProducerActivity activity = mDialogSourceActivityRule.getActivity();
+        do {
+            int result = mCopyHelper.request(window, makeDialogRect(0, 50, 100, 100), bitmap);
+            assertEquals("Scaled copy request failed", PixelCopy.SUCCESS, result);
+            assertBitmapQuadColor(bitmap,
+                    Color.BLUE, Color.BLACK, Color.BLUE, Color.BLACK);
+        } while (activity.rotate());
+    }
+
+    @Test
+    public void testDialogProducerScaling() {
+        // Since we only sample mid-pixel of each qudrant, filtering
+        // quality isn't tested
+        Window window = waitForDialogProducerActivity();
+        Bitmap bitmap = Bitmap.createBitmap(20, 20, Config.ARGB_8888);
+        PixelCopyViewProducerActivity activity = mDialogSourceActivityRule.getActivity();
+        do {
+            int result = mCopyHelper.request(window, bitmap);
+            assertEquals("Scaled copy request failed", PixelCopy.SUCCESS, result);
+            // Make sure nothing messed with the bitmap
+            assertEquals(20, bitmap.getWidth());
+            assertEquals(20, bitmap.getHeight());
+            assertEquals(Config.ARGB_8888, bitmap.getConfig());
+            assertBitmapQuadColor(bitmap,
+                    Color.RED, Color.GREEN, Color.BLUE, Color.BLACK);
+        } while (activity.rotate());
+    }
+
+    @Test
+    public void testDialogProducerCopyToRGBA16F() {
+        Window window = waitForDialogProducerActivity();
+        PixelCopyViewProducerActivity activity = mDialogSourceActivityRule.getActivity();
+
+        Bitmap bitmap;
+        do {
+            Rect src = makeDialogRect(0, 0, 100, 100);
+            bitmap = Bitmap.createBitmap(src.width(), src.height(), Config.RGBA_F16);
+            int result = mCopyHelper.request(window, src, bitmap);
+            // On OpenGL ES 2.0 devices a copy to RGBA_F16 can fail because there's
+            // not support for float textures
+            if (result != PixelCopy.ERROR_DESTINATION_INVALID) {
+                assertEquals("Fullsize copy request failed", PixelCopy.SUCCESS, result);
+                assertEquals(Config.RGBA_F16, bitmap.getConfig());
+                assertBitmapQuadColor(bitmap,
+                        Color.RED, Color.GREEN, Color.BLUE, Color.BLACK);
+                assertBitmapEdgeColor(bitmap, Color.YELLOW);
+            }
+        } while (activity.rotate());
+    }
+
     private static void assertEqualsRgba16f(String message, Bitmap bitmap, int x, int y,
             ByteBuffer dst, float r, float g, float b, float a) {
         int index = y * bitmap.getRowBytes() + (x << 3);
diff --git a/tests/tests/view/src/android/view/cts/PixelCopyViewProducerDialogActivity.java b/tests/tests/view/src/android/view/cts/PixelCopyViewProducerDialogActivity.java
new file mode 100644
index 0000000..a213758
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/PixelCopyViewProducerDialogActivity.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.cts;
+
+import android.os.Bundle;
+
+public class PixelCopyViewProducerDialogActivity extends PixelCopyViewProducerActivity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    public boolean rotate() {
+        return false;
+    }
+}
diff --git a/tests/tests/view/src/android/view/cts/surfacevalidator/CapturedActivity.java b/tests/tests/view/src/android/view/cts/surfacevalidator/CapturedActivity.java
index 1ff6dc5..4adc056 100644
--- a/tests/tests/view/src/android/view/cts/surfacevalidator/CapturedActivity.java
+++ b/tests/tests/view/src/android/view/cts/surfacevalidator/CapturedActivity.java
@@ -16,6 +16,7 @@
 package android.view.cts.surfacevalidator;
 
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import android.app.Activity;
 import android.content.Context;
@@ -23,6 +24,7 @@
 import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
 import android.graphics.Point;
+import android.graphics.Rect;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.VirtualDisplay;
 import android.media.MediaPlayer;
@@ -103,6 +105,7 @@
 
         mMediaPlayer = MediaPlayer.create(this, R.raw.colors_video);
         mMediaPlayer.setLooping(true);
+
     }
 
     public void dismissPermissionDialog() throws UiObjectNotFoundException {
@@ -207,11 +210,20 @@
             display.getRealSize(size);
             display.getMetrics(metrics);
 
+            View decorView = getWindow().getDecorView();
+            Rect boundsToCheck = new Rect(0, 0, decorView.getWidth(), decorView.getHeight());
+            int[] topLeft = decorView.getLocationOnScreen();
+            boundsToCheck.offset(topLeft[0], topLeft[1]);
+
+            if (boundsToCheck.width() < 90 || boundsToCheck.height() < 90) {
+                fail("capture bounds too small to be a fullscreen activity: " + boundsToCheck);
+            }
 
             mSurfacePixelValidator = new SurfacePixelValidator(CapturedActivity.this,
-                    size, animationTestCase.getChecker());
-            Log.d("MediaProjection", "Size is " + size.toString());
-            mVirtualDisplay = mMediaProjection.createVirtualDisplay("ScreenSharingDemo",
+                    size, boundsToCheck, animationTestCase.getChecker());
+            Log.d("MediaProjection", "Size is " + size.toString()
+                    + ", bounds are " + boundsToCheck.toShortString());
+            mVirtualDisplay = mMediaProjection.createVirtualDisplay("CtsCapturedActivity",
                     size.x, size.y,
                     metrics.densityDpi,
                     DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
diff --git a/tests/tests/view/src/android/view/cts/surfacevalidator/PixelCounter.rs b/tests/tests/view/src/android/view/cts/surfacevalidator/PixelCounter.rs
index f58b9cb..12e024c 100644
--- a/tests/tests/view/src/android/view/cts/surfacevalidator/PixelCounter.rs
+++ b/tests/tests/view/src/android/view/cts/surfacevalidator/PixelCounter.rs
@@ -18,11 +18,17 @@
 #pragma rs reduce(countBlackishPixels) accumulator(countBlackishPixelsAccum) combiner(countBlackishPixelsCombiner)
 
 uchar THRESHOLD;
+int BOUNDS[4];
 
-static void countBlackishPixelsAccum(int *accum, uchar4 pixel){
+static void countBlackishPixelsAccum(int *accum, uchar4 pixel, uint32_t x, uint32_t y) {
+
     if (pixel.r < THRESHOLD
             && pixel.g < THRESHOLD
-            && pixel.b < THRESHOLD) {
+            && pixel.b < THRESHOLD
+            && x >= BOUNDS[0]
+            && x < BOUNDS[2]
+            && y >= BOUNDS[1]
+            && y < BOUNDS[3]) {
         *accum += 1;
     }
 }
diff --git a/tests/tests/view/src/android/view/cts/surfacevalidator/SurfacePixelValidator.java b/tests/tests/view/src/android/view/cts/surfacevalidator/SurfacePixelValidator.java
index 9523b32..1a8bc0db 100644
--- a/tests/tests/view/src/android/view/cts/surfacevalidator/SurfacePixelValidator.java
+++ b/tests/tests/view/src/android/view/cts/surfacevalidator/SurfacePixelValidator.java
@@ -18,6 +18,7 @@
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Point;
+import android.graphics.Rect;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Trace;
@@ -102,7 +103,8 @@
         }
     };
 
-    public SurfacePixelValidator(Context context, Point size, PixelChecker pixelChecker) {
+    public SurfacePixelValidator(Context context, Point size, Rect boundsToCheck,
+            PixelChecker pixelChecker) {
         mWidth = size.x;
         mHeight = size.y;
 
@@ -116,6 +118,8 @@
         mScript = new ScriptC_PixelCounter(mRS);
 
         mInPixelsAllocation = createBufferQueueAllocation();
+        mScript.set_BOUNDS(new int[] {boundsToCheck.left, boundsToCheck.top,
+                boundsToCheck.right, boundsToCheck.bottom});
         mScript.set_THRESHOLD(PIXEL_CHANNEL_THRESHOLD);
 
         mInPixelsAllocation.setOnBufferAvailableListener(
diff --git a/tests/tests/view/src/android/view/textclassifier/cts/TextClassificationManagerTest.java b/tests/tests/view/src/android/view/textclassifier/cts/TextClassificationManagerTest.java
index b1d93ab..880cc0d 100644
--- a/tests/tests/view/src/android/view/textclassifier/cts/TextClassificationManagerTest.java
+++ b/tests/tests/view/src/android/view/textclassifier/cts/TextClassificationManagerTest.java
@@ -39,6 +39,10 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class TextClassificationManagerTest {
@@ -123,6 +127,38 @@
         assertFalse(Logger.DISABLED.isSmartSelection("sig.na.ture"));
     }
 
+    @Test
+    public void testResolveEntityListModifications_only_hints() {
+        TextClassifier.EntityConfig entityConfig = TextClassifier.EntityConfig.create(
+                Arrays.asList("some_hint"));
+        assertEquals(1, entityConfig.getHints().size());
+        assertTrue(entityConfig.getHints().contains("some_hint"));
+        assertEquals(Arrays.asList("foo", "bar"),
+                entityConfig.resolveEntityListModifications(Arrays.asList("foo", "bar")));
+    }
+
+    @Test
+    public void testResolveEntityListModifications_include_exclude() {
+        TextClassifier.EntityConfig entityConfig = TextClassifier.EntityConfig.create(
+                Arrays.asList("some_hint"),
+                Arrays.asList("a", "b", "c"),
+                Arrays.asList("b", "d", "x"));
+        assertEquals(1, entityConfig.getHints().size());
+        assertTrue(entityConfig.getHints().contains("some_hint"));
+        assertEquals(new HashSet(Arrays.asList("a", "c", "w")),
+                new HashSet(entityConfig.resolveEntityListModifications(
+                        Arrays.asList("c", "w", "x"))));
+    }
+
+    @Test
+    public void testResolveEntityListModifications_explicit() {
+        TextClassifier.EntityConfig entityConfig =
+                TextClassifier.EntityConfig.createWithEntityList(Arrays.asList("a", "b"));
+        assertEquals(Collections.EMPTY_LIST, entityConfig.getHints());
+        assertEquals(Arrays.asList("a", "b"),
+                entityConfig.resolveEntityListModifications(Arrays.asList("w", "x")));
+    }
+
     private static void assertValidResult(TextSelection selection) {
         assertNotNull(selection);
         assertTrue(selection.getSelectionStartIndex() >= 0);
diff --git a/tests/tests/webkit/Android.mk b/tests/tests/webkit/Android.mk
index a5f01b2..bb70293 100644
--- a/tests/tests/webkit/Android.mk
+++ b/tests/tests/webkit/Android.mk
@@ -42,5 +42,6 @@
 
 # uncomment when dalvik.annotation.Test* are removed or part of SDK
 #LOCAL_SDK_VERSION := current
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java b/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
index f10e7fd..6d61e1c 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
@@ -1030,7 +1030,6 @@
         if (!NullWebViewUtils.isWebViewAvailable()) {
             return;
         }
-        assertFalse(mSettings.getSafeBrowsingEnabled());
         mSettings.setSafeBrowsingEnabled(false);
         assertFalse(mSettings.getSafeBrowsingEnabled());
     }
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
index 7d2d84f..4bedbb1 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
@@ -3072,4 +3072,12 @@
             Assert.fail("The privacy policy URL should be a well-formed URL");
         }
     }
+
+    public void testWebViewClassLoaderReturnsNonNull() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
+        assertNotNull(WebView.getWebViewClassLoader());
+    }
 }
diff --git a/tests/tests/widget/Android.mk b/tests/tests/widget/Android.mk
index f939c43..209f6cb 100644
--- a/tests/tests/widget/Android.mk
+++ b/tests/tests/widget/Android.mk
@@ -35,6 +35,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsWidgetTestCases
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
diff --git a/tests/tests/widget/src/android/widget/cts/MagnifierTest.java b/tests/tests/widget/src/android/widget/cts/MagnifierTest.java
index fc54362..5c7c47e 100644
--- a/tests/tests/widget/src/android/widget/cts/MagnifierTest.java
+++ b/tests/tests/widget/src/android/widget/cts/MagnifierTest.java
@@ -22,11 +22,9 @@
 import static org.junit.Assume.assumeTrue;
 
 import android.app.Activity;
-import android.app.Instrumentation;
 import android.graphics.Bitmap;
 import android.graphics.PointF;
 import android.graphics.Rect;
-import android.support.test.InstrumentationRegistry;
 import android.support.test.annotation.UiThreadTest;
 import android.support.test.filters.SmallTest;
 import android.support.test.rule.ActivityTestRule;
@@ -38,6 +36,7 @@
 import android.widget.Magnifier;
 
 import com.android.compatibility.common.util.PollingCheck;
+import com.android.compatibility.common.util.WidgetTestUtils;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -46,6 +45,8 @@
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Tests for {@link Magnifier}.
@@ -53,7 +54,9 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class MagnifierTest {
-    private Instrumentation mInstrumentation;
+    private static final String TIME_LIMIT_EXCEEDED =
+            "Completing the magnifier operation took too long";
+
     private Activity mActivity;
     private LinearLayout mLayout;
     private Magnifier mMagnifier;
@@ -64,7 +67,6 @@
 
     @Before
     public void setup() {
-        mInstrumentation = InstrumentationRegistry.getInstrumentation();
         mActivity = mActivityRule.getActivity();
         PollingCheck.waitFor(mActivity::hasWindowFocus);
         mLayout = mActivity.findViewById(R.id.magnifier_activity_basic_layout);
@@ -141,25 +143,31 @@
     }
 
     @Test
-    public void testWindowContent() {
+    public void testWindowContent() throws Throwable {
         prepareFourQuadrantsScenario();
+        final CountDownLatch latch = new CountDownLatch(1);
+        mMagnifier.setOnOperationCompleteCallback(latch::countDown);
+
         // Show the magnifier at the center of the activity.
-        mInstrumentation.runOnMainSync(() -> {
+        mActivityRule.runOnUiThread(() -> {
             mMagnifier.show(mLayout.getWidth() / 2, mLayout.getHeight() / 2);
         });
-        mInstrumentation.waitForIdleSync();
+        assertTrue(TIME_LIMIT_EXCEEDED, latch.await(1, TimeUnit.SECONDS));
 
         assertFourQuadrants(mMagnifier.getContent());
     }
 
     @Test
-    public void testWindowPosition() {
+    public void testWindowPosition() throws Throwable {
         prepareFourQuadrantsScenario();
+        final CountDownLatch latch = new CountDownLatch(1);
+        mMagnifier.setOnOperationCompleteCallback(latch::countDown);
+
         // Show the magnifier at the center of the activity.
-        mInstrumentation.runOnMainSync(() -> {
+        mActivityRule.runOnUiThread(() -> {
             mMagnifier.show(mLayout.getWidth() / 2, mLayout.getHeight() / 2);
         });
-        mInstrumentation.waitForIdleSync();
+        assertTrue(TIME_LIMIT_EXCEEDED, latch.await(1, TimeUnit.SECONDS));
 
         // Assert that the magnifier position represents a valid rectangle on screen.
         final Rect position = mMagnifier.getWindowPositionOnScreen();
@@ -169,27 +177,33 @@
     }
 
     @Test
-    public void testWindowContent_modifiesAfterUpdate() {
+    public void testWindowContent_modifiesAfterUpdate() throws Throwable {
         prepareFourQuadrantsScenario();
+
         // Show the magnifier at the center of the activity.
-        mInstrumentation.runOnMainSync(() -> {
+        final CountDownLatch latchForShow = new CountDownLatch(1);
+        mMagnifier.setOnOperationCompleteCallback(latchForShow::countDown);
+        mActivityRule.runOnUiThread(() -> {
             mMagnifier.show(mLayout.getWidth() / 2, mLayout.getHeight() / 2);
         });
-        mInstrumentation.waitForIdleSync();
+        assertTrue(TIME_LIMIT_EXCEEDED, latchForShow.await(1, TimeUnit.SECONDS));
 
         final Bitmap initialBitmap = mMagnifier.getContent()
                 .copy(mMagnifier.getContent().getConfig(), true);
         assertFourQuadrants(initialBitmap);
 
         // Make the one quadrant white.
-        mInstrumentation.runOnMainSync(() -> {
-            mActivity.findViewById(R.id.magnifier_activity_four_quadrants_layout_quadrant_1)
-                    .setBackground(null);
+        final View quadrant1 =
+                mActivity.findViewById(R.id.magnifier_activity_four_quadrants_layout_quadrant_1);
+        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, quadrant1, () -> {
+            quadrant1.setBackground(null);
         });
-        mInstrumentation.waitForIdleSync();
+
         // Update the magnifier.
-        mInstrumentation.runOnMainSync(mMagnifier::update);
-        mInstrumentation.waitForIdleSync();
+        final CountDownLatch latchForUpdate = new CountDownLatch(1);
+        mMagnifier.setOnOperationCompleteCallback(latchForUpdate::countDown);
+        mActivityRule.runOnUiThread(mMagnifier::update);
+        assertTrue(TIME_LIMIT_EXCEEDED, latchForUpdate.await(1, TimeUnit.SECONDS));
 
         final Bitmap newBitmap = mMagnifier.getContent();
         assertFourQuadrants(newBitmap);
@@ -200,13 +214,13 @@
      * Sets the activity to contain four equal quadrants coloured differently and
      * instantiates a magnifier. This method should not be called on the UI thread.
      */
-    private void prepareFourQuadrantsScenario() {
-        mInstrumentation.runOnMainSync(() -> {
+    private void prepareFourQuadrantsScenario() throws Throwable {
+        WidgetTestUtils.runOnMainAndLayoutSync(mActivityRule, () -> {
             mActivity.setContentView(R.layout.magnifier_activity_four_quadrants_layout);
             mLayout = mActivity.findViewById(R.id.magnifier_activity_four_quadrants_layout);
             mMagnifier = new Magnifier(mLayout);
-        });
-        mInstrumentation.waitForIdleSync();
+        }, false);
+        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mLayout, null);
     }
 
     /**
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index 992f05e..3843780 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -86,7 +86,7 @@
 import android.text.InputFilter;
 import android.text.InputType;
 import android.text.Layout;
-import android.text.MeasuredText;
+import android.text.PrecomputedText;
 import android.text.Selection;
 import android.text.Spannable;
 import android.text.SpannableString;
@@ -1637,12 +1637,10 @@
 
     @UiThreadTest
     @Test
-    public void testSetText_MeasuredText() {
+    public void testSetText_PrecomputedText() {
         final TextView tv = findTextView(R.id.textview_text);
-        final MeasuredText measured = new MeasuredText.Builder(
-                "This is an example text.", new TextPaint())
-                .setBreakStrategy(tv.getBreakStrategy())
-                .setHyphenationFrequency(tv.getHyphenationFrequency()).build();
+        final PrecomputedText measured = PrecomputedText.create(
+                "This is an example text.", tv.getTextMetricsParams());
         tv.setText(measured);
         assertEquals(measured.toString(), tv.getText().toString());
     }
@@ -8026,6 +8024,28 @@
         assertTrue(mTextView.isFallbackLineSpacing());
     }
 
+    @UiThreadTest
+    @Test
+    public void testTextLayoutParam() {
+        mActivity.setContentView(R.layout.textview_fallbacklinespacing_layout);
+        mTextView = findTextView(R.id.textview_default);
+        PrecomputedText.Params param = mTextView.getTextMetricsParams();
+
+        assertEquals(mTextView.getBreakStrategy(), param.getBreakStrategy());
+        assertEquals(mTextView.getHyphenationFrequency(), param.getHyphenationFrequency());
+
+        assertTrue(param.equals(mTextView.getTextMetricsParams()));
+
+        mTextView.setBreakStrategy(
+                mTextView.getBreakStrategy() == Layout.BREAK_STRATEGY_SIMPLE
+                ?  Layout.BREAK_STRATEGY_BALANCED : Layout.BREAK_STRATEGY_SIMPLE);
+
+        assertFalse(param.equals(mTextView.getTextMetricsParams()));
+
+        mTextView.setTextMetricsParams(param);
+        assertTrue(param.equals(mTextView.getTextMetricsParams()));
+    }
+
     private void initializeTextForSmartSelection(CharSequence text) throws Throwable {
         assertTrue(text.length() >= SMARTSELECT_END);
         mActivityRule.runOnUiThread(() -> {
diff --git a/tests/tests/widget/src/android/widget/cts/TimePickerTest.java b/tests/tests/widget/src/android/widget/cts/TimePickerTest.java
index ce093e7..0886aa3 100644
--- a/tests/tests/widget/src/android/widget/cts/TimePickerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TimePickerTest.java
@@ -553,6 +553,12 @@
         prepareForKeyboardInput(initialHour, initialMinute, false /* is24hFormat */,
                 false /* isClockMode */);
 
+        // when testing on device with lower resolution, the Spinner mode time picker may not show
+        // completely, which will cause case fail, so in this case remove the clock time picker to
+        // focus on the test of Spinner mode
+        final TimePicker clock = mActivity.findViewById(R.id.timepicker_clock);
+        mActivityRule.runOnUiThread(() -> clock.setVisibility(View.GONE));
+
         assertEquals(initialHour, mTimePicker.getHour());
         mActivityRule.runOnUiThread(() -> mTimePicker.getHourView().requestFocus());
         mInstrumentation.waitForIdleSync();
@@ -665,6 +671,12 @@
         prepareForKeyboardInput(initialHour, initialMinute, true /* is24hFormat */,
                 false /* isClockMode */);
 
+        // when testing on device with lower resolution, the Spinner mode time picker may not show
+        // completely, which will cause case fail, so in this case remove the clock time picker to
+        // focus on the test of Spinner mode
+        final TimePicker clock = mActivity.findViewById(R.id.timepicker_clock);
+        mActivityRule.runOnUiThread(() -> clock.setVisibility(View.GONE));
+
         assertEquals(initialHour, mTimePicker.getHour());
         mActivityRule.runOnUiThread(() -> mTimePicker.getHourView().requestFocus());
         mInstrumentation.waitForIdleSync();
diff --git a/tools/cts-tradefed/res/config/retry.xml b/tools/cts-tradefed/res/config/retry.xml
index e488410..d425d8e 100644
--- a/tools/cts-tradefed/res/config/retry.xml
+++ b/tools/cts-tradefed/res/config/retry.xml
@@ -14,6 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Runs a retry of a previous CTS session.">
+    <option name="dynamic-sharding" value="true" />
+    <option name="disable-strict-sharding" value="true" />
 
     <device_recovery class="com.android.tradefed.device.WaitDeviceRecovery" />
     <build_provider class="com.android.compatibility.common.tradefed.build.CompatibilityBuildProvider" />
@@ -21,6 +23,8 @@
 
     <option name="compatibility:test-arg" value="com.android.tradefed.testtype.AndroidJUnitTest:rerun-from-file:true" />
     <option name="compatibility:test-arg" value="com.android.tradefed.testtype.AndroidJUnitTest:fallback-to-serial-rerun:false" />
+    <option name="compatibility:test-arg" value="com.android.compatibility.testtype.LibcoreTest:rerun-from-file:true" />
+    <option name="compatibility:test-arg" value="com.android.compatibility.testtype.LibcoreTest:fallback-to-serial-rerun:false" />
 
     <logger class="com.android.tradefed.log.FileLogger">
         <option name="log-level-display" value="WARN" />
@@ -36,6 +40,16 @@
     <option name="skip-device-info" value="true" />
     <option name="enable-root" value="false" />
 
+    <!-- retain 200MB of host log -->
+    <option name="max-log-size" value="200" />
+    <!--  retain 200MB of logcat -->
+    <option name="max-tmp-logcat-file" value="209715200" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="run-command" value="settings put global package_verifier_enable 0" />
+        <option name="teardown-command" value="settings put global package_verifier_enable 1"/>
+    </target_preparer>
+
     <result_reporter class="com.android.compatibility.common.tradefed.result.ConsoleReporter" />
     <result_reporter class="com.android.compatibility.common.tradefed.result.ResultReporter" />
 
diff --git a/tools/device-setup/TestDeviceSetup/Android.mk b/tools/device-setup/TestDeviceSetup/Android.mk
index edb85d2..1820347 100644
--- a/tools/device-setup/TestDeviceSetup/Android.mk
+++ b/tools/device-setup/TestDeviceSetup/Android.mk
@@ -27,6 +27,7 @@
 
 # uncomment when b/13282254 is fixed
 #LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := system_current
 
 LOCAL_PACKAGE_NAME := TestDeviceSetup