Merge "cts: Set LOCAL_SDK_VERSION where possible."
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/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/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/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 0e02c02..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/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/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/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/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/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/DeviceAtomTestCase.java b/hostsidetests/statsd/src/android/cts/statsd/atom/DeviceAtomTestCase.java
index c0f194c..c3c209f 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/DeviceAtomTestCase.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/DeviceAtomTestCase.java
@@ -178,10 +178,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/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/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/autofillservice/src/android/autofillservice/cts/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
index 4d11050..7592408 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/Helper.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
@@ -730,6 +730,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() {
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
index 6137b4b..95718ba 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
@@ -33,6 +33,7 @@
 import static android.autofillservice.cts.Helper.assertValue;
 import static android.autofillservice.cts.Helper.dumpStructure;
 import static android.autofillservice.cts.Helper.findNodeByResourceId;
+import static android.autofillservice.cts.Helper.getContext;
 import static android.autofillservice.cts.Helper.setUserComplete;
 import static android.autofillservice.cts.InstrumentedAutoFillService.SERVICE_CLASS;
 import static android.autofillservice.cts.InstrumentedAutoFillService.SERVICE_PACKAGE;
@@ -113,10 +114,12 @@
             new AutofillActivityTestRule<CheckoutActivity>(CheckoutActivity.class, false);
 
     private LoginActivity mActivity;
+    private boolean mCanPassKeys;
 
     @Before
     public void setActivity() {
         mActivity = mActivityRule.getActivity();
+        mCanPassKeys = !Helper.isAutofillWindowFullScreen(getContext());
     }
 
     /**
@@ -1184,6 +1187,66 @@
     }
 
     @Test
+    public void keyboardFilterResult() 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 filterText() throws Exception {
         final String AA = "Two A's";
         final String AB = "A and B";
diff --git a/tests/framework/base/activitymanager/Android.mk b/tests/framework/base/activitymanager/Android.mk
index 65fda92..25cfd6b 100644
--- a/tests/framework/base/activitymanager/Android.mk
+++ b/tests/framework/base/activitymanager/Android.mk
@@ -27,6 +27,7 @@
     $(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 30346bb..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
@@ -25,6 +25,7 @@
             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 =
@@ -74,12 +75,15 @@
     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");
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/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/ActivityManagerAppConfigurationTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAppConfigurationTests.java
index 7874080..59a2509 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAppConfigurationTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAppConfigurationTests.java
@@ -51,6 +51,7 @@
 import android.platform.test.annotations.Presubmit;
 import android.support.test.filters.FlakyTest;
 
+import org.junit.Ignore;
 import org.junit.Test;
 
 import java.util.ArrayList;
@@ -371,7 +372,8 @@
     }
 
     // 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
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 d3f3ee3..ab1a820 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerConfigChangeTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerConfigChangeTests.java
@@ -79,6 +79,7 @@
         testChangeFontScale(FONT_SCALE_ACTIVITY, true /* relaunch */);
     }
 
+    @FlakyTest(bugId = 73812451)
     @Presubmit
     @Test
     public void testChangeFontScaleNoRelaunch() throws Exception {
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 9c81e59..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,6 +20,9 @@
 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;
@@ -248,8 +251,8 @@
             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 "
+            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);
 
@@ -1464,8 +1467,9 @@
             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
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 c7e7381..b8885ac 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java
@@ -244,6 +244,7 @@
 
     @Test
     @Presubmit
+    @FlakyTest(bugId = 73808815)
     public void testLaunchToSideSingleInstance() throws Exception {
         launchTargetToSide(SINGLE_INSTANCE_ACTIVITY, false);
     }
@@ -482,6 +483,7 @@
         }
     }
 
+    @FlakyTest(bugId = 73813034)
     @Test
     @Presubmit
     public void testFinishDockActivityWhileMinimized() throws Exception {
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/AnimationBackgroundTests.java b/tests/framework/base/activitymanager/src/android/server/am/AnimationBackgroundTests.java
index fb56ce7..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_NAME, 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_NAME, 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/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..a70bc79 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,6 +1,7 @@
 package android.server.am.lifecycle;
 
 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.RESUMED;
 import static android.support.test.runner.lifecycle.Stage.STOPPED;
 
@@ -60,7 +61,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 +69,38 @@
         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);
     }
 }
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..094ce72 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,22 @@
     }
 
     static void assertRelaunchSequence(Class<? extends Activity> activityClass,
-            LifecycleLog lifecycleLog) {
+            LifecycleLog lifecycleLog, Stage startState) {
         final List<Stage> observedTransitions = lifecycleLog.getActivityLog(activityClass);
         log("Observed sequence: " + observedTransitions);
         final String errorMessage = errorDuringTransition(activityClass, "relaunch");
 
-        final List<Stage> expectedTransitions =
-                Arrays.asList(PAUSED, STOPPED, DESTROYED, PRE_ON_CREATE, CREATED, STARTED, RESUMED);
+        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);
+        }
         assertEquals(errorMessage, expectedTransitions, observedTransitions);
     }
 
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/ActivityManagerTestBase.java b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerTestBase.java
index 9ff84cb..18bbb5b 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;
@@ -58,6 +72,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.graphics.Bitmap;
+import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
 import android.os.SystemClock;
 import android.provider.Settings;
@@ -504,16 +519,10 @@
     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;
@@ -523,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,
@@ -1462,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;
@@ -1521,11 +1531,13 @@
         @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;
         }
 
@@ -1534,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;
         }
 
@@ -1548,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.
@@ -1566,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(mTargetActivityName));
-            }
         }
     }
 }
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/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/InputMethodServiceTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
index da6cacf..0754e7f 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
@@ -33,6 +33,7 @@
 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;
@@ -40,6 +41,7 @@
 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;
@@ -50,6 +52,7 @@
 
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
+import java.util.function.Predicate;
 
 /**
  * Tests for {@link InputMethodService} methods.
@@ -62,6 +65,23 @@
 
     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();
@@ -102,6 +122,10 @@
                     (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);
 
@@ -136,6 +160,10 @@
                     (long) getOnMainSync(() -> testActivity.getOnBackPressedCallCount()));
             mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
 
+            // InputMethodService#onKeyDown() will not handle back key event.
+            // TODO: Also check InputMethodService#requestHideSelf()
+            expectEvent(stream, backKeyDownMatcher(false), TIMEOUT);
+
             // keyboard will not hide
             notExpectEvent(stream, event -> "hideSoftInput".equals(event.getEventName()),
                     EXPECTED_TIMEOUT);
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-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/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/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/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/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
index 110534f..d90179a 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;
@@ -209,6 +210,16 @@
         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/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/drawable/cts/AnimatedImageDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedImageDrawableTest.java
index b87fd92..4fb6e19 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedImageDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedImageDrawableTest.java
@@ -90,6 +90,11 @@
         mActivity = mActivityRule.getActivity();
     }
 
+    @Test
+    public void testEmptyConstructor() {
+        new AnimatedImageDrawable();
+    }
+
     private AnimatedImageDrawable createFromImageDecoder(int resId) {
         Uri uri = null;
         try {
@@ -504,4 +509,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/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/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 9a3b940..6af1d56 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -526,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/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/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/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/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/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/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" />