Revert "Configurable verifier suite name." am: d13a2e327f am: 1071ca5ab3
am: e67205ad70

Change-Id: Iefdcf1b2c9499d7053fddf2098901f27a960c1a3
diff --git a/.gitignore b/.gitignore
index 07a80d6..dbd5bcf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,5 @@
 /bin
 .idea/*
 .idea/
+gen/
+*.iml
diff --git a/apps/CameraITS/build/envsetup.sh b/apps/CameraITS/build/envsetup.sh
index bcf294a..03b45d1 100644
--- a/apps/CameraITS/build/envsetup.sh
+++ b/apps/CameraITS/build/envsetup.sh
@@ -17,7 +17,7 @@
 # and that the unit tests for the modules passed (indicating that the setup
 # is correct).
 
-CAMERA_ITS_TOP=$PWD
+export CAMERA_ITS_TOP=$PWD
 
 [[ "${BASH_SOURCE[0]}" != "${0}" ]] || \
     { echo ">> Script must be sourced with 'source $0'" >&2; exit 1; }
@@ -31,12 +31,23 @@
 python -V 2>&1 | grep -q "Python 2.7" || \
     echo ">> Require python 2.7" >&2
 
-for M in numpy PIL Image matplotlib pylab cv2 scipy.stats scipy.spatial
+for M in numpy PIL Image matplotlib pylab scipy.stats scipy.spatial
 do
     python -c "import $M" >/dev/null 2>&1 || \
         echo ">> Require Python $M module" >&2
 done
 
+CV2_VER=$(python -c "\
+try:
+    import cv2
+    print cv2.__version__
+except:
+    print \"N/A\"
+")
+
+echo $CV2_VER | grep -q "^2.4" || \
+    echo ">> Require python opencv 2.4. Got $CV2_VER" >&2
+
 export PYTHONPATH="$PWD/pymodules:$PYTHONPATH"
 
 for M in device objects image caps dng target error
diff --git a/apps/CameraITS/pymodules/its/caps.py b/apps/CameraITS/pymodules/its/caps.py
index a33757d..d9270f7 100644
--- a/apps/CameraITS/pymodules/its/caps.py
+++ b/apps/CameraITS/pymodules/its/caps.py
@@ -394,6 +394,59 @@
             "android.edge.availableEdgeModes") and mode \
             in props["android.edge.availableEdgeModes"];
 
+
+def lens_calibrated(props):
+    """Returns whether lens position is calibrated or not.
+
+    android.lens.info.focusDistanceCalibration has 3 modes.
+    0: Uncalibrated
+    1: Approximate
+    2: Calibrated
+
+    Args:
+        props: Camera properties objects.
+
+    Returns:
+        Boolean.
+    """
+    return props.has_key("android.lens.info.focusDistanceCalibration") and \
+         props["android.lens.info.focusDistanceCalibration"] == 2
+
+
+def lens_approx_calibrated(props):
+    """Returns whether lens position is calibrated or not.
+
+    android.lens.info.focusDistanceCalibration has 3 modes.
+    0: Uncalibrated
+    1: Approximate
+    2: Calibrated
+
+    Args:
+        props: Camera properties objects.
+
+    Returns:
+        Boolean.
+    """
+    return props.has_key("android.lens.info.focusDistanceCalibration") and \
+        (props["android.lens.info.focusDistanceCalibration"] == 1 or
+         props["android.lens.info.focusDistanceCalibration"] == 2)
+
+
+def fixed_focus(props):
+    """Returns whether a device is fixed focus.
+
+    props[android.lens.info.minimumFocusDistance] == 0 is fixed focus
+
+    Args:
+        props: Camera properties objects.
+
+    Returns:
+        Boolean.
+    """
+    return props.has_key("android.lens.info.minimumFocusDistance") and \
+        props["android.lens.info.minimumFocusDistance"] == 0
+
+
 class __UnitTest(unittest.TestCase):
     """Run a suite of unit tests on this module.
     """
diff --git a/apps/CameraITS/pymodules/its/device.py b/apps/CameraITS/pymodules/its/device.py
index 351b03c..3b378cc 100644
--- a/apps/CameraITS/pymodules/its/device.py
+++ b/apps/CameraITS/pymodules/its/device.py
@@ -67,9 +67,17 @@
     PACKAGE = 'com.android.cts.verifier.camera.its'
     INTENT_START = 'com.android.cts.verifier.camera.its.START'
     ACTION_ITS_RESULT = 'com.android.cts.verifier.camera.its.ACTION_ITS_RESULT'
+    EXTRA_VERSION = 'camera.its.extra.VERSION'
+    CURRENT_ITS_VERSION = '1.0' # version number to sync with CtsVerifier
     EXTRA_CAMERA_ID = 'camera.its.extra.CAMERA_ID'
-    EXTRA_SUCCESS = 'camera.its.extra.SUCCESS'
-    EXTRA_SUMMARY = 'camera.its.extra.SUMMARY'
+    EXTRA_RESULTS = 'camera.its.extra.RESULTS'
+
+    RESULT_PASS = 'PASS'
+    RESULT_FAIL = 'FAIL'
+    RESULT_NOT_EXECUTED = 'NOT_EXECUTED'
+    RESULT_VALUES = {RESULT_PASS, RESULT_FAIL, RESULT_NOT_EXECUTED}
+    RESULT_KEY = 'result'
+    SUMMARY_KEY = 'summary'
 
     adb = "adb -d"
     device_id = ""
@@ -746,15 +754,24 @@
     Return the device ID provided in the command line if it's connected. If no
     device ID is provided in the command line and there is only one device
     connected, return the device ID by parsing the result of "adb devices".
+    Also, if the environment variable ANDROID_SERIAL is set, use it as device
+    id. When both ANDROID_SERIAL and device argument present, device argument
+    takes priority.
 
     Raise an exception if no device is connected; or the device ID provided in
     the command line is not connected; or no device ID is provided in the
-    command line and there are more than 1 device connected.
+    command line or environment variable and there are more than 1 device
+    connected.
 
     Returns:
         Device ID string.
     """
     device_id = None
+
+    # Check if device id is set in env
+    if "ANDROID_SERIAL" in os.environ:
+        device_id = os.environ["ANDROID_SERIAL"]
+
     for s in sys.argv[1:]:
         if s[:7] == "device=" and len(s) > 7:
             device_id = str(s[7:])
@@ -781,34 +798,43 @@
 
     return device_id
 
-def report_result(device_id, camera_id, success, summary_path=None):
+def report_result(device_id, camera_id, results):
     """Send a pass/fail result to the device, via an intent.
 
     Args:
         device_id: The ID string of the device to report the results to.
         camera_id: The ID string of the camera for which to report pass/fail.
-        success: Boolean, indicating if the result was pass or fail.
-        summary_path: (Optional) path to ITS summary file on host PC
-
+        results: a dictionary contains all ITS scenes as key and result/summary
+                 of current ITS run. See test_report_result unit test for
+                 an example.
     Returns:
         Nothing.
     """
     adb = "adb -s " + device_id
-    device_summary_path = "/sdcard/camera_" + camera_id + "_its_summary.txt"
-    if summary_path is not None:
-        _run("%s push %s %s" % (
-                adb, summary_path, device_summary_path))
-        _run("%s shell am broadcast -a %s --es %s %s --es %s %s --es %s %s" % (
-                adb, ItsSession.ACTION_ITS_RESULT,
-                ItsSession.EXTRA_CAMERA_ID, camera_id,
-                ItsSession.EXTRA_SUCCESS, 'True' if success else 'False',
-                ItsSession.EXTRA_SUMMARY, device_summary_path))
-    else:
-        _run("%s shell am broadcast -a %s --es %s %s --es %s %s --es %s %s" % (
-                adb, ItsSession.ACTION_ITS_RESULT,
-                ItsSession.EXTRA_CAMERA_ID, camera_id,
-                ItsSession.EXTRA_SUCCESS, 'True' if success else 'False',
-                ItsSession.EXTRA_SUMMARY, "null"))
+    # Validate/process results argument
+    for scene in results:
+        result_key = ItsSession.RESULT_KEY
+        summary_key = ItsSession.SUMMARY_KEY
+        if result_key not in results[scene]:
+            raise its.error.Error('ITS result not found for ' + scene)
+        if results[scene][result_key] not in ItsSession.RESULT_VALUES:
+            raise its.error.Error('Unknown ITS result for %s: %s' % (
+                    scene, results[result_key]))
+        if summary_key in results[scene]:
+            device_summary_path = "/sdcard/its_camera%s_%s.txt" % (
+                    camera_id, scene)
+            _run("%s push %s %s" % (
+                    adb, results[scene][summary_key], device_summary_path))
+            results[scene][summary_key] = device_summary_path
+    json_results = json.dumps(results)
+    cmd = "%s shell am broadcast -a %s --es %s %s --es %s %s --es %s \'%s\'" % (
+            adb, ItsSession.ACTION_ITS_RESULT,
+            ItsSession.EXTRA_VERSION, ItsSession.CURRENT_ITS_VERSION,
+            ItsSession.EXTRA_CAMERA_ID, camera_id,
+            ItsSession.EXTRA_RESULTS, json_results)
+    if len(cmd) > 4095:
+        print "ITS command string might be too long! len:", len(cmd)
+    _run(cmd)
 
 def _run(cmd):
     """Replacement for os.system, with hiding of stdout+stderr messages.
@@ -821,8 +847,20 @@
     """Run a suite of unit tests on this module.
     """
 
-    # TODO: Add some unit tests.
-    None
+    """
+    # TODO: this test currently needs connected device to pass
+    #       Need to remove that dependency before enabling the test
+    def test_report_result(self):
+        device_id = get_device_id()
+        camera_id = "1"
+        result_key = ItsSession.RESULT_KEY
+        results = {"scene0":{result_key:"PASS"},
+                   "scene1":{result_key:"PASS"},
+                   "scene2":{result_key:"PASS"},
+                   "scene3":{result_key:"PASS"},
+                   "sceneNotExist":{result_key:"FAIL"}}
+        report_result(device_id, camera_id, results)
+    """
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/apps/CameraITS/tests/scene0/test_metadata.py b/apps/CameraITS/tests/scene0/test_metadata.py
index ed1426b..e5fbba5 100644
--- a/apps/CameraITS/tests/scene0/test_metadata.py
+++ b/apps/CameraITS/tests/scene0/test_metadata.py
@@ -97,9 +97,12 @@
         print "Assert field of view: %.1f degrees" % fov
         assert 30 <= fov <= 130
 
-        hyperfocal = 1.0 / props["android.lens.info.hyperfocalDistance"]
-        print "Assert hyperfocal distance: %.2f m" % hyperfocal
-        assert 0.02 <= hyperfocal
+        if its.caps.lens_approx_calibrated(props):
+            diopter_hyperfocal = props["android.lens.info.hyperfocalDistance"]
+            if diopter_hyperfocal != 0.0:
+                hyperfocal = 1.0 / diopter_hyperfocal
+                print "Assert hyperfocal distance: %.2f m" % hyperfocal
+                assert 0.02 <= hyperfocal
 
 
 def getval(expr, default=None):
diff --git a/apps/CameraITS/tests/scene1/scene1.pdf b/apps/CameraITS/tests/scene1/scene1.pdf
new file mode 100644
index 0000000..7e47bcf
--- /dev/null
+++ b/apps/CameraITS/tests/scene1/scene1.pdf
Binary files differ
diff --git a/apps/CameraITS/tests/scene1/test_capture_result.py b/apps/CameraITS/tests/scene1/test_capture_result.py
index ec919f8..cde37c2 100644
--- a/apps/CameraITS/tests/scene1/test_capture_result.py
+++ b/apps/CameraITS/tests/scene1/test_capture_result.py
@@ -77,11 +77,11 @@
         h_map = props["android.lens.info.shadingMapSize"]["height"]
 
         print "Testing auto capture results"
-        lsc_map_auto = test_auto(cam, w_map, h_map)
+        lsc_map_auto = test_auto(cam, w_map, h_map, props)
         print "Testing manual capture results"
-        test_manual(cam, w_map, h_map, lsc_map_auto)
+        test_manual(cam, w_map, h_map, lsc_map_auto, props)
         print "Testing auto capture results again"
-        test_auto(cam, w_map, h_map)
+        test_auto(cam, w_map, h_map, props)
 
 # A very loose definition for two floats being close to each other;
 # there may be different interpolation and rounding used to get the
@@ -105,7 +105,7 @@
         ax.plot_wireframe(xs, ys, zs)
         matplotlib.pyplot.savefig("%s_plot_lsc_%s_ch%d.png"%(NAME,name,ch))
 
-def test_auto(cam, w_map, h_map):
+def test_auto(cam, w_map, h_map, props):
     # Get 3A lock first, so the auto values in the capture result are
     # populated properly.
     rect = [[0,0,1,1,1]]
@@ -124,9 +124,12 @@
     print "Gains:", gains
     print "Transform:", [its.objects.rational_to_float(t)
                          for t in transform]
-    print "AE region:", cap_res['android.control.aeRegions']
-    print "AF region:", cap_res['android.control.afRegions']
-    print "AWB region:", cap_res['android.control.awbRegions']
+    if props["android.control.maxRegionsAe"] > 0:
+        print "AE region:", cap_res['android.control.aeRegions']
+    if props["android.control.maxRegionsAf"] > 0:
+        print "AF region:", cap_res['android.control.afRegions']
+    if props["android.control.maxRegionsAwb"] > 0:
+        print "AWB region:", cap_res['android.control.awbRegions']
     print "LSC map:", w_map, h_map, lsc_map[:8]
 
     assert(ctrl_mode == 1)
@@ -154,7 +157,7 @@
 
     return lsc_map
 
-def test_manual(cam, w_map, h_map, lsc_map_auto):
+def test_manual(cam, w_map, h_map, lsc_map_auto, props):
     cap = cam.do_capture(manual_req)
     cap_res = cap["metadata"]
 
@@ -172,9 +175,12 @@
     print "Transform:", [its.objects.rational_to_float(t)
                          for t in transform]
     print "Tonemap:", curves[0][1::16]
-    print "AE region:", cap_res['android.control.aeRegions']
-    print "AF region:", cap_res['android.control.afRegions']
-    print "AWB region:", cap_res['android.control.awbRegions']
+    if props["android.control.maxRegionsAe"] > 0:
+        print "AE region:", cap_res['android.control.aeRegions']
+    if props["android.control.maxRegionsAf"] > 0:
+        print "AF region:", cap_res['android.control.afRegions']
+    if props["android.control.maxRegionsAwb"] > 0:
+        print "AWB region:", cap_res['android.control.awbRegions']
     print "LSC map:", w_map, h_map, lsc_map[:8]
 
     assert(ctrl_mode == 0)
diff --git a/apps/CameraITS/tests/scene1/test_ev_compensation_basic.py b/apps/CameraITS/tests/scene1/test_ev_compensation_basic.py
index 49ccbcf..cb69607 100644
--- a/apps/CameraITS/tests/scene1/test_ev_compensation_basic.py
+++ b/apps/CameraITS/tests/scene1/test_ev_compensation_basic.py
@@ -20,10 +20,14 @@
 import pylab
 import matplotlib
 import matplotlib.pyplot
-import numpy
+import numpy as np
 
 #AE must converge within this number of auto requests for EV
-THREASH_CONVERGE_FOR_EV = 8
+THRESH_CONVERGE_FOR_EV = 8
+YUV_FULL_SCALE = 255.0
+YUV_SATURATION_MIN = 253.0
+YUV_SATURATION_TOL = 1.0
+
 
 def main():
     """Tests that EV compensation is applied.
@@ -42,6 +46,9 @@
         steps_per_ev = int(1.0 / ev_per_step)
         evs = range(-2 * steps_per_ev, 2 * steps_per_ev + 1, steps_per_ev)
         lumas = []
+        reds = []
+        greens = []
+        blues = []
 
         # Converge 3A, and lock AE once converged. skip AF trigger as
         # dark/bright scene could make AF convergence fail and this test
@@ -54,24 +61,43 @@
             req = its.objects.auto_capture_request()
             req['android.control.aeExposureCompensation'] = ev
             req["android.control.aeLock"] = True
-            caps = cam.do_capture([req]*THREASH_CONVERGE_FOR_EV)
+            caps = cam.do_capture([req]*THRESH_CONVERGE_FOR_EV)
             for cap in caps:
                 if (cap['metadata']['android.control.aeState'] == LOCKED):
                     y = its.image.convert_capture_to_planes(cap)[0]
                     tile = its.image.get_image_patch(y, 0.45,0.45,0.1,0.1)
                     lumas.append(its.image.compute_image_means(tile)[0])
+                    rgb = its.image.convert_capture_to_rgb_image(cap)
+                    rgb_tile = its.image.get_image_patch(rgb,
+                                                       0.45, 0.45, 0.1, 0.1)
+                    rgb_means = its.image.compute_image_means(rgb_tile)
+                    reds.append(rgb_means[0])
+                    greens.append(rgb_means[1])
+                    blues.append(rgb_means[2])
                     break
             assert(cap['metadata']['android.control.aeState'] == LOCKED)
 
-        pylab.plot(evs, lumas, 'r')
+        pylab.plot(evs, lumas, '-ro')
+        pylab.xlabel('EV Compensation')
+        pylab.ylabel('Mean Luma (Normalized)')
         matplotlib.pyplot.savefig("%s_plot_means.png" % (NAME))
 
-        # trim trailing 1.0s (for saturated image)
-        while lumas and lumas[-1] == 1.0:
-            lumas.pop(-1)
+        # Trim extra saturated images
+        while lumas and lumas[-1] >= YUV_SATURATION_MIN/YUV_FULL_SCALE:
+            if (np.isclose(reds[-1], greens[-1],
+                           YUV_SATURATION_TOL/YUV_FULL_SCALE) and
+                    np.isclose(blues[-1], greens[-1],
+                               YUV_SATURATION_TOL/YUV_FULL_SCALE)):
+                lumas.pop(-1)
+                reds.pop(-1)
+                greens.pop(-1)
+                blues.pop(-1)
+                print 'Removed saturated image.'
+            else:
+                break
         # Only allow positive EVs to give saturated image
         assert(len(lumas) > 2)
-        luma_diffs = numpy.diff(lumas)
+        luma_diffs = np.diff(lumas)
         min_luma_diffs = min(luma_diffs)
         print "Min of the luma value difference between adjacent ev comp: ", \
                 min_luma_diffs
diff --git a/apps/CameraITS/tests/scene1/test_yuv_plus_raw.py b/apps/CameraITS/tests/scene1/test_yuv_plus_raw.py
index a5ceaba..10e100d 100644
--- a/apps/CameraITS/tests/scene1/test_yuv_plus_raw.py
+++ b/apps/CameraITS/tests/scene1/test_yuv_plus_raw.py
@@ -51,11 +51,11 @@
         tile = its.image.get_image_patch(img, 0.45, 0.45, 0.1, 0.1)
         rgb0 = its.image.compute_image_means(tile)
 
-        # Raw shots are 1/2 x 1/2 smaller after conversion to RGB, so scale the
-        # tile appropriately.
+        # Raw shots are 1/2 x 1/2 smaller after conversion to RGB, but tile
+        # cropping is relative.
         img = its.image.convert_capture_to_rgb_image(cap_raw, props=props)
         its.image.write_image(img, "%s_raw.jpg" % (NAME), True)
-        tile = its.image.get_image_patch(img, 0.475, 0.475, 0.05, 0.05)
+        tile = its.image.get_image_patch(img, 0.45, 0.45, 0.1, 0.1)
         rgb1 = its.image.compute_image_means(tile)
 
         rms_diff = math.sqrt(
diff --git a/apps/CameraITS/tests/scene1/test_yuv_plus_raw10.py b/apps/CameraITS/tests/scene1/test_yuv_plus_raw10.py
index f281089..be5f701 100644
--- a/apps/CameraITS/tests/scene1/test_yuv_plus_raw10.py
+++ b/apps/CameraITS/tests/scene1/test_yuv_plus_raw10.py
@@ -51,11 +51,11 @@
         tile = its.image.get_image_patch(img, 0.45, 0.45, 0.1, 0.1)
         rgb0 = its.image.compute_image_means(tile)
 
-        # Raw shots are 1/2 x 1/2 smaller after conversion to RGB, so scale the
-        # tile appropriately.
+        # Raw shots are 1/2 x 1/2 smaller after conversion to RGB, but tile
+        # cropping is relative.
         img = its.image.convert_capture_to_rgb_image(cap_raw, props=props)
         its.image.write_image(img, "%s_raw.jpg" % (NAME), True)
-        tile = its.image.get_image_patch(img, 0.475, 0.475, 0.05, 0.05)
+        tile = its.image.get_image_patch(img, 0.45, 0.45, 0.1, 0.1)
         rgb1 = its.image.compute_image_means(tile)
 
         rms_diff = math.sqrt(
diff --git a/apps/CameraITS/tests/scene1/test_yuv_plus_raw12.py b/apps/CameraITS/tests/scene1/test_yuv_plus_raw12.py
index 5b6051a..8070785 100644
--- a/apps/CameraITS/tests/scene1/test_yuv_plus_raw12.py
+++ b/apps/CameraITS/tests/scene1/test_yuv_plus_raw12.py
@@ -51,11 +51,11 @@
         tile = its.image.get_image_patch(img, 0.45, 0.45, 0.1, 0.1)
         rgb0 = its.image.compute_image_means(tile)
 
-        # Raw shots are 1/2 x 1/2 smaller after conversion to RGB, so scale the
-        # tile appropriately.
+        # Raw shots are 1/2 x 1/2 smaller after conversion to RGB, but tile
+        # cropping is relative.
         img = its.image.convert_capture_to_rgb_image(cap_raw, props=props)
         its.image.write_image(img, "%s_raw.jpg" % (NAME), True)
-        tile = its.image.get_image_patch(img, 0.475, 0.475, 0.05, 0.05)
+        tile = its.image.get_image_patch(img, 0.45, 0.45, 0.1, 0.1)
         rgb1 = its.image.compute_image_means(tile)
 
         rms_diff = math.sqrt(
diff --git a/apps/CameraITS/tests/scene2/scene2.pdf b/apps/CameraITS/tests/scene2/scene2.pdf
new file mode 100644
index 0000000..ccde9d98
--- /dev/null
+++ b/apps/CameraITS/tests/scene2/scene2.pdf
Binary files differ
diff --git a/apps/CameraITS/tests/scene2/test_faces.py b/apps/CameraITS/tests/scene2/test_faces.py
index cce74e7..388a7e0 100644
--- a/apps/CameraITS/tests/scene2/test_faces.py
+++ b/apps/CameraITS/tests/scene2/test_faces.py
@@ -13,6 +13,7 @@
 # limitations under the License.
 
 import its.image
+import its.caps
 import its.device
 import its.objects
 import os.path
@@ -31,16 +32,38 @@
         fd_modes = props['android.statistics.info.availableFaceDetectModes']
         a = props['android.sensor.info.activeArraySize']
         aw, ah = a['right'] - a['left'], a['bottom'] - a['top']
-        cam.do_3a()
+        if its.caps.read_3a(props):
+            gain, exp, _, _, focus = cam.do_3a(get_results=True)
+            print 'iso = %d' % gain
+            print 'exp = %.2fms' % (exp*1.0E-6)
+            if focus == 0.0:
+                print 'fd = infinity'
+            else:
+                print 'fd = %.2fcm' % (1.0E2/focus)
         for fd_mode in fd_modes:
             assert(FD_MODE_OFF <= fd_mode <= FD_MODE_FULL)
             req = its.objects.auto_capture_request()
             req['android.statistics.faceDetectMode'] = fd_mode
-            caps = cam.do_capture([req]*NUM_TEST_FRAMES)
+            max_img_size = its.objects.get_available_output_sizes("yuv", props)[0]
+            w = max_img_size[0]
+            h = max_img_size[1]
+            out_surf=None
+            if w * h > 12 * 1024 * 1024:
+                size_to_use = its.objects.get_available_output_sizes("yuv",
+                    props, max_size=(4000, 3000), match_ar_size=(w, h))[0]
+                out_surf = {
+                   "width": size_to_use[0],
+                   "height": size_to_use[1],
+                   "format": "yuv",
+                }
+            caps = cam.do_capture([req]*NUM_TEST_FRAMES, out_surfaces=out_surf)
             for i,cap in enumerate(caps):
                 md = cap['metadata']
                 assert(md['android.statistics.faceDetectMode'] == fd_mode)
                 faces = md['android.statistics.faces']
+                img = its.image.convert_capture_to_rgb_image(cap, props=props)
+                img_name = "%s_fd_mode_%s.jpg" % (NAME, fd_mode)
+                its.image.write_image(img, img_name)
 
                 # 0 faces should be returned for OFF mode
                 if fd_mode == FD_MODE_OFF:
diff --git a/apps/CameraITS/tests/scene3/scene3.pdf b/apps/CameraITS/tests/scene3/scene3.pdf
new file mode 100644
index 0000000..4c787b1
--- /dev/null
+++ b/apps/CameraITS/tests/scene3/scene3.pdf
Binary files differ
diff --git a/apps/CameraITS/tests/scene4/scene4.pdf b/apps/CameraITS/tests/scene4/scene4.pdf
new file mode 100644
index 0000000..7dcc4b9
--- /dev/null
+++ b/apps/CameraITS/tests/scene4/scene4.pdf
Binary files differ
diff --git a/apps/CameraITS/tests/scene5/test_lens_shading_and_color_uniformity.py b/apps/CameraITS/tests/scene5/test_lens_shading_and_color_uniformity.py
index 8e9f740..f8a97e4 100644
--- a/apps/CameraITS/tests/scene5/test_lens_shading_and_color_uniformity.py
+++ b/apps/CameraITS/tests/scene5/test_lens_shading_and_color_uniformity.py
@@ -52,15 +52,16 @@
 
     with its.device.ItsSession() as cam:
         props = cam.get_camera_properties()
-        # Converge 3A and get the estimates.
-        sens, exp, gains, xform, focus = cam.do_3a(get_results=True,
-                                                   do_af=False,
-                                                   lock_ae=True,
-                                                   lock_awb=True)
-        print "AE sensitivity %d, exposure %dms" % (sens, exp / 1000000.0)
-        print "AWB gains", gains
-        print "AWB transform", xform
-        print "AF distance", focus
+        if its.caps.read_3a(props):
+            # Converge 3A and get the estimates.
+            sens, exp, gains, xform, focus = cam.do_3a(get_results=True,
+                                                       do_af=False,
+                                                       lock_ae=True,
+                                                       lock_awb=True)
+            print "AE sensitivity %d, exposure %dms" % (sens, exp / 1000000.0)
+            print "AWB gains", gains
+            print "AWB transform", xform
+            print "AF distance", focus
         req = its.objects.auto_capture_request()
         img_size = its.objects.get_available_output_sizes("yuv", props)
         w = img_size[0][0]
diff --git a/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py b/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
index c4f9b84..288d6e4 100644
--- a/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
+++ b/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
@@ -35,8 +35,20 @@
 # Capture 210 VGA frames (which is 7s at 30fps)
 N = 210
 W,H = 640,480
+FEATURE_MARGIN = H * 0.20 / 2 # Only take feature points from the center 20%
+                              # so that the rotation measured have much less
+                              # of rolling shutter effect
 
-FEATURE_PARAMS = dict( maxCorners = 80,
+MIN_FEATURE_PTS = 30          # Minimum number of feature points required to
+                              # perform rotation analysis
+
+MAX_CAM_FRM_RANGE_SEC = 9.0   # Maximum allowed camera frame range. When this
+                              # number is significantly larger than 7 seconds,
+                              # usually system is in some busy/bad states.
+
+MIN_GYRO_SMP_RATE = 100.0     # Minimum gyro sample rate
+
+FEATURE_PARAMS = dict( maxCorners = 240,
                        qualityLevel = 0.3,
                        minDistance = 7,
                        blockSize = 7 )
@@ -102,6 +114,14 @@
             min_cam_time, max_cam_time, min_gyro_time, max_gyro_time)
         assert(0)
 
+    cam_frame_range = max_cam_time - min_cam_time
+    gyro_time_range = max_gyro_time - min_gyro_time
+    gyro_smp_per_sec = len(gyro_times) / gyro_time_range
+    print "Camera frame range", max_cam_time - min_cam_time
+    print "Gyro samples per second", gyro_smp_per_sec
+    assert(cam_frame_range < MAX_CAM_FRM_RANGE_SEC)
+    assert(gyro_smp_per_sec > MIN_GYRO_SMP_RATE)
+
     # Compute the camera rotation displacements (rad) between each pair of
     # adjacent frames.
     cam_rots = get_cam_rotations(frames, events["facing"])
@@ -140,9 +160,9 @@
     Returns:
         Offset (seconds) of the best alignment.
     """
-    # Measure the corr. dist. over a shift of up to +/- 100ms (1ms step size).
+    # Measure the corr. dist. over a shift of up to +/- 50ms (0.5ms step size).
     # Get the shift corresponding to the best (lowest) score.
-    candidates = range(-100,101)
+    candidates = numpy.arange(-50,50.5,0.5).tolist()
     dists = []
     for shift in candidates:
         times = cam_times + shift*MSEC_TO_NSEC
@@ -151,22 +171,26 @@
     best_corr_dist = min(dists)
     best_shift = candidates[dists.index(best_corr_dist)]
 
+    print "Best shift without fitting is ", best_shift, "ms"
+
     # Fit a curve to the corr. dist. data to measure the minima more
     # accurately, by looking at the correlation distances within a range of
-    # +/- 20ms from the measured best score; note that this will use fewer
-    # than the full +/- 20 range for the curve fit if the measured score
-    # (which is used as the center of the fit) is within 20ms of the edge of
-    # the +/- 100ms candidate range.
-    i = len(dists)/2 + best_shift
+    # +/- 10ms from the measured best score; note that this will use fewer
+    # than the full +/- 10 range for the curve fit if the measured score
+    # (which is used as the center of the fit) is within 10ms of the edge of
+    # the +/- 50ms candidate range.
+    i = dists.index(best_corr_dist)
     candidates = candidates[i-20:i+21]
     dists = dists[i-20:i+21]
     a,b,c = numpy.polyfit(candidates, dists, 2)
     exact_best_shift = -b/(2*a)
     if abs(best_shift - exact_best_shift) > 2.0 or a <= 0 or c <= 0:
         print "Test failed; bad fit to time-shift curve"
+        print "best_shift %f, exact_best_shift %f, a %f, c %f" % (best_shift,
+                exact_best_shift, a, c)
         assert(0)
 
-    xfit = [x/10.0 for x in xrange(candidates[0]*10,candidates[-1]*10)]
+    xfit = numpy.arange(candidates[0], candidates[-1], 0.05).tolist()
     yfit = [a*x*x+b*x+c for x in xfit]
     fig = matplotlib.pyplot.figure()
     pylab.plot(candidates, dists, 'r', label="data")
@@ -263,13 +287,23 @@
         frame = (frame * 255.0).astype(numpy.uint8)
         gframes.append(cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY))
     rots = []
+    ymin = H/2 - FEATURE_MARGIN
+    ymax = H/2 + FEATURE_MARGIN
     for i in range(1,len(gframes)):
         gframe0 = gframes[i-1]
         gframe1 = gframes[i]
         p0 = cv2.goodFeaturesToTrack(gframe0, mask=None, **FEATURE_PARAMS)
-        p1,st,_ = cv2.calcOpticalFlowPyrLK(gframe0, gframe1, p0, None,
+        # p0's shape is N * 1 * 2
+        mask = (p0[:,0,1] >= ymin) & (p0[:,0,1] <= ymax)
+        p0_filtered = p0[mask]
+        if len(p0_filtered) < MIN_FEATURE_PTS:
+            print "Not enough feature points in frame", i
+            print "Need at least %d features, got %d" % (
+                    MIN_FEATURE_PTS, len(p0_filtered))
+            assert(0)
+        p1,st,_ = cv2.calcOpticalFlowPyrLK(gframe0, gframe1, p0_filtered, None,
                 **LK_PARAMS)
-        tform = procrustes_rotation(p0[st==1], p1[st==1])
+        tform = procrustes_rotation(p0_filtered[st==1], p1[st==1])
         if facing == FACING_BACK:
             rot = -math.atan2(tform[0, 1], tform[0, 0])
         elif facing == FACING_FRONT:
@@ -282,7 +316,7 @@
             # Save a debug visualization of the features that are being
             # tracked in the first frame.
             frame = frames[i]
-            for x,y in p0[st==1]:
+            for x,y in p0_filtered[st==1]:
                 cv2.circle(frame, (x,y), 3, (100,100,255), -1)
             its.image.write_image(frame, "%s_features.png"%(NAME))
     return numpy.array(rots)
@@ -342,8 +376,8 @@
         print "Starting sensor event collection"
         cam.start_sensor_events()
 
-        # Sleep a few seconds for gyro events to stabilize.
-        time.sleep(2)
+        # Sleep a while for gyro events to stabilize.
+        time.sleep(0.5)
 
         # TODO: Ensure that OIS is disabled; set to DISABLE and wait some time.
 
@@ -354,7 +388,7 @@
             assert(0)
 
         fmt = {"format":"yuv", "width":W, "height":H}
-        s,e,_,_,_ = cam.do_3a(get_results=True)
+        s,e,_,_,_ = cam.do_3a(get_results=True, do_af=False)
         req = its.objects.manual_capture_request(s, e)
         print "Capturing %dx%d with sens. %d, exp. time %.1fms" % (
                 W, H, s, e*NSEC_TO_MSEC)
@@ -363,6 +397,7 @@
         # Get the gyro events.
         print "Reading out sensor events"
         gyro = cam.get_sensor_events()["gyro"]
+        print "Number of gyro samples", len(gyro)
 
         # Combine the events into a single structure.
         print "Dumping event data"
diff --git a/apps/CameraITS/tools/load_scene.py b/apps/CameraITS/tools/load_scene.py
new file mode 100644
index 0000000..4e245f4
--- /dev/null
+++ b/apps/CameraITS/tools/load_scene.py
@@ -0,0 +1,61 @@
+# Copyright 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import re
+import subprocess
+import sys
+import time
+
+
+def main():
+    """Load charts on device and display."""
+    camera_id = -1
+    scene = None
+    for s in sys.argv[1:]:
+        if s[:6] == 'scene=' and len(s) > 6:
+            scene = s[6:]
+        elif s[:7] == 'screen=' and len(s) > 7:
+            screen_id = s[7:]
+
+    cmd = ('adb -s %s shell am force-stop com.google.android.apps.docs' %
+           screen_id)
+    subprocess.Popen(cmd.split())
+
+    if not scene:
+        print 'Error: need to specify which scene to load'
+        assert False
+
+    if not screen_id:
+        print 'Error: need to specify screen serial'
+        assert False
+
+    remote_scene_file = '/sdcard/Download/%s.pdf' % scene
+    local_scene_file = os.path.join(os.environ['CAMERA_ITS_TOP'], 'tests',
+                                    scene, scene+'.pdf')
+    print 'Loading %s on %s' % (remote_scene_file, screen_id)
+    cmd = 'adb -s %s push %s /mnt%s' % (screen_id, local_scene_file,
+                                        remote_scene_file)
+    subprocess.Popen(cmd.split())
+    time.sleep(1)  # wait-for-device doesn't always seem to work...
+    # The intent require PDF viewing app be installed on device.
+    # Also the first time such app is opened it might request some permission,
+    # so it's  better to grant those permissions before using this script
+    cmd = ("adb -s %s wait-for-device shell am start -d 'file://%s'"
+           " -a android.intent.action.VIEW" % (screen_id,
+                                               remote_scene_file))
+    subprocess.Popen(cmd.split())
+
+if __name__ == '__main__':
+    main()
diff --git a/apps/CameraITS/tools/run_all_tests.py b/apps/CameraITS/tools/run_all_tests.py
index 52780eb..c6ff548 100644
--- a/apps/CameraITS/tools/run_all_tests.py
+++ b/apps/CameraITS/tools/run_all_tests.py
@@ -20,12 +20,25 @@
 import sys
 import textwrap
 import its.device
+from its.device import ItsSession
 
 def main():
     """Run all the automated tests, saving intermediate files, and producing
     a summary/report of the results.
 
     Script should be run from the top-level CameraITS directory.
+
+    Command line Arguments:
+        camera: the camera(s) to be tested. Use comma to separate multiple
+                camera Ids. Ex: "camera=0,1" or "camera=1"
+        scenes: the test scene(s) to be executed. Use comma to separate multiple
+                scenes. Ex: "scenes=scene0,scene1" or "scenes=0,1,sensor_fusion"
+                (sceneX can be abbreviated by X where X is a integer)
+        chart: [Experimental] another android device served as test chart
+               display. When this argument presents, change of test scene will
+               be handled automatically. Note that this argument requires
+               special physical/hardware setup to work and may not work on
+               all android devices.
     """
 
     SKIP_RET_CODE = 101
@@ -49,10 +62,9 @@
         "sensor_fusion":[]
     }
 
-    # Get all the scene0 and scene1 tests, which can be run using the same
-    # physical setup.
-    scenes = ["scene0", "scene1", "scene2", "scene3", "scene4", "scene5",
-              "sensor_fusion"]
+    all_scenes = ["scene0", "scene1", "scene2", "scene3", "scene4", "scene5"]
+
+    auto_scenes = ["scene0", "scene1", "scene2", "scene3", "scene4"]
 
     scene_req = {
         "scene0" : None,
@@ -75,12 +87,54 @@
     scene_extra_args = {
         "scene5" : ["doAF=False"]
     }
-    tests = []
-    for d in scenes:
-        tests += [(d,s[:-3],os.path.join("tests", d, s))
-                  for s in os.listdir(os.path.join("tests",d))
-                  if s[-3:] == ".py"]
-    tests.sort()
+
+    camera_ids = []
+    scenes = []
+    chart_host_id = None
+    for s in sys.argv[1:]:
+        if s[:7] == "camera=" and len(s) > 7:
+            camera_ids = s[7:].split(',')
+        elif s[:7] == "scenes=" and len(s) > 7:
+            scenes = s[7:].split(',')
+        elif s[:6] == 'chart=' and len(s) > 6:
+            chart_host_id = s[6:]
+
+    auto_scene_switch = chart_host_id is not None
+
+    # Run through all scenes if user does not supply one
+    possible_scenes = auto_scenes if auto_scene_switch else all_scenes
+    if not scenes:
+        scenes = possible_scenes
+    else:
+        # Validate user input scene names
+        valid_scenes = True
+        temp_scenes = []
+        for s in scenes:
+            if s in possible_scenes:
+                temp_scenes.append(s)
+            else:
+                try:
+                    # Try replace "X" to "sceneX"
+                    scene_num = int(s)
+                    scene_str = "scene" + s
+                    if scene_str not in possible_scenes:
+                        valid_scenes = False
+                        break
+                    temp_scenes.append(scene_str)
+                except ValueError:
+                    valid_scenes = False
+                    break
+
+        if not valid_scenes:
+            print "Unknown scene specifiied:", s
+            assert(False)
+        scenes = temp_scenes
+
+    # Initialize test results
+    results = {}
+    result_key = ItsSession.RESULT_KEY
+    for s in all_scenes:
+        results[s] = {result_key: ItsSession.RESULT_NOT_EXECUTED}
 
     # Make output directories to hold the generated files.
     topdir = tempfile.mkdtemp()
@@ -90,11 +144,6 @@
     device_id_arg = "device=" + device_id
     print "Testing device " + device_id
 
-    camera_ids = []
-    for s in sys.argv[1:]:
-        if s[:7] == "camera=" and len(s) > 7:
-            camera_ids.append(s[7:])
-
     # user doesn't specify camera id, run through all cameras
     if not camera_ids:
         camera_ids_path = os.path.join(topdir, "camera_ids.txt")
@@ -108,7 +157,15 @@
             for line in f:
                 camera_ids.append(line.replace('\n', ''))
 
-    print "Running ITS on the following cameras:", camera_ids
+    print "Running ITS on camera: %s, scene %s" % (camera_ids, scenes)
+
+    if auto_scene_switch:
+        print 'Waking up chart screen: ', chart_host_id
+        screen_id_arg = ('screen=%s' % chart_host_id)
+        cmd = ['python', os.path.join(os.environ['CAMERA_ITS_TOP'], 'tools',
+                                      'wake_up_screen.py'), screen_id_arg]
+        retcode = subprocess.call(cmd)
+        assert retcode == 0
 
     for camera_id in camera_ids:
         # Loop capturing images until user confirm test scene is correct
@@ -119,85 +176,117 @@
         for d in scenes:
             os.mkdir(os.path.join(topdir, camera_id, d))
 
-        print "Start running ITS on camera: ", camera_id
-        # Run each test, capturing stdout and stderr.
-        summary = "ITS test result summary for camera " + camera_id + "\n"
-        numpass = 0
-        numskip = 0
-        numnotmandatedfail = 0
-        numfail = 0
+        for scene in scenes:
+            tests = [(s[:-3],os.path.join("tests", scene, s))
+                     for s in os.listdir(os.path.join("tests",scene))
+                     if s[-3:] == ".py" and s[:4] == "test"]
+            tests.sort()
 
-        prev_scene = ""
-        for (scene,testname,testpath) in tests:
-            if scene != prev_scene and scene_req[scene] != None:
+            summary = "Cam" + camera_id + " " + scene + "\n"
+            numpass = 0
+            numskip = 0
+            num_not_mandated_fail = 0
+            numfail = 0
+            if scene_req[scene] != None:
                 out_path = os.path.join(topdir, camera_id, scene+".jpg")
                 out_arg = "out=" + out_path
-                scene_arg = "scene=" + scene_req[scene]
-                extra_args = scene_extra_args.get(scene, [])
-                cmd = ['python',
-                        os.path.join(os.getcwd(),"tools/validate_scene.py"),
-                        camera_id_arg, out_arg, scene_arg, device_id_arg] + \
-                        extra_args
+                if auto_scene_switch:
+                    scene_arg = "scene=" + scene
+                    cmd = ['python',
+                           os.path.join(os.getcwd(), 'tools/load_scene.py'),
+                           scene_arg, screen_id_arg]
+                else:
+                    scene_arg = "scene=" + scene_req[scene]
+                    extra_args = scene_extra_args.get(scene, [])
+                    cmd = ['python',
+                            os.path.join(os.getcwd(),"tools/validate_scene.py"),
+                            camera_id_arg, out_arg,
+                            scene_arg, device_id_arg] + extra_args
                 retcode = subprocess.call(cmd,cwd=topdir)
                 assert(retcode == 0)
-                print "Start running tests for", scene
-            prev_scene = scene
-            cmd = ['python', os.path.join(os.getcwd(),testpath)] + \
-                  sys.argv[1:] + [camera_id_arg]
-            outdir = os.path.join(topdir,camera_id,scene)
-            outpath = os.path.join(outdir,testname+"_stdout.txt")
-            errpath = os.path.join(outdir,testname+"_stderr.txt")
-            t0 = time.time()
-            with open(outpath,"w") as fout, open(errpath,"w") as ferr:
-                retcode = subprocess.call(cmd,stderr=ferr,stdout=fout,cwd=outdir)
-            t1 = time.time()
+            print "Start running ITS on camera %s, %s" % (camera_id, scene)
 
-            if retcode == 0:
-                retstr = "PASS "
-                numpass += 1
-            elif retcode == SKIP_RET_CODE:
-                retstr = "SKIP "
-                numskip += 1
-            elif retcode != 0 and testname in NOT_YET_MANDATED[scene]:
-                retstr = "FAIL*"
-                numnotmandatedfail += 1
+            # Run each test, capturing stdout and stderr.
+            for (testname,testpath) in tests:
+                if auto_scene_switch:
+                    # Send an input event to keep the screen not dimmed.
+                    # Since we are not using camera of chart screen, FOCUS event
+                    # should does nothing but keep the screen from dimming.
+                    # The "sleep after x minutes of inactivity" display setting
+                    # determines how long this command can keep screen bright.
+                    # Setting it to something like 30 minutes should be enough.
+                    cmd = ('adb -s %s shell input keyevent FOCUS'
+                           % chart_host_id)
+                    subprocess.call(cmd.split())
+                cmd = ['python', os.path.join(os.getcwd(),testpath)] + \
+                      sys.argv[1:] + [camera_id_arg]
+                outdir = os.path.join(topdir,camera_id,scene)
+                outpath = os.path.join(outdir,testname+"_stdout.txt")
+                errpath = os.path.join(outdir,testname+"_stderr.txt")
+                t0 = time.time()
+                with open(outpath,"w") as fout, open(errpath,"w") as ferr:
+                    retcode = subprocess.call(
+                            cmd,stderr=ferr,stdout=fout,cwd=outdir)
+                t1 = time.time()
+
+                test_failed = False
+                if retcode == 0:
+                    retstr = "PASS "
+                    numpass += 1
+                elif retcode == SKIP_RET_CODE:
+                    retstr = "SKIP "
+                    numskip += 1
+                elif retcode != 0 and testname in NOT_YET_MANDATED[scene]:
+                    retstr = "FAIL*"
+                    num_not_mandated_fail += 1
+                else:
+                    retstr = "FAIL "
+                    numfail += 1
+                    test_failed = True
+
+                msg = "%s %s/%s [%.1fs]" % (retstr, scene, testname, t1-t0)
+                print msg
+                msg_short = "%s %s [%.1fs]" % (retstr, testname, t1-t0)
+                if test_failed:
+                    summary += msg_short + "\n"
+
+            if numskip > 0:
+                skipstr = ", %d test%s skipped" % (
+                        numskip, "s" if numskip > 1 else "")
             else:
-                retstr = "FAIL "
-                numfail += 1
+                skipstr = ""
 
-            msg = "%s %s/%s [%.1fs]" % (retstr, scene, testname, t1-t0)
-            print msg
-            summary += msg + "\n"
-            if retcode != 0 and retcode != SKIP_RET_CODE:
-                # Dump the stderr if the test fails
-                with open (errpath, "r") as error_file:
-                    errors = error_file.read()
-                    summary += errors + "\n"
+            test_result = "\n%d / %d tests passed (%.1f%%)%s" % (
+                    numpass + num_not_mandated_fail, len(tests) - numskip,
+                    100.0 * float(numpass + num_not_mandated_fail) /
+                            (len(tests) - numskip)
+                            if len(tests) != numskip else 100.0,
+                    skipstr)
+            print test_result
 
-        if numskip > 0:
-            skipstr = ", %d test%s skipped" % (numskip, "s" if numskip > 1 else "")
-        else:
-            skipstr = ""
+            if num_not_mandated_fail > 0:
+                msg = "(*) tests are not yet mandated"
+                print msg
 
-        test_result = "\n%d / %d tests passed (%.1f%%)%s" % (
-                numpass + numnotmandatedfail, len(tests) - numskip,
-                100.0 * float(numpass + numnotmandatedfail) / (len(tests) - numskip)
-                    if len(tests) != numskip else 100.0,
-                skipstr)
-        print test_result
-        summary += test_result + "\n"
+            summary_path = os.path.join(topdir, camera_id, scene, "summary.txt")
+            with open(summary_path, "w") as f:
+                f.write(summary)
 
-        if numnotmandatedfail > 0:
-            msg = "(*) tests are not yet mandated"
-            print msg
-            summary += msg + "\n"
+            passed = numfail == 0
+            results[scene][result_key] = (ItsSession.RESULT_PASS if passed
+                    else ItsSession.RESULT_FAIL)
+            results[scene][ItsSession.SUMMARY_KEY] = summary_path
 
-        result = numfail == 0
         print "Reporting ITS result to CtsVerifier"
-        summary_path = os.path.join(topdir, camera_id, "summary.txt")
-        with open(summary_path, "w") as f:
-            f.write(summary)
-        its.device.report_result(device_id, camera_id, result, summary_path)
+        its.device.report_result(device_id, camera_id, results)
+
+    if auto_scene_switch:
+        print 'Shutting down chart screen: ', chart_host_id
+        screen_id_arg = ('screen=%s' % chart_host_id)
+        cmd = ['python', os.path.join(os.environ['CAMERA_ITS_TOP'], 'tools',
+                                      'turn_off_screen.py'), screen_id_arg]
+        retcode = subprocess.call(cmd)
+        assert retcode == 0
 
     print "ITS tests finished. Please go back to CtsVerifier and proceed"
 
diff --git a/apps/CameraITS/tools/turn_off_screen.py b/apps/CameraITS/tools/turn_off_screen.py
new file mode 100644
index 0000000..4163ab4
--- /dev/null
+++ b/apps/CameraITS/tools/turn_off_screen.py
@@ -0,0 +1,42 @@
+# Copyright 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import re
+import subprocess
+import sys
+
+
+def main():
+    """Put screen to sleep."""
+    screen_id = ''
+    for s in sys.argv[1:]:
+        if s[:7] == 'screen=' and len(s) > 7:
+            screen_id = s[7:]
+
+    if not screen_id:
+        print 'Error: need to specify screen serial'
+        assert False
+
+    cmd = ('adb -s %s shell dumpsys power | egrep "Display Power"'
+           % screen_id)
+    process = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)
+    cmd_ret = process.stdout.read()
+    screen_state = re.split(r'[s|=]', cmd_ret)[-1]
+    if screen_state == 'OFF\n':
+        print 'Screen OFF. Turning ON.'
+    else:
+        wakeup = ('adb -s %s shell input keyevent POWER' % screen_id)
+        subprocess.Popen(wakeup.split())
+if __name__ == '__main__':
+    main()
diff --git a/apps/CameraITS/tools/wake_up_screen.py b/apps/CameraITS/tools/wake_up_screen.py
new file mode 100644
index 0000000..68a974a
--- /dev/null
+++ b/apps/CameraITS/tools/wake_up_screen.py
@@ -0,0 +1,60 @@
+# Copyright 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import re
+import subprocess
+import sys
+import time
+
+DISPLAY_LEVEL = 96  # [0:255] Depends on tablet model. Adjust for best result.
+DISPLAY_WAIT = 0.5  # seconds. Screen commands take time to have effect
+
+
+def main():
+    """Power up and unlock screen as needed."""
+    screen_id = None
+    for s in sys.argv[1:]:
+        if s[:7] == 'screen=' and len(s) > 7:
+            screen_id = s[7:]
+
+    if not screen_id:
+        print 'Error: need to specify screen serial'
+        assert False
+
+    # turn on screen if necessary and unlock
+    cmd = ('adb -s %s shell dumpsys display | egrep "mScreenState"'
+           % screen_id)
+    process = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)
+    cmd_ret = process.stdout.read()
+    screen_state = re.split(r'[s|=]', cmd_ret)[-1]
+    if 'OFF' in screen_state:
+        print 'Screen OFF. Turning ON.'
+        wakeup = ('adb -s %s shell input keyevent POWER' % screen_id)
+        subprocess.Popen(wakeup.split())
+        time.sleep(DISPLAY_WAIT)
+    unlock = ('adb -s %s wait-for-device shell wm dismiss-keyguard'
+              % screen_id)
+    subprocess.Popen(unlock.split())
+    time.sleep(DISPLAY_WAIT)
+
+    # set brightness
+    print 'Tablet display brightness set to %d' % DISPLAY_LEVEL
+    bright = ('adb -s %s shell settings put system screen_brightness %d'
+              % (screen_id, DISPLAY_LEVEL))
+    subprocess.Popen(bright.split())
+    time.sleep(DISPLAY_WAIT)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/apps/CtsVerifier/Android.mk b/apps/CtsVerifier/Android.mk
index 304c982..cafb855 100644
--- a/apps/CtsVerifier/Android.mk
+++ b/apps/CtsVerifier/Android.mk
@@ -26,7 +26,6 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-Iaidl-files-under, src)
 
 LOCAL_STATIC_JAVA_LIBRARIES := android-ex-camera2 \
-                               android-support-v4 \
                                compatibility-common-util-devicesidelib \
                                cts-sensors-tests \
                                cts-location-tests \
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 964feb2..7f0ca22 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -18,7 +18,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="com.android.cts.verifier"
       android:versionCode="5"
-      android:versionName="7.1_r1">
+      android:versionName="7.1_r201703s">
 
     <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="25"/>
 
@@ -69,7 +69,8 @@
             android:icon="@drawable/icon"
             android:backupAgent="VerifierBackupAgent"
             android:debuggable="true"
-            android:largeHeap="true">
+            android:largeHeap="true"
+            android:theme="@android:style/Theme.DeviceDefault">
 
         <meta-data android:name="com.google.android.backup.api_key"
                 android:value="AEdPqrEAAAAIbK6ldcOzoeRtQ1u1dFVJ1A7KetRhit-a1Xa82Q" />
@@ -485,6 +486,17 @@
             <meta-data android:name="test_required_features" android:value="android.hardware.location.gps" />
         </activity>
 
+        <!--  activity android:name=".location.GnssStatusTestsActivity"
+            android:label="@string/location_gnss_status_test"
+            android:screenOrientation="locked">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.cts.intent.category.MANUAL_TEST"/>
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_hardware"/>
+            <meta-data android:name="test_required_features" android:value="android.hardware.location.gps" />
+        </activity -->
+
         <activity android:name=".location.LocationListenerActivity"
                 android:label="@string/location_listener_activity"
                 android:configChanges="keyboardHidden|orientation|screenSize">
@@ -1227,6 +1239,18 @@
             </intent-filter>
         </service>
 
+        <activity android:name=".notifications.ShortcutThrottlingResetActivity"
+            android:label="@string/shortcut_reset_test"
+            android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_notifications" />
+            <meta-data android:name="test_excluded_features"
+                android:value="android.hardware.type.watch:android.software.leanback" />
+        </activity>
+
         <activity android:name=".vr.VrListenerVerifierActivity"
             android:label="@string/vr_tests">
             <intent-filter>
diff --git a/apps/CtsVerifier/res/layout-port/gnss_test.xml b/apps/CtsVerifier/res/layout-port/gnss_test.xml
index 560133a..1838e88 100644
--- a/apps/CtsVerifier/res/layout-port/gnss_test.xml
+++ b/apps/CtsVerifier/res/layout-port/gnss_test.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2016 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,45 +12,32 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<com.android.cts.verifier.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/RootLayoutPadding"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
-    <LinearLayout app:ctsv_layout_box="all"
-        android:orientation="vertical"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <TextView
+        android:id="@+id/text"
         android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textSize="14sp" />
+
+    <ScrollView
+        android:id="@+id/log_scroll_view"
+        android:layout_width="0dp"
         android:layout_height="match_parent"
-        >
+        android:layout_weight="1"
+        android:fillViewport="true">
 
         <LinearLayout
-            android:orientation="horizontal"
+            android:id="@+id/log_layout"
             android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_weight="1">
+            android:layout_height="match_parent"
+            android:orientation="vertical" />
 
-            <TextView android:id="@+id/text"
-                android:textSize="14sp"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"/>
+    </ScrollView>
 
-            <ScrollView
-                android:id="@+id/log_scroll_view"
-                android:fillViewport="true"
-                android:layout_height="match_parent"
-                android:layout_width="0dp"
-                android:layout_weight="1">
-
-                <LinearLayout
-                    android:id="@+id/log_layout"
-                    android:orientation="vertical"
-                    android:layout_width="match_parent"
-                    android:layout_height="match_parent"/>
-
-            </ScrollView>
-
-        </LinearLayout>
-
-        <include layout="@layout/snsr_next_button" />
-
-    </LinearLayout>
-</com.android.cts.verifier.BoxInsetLayout>
+    <include layout="@layout/snsr_next_button" />
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout-round/provisioning_byod.xml b/apps/CtsVerifier/res/layout-round/provisioning_byod.xml
new file mode 100644
index 0000000..d2b6e0e
--- /dev/null
+++ b/apps/CtsVerifier/res/layout-round/provisioning_byod.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/main_layout"
+    style="@style/RootLayoutPadding"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical">
+        <TextView
+            android:id="@+id/test_instructions"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:padding="10dip"/>
+        <Button
+            android:id="@+id/prepare_test_button"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"/>
+        <ListView
+            android:id="@+id/android:list"
+            android:layout_width="match_parent"
+            android:layout_height="0dip"
+            android:layout_weight="3"/>
+        <include layout="@layout/pass_fail_buttons"/>
+    </LinearLayout>
+</android.support.v4.widget.NestedScrollView>
diff --git a/apps/CtsVerifier/res/layout-small/gnss_test.xml b/apps/CtsVerifier/res/layout-small/gnss_test.xml
index 5caea07..e36bf26 100644
--- a/apps/CtsVerifier/res/layout-small/gnss_test.xml
+++ b/apps/CtsVerifier/res/layout-small/gnss_test.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2016 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,32 +12,34 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<com.android.cts.verifier.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/RootLayoutPadding"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
-    <ScrollView android:id="@+id/log_scroll_view"
-        app:ctsv_layout_box="all"
-        android:fillViewport="true"
+    <ScrollView
+        android:id="@+id/log_scroll_view"
+        android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:layout_width="match_parent">
+        android:fillViewport="true">
         <LinearLayout
-            android:orientation="vertical"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_width="match_parent">
+            android:orientation="vertical">
 
-            <TextView android:id="@+id/text"
-                android:textSize="14sp"
+            <TextView
+                android:id="@+id/text"
                 android:layout_width="match_parent"
-                android:layout_height="wrap_content"/>
-
-            <LinearLayout android:id="@+id/log_layout"
-                android:orientation="vertical"
                 android:layout_height="wrap_content"
-                android:layout_width="match_parent"/>
+                android:textSize="14sp" />
 
-            <include layout="@layout/snsr_next_button"/>
+            <LinearLayout
+                android:id="@+id/log_layout"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="vertical" />
+
+            <include layout="@layout/snsr_next_button" />
         </LinearLayout>
 
     </ScrollView>
-</com.android.cts.verifier.BoxInsetLayout>
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout-small/intent_driven_test.xml b/apps/CtsVerifier/res/layout-small/intent_driven_test.xml
new file mode 100644
index 0000000..0a8cab6
--- /dev/null
+++ b/apps/CtsVerifier/res/layout-small/intent_driven_test.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    style="@style/RootLayoutPadding">
+
+    <ScrollView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+	<LinearLayout
+	android:layout_width="match_parent"
+	android:layout_height="match_parent"
+	android:orientation="vertical">
+        <TextView android:id="@+id/info"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:textSize="12dip"
+            android:padding="2dip"
+            android:text="@string/dc_start_alarm_test_info"/>
+
+    <LinearLayout android:id="@+id/buttons"
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+        <include layout="@layout/pass_fail_buttons"/>
+    </LinearLayout>
+</LinearLayout>
+</ScrollView>
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout-small/policy_transparency_test.xml b/apps/CtsVerifier/res/layout-small/policy_transparency_test.xml
new file mode 100644
index 0000000..1c5e448
--- /dev/null
+++ b/apps/CtsVerifier/res/layout-small/policy_transparency_test.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/root_view"
+	style="@style/RootLayoutPadding"
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:descendantFocusability="beforeDescendants"
+        android:focusableInTouchMode="true">
+    <ScrollView
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+	<LinearLayout
+		android:layout_width="match_parent"
+		android:layout_height="match_parent"
+		android:orientation="vertical">
+        <TextView
+                android:id="@+id/test_instructions"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="12dip"/>
+
+    <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical"
+            android:paddingTop="8dp">
+        <TextView android:id="@+id/widget_label"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="12dip"
+                android:paddingStart="16dp"
+                android:paddingEnd="8dp" />
+        <Switch android:id="@+id/switch_widget"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:paddingStart="8dp"
+                android:paddingEnd="16dp"
+                android:visibility="gone" />
+        <EditText android:id="@+id/edit_text_widget"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:ems="6"
+                android:singleLine="true"
+                android:gravity="center"
+                android:visibility="gone" />
+        <Button android:id="@+id/update_button"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/policy_transparency_update_button_label"
+                android:paddingStart="8dp"
+                android:paddingEnd="16dp"
+                android:visibility="gone" />
+        <Spinner android:id="@+id/spinner_widget"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:visibility="gone" />
+    </LinearLayout>
+
+    <Button android:id="@+id/open_settings_button"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/policy_transparency_open_settings_label" />
+
+    <include layout="@layout/pass_fail_buttons"/>
+</LinearLayout>
+</ScrollView>
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout-small/policy_transparency_test_list.xml b/apps/CtsVerifier/res/layout-small/policy_transparency_test_list.xml
new file mode 100644
index 0000000..0835cb1
--- /dev/null
+++ b/apps/CtsVerifier/res/layout-small/policy_transparency_test_list.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<com.android.cts.verifier.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    style="@style/RootLayoutPadding"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+<ScrollView
+	android:layout_width="match_parent"
+	android:layout_height="match_parent">
+    <LinearLayout app:ctsv_layout_box="all"
+            android:orientation="vertical"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            >
+
+        <ListView android:id="@id/android:list"
+                android:layout_width="match_parent"
+                android:layout_height="1000dip"
+		android:layout_marginTop="10dip"
+		android:layout_marginBottom="10dip"
+                />
+
+        <TextView android:id="@id/android:empty"
+                android:layout_width="match_parent"
+                android:layout_height="8dip"
+                />
+
+        <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+            <Button android:id="@+id/short_msg_button"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+		    android:textSize="8dip"
+                    android:text="@string/policy_transparency_short_support_msg_label" />
+            <Button android:id="@+id/long_msg_button"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+		    android:textSize="8dip"
+                    android:text="@string/policy_transparency_long_support_msg_label" />
+        </LinearLayout>
+        <include layout="@layout/pass_fail_buttons" />
+
+    </LinearLayout>
+</ScrollView>
+</com.android.cts.verifier.BoxInsetLayout>
diff --git a/apps/CtsVerifier/res/layout-small/positive_device_owner.xml b/apps/CtsVerifier/res/layout-small/positive_device_owner.xml
new file mode 100644
index 0000000..82f11a2
--- /dev/null
+++ b/apps/CtsVerifier/res/layout-small/positive_device_owner.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/RootLayoutPadding"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <ScrollView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:orientation="vertical">
+
+            <TextView
+                android:id="@+id/positive_device_owner_instructions"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/device_owner_positive_tests_instructions"
+                android:textSize="16dip" />
+
+            <Button
+                android:id="@+id/set_device_owner_button"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/set_device_owner_button_label" />
+
+            <ListView
+                android:id="@+id/android:list"
+                android:layout_width="match_parent"
+                android:layout_height="800dip" />
+
+            <include layout="@layout/pass_fail_buttons" />
+        </LinearLayout>
+    </ScrollView>
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout-small/wifi_lockdown.xml b/apps/CtsVerifier/res/layout-small/wifi_lockdown.xml
new file mode 100644
index 0000000..f158976
--- /dev/null
+++ b/apps/CtsVerifier/res/layout-small/wifi_lockdown.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	style="@style/RootLayoutPadding"
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+    <ScrollView
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+	<LinearLayout
+	android:layout_width="match_parent"
+	android:layout_height="match_parent"
+	android:orientation="vertical">
+        <TextView
+                android:id="@+id/device_owner_wifi_lockdown_info"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:padding="2dip"
+                android:text="@string/device_owner_wifi_lockdown_info"
+                android:textSize="12dip" />
+
+    <EditText
+        android:id="@+id/device_owner_wifi_ssid"
+        android:hint="(SSID)"
+	android:layout_marginLeft="50dip"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <RadioGroup
+        android:id="@+id/device_owner_keyManagementMethods"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+        <RadioButton
+            android:id="@+id/device_owner_keymgmnt_none"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/device_owner_wifi_key_management_none_button" />
+        <RadioButton
+            android:id="@+id/device_owner_keymgmnt_wpa"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/device_owner_wifi_key_management_wpa_button" />
+        <RadioButton
+            android:id="@+id/device_owner_keymgmnt_wep"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/device_owner_wifi_key_management_wep_button" />
+    </RadioGroup>
+
+    <Button
+        android:id="@+id/create_wifi_config_button"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+	android:textSize="12dip"
+        android:text="@string/create_wifi_config_button_label" />
+
+    <ListView
+        android:id="@+id/android:list"
+        android:layout_width="match_parent"
+        android:layout_height="200dip"/>
+
+    <include layout="@layout/pass_fail_buttons" />
+</LinearLayout>
+</ScrollView>
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/audio_dev_notify.xml b/apps/CtsVerifier/res/layout/audio_dev_notify.xml
index ceedf1c..aa6d3c4 100644
--- a/apps/CtsVerifier/res/layout/audio_dev_notify.xml
+++ b/apps/CtsVerifier/res/layout/audio_dev_notify.xml
@@ -18,12 +18,11 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:id="@+id/scrollView"
-    >
+        style="@style/RootLayoutPadding">
 
-<LinearLayout
+        <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:padding="20dp"
         android:orientation="vertical">
 
         <TextView
diff --git a/apps/CtsVerifier/res/layout/audio_frequency_line_activity.xml b/apps/CtsVerifier/res/layout/audio_frequency_line_activity.xml
index 6a755d5..41292d1 100644
--- a/apps/CtsVerifier/res/layout/audio_frequency_line_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_frequency_line_activity.xml
@@ -17,9 +17,8 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:padding="10dip"
     android:orientation="vertical"
->
+    style="@style/RootLayoutPadding">
     <ScrollView
         android:layout_width="match_parent"
         android:layout_height="match_parent"
@@ -131,4 +130,4 @@
         </LinearLayout>
     </ScrollView>
 
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/audio_frequency_mic_activity.xml b/apps/CtsVerifier/res/layout/audio_frequency_mic_activity.xml
index 8722f1d..bdf9e7c 100644
--- a/apps/CtsVerifier/res/layout/audio_frequency_mic_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_frequency_mic_activity.xml
@@ -17,9 +17,8 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:padding="10dip"
     android:orientation="vertical"
->
+    style="@style/RootLayoutPadding">
 
     <ScrollView
         android:layout_width="match_parent"
@@ -192,4 +191,4 @@
         </LinearLayout>
     </ScrollView>
 
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/audio_frequency_speaker_activity.xml b/apps/CtsVerifier/res/layout/audio_frequency_speaker_activity.xml
index 926a4c7..435f5a7 100644
--- a/apps/CtsVerifier/res/layout/audio_frequency_speaker_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_frequency_speaker_activity.xml
@@ -17,8 +17,8 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:padding="10dip"
-    android:orientation="vertical">
+    android:orientation="vertical"
+    style="@style/RootLayoutPadding">
 
     <ScrollView
        android:layout_width="match_parent"
@@ -97,4 +97,4 @@
         </LinearLayout>
       </ScrollView>
 
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/audio_frequency_unprocessed_activity.xml b/apps/CtsVerifier/res/layout/audio_frequency_unprocessed_activity.xml
index 142ffff..d02ef0b 100644
--- a/apps/CtsVerifier/res/layout/audio_frequency_unprocessed_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_frequency_unprocessed_activity.xml
@@ -10,9 +10,8 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:padding="10dip"
     android:orientation="vertical"
->
+    style="@style/RootLayoutPadding">
 
     <ScrollView
         android:layout_width="match_parent"
@@ -301,4 +300,4 @@
         </LinearLayout>
     </ScrollView>
 
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/audio_input_routingnotifications_test.xml b/apps/CtsVerifier/res/layout/audio_input_routingnotifications_test.xml
index 60a12ef..e09475c 100644
--- a/apps/CtsVerifier/res/layout/audio_input_routingnotifications_test.xml
+++ b/apps/CtsVerifier/res/layout/audio_input_routingnotifications_test.xml
@@ -18,12 +18,11 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:id="@+id/scrollView"
-    >
+        style="@style/RootLayoutPadding">
 
 <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:padding = "20dp"
         android:orientation="vertical">
 
         <TextView
diff --git a/apps/CtsVerifier/res/layout/audio_loopback_activity.xml b/apps/CtsVerifier/res/layout/audio_loopback_activity.xml
index 350f428..89d2e19 100644
--- a/apps/CtsVerifier/res/layout/audio_loopback_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_loopback_activity.xml
@@ -17,9 +17,8 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:padding="10dip"
     android:orientation="vertical"
->
+    style="@style/RootLayoutPadding">
 
     <ScrollView
         android:layout_width="match_parent"
@@ -151,4 +150,4 @@
         </LinearLayout>
     </ScrollView>
 
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/audio_output_routingnotifications_test.xml b/apps/CtsVerifier/res/layout/audio_output_routingnotifications_test.xml
index d039691..dc55e2a 100644
--- a/apps/CtsVerifier/res/layout/audio_output_routingnotifications_test.xml
+++ b/apps/CtsVerifier/res/layout/audio_output_routingnotifications_test.xml
@@ -18,12 +18,11 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:id="@+id/scrollView"
-    >
+        style="@style/RootLayoutPadding">
 
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:padding="20dp"
         android:orientation="vertical">
 
         <TextView
diff --git a/apps/CtsVerifier/res/layout/ble_advertiser_hardware_scan_filter.xml b/apps/CtsVerifier/res/layout/ble_advertiser_hardware_scan_filter.xml
index a545727..a20dea4 100644
--- a/apps/CtsVerifier/res/layout/ble_advertiser_hardware_scan_filter.xml
+++ b/apps/CtsVerifier/res/layout/ble_advertiser_hardware_scan_filter.xml
@@ -17,8 +17,7 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:orientation="vertical"
-        android:padding="10dip"
-        >
+        style="@style/RootLayoutPadding">
     <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
diff --git a/apps/CtsVerifier/res/layout/ble_advertiser_power_level.xml b/apps/CtsVerifier/res/layout/ble_advertiser_power_level.xml
index c8e0133..5a4ef24 100644
--- a/apps/CtsVerifier/res/layout/ble_advertiser_power_level.xml
+++ b/apps/CtsVerifier/res/layout/ble_advertiser_power_level.xml
@@ -17,8 +17,7 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:orientation="vertical"
-        android:padding="10dip"
-        >
+        style="@style/RootLayoutPadding">
     <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
             android:layout_width="fill_parent"
             android:layout_height="wrap_content">
diff --git a/apps/CtsVerifier/res/layout/ble_advertiser_test.xml b/apps/CtsVerifier/res/layout/ble_advertiser_test.xml
index 7db2b4e..58b7e56 100644
--- a/apps/CtsVerifier/res/layout/ble_advertiser_test.xml
+++ b/apps/CtsVerifier/res/layout/ble_advertiser_test.xml
@@ -17,8 +17,7 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:orientation="vertical"
-        android:padding="10dip"
-        >
+        style="@style/RootLayoutPadding">
     <ListView android:id="@+id/ble_advertiser_tests"
             android:layout_height="fill_parent"
             android:layout_width="match_parent"
diff --git a/apps/CtsVerifier/res/layout/bt_device_picker.xml b/apps/CtsVerifier/res/layout/bt_device_picker.xml
index 48a4b43..3c0d4bc 100644
--- a/apps/CtsVerifier/res/layout/bt_device_picker.xml
+++ b/apps/CtsVerifier/res/layout/bt_device_picker.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2011 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.
@@ -14,69 +13,78 @@
      limitations under the License.
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/RootLayoutPadding"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <ProgressBar
+        android:id="@+id/bt_progress_bar"
+        style="@android:style/Widget.DeviceDefault.ProgressBar.Horizontal"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:orientation="vertical"
-        >
+        android:layout_height="4dp"
+        android:indeterminate="true" />
 
-    <ProgressBar android:id="@+id/bt_progress_bar"
-            android:indeterminate="true"
-            android:layout_height="4dp"
-            android:layout_width="match_parent"
-            style="@android:style/Widget.DeviceDefault.ProgressBar.Horizontal"
-            />
-
-    <TextView android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:text="@string/bt_paired_devices"
-            style="?android:attr/listSeparatorTextViewStyle"
-            />
-    <FrameLayout android:orientation="vertical"
+    <ScrollView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+        <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:layout_weight="1"
-            >
-        <ListView android:id="@+id/bt_paired_devices"
+            android:orientation="vertical">
+            <TextView
+                style="?android:attr/listSeparatorTextViewStyle"
                 android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                />
-        <TextView android:id="@+id/bt_empty_paired_devices"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:gravity="center"
-                android:text="@string/bt_no_devices"
-                android:visibility="gone"
-                />
-    </FrameLayout>
-
-    <TextView android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:text="@string/bt_new_devices"
-            style="?android:attr/listSeparatorTextViewStyle"
-            />
-    <FrameLayout android:orientation="vertical"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_weight="1"
-            >
-        <ListView android:id="@+id/bt_new_devices"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                />
-        <TextView android:id="@+id/bt_empty_new_devices"
+                android:layout_height="wrap_content"
+                android:text="@string/bt_paired_devices" />
+            <FrameLayout
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:layout_weight="1"
-                android:gravity="center"
-                android:text="@string/bt_no_devices"
-                android:visibility="gone"
-                />
-    </FrameLayout>
-            
-    <Button android:id="@+id/bt_scan_button"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:drawableTop="@android:drawable/ic_menu_search"
-            android:text="@string/bt_scan"            
-            />
+                android:orientation="vertical">
+                <ListView
+                    android:id="@+id/bt_paired_devices"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent" />
+                <TextView
+                    android:id="@+id/bt_empty_paired_devices"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:gravity="center"
+                    android:text="@string/bt_no_devices"
+                    android:visibility="gone" />
+            </FrameLayout>
+
+            <TextView
+                style="?android:attr/listSeparatorTextViewStyle"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/bt_new_devices" />
+            <FrameLayout
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_weight="1"
+                android:orientation="vertical">
+                <ListView
+                    android:id="@+id/bt_new_devices"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent" />
+                <TextView
+                    android:id="@+id/bt_empty_new_devices"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:layout_weight="1"
+                    android:gravity="center"
+                    android:text="@string/bt_no_devices"
+                    android:visibility="gone" />
+            </FrameLayout>
+
+            <Button
+                android:id="@+id/bt_scan_button"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:drawableTop="@android:drawable/ic_menu_search"
+                android:text="@string/bt_scan" />
+        </LinearLayout>
+    </ScrollView>
 </LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/bt_messages.xml b/apps/CtsVerifier/res/layout/bt_messages.xml
index 1504431..0d5100e 100644
--- a/apps/CtsVerifier/res/layout/bt_messages.xml
+++ b/apps/CtsVerifier/res/layout/bt_messages.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2011 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.
@@ -14,69 +13,78 @@
      limitations under the License.
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:orientation="vertical"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        >
+    style="@style/RootLayoutPadding"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
 
-    <ProgressBar android:id="@+id/bt_progress_bar"
-        android:indeterminate="true"
-        android:layout_height="4dp"
-        android:layout_width="match_parent"
+    <ProgressBar
+        android:id="@+id/bt_progress_bar"
         style="@android:style/Widget.DeviceDefault.ProgressBar.Horizontal"
-        />
+        android:layout_width="match_parent"
+        android:layout_height="4dp"
+        android:indeterminate="true" />
 
-    <TextView android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:text="@string/bt_sent_messages"
-            style="?android:attr/listSeparatorTextViewStyle"
-            />
-    <FrameLayout android:orientation="vertical"
+    <ScrollView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+        <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:layout_weight="1"
-            >
-        <ListView android:id="@+id/bt_sent_messages"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                />
-        <TextView android:id="@+id/bt_empty_sent_messages"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:gravity="center"
-                android:visibility="gone"
-                />
-    </FrameLayout>
+            android:orientation="vertical">
 
-    <TextView android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:text="@string/bt_received_messages"
-            style="?android:attr/listSeparatorTextViewStyle"
-            />
-    <FrameLayout android:orientation="vertical"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_weight="1"
-            >
-        <ListView android:id="@+id/bt_received_messages"
+            <TextView
+                style="?android:attr/listSeparatorTextViewStyle"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/bt_sent_messages" />
+            <FrameLayout
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
-                />
-        <TextView android:id="@+id/bt_empty_received_messages"
+                android:layout_weight="1"
+                android:orientation="vertical">
+                <ListView
+                    android:id="@+id/bt_sent_messages"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent" />
+                <TextView
+                    android:id="@+id/bt_empty_sent_messages"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:gravity="center"
+                    android:visibility="gone" />
+            </FrameLayout>
+
+            <TextView
+                style="?android:attr/listSeparatorTextViewStyle"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/bt_received_messages" />
+            <FrameLayout
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
-                android:gravity="center"
-                android:visibility="gone"
-                />
-    </FrameLayout>
+                android:layout_weight="1"
+                android:orientation="vertical">
+                <ListView
+                    android:id="@+id/bt_received_messages"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent" />
+                <TextView
+                    android:id="@+id/bt_empty_received_messages"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:gravity="center"
+                    android:visibility="gone" />
+            </FrameLayout>
 
-    <Button android:id="@+id/bt_make_discoverable_button"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:drawableTop="@android:drawable/ic_menu_mylocation"
-            android:text="@string/bt_make_discoverable"
-            />
-            
-    <include layout="@layout/pass_fail_buttons" />
+            <Button
+                android:id="@+id/bt_make_discoverable_button"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:drawableTop="@android:drawable/ic_menu_mylocation"
+                android:text="@string/bt_make_discoverable" />
 
+            <include layout="@layout/pass_fail_buttons" />
+        </LinearLayout>
+    </ScrollView>
 </LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/bt_toggle.xml b/apps/CtsVerifier/res/layout/bt_toggle.xml
index 71def84..e3c00b7 100644
--- a/apps/CtsVerifier/res/layout/bt_toggle.xml
+++ b/apps/CtsVerifier/res/layout/bt_toggle.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2011 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.
@@ -14,31 +13,29 @@
      limitations under the License.
 -->
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+    <TextView
+        style="@style/InstructionsFont"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:orientation="vertical"
-        android:padding="10dip"
-        >
-    <TextView android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_alignParentTop="true"
-            android:gravity="center"
-            android:text="@string/bt_toggle_instructions"
-            style="@style/InstructionsFont"
-            />
+        android:layout_height="wrap_content"
+        android:layout_alignParentTop="true"
+        android:gravity="center"
+        android:text="@string/bt_toggle_instructions" />
 
-    <ToggleButton android:id="@+id/bt_toggle_button"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_centerInParent="true"
-            android:textOn="@string/bt_disable_bluetooth"
-            android:textOff="@string/bt_enable_bluetooth"
-            />
-            
-    <include android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_alignParentBottom="true"
-            layout="@layout/pass_fail_buttons" 
-            />
+    <ToggleButton
+        android:id="@+id/bt_toggle_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerInParent="true"
+        android:textOff="@string/bt_enable_bluetooth"
+        android:textOn="@string/bt_disable_bluetooth" />
+
+    <include
+        layout="@layout/pass_fail_buttons"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true" />
 
 </RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/ca_boot_notify.xml b/apps/CtsVerifier/res/layout/ca_boot_notify.xml
index f56209d..262c6ad 100644
--- a/apps/CtsVerifier/res/layout/ca_boot_notify.xml
+++ b/apps/CtsVerifier/res/layout/ca_boot_notify.xml
@@ -14,60 +14,59 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<com.android.cts.verifier.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-    <LinearLayout app:ctsv_layout_box="all"
-      android:orientation="vertical" android:layout_width="fill_parent"
-      android:layout_height="fill_parent">
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/RootLayoutPadding"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical">
 
-      <ScrollView
+    <ScrollView
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:layout_alignParentTop="true" >
+        android:layout_alignParentTop="true">
 
         <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-          android:orientation="vertical"
-          android:layout_width="fill_parent"
-          android:layout_height="wrap_content">
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
 
-          <TextView
-              android:id="@+id/check_cert_desc"
-              android:layout_width="wrap_content"
-              android:layout_height="wrap_content"
-              android:text="@string/caboot_check_cert_installed"/>
+            <TextView
+                android:id="@+id/check_cert_desc"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/caboot_check_cert_installed" />
 
-          <Button android:id="@+id/check_creds"
-              android:layout_width="wrap_content"
-              android:layout_height="wrap_content"
-              android:text="@string/caboot_check_creds" />
+            <Button
+                android:id="@+id/check_creds"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/caboot_check_creds" />
 
-          <TextView
-              android:id="@+id/need_to_install_cert"
-              android:layout_width="wrap_content"
-              android:layout_height="wrap_content"
-              android:text="@string/caboot_if_not_installed"/>
+            <TextView
+                android:id="@+id/need_to_install_cert"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/caboot_if_not_installed" />
 
-          <Button android:id="@+id/install"
-              android:layout_width="wrap_content"
-              android:layout_height="wrap_content"
-              android:text="@string/caboot_install_cert" />
+            <Button
+                android:id="@+id/install"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/caboot_install_cert" />
 
-          <TextView
-              android:id="@+id/reboot"
-              android:layout_width="wrap_content"
-              android:layout_height="wrap_content"
-              android:text="@string/caboot_reboot_desc"/>
+            <TextView
+                android:id="@+id/reboot"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/caboot_reboot_desc" />
 
-          <TextView
-              android:id="@+id/after_reboot"
-              android:layout_width="wrap_content"
-              android:layout_height="wrap_content"
-              android:text="@string/caboot_after_boot"/>
+            <TextView
+                android:id="@+id/after_reboot"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/caboot_after_boot" />
 
-          <include layout="@layout/pass_fail_buttons" />
+            <include layout="@layout/pass_fail_buttons" />
         </LinearLayout>
-      </ScrollView>
-    </LinearLayout>
-</com.android.cts.verifier.BoxInsetLayout>
+    </ScrollView>
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/cainstallnotify_main.xml b/apps/CtsVerifier/res/layout/cainstallnotify_main.xml
index 0182a0f..b5feeea 100644
--- a/apps/CtsVerifier/res/layout/cainstallnotify_main.xml
+++ b/apps/CtsVerifier/res/layout/cainstallnotify_main.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
      Copyright (C) 2013 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,37 +13,31 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<com.android.cts.verifier.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/RootLayoutPadding"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
-    <LinearLayout xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+
+    <ScrollView
+        android:id="@+id/ca_notify_test_scroller"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:orientation="vertical"
-        android:padding="10dip" >
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:orientation="vertical">
 
-        <ScrollView
-            android:id="@+id/ca_notify_test_scroller"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_weight="1"
-            android:orientation="vertical"
-            android:padding="10dip" >
-
-            <LinearLayout
-                android:id="@+id/ca_notify_test_items"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:orientation="vertical" >
-            </LinearLayout>
-        </ScrollView>
-
-        <include
+        <LinearLayout
+            android:id="@+id/ca_notify_test_items"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_weight="0"
-            layout="@layout/pass_fail_buttons" />
+            android:orientation="vertical" />
+    </ScrollView>
 
-    </LinearLayout>
-</com.android.cts.verifier.BoxInsetLayout>
+    <include
+        layout="@layout/pass_fail_buttons"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="0" />
+
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/da_policy_main.xml b/apps/CtsVerifier/res/layout/da_policy_main.xml
index b80649e..0f680e9 100644
--- a/apps/CtsVerifier/res/layout/da_policy_main.xml
+++ b/apps/CtsVerifier/res/layout/da_policy_main.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2011 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.
@@ -13,46 +12,49 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:orientation="vertical"
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/RootLayoutPadding"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        >
-
-    <ListView android:id="@id/android:list"
+        android:orientation="vertical">
+        <ListView
+            android:id="@id/android:list"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_weight="1"
-            />
+            android:layout_weight="1" />
 
-    <TextView android:id="@id/android:empty"
+        <TextView
+            android:id="@id/android:empty"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
             android:layout_gravity="center_vertical"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
             android:layout_weight="1"
             android:padding="10dip"
             android:text="@string/da_no_policy"
-            android:textSize="18dip"
-            />
+            android:textSize="18dip" />
 
-    <LinearLayout android:orientation="horizontal"
+        <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            >
-        <Button android:id="@+id/generate_policy_button"
+            android:orientation="horizontal">
+            <Button
+                android:id="@+id/generate_policy_button"
                 android:layout_width="1dip"
                 android:layout_height="wrap_content"
                 android:layout_weight="1"
-                android:text="@string/da_generate_policy"
-                />
-        <Button android:id="@+id/apply_policy_button"
+                android:text="@string/da_generate_policy" />
+            <Button
+                android:id="@+id/apply_policy_button"
                 android:layout_width="1dip"
                 android:layout_height="wrap_content"
                 android:layout_weight="1"
-                android:text="@string/da_apply_policy"
-                />
+                android:text="@string/da_apply_policy" />
+        </LinearLayout>
+
+        <include layout="@layout/pass_fail_buttons" />
     </LinearLayout>
-
-    <include layout="@layout/pass_fail_buttons" />
-
-</LinearLayout>
+</ScrollView>
diff --git a/apps/CtsVerifier/res/layout/fs_main.xml b/apps/CtsVerifier/res/layout/fs_main.xml
index 40b74e9..90d48e5 100644
--- a/apps/CtsVerifier/res/layout/fs_main.xml
+++ b/apps/CtsVerifier/res/layout/fs_main.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2010 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.
@@ -13,32 +12,30 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<com.android.cts.verifier.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/RootLayoutPadding"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
-    <LinearLayout app:ctsv_layout_box="all"
-             android:orientation="vertical"
-             android:layout_width="match_parent"
-             android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:orientation="vertical">
 
-         <TextView android:id="@+id/fs_warnings"
-                   android:layout_width="wrap_content"
-                   android:layout_height="wrap_content"
-                   android:text="@string/empty"/>
+    <TextView
+        android:id="@+id/fs_warnings"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/empty" />
 
-         <ListView android:id="@id/android:list"
-                   android:layout_width="match_parent"
-                   android:layout_height="match_parent"
-                   android:layout_weight="1"
-                   android:drawSelectorOnTop="false"/>
+    <ListView
+        android:id="@id/android:list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:drawSelectorOnTop="false" />
 
-         <TextView android:id="@id/android:empty"
-                   android:layout_width="match_parent"
-                   android:layout_height="match_parent"
-                   android:text="@string/fs_no_data"/>
+    <TextView
+        android:id="@id/android:empty"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:text="@string/fs_no_data" />
 
-        <include layout="@layout/pass_fail_buttons" />
-
-    </LinearLayout>
-</com.android.cts.verifier.BoxInsetLayout>
+    <include layout="@layout/pass_fail_buttons" />
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/hifi_ultrasound.xml b/apps/CtsVerifier/res/layout/hifi_ultrasound.xml
index 7d2de5a..8ad3fbd 100644
--- a/apps/CtsVerifier/res/layout/hifi_ultrasound.xml
+++ b/apps/CtsVerifier/res/layout/hifi_ultrasound.xml
@@ -14,17 +14,19 @@
      limitations under the License.
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
               android:layout_width="match_parent"
               android:layout_height="match_parent"
-              android:orientation="vertical">
+              style="@style/RootLayoutPadding">
+
+<LinearLayout
+      android:layout_width="match_parent"
+      android:layout_height="match_parent"
+      android:orientation="vertical">
 
   <TextView
       android:layout_width="match_parent"
-      android:layout_height="0dp"
-      android:layout_weight="7"
-      android:scrollbars="vertical"
-      android:gravity="bottom"
+      android:layout_height="wrap_content"
       android:id="@+id/info_text"/>
 
   <LinearLayout
@@ -46,6 +48,6 @@
         android:id="@+id/player_button"/>
   </LinearLayout>
 
-  <include layout="@layout/pass_fail_buttons" />
-
-</LinearLayout>
+      <include layout="@layout/pass_fail_buttons" />
+      </LinearLayout>
+</ScrollView>
diff --git a/apps/CtsVerifier/res/layout/intent_driven_test.xml b/apps/CtsVerifier/res/layout/intent_driven_test.xml
index dbb54c9..794a6d6 100644
--- a/apps/CtsVerifier/res/layout/intent_driven_test.xml
+++ b/apps/CtsVerifier/res/layout/intent_driven_test.xml
@@ -1,36 +1,32 @@
 <?xml version="1.0" encoding="utf-8"?>
 
-<com.android.cts.verifier.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
-    <LinearLayout app:ctsv_layout_box="all"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    style="@style/RootLayoutPadding">
+
+    <ScrollView
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:orientation="vertical">
-
-        <ScrollView
+        android:layout_height="0dp"
+        android:layout_weight="1">
+        <TextView android:id="@+id/info"
             android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_weight="1">
-            <TextView android:id="@+id/info"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:textSize="18sp"
-                android:padding="5dp"
-                android:text="@string/dc_start_alarm_test_info"/>
-        </ScrollView>
+            android:layout_height="wrap_content"
+            android:textSize="18sp"
+            android:padding="5dp"
+            android:text="@string/dc_start_alarm_test_info"/>
+    </ScrollView>
 
-        <LinearLayout android:id="@+id/buttons"
-            android:orientation="horizontal"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"/>
+    <LinearLayout android:id="@+id/buttons"
+        android:orientation="horizontal"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"/>
 
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content">
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
 
-            <include layout="@layout/pass_fail_buttons"/>
-        </LinearLayout>
+        <include layout="@layout/pass_fail_buttons"/>
     </LinearLayout>
-</com.android.cts.verifier.BoxInsetLayout>
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/its_main.xml b/apps/CtsVerifier/res/layout/its_main.xml
index 2f5eade..26f15bb 100644
--- a/apps/CtsVerifier/res/layout/its_main.xml
+++ b/apps/CtsVerifier/res/layout/its_main.xml
@@ -21,4 +21,14 @@
 
     <include layout="@layout/pass_fail_buttons" />
 
+    <TextView
+        android:id="@+id/its_progress"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="bottom"
+        android:padding="2dp"
+        android:scrollbars = "vertical"
+        android:text="@string/its_test_progress"
+        android:textSize="16sp" />
+
 </LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/js_charging.xml b/apps/CtsVerifier/res/layout/js_charging.xml
index e0986ba..306d02d 100644
--- a/apps/CtsVerifier/res/layout/js_charging.xml
+++ b/apps/CtsVerifier/res/layout/js_charging.xml
@@ -1,20 +1,36 @@
-<?xml version="1.0" encoding="utf-8"?>
-<com.android.cts.verifier.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
+<?xml version="1.0" encoding="utf-8"?><!--
+     Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/RootLayoutPadding"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
-    <ScrollView app:ctsv_layout_box="all"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <ScrollView
         android:layout_width="match_parent"
         android:layout_height="match_parent">
         <LinearLayout
-            android:orientation="vertical"
             android:layout_width="match_parent"
-            android:layout_height="match_parent">
+            android:layout_height="match_parent"
+            android:orientation="vertical">
             <TextView
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:text="@string/js_test_description"
-                android:layout_margin="@dimen/js_padding"/>
+                android:layout_margin="@dimen/js_padding"
+                android:text="@string/js_test_description"/>
             <TextView
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
@@ -26,9 +42,9 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center"
-                android:text="@string/js_start_test_text"
+                android:enabled="false"
                 android:onClick="startTest"
-                android:enabled="false"/>
+                android:text="@string/js_start_test_text"/>
             <TextView
                 android:id="@+id/js_waiting_for_charging_text_view"
                 android:layout_width="match_parent"
@@ -55,14 +71,14 @@
             <LinearLayout
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/js_padding"
-                android:layout_marginBottom="@dimen/js_padding">
+                android:layout_marginBottom="@dimen/js_padding"
+                android:layout_marginTop="@dimen/js_padding">
                 <ImageView
                     android:id="@+id/charging_on_test_image"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:src="@drawable/fs_indeterminate"
-                    android:layout_marginRight="@dimen/js_padding"/>
+                    android:layout_marginRight="@dimen/js_padding"
+                    android:src="@drawable/fs_indeterminate"/>
                 <TextView
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
@@ -78,21 +94,21 @@
             <LinearLayout
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/js_padding"
-                android:layout_marginBottom="@dimen/js_padding">
+                android:layout_marginBottom="@dimen/js_padding"
+                android:layout_marginTop="@dimen/js_padding">
                 <ImageView
                     android:id="@+id/charging_off_test_image"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:src="@drawable/fs_indeterminate"
-                    android:layout_marginRight="@dimen/js_padding"/>
+                    android:layout_marginRight="@dimen/js_padding"
+                    android:src="@drawable/fs_indeterminate"/>
                 <TextView
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:text="@string/js_charging_off_test"
                     android:textSize="16dp"/>
             </LinearLayout>
-            <include layout="@layout/pass_fail_buttons" />
+            <include layout="@layout/pass_fail_buttons"/>
         </LinearLayout>
     </ScrollView>
-</com.android.cts.verifier.BoxInsetLayout>
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/js_connectivity.xml b/apps/CtsVerifier/res/layout/js_connectivity.xml
index 0fbd48f..923d19e 100644
--- a/apps/CtsVerifier/res/layout/js_connectivity.xml
+++ b/apps/CtsVerifier/res/layout/js_connectivity.xml
@@ -1,25 +1,40 @@
-<?xml version="1.0" encoding="utf-8"?>
-<com.android.cts.verifier.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
+<?xml version="1.0" encoding="utf-8"?><!--
+     Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/RootLayoutPadding"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
-    <ScrollView app:ctsv_layout_box="all"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+    <ScrollView
         android:layout_width="match_parent"
         android:layout_height="match_parent">
         <LinearLayout
-            android:orientation="vertical" android:layout_width="match_parent"
-            android:layout_height="match_parent">
+            android:layout_width="match_parent" android:layout_height="match_parent"
+            android:orientation="vertical">
             <TextView
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:text="@string/js_test_description"
-                android:layout_margin="@dimen/js_padding"/>
+                android:layout_margin="@dimen/js_padding"
+                android:text="@string/js_test_description"/>
 
             <TextView
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:text="@string/js_connectivity_description_1"
                 android:layout_margin="@dimen/js_padding"
+                android:text="@string/js_connectivity_description_1"
                 android:textStyle="bold"/>
 
             <Button
@@ -27,21 +42,21 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center"
-                android:text="@string/js_start_test_text"
+                android:enabled="false"
                 android:onClick="startTest"
-                android:enabled="false"/>
+                android:text="@string/js_start_test_text"/>
 
             <LinearLayout
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/js_padding"
-                android:layout_marginBottom="@dimen/js_padding">
+                android:layout_marginBottom="@dimen/js_padding"
+                android:layout_marginTop="@dimen/js_padding">
                 <ImageView
                     android:id="@+id/connectivity_off_test_unmetered_image"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:src="@drawable/fs_indeterminate"
-                    android:layout_marginRight="@dimen/js_padding"/>
+                    android:layout_marginRight="@dimen/js_padding"
+                    android:src="@drawable/fs_indeterminate"/>
                 <TextView
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
@@ -52,14 +67,14 @@
             <LinearLayout
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/js_padding"
-                android:layout_marginBottom="@dimen/js_padding">
+                android:layout_marginBottom="@dimen/js_padding"
+                android:layout_marginTop="@dimen/js_padding">
                 <ImageView
                     android:id="@+id/connectivity_off_test_any_connectivity_image"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:src="@drawable/fs_indeterminate"
-                    android:layout_marginRight="@dimen/js_padding"/>
+                    android:layout_marginRight="@dimen/js_padding"
+                    android:src="@drawable/fs_indeterminate"/>
                 <TextView
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
@@ -70,14 +85,14 @@
             <LinearLayout
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/js_padding"
-                android:layout_marginBottom="@dimen/js_padding">
+                android:layout_marginBottom="@dimen/js_padding"
+                android:layout_marginTop="@dimen/js_padding">
                 <ImageView
                     android:id="@+id/connectivity_off_test_no_connectivity_image"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:src="@drawable/fs_indeterminate"
-                    android:layout_marginRight="@dimen/js_padding"/>
+                    android:layout_marginRight="@dimen/js_padding"
+                    android:src="@drawable/fs_indeterminate"/>
                 <TextView
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
@@ -85,7 +100,7 @@
                     android:textSize="16dp"/>
             </LinearLayout>
 
-            <include layout="@layout/pass_fail_buttons" />
+            <include layout="@layout/pass_fail_buttons"/>
         </LinearLayout>
     </ScrollView>
-</com.android.cts.verifier.BoxInsetLayout>
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/js_idle.xml b/apps/CtsVerifier/res/layout/js_idle.xml
index 732f503..620ed97 100644
--- a/apps/CtsVerifier/res/layout/js_idle.xml
+++ b/apps/CtsVerifier/res/layout/js_idle.xml
@@ -1,48 +1,61 @@
-<?xml version="1.0" encoding="utf-8"?>
-<com.android.cts.verifier.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
+<?xml version="1.0" encoding="utf-8"?><!--
+     Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
-    <ScrollView app:ctsv_layout_box="all"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+    <ScrollView
         android:layout_width="match_parent"
         android:layout_height="match_parent">
-        <LinearLayout
-            android:orientation="vertical"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent">
+        <LinearLayout android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:orientation="vertical">
             <TextView
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:text="@string/js_test_description"
-                android:layout_margin="@dimen/js_padding"/>
+                android:layout_margin="@dimen/js_padding"
+                android:text="@string/js_test_description"/>
             <Button
                 android:id="@+id/js_idle_start_test_button"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center"
-                android:text="@string/js_start_test_text"
+                android:enabled="false"
                 android:onClick="startTest"
-                android:enabled="false"/>
+                android:text="@string/js_start_test_text"/>
             <TextView
                 android:id="@+id/js_idle_continue_instruction_view"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:text="@string/js_idle_continue_instruction"
                 android:layout_margin="@dimen/js_padding"
+                android:text="@string/js_idle_continue_instruction"
                 android:textStyle="bold"
                 android:visibility="gone"/>
 
             <LinearLayout
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/js_padding"
-                android:layout_marginBottom="@dimen/js_padding">
+                android:layout_marginBottom="@dimen/js_padding"
+                android:layout_marginTop="@dimen/js_padding">
                 <ImageView
                     android:id="@+id/idle_off_test_image"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:src="@drawable/fs_indeterminate"
-                    android:layout_marginRight="@dimen/js_padding"/>
+                    android:layout_marginRight="@dimen/js_padding"
+                    android:src="@drawable/fs_indeterminate"/>
                 <TextView
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
@@ -52,21 +65,22 @@
             <LinearLayout
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/js_padding"
-                android:layout_marginBottom="@dimen/js_padding">
+                android:layout_marginBottom="@dimen/js_padding"
+                android:layout_marginTop="@dimen/js_padding">
                 <ImageView
                     android:id="@+id/idle_on_test_image"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:src="@drawable/fs_indeterminate"
-                    android:layout_marginRight="@dimen/js_padding"/>
+                    android:layout_marginRight="@dimen/js_padding"
+                    android:src="@drawable/fs_indeterminate"/>
                 <TextView
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:text="@string/js_idle_item_idle_on"
                     android:textSize="16dp"/>
             </LinearLayout>
-            <include layout="@layout/pass_fail_buttons" />
+
+            <include layout="@layout/pass_fail_buttons"/>
         </LinearLayout>
     </ScrollView>
-</com.android.cts.verifier.BoxInsetLayout>
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/keychain_main.xml b/apps/CtsVerifier/res/layout/keychain_main.xml
index b134908..e31cac8 100644
--- a/apps/CtsVerifier/res/layout/keychain_main.xml
+++ b/apps/CtsVerifier/res/layout/keychain_main.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
      Copyright (C) 2015 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,23 +13,22 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<com.android.cts.verifier.BoxInsetLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/RootLayoutPadding"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:orientation="vertical">
 
-    <LinearLayout xmlns:app="http://schemas.android.com/apk/res-auto"
+    <ScrollView
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:orientation="vertical"
-        android:padding="10dip">
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:fillViewport="true">
 
-        <ScrollView
+        <LinearLayout
             android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_weight="1"
-            android:fillViewport="true">
+            android:layout_height="match_parent"
+            android:orientation="vertical">
 
             <LinearLayout
                 android:id="@+id/test_messages"
@@ -53,43 +51,43 @@
                     android:orientation="vertical" />
 
             </LinearLayout>
-        </ScrollView>
 
-        <LinearLayout
-            android:id="@+id/action_buttons"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_weight="0"
-            android:orientation="horizontal">
+            <LinearLayout
+                android:id="@+id/action_buttons"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_weight="0"
+                android:orientation="horizontal">
 
-            <Button
-                android:id="@+id/action_reset"
-                android:text="@string/keychain_reset"
-                android:layout_weight="1"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content" />
+                <Button
+                    android:id="@+id/action_reset"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:text="@string/keychain_reset" />
 
-            <Button
-                android:id="@+id/action_skip"
-                android:text="@string/keychain_skip"
-                android:layout_weight="1"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content" />
+                <Button
+                    android:id="@+id/action_skip"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:text="@string/keychain_skip" />
 
-            <Button
-                android:id="@+id/action_next"
-                android:text="@string/next_button_text"
-                android:layout_weight="1"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content" />
+                <Button
+                    android:id="@+id/action_next"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:text="@string/next_button_text" />
 
+            </LinearLayout>
         </LinearLayout>
+    </ScrollView>
 
-        <include
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_weight="0"
-            layout="@layout/pass_fail_buttons" />
+    <include
+        layout="@layout/pass_fail_buttons"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="0" />
 
-    </LinearLayout>
-</com.android.cts.verifier.BoxInsetLayout>
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/list_content.xml b/apps/CtsVerifier/res/layout/list_content.xml
index e7de596..decef55 100644
--- a/apps/CtsVerifier/res/layout/list_content.xml
+++ b/apps/CtsVerifier/res/layout/list_content.xml
@@ -15,14 +15,12 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License
   -->
-<com.android.cts.verifier.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <ListView
-        android:id="@android:id/list"
-        app:ctsv_layout_box="all"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-</com.android.cts.verifier.BoxInsetLayout>
+    android:layout_height="match_parent"
+    style="@style/RootLayoutPadding">
+        <ListView
+            android:id="@android:id/list"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/location_mode_main.xml b/apps/CtsVerifier/res/layout/location_mode_main.xml
index 58ac069..a9206fa 100644
--- a/apps/CtsVerifier/res/layout/location_mode_main.xml
+++ b/apps/CtsVerifier/res/layout/location_mode_main.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
      Copyright (C) 2013 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,37 +13,31 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<com.android.cts.verifier.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/RootLayoutPadding"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
-    <LinearLayout app:ctsv_layout_box="all"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+    <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:orientation="vertical"
-        android:padding="10dip" >
+        android:orientation="vertical">
 
         <ScrollView
             android:id="@+id/test_scroller"
             android:layout_width="match_parent"
             android:layout_height="0dp"
             android:layout_weight="1"
-            android:orientation="vertical"
-            android:padding="10dip" >
-
+            android:orientation="vertical">
             <LinearLayout
                 android:id="@+id/test_items"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:orientation="vertical" >
+                android:orientation="vertical">
             </LinearLayout>
         </ScrollView>
 
-        <include
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_weight="0"
-            layout="@layout/pass_fail_buttons" />
+        <include layout="@layout/pass_fail_buttons"/>
 
     </LinearLayout>
-</com.android.cts.verifier.BoxInsetLayout>
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/network_screen_off.xml b/apps/CtsVerifier/res/layout/network_screen_off.xml
index 5a2446d..c0eeee8 100644
--- a/apps/CtsVerifier/res/layout/network_screen_off.xml
+++ b/apps/CtsVerifier/res/layout/network_screen_off.xml
@@ -15,7 +15,8 @@
 -->
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="match_parent"
-        android:layout_height="match_parent">
+        android:layout_height="match_parent"
+        style="@style/RootLayoutPadding">
 
     <Button android:id="@+id/start_btn"
             android:text="@string/network_screen_off_test_start"
diff --git a/apps/CtsVerifier/res/layout/nls_main.xml b/apps/CtsVerifier/res/layout/nls_main.xml
index 0ee4cbf..24dfb91 100644
--- a/apps/CtsVerifier/res/layout/nls_main.xml
+++ b/apps/CtsVerifier/res/layout/nls_main.xml
@@ -18,15 +18,14 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical"
-    android:padding="10dip" >
+    style="@style/RootLayoutPadding">
 
     <ScrollView
         android:id="@+id/nls_test_scroller"
         android:layout_width="match_parent"
         android:layout_height="0dp"
         android:layout_weight="1"
-        android:orientation="vertical"
-        android:padding="10dip" >
+        android:orientation="vertical">
 
         <LinearLayout
             android:id="@+id/nls_test_items"
diff --git a/apps/CtsVerifier/res/layout/pa_main.xml b/apps/CtsVerifier/res/layout/pa_main.xml
index b748123..a08daf0 100644
--- a/apps/CtsVerifier/res/layout/pa_main.xml
+++ b/apps/CtsVerifier/res/layout/pa_main.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2014 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.
@@ -13,24 +12,19 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<com.android.cts.verifier.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
-    <RelativeLayout app:ctsv_layout_box="all"
+
+    <include
+        android:id="@+id/pass_fail_buttons"
+        layout="@layout/pass_fail_buttons"
+        android:layout_gravity="top" />
+
+    <TextureView
+        android:id="@+id/texture_view"
         android:layout_width="match_parent"
-        android:layout_height="match_parent" >
+        android:layout_height="match_parent"
+        android:layout_below="@id/pass_fail_buttons" />
 
-        <include
-            android:id="@+id/pass_fail_buttons"
-            android:layout_gravity="top"
-            layout="@layout/pass_fail_buttons" />
-
-        <TextureView
-            android:id="@+id/texture_view"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_below="@id/pass_fail_buttons" />
-
-    </RelativeLayout>
-</com.android.cts.verifier.BoxInsetLayout>
+</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/pass_fail_list.xml b/apps/CtsVerifier/res/layout/pass_fail_list.xml
index 575e630..20e3c3b 100644
--- a/apps/CtsVerifier/res/layout/pass_fail_list.xml
+++ b/apps/CtsVerifier/res/layout/pass_fail_list.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2011 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.
@@ -13,30 +12,23 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<com.android.cts.verifier.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/RootLayoutPadding"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:orientation="vertical">
 
-    <LinearLayout app:ctsv_layout_box="all"
-            android:orientation="vertical"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            >
+    <ListView
+        android:id="@+id/android:list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_weight="1" />
 
-        <ListView android:id="@id/android:list"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:layout_weight="1"
-                />
+    <TextView
+        android:id="@+id/android:empty"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_weight="1" />
 
-        <TextView android:id="@id/android:empty"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:layout_weight="1"
-                />
-
-        <include layout="@layout/pass_fail_buttons" />
-
-    </LinearLayout>
-</com.android.cts.verifier.BoxInsetLayout>
+    <include layout="@layout/pass_fail_buttons" />
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/pass_fail_text.xml b/apps/CtsVerifier/res/layout/pass_fail_text.xml
index e6b6a73..99d0b7a 100644
--- a/apps/CtsVerifier/res/layout/pass_fail_text.xml
+++ b/apps/CtsVerifier/res/layout/pass_fail_text.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2011 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.
@@ -14,21 +13,21 @@
      limitations under the License.
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:orientation="vertical"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        >
+    style="@style/RootLayoutPadding"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
 
-    <ScrollView android:id="@+id/scroll"
+    <ScrollView
+        android:id="@+id/scroll"
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1">
+        <TextView
+            android:id="@+id/text"
+            style="@style/InstructionsFont"
             android:layout_width="match_parent"
-            android:layout_height="0dip"
-            android:layout_weight="1"
-            >
-        <TextView android:id="@+id/text"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                style="@style/InstructionsFont"
-                />
+            android:layout_height="wrap_content" />
     </ScrollView>
 
     <include layout="@layout/pass_fail_buttons" />
diff --git a/apps/CtsVerifier/res/layout/pla_list.xml b/apps/CtsVerifier/res/layout/pla_list.xml
index 0973136..83dac69 100644
--- a/apps/CtsVerifier/res/layout/pla_list.xml
+++ b/apps/CtsVerifier/res/layout/pla_list.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2014 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.
@@ -14,14 +13,14 @@
      limitations under the License.
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/RootLayoutPadding"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
-    android:orientation="vertical" >
+    android:orientation="vertical">
 
     <ListView
         android:id="@+id/pla_list"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content" >
-    </ListView>
+        android:layout_height="wrap_content" />
 
 </LinearLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/layout/poa_main.xml b/apps/CtsVerifier/res/layout/poa_main.xml
index b3c5588..f43b458 100644
--- a/apps/CtsVerifier/res/layout/poa_main.xml
+++ b/apps/CtsVerifier/res/layout/poa_main.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2014 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.
@@ -13,22 +12,22 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<com.android.cts.verifier.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-    <LinearLayout app:ctsv_layout_box="all"
-        android:layout_width="fill_parent"
-        android:layout_height="fill_parent"
-        android:orientation="vertical" >
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/RootLayoutPadding"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical">
 
-        <include layout="@layout/pass_fail_buttons" />
+    <include layout="@layout/pass_fail_buttons" />
 
+    <ScrollView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
         <TextView
             android:id="@+id/poa_status_text"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:textAppearance="@style/InstructionsFont" />
+    </ScrollView>
 
-    </LinearLayout>
-</com.android.cts.verifier.BoxInsetLayout>
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/poa_touch.xml b/apps/CtsVerifier/res/layout/poa_touch.xml
index 0085227..cba7e98 100644
--- a/apps/CtsVerifier/res/layout/poa_touch.xml
+++ b/apps/CtsVerifier/res/layout/poa_touch.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2014 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.
@@ -15,12 +14,12 @@
 -->
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="match_parent" >
+    android:layout_height="match_parent">
     <com.android.cts.verifier.projection.offscreen.ColorChangeOnKeyView
         android:id="@+id/multi_touch_view"
-        android:focusable="true"
-        android:focusableInTouchMode="true"
         android:layout_width="match_parent"
-        android:layout_height="match_parent" />
+        android:layout_height="match_parent"
+        android:focusable="true"
+        android:focusableInTouchMode="true" />
 
 </RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/positive_device_owner.xml b/apps/CtsVerifier/res/layout/positive_device_owner.xml
index 2ffb463..fa437de 100644
--- a/apps/CtsVerifier/res/layout/positive_device_owner.xml
+++ b/apps/CtsVerifier/res/layout/positive_device_owner.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2015 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -14,36 +13,38 @@
      limitations under the License.
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:orientation="vertical"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        >
+    style="@style/RootLayoutPadding"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
 
     <ScrollView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+        <LinearLayout
             android:layout_width="match_parent"
-            android:layout_height="150dp"
-            android:layout_weight="2">
-        <TextView
+            android:layout_height="match_parent"
+            android:orientation="vertical">
+
+            <TextView
                 android:id="@+id/positive_device_owner_instructions"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:padding="10dip"
                 android:text="@string/device_owner_positive_tests_instructions"
                 android:textSize="18dip" />
+
+            <Button
+                android:id="@+id/set_device_owner_button"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/set_device_owner_button_label" />
+
+            <ListView
+                android:id="@+id/android:list"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content" />
+
+            <include layout="@layout/pass_fail_buttons" />
+        </LinearLayout>
     </ScrollView>
-
-    <Button
-        android:id="@+id/set_device_owner_button"
-        android:layout_width="204dp"
-        android:layout_height="wrap_content"
-        android:text="@string/set_device_owner_button_label" />
-
-    <ListView
-        android:id="@+id/android:list"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_weight="3" />
-
-    <include layout="@layout/pass_fail_buttons" />
-
 </LinearLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/layout/provisioning_byod.xml b/apps/CtsVerifier/res/layout/provisioning_byod.xml
index 54b5121..227d8d8 100644
--- a/apps/CtsVerifier/res/layout/provisioning_byod.xml
+++ b/apps/CtsVerifier/res/layout/provisioning_byod.xml
@@ -1,12 +1,8 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2011 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.
@@ -14,34 +10,28 @@
      limitations under the License.
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:orientation="vertical"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        >
-
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
     <ScrollView
-            android:layout_width="match_parent"
-            android:layout_height="150dp"
-            android:layout_weight="2">
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="2">
         <TextView
-                android:id="@+id/test_instructions"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:padding="10dip"
-                android:textSize="18dip" />
+            android:id="@+id/test_instructions"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:padding="10dip"
+            android:textSize="18dip"/>
     </ScrollView>
-
     <Button
         android:id="@+id/prepare_test_button"
-        android:layout_width="204dp"
-        android:layout_height="wrap_content" />
-
+        android:layout_width="204dip"
+        android:layout_height="wrap_content"/>
     <ListView
         android:id="@+id/android:list"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_weight="3" />
-
-    <include layout="@layout/pass_fail_buttons" />
-
-</LinearLayout>
\ No newline at end of file
+        android:layout_weight="3"/>
+    <include layout="@layout/pass_fail_buttons"/>
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/pwa_widgets.xml b/apps/CtsVerifier/res/layout/pwa_widgets.xml
index 7ead0cb..cb611b9 100644
--- a/apps/CtsVerifier/res/layout/pwa_widgets.xml
+++ b/apps/CtsVerifier/res/layout/pwa_widgets.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2014 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.
@@ -13,50 +12,50 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<com.android.cts.verifier.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
-     <TextureView
-         app:ctsv_layout_box="all"
-         android:id="@+id/texture_view"
-         android:layout_width="match_parent"
-         android:layout_height="match_parent" />
+    <LinearLayout
+        android:id="@+id/test_controls"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:layout_gravity="top">
 
-     <LinearLayout
-         app:ctsv_layout_box="all"
-         android:layout_width="fill_parent"
-         android:layout_height="wrap_content"
-         android:orientation="vertical" >
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
 
-         <LinearLayout
-             android:layout_width="match_parent"
-             android:layout_height="match_parent" >
+            <include layout="@layout/pass_fail_buttons" />
+        </LinearLayout>
 
-             <include layout="@layout/pass_fail_buttons" />
-         </LinearLayout>
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal">
 
-         <LinearLayout
-             android:layout_width="match_parent"
-             android:layout_height="wrap_content"
-             android:orientation="horizontal" >
+            <Button
+                android:id="@+id/up_button"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:text="@string/pwa_button_up" />
 
-             <Button
-                 android:id="@+id/up_button"
-                 android:layout_width="match_parent"
-                 android:layout_height="wrap_content"
-                 android:layout_weight="1"
-                 android:text="@string/pwa_button_up" />
+            <Button
+                android:id="@+id/down_button"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:text="@string/pwa_button_down" />
 
-             <Button
-                 android:id="@+id/down_button"
-                 android:layout_width="match_parent"
-                 android:layout_height="wrap_content"
-                 android:layout_weight="1"
-                 android:text="@string/pwa_button_down" />
+        </LinearLayout>
+    </LinearLayout>
 
-         </LinearLayout>
-     </LinearLayout>
+    <TextureView
+        android:id="@+id/texture_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_below="@id/test_controls" />
 
-</com.android.cts.verifier.BoxInsetLayout>
+</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/requesting_bugreport_device_owner.xml b/apps/CtsVerifier/res/layout/requesting_bugreport_device_owner.xml
index b2955ec..b83388b 100644
--- a/apps/CtsVerifier/res/layout/requesting_bugreport_device_owner.xml
+++ b/apps/CtsVerifier/res/layout/requesting_bugreport_device_owner.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2016 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -14,36 +13,38 @@
      limitations under the License.
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:orientation="vertical"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        >
+    style="@style/RootLayoutPadding"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
 
     <ScrollView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+        <LinearLayout
             android:layout_width="match_parent"
-            android:layout_height="100dp"
-            android:layout_weight="2">
-        <TextView
+            android:layout_height="match_parent"
+            android:orientation="vertical">
+
+            <TextView
                 android:id="@+id/requesting_bugreport_device_owner_instructions"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:padding="10dip"
                 android:text="@string/device_owner_requesting_bugreport_tests_info"
                 android:textSize="18dip" />
+
+            <Button
+                android:id="@+id/set_device_owner_button"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/set_device_owner_button_label" />
+
+            <ListView
+                android:id="@+id/android:list"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content" />
+
+            <include layout="@layout/pass_fail_buttons" />
+        </LinearLayout>
     </ScrollView>
-
-    <Button
-        android:id="@+id/set_device_owner_button"
-        android:layout_width="204dp"
-        android:layout_height="wrap_content"
-        android:text="@string/set_device_owner_button_label" />
-
-    <ListView
-        android:id="@+id/android:list"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_weight="3" />
-
-    <include layout="@layout/pass_fail_buttons" />
-
 </LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/snsr_hrm.xml b/apps/CtsVerifier/res/layout/snsr_hrm.xml
index 506ba9f..4c6b6ff 100644
--- a/apps/CtsVerifier/res/layout/snsr_hrm.xml
+++ b/apps/CtsVerifier/res/layout/snsr_hrm.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
   ~ Copyright (C) 2014 The Android Open Source Project
   ~
   ~ Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,43 +14,45 @@
   ~ limitations under the License
   -->
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/RootLayoutPadding"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <include
+        android:id="@+id/pass_fail_buttons"
+        layout="@layout/pass_fail_buttons"
         android:layout_width="match_parent"
-        android:layout_height="match_parent">
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true" />
 
-    <include android:id="@+id/pass_fail_buttons"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_alignParentBottom="true"
-            layout="@layout/pass_fail_buttons" />
+    <TextView
+        android:id="@+id/sensor_value"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_above="@+id/sensor_accuracy_value"
+        android:layout_centerInParent="true"
+        android:layout_marginBottom="10dip"
+        android:background="@drawable/gray_bubble"
+        android:drawablePadding="10dip"
+        android:paddingBottom="5dip"
+        android:paddingLeft="10dip"
+        android:paddingRight="10dip"
+        android:paddingTop="5dip"
+        android:textSize="28dip" />
 
-    <TextView android:id="@+id/sensor_value"
-              android:background="@drawable/gray_bubble"
-              android:drawablePadding="10dip"
-              android:layout_above="@+id/sensor_accuracy_value"
-              android:layout_centerInParent="true"
-              android:layout_width="wrap_content"
-              android:layout_height="wrap_content"
-              android:layout_marginBottom="10dip"
-              android:paddingLeft="10dip"
-              android:paddingRight="10dip"
-              android:paddingTop="5dip"
-              android:paddingBottom="5dip"
-              android:textSize="28dip"
-        />
-
-    <TextView android:id="@+id/sensor_accuracy_value"
-              android:background="@drawable/gray_bubble"
-              android:drawablePadding="10dip"
-              android:layout_above="@+id/pass_fail_buttons"
-              android:layout_centerInParent="true"
-              android:layout_width="wrap_content"
-              android:layout_height="wrap_content"
-              android:layout_marginBottom="10dip"
-              android:paddingLeft="10dip"
-              android:paddingRight="10dip"
-              android:paddingTop="5dip"
-              android:paddingBottom="5dip"
-              android:textSize="28dip"
-        />
+    <TextView
+        android:id="@+id/sensor_accuracy_value"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_above="@+id/pass_fail_buttons"
+        android:layout_centerInParent="true"
+        android:layout_marginBottom="10dip"
+        android:background="@drawable/gray_bubble"
+        android:drawablePadding="10dip"
+        android:paddingBottom="5dip"
+        android:paddingLeft="10dip"
+        android:paddingRight="10dip"
+        android:paddingTop="5dip"
+        android:textSize="28dip" />
 
 </RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/snsr_next_button.xml b/apps/CtsVerifier/res/layout/snsr_next_button.xml
index 391c394..78c9f1f 100644
--- a/apps/CtsVerifier/res/layout/snsr_next_button.xml
+++ b/apps/CtsVerifier/res/layout/snsr_next_button.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2013 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.
@@ -14,35 +13,32 @@
      limitations under the License.
 -->
 <GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:orientation="horizontal"
-        android:columnCount="@integer/test_list_footer_button_count"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:columnCount="@integer/test_list_footer_button_count"
+    android:orientation="horizontal"
+    android:paddingBottom="@dimen/snsr_view_padding_bottom"
+    android:paddingTop="@dimen/snsr_view_padding_top">
+
+    <Button
+        android:id="@+id/next_button"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:paddingBottom="@dimen/snsr_view_padding_bottom"
-        android:paddingTop="@dimen/snsr_view_padding_top"
-        >
+        android:text="@string/next_button_text" />
 
-    <Button android:id="@+id/next_button"
-            android:layout_height="wrap_content"
-            android:layout_width="wrap_content"
-            android:layout_columnWeight="1"
-            android:text="@string/next_button_text"
-            />
+    <Button
+        android:id="@+id/pass_button"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:drawableTop="@drawable/fs_good"
+        android:visibility="gone" />
 
-    <Button android:id="@+id/pass_button"
-            android:visibility="gone"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_columnWeight="1"
-            android:drawableTop="@drawable/fs_good"
-            />
-
-    <Button android:id="@+id/fail_button"
-            android:visibility="gone"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_columnWeight="1"
-            android:drawableTop="@drawable/fs_error"
-            />
+    <Button
+        android:id="@+id/fail_button"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_columnWeight="1"
+        android:drawableTop="@drawable/fs_error"
+        android:visibility="gone" />
 
 </GridLayout>
diff --git a/apps/CtsVerifier/res/values-round/styles.xml b/apps/CtsVerifier/res/values-round/styles.xml
new file mode 100644
index 0000000..31e3c17
--- /dev/null
+++ b/apps/CtsVerifier/res/values-round/styles.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <style name="RootLayoutPadding">
+        <item name="android:paddingEnd">?android:listPreferredItemPaddingEnd</item>
+        <item name="android:paddingBottom">?android:dialogPreferredPadding</item>
+        <item name="android:paddingLeft">?android:listPreferredItemPaddingLeft</item>
+        <item name="android:paddingRight">?android:listPreferredItemPaddingRight</item>
+        <item name="android:paddingStart">?android:listPreferredItemPaddingStart</item>
+        <item name="android:paddingTop">?android:dialogPreferredPadding</item>
+    </style>
+</resources>
diff --git a/apps/CtsVerifier/res/values-watch/styles.xml b/apps/CtsVerifier/res/values-watch/styles.xml
new file mode 100644
index 0000000..31e3c17
--- /dev/null
+++ b/apps/CtsVerifier/res/values-watch/styles.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <style name="RootLayoutPadding">
+        <item name="android:paddingEnd">?android:listPreferredItemPaddingEnd</item>
+        <item name="android:paddingBottom">?android:dialogPreferredPadding</item>
+        <item name="android:paddingLeft">?android:listPreferredItemPaddingLeft</item>
+        <item name="android:paddingRight">?android:listPreferredItemPaddingRight</item>
+        <item name="android:paddingStart">?android:listPreferredItemPaddingStart</item>
+        <item name="android:paddingTop">?android:dialogPreferredPadding</item>
+    </style>
+</resources>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index ad6fe9b..dfc5254 100755
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -426,6 +426,7 @@
     <string name="location_gnss_reg_test">GNSS Measurement Registration Test</string>
     <string name="location_gnss_value_test">GNSS Measurement Values Test</string>
     <string name="location_gnss_nav_msg_test">GNSS Navigation Message Test</string>
+    <string name="location_gnss_status_test">GNSS Status Test</string>
     <string name="location_gnss_test_info">This test verifies basic GNSS behavior.
         Make sure the device has line of sight to GNSS satellites
         (for example, stationary on a windowsill.  If needed, try again, outside, also with the
@@ -985,6 +986,10 @@
     </string>
     <string name="its_test_passed">All Camera ITS tests passed.  Pass button enabled!</string>
     <string name="its_test_failed">Some Camera ITS tests failed.</string>
+    <string name="its_version_mismatch">
+        CtsVerifier and ITS script version mismatch. Please update CtsVerifier and ITS script.
+    </string>
+    <string name="its_test_progress">ITS test progress will be shown here.</string>
 
     <!-- Strings for the Camera Flashlight test activity -->
     <string name="camera_flashlight_test">Camera Flashlight</string>
@@ -1194,6 +1199,16 @@
     <string name="package_priority_default">Find \"%s\" in the \"Notifications\" settings panel, and disallow it to Override Do Not Disturb.</string>
     <string name="package_priority_user_order">Check that ranker respects user priorities.</string>
 
+    <string name="shortcut_reset_test">Shortcut Reset Rate-limiting Test</string>
+    <string name="shortcut_reset_info">This test checks that when an inline-reply happens, ShortcutManager\'s rate-limiting
+        is reset.</string>
+    <string name="shortcut_reset_bot">Verifying that the CTS Robot helper package is installed.</string>
+    <string name="shortcut_reset_start">Showing the notification.</string>
+    <string name="shortcut_reset_prompt_inline_reply">Open the notification shade,
+        find the \"Shortcut Reset Rate-limiting Test\" notification, type something in the inline-reply field and
+        press the send button.</string>
+    <string name="shortcut_reset_check_result">Check ShortcutManager rate-limit has been reset.</string>
+
     <string name="attention_test">Notification Attention Management Test</string>
     <string name="attention_info">This test checks that the NotificationManagerService is
         respecting user preferences about notification ranking and filtering.
@@ -2156,9 +2171,12 @@
     <string name="device_owner_disallow_usb_file_transfer_test">Disallow USB file transfer</string>
     <string name="device_owner_disallow_usb_file_transfer_test_info">
             Please press below button to set the \"disallow USB file transfer\" restriction.\n
-            Next, connect your device to your desktop computer through USB, open the USB notification from the status bar
-            and check that the \"Transfer files (MTP)\" and \"Transfer photos (PTP)\" cannot be selected and triggers a support message when trying to select them.\n
-            Also, check that if you can download files from your phone to the desktop computer. The test is successful if the files from your phone are not and cannot be downloaded through USB.\n
+            If a USB notification appears, open the notification and check that the
+            \"Transfer files (MTP)\" and \"Transfer photos (PTP)\" cannot be selected and trigger a
+            support message when trying to select them.\n
+            Check if you can mount the device as a USB drive on your desktop computer. The test is
+            successful if you cannot mount the device, and files from your phone cannot be
+            downloaded through USB.\n
             Please mark the test accordingly.
     </string>
     <string name="device_owner_set_user_icon">Setting the user icon</string>
diff --git a/apps/CtsVerifier/res/values/styles.xml b/apps/CtsVerifier/res/values/styles.xml
index 16fa87f..fa82169 100644
--- a/apps/CtsVerifier/res/values/styles.xml
+++ b/apps/CtsVerifier/res/values/styles.xml
@@ -10,4 +10,12 @@
         <item name="android:textSize">18sp</item>
         <item name="android:padding">5dp</item>
     </style>
+    <style name="RootLayoutPadding">
+      <item name="android:paddingEnd">?android:attr/listPreferredItemPaddingEnd</item>
+      <item name="android:paddingBottom">?android:attr/dialogPreferredPadding</item>
+      <item name="android:paddingLeft">?android:attr/listPreferredItemPaddingLeft</item>
+      <item name="android:paddingRight">?android:attr/listPreferredItemPaddingRight</item>
+      <item name="android:paddingStart">?android:attr/listPreferredItemPaddingStart</item>
+      <item name="android:paddingTop">?android:attr/dialogPreferredPadding</item>
+    </style>
 </resources>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/DialogTestListActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/DialogTestListActivity.java
index 167fd84..6933ef4 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/DialogTestListActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/DialogTestListActivity.java
@@ -21,10 +21,12 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.database.DataSetObserver;
 import android.os.Bundle;
 import android.util.Log;
 import android.view.LayoutInflater;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.Button;
@@ -49,6 +51,7 @@
     private final int mInstructionsStringId;
 
     protected Button mPrepareTestButton;
+    protected ListView mTestFeaturesList;
 
     protected int mCurrentTestPosition;
 
@@ -85,15 +88,31 @@
 
         mCurrentTestPosition = 0;
 
-        TextView instructionTextView = (TextView)findViewById(R.id.test_instructions);
+        TextView instructionTextView = (TextView) findViewById(R.id.test_instructions);
         instructionTextView.setText(mInstructionsStringId);
-        mPrepareTestButton = (Button)findViewById(R.id.prepare_test_button);
+        mPrepareTestButton = (Button) findViewById(R.id.prepare_test_button);
+        mTestFeaturesList = (ListView) findViewById(android.R.id.list);
+        if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
+            mTestFeaturesList.setOnTouchListener((View v, MotionEvent e) -> {
+                switch (e.getAction()) {
+                    case MotionEvent.ACTION_DOWN:
+                        v.getParent().requestDisallowInterceptTouchEvent(true);
+                        break;
+                    case MotionEvent.ACTION_UP:
+                        v.getParent().requestDisallowInterceptTouchEvent(false);
+                        break;
+                    default:
+                }
+                return false;
+            });
+        }
     }
 
     /**
      * Subclasses must add their tests items to the provided adapter(usually instances of
      * {@link DialogTestListItem} or {@link DialogTestListItemWithIcon} but any class deriving from
      * {@link TestListAdapter.TestListItem} will do).
+     *
      * @param adapter The adapter to add test items to.
      */
     protected abstract void setupTests(ArrayTestListAdapter adapter);
@@ -165,7 +184,7 @@
                 .getItem(position);
         if (test instanceof DialogTestListItem) {
             mCurrentTestPosition = position;
-            ((DialogTestListItem)test).performTest(this);
+            ((DialogTestListItem) test).performTest(this);
         } else {
             try {
                 super.handleItemClick(l, v, position, id);
@@ -180,6 +199,7 @@
 
     /**
      * Start a test's manual intent
+     *
      * @param test The test the manual intent of which is to be started.
      * @return true if activity could be started successfully, false otherwise.
      */
@@ -218,6 +238,7 @@
 
         public interface TestCallback {
             void onPass();
+
             void onFail();
         }
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/HifiUltrasoundSpeakerTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/HifiUltrasoundSpeakerTestActivity.java
index dc81e19..f9f5823 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/HifiUltrasoundSpeakerTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/HifiUltrasoundSpeakerTestActivity.java
@@ -41,6 +41,9 @@
 import com.androidplot.xy.XYSeries;
 import com.androidplot.xy.*;
 
+import com.android.compatibility.common.util.CddTest;
+
+@CddTest(requirement="7.8.3")
 public class HifiUltrasoundSpeakerTestActivity extends PassFailButtons.Activity {
 
   public enum Status {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsSerializer.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsSerializer.java
index 193c94c..2a6c146 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsSerializer.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsSerializer.java
@@ -371,7 +371,7 @@
         try {
             Object keyValue = getKeyValue(md, keyObj);
             if (keyValue == null) {
-                return new MetadataEntry(keyName, JSONObject.NULL);
+                return null;
             }
             int arrayLen = Array.getLength(keyValue);
             Type elmtType = ((GenericArrayType)keyType).getGenericComponentType();
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 6f54821..8710096 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
@@ -197,6 +197,8 @@
     private volatile LinkedList<MySensorEvent> mEvents = null;
     private volatile Object mEventLock = new Object();
     private volatile boolean mEventsEnabled = false;
+    private HandlerThread mSensorThread = null;
+    private Handler mSensorHandler = null;
 
     public interface CaptureCallback {
         void onCaptureAvailable(Image capture);
@@ -228,9 +230,15 @@
             mAccelSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
             mMagSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
             mGyroSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
-            mSensorManager.registerListener(this, mAccelSensor, SensorManager.SENSOR_DELAY_FASTEST);
-            mSensorManager.registerListener(this, mMagSensor, SensorManager.SENSOR_DELAY_FASTEST);
-            mSensorManager.registerListener(this, mGyroSensor, SensorManager.SENSOR_DELAY_FASTEST);
+            mSensorThread = new HandlerThread("SensorThread");
+            mSensorThread.start();
+            mSensorHandler = new Handler(mSensorThread.getLooper());
+            mSensorManager.registerListener(this, mAccelSensor,
+                    SensorManager.SENSOR_DELAY_NORMAL, mSensorHandler);
+            mSensorManager.registerListener(this, mMagSensor,
+                    SensorManager.SENSOR_DELAY_NORMAL, mSensorHandler);
+            mSensorManager.registerListener(this, mGyroSensor,
+                    /*200hz*/5000, mSensorHandler);
 
             // Get a handle to the system vibrator.
             mVibrator = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
@@ -291,6 +299,10 @@
                 mSaveThreads[i] = null;
             }
         }
+        if (mSensorThread != null) {
+            mSensorThread.quitSafely();
+            mSensorThread = null;
+        }
         if (mResultThread != null) {
             mResultThread.quitSafely();
             mResultThread = null;
@@ -404,6 +416,7 @@
         // (called on different threads) will need to send data back to the host script.
 
         public Socket mOpenSocket = null;
+        private Thread mThread = null;
 
         public SocketWriteRunnable(Socket openSocket) {
             mOpenSocket = openSocket;
@@ -421,6 +434,7 @@
                     ByteBuffer b = mSocketWriteQueue.take();
                     synchronized(mSocketWriteDrainLock) {
                         if (mOpenSocket == null) {
+                            Logt.e(TAG, "No open socket connection!");
                             continue;
                         }
                         if (b.hasArray()) {
@@ -442,14 +456,26 @@
                     }
                 } catch (IOException e) {
                     Logt.e(TAG, "Error writing to socket", e);
+                    mOpenSocket = null;
                     break;
                 } catch (java.lang.InterruptedException e) {
                     Logt.e(TAG, "Error writing to socket (interrupted)", e);
+                    mOpenSocket = null;
                     break;
                 }
             }
             Logt.i(TAG, "Socket writer thread terminated");
         }
+
+        public synchronized void checkAndStartThread() {
+            if (mThread == null || mThread.getState() == Thread.State.TERMINATED) {
+                mThread = new Thread(this);
+            }
+            if (mThread.getState() == Thread.State.NEW) {
+                mThread.start();
+            }
+        }
+
     }
 
     class SocketRunnable implements Runnable {
@@ -475,7 +501,6 @@
 
             // Create a new thread to handle writes to this socket.
             mSocketWriteRunnable = new SocketWriteRunnable(null);
-            (new Thread(mSocketWriteRunnable)).start();
 
             while (!mThreadExitFlag) {
                 // Receive the socket-open request from the host.
@@ -489,6 +514,7 @@
                     mSocketWriteQueue.clear();
                     mInflightImageSizes.clear();
                     mSocketWriteRunnable.setOpenSocket(mOpenSocket);
+                    mSocketWriteRunnable.checkAndStartThread();
                     Logt.i(TAG, "Socket connected");
                 } catch (IOException e) {
                     Logt.e(TAG, "Socket open error: ", e);
@@ -1277,6 +1303,8 @@
 
             // Initiate the captures.
             long maxExpTimeNs = -1;
+            List<CaptureRequest> requestList =
+                    new ArrayList<>(requests.size());
             for (int i = 0; i < requests.size(); i++) {
                 CaptureRequest.Builder req = requests.get(i);
                 // For DNG captures, need the LSC map to be available.
@@ -1291,8 +1319,9 @@
                 for (int j = 0; j < numCaptureSurfaces; j++) {
                     req.addTarget(mOutputImageReaders[j].getSurface());
                 }
-                mSession.capture(req.build(), mCaptureResultListener, mResultHandler);
+                requestList.add(req.build());
             }
+            mSession.captureBurst(requestList, mCaptureResultListener, mResultHandler);
 
             long timeout = TIMEOUT_CALLBACK * 1000;
             if (maxExpTimeNs > 0) {
@@ -1478,6 +1507,11 @@
     }
 
     @Override
+    public final void onAccuracyChanged(Sensor sensor, int accuracy) {
+        Logt.i(TAG, "Sensor " + sensor.getName() + " accuracy changed to " + accuracy);
+    }
+
+    @Override
     public final void onSensorChanged(SensorEvent event) {
         synchronized(mEventLock) {
             if (mEventsEnabled) {
@@ -1492,10 +1526,6 @@
         }
     }
 
-    @Override
-    public final void onAccuracyChanged(Sensor sensor, int accuracy) {
-    }
-
     private final CaptureCallback mCaptureCallback = new CaptureCallback() {
         @Override
         public void onCaptureAvailable(Image capture) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java
index 0c39a9e..a8affcd 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java
@@ -25,15 +25,21 @@
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraManager;
 import android.os.Bundle;
+import android.text.method.ScrollingMovementMethod;
 import android.util.Log;
 import android.view.WindowManager;
+import android.widget.TextView;
 import android.widget.Toast;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
 import java.util.HashSet;
 import java.util.HashMap;
-import java.util.Arrays;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
 import java.io.BufferedReader;
 import java.io.FileReader;
 import java.io.FileNotFoundException;
@@ -44,6 +50,8 @@
 import com.android.cts.verifier.PassFailButtons;
 import com.android.cts.verifier.R;
 
+import org.json.JSONArray;
+import org.json.JSONObject;
 
 /**
  * Test for Camera features that require that the camera be aimed at a specific test scene.
@@ -53,48 +61,216 @@
 public class ItsTestActivity extends PassFailButtons.Activity {
     private static final String TAG = "ItsTestActivity";
     private static final String EXTRA_CAMERA_ID = "camera.its.extra.CAMERA_ID";
-    private static final String EXTRA_SUCCESS = "camera.its.extra.SUCCESS";
-    private static final String EXTRA_SUMMARY = "camera.its.extra.SUMMARY";
+    private static final String EXTRA_RESULTS = "camera.its.extra.RESULTS";
+    private static final String EXTRA_VERSION = "camera.its.extra.VERSION";
+    private static final String CURRENT_VERSION = "1.0";
     private static final String ACTION_ITS_RESULT =
             "com.android.cts.verifier.camera.its.ACTION_ITS_RESULT";
 
-    class SuccessReceiver extends BroadcastReceiver {
+    private static final String RESULT_PASS = "PASS";
+    private static final String RESULT_FAIL = "FAIL";
+    private static final String RESULT_NOT_EXECUTED = "NOT_EXECUTED";
+    private static final Set<String> RESULT_VALUES = new HashSet<String>(
+            Arrays.asList(new String[] {RESULT_PASS, RESULT_FAIL, RESULT_NOT_EXECUTED}));
+    private static final int MAX_SUMMARY_LEN = 200;
+
+    private final ResultReceiver mResultsReceiver = new ResultReceiver();
+
+    // Initialized in onCreate
+    ArrayList<String> mNonLegacyCameraIds = null;
+
+    // TODO: cache the following in saved bundle
+    private Set<ResultKey> mAllScenes = null;
+    // (camera, scene) -> (pass, fail)
+    private final HashMap<ResultKey, Boolean> mExecutedScenes = new HashMap<>();
+    // map camera id to ITS summary report path
+    private final HashMap<ResultKey, String> mSummaryMap = new HashMap<>();
+
+    final class ResultKey {
+        public final String cameraId;
+        public final String sceneId;
+
+        public ResultKey(String cameraId, String sceneId) {
+            this.cameraId = cameraId;
+            this.sceneId = sceneId;
+        }
+
+        @Override
+        public boolean equals(final Object o) {
+            if (o == null) return false;
+            if (this == o) return true;
+            if (o instanceof ResultKey) {
+                final ResultKey other = (ResultKey) o;
+                return cameraId.equals(other.cameraId) && sceneId.equals(other.sceneId);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            int h = cameraId.hashCode();
+            h = ((h << 5) - h) ^ sceneId.hashCode();
+            return h;
+        }
+    }
+
+    private final Comparator<ResultKey> mComparator = new Comparator<ResultKey>() {
+        @Override
+        public int compare(ResultKey k1, ResultKey k2) {
+            if (k1.cameraId.equals(k2.cameraId))
+                return k1.sceneId.compareTo(k2.sceneId);
+            return k1.cameraId.compareTo(k2.cameraId);
+        }
+    };
+
+    class ResultReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
             Log.i(TAG, "Received result for Camera ITS tests");
             if (ACTION_ITS_RESULT.equals(intent.getAction())) {
+                String version = intent.getStringExtra(EXTRA_VERSION);
+                if (version == null || !version.equals(CURRENT_VERSION)) {
+                    Log.e(TAG, "Its result version mismatch: expect " + CURRENT_VERSION +
+                            ", got " + ((version == null) ? "null" : version));
+                    ItsTestActivity.this.showToast(R.string.its_version_mismatch);
+                    return;
+                }
+
                 String cameraId = intent.getStringExtra(EXTRA_CAMERA_ID);
-                String result = intent.getStringExtra(EXTRA_SUCCESS);
-                String summaryPath = intent.getStringExtra(EXTRA_SUMMARY);
+                String results = intent.getStringExtra(EXTRA_RESULTS);
+                if (cameraId == null || results == null) {
+                    Log.e(TAG, "cameraId = " + ((cameraId == null) ? "null" : cameraId) +
+                            ", results = " + ((results == null) ? "null" : results));
+                    return;
+                }
+
                 if (!mNonLegacyCameraIds.contains(cameraId)) {
                     Log.e(TAG, "Unknown camera id " + cameraId + " reported to ITS");
                     return;
                 }
 
-                Log.i(TAG, "ITS summary path is: " + summaryPath);
-                mSummaryMap.put(cameraId, summaryPath);
-                // Create summary report
-                if (mSummaryMap.keySet().containsAll(mNonLegacyCameraIds)) {
+                try {
+                    /* Sample JSON results string
+                    {
+                       "scene0":{
+                          "result":"PASS",
+                          "summary":"/sdcard/cam0_scene0.txt"
+                       },
+                       "scene1":{
+                          "result":"NOT_EXECUTED"
+                       },
+                       "scene2":{
+                          "result":"FAIL",
+                          "summary":"/sdcard/cam0_scene2.txt"
+                       }
+                    }
+                    */
+                    JSONObject jsonResults = new JSONObject(results);
+                    Set<String> scenes = new HashSet<>();
+                    Iterator<String> keys = jsonResults.keys();
+                    while (keys.hasNext()) {
+                        scenes.add(keys.next());
+                    }
+                    boolean newScenes = false;
+                    if (mAllScenes == null) {
+                        mAllScenes = new TreeSet<>(mComparator);
+                        newScenes = true;
+                    } else { // See if scene lists changed
+                        for (String scene : scenes) {
+                            if (!mAllScenes.contains(new ResultKey(cameraId, scene))) {
+                                // Scene list changed. Cleanup previous test results
+                                newScenes = true;
+                                break;
+                            }
+                        }
+                        for (ResultKey k : mAllScenes) {
+                            if (!scenes.contains(k.sceneId)) {
+                                newScenes = true;
+                                break;
+                            }
+                        }
+                    }
+                    if (newScenes) {
+                        mExecutedScenes.clear();
+                        mAllScenes.clear();
+                        for (String scene : scenes) {
+                            for (String c : mNonLegacyCameraIds) {
+                                mAllScenes.add(new ResultKey(c, scene));
+                            }
+                        }
+                    }
+
+                    // Update test execution results
+                    for (String scene : scenes) {
+                        JSONObject sceneResult = jsonResults.getJSONObject(scene);
+                        String result = sceneResult.getString("result");
+                        if (result == null) {
+                            Log.e(TAG, "Result for " + scene + " is null");
+                            return;
+                        }
+                        Log.i(TAG, "ITS camera" + cameraId + " " + scene + ": result:" + result);
+                        if (!RESULT_VALUES.contains(result)) {
+                            Log.e(TAG, "Unknown result for " + scene + ": " + result);
+                            return;
+                        }
+                        ResultKey key = new ResultKey(cameraId, scene);
+                        if (result.equals(RESULT_PASS) || result.equals(RESULT_FAIL)) {
+                            boolean pass = result.equals(RESULT_PASS);
+                            mExecutedScenes.put(key, pass);
+                            String summary = sceneResult.optString("summary");
+                            if (!summary.equals("")) {
+                                mSummaryMap.put(key, summary);
+                            }
+                        } // do nothing for NOT_EXECUTED scenes
+                    }
+                } catch (org.json.JSONException e) {
+                    Log.e(TAG, "Error reading json result string:" + results , e);
+                    return;
+                }
+
+                // Set summary if all scenes reported
+                if (mSummaryMap.keySet().containsAll(mAllScenes)) {
                     StringBuilder summary = new StringBuilder();
-                    for (String id : mNonLegacyCameraIds) {
-                        String path = mSummaryMap.get(id);
+                    for (String path : mSummaryMap.values()) {
                         appendFileContentToSummary(summary, path);
                     }
+                    if (summary.length() > MAX_SUMMARY_LEN) {
+                        Log.w(TAG, "ITS summary report too long: len: " + summary.length());
+                    }
                     ItsTestActivity.this.getReportLog().setSummary(
                             summary.toString(), 1.0, ResultType.NEUTRAL, ResultUnit.NONE);
                 }
-                boolean pass = result.equals("True");
-                if(pass) {
-                    Log.i(TAG, "Received Camera " + cameraId + " ITS SUCCESS from host.");
-                    mITSPassedCameraIds.add(cameraId);
-                    if (mNonLegacyCameraIds != null && mNonLegacyCameraIds.size() != 0 &&
-                            mITSPassedCameraIds.containsAll(mNonLegacyCameraIds)) {
-                        ItsTestActivity.this.showToast(R.string.its_test_passed);
-                        ItsTestActivity.this.getPassButton().setEnabled(true);
+
+                // Display current progress
+                StringBuilder progress = new StringBuilder();
+                for (ResultKey k : mAllScenes) {
+                    String status = RESULT_NOT_EXECUTED;
+                    if (mExecutedScenes.containsKey(k)) {
+                        status = mExecutedScenes.get(k) ? RESULT_PASS : RESULT_FAIL;
                     }
+                    progress.append(String.format("Cam %s, %s: %s\n",
+                            k.cameraId, k.sceneId, status));
+                }
+                TextView progressView = (TextView) findViewById(R.id.its_progress);
+                progressView.setMovementMethod(new ScrollingMovementMethod());
+                progressView.setText(progress.toString());
+
+
+                // Enable pass button if all scenes pass
+                boolean allScenesPassed = true;
+                for (ResultKey k : mAllScenes) {
+                    Boolean pass = mExecutedScenes.get(k);
+                    if (pass == null || pass == false) {
+                        allScenesPassed = false;
+                        break;
+                    }
+                }
+                if (allScenesPassed) {
+                    // Enable pass button
+                    ItsTestActivity.this.showToast(R.string.its_test_passed);
+                    ItsTestActivity.this.getPassButton().setEnabled(true);
                 } else {
-                    Log.i(TAG, "Received Camera " + cameraId + " ITS FAILURE from host.");
-                    ItsTestActivity.this.showToast(R.string.its_test_failed);
+                    ItsTestActivity.this.getPassButton().setEnabled(false);
                 }
             }
         }
@@ -127,12 +303,6 @@
         }
     }
 
-    private final SuccessReceiver mSuccessReceiver = new SuccessReceiver();
-    private final HashSet<String> mITSPassedCameraIds = new HashSet<>();
-    // map camera id to ITS summary report path
-    private final HashMap<String, String> mSummaryMap = new HashMap<>();
-    ArrayList<String> mNonLegacyCameraIds = null;
-
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -168,6 +338,7 @@
                     "Received error from camera service while checking device capabilities: "
                             + e, Toast.LENGTH_SHORT).show();
         }
+
         getPassButton().setEnabled(false);
     }
 
@@ -180,7 +351,7 @@
         } else {
             Log.d(TAG, "register ITS result receiver");
             IntentFilter filter = new IntentFilter(ACTION_ITS_RESULT);
-            registerReceiver(mSuccessReceiver, filter);
+            registerReceiver(mResultsReceiver, filter);
         }
     }
 
@@ -188,7 +359,7 @@
     protected void onPause() {
         super.onPause();
         Log.d(TAG, "unregister ITS result receiver");
-        unregisterReceiver(mSuccessReceiver);
+        unregisterReceiver(mResultsReceiver);
     }
 
     @Override
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/location/GnssStatusTestsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/location/GnssStatusTestsActivity.java
new file mode 100644
index 0000000..a64c5d3
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/location/GnssStatusTestsActivity.java
@@ -0,0 +1,15 @@
+package com.android.cts.verifier.location;
+
+import com.android.cts.verifier.location.base.GnssCtsTestActivity;
+import android.location.cts.GnssStatusTest;
+
+/**
+ * Activity to execute CTS GnssStatusTest.
+ * It is a wrapper for {@link GnssStatusTest} running with AndroidJUnitRunner.
+ */
+
+public class GnssStatusTestsActivity extends GnssCtsTestActivity {
+  public GnssStatusTestsActivity() {
+    super(GnssStatusTest.class);
+  }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
index 9af0840..c42f7da 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
@@ -299,11 +299,13 @@
                 R.string.provisioning_byod_cross_profile_from_work_instruction,
                 new Intent(ByodHelperActivity.ACTION_TEST_CROSS_PROFILE_INTENTS_DIALOG));
 
+        /* Disable due to b/33571176
         mAppLinkingTest = new DialogTestListItem(this,
                 R.string.provisioning_app_linking,
                 "BYOD_AppLinking",
                 R.string.provisioning_byod_app_linking_instruction,
                 new Intent(ByodHelperActivity.ACTION_TEST_APP_LINKING_DIALOG));
+        */
 
         mKeyguardDisabledFeaturesTest = TestListItem.newTest(this,
                 R.string.provisioning_byod_keyguard_disabled_features,
@@ -350,6 +352,7 @@
                 R.string.profile_owner_permission_lockdown_test_info,
                 permissionCheckIntent);
 
+        /* Disable due to b/33571768
         mSelectWorkChallenge = new DialogTestListItem(this,
                 R.string.provisioning_byod_select_work_challenge,
                 "BYOD_SelectWorkChallenge",
@@ -361,6 +364,7 @@
                 "BYOD_ConfirmWorkCredentials",
                 R.string.provisioning_byod_confirm_work_credentials_description,
                 new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME));
+        */
 
         mOrganizationInfoTest = TestListItem.newTest(this,
                 R.string.provisioning_byod_organization_info,
@@ -404,7 +408,9 @@
 
         adapter.add(mCrossProfileIntentFiltersTestFromPersonal);
         adapter.add(mCrossProfileIntentFiltersTestFromWork);
+        /* Disable due to b/33571176
         adapter.add(mAppLinkingTest);
+        */
         adapter.add(mDisableNonMarketTest);
         adapter.add(mEnableNonMarketTest);
         adapter.add(mIntentFiltersTest);
@@ -413,8 +419,10 @@
         adapter.add(mAuthenticationBoundKeyTest);
         adapter.add(mVpnTest);
         adapter.add(mTurnOffWorkFeaturesTest);
+        /* Disable due to b/33571768
         adapter.add(mSelectWorkChallenge);
         adapter.add(mConfirmWorkCredentials);
+        */
         adapter.add(mOrganizationInfoTest);
         adapter.add(mParentProfilePassword);
         adapter.add(mPolicyTransparencyTest);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/KeyguardDisabledFeaturesActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/KeyguardDisabledFeaturesActivity.java
index 5585cbc..27a140c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/KeyguardDisabledFeaturesActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/KeyguardDisabledFeaturesActivity.java
@@ -21,6 +21,8 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.hardware.fingerprint.FingerprintManager;
 import android.os.Bundle;
 import android.provider.Settings;
@@ -32,6 +34,8 @@
 import com.android.cts.verifier.DialogTestListActivity;
 import com.android.cts.verifier.R;
 
+import java.util.List;
+
 public class KeyguardDisabledFeaturesActivity extends DialogTestListActivity {
 
     protected DevicePolicyManager mDpm;
@@ -131,11 +135,20 @@
 
     @Override
     protected void setupTests(ArrayTestListAdapter adapter) {
-        setupDisableTrustAgentsTest(adapter);
+        if (hasTrustAgents()) {
+            setupDisableTrustAgentsTest(adapter);
+        }
         setupDisableUnredactedWorkNotification(adapter);
         setupFingerprintTests(adapter);
     }
 
+    private boolean hasTrustAgents() {
+        PackageManager packageManager = getPackageManager();
+        Intent intent = new Intent("android.service.trust.TrustAgentService");
+        List<ResolveInfo> resolveInfos = packageManager.queryIntentServices(intent, 0);
+        return resolveInfos.size() > 0;
+    }
+
     @Override
     protected void clearRemainingState(final DialogTestListItem test) {
         super.clearRemainingState(test);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/UserRestrictions.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/UserRestrictions.java
index 935a1b8..968aa5b 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/UserRestrictions.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/UserRestrictions.java
@@ -207,6 +207,10 @@
                 return pm.hasSystemFeature(PackageManager.FEATURE_NFC);
             case UserManager.DISALLOW_SHARE_LOCATION:
                 return pm.hasSystemFeature(PackageManager.FEATURE_LOCATION);
+            case UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES:
+                return !pm.hasSystemFeature(PackageManager.FEATURE_WATCH);
+            case UserManager.DISALLOW_CONFIG_CREDENTIALS:
+                return !pm.hasSystemFeature(PackageManager.FEATURE_WATCH);
             default:
                 return true;
         }
@@ -222,4 +226,4 @@
             this.intentAction = intentAction;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/PackagePriorityVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/PackagePriorityVerifierActivity.java
index 5870981..b40ecc6 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/PackagePriorityVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/PackagePriorityVerifierActivity.java
@@ -39,7 +39,7 @@
     private static final String ACTION_CANCEL = "com.android.cts.robot.ACTION_CANCEL";
     private static final String EXTRA_ID = "ID";
     private static final String EXTRA_NOTIFICATION = "NOTIFICATION";
-    private static final String NOTIFICATION_BOT_PACKAGE = "com.android.cts.robot";
+    static final String NOTIFICATION_BOT_PACKAGE = "com.android.cts.robot";
     private CharSequence mAppLabel;
 
     @Override
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/ShortcutThrottlingResetActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/ShortcutThrottlingResetActivity.java
new file mode 100644
index 0000000..313ebfa
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/ShortcutThrottlingResetActivity.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.notifications;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.cts.verifier.R;
+
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Test to make sure, when an inline reply happens, the shortcut manager rate-limiting must
+ * be reset.
+ *
+ * We use the "BOT" apk here, because rate-limiting will be reset when an app shows an activity
+ * too -- so as long as this (or any) test activity is shown, CTS verifier won't be rate-limited.
+ */
+public class ShortcutThrottlingResetActivity extends InteractiveVerifierActivity {
+    private static final String TAG = "ShortcutThrottlingReset";
+
+    private static final String NOTIFICATION_BOT_PACKAGE
+            = PackagePriorityVerifierActivity.NOTIFICATION_BOT_PACKAGE;
+
+    private static final String ACTION_RESET_SETUP_NOTIFICATION =
+            "com.android.cts.robot.ACTION_RESET_SETUP_NOTIFICATION";
+
+    private static final String EXTRA_NOTIFICATION_TITLE = "EXTRA_NOTIFICATION_TITLE";
+    private static final String EXTRA_RESET_REPLY_PACKAGE = "EXTRA_RESET_REPLY_PACKAGE";
+    private static final String EXTRA_RESET_REPLY_ACTION = "EXTRA_RESET_REPLY_ACTION";
+    private static final String EXTRA_RESET_REPLY_ERROR = "EXTRA_RESET_REPLY_ERROR";
+
+    private static final String SUCCESS = "**SUCCESS**";
+
+    private String mReplyAction;
+
+    private final AtomicReference<Intent> mReplyIntent = new AtomicReference<>(null);
+
+    @Override
+    int getTitleResource() {
+        return R.string.shortcut_reset_test;
+    }
+
+    @Override
+    int getInstructionsResource() {
+        return R.string.shortcut_reset_info;
+    }
+
+    @Override
+    protected void onCreate(Bundle savedState) {
+        super.onCreate(savedState);
+
+        // Generate an unique reply action and register the reply receiver.
+        mReplyAction = "reply_" + new SecureRandom().nextLong();
+        final IntentFilter replyFilter = new IntentFilter(mReplyAction);
+        registerReceiver(mReplyReceiver, replyFilter);
+    }
+
+    @Override
+    protected void onDestroy() {
+        unregisterReceiver(mReplyReceiver);
+        super.onDestroy();
+    }
+
+    @Override
+    protected List<InteractiveTestCase> createTestItems() {
+        List<InteractiveTestCase> tests = new ArrayList<>();
+        tests.add(new CheckForBot());
+        tests.add(new SetupNotification());
+        tests.add(new WaitForTestReply());
+        tests.add(new CheckResult());
+        return tests;
+    }
+
+
+    private final BroadcastReceiver mReplyReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            Log.i(TAG, "Received reply from robot helper: " + intent);
+            mReplyIntent.set(intent);
+        }
+    };
+
+
+    /** Make sure the helper package is installed. */
+    protected class CheckForBot extends InteractiveTestCase {
+        @Override
+        View inflate(ViewGroup parent) {
+            return createAutoItem(parent, R.string.shortcut_reset_bot);
+        }
+
+        @Override
+        void test() {
+            PackageManager pm = mContext.getPackageManager();
+            try {
+                pm.getPackageInfo(NOTIFICATION_BOT_PACKAGE, 0);
+                status = PASS;
+            } catch (PackageManager.NameNotFoundException e) {
+                status = FAIL;
+                logFail("You must install the CTS Robot helper, aka " + NOTIFICATION_BOT_PACKAGE);
+            }
+            next();
+        }
+    }
+
+    /**
+     * Request the bot apk to show the notification.
+     */
+    protected class SetupNotification extends InteractiveTestCase {
+        @Override
+        View inflate(ViewGroup parent) {
+            return createAutoItem(parent, R.string.shortcut_reset_start);
+        }
+
+        @Override
+        void test() {
+            final Intent intent = new Intent(ACTION_RESET_SETUP_NOTIFICATION);
+            intent.setPackage(NOTIFICATION_BOT_PACKAGE);
+
+            intent.putExtra(EXTRA_NOTIFICATION_TITLE, getResources().getString(getTitleResource()));
+
+            intent.putExtra(EXTRA_RESET_REPLY_PACKAGE, getPackageName());
+            intent.putExtra(EXTRA_RESET_REPLY_ACTION, mReplyAction);
+
+            intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
+            sendBroadcast(intent);
+            status = PASS;
+            next();
+        }
+    }
+
+    /**
+     * Let the human tester do an inline reply, and wait for the reply broadcast from the bot apk.
+     */
+    protected class WaitForTestReply extends InteractiveTestCase {
+        @Override
+        View inflate(ViewGroup parent) {
+            return createAutoItem(parent, R.string.shortcut_reset_prompt_inline_reply);
+        }
+
+        @Override
+        void test() {
+            final Intent replyIntent = mReplyIntent.get();
+            if (replyIntent == null) {
+                // Reply not received yet.
+                status = RETEST;
+                delay();
+                return;
+            }
+            status = PASS;
+            next();
+        }
+    }
+
+    /**
+     * Check the reply from the bot apk.
+     */
+    protected class CheckResult extends InteractiveTestCase {
+        @Override
+        View inflate(ViewGroup parent) {
+            return createAutoItem(parent, R.string.shortcut_reset_check_result);
+        }
+
+        @Override
+        void test() {
+            final Intent replyIntent = mReplyIntent.get();
+            if (replyIntent == null) {
+                logFail("Internal error, replyIntent shouldn't be null here.");
+                status = FAIL;
+                return;
+            }
+            final String error = replyIntent.getStringExtra(EXTRA_RESET_REPLY_ERROR);
+            if (SUCCESS.equals(error)) {
+                status = PASS;
+                next();
+                return;
+            }
+            logFail("Test failed. Error message=" + error);
+            status = FAIL;
+            next();
+        }
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/BatchingTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/BatchingTestActivity.java
index 7ef63d7..b7d9617 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/BatchingTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/BatchingTestActivity.java
@@ -19,6 +19,7 @@
 import com.android.cts.verifier.R;
 import com.android.cts.verifier.sensors.base.SensorCtsVerifierTestActivity;
 
+import android.content.pm.PackageManager;
 import android.hardware.Sensor;
 import android.hardware.SensorManager;
 import android.hardware.cts.helpers.TestSensorEnvironment;
@@ -82,6 +83,9 @@
 
     @SuppressWarnings("unused")
     public String testProximity_batching() throws Throwable {
+        if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_SENSOR_PROXIMITY)) {
+            return null;
+        }
         return runBatchTest(
                 Sensor.TYPE_PROXIMITY,
                 REPORT_LATENCY_10_SEC,
@@ -90,6 +94,9 @@
 
     @SuppressWarnings("unused")
     public String testProximity_flush() throws Throwable {
+        if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_SENSOR_PROXIMITY)) {
+            return null;
+        }
         return runFlushTest(
                 Sensor.TYPE_PROXIMITY,
                 REPORT_LATENCY_10_SEC,
diff --git a/apps/NotificationBot/AndroidManifest.xml b/apps/NotificationBot/AndroidManifest.xml
index b63791f..0388cbc 100644
--- a/apps/NotificationBot/AndroidManifest.xml
+++ b/apps/NotificationBot/AndroidManifest.xml
@@ -39,10 +39,10 @@
             <intent-filter>
                 <action android:name="com.android.cts.robot.ACTION_POST" />
                 <action android:name="com.android.cts.robot.ACTION_CANCEL" />
+                <action android:name="com.android.cts.robot.ACTION_RESET_SETUP_NOTIFICATION" />
+                <action android:name="com.android.cts.robot.ACTION_INLINE_REPLY" />
             </intent-filter>
         </receiver>
-
-
     </application>
 
 </manifest>
diff --git a/apps/NotificationBot/src/com/android/cts/robot/NotificationBot.java b/apps/NotificationBot/src/com/android/cts/robot/NotificationBot.java
index 2aa5f41..746b840 100644
--- a/apps/NotificationBot/src/com/android/cts/robot/NotificationBot.java
+++ b/apps/NotificationBot/src/com/android/cts/robot/NotificationBot.java
@@ -15,14 +15,23 @@
  */
 package com.android.cts.robot;
 
-import android.app.Activity;
 import android.app.Notification;
+import android.app.Notification.Action;
 import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.RemoteInput;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
+import android.os.SystemClock;
 import android.util.Log;
 
+import java.util.ArrayList;
+import java.util.List;
+
 
 public class NotificationBot extends BroadcastReceiver {
     private static final String TAG = "NotificationBot";
@@ -30,6 +39,21 @@
     private static final String EXTRA_NOTIFICATION = "NOTIFICATION";
     private static final String ACTION_POST = "com.android.cts.robot.ACTION_POST";
     private static final String ACTION_CANCEL = "com.android.cts.robot.ACTION_CANCEL";
+    private static final String ACTION_RESET_SETUP_NOTIFICATION =
+            "com.android.cts.robot.ACTION_RESET_SETUP_NOTIFICATION";
+
+    private static final String ACTION_INLINE_REPLY =
+            "com.android.cts.robot.ACTION_INLINE_REPLY";
+
+    private static final String EXTRA_RESET_REPLY_PACKAGE = "EXTRA_RESET_REPLY_PACKAGE";
+    private static final String EXTRA_RESET_REPLY_ACTION = "EXTRA_RESET_REPLY_ACTION";
+    private static final String EXTRA_NOTIFICATION_TITLE = "EXTRA_NOTIFICATION_TITLE";
+
+    private static final String EXTRA_RESET_REPLY_ERROR = "EXTRA_RESET_REPLY_ERROR";
+
+    private static final String EXTRA_RESET_REQUEST_INTENT = "EXTRA_RESET_REQUEST_INTENT";
+
+    private static final String SUCCESS = "**SUCCESS**";
 
     @Override
     public void onReceive(Context context, Intent intent) {
@@ -60,8 +84,112 @@
                     (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
             noMa.cancel(id);
 
+        } else if (ACTION_RESET_SETUP_NOTIFICATION.equals(intent.getAction())) {
+            testShortcutResetSetupNotification(context, intent);
+
+        } else if (ACTION_INLINE_REPLY.equals(intent.getAction())) {
+            testShortcutResetInlineReplyReceived(context, intent);
+
         } else {
             Log.i(TAG, "received unexpected action: " + intent.getAction());
         }
     }
+
+    /**
+     * Test start request from CTS verifier.  Show a notification with inline reply, which will
+     * trigger {@link #testShortcutResetInlineReplyReceived}.
+     */
+    private static void testShortcutResetSetupNotification(Context context, Intent intent) {
+        final NotificationManager nm = context.getSystemService(NotificationManager.class);
+        nm.cancelAll();
+
+        final ShortcutManager sm = context.getSystemService(ShortcutManager.class);
+
+        final List<ShortcutInfo> EMPTY_LIST = new ArrayList<>();
+
+        long timeout = SystemClock.elapsedRealtime() + 10 * 1000;
+
+        // First, make sure this package is throttled.
+        while (!sm.isRateLimitingActive()) {
+            sm.setDynamicShortcuts(EMPTY_LIST);
+            try {
+                Thread.sleep(0);
+            } catch (InterruptedException e) {
+            }
+            if (SystemClock.elapsedRealtime() >= timeout) {
+                sendShortcutResetReply(context, intent,
+                        "ShortcutMager rate-limiting not activated.");
+                return;
+            }
+        }
+
+        // Show a notification with inline reply.
+        final PendingIntent receiverIntent =
+                PendingIntent.getBroadcast(context, 0,
+                        new Intent(ACTION_INLINE_REPLY)
+                                .setComponent(new ComponentName(context, NotificationBot.class))
+                                .putExtra(EXTRA_RESET_REQUEST_INTENT, intent),
+                        PendingIntent.FLAG_UPDATE_CURRENT);
+        final RemoteInput ri = new RemoteInput.Builder("result")
+                .setLabel("Type something here and press send button").build();
+
+        final Notification.Builder nb = new Notification.Builder(context)
+                .setContentTitle(intent.getStringExtra(EXTRA_NOTIFICATION_TITLE))
+                .setSmallIcon(android.R.drawable.ic_popup_sync)
+                .addAction(new Action.Builder(0,
+                        "Type something here and press send button", receiverIntent)
+                        .addRemoteInput(ri)
+                        .build());
+        context.getSystemService(NotificationManager.class).notify(0, nb.build());
+    }
+
+    /**
+     * Invoked when the inline reply from {@link #testShortcutResetSetupNotification} is performed.
+     *
+     * Check the shortcut manager rate-limiting state, and post the reply to CTS verifier.
+     */
+    private static void testShortcutResetInlineReplyReceived(Context context, Intent intent) {
+        Log.i(TAG, "Inline reply received");
+
+        final NotificationManager nm = context.getSystemService(NotificationManager.class);
+        nm.cancelAll();
+
+        // Close notification shade.
+        context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+
+        // Check if rate-limiting has been reset.
+        final ShortcutManager sm = context.getSystemService(ShortcutManager.class);
+
+        String error;
+        final boolean success = !sm.isRateLimitingActive();
+        if (success) {
+            error = SUCCESS;
+        } else {
+            error = "Inline reply received, but ShortcutManager rate-limiting is still active.";
+        }
+
+        // Send back the result.
+        sendShortcutResetReply(context,
+                intent.getParcelableExtra(EXTRA_RESET_REQUEST_INTENT), error);
+    }
+
+    /**
+     * Reply an error message, or {@link #SUCCESS} for success, to CTS verifier for shortcut manager
+     * reset rate-limiting test.
+
+     * @param requestIntent original intent sent from the verifier to
+     *     {@link #testShortcutResetSetupNotification}.
+     * @param error error message, or {@link #SUCCESS} if success.
+     */
+    private static void sendShortcutResetReply(Context context, Intent requestIntent, String error) {
+        final Intent replyIntent = new Intent();
+        replyIntent.setAction(requestIntent.getStringExtra(EXTRA_RESET_REPLY_ACTION));
+        replyIntent.putExtra(EXTRA_RESET_REPLY_ERROR, error);
+
+        if (error != null) {
+            Log.e(TAG, error);
+        }
+
+        context.sendBroadcast(replyIntent);
+    }
 }
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfo.java
index 8aa3380..750e45f 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfo.java
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfo.java
@@ -87,7 +87,7 @@
                     mResultCode = ResultCode.COMPLETED;
                 }
             } catch (Exception e) {
-                failed("Could not collect device info: " + e.getMessage());
+                failed("Could not collect device info", e);
             }
         }
 
@@ -136,6 +136,12 @@
         Log.e(LOG_TAG, message, exception);
     }
 
+    private void failed(String message, Throwable exception) {
+        mResultCode = ResultCode.FAILED;
+        mErrorMessage = message;
+        Log.e(LOG_TAG, message, exception);
+    }
+
     private void failed(String message) {
         mResultCode = ResultCode.FAILED;
         mErrorMessage = message;
diff --git a/common/device-side/util/src/com/android/compatibility/common/util/DeviceInfoStore.java b/common/device-side/util/src/com/android/compatibility/common/util/DeviceInfoStore.java
index 9f1bda5..735b955 100644
--- a/common/device-side/util/src/com/android/compatibility/common/util/DeviceInfoStore.java
+++ b/common/device-side/util/src/com/android/compatibility/common/util/DeviceInfoStore.java
@@ -135,9 +135,7 @@
      */
     @Override
     public void addResult(String name, float value) throws IOException {
-        checkName(name);
-        mJsonWriter.name(name);
-        mJsonWriter.value(value);
+        addResult(name, (double) value);
     }
 
     /**
@@ -146,8 +144,12 @@
     @Override
     public void addResult(String name, double value) throws IOException {
         checkName(name);
-        mJsonWriter.name(name);
-        mJsonWriter.value(value);
+        if (isDoubleNaNOrInfinite(value)) {
+            return;
+        } else {
+            mJsonWriter.name(name);
+            mJsonWriter.value(value);
+        }
     }
 
     /**
@@ -203,13 +205,11 @@
      */
     @Override
     public void addArrayResult(String name, float[] array) throws IOException {
-        checkName(name);
-        mJsonWriter.name(name);
-        mJsonWriter.beginArray();
-        for (float value : checkArray(array)) {
-            mJsonWriter.value(value);
+        double[] doubleArray = new double[array.length];
+        for (int i = 0; i < array.length; i++) {
+            doubleArray[i] = array[i];
         }
-        mJsonWriter.endArray();
+        addArrayResult(name, doubleArray);
     }
 
     /**
@@ -221,6 +221,9 @@
         mJsonWriter.name(name);
         mJsonWriter.beginArray();
         for (double value : checkArray(array)) {
+            if (isDoubleNaNOrInfinite(value)) {
+                continue;
+            }
             mJsonWriter.value(value);
         }
         mJsonWriter.endArray();
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 4aba37a..eecb15c 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
@@ -132,6 +132,13 @@
                 addSubPlan(flatArgs);
             }
         }, "a(?:dd)?", "s(?:ubplan)?", null);
+        trie.put(new Runnable() {
+            @Override
+            public void run() {
+                printLine(String.format("Android %s %s (%s)", SuiteInfo.FULLNAME,
+                        SuiteInfo.VERSION, SuiteInfo.BUILD_NUMBER));
+            }
+        }, "version"); // override tradefed 'version' command to print test suite name and version
 
         // find existing help for 'LIST_PATTERN' commands, and append these commands help
         String listHelp = commandHelp.get(LIST_PATTERN);
diff --git a/common/util/src/com/android/compatibility/common/util/CddTest.java b/common/util/src/com/android/compatibility/common/util/CddTest.java
new file mode 100644
index 0000000..34ee663
--- /dev/null
+++ b/common/util/src/com/android/compatibility/common/util/CddTest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compatibility.common.util;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Marks the type of test with purpose of asserting CDD requirements.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface CddTest {
+    String requirement();
+}
diff --git a/common/util/src/com/android/compatibility/common/util/InfoStore.java b/common/util/src/com/android/compatibility/common/util/InfoStore.java
index 6c5cc0d..b8014f7 100644
--- a/common/util/src/com/android/compatibility/common/util/InfoStore.java
+++ b/common/util/src/com/android/compatibility/common/util/InfoStore.java
@@ -189,4 +189,8 @@
         }
         return value;
     }
+
+    protected static boolean isDoubleNaNOrInfinite(Double value) {
+        return Double.isNaN(value) || Double.isInfinite(value);
+    }
 }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
index 99a7e8f..2180c96 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
@@ -179,7 +179,7 @@
                     getDevice().executeShellCommand("sm set-emulate-fbe false");
                     getDevice().waitForDeviceOnline();
                 } else {
-                    getDevice().nonBlockingReboot();
+                    getDevice().rebootUntilOnline();
                 }
                 waitForBootCompleted();
             }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java
index 7bd42b5..009d81b 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java
@@ -51,10 +51,7 @@
         assertNotNull(mAbi);
         assertNotNull(mCtsBuild);
 
-        getDevice().uninstallPackage(CLIENT_PKG);
-
-        assertNull(getDevice().installPackage(
-                MigrationHelper.getTestFile(mCtsBuild, CLIENT_APK), false));
+        reinstallClientPackage();
     }
 
     @Override
@@ -68,4 +65,11 @@
             throws DeviceNotAvailableException {
         Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
     }
+
+    protected void reinstallClientPackage() throws Exception {
+        getDevice().uninstallPackage(CLIENT_PKG);
+
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, CLIENT_APK), false));
+    }
 }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ScopedDirectoryAccessTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ScopedDirectoryAccessTest.java
index ffc7597..889b20b 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ScopedDirectoryAccessTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ScopedDirectoryAccessTest.java
@@ -42,6 +42,14 @@
         runDeviceTests(CLIENT_PKG, ".ScopedDirectoryAccessClientTest", "testNotAskedAgain");
     }
 
+    public void testDeniesOnceForAllClearedWhenPackageRemoved() throws Exception {
+        runDeviceTests(CLIENT_PKG, ".ScopedDirectoryAccessClientTest",
+                "testRemovePackageStep1UserDenies");
+        reinstallClientPackage();
+        runDeviceTests(CLIENT_PKG, ".ScopedDirectoryAccessClientTest",
+                "testRemovePackageStep2UserAcceptsDoNotClear");
+    }
+
     public void testDeniesOnceButAllowsAskingAgain() throws Exception {
         runDeviceTests(CLIENT_PKG, ".ScopedDirectoryAccessClientTest",
                 "testDeniesOnceButAllowsAskingAgain");
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTestCase.java b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTestCase.java
index e52af73..a26ec2d 100644
--- a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTestCase.java
+++ b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTestCase.java
@@ -150,7 +150,15 @@
         return result;
     }
 
+    /**
+     * Clears the DocumentsUI package data, unless test name ends on {@code DoNotClear}.
+     */
     protected void clearDocumentsUi() throws Exception {
+        final String testName = getName();
+        if (testName.endsWith("DoNotClear")) {
+            Log.d(TAG, "Not clearing DocumentsUI due to test name: " + testName);
+            return;
+        }
         executeShellCommand("pm clear com.android.documentsui");
     }
 }
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/ScopedDirectoryAccessClientTest.java b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/ScopedDirectoryAccessClientTest.java
index a4d35fb..dec8769 100644
--- a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/ScopedDirectoryAccessClientTest.java
+++ b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/ScopedDirectoryAccessClientTest.java
@@ -117,9 +117,9 @@
         if (!supportedHardware()) return;
 
         for (StorageVolume volume : getVolumes()) {
-            userAcceptsOpenExternalDirectoryTest(volume, DIRECTORY_PICTURES);
+            userAcceptsTest(volume, DIRECTORY_PICTURES);
             if (!volume.isPrimary()) {
-                userAcceptsOpenExternalDirectoryTest(volume, DIRECTORY_ROOT);
+                userAcceptsTest(volume, DIRECTORY_ROOT);
             }
         }
     }
@@ -133,7 +133,7 @@
         if (!output.isEmpty()) {
             fail("Command '" + command + "' failed: '" + output + "'");
         }
-        userAcceptsOpenExternalDirectoryTest(getPrimaryVolume(), DIRECTORY_PICTURES);
+        userAcceptsTest(getPrimaryVolume(), DIRECTORY_PICTURES);
     }
 
     public void testNotAskedAgain() throws Exception {
@@ -141,7 +141,7 @@
 
         for (StorageVolume volume : getVolumes()) {
             final String volumeDesc = volume.getDescription(getInstrumentation().getContext());
-            final Uri grantedUri = userAcceptsOpenExternalDirectoryTest(volume, DIRECTORY_PICTURES);
+            final Uri grantedUri = userAcceptsTest(volume, DIRECTORY_PICTURES);
 
             // Calls it again - since the permission has been granted, it should return right
             // away, without popping up the permissions dialog.
@@ -151,7 +151,7 @@
             assertEquals(grantedUri, newData.getData());
 
             // Make sure other directories still require user permission.
-            final Uri grantedUri2 = userAcceptsOpenExternalDirectoryTest(volume, DIRECTORY_ALARMS);
+            final Uri grantedUri2 = userAcceptsTest(volume, DIRECTORY_ALARMS);
             assertNotEqual(grantedUri, grantedUri2);
         }
     }
@@ -162,7 +162,7 @@
         for (StorageVolume volume : getVolumes()) {
             if (volume.isPrimary()) continue;
             final String volumeDesc = volume.getDescription(getInstrumentation().getContext());
-            final Uri grantedRootUri = userAcceptsOpenExternalDirectoryTest(volume, DIRECTORY_ROOT);
+            final Uri grantedRootUri = userAcceptsTest(volume, DIRECTORY_ROOT);
 
             // Calls it again - since the permission has been granted, it should return right
             // away, without popping up the permissions dialog.
@@ -204,7 +204,7 @@
                 assertActivityFailed();
 
                 // Third time is a charm...
-                userAcceptsOpenExternalDirectoryTest(volume, dir);
+                userAcceptsTest(volume, dir);
             }
         }
     }
@@ -216,33 +216,48 @@
         for (StorageVolume volume : getVolumes()) {
             for (String dir : dirs) {
                 if (volume.isPrimary() && dir == DIRECTORY_ROOT) continue;
-                // Rejects the first attempt...
-                UiAlertDialog dialog = openExternalDirectoryValidPath(volume, dir);
-                dialog.assertDoNotAskAgainVisibility(false);
-                dialog.noButton.click();
-                assertActivityFailed();
-
-                // ...and the second, checking the box
-                dialog = openExternalDirectoryValidPath(volume, dir);
-                UiObject checkbox = dialog.assertDoNotAskAgainVisibility(true);
-                assertTrue("checkbox should not be checkable", checkbox.isCheckable());
-                assertFalse("checkbox should not be checked", checkbox.isChecked());
-                checkbox.click();
-                assertTrue("checkbox should be checked", checkbox.isChecked()); // Sanity check
-                assertFalse("allow button should be disabled", dialog.yesButton.isEnabled());
-
-                dialog.noButton.click();
-                assertActivityFailed();
-
-                // Third strike out...
-                sendOpenExternalDirectoryIntent(volume, dir);
-                assertActivityFailed();
+                deniesOnceForAllTest(volume, dir);
             }
         }
     }
 
-    private Uri userAcceptsOpenExternalDirectoryTest(StorageVolume volume, String directoryName)
-            throws Exception {
+    private void deniesOnceForAllTest(StorageVolume volume, String dir) throws Exception {
+        // Rejects the first attempt...
+        UiAlertDialog dialog = openExternalDirectoryValidPath(volume, dir);
+        dialog.assertDoNotAskAgainVisibility(false);
+        dialog.noButton.click();
+        assertActivityFailed();
+
+        // ...and the second, checking the box
+        dialog = openExternalDirectoryValidPath(volume, dir);
+        UiObject checkbox = dialog.assertDoNotAskAgainVisibility(true);
+        assertTrue("checkbox should not be checkable", checkbox.isCheckable());
+        assertFalse("checkbox should not be checked", checkbox.isChecked());
+        checkbox.click();
+        assertTrue("checkbox should be checked", checkbox.isChecked()); // Sanity check
+        assertFalse("allow button should be disabled", dialog.yesButton.isEnabled());
+
+        dialog.noButton.click();
+        assertActivityFailed();
+
+        // Third strike out...
+        sendOpenExternalDirectoryIntent(volume, dir);
+        assertActivityFailed();
+    }
+
+    public void testRemovePackageStep1UserDenies() throws Exception {
+        if (!supportedHardware()) return;
+
+        deniesOnceForAllTest(getPrimaryVolume(), DIRECTORY_NOTIFICATIONS);
+    }
+
+    public void testRemovePackageStep2UserAcceptsDoNotClear() throws Exception {
+        if (!supportedHardware()) return;
+
+        userAcceptsTest(getPrimaryVolume(), DIRECTORY_NOTIFICATIONS);
+    }
+
+    private Uri userAcceptsTest(StorageVolume volume, String directoryName) throws Exception {
         // Asserts dialog contain the proper message.
         final UiAlertDialog dialog = openExternalDirectoryValidPath(volume, directoryName);
         final String message = dialog.messageText.getText();
diff --git a/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/EncryptionAppTest.java b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/EncryptionAppTest.java
index 50eb7c8..63b2f21 100644
--- a/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/EncryptionAppTest.java
+++ b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/EncryptionAppTest.java
@@ -182,6 +182,14 @@
         view.click();
         mDevice.waitForIdle();
 
+        // Yes, we really want "none" if prompted again
+        view = new UiObject(new UiSelector()
+                .resourceId("com.android.settings:id/lock_none"));
+        if (view.waitForExists(TIMEOUT)) {
+            view.click();
+            mDevice.waitForIdle();
+        }
+
         // Yes, we really want to
         view = new UiObject(new UiSelector()
                 .resourceId("android:id/button1"));
diff --git a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/ExternalStorageTest.java b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/ExternalStorageTest.java
index 6030f1c..13b7bcb 100644
--- a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/ExternalStorageTest.java
+++ b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/ExternalStorageTest.java
@@ -128,8 +128,12 @@
                     getContext().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "meow");
 
             final long id = dm.enqueue(new Request(source).setDestinationUri(Uri.fromFile(target)));
-            receiver.waitForDownloadComplete(30 * DateUtils.SECOND_IN_MILLIS, id);
-            assertSuccessfulDownload(id, target);
+            try {
+                receiver.waitForDownloadComplete(30 * DateUtils.SECOND_IN_MILLIS, id);
+                assertSuccessfulDownload(id, target);
+            } finally {
+                dm.remove(id);
+            }
         } finally {
             mContext.unregisterReceiver(receiver);
         }
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java
index d0453fb..e92234e 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java
@@ -38,12 +38,14 @@
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject;
 import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.UiScrollable;
 import android.support.test.uiautomator.UiSelector;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.Switch;
+import android.widget.ScrollView;
 import junit.framework.Assert;
 import org.junit.Before;
 import org.junit.runner.RunWith;
@@ -128,6 +130,7 @@
 
     private Context mContext;
     private Resources mPlatformResources;
+    private boolean mWatch;
 
     protected static Instrumentation getInstrumentation() {
         return InstrumentationRegistry.getInstrumentation();
@@ -172,6 +175,8 @@
             /* cannot happen */
         }
 
+        mWatch = mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
+
         UiObject2 button = getUiDevice().findObject(By.text("Close"));
         if (button != null) {
             button.click();
@@ -205,11 +210,13 @@
     }
 
     protected void clickAllowButton() throws Exception {
+        scrollToBottomIfWatch();
         getUiDevice().findObject(new UiSelector().resourceId(
                 "com.android.packageinstaller:id/permission_allow_button")).click();
     }
 
     protected void clickDenyButton() throws Exception {
+        scrollToBottomIfWatch();
         getUiDevice().findObject(new UiSelector().resourceId(
                 "com.android.packageinstaller:id/permission_deny_button")).click();
     }
@@ -220,6 +227,7 @@
     }
 
     protected void clickDontAskAgainButton() throws Exception {
+        scrollToBottomIfWatch();
         getUiDevice().findObject(new UiSelector().resourceId(
                 "com.android.packageinstaller:id/permission_deny_dont_ask_again_button")).click();
     }
@@ -240,6 +248,16 @@
         setPermissionGrantState(permissions, false, legacyApp);
     }
 
+    private void scrollToBottomIfWatch() throws Exception {
+        if (mWatch) {
+            UiScrollable scrollable =
+                    new UiScrollable(new UiSelector().className(ScrollView.class));
+            if (scrollable.exists()) {
+                scrollable.flingToEnd(10);
+            }
+        }
+    }
+
     private void setPermissionGrantState(String[] permissions, boolean granted,
             boolean legacyApp) throws Exception {
         getUiDevice().pressBack();
@@ -294,6 +312,7 @@
                 waitForIdle();
 
                 if (wasGranted && legacyApp) {
+                    scrollToBottomIfWatch();
                     String packageName = getInstrumentation().getContext().getPackageManager()
                             .getPermissionControllerPackageName();
                     String resIdName = "com.android.packageinstaller"
@@ -303,7 +322,7 @@
                     final int confirmResId = resources.getIdentifier(resIdName, null, null);
                     String confirmTitle = resources.getString(confirmResId);
                     UiObject denyAnyway = getUiDevice().findObject(new UiSelector()
-                            .text(confirmTitle.toUpperCase()));
+                            .textStartsWith(confirmTitle));
                     denyAnyway.click();
 
                     waitForIdle();
@@ -414,6 +433,7 @@
                 (AccessibilityEvent event) -> event.getEventType()
                         == AccessibilityEvent.TYPE_VIEW_SCROLLED,
                 GLOBAL_TIMEOUT_MILLIS);
+        node.refresh();
         waitForIdle();
     }
 
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 fae0a3c..dc528a1 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
@@ -28,6 +28,7 @@
 import android.Manifest;
 import android.content.pm.PackageManager;
 import android.os.Environment;
+import org.junit.Before;
 import org.junit.Test;
 
 /**
@@ -36,6 +37,16 @@
 public class UsePermissionTest23 extends BasePermissionsTest {
     private static final int REQUEST_CODE_PERMISSIONS = 42;
 
+    private boolean mLeanback;
+    private boolean mWatch;
+
+    @Before
+    public void initialize() {
+        PackageManager pm = getInstrumentation().getContext().getPackageManager();
+        mLeanback = pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+        mWatch = pm.hasSystemFeature(PackageManager.FEATURE_WATCH);
+    }
+
     public void testFail() throws Exception {
         fail("Expected");
     }
@@ -564,12 +575,11 @@
     }
 
     private void denyWithPrejudice() throws Exception {
-        if (!getInstrumentation().getContext().getPackageManager()
-                .hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
+        if (mLeanback || mWatch) {
+            clickDontAskAgainButton();
+        } else {
             clickDontAskAgainCheckbox();
             clickDenyButton();
-        } else {
-            clickDontAskAgainButton();
         }
     }
 }
diff --git a/hostsidetests/devicepolicy/app/AccountCheck/Android.mk b/hostsidetests/devicepolicy/app/AccountCheck/Android.mk
new file mode 100644
index 0000000..41a41d0
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/AccountCheck/Android.mk
@@ -0,0 +1,17 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include $(call all-subdir-makefiles)
diff --git a/hostsidetests/devicepolicy/app/AccountCheck/Auth/Android.mk b/hostsidetests/devicepolicy/app/AccountCheck/Auth/Android.mk
new file mode 100644
index 0000000..207b875
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/AccountCheck/Auth/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_PACKAGE_NAME := CtsAccountCheckAuthApp
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 ctstestrunner ub-uiautomator android-support-test
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/AccountCheck/Auth/AndroidManifest.xml b/hostsidetests/devicepolicy/app/AccountCheck/Auth/AndroidManifest.xml
new file mode 100644
index 0000000..1f488e5
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/AccountCheck/Auth/AndroidManifest.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.cts.devicepolicy.accountcheck.auth"
+    android:sharedUserId="com.android.cts.devicepolicy.accountcheck.uid">
+
+    <!-- GET_ACCOUNTS may stop working.  Targeting at 25 may prevent it. -->
+    <uses-sdk android:minSdkVersion="25" android:targetSdkVersion="25" />
+
+    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
+    <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
+    <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
+
+    <application>
+        <service android:name="com.android.cts.devicepolicy.accountcheck.TestAuthenticator"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.accounts.AccountAuthenticator" />
+            </intent-filter>
+
+            <meta-data android:name="android.accounts.AccountAuthenticator"
+                       android:resource="@xml/authenticator" />
+        </service>
+    </application>
+
+    <instrumentation
+        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.cts.devicepolicy.accountcheck.auth" />
+</manifest>
+
diff --git a/hostsidetests/devicepolicy/app/AccountCheck/Auth/res/xml/authenticator.xml b/hostsidetests/devicepolicy/app/AccountCheck/Auth/res/xml/authenticator.xml
new file mode 100644
index 0000000..ad963d7
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/AccountCheck/Auth/res/xml/authenticator.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- The attributes in this XML file provide configuration information -->
+<!-- for the Account Manager. -->
+
+<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:accountType="com.android.cts.devicepolicy.accountcheck" />
diff --git a/hostsidetests/devicepolicy/app/AccountCheck/Auth/src/com/android/cts/devicepolicy/accountcheck/AccountCheckTest.java b/hostsidetests/devicepolicy/app/AccountCheck/Auth/src/com/android/cts/devicepolicy/accountcheck/AccountCheckTest.java
new file mode 100644
index 0000000..62c0b0b
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/AccountCheck/Auth/src/com/android/cts/devicepolicy/accountcheck/AccountCheckTest.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.devicepolicy.accountcheck;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.os.Bundle;
+import android.os.SystemClock;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+public class AccountCheckTest extends AndroidTestCase {
+    private static final String TAG = "AccountCheckTest";
+
+    private static final String ACCOUNT_TYPE = "com.android.cts.devicepolicy.accountcheck";
+    private static final String ACCOUNT_FEATURE_ALLOWED =
+            "android.account.DEVICE_OR_PROFILE_OWNER_ALLOWED";
+    private static final String ACCOUNT_FEATURE_DISALLOWED =
+            "android.account.DEVICE_OR_PROFILE_OWNER_DISALLOWED";
+
+    private DevicePolicyManager mDevicePolicyManager;
+    private AccountManager mAccountManager;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mDevicePolicyManager = getContext().getSystemService(DevicePolicyManager.class);
+        mAccountManager = getContext().getSystemService(AccountManager.class);
+    }
+
+    /**
+     * Remove all test accounts.
+     */
+    public void testRemoveAllAccounts() throws Exception {
+        for (Account account : mAccountManager.getAccountsByType(ACCOUNT_TYPE)) {
+            Log.i(TAG, "Removing account: " + account);
+            mAccountManager.removeAccountExplicitly(account);
+        }
+    }
+
+    private void addAccount(String... features) throws Exception {
+        final Bundle result = mAccountManager.addAccount(
+                ACCOUNT_TYPE,
+                null, // tokentype
+                features,
+                null, // options
+                null, // activity
+                null, // callback
+                null // handler
+        ).getResult();
+        assertEquals(ACCOUNT_TYPE, result.getString(AccountManager.KEY_ACCOUNT_TYPE));
+    }
+
+    /**
+     * Add an incompatible account, type A, no features.
+     */
+    public void testAddIncompatibleA() throws Exception {
+        addAccount();
+    }
+
+    /**
+     * Add an incompatible account, type B.  Disallow feature only.
+     */
+    public void testAddIncompatibleB() throws Exception {
+        addAccount(ACCOUNT_FEATURE_DISALLOWED);
+    }
+
+    /**
+     * Add an incompatible account, type C.  Has the disallow feature.
+     */
+    public void testAddIncompatibleC() throws Exception {
+        addAccount(ACCOUNT_FEATURE_ALLOWED, ACCOUNT_FEATURE_DISALLOWED);
+    }
+
+    /**
+     * Add a compatible account.
+     */
+    public void testAddCompatible() throws Exception {
+        addAccount(ACCOUNT_FEATURE_ALLOWED);
+    }
+
+    /**
+     * Remove the non-test-only (profile|device) owner.  Note this package and the test-only owner
+     * have the same UID, so we can call clearXxX() from this package.
+     */
+    public void testCleanUpNonTestOwner() throws Exception {
+        final ComponentName admin = new ComponentName(
+                "com.android.cts.devicepolicy.accountcheck.nontestonly",
+                "com.android.cts.devicepolicy.accountcheck.owner.AdminReceiver");
+
+        if (mDevicePolicyManager.isDeviceOwnerApp(admin.getPackageName())) {
+            Log.i(TAG, "testCleanUpNonTestOwner: Removing as DO");
+            mDevicePolicyManager.clearDeviceOwnerApp(admin.getPackageName());
+        }
+
+        if (mDevicePolicyManager.isProfileOwnerApp(admin.getPackageName())) {
+            Log.i(TAG, "testCleanUpNonTestOwner: Removing as PO");
+            mDevicePolicyManager.clearProfileOwner(admin);
+        }
+
+        if (mDevicePolicyManager.isAdminActive(admin)) {
+            Log.i(TAG, "testCleanUpNonTestOwner: Removing as DA");
+            mDevicePolicyManager.removeActiveAdmin(admin);
+
+            final long timeout = SystemClock.elapsedRealtime() + 60 * 1000;
+            while (SystemClock.elapsedRealtime() < timeout
+                    && mDevicePolicyManager.isAdminActive(admin)) {
+                Thread.sleep(100);
+            }
+        }
+        // Give the system a breath.
+        Thread.sleep(5000);
+    }
+
+    /**
+     * Test there are no preconfigured accounts that don't accept DO/PO.
+     */
+    public void testCheckPreconfiguredAccountFeatures() {
+        final AccountManager am = AccountManager.get(mContext);
+        final Account accounts[] = am.getAccounts();
+        if (accounts.length == 0) {
+            Log.v(TAG, "No preconfigured accounts found.");
+            return; // pass.
+        }
+        final String[] feature_allow =
+                {"android.account.DEVICE_OR_PROFILE_OWNER_ALLOWED"};
+        final String[] feature_disallow =
+                {"android.account.DEVICE_OR_PROFILE_OWNER_DISALLOWED"};
+
+        // Even if we find incompatible accounts along the way, we still check all accounts
+        // for logging.
+        final StringBuilder error = new StringBuilder();
+        for (Account account : accounts) {
+            Log.v(TAG, "Checking " + account);
+            if (hasAccountFeatures(am, account, feature_disallow)) {
+                error.append(account + " has " + feature_disallow[0] + "\n");
+            }
+            if (!hasAccountFeatures(am, account, feature_allow)) {
+                error.append(account + " doesn't have " + feature_allow[0] + "\n");
+            }
+        }
+        if (error.length() > 0) {
+            fail(error.toString());
+        }
+    }
+
+    private boolean hasAccountFeatures(AccountManager am, Account account, String[] features) {
+        try {
+            return am.hasFeatures(account, features, null, null).getResult();
+        } catch (Exception e) {
+            Log.w(TAG, "Failed to get account feature", e);
+            return false;
+        }
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/AccountCheck/Auth/src/com/android/cts/devicepolicy/accountcheck/TestAuthenticator.java b/hostsidetests/devicepolicy/app/AccountCheck/Auth/src/com/android/cts/devicepolicy/accountcheck/TestAuthenticator.java
new file mode 100644
index 0000000..31c79d7
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/AccountCheck/Auth/src/com/android/cts/devicepolicy/accountcheck/TestAuthenticator.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.devicepolicy.accountcheck;
+
+import android.accounts.AbstractAccountAuthenticator;
+import android.accounts.Account;
+import android.accounts.AccountAuthenticatorResponse;
+import android.accounts.AccountManager;
+import android.accounts.NetworkErrorException;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.SystemClock;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class TestAuthenticator extends Service {
+    private static final String TAG = "TestAuthenticator";
+
+    private static Authenticator sInstance;
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        if (sInstance == null) {
+            sInstance = new Authenticator(getApplicationContext());
+
+        }
+        return sInstance.getIBinder();
+    }
+
+    public static class Authenticator extends AbstractAccountAuthenticator {
+
+        private final Context mContxet;
+
+        public Authenticator(Context context) {
+            super(context);
+            mContxet = context;
+        }
+
+        @Override
+        public Bundle addAccount(AccountAuthenticatorResponse response, String accountType,
+                String authTokenType, String[] requiredFeatures, Bundle options)
+                throws NetworkErrorException {
+
+            // Create an account whose name is:
+            //   [current time] + ":" + [all requested features concatenated with , ]
+
+            if (requiredFeatures == null) {
+                requiredFeatures = new String[0];
+            }
+
+            final String name = SystemClock.elapsedRealtimeNanos()
+                    + ":" + TextUtils.join(",", requiredFeatures);
+
+            Log.v(TAG, "Adding account '" + name + "' for " + accountType
+                    + "... " + Arrays.asList(requiredFeatures));
+
+            Bundle result = new Bundle();
+            result.putString(AccountManager.KEY_ACCOUNT_TYPE, accountType);
+            result.putString(AccountManager.KEY_ACCOUNT_NAME, name);
+
+            mContxet.getSystemService(AccountManager.class).addAccountExplicitly(
+                    new Account(name, accountType), "password", new Bundle());
+
+            return result;
+        }
+
+        @Override
+        public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
+            return new Bundle();
+        }
+
+        @Override
+        public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account,
+                String authTokenType, Bundle options) throws NetworkErrorException {
+            return new Bundle();
+        }
+
+        @Override
+        public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account,
+                Bundle options) throws NetworkErrorException {
+            return new Bundle();
+        }
+
+        @Override
+        public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account,
+                String authTokenType, Bundle options) throws NetworkErrorException {
+            return new Bundle();
+        }
+
+        @Override
+        public String getAuthTokenLabel(String authTokenType) {
+            return "token_label";
+        }
+
+        @Override
+        public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account,
+                String[] features) throws NetworkErrorException {
+
+            final int p = account.name.indexOf(':');
+
+            boolean hasAll = true;
+            final List<String> hasFeatures =
+                    Arrays.asList(TextUtils.split(account.name.substring(p + 1), ","));
+            for (String requested : features) {
+                if (!hasFeatures.contains(requested)) {
+                    hasAll = false;
+                    break;
+                }
+            }
+
+            Bundle result = new Bundle();
+            result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, hasAll);
+            return result;
+        }
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/AccountCheck/NonTestOnlyOwner/Android.mk b/hostsidetests/devicepolicy/app/AccountCheck/NonTestOnlyOwner/Android.mk
new file mode 100644
index 0000000..26e6dca
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/AccountCheck/NonTestOnlyOwner/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_PACKAGE_NAME := CtsAccountCheckNonTestOnlyOwnerApp
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, ../src-owner)
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 ctstestrunner ub-uiautomator android-support-test
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/AccountCheck/NonTestOnlyOwner/AndroidManifest.xml b/hostsidetests/devicepolicy/app/AccountCheck/NonTestOnlyOwner/AndroidManifest.xml
new file mode 100644
index 0000000..6b130b5
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/AccountCheck/NonTestOnlyOwner/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.cts.devicepolicy.accountcheck.nontestonly"
+    android:sharedUserId="com.android.cts.devicepolicy.accountcheck.uid">
+
+    <application android:testOnly="false">
+        <receiver
+            android:name="com.android.cts.devicepolicy.accountcheck.owner.AdminReceiver"
+            android:permission="android.permission.BIND_DEVICE_ADMIN">
+            <meta-data android:name="android.app.device_admin"
+                android:resource="@xml/device_admin" />
+            <intent-filter>
+                <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+            </intent-filter>
+        </receiver>
+    </application>
+    <!--
+      Don't need instrumentation. All the three device side apps have the same UID, so we're able
+      to run all tests from the Auth package.
+    -->
+</manifest>
diff --git a/hostsidetests/devicepolicy/app/AccountCheck/NonTestOnlyOwner/res/xml/device_admin.xml b/hostsidetests/devicepolicy/app/AccountCheck/NonTestOnlyOwner/res/xml/device_admin.xml
new file mode 100644
index 0000000..98e7028
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/AccountCheck/NonTestOnlyOwner/res/xml/device_admin.xml
@@ -0,0 +1,16 @@
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<device-admin xmlns:android="http://schemas.android.com/apk/res/android" android:visible="false">
+</device-admin>
diff --git a/hostsidetests/devicepolicy/app/AccountCheck/TestOnlyOwner/Android.mk b/hostsidetests/devicepolicy/app/AccountCheck/TestOnlyOwner/Android.mk
new file mode 100644
index 0000000..eeba939
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/AccountCheck/TestOnlyOwner/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_PACKAGE_NAME := CtsAccountCheckTestOnlyOwnerApp
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, ../src-owner)
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 ctstestrunner ub-uiautomator android-support-test
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/AccountCheck/TestOnlyOwner/AndroidManifest.xml b/hostsidetests/devicepolicy/app/AccountCheck/TestOnlyOwner/AndroidManifest.xml
new file mode 100644
index 0000000..a9673e9
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/AccountCheck/TestOnlyOwner/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.cts.devicepolicy.accountcheck.testonly"
+    android:sharedUserId="com.android.cts.devicepolicy.accountcheck.uid">
+
+    <application android:testOnly="true">
+        <receiver
+            android:name="com.android.cts.devicepolicy.accountcheck.owner.AdminReceiver"
+            android:permission="android.permission.BIND_DEVICE_ADMIN">
+            <meta-data android:name="android.app.device_admin"
+                android:resource="@xml/device_admin" />
+            <intent-filter>
+                <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+            </intent-filter>
+        </receiver>
+    </application>
+    <!--
+      Don't need instrumentation. All the three device side apps have the same UID, so we're able
+      to run all tests from the Auth package.
+    -->
+</manifest>
diff --git a/hostsidetests/devicepolicy/app/AccountCheck/TestOnlyOwner/res/xml/device_admin.xml b/hostsidetests/devicepolicy/app/AccountCheck/TestOnlyOwner/res/xml/device_admin.xml
new file mode 100644
index 0000000..98e7028
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/AccountCheck/TestOnlyOwner/res/xml/device_admin.xml
@@ -0,0 +1,16 @@
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<device-admin xmlns:android="http://schemas.android.com/apk/res/android" android:visible="false">
+</device-admin>
diff --git a/hostsidetests/devicepolicy/app/AccountCheck/TestOnlyOwnerUpdate/Android.mk b/hostsidetests/devicepolicy/app/AccountCheck/TestOnlyOwnerUpdate/Android.mk
new file mode 100644
index 0000000..a86a98b
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/AccountCheck/TestOnlyOwnerUpdate/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_PACKAGE_NAME := CtsAccountCheckTestOnlyOwnerUpdateApp
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, ../src-owner)
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 ctstestrunner ub-uiautomator android-support-test
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/AccountCheck/TestOnlyOwnerUpdate/AndroidManifest.xml b/hostsidetests/devicepolicy/app/AccountCheck/TestOnlyOwnerUpdate/AndroidManifest.xml
new file mode 100644
index 0000000..cd186e9
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/AccountCheck/TestOnlyOwnerUpdate/AndroidManifest.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<!-- This package is exactly same as TestOnlyOwner, except for testOnly=false -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.cts.devicepolicy.accountcheck.testonly"
+    android:sharedUserId="com.android.cts.devicepolicy.accountcheck.uid">
+
+    <application android:testOnly="false">
+        <receiver
+            android:name="com.android.cts.devicepolicy.accountcheck.owner.AdminReceiver"
+            android:permission="android.permission.BIND_DEVICE_ADMIN">
+            <meta-data android:name="android.app.device_admin"
+                android:resource="@xml/device_admin" />
+            <intent-filter>
+                <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+            </intent-filter>
+        </receiver>
+    </application>
+    <!--
+      Don't need instrumentation. All the three device side apps have the same UID, so we're able
+      to run all tests from the Auth package.
+    -->
+</manifest>
diff --git a/hostsidetests/devicepolicy/app/AccountCheck/TestOnlyOwnerUpdate/res/xml/device_admin.xml b/hostsidetests/devicepolicy/app/AccountCheck/TestOnlyOwnerUpdate/res/xml/device_admin.xml
new file mode 100644
index 0000000..98e7028
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/AccountCheck/TestOnlyOwnerUpdate/res/xml/device_admin.xml
@@ -0,0 +1,16 @@
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<device-admin xmlns:android="http://schemas.android.com/apk/res/android" android:visible="false">
+</device-admin>
diff --git a/hostsidetests/devicepolicy/app/AccountCheck/src-owner/com/android/cts/devicepolicy/accountcheck/owner/AdminReceiver.java b/hostsidetests/devicepolicy/app/AccountCheck/src-owner/com/android/cts/devicepolicy/accountcheck/owner/AdminReceiver.java
new file mode 100644
index 0000000..bf2ec17
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/AccountCheck/src-owner/com/android/cts/devicepolicy/accountcheck/owner/AdminReceiver.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.devicepolicy.accountcheck.owner;
+
+import android.app.admin.DeviceAdminReceiver;
+
+public class AdminReceiver extends DeviceAdminReceiver {
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceAdmin/src/com.android.cts.deviceadmin/DeviceAdminPasswordTest.java b/hostsidetests/devicepolicy/app/DeviceAdmin/src/com.android.cts.deviceadmin/DeviceAdminPasswordTest.java
index 2d1197b..26d89c0 100644
--- a/hostsidetests/devicepolicy/app/DeviceAdmin/src/com.android.cts.deviceadmin/DeviceAdminPasswordTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAdmin/src/com.android.cts.deviceadmin/DeviceAdminPasswordTest.java
@@ -68,20 +68,22 @@
     }
 
     private void assertHasPassword() {
-        dpm.setPasswordMinimumLength(mAdminComponent, 1);
+        final int currentQuality = dpm.getPasswordQuality(mAdminComponent);
+        dpm.setPasswordQuality(mAdminComponent, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
         try {
             assertTrue("No password set", dpm.isActivePasswordSufficient());
         } finally {
-            dpm.setPasswordMinimumLength(mAdminComponent, 0);
+            dpm.setPasswordQuality(mAdminComponent, currentQuality);
         }
     }
 
     private void assertNoPassword() {
-        dpm.setPasswordMinimumLength(mAdminComponent, 1);
+        final int currentQuality = dpm.getPasswordQuality(mAdminComponent);
+        dpm.setPasswordQuality(mAdminComponent, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
         try {
             assertFalse("Password is set", dpm.isActivePasswordSufficient());
         } finally {
-            dpm.setPasswordMinimumLength(mAdminComponent, 0);
+            dpm.setPasswordQuality(mAdminComponent, currentQuality);
         }
     }
 
diff --git a/hostsidetests/devicepolicy/app/DeviceAdmin/src/com.android.cts.deviceadmin/DeviceOwnerPasswordTest.java b/hostsidetests/devicepolicy/app/DeviceAdmin/src/com.android.cts.deviceadmin/DeviceOwnerPasswordTest.java
index a00b4eb..d7c3bcf 100644
--- a/hostsidetests/devicepolicy/app/DeviceAdmin/src/com.android.cts.deviceadmin/DeviceOwnerPasswordTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAdmin/src/com.android.cts.deviceadmin/DeviceOwnerPasswordTest.java
@@ -56,8 +56,9 @@
         dpm.setPasswordMinimumLength(mAdminComponent, 10);
         caseDescription = "minimum password length = 10";
         assertEquals(10, dpm.getPasswordMinimumLength(mAdminComponent));
-        assertFalse(dpm.isActivePasswordSufficient());
+        assertTrue(dpm.isActivePasswordSufficient()); // length not checked for this quality
 
+        // TODO(ascull): fix resetPassword() logic so these succeed
         assertPasswordFails("1234", caseDescription);
         assertPasswordFails("abcd", caseDescription);
         assertPasswordFails("abcd1234", caseDescription);
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/AndroidManifest.xml b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/AndroidManifest.xml
index 744db8f..632899d 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/AndroidManifest.xml
@@ -39,8 +39,6 @@
             </intent-filter>
         </receiver>
         <activity
-            android:name="com.android.cts.deviceandprofileowner.ScreenCaptureDisabledActivity" />
-        <activity
             android:name="com.android.cts.deviceandprofileowner.ExampleIntentReceivingActivity1">
             <intent-filter>
                 <action android:name="com.android.cts.deviceandprofileowner.EXAMPLE_ACTION" />
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ScreenCaptureDisabledActivity.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ScreenCaptureDisabledActivity.java
deleted file mode 100644
index b5b4fdc..0000000
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ScreenCaptureDisabledActivity.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.cts.deviceandprofileowner;
-
-import android.app.Activity;
-import android.content.Intent;
-
-/**
- * Test activity for setScreenCaptureDisabled().
- */
-public class ScreenCaptureDisabledActivity extends Activity {
-
-    static final String ACTIVITY_RESUMED =
-            "com.android.cts.deviceandprofileowner.ACTIVITY_RESUMED";
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        sendBroadcast(new Intent(ACTIVITY_RESUMED));
-    }
-}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ScreenCaptureDisabledTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ScreenCaptureDisabledTest.java
index e2deaa4..b7f9066 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ScreenCaptureDisabledTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ScreenCaptureDisabledTest.java
@@ -16,16 +16,8 @@
 package com.android.cts.deviceandprofileowner;
 
 import android.app.admin.DevicePolicyManager;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.util.Log;
 
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
 /**
  * Tests for {@link DevicePolicyManager#setScreenCaptureDisabled} and
  * {@link DevicePolicyManager#getScreenCaptureDisabled} APIs.
@@ -34,66 +26,23 @@
 
     private static final String TAG = "ScreenCaptureDisabledTest";
 
-    private ScreenCaptureBroadcastReceiver mReceiver = new ScreenCaptureBroadcastReceiver();
-
-    protected void setUp() throws Exception {
-        super.setUp();
-        mContext.registerReceiver(mReceiver, new IntentFilter(
-                ScreenCaptureDisabledActivity.ACTIVITY_RESUMED));
-    }
-
-    protected void tearDown() throws Exception {
-        mContext.unregisterReceiver(mReceiver);
-        super.tearDown();
-    }
-
     public void testSetScreenCaptureDisabled_false() throws Exception {
         mDevicePolicyManager.setScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT, false);
         assertFalse(mDevicePolicyManager.getScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT));
         assertFalse(mDevicePolicyManager.getScreenCaptureDisabled(null /* any admin */));
-        startTestActivity();
-        assertNotNull(getInstrumentation().getUiAutomation().takeScreenshot());
     }
 
     public void testSetScreenCaptureDisabled_true() throws Exception {
         mDevicePolicyManager.setScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT, true);
         assertTrue(mDevicePolicyManager.getScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT));
         assertTrue(mDevicePolicyManager.getScreenCaptureDisabled(null /* any admin */));
-        startTestActivity();
+    }
+
+    public void testScreenCaptureImpossible() throws Exception {
         assertNull(getInstrumentation().getUiAutomation().takeScreenshot());
     }
 
     public void testScreenCapturePossible() throws Exception {
         assertNotNull(getInstrumentation().getUiAutomation().takeScreenshot());
     }
-
-    // We need to launch an activity before trying to take a screen shot, because screenshots are
-    // only blocked on a per-user basis in the profile owner case depending on the owner of the
-    // foreground activity.
-    private void startTestActivity() throws Exception {
-        Intent launchIntent = new Intent();
-        launchIntent.setComponent(new ComponentName(PACKAGE_NAME,
-                ScreenCaptureDisabledActivity.class.getName()));
-        launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        mContext.startActivity(launchIntent);
-        assertTrue(mReceiver.waitForBroadcast());
-        Thread.sleep(1000);
-    }
-
-    private class ScreenCaptureBroadcastReceiver extends BroadcastReceiver {
-        private final Semaphore mSemaphore = new Semaphore(0);
-
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            Log.d(TAG, "Broadcast received");
-            mSemaphore.release();
-        }
-
-        public boolean waitForBroadcast() throws Exception {
-            if (mSemaphore.tryAcquire(5, TimeUnit.SECONDS)) {
-                return true;
-            }
-            return false;
-        }
-    }
 }
diff --git a/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleActivity.java b/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleActivity.java
index 628a2cd..918094c 100644
--- a/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleActivity.java
+++ b/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleActivity.java
@@ -20,6 +20,7 @@
 import android.content.Intent;
 import android.os.Bundle;
 import android.util.Log;
+import android.view.WindowManager;
 
 import java.lang.Override;
 
@@ -35,6 +36,7 @@
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
         Log.i(TAG, "Created for user " + android.os.Process.myUserHandle());
     }
 
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/AccountCheckHostSideTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/AccountCheckHostSideTest.java
new file mode 100644
index 0000000..57c3b55
--- /dev/null
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/AccountCheckHostSideTest.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.devicepolicy;
+
+import com.android.tradefed.log.LogUtil.CLog;
+
+import junit.framework.AssertionFailedError;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class AccountCheckHostSideTest extends BaseDevicePolicyTest {
+    private static final String APK_NON_TEST_ONLY = "CtsAccountCheckNonTestOnlyOwnerApp.apk";
+    private static final String APK_TEST_ONLY = "CtsAccountCheckTestOnlyOwnerApp.apk";
+    private static final String APK_TEST_ONLY_UPDATE = "CtsAccountCheckTestOnlyOwnerUpdateApp.apk";
+    private static final String APK_AUTH = "CtsAccountCheckAuthApp.apk";
+
+    private static final String PACKAGE_NON_TEST_ONLY =
+            "com.android.cts.devicepolicy.accountcheck.nontestonly";
+    private static final String PACKAGE_TEST_ONLY =
+            "com.android.cts.devicepolicy.accountcheck.testonly";
+    private static final String PACKAGE_AUTH = "com.android.cts.devicepolicy.accountcheck.auth";
+
+    private static final String OWNER_TEST_ONLY = PACKAGE_TEST_ONLY
+            + "/com.android.cts.devicepolicy.accountcheck.owner.AdminReceiver";
+    private static final String OWNER_NON_TEST_ONLY = PACKAGE_NON_TEST_ONLY
+            + "/com.android.cts.devicepolicy.accountcheck.owner.AdminReceiver";
+
+    private static final String TEST_CLASS =
+            "com.android.cts.devicepolicy.accountcheck.AccountCheckTest";
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mHasFeature) {
+            if (getDevice().getInstalledPackageNames().contains(PACKAGE_AUTH)) {
+                runCleanupTestOnlyOwnerAllowingFailure();
+                runCleanupNonTestOnlyOwnerAllowingFailure();
+
+                // This shouldn't be needed since we're uninstalling the authenticator,
+                // but sometimes the account manager fails to clean up?
+                removeAllAccountsAllowingFailure();
+            }
+
+            getDevice().uninstallPackage(PACKAGE_AUTH);
+            getDevice().uninstallPackage(PACKAGE_TEST_ONLY);
+            getDevice().uninstallPackage(PACKAGE_NON_TEST_ONLY);
+        }
+        super.tearDown();
+    }
+
+    private void runTest(String method) throws Exception {
+        assertTrue(runDeviceTests(PACKAGE_AUTH, TEST_CLASS, method));
+    }
+
+    private void runCleanupTestOnlyOwner() throws Exception {
+        assertTrue(removeAdmin(OWNER_TEST_ONLY, mPrimaryUserId));
+    }
+
+    private void runCleanupTestOnlyOwnerAllowingFailure() throws Exception {
+        try {
+            runCleanupTestOnlyOwner();
+        } catch (AssertionFailedError ignore) {
+        }
+    }
+
+    private void runCleanupNonTestOnlyOwner() throws Exception {
+        runTest("testCleanUpNonTestOwner");
+    }
+
+    private void runCleanupNonTestOnlyOwnerAllowingFailure() throws Exception {
+        try {
+            runCleanupNonTestOnlyOwner();
+        } catch (AssertionFailedError ignore) {
+        }
+    }
+
+    private void removeAllAccounts() throws Exception {
+        runTest("testRemoveAllAccounts");
+    }
+
+    private void removeAllAccountsAllowingFailure() throws Exception {
+        try {
+            removeAllAccounts();
+        } catch (AssertionFailedError ignore) {
+        }
+    }
+
+    private void assertTestOnlyInstallable() throws Exception {
+        setDeviceOwnerOrFail(OWNER_TEST_ONLY, mPrimaryUserId);
+        runCleanupTestOnlyOwner();
+
+        setProfileOwnerOrFail(OWNER_TEST_ONLY, mPrimaryUserId);
+        runCleanupTestOnlyOwner();
+    }
+
+    private void assertNonTestOnlyInstallable() throws Exception {
+        setDeviceOwnerOrFail(OWNER_NON_TEST_ONLY, mPrimaryUserId);
+        runCleanupNonTestOnlyOwner();
+
+        setProfileOwnerOrFail(OWNER_NON_TEST_ONLY, mPrimaryUserId);
+        runCleanupNonTestOnlyOwner();
+    }
+
+    private void assertTestOnlyNotInstallable() throws Exception {
+        setDeviceOwnerExpectingFailure(OWNER_TEST_ONLY, mPrimaryUserId);
+        runCleanupTestOnlyOwnerAllowingFailure();
+
+        setProfileOwnerExpectingFailure(OWNER_TEST_ONLY, mPrimaryUserId);
+        runCleanupTestOnlyOwnerAllowingFailure();
+    }
+
+    private void assertNonTestOnlyNotInstallable() throws Exception {
+        setDeviceOwnerExpectingFailure(OWNER_NON_TEST_ONLY, mPrimaryUserId);
+        runCleanupNonTestOnlyOwnerAllowingFailure();
+
+        setProfileOwnerExpectingFailure(OWNER_NON_TEST_ONLY, mPrimaryUserId);
+        runCleanupNonTestOnlyOwnerAllowingFailure();
+    }
+
+    private boolean hasAccounts() throws Exception {
+        final String accountDump = getDevice().executeShellCommand("dumpsys account");
+
+        final Pattern p = Pattern.compile("^\\s*Accounts\\:\\s*(\\d+)", Pattern.MULTILINE);
+        final Matcher m = p.matcher(accountDump);
+        if (!m.find()) {
+            fail("Unable to obtain # of accounts");
+            return true;
+        }
+        final String count = m.group(1);
+
+        CLog.i("# of preconfigured accounts=" + count);
+
+        return Integer.parseInt(count) > 0;
+    }
+
+    public void testAccountCheck() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        installAppAsUser(APK_AUTH, mPrimaryUserId);
+        installAppAsUser(APK_NON_TEST_ONLY, mPrimaryUserId);
+        installAppAsUser(APK_TEST_ONLY, mPrimaryUserId);
+
+        runCleanupTestOnlyOwnerAllowingFailure();
+        runCleanupNonTestOnlyOwnerAllowingFailure();
+        removeAllAccountsAllowingFailure();
+        try {
+            runTest("testCheckPreconfiguredAccountFeatures");
+
+            final boolean hasPreconfiguredAccounts = hasAccounts();
+
+            // All pre-configured accounts must be "compatible", so the test-only owner can be
+            // installed.
+            assertTestOnlyInstallable();
+
+            if (hasPreconfiguredAccounts) {
+                assertNonTestOnlyNotInstallable();
+            } else {
+                assertNonTestOnlyInstallable();
+            }
+
+            // Incompatible, type A.
+            runTest("testAddIncompatibleA");
+
+            assertTestOnlyNotInstallable();
+            assertNonTestOnlyNotInstallable();
+
+            // The following tests use non-public strings, so disabled until they go public.
+//            // Incompatible, type B.
+//            removeAllAccounts();
+//            runTest("testAddIncompatibleB");
+//
+//            assertTestOnlyNotInstallable();
+//            assertNonTestOnlyNotInstallable();
+//
+//            // Incompatible, type C.
+//            removeAllAccounts();
+//            runTest("testAddIncompatibleC");
+//
+//            assertTestOnlyNotInstallable();
+//            assertNonTestOnlyNotInstallable();
+//
+//            // Compatible.
+//            removeAllAccounts();
+//            runTest("testAddCompatible");
+//
+//            assertTestOnlyInstallable(); // Now test-only owner can be accepted.
+//            assertNonTestOnlyNotInstallable();
+//
+//            // 2 compatible accounts.
+//            removeAllAccounts();
+//            runTest("testAddCompatible");
+//            runTest("testAddCompatible");
+//
+//            assertTestOnlyInstallable(); // Now test-only owner can be accepted.
+//
+//            assertNonTestOnlyNotInstallable();
+//
+//            // 2 compatible accounts + 1 incompatible.
+//            removeAllAccounts();
+//            runTest("testAddIncompatibleA");
+//            runTest("testAddCompatible");
+//            runTest("testAddCompatible");
+//
+//            assertTestOnlyNotInstallable();
+//            assertNonTestOnlyNotInstallable();
+//
+//            // 2 compatible accounts + 1 incompatible, different order.
+//            removeAllAccounts();
+//            runTest("testAddCompatible");
+//            runTest("testAddCompatible");
+//            runTest("testAddIncompatibleB");
+//
+//            assertTestOnlyNotInstallable();
+//            assertNonTestOnlyNotInstallable();
+        } catch (Throwable th) {
+            CLog.w("Tests failed; current accounts are:");
+            CLog.w(getDevice().executeShellCommand("dumpsys account"));
+
+            // Dump accounts
+            throw th;
+        }
+    }
+
+    /**
+     * Make sure even if the "test-only" flag changes when an app is updated, we still respect
+     * the original value.
+     */
+    public void testInheritTestOnly() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        try {
+            installAppAsUser(APK_TEST_ONLY, mPrimaryUserId);
+
+            // Set as DO.
+            setDeviceOwnerOrFail(OWNER_TEST_ONLY, mPrimaryUserId);
+
+            // Override with a package that's not test-only.
+            installAppAsUser(APK_TEST_ONLY_UPDATE, mPrimaryUserId);
+
+            // But DPMS keeps the original test-only flag, so it's still removable.
+            runCleanupTestOnlyOwner();
+
+            return;
+        } catch (Throwable e) {
+            // If failed, re-install the APK with test-only=true.
+            try {
+                installAppAsUser(APK_TEST_ONLY, mPrimaryUserId);
+                runCleanupTestOnlyOwner();
+            } catch (Exception inner) {
+                CLog.e("Unable to clean up after a failure: " + e.getMessage());
+            }
+
+            throw e;
+        }
+    }
+}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index 5ca134a..85e1f7d 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -17,8 +17,6 @@
 package com.android.cts.devicepolicy;
 
 import com.android.cts.migration.MigrationHelper;
-import com.android.ddmlib.Log.LogLevel;
-import com.android.ddmlib.testrunner.InstrumentationResultParser;
 import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
 import com.android.ddmlib.testrunner.TestIdentifier;
 import com.android.ddmlib.testrunner.TestResult;
@@ -26,21 +24,17 @@
 import com.android.ddmlib.testrunner.TestRunResult;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.result.CollectingTestListener;
 import com.android.tradefed.testtype.DeviceTestCase;
 import com.android.tradefed.testtype.IBuildReceiver;
 
-import java.io.File;
 import java.io.FileNotFoundException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 import javax.annotation.Nullable;
 
@@ -229,6 +223,12 @@
         return runDeviceTestsAsUser(pkgName, testClassName, testMethodName, userId, params);
     }
 
+    protected boolean runDeviceTests(
+            String pkgName, @Nullable String testClassName, String testMethodName)
+            throws DeviceNotAvailableException {
+        return runDeviceTestsAsUser(pkgName, testClassName, testMethodName, mPrimaryUserId);
+    }
+
     protected boolean runDeviceTestsAsUser(String pkgName, @Nullable String testClassName,
             @Nullable String testMethodName, int userId,
             Map<String, String> params) throws DeviceNotAvailableException {
@@ -259,7 +259,7 @@
     /** Reboots the device and block until the boot complete flag is set. */
     protected void rebootAndWaitUntilReady() throws DeviceNotAvailableException {
         getDevice().executeShellCommand("reboot");
-        assertTrue("Device failed to boot", getDevice().waitForBootComplete(60000));
+        assertTrue("Device failed to boot", getDevice().waitForBootComplete(120000));
     }
 
     /** Returns true if the system supports the split between system and primary user. */
@@ -410,11 +410,23 @@
     protected void setProfileOwnerOrFail(String componentName, int userId)
             throws Exception {
         if (!setProfileOwner(componentName, userId, /*expectFailure*/ false)) {
-            removeUser(userId);
+            if (userId != 0) { // don't remove system user.
+                removeUser(userId);
+            }
             fail("Failed to set profile owner");
         }
     }
 
+    protected void setProfileOwnerExpectingFailure(String componentName, int userId)
+            throws Exception {
+        if (setProfileOwner(componentName, userId, /* expectFailure =*/ true)) {
+            if (userId != 0) { // don't remove system user.
+                removeUser(userId);
+            }
+            fail("Setting profile owner should have failed.");
+        }
+    }
+
     private String setDeviceAdminInner(String componentName, int userId)
             throws DeviceNotAvailableException {
         String command = "dpm set-active-admin --user " + userId + " '" + componentName + "'";
@@ -454,6 +466,16 @@
         return success;
     }
 
+    protected void setDeviceOwnerOrFail(String componentName, int userId)
+            throws Exception {
+        assertTrue(setDeviceOwner(componentName, userId, /* expectFailure =*/ false));
+    }
+
+    protected void setDeviceOwnerExpectingFailure(String componentName, int userId)
+            throws Exception {
+        assertFalse(setDeviceOwner(componentName, userId, /* expectFailure =*/ true));
+    }
+
     protected String getSettings(String namespace, String name, int userId)
             throws DeviceNotAvailableException {
         String command = "settings --user " + userId + " get " + namespace + " " + name;
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
index d36e473..7427570 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
@@ -106,6 +106,7 @@
             getDevice().uninstallPackage(INTENT_RECEIVER_PKG);
             getDevice().uninstallPackage(INTENT_SENDER_PKG);
             getDevice().uninstallPackage(CUSTOMIZATION_APP_PKG);
+            getDevice().uninstallPackage(TEST_APP_PKG);
 
             // Press the HOME key to close any alart dialog that may be shown.
             getDevice().executeShellCommand("input keyevent 3");
@@ -288,11 +289,9 @@
         // We need to ensure that the policy is deactivated for the device owner case, so making
         // sure the second test is run even if the first one fails
         try {
-            executeDeviceTestMethod(".ScreenCaptureDisabledTest",
-                    "testSetScreenCaptureDisabled_true");
+            setScreenCaptureDisabled(mUserId, true);
         } finally {
-            executeDeviceTestMethod(".ScreenCaptureDisabledTest",
-                    "testSetScreenCaptureDisabled_false");
+            setScreenCaptureDisabled(mUserId, false);
         }
     }
 
@@ -457,6 +456,10 @@
         if (!mHasFeature) {
             return;
         }
+        boolean mIsWatch = hasDeviceFeature("android.hardware.type.watch");
+        if (mIsWatch) {
+            return;
+        }
         // UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES
         final String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources";
         final String UNKNOWN_SOURCES_SETTING = "install_non_market_apps";
@@ -496,12 +499,7 @@
             putSettings(SECURE_SETTING_CATEGORY, PACKAGE_VERIFIER_USER_CONSENT_SETTING, "-1",
                     mUserId);
             putSettings(GLOBAL_SETTING_CATEGORY, PACKAGE_VERIFIER_ENABLE_SETTING, "0", mUserId);
-            assertEquals("1",
-                    getSettings(SECURE_SETTING_CATEGORY, UNKNOWN_SOURCES_SETTING, mUserId));
-            assertEquals("-1", getSettings(SECURE_SETTING_CATEGORY,
-                    PACKAGE_VERIFIER_USER_CONSENT_SETTING, mUserId));
-            assertEquals("0", getSettings(GLOBAL_SETTING_CATEGORY,
-                    PACKAGE_VERIFIER_ENABLE_SETTING, mUserId));
+            // Skip verifying above setting values as some of them may be overrided.
             assertTrue(runDeviceTestsAsUser(PACKAGE_INSTALLER_PKG, ".ManualPackageInstallTest",
                     "testManualInstallSucceeded", mUserId));
         } finally {
@@ -617,4 +615,38 @@
         assertTrue("Command was expected to succeed " + commandOutput,
                 commandOutput.contains("Status: ok"));
     }
+
+    /**
+     * Start SimpleActivity synchronously in a particular user.
+     */
+    protected void startScreenCaptureDisabledActivity(int userId) throws Exception {
+        installAppAsUser(TEST_APP_APK, userId);
+        String command = "am start -W --user " + userId + " " + TEST_APP_PKG + "/"
+                + TEST_APP_PKG + ".SimpleActivity";
+        getDevice().executeShellCommand(command);
+    }
+
+    // TODO: Remove this after investigation in b/28995242 is done
+    // So we can check which one is the top window / activity.
+    private void runDumpsysWindow() throws Exception {
+        String command = "dumpsys window displays";
+        CLog.d("Output for command " + command + ": " + getDevice().executeShellCommand(command));
+        command = "dumpsys activity a";
+        CLog.d("Output for command " + command + ": " + getDevice().executeShellCommand(command));
+    }
+
+    protected void setScreenCaptureDisabled(int userId, boolean disabled) throws Exception {
+        String testMethodName = disabled
+                ? "testSetScreenCaptureDisabled_true"
+                : "testSetScreenCaptureDisabled_false";
+        executeDeviceTestMethod(".ScreenCaptureDisabledTest", testMethodName);
+        startScreenCaptureDisabledActivity(userId);
+        // [b/28995242], dump windows to make sure the top window is
+        // ScreenCaptureDisabledActivity.
+        runDumpsysWindow();
+        testMethodName = disabled
+                ? "testScreenCaptureImpossible"
+                : "testScreenCapturePossible";
+        executeDeviceTestMethod(".ScreenCaptureDisabledTest", testMethodName);
+    }
 }
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java
index b467aed..afc4e34 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java
@@ -73,29 +73,13 @@
         if (!mHasFeature) {
             return;
         }
-        runDumpsysWindow();
-        try {
-            executeDeviceTestMethod(".ScreenCaptureDisabledTest",
-                    "testSetScreenCaptureDisabled_true");
-            // start the ScreenCaptureDisabledActivity in the parent
-            installAppAsUser(DEVICE_ADMIN_APK, mParentUserId);
-            String command = "am start -W --user " + mParentUserId + " " + DEVICE_ADMIN_PKG + "/"
-                    + DEVICE_ADMIN_PKG + ".ScreenCaptureDisabledActivity";
-            getDevice().executeShellCommand(command);
-            executeDeviceTestMethod(".ScreenCaptureDisabledTest", "testScreenCapturePossible");
-        } catch (AssertionError e) {
-            runDumpsysWindow();
-            CLog.e("testScreenCaptureDisabled_allowedPrimaryUser failed", e);
-            fail("testScreenCaptureDisabled_allowedPrimaryUser failed");
-        }
-    }
+        // disable screen capture in profile
+        setScreenCaptureDisabled(mUserId, true);
 
-    // TODO: Remove this after investigation in b/28995242 is done
-    private void runDumpsysWindow() throws Exception {
-        String command = "dumpsys window displays";
-        CLog.d("Output for command " + command + ": " + getDevice().executeShellCommand(command));
-        command = "dumpsys window policy";
-        CLog.d("Output for command " + command + ": " + getDevice().executeShellCommand(command));
+        // start the ScreenCaptureDisabledActivity in the parent
+        installAppAsUser(DEVICE_ADMIN_APK, mParentUserId);
+        startScreenCaptureDisabledActivity(mParentUserId);
+        executeDeviceTestMethod(".ScreenCaptureDisabledTest", "testScreenCapturePossible");
     }
 
     @Override
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/UserRestrictionsTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/UserRestrictionsTest.java
index 789ce87..bc61a81 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/UserRestrictionsTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/UserRestrictionsTest.java
@@ -45,7 +45,8 @@
                         removeAdmin(DEVICE_ADMIN_PKG + "/" + ADMIN_RECEIVER_TEST_CLASS,
                                 mDeviceOwnerUserId));
                 assertTrue("Some user restrictions are still set",
-                        runTests("userrestrictions.CheckNoOwnerRestrictionsTest", mDeviceOwnerUserId));
+                        runTests("userrestrictions.CheckNoOwnerRestrictionsTest",
+                                mDeviceOwnerUserId));
             }
 
             // DO/PO might have set DISALLOW_REMOVE_USER, so it needs to be done after removing
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java
index ba56665..78ba4b9 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java
@@ -16,6 +16,7 @@
 
 package com.android.cts.net.hostside;
 
+import android.os.SystemClock;
 import android.util.Log;
 
 /**
@@ -138,4 +139,40 @@
         assertsForegroundAlwaysHasNetworkAccess();
         assertBackgroundNetworkAccess(true);
     }
+
+    public void testAppIdleNetworkAccess_whenCharging() throws Exception {
+        if (!isSupported()) return;
+
+        // Check that app is paroled when charging
+        setAppIdle(true);
+        assertBackgroundNetworkAccess(false);
+        turnBatteryOn();
+        assertBackgroundNetworkAccess(true);
+        turnBatteryOff();
+        assertBackgroundNetworkAccess(false);
+
+        // Check that app is restricted when not idle but power-save is on
+        setAppIdle(false);
+        assertBackgroundNetworkAccess(true);
+        setBatterySaverMode(true);
+        assertBackgroundNetworkAccess(false);
+        turnBatteryOn();
+        assertBackgroundNetworkAccess(true);
+
+        // And when no longer charging, it still has network access, since it's not idle
+        turnBatteryOff();
+        assertBackgroundNetworkAccess(true);
+    }
+
+    public void testAppIdle_toast() throws Exception {
+        if (!isSupported()) return;
+
+        setAppIdle(true);
+        assertAppIdle(true);
+        assertEquals("Shown", showToast());
+        assertAppIdle(true);
+        // Wait for a couple of seconds for the toast to actually be shown
+        SystemClock.sleep(2000);
+        assertAppIdle(true);
+    }
 }
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractBatterySaverModeTestCase.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractBatterySaverModeTestCase.java
index c1c91da..50bcc60 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractBatterySaverModeTestCase.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractBatterySaverModeTestCase.java
@@ -85,16 +85,24 @@
         assertsForegroundAlwaysHasNetworkAccess();
         assertBackgroundNetworkAccess(false);
 
-        // Make sure foreground app doesn't lose access upon enabling it.
+        // Make sure foreground app doesn't lose access upon Battery Saver.
         setBatterySaverMode(false);
         launchActivity();
         assertForegroundNetworkAccess();
         setBatterySaverMode(true);
         assertForegroundNetworkAccess();
+
+        // Although it should not have access while the screen is off.
+        turnScreenOff();
+        assertBackgroundNetworkAccess(false);
+        turnScreenOn();
+        assertForegroundNetworkAccess();
+
+        // Goes back to background state.
         finishActivity();
         assertBackgroundNetworkAccess(false);
 
-        // Same for foreground service.
+        // Make sure foreground service doesn't lose access upon enabling Battery Saver.
         setBatterySaverMode(false);
         startForegroundService();
         assertForegroundNetworkAccess();
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
index 4bfd50d..cbd8fea 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
@@ -29,6 +29,7 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
@@ -64,6 +65,8 @@
             "com.android.cts.net.hostside.app2.action.RECEIVER_READY";
     static final String ACTION_SEND_NOTIFICATION =
             "com.android.cts.net.hostside.app2.action.SEND_NOTIFICATION";
+    static final String ACTION_SHOW_TOAST =
+            "com.android.cts.net.hostside.app2.action.SHOW_TOAST";
     private static final String EXTRA_ACTION = "com.android.cts.net.hostside.app2.extra.ACTION";
     private static final String EXTRA_RECEIVER_NAME =
             "com.android.cts.net.hostside.app2.extra.RECEIVER_NAME";
@@ -97,6 +100,8 @@
     protected WifiManager mWfm;
     protected int mUid;
     private String mMeteredWifi;
+    private boolean mHasWatch;
+    private String mDeviceIdleConstantsSetting;
 
     @Override
     protected void setUp() throws Exception {
@@ -108,7 +113,13 @@
         mWfm = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
         mUid = getUid(TEST_APP2_PKG);
         final int myUid = getUid(mContext.getPackageName());
-
+        mHasWatch = mContext.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_WATCH);
+        if (mHasWatch) {
+            mDeviceIdleConstantsSetting = "device_idle_constants_watch";
+        } else {
+            mDeviceIdleConstantsSetting = "device_idle_constants";
+        }
         Log.i(TAG, "Apps status on " + getName() + ":\n"
                 + "\ttest app: uid=" + myUid + ", state=" + getProcessStateByUid(myUid) + "\n"
                 + "\tapp2: uid=" + mUid + ", state=" + getProcessStateByUid(mUid));
@@ -244,7 +255,7 @@
             if (isBackground(state.state)) {
                 return;
             }
-            Log.d(TAG, "App not on background state on attempt #" + i
+            Log.d(TAG, "App not on background state (" + state + ") on attempt #" + i
                     + "; sleeping 1s before trying again");
             SystemClock.sleep(SECOND_IN_MS);
         }
@@ -724,14 +735,14 @@
     }
 
     protected void setPendingIntentWhitelistDuration(int durationMs) throws Exception {
-        final String command = String.format(
-                "settings put global device_idle_constants %s=%d",
-                "notification_whitelist_duration", durationMs);
-        executeSilentShellCommand(command);
+        executeSilentShellCommand(String.format(
+                "settings put global %s %s=%d", mDeviceIdleConstantsSetting,
+                "notification_whitelist_duration", durationMs));
     }
 
     protected void resetDeviceIdleSettings() throws Exception {
-        executeShellCommand("settings delete global device_idle_constants");
+        executeShellCommand(String.format("settings delete global %s",
+                mDeviceIdleConstantsSetting));
     }
 
     protected void startForegroundService() throws Exception {
@@ -783,6 +794,17 @@
         mContext.sendBroadcast(intent);
     }
 
+    protected String showToast() {
+        final Intent intent = new Intent(ACTION_SHOW_TOAST);
+        intent.setPackage(TEST_APP2_PKG);
+        Log.d(TAG, "Sending request to show toast");
+        try {
+            return sendOrderedBroadcast(intent, 3 * SECOND_IN_MS);
+        } catch (Exception e) {
+            return "";
+        }
+    }
+
     private String toString(int status) {
         switch (status) {
             case RESTRICT_BACKGROUND_STATUS_DISABLED:
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
index 3e6bd33..881b3b4 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
@@ -98,16 +98,24 @@
         assertsForegroundAlwaysHasNetworkAccess();
         assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED);
 
-        // Make sure foreground app doesn't lose access upon enabling it.
+        // Make sure foreground app doesn't lose access upon enabling Data Saver.
         setRestrictBackground(false);
         launchActivity();
         assertForegroundNetworkAccess();
         setRestrictBackground(true);
         assertForegroundNetworkAccess();
+
+        // Although it should not have access while the screen is off.
+        turnScreenOff();
+        assertBackgroundNetworkAccess(false);
+        turnScreenOn();
+        assertForegroundNetworkAccess();
+
+        // Goes back to background state.
         finishActivity();
         assertBackgroundNetworkAccess(false);
 
-        // Same for foreground service.
+        // Make sure foreground service doesn't lose access upon enabling Data Saver.
         setRestrictBackground(false);
         startForegroundService();
         assertForegroundNetworkAccess();
diff --git a/hostsidetests/net/app2/AndroidManifest.xml b/hostsidetests/net/app2/AndroidManifest.xml
index 1fa49ba..adf0045 100644
--- a/hostsidetests/net/app2/AndroidManifest.xml
+++ b/hostsidetests/net/app2/AndroidManifest.xml
@@ -46,6 +46,7 @@
                 <action android:name="com.android.cts.net.hostside.app2.action.GET_RESTRICT_BACKGROUND_STATUS" />
                 <action android:name="com.android.cts.net.hostside.app2.action.CHECK_NETWORK" />
                 <action android:name="com.android.cts.net.hostside.app2.action.SEND_NOTIFICATION" />
+                <action android:name="com.android.cts.net.hostside.app2.action.SHOW_TOAST" />
                 </intent-filter>
         </receiver>
     </application>
diff --git a/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/Common.java b/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/Common.java
index 8806e3b..e07c0f5 100644
--- a/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/Common.java
+++ b/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/Common.java
@@ -38,6 +38,8 @@
             "com.android.cts.net.hostside.app2.action.FINISH_ACTIVITY";
     static final String ACTION_SEND_NOTIFICATION =
             "com.android.cts.net.hostside.app2.action.SEND_NOTIFICATION";
+    static final String ACTION_SHOW_TOAST =
+            "com.android.cts.net.hostside.app2.action.SHOW_TOAST";
     static final String EXTRA_ACTION = "com.android.cts.net.hostside.app2.extra.ACTION";
     static final String EXTRA_RECEIVER_NAME =
             "com.android.cts.net.hostside.app2.extra.RECEIVER_NAME";
diff --git a/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java b/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java
index 6d01b15..733c3aa 100644
--- a/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java
+++ b/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java
@@ -23,6 +23,7 @@
 import static com.android.cts.net.hostside.app2.Common.ACTION_GET_RESTRICT_BACKGROUND_STATUS;
 import static com.android.cts.net.hostside.app2.Common.ACTION_RECEIVER_READY;
 import static com.android.cts.net.hostside.app2.Common.ACTION_SEND_NOTIFICATION;
+import static com.android.cts.net.hostside.app2.Common.ACTION_SHOW_TOAST;
 import static com.android.cts.net.hostside.app2.Common.EXTRA_ACTION;
 import static com.android.cts.net.hostside.app2.Common.EXTRA_NOTIFICATION_ID;
 import static com.android.cts.net.hostside.app2.Common.EXTRA_NOTIFICATION_TYPE;
@@ -51,6 +52,7 @@
 import android.net.NetworkInfo;
 import android.os.Bundle;
 import android.util.Log;
+import android.widget.Toast;
 
 import java.net.HttpURLConnection;
 import java.net.URL;
@@ -104,6 +106,9 @@
             case ACTION_SEND_NOTIFICATION:
                 sendNotification(context, intent);
                 break;
+            case ACTION_SHOW_TOAST:
+                showToast(context);
+                break;
             default:
                 Log.e(TAG, "received unexpected action: " + action);
         }
@@ -302,4 +307,9 @@
         ((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE))
             .notify(notificationId, notification);
     }
+
+    private void showToast(Context context) {
+        Toast.makeText(context, "Toast from CTS test", Toast.LENGTH_SHORT).show();
+        setResultData("Shown");
+    }
 }
diff --git a/hostsidetests/net/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java b/hostsidetests/net/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
index 7d5f817..faf75d9 100644
--- a/hostsidetests/net/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
+++ b/hostsidetests/net/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
@@ -171,6 +171,22 @@
                 "testBackgroundNetworkAccess_enabled");
     }
 
+    public void testAppIdleNonMetered_whenCharging() throws Exception {
+        runDeviceTests(TEST_PKG, TEST_PKG + ".AppIdleNonMeteredTest",
+                "testAppIdleNetworkAccess_whenCharging");
+    }
+
+    public void testAppIdleMetered_whenCharging() throws Exception {
+        runDeviceTests(TEST_PKG, TEST_PKG + ".AppIdleMeteredTest",
+                "testAppIdleNetworkAccess_whenCharging");
+    }
+
+    public void testAppIdle_toast() throws Exception {
+        // Check that showing a toast doesn't bring an app out of standby
+        runDeviceTests(TEST_PKG, TEST_PKG + ".AppIdleNonMeteredTest",
+                "testAppIdle_toast");
+    }
+
     /********************
      * Doze Mode tests. *
      ********************/
diff --git a/hostsidetests/retaildemo/Android.mk b/hostsidetests/retaildemo/Android.mk
new file mode 100644
index 0000000..0aa5ee1
--- /dev/null
+++ b/hostsidetests/retaildemo/Android.mk
@@ -0,0 +1,35 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CtsRetailDemoHostTestCases
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := tools-common-prebuilt cts-tradefed tradefed-prebuilt
+
+LOCAL_CTS_TEST_PACKAGE := android.host.retaildemo
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+include $(BUILD_CTS_HOST_JAVA_LIBRARY)
+
+# Build the test APKs using their own makefiles
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/retaildemo/AndroidTest.xml b/hostsidetests/retaildemo/AndroidTest.xml
new file mode 100644
index 0000000..c174489
--- /dev/null
+++ b/hostsidetests/retaildemo/AndroidTest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for the CTS retaildemo host tests">
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+        <option name="test-file-name" value="CtsRetailDemoApp.apk" />
+        <option name="cleanup-apks" value="true" />
+    </target_preparer>
+
+    <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+        <option name="jar" value="CtsRetailDemoHostTestCases.jar" />
+    </test>
+
+</configuration>
\ No newline at end of file
diff --git a/hostsidetests/retaildemo/app/Android.mk b/hostsidetests/retaildemo/app/Android.mk
new file mode 100644
index 0000000..e91e1da
--- /dev/null
+++ b/hostsidetests/retaildemo/app/Android.mk
@@ -0,0 +1,35 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Don't include this package in any target
+LOCAL_MODULE_TAGS := tests
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_PACKAGE_NAME := CtsRetailDemoApp
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/retaildemo/app/AndroidManifest.xml b/hostsidetests/retaildemo/app/AndroidManifest.xml
new file mode 100644
index 0000000..b36ee1b
--- /dev/null
+++ b/hostsidetests/retaildemo/app/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.cts.retaildemo">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+            android:targetPackage="com.android.cts.retaildemo"
+            android:label="RetailDemo device side tests" />
+</manifest>
diff --git a/hostsidetests/retaildemo/app/src/com/android/cts/retaildemo/DemoUserTest.java b/hostsidetests/retaildemo/app/src/com/android/cts/retaildemo/DemoUserTest.java
new file mode 100644
index 0000000..bb20b1a
--- /dev/null
+++ b/hostsidetests/retaildemo/app/src/com/android/cts/retaildemo/DemoUserTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.retaildemo;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import android.content.Context;
+import android.os.UserManager;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@SmallTest
+@RunWith(JUnit4.class)
+public class DemoUserTest {
+    private UserManager mUm;
+
+    @Before
+    public void setUp() {
+        mUm = InstrumentationRegistry.getContext().getSystemService(UserManager.class);
+    }
+
+    @Test
+    public void testIsDemoUser_success() {
+        assertTrue(mUm.isDemoUser());
+    }
+
+    @Test
+    public void testIsDemoUser_failure() {
+        assertFalse(mUm.isDemoUser());
+    }
+}
diff --git a/hostsidetests/retaildemo/src/android/host/retaildemo/BaseTestCase.java b/hostsidetests/retaildemo/src/android/host/retaildemo/BaseTestCase.java
new file mode 100644
index 0000000..5033b6d
--- /dev/null
+++ b/hostsidetests/retaildemo/src/android/host/retaildemo/BaseTestCase.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.host.retaildemo;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.ddmlib.testrunner.TestResult;
+import com.android.ddmlib.testrunner.TestResult.TestStatus;
+import com.android.ddmlib.testrunner.TestRunResult;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Map;
+
+public class BaseTestCase extends DeviceTestCase implements IBuildReceiver {
+    private static final String RETAIL_DEMO_TEST_PKG = "com.android.cts.retaildemo";
+    private static final String RUNNER = "android.support.test.runner.AndroidJUnitRunner";
+
+    private IBuildInfo mBuildInfo;
+    private CompatibilityBuildHelper mBuildHelper;
+
+    private ArrayList<Integer> mTestUsers;
+
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mBuildInfo = buildInfo;
+        mBuildHelper = new CompatibilityBuildHelper(mBuildInfo);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        assertNotNull(mBuildInfo); // ensure build has been set before test is run.
+        mTestUsers = new ArrayList<>();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        for (int userId : mTestUsers) {
+            getDevice().removeUser(userId);
+        }
+        super.tearDown();
+    }
+
+    protected int createDemoUser() throws DeviceNotAvailableException, IllegalStateException {
+        final String command = "pm create-user --ephemeral --demo "
+                + "TestUser_" + System.currentTimeMillis();
+        CLog.d("Starting command: " + command);
+        final String output = getDevice().executeShellCommand(command);
+        CLog.d("Output for command " + command + ": " + output);
+
+        if (output.startsWith("Success")) {
+            try {
+                int userId = Integer.parseInt(output.substring(output.lastIndexOf(" ")).trim());
+                mTestUsers.add(userId);
+                return userId;
+            } catch (NumberFormatException e) {
+                CLog.e("Failed to parse result: %s", output);
+            }
+        } else {
+            CLog.e("Failed to create demo user: %s", output);
+        }
+        throw new IllegalStateException();
+    }
+
+    protected void installAppAsUser(String appFileName, int userId)
+            throws FileNotFoundException, DeviceNotAvailableException {
+        CLog.d("Installing app " + appFileName + " for user " + userId);
+        File apkFile = new File(mBuildHelper.getTestsDir(), appFileName);
+        final String result = getDevice().installPackageForUser(
+                apkFile, true, true, userId, "-t");
+        assertNull("Failed to install " + appFileName + " for user " + userId + ": " + result,
+                result);
+    }
+
+    protected boolean runDeviceTestsAsUser(String testClassName, String testMethodName, int userId)
+            throws Exception {
+        if (testClassName != null && testClassName.startsWith(".")) {
+            testClassName = RETAIL_DEMO_TEST_PKG + testClassName;
+        }
+
+        RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(
+                RETAIL_DEMO_TEST_PKG, RUNNER, getDevice().getIDevice());
+        if (testClassName != null && testMethodName != null) {
+            testRunner.setMethodName(testClassName, testMethodName);
+        } else if (testClassName != null) {
+            testRunner.setClassName(testClassName);
+        }
+
+        CollectingTestListener listener = new CollectingTestListener();
+        assertTrue(getDevice().runInstrumentationTestsAsUser(testRunner, userId, listener));
+
+        TestRunResult runResult = listener.getCurrentRunResults();
+        printTestResult(runResult);
+        return !runResult.hasFailedTests() && runResult.getNumTestsInState(TestStatus.PASSED) > 0;
+    }
+
+    private void printTestResult(TestRunResult runResult) {
+        for (Map.Entry<TestIdentifier, TestResult> testEntry :
+                runResult.getTestResults().entrySet()) {
+            TestResult testResult = testEntry.getValue();
+            CLog.d("Test " + testEntry.getKey() + ": " + testResult.getStatus());
+            if (testResult.getStatus() != TestStatus.PASSED) {
+                CLog.d(testResult.getStackTrace());
+            }
+        }
+    }
+}
diff --git a/hostsidetests/retaildemo/src/android/host/retaildemo/DemoModeTest.java b/hostsidetests/retaildemo/src/android/host/retaildemo/DemoModeTest.java
new file mode 100644
index 0000000..3fdfd72
--- /dev/null
+++ b/hostsidetests/retaildemo/src/android/host/retaildemo/DemoModeTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.host.retaildemo;
+
+import static junit.framework.Assert.assertTrue;
+
+public class DemoModeTest extends BaseTestCase {
+    private static final String RETAIL_DEMO_TEST_APK = "CtsRetailDemoApp.apk";
+
+    public void testIsDemoUser_inPrimaryUser() throws Exception {
+        assertTrue(runDeviceTestsAsUser(
+                ".DemoUserTest", "testIsDemoUser_failure", getDevice().getPrimaryUserId()));
+    }
+
+    public void testIsDemoUser_inDemoUser() throws Exception {
+        if (!getDevice().isMultiUserSupported()) {
+            return;
+        }
+        final int demoUserId = createDemoUser();
+        getDevice().startUser(demoUserId);
+        installAppAsUser(RETAIL_DEMO_TEST_APK, demoUserId);
+        assertTrue(runDeviceTestsAsUser(
+                ".DemoUserTest", "testIsDemoUser_success", demoUserId));
+    }
+}
diff --git a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
index b74eba7..a8c35d2 100644
--- a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
+++ b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
@@ -27,6 +27,8 @@
 import com.android.tradefed.testtype.IBuildReceiver;
 import com.android.tradefed.testtype.IDeviceTest;
 
+import com.android.compatibility.common.util.CddTest;
+
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileReader;
@@ -123,6 +125,7 @@
      *
      * @throws Exception
      */
+    @CddTest(requirement="9.7")
     public void testGlobalEnforcing() throws Exception {
         CollectingOutputReceiver out = new CollectingOutputReceiver();
         mDevice.executeShellCommand("cat /sys/fs/selinux/enforce", out);
@@ -134,6 +137,7 @@
      *
      * @throws Exception
      */
+    @CddTest(requirement="9.7")
     @RestrictedBuildTest
     public void testAllDomainsEnforcing() throws Exception {
 
@@ -188,6 +192,7 @@
      *
      * @throws Exception
      */
+    @CddTest(requirement="9.7")
     public void testMLSAttributes() throws Exception {
         assertNotInAttribute("mlstrustedsubject", "untrusted_app");
         assertNotInAttribute("mlstrustedobject", "app_data_file");
@@ -198,6 +203,7 @@
      *
      * @throws Exception
      */
+    @CddTest(requirement="9.7")
     public void testValidSeappContexts() throws Exception {
 
         /* obtain seapp_contexts file from running device */
@@ -257,6 +263,7 @@
      *
      * @throws Exception
      */
+    @CddTest(requirement="9.7")
     public void testAospSeappContexts() throws Exception {
 
         /* obtain seapp_contexts file from running device */
@@ -276,6 +283,7 @@
      *
      * @throws Exception
      */
+    @CddTest(requirement="9.7")
     public void testAospFileContexts() throws Exception {
 
         /* retrieve the checkfc executable from jar */
@@ -311,6 +319,7 @@
      *
      * @throws Exception
      */
+    @CddTest(requirement="9.7")
     public void testAospPropertyContexts() throws Exception {
 
         /* obtain property_contexts file from running device */
@@ -330,6 +339,7 @@
      *
      * @throws Exception
      */
+    @CddTest(requirement="9.7")
     public void testAospServiceContexts() throws Exception {
 
         /* obtain service_contexts file from running device */
@@ -348,6 +358,7 @@
      *
      * @throws Exception
      */
+    @CddTest(requirement="9.7")
     public void testValidFileContexts() throws Exception {
 
         /* retrieve the checkfc executable from jar */
@@ -383,6 +394,7 @@
      *
      * @throws Exception
      */
+    @CddTest(requirement="9.7")
     public void testValidPropertyContexts() throws Exception {
 
         /* retrieve the checkfc executable from jar */
@@ -418,6 +430,7 @@
      *
      * @throws Exception
      */
+    @CddTest(requirement="9.7")
     public void testValidServiceContexts() throws Exception {
 
         /* retrieve the checkfc executable from jar */
@@ -453,6 +466,7 @@
      *
      * @throws Exception
      */
+    @CddTest(requirement="9.7")
     public void testNoBooleans() throws Exception {
 
         /* run sepolicy-analyze booleans check on policy file */
@@ -629,67 +643,80 @@
     }
 
     /* Init is always there */
+    @CddTest(requirement="9.7")
     public void testInitDomain() throws DeviceNotAvailableException {
         assertDomainOne("u:r:init:s0", "/init");
     }
 
     /* Ueventd is always there */
+    @CddTest(requirement="9.7")
     public void testUeventdDomain() throws DeviceNotAvailableException {
         assertDomainOne("u:r:ueventd:s0", "/sbin/ueventd");
     }
 
     /* Devices always have healthd */
+    @CddTest(requirement="9.7")
     public void testHealthdDomain() throws DeviceNotAvailableException {
         assertDomainOne("u:r:healthd:s0", "/sbin/healthd");
     }
 
     /* Servicemanager is always there */
+    @CddTest(requirement="9.7")
     public void testServicemanagerDomain() throws DeviceNotAvailableException {
         assertDomainOne("u:r:servicemanager:s0", "/system/bin/servicemanager");
     }
 
     /* Vold is always there */
+    @CddTest(requirement="9.7")
     public void testVoldDomain() throws DeviceNotAvailableException {
         assertDomainOne("u:r:vold:s0", "/system/bin/vold");
     }
 
     /* netd is always there */
+    @CddTest(requirement="9.7")
     public void testNetdDomain() throws DeviceNotAvailableException {
         assertDomainOne("u:r:netd:s0", "/system/bin/netd");
     }
 
     /* Debuggerd is always there */
+    @CddTest(requirement="9.7")
     public void testDebuggerdDomain() throws DeviceNotAvailableException {
         assertDomainN("u:r:debuggerd:s0", "/system/bin/debuggerd", "/system/bin/debuggerd64",
                 "debuggerd:signaller", "debuggerd64:signaller");
     }
 
     /* Surface flinger is always there */
+    @CddTest(requirement="9.7")
     public void testSurfaceflingerDomain() throws DeviceNotAvailableException {
         assertDomainOne("u:r:surfaceflinger:s0", "/system/bin/surfaceflinger");
     }
 
     /* Zygote is always running */
+    @CddTest(requirement="9.7")
     public void testZygoteDomain() throws DeviceNotAvailableException {
         assertDomainN("u:r:zygote:s0", "zygote", "zygote64");
     }
 
     /* Checks drmserver for devices that require it */
+    @CddTest(requirement="9.7")
     public void testDrmServerDomain() throws DeviceNotAvailableException {
         assertDomainZeroOrOne("u:r:drmserver:s0", "/system/bin/drmserver");
     }
 
     /* Installd is always running */
+    @CddTest(requirement="9.7")
     public void testInstalldDomain() throws DeviceNotAvailableException {
         assertDomainOne("u:r:installd:s0", "/system/bin/installd");
     }
 
     /* keystore is always running */
+    @CddTest(requirement="9.7")
     public void testKeystoreDomain() throws DeviceNotAvailableException {
         assertDomainOne("u:r:keystore:s0", "/system/bin/keystore");
     }
 
     /* System server better be running :-P */
+    @CddTest(requirement="9.7")
     public void testSystemServerDomain() throws DeviceNotAvailableException {
         assertDomainOne("u:r:system_server:s0", "system_server");
     }
@@ -698,26 +725,31 @@
      * Some OEMs do not use sdcardd so transient. Other OEMs have multiple sdcards
      * so they run the daemon multiple times.
      */
+    @CddTest(requirement="9.7")
     public void testSdcarddDomain() throws DeviceNotAvailableException {
         assertDomainHasExecutable("u:r:sdcardd:s0", "/system/bin/sdcard");
     }
 
     /* Watchdogd may or may not be there */
+    @CddTest(requirement="9.7")
     public void testWatchdogdDomain() throws DeviceNotAvailableException {
         assertDomainZeroOrOne("u:r:watchdogd:s0", "/sbin/watchdogd");
     }
 
     /* logd may or may not be there */
+    @CddTest(requirement="9.7")
     public void testLogdDomain() throws DeviceNotAvailableException {
         assertDomainZeroOrOne("u:r:logd:s0", "/system/bin/logd");
     }
 
     /* lmkd may or may not be there */
+    @CddTest(requirement="9.7")
     public void testLmkdDomain() throws DeviceNotAvailableException {
         assertDomainZeroOrOne("u:r:lmkd:s0", "/system/bin/lmkd");
     }
 
     /* Wifi may be off so cardinality of 0 or 1 is ok */
+    @CddTest(requirement="9.7")
     public void testWpaDomain() throws DeviceNotAvailableException {
         assertDomainZeroOrOne("u:r:wpa:s0", "/system/bin/wpa_supplicant");
     }
@@ -726,6 +758,7 @@
      * Nothing should be running in this domain, cardinality test is all thats
      * needed
      */
+    @CddTest(requirement="9.7")
     public void testInitShellDomain() throws DeviceNotAvailableException {
         assertDomainEmpty("u:r:init_shell:s0");
     }
@@ -734,6 +767,7 @@
      * Nothing should be running in this domain, cardinality test is all thats
      * needed
      */
+    @CddTest(requirement="9.7")
     public void testRecoveryDomain() throws DeviceNotAvailableException {
         assertDomainEmpty("u:r:recovery:s0");
     }
@@ -742,6 +776,7 @@
      * Nothing should be running in this domain, cardinality test is all thats
      * needed
      */
+    @CddTest(requirement="9.7")
     @RestrictedBuildTest
     public void testSuDomain() throws DeviceNotAvailableException {
         assertDomainEmpty("u:r:su:s0");
@@ -750,6 +785,7 @@
     /*
      * All kthreads should be in kernel context.
      */
+    @CddTest(requirement="9.7")
     public void testKernelDomain() throws DeviceNotAvailableException {
         String domain = "u:r:kernel:s0";
         List<ProcessDetails> procs = ProcessDetails.getProcMap(mDevice).get(domain);
diff --git a/hostsidetests/services/activitymanager/app/src/android/server/app/AbstractLifecycleLogActivity.java b/hostsidetests/services/activitymanager/app/src/android/server/app/AbstractLifecycleLogActivity.java
index bb54bc4..8abb1c5 100644
--- a/hostsidetests/services/activitymanager/app/src/android/server/app/AbstractLifecycleLogActivity.java
+++ b/hostsidetests/services/activitymanager/app/src/android/server/app/AbstractLifecycleLogActivity.java
@@ -57,7 +57,8 @@
         final String line = "config" +
                 " size=" + buildCoordString(config.screenWidthDp, config.screenHeightDp) +
                 " displaySize=" + buildCoordString(point.x, point.y) +
-                " metricsSize=" + buildCoordString(metrics.widthPixels, metrics.heightPixels);
+                " metricsSize=" + buildCoordString(metrics.widthPixels, metrics.heightPixels) +
+                " smallestScreenWidth=" + config.smallestScreenWidthDp;
 
         Log.i(getTag(), line);
     }
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerActivityVisiblityTests.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerActivityVisiblityTests.java
index 2417da7..5aafe8e 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerActivityVisiblityTests.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerActivityVisiblityTests.java
@@ -16,7 +16,9 @@
 
 package android.server.cts;
 
+import com.android.ddmlib.Log.LogLevel;
 import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.log.LogUtil.CLog;
 
 import java.lang.Exception;
 import java.lang.String;
@@ -126,6 +128,11 @@
     }
 
     public void testTranslucentActivityOverDockedStack() throws Exception {
+        if (!supportsMultiWindowMode()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
+            return;
+        }
+
         launchActivityInDockStack(DOCKED_ACTIVITY_NAME);
         mAmWmState.computeState(mDevice, new String[] {DOCKED_ACTIVITY_NAME});
         launchActivityInStack(TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID);
@@ -149,6 +156,11 @@
     }
 
     public void testFinishActivityInNonFocusedStack() throws Exception {
+        if (!supportsMultiWindowMode()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
+            return;
+        }
+
         // Launch two activities in docked stack.
         launchActivityInDockStack(LAUNCHING_ACTIVITY);
         launchActivity(false /* toSide */, false /* randomData */, false /* multipleTaskFlag */,
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerAppConfigurationTests.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerAppConfigurationTests.java
index 5b21ee9..9ef7093 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerAppConfigurationTests.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerAppConfigurationTests.java
@@ -15,6 +15,9 @@
  */
 package android.server.cts;
 
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.log.LogUtil.CLog;
+
 import java.awt.Rectangle;
 import java.util.ArrayList;
 import java.util.List;
@@ -33,6 +36,11 @@
      * docked state.
      */
     public void testConfigurationUpdatesWhenResizedFromFullscreen() throws Exception {
+        if (!supportsMultiWindowMode()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
+            return;
+        }
+
         launchActivityInStack(RESIZEABLE_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID);
         final ReportedSizes fullscreenSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
                 FULLSCREEN_WORKSPACE_STACK_ID);
@@ -49,6 +57,11 @@
      * from docked state to fullscreen (reverse).
      */
     public void testConfigurationUpdatesWhenResizedFromDockedStack() throws Exception {
+        if (!supportsMultiWindowMode()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
+            return;
+        }
+
         launchActivityInStack(RESIZEABLE_ACTIVITY_NAME, DOCKED_STACK_ID);
         final ReportedSizes dockedSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
                 DOCKED_STACK_ID);
@@ -64,15 +77,17 @@
      * Tests whether the Display sizes change when rotating the device.
      */
     public void testConfigurationUpdatesWhenRotatingWhileFullscreen() throws Exception {
+        if (!supportsScreenRotation()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no rotation support");
+            return;
+        }
+
         setDeviceRotation(0);
         launchActivityInStack(RESIZEABLE_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID);
-        final ReportedSizes orientationASizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
+        final ReportedSizes initialSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
                 FULLSCREEN_WORKSPACE_STACK_ID);
 
-        setDeviceRotation(1);
-        final ReportedSizes orientationBSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
-                FULLSCREEN_WORKSPACE_STACK_ID);
-        assertSizesRotate(orientationASizes, orientationBSizes);
+        rotateAndCheckSizes(initialSizes, FULLSCREEN_WORKSPACE_STACK_ID);
     }
 
     /**
@@ -80,15 +95,63 @@
      * is in the docked stack.
      */
     public void testConfigurationUpdatesWhenRotatingWhileDocked() throws Exception {
+        if (!supportsScreenRotation()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no rotation support");
+            return;
+        }
+        if (!supportsMultiWindowMode()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
+            return;
+        }
+
         setDeviceRotation(0);
-        launchActivityInStack(RESIZEABLE_ACTIVITY_NAME, DOCKED_STACK_ID);
-        final ReportedSizes orientationASizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
+        launchActivityInDockStack(LAUNCHING_ACTIVITY);
+        // Launch our own activity to side in case Recents (or other activity to side) doesn't
+        // support rotation.
+        launchActivityToSide(false /* randomData */, false /* multipleTask */, TEST_ACTIVITY_NAME);
+        // Launch target activity in docked stack.
+        launchActivity(false /* toSide */, false /* randomData */, false /* multipleTask */,
+                RESIZEABLE_ACTIVITY_NAME);
+        final ReportedSizes initialSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
                 DOCKED_STACK_ID);
 
-        setDeviceRotation(1);
-        final ReportedSizes orientationBSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
-                DOCKED_STACK_ID);
-        assertSizesRotate(orientationASizes, orientationBSizes);
+        rotateAndCheckSizes(initialSizes, DOCKED_STACK_ID);
+    }
+
+    /**
+     * Same as {@link #testConfigurationUpdatesWhenRotatingWhileDocked()} but when the Activity
+     * is launched to side from docked stack.
+     */
+    public void testConfigurationUpdatesWhenRotatingToSideFromDocked() throws Exception {
+        if (!supportsScreenRotation()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no rotation support");
+            return;
+        }
+        if (!supportsMultiWindowMode()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
+            return;
+        }
+
+        setDeviceRotation(0);
+
+        launchActivityInDockStack(LAUNCHING_ACTIVITY);
+        launchActivityToSide(false /* randomData */, false /* multipleTaskFlag */,
+                RESIZEABLE_ACTIVITY_NAME);
+        final ReportedSizes initialSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
+                FULLSCREEN_WORKSPACE_STACK_ID);
+
+        rotateAndCheckSizes(initialSizes, FULLSCREEN_WORKSPACE_STACK_ID);
+    }
+
+    private void rotateAndCheckSizes(ReportedSizes prevSizes, int stackId) throws Exception {
+        for (int rotation = 3; rotation >= 0; --rotation) {
+            clearLogcat();
+            setDeviceRotation(rotation);
+            final ReportedSizes rotatedSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
+                    stackId);
+            assertSizesRotate(prevSizes, rotatedSizes);
+            prevSizes = rotatedSizes;
+        }
     }
 
     /**
@@ -114,6 +177,11 @@
      * Asserts that initial and final reported sizes in fullscreen stack are the same.
      */
     private void moveActivityFullSplitFull(String activityName) throws Exception {
+        if (!supportsMultiWindowMode()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
+            return;
+        }
+
         // Launch to fullscreen stack and record size.
         launchActivityInStack(activityName, FULLSCREEN_WORKSPACE_STACK_ID);
         final ReportedSizes initialFullscreenSizes = getActivityDisplaySize(activityName,
@@ -163,6 +231,11 @@
      * Asserts that initial and final reported sizes in docked stack are the same.
      */
     private void moveActivitySplitFullSplit(String activityName) throws Exception {
+        if (!supportsMultiWindowMode()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
+            return;
+        }
+
         // Launch to docked stack and record size.
         launchActivityInStack(activityName, DOCKED_STACK_ID);
         final ReportedSizes initialDockedSizes = getActivityDisplaySize(activityName,
@@ -207,6 +280,8 @@
         final boolean afterConfigPortrait = rotationB.widthDp < rotationB.heightDp;
         assertEquals(beforePortrait, beforeConfigPortrait);
         assertEquals(afterPortrait, afterConfigPortrait);
+
+        assertEquals(rotationA.smallestWidthDp, rotationB.smallestWidthDp);
     }
 
     /**
@@ -238,6 +313,7 @@
         assertEquals(firstSize.displayHeight, secondSize.displayHeight);
         assertEquals(firstSize.metricsWidth, secondSize.metricsWidth);
         assertEquals(firstSize.metricsHeight, secondSize.metricsHeight);
+        assertEquals(firstSize.smallestWidthDp, secondSize.smallestWidthDp);
     }
 
     private ReportedSizes getActivityDisplaySize(String activityName, int stackId)
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerConfigChangeTests.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerConfigChangeTests.java
index e5a121d..130e84e 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerConfigChangeTests.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerConfigChangeTests.java
@@ -16,17 +16,30 @@
 
 package android.server.cts;
 
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.log.LogUtil.CLog;
+
 public class ActivityManagerConfigChangeTests extends ActivityManagerTestBase {
 
     private static final String TEST_ACTIVITY_NAME = "TestActivity";
     private static final String NO_RELAUNCH_ACTIVITY_NAME = "NoRelaunchActivity";
 
     public void testRotation90Relaunch() throws Exception{
+        if (!supportsScreenRotation()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no rotation support");
+            return;
+        }
+
         // Should relaunch on every rotation and receive no onConfigurationChanged()
         testRotation(TEST_ACTIVITY_NAME, 1, 1, 0);
     }
 
     public void testRotation90NoRelaunch() throws Exception {
+        if (!supportsScreenRotation()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no rotation support");
+            return;
+        }
+
         // Should receive onConfigurationChanged() on every rotation and no relaunch
         testRotation(NO_RELAUNCH_ACTIVITY_NAME, 1, 0, 1);
     }
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
index 19fc84a..ec0b7b0 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
@@ -16,6 +16,9 @@
 
 package android.server.cts;
 
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.log.LogUtil.CLog;
+
 import java.awt.Rectangle;
 
 public class ActivityManagerDockedStackTests extends ActivityManagerTestBase {
@@ -40,6 +43,11 @@
     }
 
     public void testDockActivity() throws Exception {
+        if (!supportsMultiWindowMode()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
+            return;
+        }
+
         launchActivityInDockStack(TEST_ACTIVITY_NAME);
         mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
         mAmWmState.assertContainsStack("Must contain home stack.", HOME_STACK_ID);
@@ -57,6 +65,11 @@
     }
 
     public void testLaunchToSide() throws Exception {
+        if (!supportsMultiWindowMode()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
+            return;
+        }
+
         launchActivityInDockStack(LAUNCHING_ACTIVITY);
         mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
         launchActivityToSide();
@@ -227,6 +240,11 @@
     }
 
     public void testRotationWhenDocked() throws Exception {
+        if (!supportsMultiWindowMode()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
+            return;
+        }
+
         launchActivityInDockStack(LAUNCHING_ACTIVITY);
         mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
         launchActivityToSide();
@@ -262,6 +280,11 @@
     }
 
     public void testRotationWhenDockedWhileLocked() throws Exception {
+        if (!supportsMultiWindowMode()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
+            return;
+        }
+
         launchActivityInDockStack(LAUNCHING_ACTIVITY);
         mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
         launchActivityToSide();
@@ -295,6 +318,11 @@
     }
 
     public void testResizeDockedStack() throws Exception {
+        if (!supportsMultiWindowMode()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
+            return;
+        }
+
         launchActivityInDockStack(DOCKED_ACTIVITY_NAME);
         mAmWmState.computeState(mDevice, new String[] {DOCKED_ACTIVITY_NAME});
         launchActivityInStack(TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID);
@@ -313,6 +341,10 @@
     }
 
     public void testActivityLifeCycleOnResizeDockedStack() throws Exception {
+        if (!supportsMultiWindowMode()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
+            return;
+        }
         final String[] waitTestActivityName = new String[] {TEST_ACTIVITY_NAME};
         executeShellCommand(getAmStartCmd(TEST_ACTIVITY_NAME));
         mAmWmState.computeState(mDevice, waitTestActivityName);
@@ -370,9 +402,4 @@
             throws Exception {
         launchActivityToSide(randomData, multipleTaskFlag, null);
     }
-
-    private void launchActivityToSide(boolean randomData, boolean multipleTaskFlag,
-            String targetActivity) throws Exception {
-        launchActivity(true /* toSide */, randomData, multipleTaskFlag, targetActivity);
-    }
 }
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerManifestLayoutTests.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerManifestLayoutTests.java
index 2395e55..70b0518 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerManifestLayoutTests.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerManifestLayoutTests.java
@@ -31,6 +31,7 @@
 import static android.server.cts.ActivityAndWindowManagersState.dpToPx;
 import static com.android.ddmlib.Log.LogLevel.INFO;
 
+import com.android.ddmlib.Log.LogLevel;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.log.LogUtil.CLog;
 
@@ -80,6 +81,10 @@
     }
 
     public void testMinimalSizeDocked() throws Exception {
+        if (!supportsMultiWindowMode()) {
+            CLog.logAndDisplay(INFO, "Skipping test: no multi-window support");
+            return;
+        }
         testMinimalSize(DOCKED_STACK_ID);
     }
 
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerTestBase.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerTestBase.java
index f4d84c7..735a303 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerTestBase.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerTestBase.java
@@ -35,6 +35,8 @@
 public abstract class ActivityManagerTestBase extends DeviceTestCase {
     private static final boolean PRETEND_DEVICE_SUPPORTS_PIP = false;
     private static final boolean PRETEND_DEVICE_SUPPORTS_FREEFORM = false;
+    private static final boolean PRETEND_DEVICE_SUPPORTS_DOCKING = false;
+    private static final boolean PRETEND_DEVICE_SUPPORTS_ROTATION = false;
 
     // Constants copied from ActivityManager.StackId. If they are changed there, these must be
     // updated.
@@ -190,6 +192,11 @@
         moveActivityToDockStack(activityName);
     }
 
+    protected void launchActivityToSide(boolean randomData, boolean multipleTaskFlag,
+            String targetActivity) throws Exception {
+        launchActivity(true /* toSide */, randomData, multipleTaskFlag, targetActivity);
+    }
+
     protected void moveActivityToDockStack(String activityName) throws Exception {
         moveActivityToStack(activityName, DOCKED_STACK_ID);
     }
@@ -259,6 +266,16 @@
                 || PRETEND_DEVICE_SUPPORTS_FREEFORM;
     }
 
+    protected boolean supportsMultiWindowMode() throws DeviceNotAvailableException {
+        return !hasDeviceFeature("android.hardware.type.watch")
+                || PRETEND_DEVICE_SUPPORTS_DOCKING;
+    }
+
+    protected boolean supportsScreenRotation() throws DeviceNotAvailableException {
+        return !hasDeviceFeature("android.hardware.type.watch")
+                || PRETEND_DEVICE_SUPPORTS_ROTATION;
+    }
+
     protected boolean hasDeviceFeature(String requiredFeature) throws DeviceNotAvailableException {
         if (mAvailableFeatures == null) {
             // TODO: Move this logic to ITestDevice.
@@ -461,7 +478,7 @@
     private static final Pattern sDestroyPattern = Pattern.compile("(.+): onDestroy");
     private static final Pattern sNewConfigPattern = Pattern.compile(
             "(.+): config size=\\((\\d+),(\\d+)\\) displaySize=\\((\\d+),(\\d+)\\)" +
-            " metricsSize=\\((\\d+),(\\d+)\\)");
+            " metricsSize=\\((\\d+),(\\d+)\\) smallestScreenWidth=(\\d+)");
     private static final Pattern sDisplayStatePattern =
             Pattern.compile("Display Power: state=(.+)");
 
@@ -472,6 +489,15 @@
         int displayHeight;
         int metricsWidth;
         int metricsHeight;
+        int smallestWidthDp;
+
+        @Override
+        public String toString() {
+            return "ReportedSizes: {widthDp=" + widthDp + " heightDp=" + heightDp +
+                    " displayWidth=" + displayWidth + " displayHeight=" + displayHeight +
+                    " metricsWidth=" + metricsWidth + " metricsHeight=" + metricsHeight +
+                    " smallestWidthDp=" + smallestWidthDp + "}";
+        }
     }
 
     protected ReportedSizes getLastReportedSizesForActivity(String activityName)
@@ -488,6 +514,7 @@
                 details.displayHeight = Integer.parseInt(matcher.group(5));
                 details.metricsWidth = Integer.parseInt(matcher.group(6));
                 details.metricsHeight = Integer.parseInt(matcher.group(7));
+                details.smallestWidthDp = Integer.parseInt(matcher.group(8));
                 return details;
             }
         }
diff --git a/hostsidetests/services/windowmanager/src/android/wm/cts/CrossAppDragAndDropTests.java b/hostsidetests/services/windowmanager/src/android/wm/cts/CrossAppDragAndDropTests.java
index 8fc3264..fa1ae69 100644
--- a/hostsidetests/services/windowmanager/src/android/wm/cts/CrossAppDragAndDropTests.java
+++ b/hostsidetests/services/windowmanager/src/android/wm/cts/CrossAppDragAndDropTests.java
@@ -92,15 +92,25 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+
         mDevice = getDevice();
+
+        if (!supportsDragAndDrop()) {
+            return;
+        }
+
         mSourcePackageName = SOURCE_PACKAGE_NAME;
         mTargetPackageName = TARGET_PACKAGE_NAME;
-        cleanupState();
     }
 
     @Override
     protected void tearDown() throws Exception {
         super.tearDown();
+
+        if (!supportsDragAndDrop()) {
+            return;
+        }
+
         mDevice.executeShellCommand(AM_FORCE_STOP + mSourcePackageName);
         mDevice.executeShellCommand(AM_FORCE_STOP + mTargetPackageName);
     }
@@ -288,6 +298,9 @@
 
     private void doTestDragAndDrop(String sourceMode, String targetMode, String expectedDropResult)
             throws Exception {
+        if (!supportsDragAndDrop()) {
+            return;
+        }
 
         launchDockedActivity(mSourcePackageName, SOURCE_ACTIVITY_NAME, sourceMode);
         launchFullscreenActivity(mTargetPackageName, TARGET_ACTIVITY_NAME, targetMode);
@@ -303,8 +316,11 @@
         assertResult(RESULT_KEY_DROP_RESULT, expectedDropResult);
     }
 
+    private void assertResult(String resultKey, String expectedResult) throws Exception {
+        if (!supportsDragAndDrop()) {
+            return;
+        }
 
-    private void assertResult(String resultKey, String expectedResult) {
         if (expectedResult == null) {
             if (mResults.containsKey(resultKey)) {
                 fail("Unexpected " + resultKey + "=" + mResults.get(resultKey));
@@ -315,6 +331,18 @@
         }
     }
 
+    private boolean supportsDragAndDrop() throws Exception {
+        String supportsMultiwindow = mDevice.executeShellCommand("am supports-multiwindow").trim();
+        if ("true".equals(supportsMultiwindow)) {
+            return true;
+        } else if ("false".equals(supportsMultiwindow)) {
+            return false;
+        } else {
+            throw new Exception(
+                    "device does not support \"am supports-multiwindow\" shell command.");
+        }
+    }
+
     public void testCancelSoon() throws Exception {
         doTestDragAndDrop(CANCEL_SOON, REQUEST_NONE, null);
         assertResult(RESULT_KEY_DRAG_STARTED, RESULT_OK);
diff --git a/hostsidetests/shortcuts/hostside/src/android/content/pm/cts/shortcuthost/ShortcutManagerBackupTest.java b/hostsidetests/shortcuts/hostside/src/android/content/pm/cts/shortcuthost/ShortcutManagerBackupTest.java
index 75e6ef5..03e0e5c 100644
--- a/hostsidetests/shortcuts/hostside/src/android/content/pm/cts/shortcuthost/ShortcutManagerBackupTest.java
+++ b/hostsidetests/shortcuts/hostside/src/android/content/pm/cts/shortcuthost/ShortcutManagerBackupTest.java
@@ -40,16 +40,24 @@
     private static final String PUBLISHER3_PKG =
             "android.content.pm.cts.shortcut.backup.publisher3";
 
+    private static final String FEATURE_BACKUP = "android.software.backup";
+
+    private boolean mSupportsBackup;
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
 
-        clearShortcuts(LAUNCHER1_PKG, getPrimaryUserId());
-        clearShortcuts(LAUNCHER2_PKG, getPrimaryUserId());
-        clearShortcuts(LAUNCHER3_PKG, getPrimaryUserId());
-        clearShortcuts(PUBLISHER1_PKG, getPrimaryUserId());
-        clearShortcuts(PUBLISHER2_PKG, getPrimaryUserId());
-        clearShortcuts(PUBLISHER3_PKG, getPrimaryUserId());
+        mSupportsBackup = getDevice().hasFeature(FEATURE_BACKUP);
+
+        if (mSupportsBackup) {
+            clearShortcuts(LAUNCHER1_PKG, getPrimaryUserId());
+            clearShortcuts(LAUNCHER2_PKG, getPrimaryUserId());
+            clearShortcuts(LAUNCHER3_PKG, getPrimaryUserId());
+            clearShortcuts(PUBLISHER1_PKG, getPrimaryUserId());
+            clearShortcuts(PUBLISHER2_PKG, getPrimaryUserId());
+            clearShortcuts(PUBLISHER3_PKG, getPrimaryUserId());
+        }
     }
 
     @Override
@@ -58,13 +66,15 @@
             dumpsys("tearDown");
         }
 
-        getDevice().uninstallPackage(LAUNCHER1_PKG);
-        getDevice().uninstallPackage(LAUNCHER2_PKG);
-        getDevice().uninstallPackage(LAUNCHER3_PKG);
+        if (mSupportsBackup) {
+            getDevice().uninstallPackage(LAUNCHER1_PKG);
+            getDevice().uninstallPackage(LAUNCHER2_PKG);
+            getDevice().uninstallPackage(LAUNCHER3_PKG);
 
-        getDevice().uninstallPackage(PUBLISHER1_PKG);
-        getDevice().uninstallPackage(PUBLISHER2_PKG);
-        getDevice().uninstallPackage(PUBLISHER3_PKG);
+            getDevice().uninstallPackage(PUBLISHER1_PKG);
+            getDevice().uninstallPackage(PUBLISHER2_PKG);
+            getDevice().uninstallPackage(PUBLISHER3_PKG);
+        }
 
         super.tearDown();
     }
@@ -97,6 +107,10 @@
     }
 
     public void testBackupAndRestore() throws Exception {
+        if (!mSupportsBackup) {
+            return;
+        }
+
         installAppAsUser(LAUNCHER1_APK, getPrimaryUserId());
         installAppAsUser(LAUNCHER2_APK, getPrimaryUserId());
         installAppAsUser(LAUNCHER3_APK, getPrimaryUserId());
@@ -183,6 +197,9 @@
     }
 
     public void testBackupAndRestore_withNoUninstall() throws Exception {
+        if (!mSupportsBackup) {
+            return;
+        }
 
         installAppAsUser(PUBLISHER1_APK, getPrimaryUserId());
 
diff --git a/hostsidetests/sustainedperf/src/android/SustainedPerformance/cts/SustainedPerformanceHostTest.java b/hostsidetests/sustainedperf/src/android/SustainedPerformance/cts/SustainedPerformanceHostTest.java
index 683aded..fffeeb8 100644
--- a/hostsidetests/sustainedperf/src/android/SustainedPerformance/cts/SustainedPerformanceHostTest.java
+++ b/hostsidetests/sustainedperf/src/android/SustainedPerformance/cts/SustainedPerformanceHostTest.java
@@ -193,27 +193,7 @@
         appResultsWithMode.clear();
         dhrystoneResultsWithoutMode.clear();
         dhrystoneResultsWithMode.clear();
-        /*
-         * Run the test without the mode.
-         * Start the application and collect stats.
-         * Run two threads of dhrystone and collect stats.
-         */
-        setUpEnvironment();
-        device.executeShellCommand(START_COMMAND);
-        Thread dhrystone = new Thread(new Dhrystone(false, 1));
-        Thread dhrystone1 = new Thread(new Dhrystone(false, 2));
-        dhrystone.start();
-        dhrystone1.start();
-        Thread.sleep(testDuration);
-        device.executeShellCommand(STOP_COMMAND);
-        dhrystone.join();
-        dhrystone1.join();
-        logs = device.executeAdbCommand("logcat", "-v", "brief", "-d", CLASS + ":I", "*:S");
-        analyzeResults(logs, false);
-        double diff = (dhryMax - dhryMin)*100/dhryMax;
-        dhrystoneResultsWithoutMode.add(0, dhryMin);
-        dhrystoneResultsWithoutMode.add(1, dhryMax);
-        dhrystoneResultsWithoutMode.add(2, diff);
+
         /*
          * Run the test with the mode.
          * Start the application and collect stats.
@@ -221,8 +201,8 @@
          */
         setUpEnvironment();
         device.executeShellCommand(START_COMMAND_MODE);
-        dhrystone = new Thread(new Dhrystone(true, 1));
-        dhrystone1 = new Thread(new Dhrystone(true, 2));
+        Thread dhrystone = new Thread(new Dhrystone(true, 1));
+        Thread dhrystone1 = new Thread(new Dhrystone(true, 2));
         dhrystone.start();
         dhrystone1.start();
         Thread.sleep(testDuration);
@@ -231,7 +211,7 @@
         dhrystone1.join();
         logs = device.executeAdbCommand("logcat", "-v", "brief", "-d", CLASS + ":I", "*:S");
         analyzeResults(logs, true);
-        diff = (dhryMax - dhryMin)*100/dhryMax;
+        double diff = (dhryMax - dhryMin)*100/dhryMax;
         dhrystoneResultsWithMode.add(0, dhryMin);
         dhrystoneResultsWithMode.add(1, dhryMax);
         dhrystoneResultsWithMode.add(2, diff);
@@ -239,21 +219,12 @@
         device.executeShellCommand("settings put global airplane_mode_on 0");
         device.executeShellCommand("am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false");
 
-        double resDhry = dhrystoneResultsWithMode.get(2);
-        double resApp = appResultsWithMode.get(2);
-
-        /* Report if performance is below 5% margin for both dhrystone and shader */
-        if ((resDhry > 5) || (resApp > 5)) {
-            Log.w("SustainedPerformanceHostTests",
-                  "Sustainable mode results, Dhrystone: " + resDhry + " App: " + resApp);
-        }
-
         /*
-         * Error if the performance in the mode is not consistent with
+         * Checks if the performance in the mode is consistent with
          * 5% error margin for shader and 10% error margin for dhrystone.
          */
         assertFalse("Results in the mode are not sustainable",
-                    (resDhry > 15) ||
-                    (resApp > 5));
+                (dhrystoneResultsWithMode.get(2) > 10) ||
+                (appResultsWithMode.get(2)) > 5);
     }
 }
diff --git a/hostsidetests/theme/README b/hostsidetests/theme/README
index b2ae8de..76902e4 100644
--- a/hostsidetests/theme/README
+++ b/hostsidetests/theme/README
@@ -39,7 +39,7 @@
      adb devices
 
   2. Image generation occurs on all devices in parallel. Resulting sets of
-     reference images are saved in assets/<api>/<dpi>.zip and will overwrite
+     reference images are saved in assets/<dpi>.zip and will overwrite
      any existing sets. Image generation may be started using:
 
      ./cts/hostsidetests/theme/generate_images.sh
diff --git a/hostsidetests/theme/app/AndroidManifest.xml b/hostsidetests/theme/app/AndroidManifest.xml
index d39f1ae..d9a89c6 100755
--- a/hostsidetests/theme/app/AndroidManifest.xml
+++ b/hostsidetests/theme/app/AndroidManifest.xml
@@ -31,7 +31,7 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
-        <activity android:name=".GenerateImagesActivity"
+        <activity android:name=".GenerateImagesActivity" android:screenOrientation="portrait"
                   android:exported="true" />
     </application>
 
diff --git a/hostsidetests/theme/assets/420dpi.zip b/hostsidetests/theme/assets/420dpi.zip
index 1c380ff..bf70d35 100644
--- a/hostsidetests/theme/assets/420dpi.zip
+++ b/hostsidetests/theme/assets/420dpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/560dpi.zip b/hostsidetests/theme/assets/560dpi.zip
index a171f7c..74e2228 100644
--- a/hostsidetests/theme/assets/560dpi.zip
+++ b/hostsidetests/theme/assets/560dpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/hdpi.zip b/hostsidetests/theme/assets/hdpi.zip
new file mode 100644
index 0000000..6cc2d50
--- /dev/null
+++ b/hostsidetests/theme/assets/hdpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/mdpi.zip b/hostsidetests/theme/assets/mdpi.zip
new file mode 100644
index 0000000..a350ff6
--- /dev/null
+++ b/hostsidetests/theme/assets/mdpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/xhdpi.zip b/hostsidetests/theme/assets/xhdpi.zip
index 96d4ae0..cceab80 100644
--- a/hostsidetests/theme/assets/xhdpi.zip
+++ b/hostsidetests/theme/assets/xhdpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/xxhdpi.zip b/hostsidetests/theme/assets/xxhdpi.zip
index 60529ca..05f2b8d 100644
--- a/hostsidetests/theme/assets/xxhdpi.zip
+++ b/hostsidetests/theme/assets/xxhdpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/24/xxxhdpi.zip b/hostsidetests/theme/assets/xxxhdpi.zip
similarity index 89%
rename from hostsidetests/theme/assets/24/xxxhdpi.zip
rename to hostsidetests/theme/assets/xxxhdpi.zip
index 4049156..f4e0713 100644
--- a/hostsidetests/theme/assets/24/xxxhdpi.zip
+++ b/hostsidetests/theme/assets/xxxhdpi.zip
Binary files differ
diff --git a/hostsidetests/theme/run_theme_capture_device.py b/hostsidetests/theme/run_theme_capture_device.py
index 8d4c72f..a516717 100755
--- a/hostsidetests/theme/run_theme_capture_device.py
+++ b/hostsidetests/theme/run_theme_capture_device.py
@@ -97,7 +97,6 @@
     print "Found device: " + deviceSerial
     device = androidDevice(deviceSerial)
 
-    outPath = outPath + "/%d" % (device.getSdkLevel())
     density = device.getDensity()
     if CTS_THEME_dict.has_key(density):
         resName = CTS_THEME_dict[density]
diff --git a/hostsidetests/theme/src/android/theme/cts/ComparisonTask.java b/hostsidetests/theme/src/android/theme/cts/ComparisonTask.java
index 5f4a741..d9ed8a1 100755
--- a/hostsidetests/theme/src/android/theme/cts/ComparisonTask.java
+++ b/hostsidetests/theme/src/android/theme/cts/ComparisonTask.java
@@ -36,6 +36,9 @@
 
     private static final int IMAGE_THRESHOLD = 2;
 
+    /** Maximum allowable number of consecutive failed pixels. */
+    private static final int MAX_CONSECUTIVE_FAILURES = 1;
+
     private final File mExpected;
     private final File mActual;
 
@@ -95,6 +98,8 @@
         }
 
         for (int i = 0; i < w; i++) {
+            int consecutive = 0;
+
             for (int j = 0; j < h; j++) {
                 final int p1 = reference.getRGB(i, j);
                 final int p2 = generated.getRGB(i, j);
@@ -106,7 +111,13 @@
                 if (Math.abs(db) > threshold ||
                         Math.abs(dg) > threshold ||
                         Math.abs(dr) > threshold) {
-                    return false;
+                    consecutive++;
+
+                    if (consecutive > MAX_CONSECUTIVE_FAILURES) {
+                        return false;
+                    }
+                } else {
+                    consecutive = 0;
                 }
             }
         }
diff --git a/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java b/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java
index e04a10b..eb2cb80 100644
--- a/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java
+++ b/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java
@@ -125,7 +125,7 @@
         mCompletionService = new ExecutorCompletionService<>(mExecutionService);
     }
 
-    private Map<String, File> extractReferenceImages(String zipFile) {
+    private Map<String, File> extractReferenceImages(String zipFile) throws Exception {
         final Map<String, File> references = new HashMap<>();
         final InputStream zipStream = ThemeHostTest.class.getResourceAsStream(zipFile);
         if (zipStream != null) {
@@ -150,7 +150,12 @@
                 fail("Failed to unzip assets: " + zipFile);
             }
         } else {
-            fail("Failed to get resource: " + zipFile);
+            if (checkHardwareTypeSkipTest(mDevice.executeShellCommand(HARDWARE_TYPE_CMD).trim())) {
+                Log.logAndDisplay(LogLevel.WARN, LOG_TAG,
+                        "Could not obtain resources for skipped themes test: " + zipFile);
+            } else {
+                fail("Failed to get resource: " + zipFile);
+            }
         }
 
         return references;
diff --git a/tests/accessibilityservice/AndroidManifest.xml b/tests/accessibilityservice/AndroidManifest.xml
index 3381f48..e13cdee 100644
--- a/tests/accessibilityservice/AndroidManifest.xml
+++ b/tests/accessibilityservice/AndroidManifest.xml
@@ -67,8 +67,7 @@
 
         <activity
             android:label="@string/accessibility_soft_keyboard_modes_activity"
-            android:name=".AccessibilitySoftKeyboardModesTest$SoftKeyboardModesActivity"
-            android:windowSoftInputMode="stateAlwaysVisible" />
+            android:name=".AccessibilitySoftKeyboardModesTest$SoftKeyboardModesActivity" />
 
         <service
             android:name=".InstrumentedAccessibilityService"
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
index d8a1be1..a94345c 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
@@ -24,6 +24,7 @@
 import android.app.Service;
 import android.app.UiAutomation;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.test.suitebuilder.annotation.MediumTest;
 import android.text.TextUtils;
@@ -314,12 +315,18 @@
     @SuppressWarnings("deprecation")
     public void testTypeNotificationStateChangedAccessibilityEvent() throws Throwable {
         // No notification UI on televisions.
-        if((getActivity().getResources().getConfiguration().uiMode
+        if ((getActivity().getResources().getConfiguration().uiMode
                 & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
             Log.i(LOG_TAG, "Skipping: testTypeNotificationStateChangedAccessibilityEvent" +
                     " - No notification UI on televisions.");
             return;
         }
+        PackageManager pm = getInstrumentation().getTargetContext().getPackageManager();
+        if (pm.hasSystemFeature(pm.FEATURE_WATCH)) {
+            Log.i(LOG_TAG, "Skipping: testTypeNotificationStateChangedAccessibilityEvent" +
+                    " - Watches have different notification system.");
+            return;
+        }
 
         String message = getActivity().getString(R.string.notification_message);
 
@@ -346,32 +353,41 @@
         expected.getText().add(message);
         expected.setParcelableData(notification);
 
-        AccessibilityEvent awaitedEvent =
-            getInstrumentation().getUiAutomation().executeAndWaitForEvent(
-                new Runnable() {
-            @Override
-            public void run() {
-                // trigger the event
-                getActivity().runOnUiThread(new Runnable() {
-                    @Override
-                    public void run() {
-                        // trigger the event
-                        NotificationManager notificationManager =
-                            (NotificationManager) getActivity().getSystemService(
-                                    Service.NOTIFICATION_SERVICE);
-                        notificationManager.notify(notificationId, notification);
-                        getActivity().finish();
-                    }
-                });
-            }},
-            new UiAutomation.AccessibilityEventFilter() {
-                // check the received event
+        AccessibilityEvent awaitedEvent;
+        NotificationManager notificationManager =
+                (NotificationManager) getActivity().getSystemService(Service.NOTIFICATION_SERVICE);
+        try {
+            awaitedEvent = getInstrumentation().getUiAutomation().executeAndWaitForEvent(
+                    new Runnable() {
                 @Override
-                public boolean accept(AccessibilityEvent event) {
-                    return equalsAccessiblityEvent(event, expected);
+                public void run() {
+                    // trigger the event
+                    getActivity().runOnUiThread(new Runnable() {
+                        @Override
+                        public void run() {
+                            // trigger the event
+                            notificationManager.notify(notificationId, notification);
+                        }
+                    });
+                }},
+                new UiAutomation.AccessibilityEventFilter() {
+                    // check the received event
+                    @Override
+                    public boolean accept(AccessibilityEvent event) {
+                        return equalsAccessiblityEvent(event, expected);
+                    }
+                },
+                TIMEOUT_ASYNC_PROCESSING);
+        } finally {
+            getActivity().runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    notificationManager.cancel(notificationId);
+                    getActivity().finish();
                 }
-            },
-            TIMEOUT_ASYNC_PROCESSING);
+            });
+        }
+
         assertNotNull("Did not receive expected event: " + expected, awaitedEvent);
     }
 
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java
index 6542778..8dbbeef 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java
@@ -333,39 +333,38 @@
         }
     }
 
+    // This test assumes device's screen contains its center (W/2, H/2) with some surroundings
+    // and should work for rectangular, round and round with chin screens.
     public void testClickWhenMagnified_matchesActualTouch() throws InterruptedException {
         if (!mHasTouchScreen) {
             return;
         }
 
-        final int clickXInsideView = 10;
-        final int clickYInsideView = 20;
-        int clickX = clickXInsideView + mViewBounds.left;
-        int clickY = clickYInsideView + mViewBounds.top;
+        final int clickShiftFromCenterX = 10;
+        final int clickShiftFromCenterY = 20;
+        final Resources res = getInstrumentation().getTargetContext().getResources();
+        final DisplayMetrics metrics = res.getDisplayMetrics();
+        final int centerX = metrics.widthPixels / 2;
+        final int centerY = metrics.heightPixels / 2;
         final float TOUCH_TOLERANCE = 2.0f;
 
         StubMagnificationAccessibilityService magnificationService =
                 StubMagnificationAccessibilityService.enableSelf(this);
         android.accessibilityservice.AccessibilityService.MagnificationController
                 magnificationController = magnificationService.getMagnificationController();
-        final Resources res = getInstrumentation().getTargetContext().getResources();
-        final DisplayMetrics metrics = res.getDisplayMetrics();
         try {
-            // Magnify screen by 2x from upper left corner
+            // Magnify screen by 2x with a magnification center in the center of the screen
             final AtomicBoolean setScale = new AtomicBoolean();
             final float magnificationFactor = 2.0f;
-            // Center to have (0,0) in the upper-left corner
-            final float centerX = metrics.widthPixels / (2.0f * magnificationFactor) - 1.0f;
-            final float centerY = metrics.heightPixels / (2.0f * magnificationFactor) - 1.0f;
             magnificationService.runOnServiceSync(() -> {
                         setScale.set(magnificationController.setScale(magnificationFactor, false));
-                        // Make sure the upper right corner is on the screen
                         magnificationController.setCenter(centerX, centerY, false);
                     });
             assertTrue("Failed to set scale", setScale.get());
 
-            GestureDescription click = createClick((int) (clickX * magnificationFactor),
-                    (int) (clickY * magnificationFactor));
+            final int clickMagnifiedX = (int) (centerX + magnificationFactor * clickShiftFromCenterX);
+            final int clickMagnifiedY = (int) (centerY + magnificationFactor * clickShiftFromCenterY);
+            GestureDescription click = createClick(clickMagnifiedX, clickMagnifiedY);
             mService.runOnServiceSync(() -> mService.doDispatchGesture(click, mCallback, null));
             mCallback.assertGestureCompletes(GESTURE_COMPLETION_TIMEOUT);
             waitForMotionEvents(3);
@@ -382,14 +381,18 @@
         MotionEvent clickDown = mMotionEvents.get(0);
         MotionEvent clickUp = mMotionEvents.get(1);
 
+        final int centerXInsideView = centerX - mViewBounds.left;
+        final int centerYInsideView = centerY - mViewBounds.top;
+        final int expectedClickXInsideView = centerXInsideView + clickShiftFromCenterX;
+        final int expectedClickYInsideView = centerYInsideView + clickShiftFromCenterY;
         assertEquals(MotionEvent.ACTION_DOWN, clickDown.getActionMasked());
-        assertEquals((float) clickXInsideView, clickDown.getX(), TOUCH_TOLERANCE);
-        assertEquals((float) clickYInsideView, clickDown.getY(), TOUCH_TOLERANCE);
+        assertEquals((float) expectedClickXInsideView, clickDown.getX(), TOUCH_TOLERANCE);
+        assertEquals((float) expectedClickYInsideView, clickDown.getY(), TOUCH_TOLERANCE);
         assertEquals(clickDown.getDownTime(), clickDown.getEventTime());
 
         assertEquals(MotionEvent.ACTION_UP, clickUp.getActionMasked());
-        assertEquals((float) clickXInsideView, clickUp.getX(), TOUCH_TOLERANCE);
-        assertEquals((float) clickYInsideView, clickUp.getY(), TOUCH_TOLERANCE);
+        assertEquals((float) expectedClickXInsideView, clickUp.getX(), TOUCH_TOLERANCE);
+        assertEquals((float) expectedClickYInsideView, clickUp.getY(), TOUCH_TOLERANCE);
     }
 
 
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGlobalActionsTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGlobalActionsTest.java
index bbda333..486e4fa 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGlobalActionsTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGlobalActionsTest.java
@@ -58,20 +58,23 @@
 
     @MediumTest
     public void testPerformGlobalActionRecents() throws Exception {
-        // Check whether the action succeeded.
-        assertTrue(getInstrumentation().getUiAutomation().performGlobalAction(
-                AccessibilityService.GLOBAL_ACTION_RECENTS));
+        // Perform the action.
+        boolean actionWasPerformed =
+                getInstrumentation().getUiAutomation().performGlobalAction(
+                        AccessibilityService.GLOBAL_ACTION_RECENTS);
 
         // Sleep a bit so the UI is settled.
         waitForIdle();
 
-        // This is a necessary since the back action does not
-        // dismiss recents until they stop animating. Sigh...
-        SystemClock.sleep(5000);
+        if (actionWasPerformed) {
+            // This is a necessary since the back action does not
+            // dismiss recents until they stop animating. Sigh...
+            SystemClock.sleep(5000);
 
-        // Clean up.
-        getInstrumentation().getUiAutomation().performGlobalAction(
-                AccessibilityService.GLOBAL_ACTION_BACK);
+            // Clean up.
+            getInstrumentation().getUiAutomation().performGlobalAction(
+                    AccessibilityService.GLOBAL_ACTION_BACK);
+        }
 
         // Sleep a bit so the UI is settled.
         waitForIdle();
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilitySoftKeyboardModesTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilitySoftKeyboardModesTest.java
index 263c402..58d8355 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilitySoftKeyboardModesTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilitySoftKeyboardModesTest.java
@@ -16,25 +16,25 @@
 
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.accessibilityservice.AccessibilityService.SoftKeyboardController;
+import android.app.Activity;
 import android.app.UiAutomation;
-import android.content.ContentResolver;
-import android.content.Context;
 import android.os.Bundle;
-import android.os.ParcelFileDescriptor;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.ResultReceiver;
 import android.os.SystemClock;
-import android.provider.Settings;
 import android.test.ActivityInstrumentationTestCase2;
+import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
 
 import android.accessibilityservice.cts.R;
+import android.view.accessibility.AccessibilityWindowInfo;
+import android.view.inputmethod.InputMethodManager;
 
-import java.io.BufferedReader;
-import java.io.FileInputStream;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.nio.charset.StandardCharsets;
 import java.util.List;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
 /**
@@ -56,6 +56,12 @@
      */
     private static final long TIMEOUT_ACCESSIBILITY_STATE_IDLE = 500;
 
+    /**
+     * The timeout since {@link InputMethodManager#showSoftInput(View, int, ResultReceiver)}
+     * is called to {@link ResultReceiver#onReceiveResult(int, Bundle)} is called back.
+     */
+    private static final int TIMEOUT_SHOW_SOFTINPUT_RESULT = 2000;
+
     private static final int SHOW_MODE_AUTO = 0;
     private static final int SHOW_MODE_HIDDEN = 1;
 
@@ -91,7 +97,11 @@
 
     @Override
     public void tearDown() throws Exception {
+        mKeyboardController.setShowMode(SHOW_MODE_AUTO);
         mService.runOnServiceSync(() -> mService.disableSelf());
+        Activity activity = getActivity();
+        activity.getSystemService(InputMethodManager.class)
+                .hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
     }
 
     public void testApiReturnValues_shouldChangeValueOnRequestAndSendCallback() throws Exception {
@@ -109,7 +119,7 @@
                 };
         mKeyboardController.addOnShowModeChangedListener(listener);
 
-        // The soft keyboard should be in its' default mode.
+        // The soft keyboard should be in its default mode.
         assertEquals(SHOW_MODE_AUTO, mKeyboardController.getShowMode());
 
         // Set the show mode to SHOW_MODE_HIDDEN.
@@ -130,56 +140,24 @@
         assertTrue(mKeyboardController.removeOnShowModeChangedListener(listener));
     }
 
-    public void testHideSoftKeyboard_shouldHideAndShowKeyboardOnRequest() throws Exception {
-        // The soft keyboard should be in its' default mode.
+    public void testHideSoftKeyboard_shouldHideKeyboardOnRequest() throws Exception {
+        // The soft keyboard should be in its default mode.
         assertEquals(SHOW_MODE_AUTO, mKeyboardController.getShowMode());
 
-        // Note: This Activity always has a visible keyboard (due to windowSoftInputMode being set
-        // to stateAlwaysVisible).
-        waitForIdle();
-        int numWindowsWithIme = mUiAutomation.getWindows().size();
+        if (!tryShowSoftInput()) {
+            // If the current (default) IME declined to show its window, then there is nothing we
+            // can test here.
+            // TODO: Create a mock IME so that we can test only the framework behavior.
+            return;
+        }
 
+        waitForImePresentToBe(true);
         // Request the keyboard be hidden.
         assertTrue(mKeyboardController.setShowMode(SHOW_MODE_HIDDEN));
-        waitForWindowStateChanged();
-        waitForIdle();
 
-        // Make sure the keyboard is hidden.
-        assertEquals(numWindowsWithIme - 1, mUiAutomation.getWindows().size());
+        waitForImePresentToBe(false);
 
-        // Request the default keyboard mode.
         assertTrue(mKeyboardController.setShowMode(SHOW_MODE_AUTO));
-        waitForWindowStateChanged();
-        waitForIdle();
-
-        // Make sure the keyboard is visible.
-        assertEquals(numWindowsWithIme, mUiAutomation.getWindows().size());
-    }
-
-    public void testHideSoftKeyboard_shouldHideKeyboardUntilServiceIsDisabled() throws Exception {
-        // The soft keyboard should be in its' default mode.
-        assertEquals(SHOW_MODE_AUTO, mKeyboardController.getShowMode());
-
-        // Note: This Activity always has a visible keyboard (due to windowSoftInputMode being set
-        // to stateAlwaysVisible).
-        waitForIdle();
-        int numWindowsWithIme = mUiAutomation.getWindows().size();
-
-        // Set the show mode to SHOW_MODE_HIDDEN.
-        assertTrue(mKeyboardController.setShowMode(SHOW_MODE_HIDDEN));
-        waitForWindowStateChanged();
-        waitForIdle();
-
-        // Make sure the keyboard is hidden.
-        assertEquals(numWindowsWithIme - 1, mUiAutomation.getWindows().size());
-
-        // Make sure we can see the soft keyboard once all Accessibility Services are disabled.
-        mService.disableSelf();
-        waitForWindowStateChanged();
-        waitForIdle();
-
-        // See how many windows are present.
-        assertEquals(numWindowsWithIme, mUiAutomation.getWindows().size());
     }
 
     private void waitForCallbackValueWithLock(int expectedValue) throws Exception {
@@ -202,7 +180,7 @@
                 + "> does not match expected value < " + expectedValue + ">");
     }
 
-    private void waitForWindowStateChanged() throws Exception {
+    private void waitForWindowChanges() {
         try {
             mUiAutomation.executeAndWaitForEvent(new Runnable() {
                 @Override
@@ -223,8 +201,64 @@
         }
     }
 
-    private void waitForIdle() throws TimeoutException {
-        mUiAutomation.waitForIdle(TIMEOUT_ACCESSIBILITY_STATE_IDLE, TIMEOUT_ASYNC_PROCESSING);
+    private boolean isImeWindowPresent() {
+        List<AccessibilityWindowInfo> windows = mUiAutomation.getWindows();
+        for (int i = 0; i < windows.size(); i++) {
+            if (windows.get(i).getType() == AccessibilityWindowInfo.TYPE_INPUT_METHOD) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private void waitForImePresentToBe(boolean imeShown) {
+        long timeOutTime = System.currentTimeMillis() + TIMEOUT_ASYNC_PROCESSING;
+        while (isImeWindowPresent() != imeShown) {
+            assertTrue(System.currentTimeMillis() < timeOutTime);
+            waitForWindowChanges();
+        }
+    }
+
+    /**
+     * Tries to call {@link InputMethodManager#hideSoftInputFromWindow(IBinder, int)} to see if
+     * software keyboard is shown as a result or not.
+     * @return {@code true} if the current input method reported that it is currently shown
+     * @throws Exception when the result is unknown, including the system did not return the result
+     *                   within {@link #TIMEOUT_SHOW_SOFTINPUT_RESULT}
+     */
+    private boolean tryShowSoftInput() throws Exception {
+        final BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(1);
+
+        getInstrumentation().runOnMainSync(() -> {
+            Activity activity = getActivity();
+            ResultReceiver resultReceiver =
+                    new ResultReceiver(new Handler(activity.getMainLooper())) {
+                            @Override
+                            protected void onReceiveResult(int resultCode, Bundle resultData) {
+                                queue.add(resultCode);
+                            }
+                    };
+            View editText = activity.findViewById(R.id.edit_text);
+            activity.getSystemService(InputMethodManager.class)
+                    .showSoftInput(editText, InputMethodManager.SHOW_FORCED, resultReceiver);
+        });
+
+        Integer result;
+        try {
+            result = queue.poll(TIMEOUT_SHOW_SOFTINPUT_RESULT, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+            throw new Exception("Failed to get the result of showSoftInput().", e);
+        }
+        if (result == null) {
+            throw new Exception("Failed to get the result of showSoftInput() within timeout.");
+        }
+        switch (result) {
+            case InputMethodManager.RESULT_SHOWN:
+            case InputMethodManager.RESULT_UNCHANGED_SHOWN:
+                return true;
+            default:
+                return false;
+        }
     }
 
     /**
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java
index 3924c75..9fa2deb 100755
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java
@@ -27,9 +27,11 @@
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.app.UiAutomation;
 import android.content.pm.PackageManager;
+import android.content.res.Resources;
 import android.graphics.Rect;
 import android.test.suitebuilder.annotation.MediumTest;
 import android.view.Gravity;
+import android.view.View;
 import android.view.Window;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
@@ -53,7 +55,8 @@
  */
 public class AccessibilityWindowQueryTest
         extends AccessibilityActivityTestCase<AccessibilityWindowQueryActivity> {
-
+    private static String CONTENT_VIEW_RES_NAME =
+            "android.accessibilityservice.cts:id/added_content";
     private static final long TIMEOUT_WINDOW_STATE_IDLE = 500;
 
     public AccessibilityWindowQueryTest() {
@@ -61,10 +64,27 @@
     }
 
     @MediumTest
-    public void testFindByText() throws Exception {
+    public void testFindByText() throws Throwable {
+        // First, make the root view of the activity an accessibility node. This allows us to
+        // later exclude views that are part of the activity's DecorView.
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                getActivity().findViewById(R.id.added_content)
+                    .setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+            }
+        });
+
+        // Start looking from the added content instead of from the root accessibility node so
+        // that nodes that we don't expect (i.e. window control buttons) are not included in the
+        // list of accessibility nodes returned by findAccessibilityNodeInfosByText.
+        final AccessibilityNodeInfo addedContent = getInstrumentation().getUiAutomation()
+                .getRootInActiveWindow().findAccessibilityNodeInfosByViewId(CONTENT_VIEW_RES_NAME)
+                        .get(0);
+
         // find a view by text
-        List<AccessibilityNodeInfo> buttons = getInstrumentation().getUiAutomation()
-                .getRootInActiveWindow().findAccessibilityNodeInfosByText("b");
+        List<AccessibilityNodeInfo> buttons = addedContent.findAccessibilityNodeInfosByText("b");
+
         assertEquals(9, buttons.size());
     }
 
@@ -555,6 +575,26 @@
             // Android TV doesn't support the divider window
             return;
         }
+
+        // Get com.android.internal.R.bool.config_supportsSplitScreenMultiWindow
+        try {
+            if (!getInstrumentation().getContext().getResources().getBoolean(
+                    Resources.getSystem().getIdentifier(
+                            "config_supportsSplitScreenMultiWindow", "bool", "android"))) {
+                // Check if split screen multi window is not supported.
+                return;
+            }
+        } catch (Resources.NotFoundException e) {
+            // Do nothing, assume split screen multi window is supported.
+        }
+
+        // Get com.android.internal.R.bool.config_supportsMultiWindow
+        if (!getInstrumentation().getContext().getResources().getBoolean(
+                Resources.getSystem().getIdentifier("config_supportsMultiWindow", "bool",
+                        "android"))) {
+            // Check if multiWindow is supported.
+            return;
+        }
         setAccessInteractiveWindowsFlag();
         final UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
         assertFalse(isDividerWindowPresent(uiAutomation));
@@ -817,7 +857,6 @@
             classNameAndTextList.add("android.widget.ButtonB8");
             classNameAndTextList.add("android.widget.ButtonB9");
 
-            String contentViewIdResName = "android.accessibilityservice.cts:id/added_content";
             boolean verifyContent = false;
 
             Queue<AccessibilityNodeInfo> fringe = new LinkedList<AccessibilityNodeInfo>();
@@ -828,7 +867,7 @@
                 AccessibilityNodeInfo current = fringe.poll();
 
                 if (!verifyContent
-                        && contentViewIdResName.equals(current.getViewIdResourceName())) {
+                        && CONTENT_VIEW_RES_NAME.equals(current.getViewIdResourceName())) {
                     verifyContent = true;
                 }
 
diff --git a/tests/app/app/AndroidManifest.xml b/tests/app/app/AndroidManifest.xml
index 10a6792..b5460a6 100644
--- a/tests/app/app/AndroidManifest.xml
+++ b/tests/app/app/AndroidManifest.xml
@@ -329,6 +329,21 @@
 
         <activity android:name="android.app.stubs.KeyboardShortcutsActivity" />
 
+        <service
+            android:name="android.app.stubs.LiveWallpaper"
+            android:icon="@drawable/robot"
+            android:label="@string/wallpaper_title"
+            android:permission="android.permission.BIND_WALLPAPER">
+            <intent-filter>
+                <action android:name="android.service.wallpaper.WallpaperService">
+                </action>
+            </intent-filter>
+            <meta-data
+                android:name="android.service.wallpaper"
+                android:resource="@xml/wallpaper">
+            </meta-data>
+        </service>
+
     </application>
 
 </manifest>
diff --git a/tests/app/app/res/values/strings.xml b/tests/app/app/res/values/strings.xml
index 5e9e6d7..839e398 100644
--- a/tests/app/app/res/values/strings.xml
+++ b/tests/app/app/res/values/strings.xml
@@ -177,4 +177,10 @@
 I think so, so how about double this string, like copy and paste! </string>
     <string name="rectangle200">"M 0,0 l 200,0 l 0, 200 l -200, 0 z"</string>
     <string name="hello">Hello World</string>
+
+    <string name="wallpaper_description">Description</string>
+    <string name="wallpaper_collection">Collection</string>
+    <string name="wallpaper_title">Title</string>
+    <string name="wallpaper_context">Context</string>
+    <string name="wallpaper_context_uri">http://android.com</string>
 </resources>
diff --git a/tests/app/app/res/xml/wallpaper.xml b/tests/app/app/res/xml/wallpaper.xml
new file mode 100644
index 0000000..f70b20f
--- /dev/null
+++ b/tests/app/app/res/xml/wallpaper.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<wallpaper
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:thumbnail="@drawable/icon_red"
+    android:author="@string/wallpaper_collection"
+    android:description="@string/wallpaper_description"
+    android:showMetadataInPreview="true"
+    android:contextDescription="@string/wallpaper_context"
+    android:contextUri="@string/wallpaper_context_uri"
+/>
\ No newline at end of file
diff --git a/tests/app/app/src/android/app/stubs/LiveWallpaper.java b/tests/app/app/src/android/app/stubs/LiveWallpaper.java
new file mode 100644
index 0000000..5b8a82e
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/LiveWallpaper.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.stubs;
+
+import android.service.wallpaper.WallpaperService;
+
+public class LiveWallpaper extends WallpaperService {
+
+    @Override
+    public Engine onCreateEngine() {
+        return new Engine();
+    }
+}
diff --git a/tests/app/src/android/app/cts/ActivityManagerMemoryClassTest.java b/tests/app/src/android/app/cts/ActivityManagerMemoryClassTest.java
index 2b84be6..fefa546 100644
--- a/tests/app/src/android/app/cts/ActivityManagerMemoryClassTest.java
+++ b/tests/app/src/android/app/cts/ActivityManagerMemoryClassTest.java
@@ -27,6 +27,8 @@
 import android.view.Display;
 import android.view.WindowManager;
 
+import com.android.compatibility.common.util.CddTest;
+
 import java.util.HashMap;
 import java.util.Map;
 
@@ -148,6 +150,7 @@
         }
     }
 
+    @CddTest(requirement="3.7")
     public void testGetMemoryClass() throws Exception {
         int memoryClass = getMemoryClass();
         int screenDensity = getScreenDensity();
diff --git a/tests/app/src/android/app/cts/ApplicationTest.java b/tests/app/src/android/app/cts/ApplicationTest.java
index aaed064..664d3ee 100644
--- a/tests/app/src/android/app/cts/ApplicationTest.java
+++ b/tests/app/src/android/app/cts/ApplicationTest.java
@@ -57,7 +57,13 @@
             }
         });
         instrumentation.waitForIdleSync();
-        assertTrue(mockApp.isOnConfigurationChangedCalled);
+        final boolean isInMultiwindowMode = activity.isInMultiWindowMode();
+        if (activity.isInMultiWindowMode()) {
+            assertFalse("Orientation change should not trigger global configuration change when "
+                    + " in multi-window mode.", mockApp.isOnConfigurationChangedCalled);
+        } else {
+            assertTrue(mockApp.isOnConfigurationChangedCalled);
+        }
     }
 
 }
diff --git a/tests/app/src/android/app/cts/DownloadManagerTest.java b/tests/app/src/android/app/cts/DownloadManagerTest.java
index 50eb96b..1bec983 100644
--- a/tests/app/src/android/app/cts/DownloadManagerTest.java
+++ b/tests/app/src/android/app/cts/DownloadManagerTest.java
@@ -34,6 +34,8 @@
 import android.util.Log;
 import android.webkit.cts.CtsTestServer;
 
+import com.android.compatibility.common.util.CddTest;
+
 import java.io.File;
 import java.util.Arrays;
 import java.util.HashSet;
@@ -181,6 +183,7 @@
         }
     }
 
+    @CddTest(requirement="7.6.1")
     public void testMinimumDownload() throws Exception {
         final DownloadCompleteReceiver receiver = new DownloadCompleteReceiver();
         try {
diff --git a/tests/app/src/android/app/cts/SearchManagerTest.java b/tests/app/src/android/app/cts/SearchManagerTest.java
index 13a8073..bf7e2f9 100644
--- a/tests/app/src/android/app/cts/SearchManagerTest.java
+++ b/tests/app/src/android/app/cts/SearchManagerTest.java
@@ -16,11 +16,13 @@
 
 package android.app.cts;
 
+import android.app.SearchManager;
+import android.app.UiModeManager;
 import android.app.stubs.CTSActivityTestCaseBase;
 import android.app.stubs.SearchManagerStubActivity;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.PackageManager;
+import android.content.res.Configuration;
 
 public class SearchManagerTest extends CTSActivityTestCaseBase {
 
@@ -33,7 +35,7 @@
     }
 
     public void testStopSearch() throws InterruptedException {
-        if (isTelevision()) {
+        if (!hasGlobalSearchActivity()) {
             return;
         }
         SearchManagerStubActivity.setCTSResult(this);
@@ -42,7 +44,7 @@
     }
 
     public void testSetOnDismissListener() throws InterruptedException {
-        if (isTelevision()) {
+        if (!hasGlobalSearchActivity()) {
             return;
         }
         SearchManagerStubActivity.setCTSResult(this);
@@ -51,7 +53,7 @@
     }
 
     public void testSetOnCancelListener() throws InterruptedException {
-        if (isTelevision()) {
+        if (!hasGlobalSearchActivity()) {
             return;
         }
         SearchManagerStubActivity.setCTSResult(this);
@@ -59,10 +61,22 @@
         waitForResult();
     }
 
-    private boolean isTelevision() {
+    private boolean hasGlobalSearchActivity() {
         Context context = getInstrumentation().getTargetContext();
-        PackageManager pm = context.getPackageManager();
-        return pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION)
-                || pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+        UiModeManager uiModeManager = context.getSystemService(UiModeManager.class);
+        if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {
+            return false;
+        }
+        SearchManager searchManager =
+                (SearchManager) context.getSystemService(Context.SEARCH_SERVICE);
+        if (searchManager == null) {
+            return false;
+        }
+        try {
+            return searchManager.getGlobalSearchActivity() != null;
+        } catch (NullPointerException e) {
+            // Means there is no internal search service.
+            return false;
+        }
     }
 }
diff --git a/tests/app/src/android/app/cts/SystemFeaturesTest.java b/tests/app/src/android/app/cts/SystemFeaturesTest.java
index 979d18a..f03c549 100644
--- a/tests/app/src/android/app/cts/SystemFeaturesTest.java
+++ b/tests/app/src/android/app/cts/SystemFeaturesTest.java
@@ -474,6 +474,10 @@
         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE) &&
                 !mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEVISION) &&
                 !mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)) {
+            // USB accessory mode is only a requirement for devices with USB ports supporting
+            // peripheral mode. As there is no public API to distinguish a device with only host
+            // mode support from having both peripheral and host support, the test may have
+            // false negatives.
             assertAvailable(PackageManager.FEATURE_USB_ACCESSORY);
         }
     }
diff --git a/tests/app/src/android/app/cts/WallpaperInfoTest.java b/tests/app/src/android/app/cts/WallpaperInfoTest.java
new file mode 100644
index 0000000..1b30902
--- /dev/null
+++ b/tests/app/src/android/app/cts/WallpaperInfoTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.cts;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import android.app.WallpaperInfo;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.service.wallpaper.WallpaperService;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class WallpaperInfoTest {
+
+    @Test
+    public void test() throws Exception {
+        Context context = InstrumentationRegistry.getTargetContext();
+        Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
+        intent.setPackage("android.app.stubs");
+        PackageManager pm = context.getPackageManager();
+        List<ResolveInfo> result = pm.queryIntentServices(intent, PackageManager.GET_META_DATA);
+        assertEquals(1, result.size());
+        ResolveInfo info = result.get(0);
+        WallpaperInfo wallpaperInfo = new WallpaperInfo(context, info);
+        assertEquals("Title", wallpaperInfo.loadLabel(pm));
+        assertEquals("Description", wallpaperInfo.loadDescription(pm));
+        assertEquals("Collection", wallpaperInfo.loadAuthor(pm));
+        assertEquals("Context", wallpaperInfo.loadContextDescription(pm));
+        assertEquals("http://android.com", wallpaperInfo.loadContextUri(pm).toString());
+        assertEquals(true, wallpaperInfo.getShowMetadataInPreview());
+        assertNotNull(wallpaperInfo.loadIcon(pm));
+        assertNotNull(wallpaperInfo.loadThumbnail(pm));
+    }
+}
diff --git a/tests/backup/src/android/backup/cts/BackupQuotaTest.java b/tests/backup/src/android/backup/cts/BackupQuotaTest.java
index 01c368a..0493993 100644
--- a/tests/backup/src/android/backup/cts/BackupQuotaTest.java
+++ b/tests/backup/src/android/backup/cts/BackupQuotaTest.java
@@ -17,6 +17,7 @@
 package android.backup.cts;
 
 import android.app.Instrumentation;
+import android.content.pm.PackageManager;
 import android.os.ParcelFileDescriptor;
 import android.test.InstrumentationTestCase;
 import android.util.Log;
@@ -46,12 +47,19 @@
 
     private static final int SMALL_LOGCAT_DELAY = 1000;
 
+    private boolean isBackupSupported;
     private boolean wasBackupEnabled;
     private String oldTransport;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+        PackageManager packageManager = getInstrumentation().getContext().getPackageManager();
+        isBackupSupported = packageManager != null
+                && packageManager.hasSystemFeature(PackageManager.FEATURE_BACKUP);
+        if (!isBackupSupported) {
+            return;
+        }
         // Enable backup and select local backup transport
         assertTrue("LocalTransport should be available.", hasBackupTransport(LOCAL_TRANSPORT));
         wasBackupEnabled = enableBackup(true);
@@ -61,12 +69,17 @@
     @Override
     protected void tearDown() throws Exception {
         // Return old transport
-        setBackupTransport(oldTransport);
-        enableBackup(wasBackupEnabled);
+        if (isBackupSupported) {
+            setBackupTransport(oldTransport);
+            enableBackup(wasBackupEnabled);
+        }
         super.tearDown();
     }
 
     public void testQuotaExceeded() throws Exception {
+        if (!isBackupSupported) {
+            return;
+        }
         exec("logcat --clear");
         exec("setprop log.tag." + APP_LOG_TAG +" VERBOSE");
         // Launch test app and create file exceeding limit for local transport
diff --git a/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java b/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
index ebda3dd..ae5c2ea 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
@@ -2622,7 +2622,7 @@
             }
         }
 
-        mSession.stopRepeating();
+        stopPreview();
     }
 
     /**
diff --git a/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java b/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java
index 6ab55b0..8f32d52 100644
--- a/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java
@@ -40,6 +40,7 @@
 import android.media.Image;
 import android.media.ImageReader;
 import android.os.ConditionVariable;
+import android.os.SystemClock;
 import android.util.Log;
 import android.util.Pair;
 import android.util.Size;
@@ -54,8 +55,10 @@
 import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Collections;
+import java.util.Date;
 import java.util.List;
 import java.util.TimeZone;
+import java.text.SimpleDateFormat;
 
 import static android.hardware.camera2.cts.helpers.AssertHelpers.*;
 
@@ -243,10 +246,19 @@
                         previewListener));
                 captureListeners.add(previewListener);
 
+                Date beforeCaptureDate = new Date();
                 Pair<List<Image>, CaptureResult> resultPair = captureSingleRawShot(activeArraySize,
                         captureReaders, /*waitForAe*/false, captureListeners);
+                Date afterCaptureDate = new Date();
                 CameraCharacteristics characteristics = mStaticInfo.getCharacteristics();
 
+                if (VERBOSE) {
+                    Log.v(TAG, "Sensor timestamp (ms): " +
+                            resultPair.second.get(CaptureResult.SENSOR_TIMESTAMP) / 1000000);
+                    Log.v(TAG, "SystemClock.elapsedRealtimeNanos (ms): " +
+                            SystemClock.elapsedRealtimeNanos() / 1000000);
+                    Log.v(TAG, "SystemClock.uptimeMillis(): " + SystemClock.uptimeMillis());
+                }
                 // Test simple writeImage, no header checks
                 DngCreator dngCreator = new DngCreator(characteristics, resultPair.second);
                 Location l = new Location("test");
@@ -264,7 +276,7 @@
 
                 String filePath = DEBUG_FILE_NAME_BASE + "/camera_thumb_" + deviceId + "_" +
                         DEBUG_DNG_FILE;
-                // Write out captured DNG file for the first camera device if setprop is enabled
+                // Write out captured DNG file for the first camera device
                 fileStream = new FileOutputStream(filePath);
                 fileStream.write(outputStream.toByteArray());
                 fileStream.flush();
@@ -292,6 +304,30 @@
                         exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                                 ExifInterface.ORIENTATION_UNDEFINED));
 
+                // Verify the date/time
+                final SimpleDateFormat dngDateTimeStampFormat =
+                        new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
+                dngDateTimeStampFormat.setLenient(false);
+
+                String dateTimeString =
+                        exifInterface.getAttribute(ExifInterface.TAG_DATETIME);
+                assertTrue(dateTimeString != null);
+
+                Date dateTime = dngDateTimeStampFormat.parse(dateTimeString);
+                long captureTimeMs = dateTime.getTime();
+
+                Log.i(TAG, "DNG DateTime tag: " + dateTimeString);
+                Log.i(TAG, "Before capture time: " + beforeCaptureDate.getTime());
+                Log.i(TAG, "Capture time: " + captureTimeMs);
+                Log.i(TAG, "After capture time: " + afterCaptureDate.getTime());
+
+                // Offset beforeCaptureTime by 1 second to account for rounding down of
+                // DNG tag
+                long beforeCaptureTimeMs = beforeCaptureDate.getTime() - 1000;
+                long afterCaptureTimeMs = afterCaptureDate.getTime();
+                assertTrue(captureTimeMs >= beforeCaptureTimeMs);
+                assertTrue(captureTimeMs <= afterCaptureTimeMs);
+
                 if (!VERBOSE) {
                     // Delete the captured DNG file.
                     File dngFile = new File(filePath);
diff --git a/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java b/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
index d101036..d466662 100644
--- a/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
@@ -1282,14 +1282,15 @@
                                          duration, expectedDurationMs));
             }
 
-            // TODO: Don't skip this for video snapshot
-            if (!mStaticInfo.isHardwareLevelLegacy()) {
-                assertTrue(String.format(
-                        "Camera %s: Video duration doesn't match: recorded %fms, expected %fms.",
-                        mCamera.getId(), duration, expectedDurationMs),
-                        Math.abs(duration - expectedDurationMs) <
-                        DURATION_MARGIN * expectedDurationMs);
-            }
+            // Do rest of validation only for better-than-LEGACY devices
+            if (mStaticInfo.isHardwareLevelLegacy()) return;
+
+            // TODO: Don't skip this one for video snapshot on LEGACY
+            assertTrue(String.format(
+                    "Camera %s: Video duration doesn't match: recorded %fms, expected %fms.",
+                    mCamera.getId(), duration, expectedDurationMs),
+                    Math.abs(duration - expectedDurationMs) <
+                    DURATION_MARGIN * expectedDurationMs);
 
             // Check for framedrop
             long lastSampleUs = 0;
diff --git a/tests/camera/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java b/tests/camera/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java
index aec5685..2a49857 100644
--- a/tests/camera/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java
@@ -461,7 +461,13 @@
 
         for (int i = 0; i < fpsRanges.length; i += 1) {
             fpsRange = fpsRanges[i];
-            maxPreviewSz = getMaxPreviewSizeForFpsRange(fpsRange);
+            if (mStaticInfo.isHardwareLevelLegacy()) {
+                // Legacy devices don't report minimum frame duration for preview sizes. The FPS
+                // range should be valid for any supported preview size.
+                maxPreviewSz = mOrderedPreviewSizes.get(0);
+            } else {
+                maxPreviewSz = getMaxPreviewSizeForFpsRange(fpsRange);
+            }
 
             requestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, fpsRange);
             // Turn off auto antibanding to avoid exposure time and frame duration interference
diff --git a/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java b/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
index 8d141c4..a95f4f3 100644
--- a/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
+++ b/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
@@ -222,9 +222,11 @@
      * Does _not_ wait for the device to go idle
      */
     protected void stopPreview() throws Exception {
-        if (VERBOSE) Log.v(TAG, "Stopping preview");
         // Stop repeat, wait for captures to complete, and disconnect from surfaces
-        mSession.close();
+        if (mSession != null) {
+            if (VERBOSE) Log.v(TAG, "Stopping preview");
+            mSession.close();
+        }
     }
 
     /**
@@ -232,11 +234,13 @@
      * resulting in an idle device.
      */
     protected void stopPreviewAndDrain() throws Exception {
-        if (VERBOSE) Log.v(TAG, "Stopping preview and waiting for idle");
         // Stop repeat, wait for captures to complete, and disconnect from surfaces
-        mSession.close();
-        mSessionListener.getStateWaiter().waitForState(BlockingSessionCallback.SESSION_CLOSED,
-                /*timeoutMs*/WAIT_FOR_RESULT_TIMEOUT_MS);
+        if (mSession != null) {
+            if (VERBOSE) Log.v(TAG, "Stopping preview and waiting for idle");
+            mSession.close();
+            mSessionListener.getStateWaiter().waitForState(BlockingSessionCallback.SESSION_CLOSED,
+                    /*timeoutMs*/WAIT_FOR_RESULT_TIMEOUT_MS);
+        }
     }
 
     /**
diff --git a/tests/core/runner/src/com/android/cts/runner/CtsTestRunListener.java b/tests/core/runner/src/com/android/cts/runner/CtsTestRunListener.java
index 57dc7c6..1f9a939 100644
--- a/tests/core/runner/src/com/android/cts/runner/CtsTestRunListener.java
+++ b/tests/core/runner/src/com/android/cts/runner/CtsTestRunListener.java
@@ -16,6 +16,7 @@
 
 package com.android.cts.runner;
 
+import android.app.ActivityManager;
 import android.app.Instrumentation;
 import android.app.KeyguardManager;
 import android.content.Context;
@@ -219,6 +220,13 @@
             mProperties.setProperty("android.cts.device.multicast",
                     Boolean.toString(pm.hasSystemFeature(PackageManager.FEATURE_WIFI)));
             mDefaultIs24Hour = getDateFormatIs24Hour();
+
+            // There are tests in libcore that should be disabled for low ram devices. They can't
+            // access ActivityManager to call isLowRamDevice, but can read system properties.
+            ActivityManager activityManager =
+                    (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+            mProperties.setProperty("android.cts.device.lowram",
+                    Boolean.toString(activityManager.isLowRamDevice()));
         }
 
         void reset() {
diff --git a/tests/deviceadmin/uninstalltest/src/android/devicepolicy/cts/uiautomatertest/DeviceAdminUninstallTest.java b/tests/deviceadmin/uninstalltest/src/android/devicepolicy/cts/uiautomatertest/DeviceAdminUninstallTest.java
index a8e7cc1..d4f04de 100644
--- a/tests/deviceadmin/uninstalltest/src/android/devicepolicy/cts/uiautomatertest/DeviceAdminUninstallTest.java
+++ b/tests/deviceadmin/uninstalltest/src/android/devicepolicy/cts/uiautomatertest/DeviceAdminUninstallTest.java
@@ -15,6 +15,9 @@
  */
 package android.devicepolicy.cts.uiautomatertest;
 
+import static android.content.Intent.CATEGORY_DEFAULT;
+import static android.provider.Settings.ACTION_SETTINGS;
+
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.app.admin.DevicePolicyManager;
@@ -26,6 +29,19 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.net.Uri;
 import android.provider.Settings;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.BySelector;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.UiObjectNotFoundException;
+import android.support.test.uiautomator.UiScrollable;
+import android.support.test.uiautomator.UiSelector;
+import android.support.test.uiautomator.Until;
+import android.util.Log;
 import android.widget.ScrollView;
 
 import org.junit.After;
@@ -38,18 +54,6 @@
 import java.io.StringWriter;
 import java.util.List;
 import java.util.regex.Pattern;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
-import android.support.test.filters.LargeTest;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.BySelector;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject;
-import android.support.test.uiautomator.UiObjectNotFoundException;
-import android.support.test.uiautomator.UiScrollable;
-import android.support.test.uiautomator.UiSelector;
-import android.support.test.uiautomator.Until;
-import android.util.Log;
 
 @RunWith(AndroidJUnit4.class)
 @LargeTest
@@ -60,14 +64,6 @@
     private static final String URI_PACKAGE_PREFIX = "package:";
     private static final String UNINSTALL_BUTTON_TEXT_REGEX = "(?i)uninstall";
 
-    private static final UiSelector DEACTIVATE_AND_UNINSTALL_BUTTON_SELECTOR = new UiSelector()
-            .resourceId("com.android.settings:id/action_button");
-    // Changing the below two selectors to match the button based on text due to b/29960172
-    private static final UiSelector UNINSTALL_BUTTON_SELECTOR = new UiSelector()
-            .clickable(true).textMatches(UNINSTALL_BUTTON_TEXT_REGEX);
-    private static final BySelector UNINSTALL_BUTTON_BYSELECTOR = By
-            .clickable(true).text(Pattern.compile(UNINSTALL_BUTTON_TEXT_REGEX));
-
     private static final UiSelector OK_BUTTON_SELECTOR = new UiSelector()
             .resourceId("android:id/button1");
     private static final UiSelector SCROLL_VIEW_SELECTOR =
@@ -83,7 +79,10 @@
     private DevicePolicyManager mDpm;
     private PackageManager mPm;
     private Activity mActivity;
+    private UiSelector mDeactivateAndUninstallButtonSelector;
+    private BySelector mUninstallButtonSelector;
     private boolean mHasFeature;
+    private boolean mIsWatch;
 
     @Before
     public void setUp() throws Exception {
@@ -97,6 +96,17 @@
         mInstrumentation = InstrumentationRegistry.getInstrumentation();
         mUiDevice = UiDevice.getInstance(mInstrumentation);
         mDpm = mContext.getSystemService(DevicePolicyManager.class);
+        mIsWatch = mPm.hasSystemFeature(PackageManager.FEATURE_WATCH);
+        if (mIsWatch) {
+            mUninstallButtonSelector = By.clickable(true).hasDescendant(
+                    By.text(Pattern.compile(UNINSTALL_BUTTON_TEXT_REGEX)));
+        } else {
+            mUninstallButtonSelector = By.clickable(true).text(
+                    Pattern.compile(UNINSTALL_BUTTON_TEXT_REGEX));
+        }
+        mDeactivateAndUninstallButtonSelector = new UiSelector().resourceId(
+                getDefaultSettingsPackageName() + ":id/action_button");
+
         startTestActivity();
     }
 
@@ -158,15 +168,21 @@
     private void automateUninstallThroughUi() {
         String errorMessage = "No exception in UI Automation";
 
-        UiObject uninstallButton = mUiDevice.findObject(UNINSTALL_BUTTON_SELECTOR);
         UiScrollable scrollable = new UiScrollable(SCROLL_VIEW_SELECTOR);
-        UiObject deactivateButton = mUiDevice.findObject(DEACTIVATE_AND_UNINSTALL_BUTTON_SELECTOR);
+        UiObject deactivateButton = mUiDevice.findObject(mDeactivateAndUninstallButtonSelector);
         UiObject okButton = mUiDevice.findObject(OK_BUTTON_SELECTOR);
 
-        mUiDevice.wait(Until.hasObject(UNINSTALL_BUTTON_BYSELECTOR), WAIT_FOR_ACTIVITY_TIMEOUT);
         try {
-            uninstallButton.clickAndWaitForNewWindow();
-            scrollable.scrollIntoView(DEACTIVATE_AND_UNINSTALL_BUTTON_SELECTOR);
+            UiObject2 uninstallButton = mUiDevice.wait(
+                    Until.findObject(mUninstallButtonSelector), WAIT_FOR_ACTIVITY_TIMEOUT);
+            uninstallButton.clickAndWait(Until.newWindow(), WAIT_FOR_ACTIVITY_TIMEOUT);
+
+            /** Watch specific: Extra confirm button click */
+            if (mIsWatch) {
+                okButton.clickAndWaitForNewWindow();
+            }
+
+            scrollable.scrollIntoView(mDeactivateAndUninstallButtonSelector);
             deactivateButton.clickAndWaitForNewWindow();
             waitTillNoActiveAdmin();
             okButton.clickAndWaitForNewWindow();
@@ -185,6 +201,12 @@
         return errorWriter.toString();
     }
 
+    private String getDefaultSettingsPackageName() {
+        Intent intent = new Intent(ACTION_SETTINGS).addCategory(CATEGORY_DEFAULT);
+        String packageName = intent.resolveActivity(mPm).getPackageName();
+        return packageName;
+    }
+
     @Test
     public void uninstallPackageWithActiveAdmin() {
         if (!mHasFeature) {
diff --git a/tests/filesystem/src/android/filesystem/cts/FileUtil.java b/tests/filesystem/src/android/filesystem/cts/FileUtil.java
index fc8eee0..8149105 100755
--- a/tests/filesystem/src/android/filesystem/cts/FileUtil.java
+++ b/tests/filesystem/src/android/filesystem/cts/FileUtil.java
@@ -41,6 +41,8 @@
     private static final String TAG = "FileUtil";
     private static final Random mRandom = new Random(0);
     private static long mFileId = 0;
+
+    public static final int BUFFER_SIZE = 10 * 1024 * 1024;
     /**
      * create array with different data per each call
      *
@@ -140,7 +142,6 @@
      */
     public static File createNewFilledFile(Context context, String dirName, long length)
             throws IOException {
-        final int BUFFER_SIZE = 10 * 1024 * 1024;
         File file = createNewFile(context, dirName);
         FileOutputStream out = new FileOutputStream(file);
         byte[] data = generateRandomData(BUFFER_SIZE);
diff --git a/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java b/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java
index f30c7a3..7b97f8f 100644
--- a/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java
+++ b/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java
@@ -17,7 +17,8 @@
 package android.filesystem.cts;
 
 import android.cts.util.CtsAndroidTestCase;
-
+import android.os.Environment;
+import com.android.compatibility.common.util.CddTest;
 import com.android.compatibility.common.util.DeviceReportLog;
 
 public class RandomRWTest extends CtsAndroidTestCase {
@@ -32,6 +33,7 @@
         super.tearDown();
     }
 
+    @CddTest(requirement="8.2")
     public void testRandomRead() throws Exception {
         final int READ_BUFFER_SIZE = 4 * 1024;
         final long fileSize = FileUtil.getFileSizeExceedingMemory(getContext(), READ_BUFFER_SIZE);
@@ -46,13 +48,20 @@
     }
 
     // It is taking too long in some device, and thus cannot run multiple times
+    @CddTest(requirement="8.2")
     public void testRandomUpdate() throws Exception {
         final int WRITE_BUFFER_SIZE = 4 * 1024;
-        final long fileSize = 256 * 1024 * 1024;
+        final long usableSpace = Environment.getDataDirectory().getUsableSpace();
+        long fileSize = 256 * 1024 * 1024;
+        while (usableSpace < fileSize) {
+            fileSize = fileSize / 2;
+        }
         String streamName = "test_random_update";
         DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
-        FileUtil.doRandomWriteTest(getContext(), DIR_RANDOM_WR, report, fileSize,
+        if (fileSize > FileUtil.BUFFER_SIZE) {
+            FileUtil.doRandomWriteTest(getContext(), DIR_RANDOM_WR, report, fileSize,
                 WRITE_BUFFER_SIZE);
+        }
         report.submit(getInstrumentation());
     }
 }
diff --git a/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java b/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java
index c19d03c..2db2f24 100644
--- a/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java
+++ b/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java
@@ -25,6 +25,8 @@
 import com.android.compatibility.common.util.ResultUnit;
 import com.android.compatibility.common.util.Stat;
 
+import com.android.compatibility.common.util.CddTest;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
@@ -44,6 +46,7 @@
         super.tearDown();
     }
 
+    @CddTest(requirement="8.2")
     public void testSingleSequentialWrite() throws Exception {
         final long fileSize = FileUtil.getFileSizeExceedingMemory(getContext(), BUFFER_SIZE);
         if (fileSize == 0) { // not enough space, give up
@@ -85,6 +88,7 @@
                 NUMBER_REPETITION, REPORT_LOG_NAME, streamName);
     }
 
+    @CddTest(requirement="8.2")
     public void testSingleSequentialRead() throws Exception {
         final long fileSize = FileUtil.getFileSizeExceedingMemory(getContext(), BUFFER_SIZE);
         if (fileSize == 0) { // not enough space, give up
diff --git a/tests/signature/src/android/signature/cts/JDiffClassDescription.java b/tests/signature/src/android/signature/cts/JDiffClassDescription.java
index 2e13650..92f56bd 100644
--- a/tests/signature/src/android/signature/cts/JDiffClassDescription.java
+++ b/tests/signature/src/android/signature/cts/JDiffClassDescription.java
@@ -1213,7 +1213,9 @@
     private static String scrubJdiffParamType(String paramType) {
         // <? extends java.lang.Object and <?> are the same, so
         // canonicalize them to one form.
-        return paramType.replace("<? extends java.lang.Object>", "<?>");
+        return paramType
+            .replace("? extends java.lang.Object", "?")
+            .replace("? super java.lang.Object", "? super ?");
     }
 
     /**
diff --git a/tests/tests/content/src/android/content/cts/IntentTest.java b/tests/tests/content/src/android/content/cts/IntentTest.java
index 65da548..dbbbe15 100644
--- a/tests/tests/content/src/android/content/cts/IntentTest.java
+++ b/tests/tests/content/src/android/content/cts/IntentTest.java
@@ -38,6 +38,8 @@
 import android.util.AttributeSet;
 import android.util.Xml;
 
+import com.android.content.cts.DummyParcelable;
+
 import java.io.IOException;
 import java.io.Serializable;
 import java.net.URISyntaxException;
@@ -1750,6 +1752,49 @@
         assertEquals("foo/bar", Intent.normalizeMimeType("   foo/bar    "));
     }
 
+    public void testRemoveUnsafeExtras() {
+        final Intent intent = new Intent();
+        final DummyParcelable dummyParcelable = new DummyParcelable();
+        intent.removeUnsafeExtras();
+        assertNull(intent.getExtras());
+
+        // Check that removeUnsafeExtras keeps the same bundle if no changes are made.
+        Bundle origExtras = new Bundle();
+        origExtras.putString("foo", "bar");
+        intent.replaceExtras(origExtras);
+        intent.removeUnsafeExtras();
+        Bundle newExtras = intent.getExtras();
+        assertEquals(1, newExtras.size());
+        assertEquals("bar", newExtras.get("foo"));
+
+        // Check that removeUnsafeExtras will strip non-framework parcelables without modifying
+        // the original extras bundle.
+        origExtras.putParcelable("baddy", dummyParcelable);
+        intent.replaceExtras(origExtras);
+        intent.removeUnsafeExtras();
+        newExtras = intent.getExtras();
+        assertEquals(1, newExtras.size());
+        assertEquals("bar", newExtras.get("foo"));
+        assertEquals(2, origExtras.size());
+        assertEquals("bar", origExtras.get("foo"));
+        assertSame(dummyParcelable, origExtras.get("baddy"));
+
+        // Check that nested bad values will be stripped.
+        Bundle origSubExtras = new Bundle();
+        origSubExtras.putParcelable("baddy", dummyParcelable);
+        origExtras.putBundle("baddy", origSubExtras);
+        intent.replaceExtras(origExtras);
+        intent.removeUnsafeExtras();
+        newExtras = intent.getExtras();
+        assertEquals(2, newExtras.size());
+        assertEquals("bar", newExtras.get("foo"));
+        Bundle newSubExtras = newExtras.getBundle("baddy");
+        assertNotSame(origSubExtras, newSubExtras);
+        assertEquals(0, newSubExtras.size());
+        assertEquals(1, origSubExtras.size());
+        assertSame(dummyParcelable, origSubExtras.get("baddy"));
+    }
+
     private static class TestSerializable implements Serializable {
         static final long serialVersionUID = 1l;
         public String Name;
diff --git a/tests/tests/content/src/com/android/content/cts/DummyParcelable.java b/tests/tests/content/src/com/android/content/cts/DummyParcelable.java
new file mode 100644
index 0000000..5eb8418
--- /dev/null
+++ b/tests/tests/content/src/com/android/content/cts/DummyParcelable.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.content.cts;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class DummyParcelable implements Parcelable {
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+    }
+
+    public static final Parcelable.Creator<DummyParcelable> CREATOR
+            = new Parcelable.Creator<DummyParcelable>() {
+        public DummyParcelable createFromParcel(Parcel in) {
+            return new DummyParcelable();
+        }
+
+        public DummyParcelable[] newArray(int size) {
+            return new DummyParcelable[size];
+        }
+    };
+}
diff --git a/tests/tests/graphics/Android.mk b/tests/tests/graphics/Android.mk
index 7e26e07..d4d0d33 100644
--- a/tests/tests/graphics/Android.mk
+++ b/tests/tests/graphics/Android.mk
@@ -32,8 +32,6 @@
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
 
-LOCAL_SDK_VERSION := current
-
 include $(BUILD_CTS_PACKAGE)
 
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/graphics/res/drawable-nodpi/bitmap_shader_am_density_golden_160.png b/tests/tests/graphics/res/drawable-nodpi/bitmap_shader_am_density_golden_160.png
new file mode 100644
index 0000000..2e77270
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/bitmap_shader_am_density_golden_160.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/bitmap_shader_am_density_golden_320.png b/tests/tests/graphics/res/drawable-nodpi/bitmap_shader_am_density_golden_320.png
new file mode 100644
index 0000000..5a5c3d2
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/bitmap_shader_am_density_golden_320.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/bitmap_shader_am_density_golden_80.png b/tests/tests/graphics/res/drawable-nodpi/bitmap_shader_am_density_golden_80.png
new file mode 100644
index 0000000..611b27b
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/bitmap_shader_am_density_golden_80.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/bitmap_shader_density_golden_160.png b/tests/tests/graphics/res/drawable-nodpi/bitmap_shader_density_golden_160.png
new file mode 100644
index 0000000..2e77270
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/bitmap_shader_density_golden_160.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/bitmap_shader_density_golden_320.png b/tests/tests/graphics/res/drawable-nodpi/bitmap_shader_density_golden_320.png
new file mode 100644
index 0000000..e8beaa5
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/bitmap_shader_density_golden_320.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/bitmap_shader_density_golden_80.png b/tests/tests/graphics/res/drawable-nodpi/bitmap_shader_density_golden_80.png
new file mode 100644
index 0000000..b869ed7
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/bitmap_shader_density_golden_80.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable/bitmap_shader_am_density.xml b/tests/tests/graphics/res/drawable/bitmap_shader_am_density.xml
new file mode 100644
index 0000000..dfecfbb
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/bitmap_shader_am_density.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2016 The Android Open Source Project
+    
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+    
+          http://www.apache.org/licenses/LICENSE-2.0
+    
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+        android:src="@drawable/bitmap_shader_density_internal"
+        android:tileModeX="repeat"
+        android:tileModeY="clamp"
+        android:autoMirrored="true" />
diff --git a/tests/tests/graphics/res/drawable/bitmap_shader_am_density_internal.png b/tests/tests/graphics/res/drawable/bitmap_shader_am_density_internal.png
new file mode 100644
index 0000000..b6d4d89
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/bitmap_shader_am_density_internal.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable/bitmap_shader_density.xml b/tests/tests/graphics/res/drawable/bitmap_shader_density.xml
new file mode 100644
index 0000000..435b06a
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/bitmap_shader_density.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2016 The Android Open Source Project
+    
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+    
+          http://www.apache.org/licenses/LICENSE-2.0
+    
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+        android:src="@drawable/bitmap_shader_density_internal"
+        android:tileModeX="repeat"
+        android:tileModeY="clamp" />
diff --git a/tests/tests/graphics/res/drawable/bitmap_shader_density_internal.png b/tests/tests/graphics/res/drawable/bitmap_shader_density_internal.png
new file mode 100644
index 0000000..b6d4d89
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/bitmap_shader_density_internal.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable/custom_animation_scale_list_drawable.xml b/tests/tests/graphics/res/drawable/custom_animation_scale_list_drawable.xml
new file mode 100644
index 0000000..1e9fbff
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/custom_animation_scale_list_drawable.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<com.android.internal.graphics.drawable.AnimationScaleListDrawable
+        xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/vector_icon_create" />
+    <item android:drawable="@drawable/animation_vector_drawable_grouping_1" />
+</com.android.internal.graphics.drawable.AnimationScaleListDrawable>
diff --git a/tests/tests/graphics/res/drawable/layerdrawable_theme.xml b/tests/tests/graphics/res/drawable/layerdrawable_theme.xml
index 2a678ff..fac42b2 100644
--- a/tests/tests/graphics/res/drawable/layerdrawable_theme.xml
+++ b/tests/tests/graphics/res/drawable/layerdrawable_theme.xml
@@ -25,5 +25,6 @@
             android:dither="?attr/themeBoolean"
             android:src="?attr/themeNinePatch" />
     </item>
+    <item android:drawable="?attr/themeDrawable" />
 
-</layer-list>
\ No newline at end of file
+</layer-list>
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/BitmapDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/BitmapDrawableTest.java
index 755da01..f9592dc 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/BitmapDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/BitmapDrawableTest.java
@@ -41,6 +41,7 @@
 import android.graphics.drawable.Drawable.ConstantState;
 import android.test.InstrumentationTestCase;
 import android.util.AttributeSet;
+import android.util.LayoutDirection;
 import android.util.Xml;
 import android.view.Gravity;
 
@@ -506,29 +507,25 @@
     };
 
     private static final int[] DENSITY_IMAGES = new int[] {
-            R.drawable.bitmap_density
-    };
-
-    private static final int[][] DENSITY_GOLDEN_IMAGES = new int[][] {
-            {
-                    R.drawable.bitmap_density_golden_160,
-                    R.drawable.bitmap_density_golden_80,
-                    R.drawable.bitmap_density_golden_320,
-            }
+            R.drawable.bitmap_density,
+            R.drawable.bitmap_shader_density,
+            R.drawable.bitmap_shader_am_density,
     };
 
     public void testPreloadDensity() throws XmlPullParserException, IOException {
         final Resources res = mContext.getResources();
         final int densityDpi = res.getConfiguration().densityDpi;
         try {
-            testPreloadDensityInner(res, DENSITY_IMAGES[0], DENSITY_VALUES, DENSITY_GOLDEN_IMAGES[0]);
+            for (int i = 0; i < DENSITY_IMAGES.length; i++) {
+                testPreloadDensityInner(res, DENSITY_IMAGES[i], DENSITY_VALUES);
+            }
         } finally {
             DrawableTestUtils.setResourcesDensity(res, densityDpi);
         }
     }
 
-    private void testPreloadDensityInner(Resources res, int sourceResId, int[] densities,
-            int[] goldenResIds) throws XmlPullParserException, IOException {
+    private void testPreloadDensityInner(Resources res, int sourceResId, int[] densities)
+            throws XmlPullParserException, IOException {
         final Rect tempPadding = new Rect();
 
         // Capture initial state at preload density.
@@ -544,7 +541,7 @@
         final int origHeight = preloadedDrawable.getIntrinsicHeight();
         assertFalse(preloadedDrawable.getPadding(tempPadding));
 
-        compareOrSave(preloadedDrawable, preloadDensityDpi, sourceResId, goldenResIds[0]);
+        compareOrSave(preloadedDrawable, preloadDensityDpi, sourceResId);
 
         for (int i = 1; i < densities.length; i++) {
             final int scaledDensityDpi = densities[i];
@@ -553,6 +550,7 @@
 
             final BitmapDrawable scaledDrawable =
                     (BitmapDrawable) preloadedConstantState.newDrawable(res);
+            scaledDrawable.setLayoutDirection(LayoutDirection.RTL);
 
             // Sizes are rounded.
             assertEquals(Math.round(origWidth * scale), scaledDrawable.getIntrinsicWidth());
@@ -561,7 +559,7 @@
             // Bitmaps have no padding.
             assertFalse(scaledDrawable.getPadding(tempPadding));
 
-            compareOrSave(scaledDrawable, scaledDensityDpi, sourceResId, goldenResIds[i]);
+            compareOrSave(scaledDrawable, scaledDensityDpi, sourceResId);
 
             // Ensure theme density is applied correctly. Unlike most
             // drawables, we don't have any loss of accuracy because density
@@ -576,7 +574,7 @@
         }
     }
 
-    private void compareOrSave(Drawable dr, int densityDpi, int sourceResId, int goldenResId) {
+    private void compareOrSave(Drawable dr, int densityDpi, int sourceResId) {
         final int width = dr.getIntrinsicWidth();
         final int height = dr.getIntrinsicHeight();
         final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
@@ -589,6 +587,7 @@
         if (DBG_DUMP_PNG) {
             saveGoldenImage(bitmap, sourceResId, densityDpi);
         } else {
+            final int goldenResId = getGoldenImageResId(sourceResId, densityDpi);
             final Bitmap golden = BitmapFactory.decodeResource(
                     mContext.getResources(), goldenResId);
             DrawableTestUtils.compareImages(densityDpi + " dpi", golden, bitmap,
@@ -596,28 +595,32 @@
         }
     }
 
+    private int getGoldenImageResId(int sourceResId, int densityDpi) {
+        final String name = getGoldenImageName(sourceResId, densityDpi);
+        return mContext.getResources().getIdentifier(name, "drawable", mContext.getPackageName());
+    }
+
+    private String getGoldenImageName(int sourceResId, int densityDpi) {
+        return mContext.getResources().getResourceEntryName(sourceResId) + "_golden_" + densityDpi;
+    }
+
     private void saveGoldenImage(Bitmap bitmap, int sourceResId, int densityDpi) {
         // Save the image to the disk.
         FileOutputStream out = null;
 
         try {
-            final String outputFolder = "/sdcard/temp/";
-            final File folder = new File(outputFolder);
-            if (!folder.exists()) {
-                folder.mkdir();
+            final File outputFolder = new File("/sdcard/temp/");
+            if (!outputFolder.exists()) {
+                outputFolder.mkdir();
             }
 
-            final String sourceFilename = new File(
-                    mContext.getResources().getString(sourceResId)).getName();
-            final String sourceTitle = sourceFilename.substring(0, sourceFilename.lastIndexOf("."));
-            final String outputTitle = sourceTitle + "_golden_" + densityDpi;
-            final String outputFilename = outputFolder + outputTitle + ".png";
-            final File outputFile = new File(outputFilename);
-            if (!outputFile.exists()) {
-                outputFile.createNewFile();
+            final String goldenFilename = getGoldenImageName(sourceResId, densityDpi) + ".png";
+            final File goldenFile = new File(outputFolder, goldenFilename);
+            if (!goldenFile.exists()) {
+                goldenFile.createNewFile();
             }
 
-            out = new FileOutputStream(outputFile, false);
+            out = new FileOutputStream(goldenFile, false);
             bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
         } catch (Exception e) {
             e.printStackTrace();
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/CustomAnimationScaleListDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/CustomAnimationScaleListDrawableTest.java
new file mode 100644
index 0000000..3445641
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/CustomAnimationScaleListDrawableTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.drawable.cts;
+
+import android.animation.ValueAnimator;
+import android.graphics.cts.R;
+import android.graphics.drawable.Animatable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.DrawableContainer;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+
+/**
+ * This test is used to verify that the CustomAnimationScaleListDrawable's current drawable depends
+ * on animation duration scale. When the scale is 0, it is a static drawable, otherwise, it is an
+ * animatable drawable.
+ */
+public class CustomAnimationScaleListDrawableTest extends AndroidTestCase {
+    @MediumTest
+    public void testNonZeroDurationScale() {
+        float originalScale = ValueAnimator.getDurationScale();
+        ValueAnimator.setDurationScale(2.0f);
+        Drawable dr = getContext().getDrawable(R.drawable.custom_animation_scale_list_drawable);
+        assertTrue(dr instanceof DrawableContainer);
+
+        assertTrue(dr.getCurrent() instanceof Animatable);
+        ValueAnimator.setDurationScale(originalScale);
+    }
+
+    @MediumTest
+    public void testZeroDurationScale() {
+        float originalScale = ValueAnimator.getDurationScale();
+        ValueAnimator.setDurationScale(0f);
+        Drawable dr = getContext().getDrawable(R.drawable.custom_animation_scale_list_drawable);
+        assertTrue(dr instanceof DrawableContainer);
+        assertFalse(dr.getCurrent() instanceof Animatable);
+        ValueAnimator.setDurationScale(originalScale);
+    }
+}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/ThemedDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/ThemedDrawableTest.java
index 52bef55..7c6fe7c 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/ThemedDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/ThemedDrawableTest.java
@@ -22,6 +22,7 @@
 import android.graphics.Color;
 import android.graphics.Rect;
 import android.graphics.Shader.TileMode;
+import android.graphics.drawable.Drawable;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.GradientDrawable;
@@ -34,7 +35,6 @@
 
 import android.graphics.cts.R;
 
-@TargetApi(21)
 public class ThemedDrawableTest extends AndroidTestCase {
 
     @Override
@@ -150,9 +150,14 @@
         assertEquals(true, d.isAutoMirrored());
 
         BitmapDrawable bitmapDrawable  = (BitmapDrawable) d.getDrawable(0);
+        assertEquals(d, bitmapDrawable.getCallback());
         internalTestBitmapDrawable(bitmapDrawable);
 
         NinePatchDrawable ninePatchDrawable = (NinePatchDrawable) d.getDrawable(1);
+        assertEquals(d, ninePatchDrawable.getCallback());
         internalTestNinePatchDrawable(ninePatchDrawable);
+
+        Drawable themeDrawable = (Drawable) d.getDrawable(2);
+        assertEquals(d, themeDrawable.getCallback());
     }
 }
diff --git a/tests/tests/graphics/src/android/opengl/cts/EglConfigTest.java b/tests/tests/graphics/src/android/opengl/cts/EglConfigTest.java
index 33e8204..1468382 100644
--- a/tests/tests/graphics/src/android/opengl/cts/EglConfigTest.java
+++ b/tests/tests/graphics/src/android/opengl/cts/EglConfigTest.java
@@ -63,6 +63,8 @@
             EglConfigCtsActivity activity = launchActivity("android.graphics.cts",
                     EglConfigCtsActivity.class, extras);
             activity.waitToFinishDrawing();
+            // TODO(b/30948621): Remove the sleep below once b/30948621 is fixed.
+            Thread.sleep(500);
             activity.finish();
             mInstrumentation.waitForIdleSync();
         }
diff --git a/tests/tests/location/src/android/location/cts/GnssStatusTest.java b/tests/tests/location/src/android/location/cts/GnssStatusTest.java
new file mode 100644
index 0000000..e8f3cb1
--- /dev/null
+++ b/tests/tests/location/src/android/location/cts/GnssStatusTest.java
@@ -0,0 +1,49 @@
+package android.location.cts;
+
+import android.location.GnssStatus;
+
+public class GnssStatusTest extends GnssTestCase  {
+
+    private static final String TAG = "GnssStatusTest";
+    private static final int LOCATION_TO_COLLECT_COUNT = 1;
+    private static final int STATUS_TO_COLLECT_COUNT = 3;
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    mTestLocationManager = new TestLocationManager(getContext());
+  }
+
+  /**
+   * Tests that one can listen for {@link GnssStatus}.
+   */
+  public void testGnssStatusChanges() throws Exception {
+    // Checks if GPS hardware feature is present, skips test (pass) if not,
+    // and hard asserts that Location/GPS (Provider) is turned on if is Cts Verifier.
+    if (!TestMeasurementUtil.canTestRunOnCurrentDevice(mTestLocationManager,
+        TAG, MIN_HARDWARE_YEAR_MEASUREMENTS_REQUIRED, isCtsVerifierTest())) {
+      return;
+    }
+
+    // Register Gps Status Listener.
+    TestGnssStatusCallback testGnssStatusCallback =
+        new TestGnssStatusCallback(TAG, STATUS_TO_COLLECT_COUNT);
+    mTestLocationManager.registerGnssStatusCallback(testGnssStatusCallback);
+
+    TestLocationListener locationListener = new TestLocationListener(LOCATION_TO_COLLECT_COUNT);
+    mTestLocationManager.requestLocationUpdates(locationListener);
+
+    boolean success = testGnssStatusCallback.awaitStart();
+    success = success ? testGnssStatusCallback.awaitStatus() : false;
+    success = success ? testGnssStatusCallback.awaitTtff() : false;
+    mTestLocationManager.removeLocationUpdates(locationListener);
+    success = success ? testGnssStatusCallback.awaitStop() : false;
+    mTestLocationManager.unregisterGnssStatusCallback(testGnssStatusCallback);
+
+    SoftAssert.failOrWarning(isMeasurementTestStrict(),
+        "Time elapsed without getting the right status changes."
+            + " Possibly, the test has been run deep indoors."
+            + " Consider retrying test outdoors.",
+        success);
+  }
+}
diff --git a/tests/tests/location/src/android/location/cts/TestGnssStatusCallback.java b/tests/tests/location/src/android/location/cts/TestGnssStatusCallback.java
index cc4c930..c63fb01 100644
--- a/tests/tests/location/src/android/location/cts/TestGnssStatusCallback.java
+++ b/tests/tests/location/src/android/location/cts/TestGnssStatusCallback.java
@@ -18,6 +18,7 @@
 
 import android.location.GnssStatus;
 
+import android.util.Log;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
@@ -28,34 +29,50 @@
  */
 class TestGnssStatusCallback extends GnssStatus.Callback {
 
+    private final String mTag;
     private volatile boolean mGpsStatusReceived;
     private GnssStatus mGnssStatus = null;
     // Timeout in sec for count down latch wait
     private static final int TIMEOUT_IN_SEC = 90;
-    private final CountDownLatch mCountDownLatch;
+    private final CountDownLatch mLatchStart;
+    private final CountDownLatch mLatchStatus;
+    private final CountDownLatch mLatchTtff;
+    private final CountDownLatch mLatchStop;
+
     // Store list of Prn for Satellites.
     private List<List<Integer>> mGpsSatellitePrns;
 
-    TestGnssStatusCallback(int gpsStatusCountToCollect) {
-        mCountDownLatch = new CountDownLatch(gpsStatusCountToCollect);
+    TestGnssStatusCallback(String tag, int gpsStatusCountToCollect) {
+        this.mTag = tag;
+        mLatchStart = new CountDownLatch(1);
+        mLatchStatus = new CountDownLatch(gpsStatusCountToCollect);
+        mLatchTtff = new CountDownLatch(1);
+        mLatchStop = new CountDownLatch(1);
         mGpsSatellitePrns = new ArrayList<List<Integer>>();
     }
 
     @Override
     public void onStarted() {
+        Log.i(mTag, "Gnss Status Listener Started");
+        mLatchStart.countDown();
     }
 
     @Override
     public void onStopped() {
+        Log.i(mTag, "Gnss Status Listener Stopped");
+        mLatchStop.countDown();
     }
 
     @Override
     public void onFirstFix(int ttffMillis) {
+        Log.i(mTag, "Gnss Status Listener Received TTFF");
+        mLatchTtff.countDown();
     }
 
     @Override
     public void onSatelliteStatusChanged(GnssStatus status) {
-        mCountDownLatch.countDown();
+        Log.i(mTag, "Gnss Status Listener Received Status Update");
+        mLatchStatus.countDown();
     }
 
     /**
@@ -86,7 +103,19 @@
         return mGnssStatus;
     }
 
-    public boolean await() throws InterruptedException {
-        return TestUtils.waitFor(mCountDownLatch, TIMEOUT_IN_SEC);
+    public boolean awaitStart() throws InterruptedException {
+        return TestUtils.waitFor(mLatchStart, TIMEOUT_IN_SEC);
+    }
+
+    public boolean awaitStatus() throws InterruptedException {
+        return TestUtils.waitFor(mLatchStatus, TIMEOUT_IN_SEC);
+    }
+
+    public boolean awaitTtff() throws InterruptedException {
+        return TestUtils.waitFor(mLatchTtff, TIMEOUT_IN_SEC);
+    }
+
+    public boolean awaitStop() throws InterruptedException {
+        return TestUtils.waitFor(mLatchStop, TIMEOUT_IN_SEC);
     }
 }
diff --git a/tests/tests/location/src/android/location/cts/TestLocationManager.java b/tests/tests/location/src/android/location/cts/TestLocationManager.java
index 26cc057..cca2b78 100644
--- a/tests/tests/location/src/android/location/cts/TestLocationManager.java
+++ b/tests/tests/location/src/android/location/cts/TestLocationManager.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.location.GnssMeasurementsEvent;
 import android.location.GnssNavigationMessage;
+import android.location.GnssStatus;
 import android.location.GpsStatus;
 import android.location.LocationListener;
 import android.location.LocationManager;
@@ -193,6 +194,28 @@
     }
 
     /**
+     * Add a GNSS Status callback.
+     *
+     * @param callback a {@link GnssStatus.Callback} object to register.
+     * @return {@code true} if the listener was added successfully, {@code false} otherwise.
+     */
+    public boolean registerGnssStatusCallback(GnssStatus.Callback callback) {
+        Log.i(TAG, "Add Gnss Status Callback.");
+        return mLocationManager.registerGnssStatusCallback(
+            callback, new Handler(Looper.getMainLooper()));
+    }
+
+    /**
+     * Removes a GNSS Status callback.
+     *
+     * @param callback a {@link GnssStatus.Callback} object to remove.
+     */
+    public void unregisterGnssStatusCallback(GnssStatus.Callback callback) {
+        Log.i(TAG, "Remove Gnss Status Callback.");
+        mLocationManager.unregisterGnssStatusCallback(callback);
+    }
+
+    /**
      * Get LocationManager
      *
      * @return locationManager
diff --git a/tests/tests/media/res/raw/largealbumart.mp3 b/tests/tests/media/res/raw/largealbumart.mp3
new file mode 100644
index 0000000..e630f0d
--- /dev/null
+++ b/tests/tests/media/res/raw/largealbumart.mp3
Binary files differ
diff --git a/tests/tests/media/src/android/media/cts/AudioNativeTest.java b/tests/tests/media/src/android/media/cts/AudioNativeTest.java
index bfc34d1..7301cc7 100644
--- a/tests/tests/media/src/android/media/cts/AudioNativeTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioNativeTest.java
@@ -24,7 +24,6 @@
 import android.media.AudioManager;
 
 public class AudioNativeTest extends CtsAndroidTestCase {
-    // Assume stereo here until b/23899814 is fixed.
     public static final int MAX_CHANNEL_COUNT = 2;
     public static final int MAX_INDEX_MASK = (1 << MAX_CHANNEL_COUNT) - 1;
 
@@ -215,11 +214,7 @@
         }
         AudioTrackNative track = new AudioTrackNative();
 
-        // TODO: when b/23899814 is fixed, use AudioManager.getDevices() to enumerate
-        // actual devices and their channel counts instead of assuming stereo.
-        //
         int maxOutputChannels = 2;
-
         int validIndexMask = (1 << maxOutputChannels) - 1;
 
         for (int mask = 0; mask <= MAX_INDEX_MASK; ++mask) {
@@ -241,14 +236,20 @@
         if (!hasMicrophone()) {
             return;
         }
+
+        AudioManager audioManager =
+                (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
         AudioRecordNative recorder = new AudioRecordNative();
 
-        // TODO: when b/23899814 is fixed, use AudioManager.getDevices() to enumerate
-        // actual devices and their channel counts instead of assuming stereo.
-        //
-        int maxInputChannels = 2;
+        int maxInputChannels = 0;
+        for (AudioDeviceInfo deviceInfo :
+                audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)) {
+            for (int channels : deviceInfo.getChannelCounts()) {
+                maxInputChannels = Math.max(channels, maxInputChannels);
+            }
+        }
 
-        int validIndexMask = (1 << maxInputChannels) -1;
+        int validIndexMask = (1 << maxInputChannels) - 1;
 
         for (int mask = 0; mask <= MAX_INDEX_MASK; ++mask) {
             int channelCount = Long.bitCount(mask);
diff --git a/tests/tests/media/src/android/media/cts/DecodeAccuracyTest.java b/tests/tests/media/src/android/media/cts/DecodeAccuracyTest.java
index 7b74ba7..9b1dc81 100644
--- a/tests/tests/media/src/android/media/cts/DecodeAccuracyTest.java
+++ b/tests/tests/media/src/android/media/cts/DecodeAccuracyTest.java
@@ -19,11 +19,22 @@
 
 import android.annotation.TargetApi;
 import android.content.Context;
+import android.cts.util.MediaUtils;
 import android.graphics.Bitmap;
+import android.media.MediaFormat;
+import android.support.test.runner.AndroidJUnit4;
 import android.util.Log;
 import android.view.View;
 
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.rules.Timeout;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
 @TargetApi(24)
+@RunWith(AndroidJUnit4.class)
 public class DecodeAccuracyTest extends DecodeAccuracyTestBase {
 
     private static final String TAG = DecodeAccuracyTest.class.getSimpleName();
@@ -32,12 +43,17 @@
     private static final String H264_CROPPED_VIDEO_FILE_NAME = "520x360h264decodertest.mp4";
     private static final int ALLOWED_GREATEST_PIXEL_DIFFERENCE = 90;
     private static final int OFFSET = 10;
+    private static final int PER_TEST_TIMEOUT_S = 30;
 
     private View videoView;
     private VideoViewFactory videoViewFactory;
 
+    @Rule
+    public Timeout globalTimeout = Timeout.seconds(PER_TEST_TIMEOUT_S);
+
+    @After
     @Override
-    protected void tearDown() throws Exception {
+    public void tearDown() throws Exception {
         if (videoView != null) {
             getHelper().cleanUpView(videoView);
         }
@@ -48,36 +64,42 @@
     }
 
     /* <------------- Tests Using H264 -------------> */
+    @Test
     public void testH264GLViewVideoDecode() throws Exception {
         runH264DecodeAccuracyTest(
                 new GLSurfaceViewFactory(),
                 new VideoFormat(H264_VIDEO_FILE_NAME));
     }
 
+    @Test
     public void testH264GLViewLargerHeightVideoDecode() throws Exception {
         runH264DecodeAccuracyTest(
                 new GLSurfaceViewFactory(),
                 getLargerHeightVideoFormat(new VideoFormat(H264_VIDEO_FILE_NAME)));
     }
 
+    @Test
     public void testH264GLViewLargerWidthVideoDecode() throws Exception {
         runH264DecodeAccuracyTest(
                 new GLSurfaceViewFactory(),
                 getLargerWidthVideoFormat(new VideoFormat(H264_VIDEO_FILE_NAME)));
     }
 
+    @Test
     public void testH264SurfaceViewVideoDecode() throws Exception {
         runH264DecodeAccuracyTest(
                 new SurfaceViewFactory(),
                 new VideoFormat(H264_VIDEO_FILE_NAME));
     }
 
+    @Test
     public void testH264SurfaceViewLargerHeightVideoDecode() throws Exception {
         runH264DecodeAccuracyTest(
                 new SurfaceViewFactory(),
                 getLargerHeightVideoFormat(new VideoFormat(H264_VIDEO_FILE_NAME)));
     }
 
+    @Test
     public void testH264SurfaceViewLargerWidthVideoDecode() throws Exception {
         runH264DecodeAccuracyTest(
                 new SurfaceViewFactory(),
@@ -85,36 +107,42 @@
     }
 
     /* <------------- Tests Using VP9 -------------> */
+    @Test
     public void testVP9GLViewVideoDecode() throws Exception {
         runVP9DecodeAccuracyTest(
                 new GLSurfaceViewFactory(),
                 new VideoFormat(VP9_VIDEO_FILE_NAME));
     }
 
+    @Test
     public void testVP9GLViewLargerHeightVideoDecode() throws Exception {
         runVP9DecodeAccuracyTest(
                 new GLSurfaceViewFactory(),
                 getLargerHeightVideoFormat(new VideoFormat(VP9_VIDEO_FILE_NAME)));
     }
 
+    @Test
     public void testVP9GLViewLargerWidthVideoDecode() throws Exception {
         runVP9DecodeAccuracyTest(
                 new GLSurfaceViewFactory(),
                 getLargerWidthVideoFormat(new VideoFormat(VP9_VIDEO_FILE_NAME)));
     }
 
+    @Test
     public void testVP9SurfaceViewVideoDecode() throws Exception {
         runVP9DecodeAccuracyTest(
                 new SurfaceViewFactory(),
                 new VideoFormat(VP9_VIDEO_FILE_NAME));
     }
 
+    @Test
     public void testVP9SurfaceViewLargerHeightVideoDecode() throws Exception {
         runVP9DecodeAccuracyTest(
                 new SurfaceViewFactory(),
                 getLargerHeightVideoFormat(new VideoFormat(VP9_VIDEO_FILE_NAME)));
     }
 
+    @Test
     public void testVP9SurfaceViewLargerWidthVideoDecode() throws Exception {
         runVP9DecodeAccuracyTest(
                 new SurfaceViewFactory(),
@@ -122,12 +150,14 @@
     }
 
     /* <------------- Tests H264 with cropping -------------> */
+    @Test
     public void testH264GLViewCroppedVideoDecode() throws Exception {
         runH264DecodeCroppedTest(
                 new GLSurfaceViewFactory(),
                 new VideoFormat(H264_CROPPED_VIDEO_FILE_NAME));
     }
 
+    @Test
     public void testH264SurfaceViewCroppedVideoDecode() throws Exception {
         runH264DecodeCroppedTest(
                 new SurfaceViewFactory(),
@@ -136,17 +166,23 @@
 
     private void runH264DecodeAccuracyTest(
             VideoViewFactory videoViewFactory, VideoFormat videoFormat) {
-        runDecodeAccuracyTest(videoViewFactory, videoFormat, R.raw.h264decodertestgolden);
+        if (MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
+            runDecodeAccuracyTest(videoViewFactory, videoFormat, R.raw.h264decodertestgolden);
+        }
     }
 
     private void runVP9DecodeAccuracyTest(
             VideoViewFactory videoViewFactory, VideoFormat videoFormat) {
-        runDecodeAccuracyTest(videoViewFactory, videoFormat, R.raw.vp9decodertestgolden);
+        if (MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_VP9)) {
+            runDecodeAccuracyTest(videoViewFactory, videoFormat, R.raw.vp9decodertestgolden);
+        }
     }
 
     private void runH264DecodeCroppedTest(
             VideoViewFactory videoViewFactory, VideoFormat videoFormat) {
-        runDecodeAccuracyTest(videoViewFactory, videoFormat, R.raw.h264decodertest520x360golden);
+        if (MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
+            runDecodeAccuracyTest(videoViewFactory, videoFormat, R.raw.h264decodertest520x360golden);
+        }
     }
 
     private void runDecodeAccuracyTest(
@@ -191,7 +227,8 @@
 
     private void validateResult(
             VideoFormat videoFormat, VideoViewSnapshot videoViewSnapshot, int goldenResId) {
-        final Bitmap result = getHelper().generateBitmapFromVideoViewSnapshot(videoViewSnapshot);
+        final Bitmap result = checkNotNull("The expected bitmap from snapshot is null",
+                getHelper().generateBitmapFromVideoViewSnapshot(videoViewSnapshot));
         final Bitmap golden = getHelper().generateBitmapFromImageResourceId(goldenResId);
         final BitmapCompare.Difference difference = BitmapCompare.computeMinimumDifference(
                 result, golden, videoFormat.getOriginalWidth(), videoFormat.getOriginalHeight());
diff --git a/tests/tests/media/src/android/media/cts/DecodeAccuracyTestBase.java b/tests/tests/media/src/android/media/cts/DecodeAccuracyTestBase.java
index fae1bb4..1ce732d 100644
--- a/tests/tests/media/src/android/media/cts/DecodeAccuracyTestBase.java
+++ b/tests/tests/media/src/android/media/cts/DecodeAccuracyTestBase.java
@@ -44,6 +44,8 @@
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.SystemClock;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
 import android.test.ActivityInstrumentationTestCase2;
 import android.util.Log;
 import android.util.Pair;
@@ -73,7 +75,12 @@
 import javax.microedition.khronos.egl.EGLDisplay;
 import javax.microedition.khronos.egl.EGLSurface;
 
+import org.junit.After;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+
 @TargetApi(16)
+@RunWith(AndroidJUnit4.class)
 public class DecodeAccuracyTestBase
     extends ActivityInstrumentationTestCase2<DecodeAccuracyTestActivity> {
 
@@ -86,9 +93,12 @@
         super(DecodeAccuracyTestActivity.class);
     }
 
+    @Before
     @Override
-    protected void setUp() throws Exception {
+    public void setUp() throws Exception {
         super.setUp();
+        injectInstrumentation(InstrumentationRegistry.getInstrumentation());
+        setActivityInitialTouchMode(false);
         mActivity = getActivity();
         getInstrumentation().waitForIdleSync();
         mContext = getInstrumentation().getTargetContext();
@@ -96,8 +106,9 @@
         testHelper = new TestHelper(mContext, mActivity);
     }
 
+    @After
     @Override
-    protected void tearDown() throws Exception {
+    public void tearDown() throws Exception {
         mActivity = null;
         super.tearDown();
     }
@@ -117,6 +128,11 @@
         return reference;
     }
 
+    public static <T> T checkNotNull(String msg, T reference) {
+        assertNotNull(msg, reference);
+        return reference;
+    }
+
     public static class SimplePlayer {
 
         public static final long DECODE_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(1) / 2;
@@ -419,6 +435,8 @@
     /* Utility class for collecting common test case functionality. */
     class TestHelper {
 
+        private final String TAG =  TestHelper.class.getSimpleName();
+
         private final Context context;
         private final Handler handler;
         private final Activity activity;
@@ -473,13 +491,21 @@
         }
 
         public synchronized Bitmap generateBitmapFromVideoViewSnapshot(VideoViewSnapshot snapshot) {
+            final long timeOutMs = TimeUnit.SECONDS.toMillis(10);
+            final long start = SystemClock.elapsedRealtime();
             handler.post(snapshot);
             try {
-                while (!snapshot.isBitmapReady()) {
+                while (!snapshot.isBitmapReady()
+                        && (SystemClock.elapsedRealtime() - start < timeOutMs)) {
                     Thread.sleep(100);
                 }
             } catch (InterruptedException e) {
                 e.printStackTrace();
+                return null;
+            }
+            if (!snapshot.isBitmapReady()) {
+                Log.e(TAG, "Time out in generateBitmapFromVideoViewSnapshot().");
+                return null;
             }
             return snapshot.getBitmap();
         }
@@ -1165,8 +1191,7 @@
 class SurfaceViewSnapshot extends VideoViewSnapshot  {
 
     private static final String TAG = SurfaceViewSnapshot.class.getSimpleName();
-    private static final int PIXELCOPY_REQUEST_SLEEP_MS = 30;
-    private static final int PIXELCOPY_REQUEST_MAX_ATTEMPTS = 20;
+    private static final int PIXELCOPY_REQUEST_SLEEP_MS = 100;
     private static final int PIXELCOPY_TIMEOUT_MS = 1000;
 
     private final Thread copyThread;
@@ -1182,15 +1207,13 @@
                 bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
                 try {
                     // Wait for SurfaceView to be available.
-                    for (int i = 0; i < PIXELCOPY_REQUEST_MAX_ATTEMPTS; i++) {
-                        copyResult = copyHelper.request(surfaceView, bitmap);
-                        if (copyResult == PixelCopy.SUCCESS) {
-                            break;
-                        }
+                    while (copyResult != PixelCopy.SUCCESS) {
                         Thread.sleep(PIXELCOPY_REQUEST_SLEEP_MS);
+                        copyResult = copyHelper.request(surfaceView, bitmap);
                     }
                 } catch (InterruptedException e) {
-                    Log.w(TAG, "Pixel Copy is stopped/interrupted before it finishes.", e);
+                    Log.e(TAG, "Pixel Copy is stopped/interrupted before it finishes.", e);
+                    bitmap = null;
                 }
                 copyHelper.release();
             }
@@ -1294,10 +1317,10 @@
         try {
             waitForByteBuffer();
         } catch (InterruptedException e) {
-            Log.w(TAG, e.getMessage());
-            Log.w(TAG, "ByteBuffer may contain incorrect pixels.");
+            Log.e(TAG, e.getMessage());
+            bitmap = null;
+            return;
         }
-        // Get ByteBuffer anyway. Let the test fail if ByteBuffer contains incorrect pixels.
         ByteBuffer byteBuffer = glSurfaceViewFactory.getByteBuffer();
         bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
         byteBuffer.rewind();
diff --git a/tests/tests/media/src/android/media/cts/DecoderTest.java b/tests/tests/media/src/android/media/cts/DecoderTest.java
index 13ebeff..3025306 100755
--- a/tests/tests/media/src/android/media/cts/DecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/DecoderTest.java
@@ -501,9 +501,9 @@
 
     private void testTrackSelection(int resid) throws Exception {
         AssetFileDescriptor fd1 = null;
+        MediaExtractor ex1 = new MediaExtractor();
         try {
             fd1 = mResources.openRawResourceFd(resid);
-            MediaExtractor ex1 = new MediaExtractor();
             ex1.setDataSource(fd1.getFileDescriptor(), fd1.getStartOffset(), fd1.getLength());
 
             ByteBuffer buf1 = ByteBuffer.allocate(1024*1024);
@@ -664,6 +664,9 @@
             }
 
         } finally {
+            if (ex1 != null) {
+                ex1.release();
+            }
             if (fd1 != null) {
                 fd1.close();
             }
diff --git a/tests/tests/media/src/android/media/cts/DeviceUtils.java b/tests/tests/media/src/android/media/cts/DeviceUtils.java
new file mode 100644
index 0000000..9051c69
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/DeviceUtils.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.cts;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+
+import android.media.AudioDeviceInfo;
+import android.media.AudioManager;
+
+import android.util.Log;
+
+/* package */ class DeviceUtils {
+    private static final String TAG = "DeviceUtils";
+
+    /* package */ static boolean hasOutputDevice(AudioManager audioMgr) {
+        AudioDeviceInfo[] devices = audioMgr.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
+        return devices.length != 0;
+    }
+
+    /* package */ static boolean hasInputDevice(AudioManager audioMgr) {
+        AudioDeviceInfo[] devices = audioMgr.getDevices(AudioManager.GET_DEVICES_INPUTS);
+        return devices.length != 0;
+    }
+
+    /* package */ static boolean isTVDevice(Context context) {
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+    }
+
+    /*
+     * HDMI
+     */
+    /* package */ static boolean isHDMIConnected(Context context) {
+        // configure the IntentFilter
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(AudioManager.ACTION_HDMI_AUDIO_PLUG);
+        Intent intent = context.registerReceiver(null, intentFilter);
+
+        return intent != null && intent.getIntExtra(AudioManager.EXTRA_AUDIO_PLUG_STATE, 0) != 0;
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/EncoderTest.java b/tests/tests/media/src/android/media/cts/EncoderTest.java
index adb2351..e086347 100644
--- a/tests/tests/media/src/android/media/cts/EncoderTest.java
+++ b/tests/tests/media/src/android/media/cts/EncoderTest.java
@@ -161,7 +161,7 @@
         try {
             pool.shutdown();
             assertTrue("timed out waiting for encoder threads",
-                    pool.awaitTermination(5, TimeUnit.MINUTES));
+                    pool.awaitTermination(10, TimeUnit.MINUTES));
         } catch (InterruptedException e) {
             fail("interrupted while waiting for encoder threads");
         }
diff --git a/tests/tests/media/src/android/media/cts/EnumDevicesTest.java b/tests/tests/media/src/android/media/cts/EnumDevicesTest.java
index 94af087..1d84a3e 100644
--- a/tests/tests/media/src/android/media/cts/EnumDevicesTest.java
+++ b/tests/tests/media/src/android/media/cts/EnumDevicesTest.java
@@ -28,10 +28,14 @@
 
 import android.test.AndroidTestCase;
 
+import android.util.Log;
+
 /**
  * TODO: Insert description here. (generated by pmclean)
  */
 public class EnumDevicesTest extends AndroidTestCase {
+    private static final String TAG = "EnumDevicesTest";
+
     private AudioManager mAudioManager;
 
     boolean mAddCallbackCalled = false;
@@ -54,25 +58,39 @@
         assertTrue(deviceList != null);
         assertTrue(deviceList.length == 0);
 
+        PackageManager pkgMgr = mContext.getPackageManager();
+
+        boolean isTvDevice = DeviceUtils.isTVDevice(mContext);
+
         int numOutputDevices = 0;
-        if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT)) {
+        if (pkgMgr.hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT)) {
             // test OUTPUTS
             deviceList = mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
             assertTrue(deviceList != null);
-            numOutputDevices = deviceList.length;
-            assertTrue(numOutputDevices != 0);
 
-            // all should be "sinks"
+            numOutputDevices = deviceList.length;
+            if (numOutputDevices == 0) {
+                boolean isHDMIConnected = DeviceUtils.isHDMIConnected(mContext);
+                if (isTvDevice && !isHDMIConnected) {
+                    Log.w(TAG, "getDevices test: failure due to missing reported output " +
+                               "or the test is run on a TV device with no HDMI connected");
+                }
+                assertTrue("getDevices test: failure due to missing HDMI connection " +
+                           "or missing output", false);
+            }
+
+            // any reported output devices should be "sinks"
             for(int index = 0; index < numOutputDevices; index++) {
                 assertTrue(deviceList[index].isSink());
             }
         }
 
         int numInputDevices = 0;
-        if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MICROPHONE)) {
+        if (pkgMgr.hasSystemFeature(PackageManager.FEATURE_MICROPHONE)) {
             // test INPUTS
             deviceList = mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS);
             assertTrue(deviceList != null);
+
             numInputDevices = deviceList.length;
             assertTrue(numInputDevices != 0);
 
@@ -86,6 +104,7 @@
         if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT) &&
                 mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MICROPHONE)) {
             deviceList = mAudioManager.getDevices(AudioManager.GET_DEVICES_ALL);
+            assertTrue(deviceList != null);
             assertTrue(deviceList.length == (numOutputDevices + numInputDevices));
         }
     }
diff --git a/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java b/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
index 0b38e1b..890073c 100644
--- a/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
@@ -124,6 +124,12 @@
                 mRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_WRITER));
     }
 
+    public void testLargeAlbumArt() {
+        setDataSourceFd(R.raw.largealbumart);
+
+        assertNotNull("couldn't retrieve album art", mRetriever.getEmbeddedPicture());
+    }
+
     public void testSetDataSourceNullPath() {
         try {
             mRetriever.setDataSource((String)null);
diff --git a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
index dffb653..2d38933 100644
--- a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
@@ -425,8 +425,9 @@
     }
 
     public void testRecordAudioFromAudioSourceUnprocessed() throws Exception {
-        if (!hasMicrophone()) {
-            return; // skip
+        if (!hasMicrophone() || !hasAmrNb()) {
+            MediaUtils.skipTest("no audio codecs or microphone");
+            return;
         }
         mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.UNPROCESSED);
         mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
@@ -934,13 +935,14 @@
         boolean success = false;
         Surface surface = null;
         int noOfFailure = 0;
-        final float frameRate = getMaxFrameRateForCodec(MediaRecorder.VideoEncoder.H264);
 
         if (!hasH264()) {
             MediaUtils.skipTest("no codecs");
             return true;
         }
 
+        final float frameRate = getMaxFrameRateForCodec(MediaRecorder.VideoEncoder.H264);
+
         try {
             if (persistent) {
                 surface = MediaCodec.createPersistentInputSurface();
diff --git a/tests/tests/media/src/android/media/cts/RoutingTest.java b/tests/tests/media/src/android/media/cts/RoutingTest.java
index 22aaaa3..7614568 100644
--- a/tests/tests/media/src/android/media/cts/RoutingTest.java
+++ b/tests/tests/media/src/android/media/cts/RoutingTest.java
@@ -352,6 +352,11 @@
     }
 
     public void test_audioTrack_getRoutedDevice() {
+        if (!DeviceUtils.hasOutputDevice(mAudioManager)) {
+            Log.i(TAG, "No output devices. Test skipped");
+            return; // nothing to test here
+        }
+
         int bufferSize =
                 AudioTrack.getMinBufferSize(
                     41000,
@@ -415,6 +420,11 @@
             return;
         }
 
+        if (!DeviceUtils.hasInputDevice(mAudioManager)) {
+            Log.i(TAG, "No input devices. Test skipped");
+            return; // nothing to test here
+        }
+
         int bufferSize =
                 AudioRecord.getMinBufferSize(
                     41000,
diff --git a/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java b/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java
index 07f00eb..c6e0578 100644
--- a/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java
+++ b/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java
@@ -28,6 +28,7 @@
 import android.media.MediaExtractor;
 import android.media.MediaFormat;
 import android.util.Log;
+import android.util.Pair;
 import android.view.Surface;
 
 import com.android.compatibility.common.util.DeviceReportLog;
@@ -60,7 +61,8 @@
     private static final boolean OTHER = false;
 
     private static final int MAX_SIZE_SAMPLES_IN_MEMORY_BYTES = 12 << 20;  // 12MB
-    LinkedList<ByteBuffer> mSamplesInMemory = new LinkedList<ByteBuffer>();
+    // each sample contains the buffer and the PTS offset from the frame index
+    LinkedList<Pair<ByteBuffer, Double>> mSamplesInMemory = new LinkedList<Pair<ByteBuffer, Double>>();
     private MediaFormat mDecInputFormat;
     private MediaFormat mDecOutputFormat;
     private int mBitrate;
@@ -117,6 +119,16 @@
         int trackIndex = extractor.getSampleTrackIndex();
         MediaFormat format = extractor.getTrackFormat(trackIndex);
         String mime = format.getString(MediaFormat.KEY_MIME);
+
+        // use frame rate to calculate PTS offset used for PTS scaling
+        double frameRate = 0.; // default - 0 is used for using zero PTS offset
+        if (format.containsKey(MediaFormat.KEY_FRAME_RATE)) {
+            frameRate = format.getInteger(MediaFormat.KEY_FRAME_RATE);
+        } else if (!mime.equals(MediaFormat.MIMETYPE_VIDEO_VP8)
+                && !mime.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
+            fail("need framerate info for video file");
+        }
+
         ByteBuffer[] codecInputBuffers;
         ByteBuffer[] codecOutputBuffers;
 
@@ -125,14 +137,25 @@
             ByteBuffer tmpBuf = ByteBuffer.allocate(w * h * 3 / 2);
             int sampleSize = 0;
             int index = 0;
+            long firstPTS = 0;
+            double presentationOffset = 0.;
             while ((sampleSize = extractor.readSampleData(tmpBuf, 0 /* offset */)) > 0) {
                 if (totalMemory + sampleSize > MAX_SIZE_SAMPLES_IN_MEMORY_BYTES) {
                     break;
                 }
+                if (mSamplesInMemory.size() == 0) {
+                    firstPTS = extractor.getSampleTime();
+                }
                 ByteBuffer copied = ByteBuffer.allocate(sampleSize);
                 copied.put(tmpBuf);
-                mSamplesInMemory.addLast(copied);
+                if (frameRate > 0.) {
+                    // presentation offset is an offset from the frame index
+                    presentationOffset =
+                        (extractor.getSampleTime() - firstPTS) * frameRate / 1e6 - index;
+                }
+                mSamplesInMemory.addLast(Pair.create(copied, presentationOffset));
                 totalMemory += sampleSize;
+                ++index;
                 extractor.advance();
             }
             Log.d(TAG, mSamplesInMemory.size() + " samples in memory for " +
@@ -149,7 +172,7 @@
 
         MediaCodec codec = MediaCodec.createByCodecName(name);
         VideoCapabilities cap = codec.getCodecInfo().getCapabilitiesForType(mime).getVideoCapabilities();
-        int frameRate = cap.getSupportedFrameRatesFor(w, h).getUpper().intValue();
+        frameRate = cap.getSupportedFrameRatesFor(w, h).getUpper();
         codec.configure(format, surface, null /* crypto */, 0 /* flags */);
         codec.start();
         codecInputBuffers = codec.getInputBuffers();
@@ -174,13 +197,14 @@
 
                 if (inputBufIndex >= 0) {
                     ByteBuffer dstBuf = codecInputBuffers[inputBufIndex];
-                    ByteBuffer sample =
+                    // sample contains the buffer and the PTS offset normalized to frame index
+                    Pair<ByteBuffer, Double> sample =
                             mSamplesInMemory.get(sampleIndex++ % mSamplesInMemory.size());
-                    sample.rewind();
-                    int sampleSize = sample.remaining();
-                    dstBuf.put(sample);
-                    // use 120fps to compute pts
-                    long presentationTimeUs = inputNum * 1000000L / frameRate;
+                    sample.first.rewind();
+                    int sampleSize = sample.first.remaining();
+                    dstBuf.put(sample.first);
+                    // use max supported framerate to compute pts
+                    long presentationTimeUs = (long)((inputNum + sample.second) * 1e6 / frameRate);
 
                     long elapsed = System.currentTimeMillis() - start;
                     sawInputEOS = ((++inputNum == TOTAL_FRAMES)
diff --git a/tests/tests/mediastress/preconditions/src/android/mediastress/cts/preconditions/MediaPreparer.java b/tests/tests/mediastress/preconditions/src/android/mediastress/cts/preconditions/MediaPreparer.java
index a780317..13ff24b 100644
--- a/tests/tests/mediastress/preconditions/src/android/mediastress/cts/preconditions/MediaPreparer.java
+++ b/tests/tests/mediastress/preconditions/src/android/mediastress/cts/preconditions/MediaPreparer.java
@@ -102,6 +102,12 @@
     /* Key to retrieve resolution string in metrics upon MediaPreparerListener.testEnded() */
     private static final String RESOLUTION_STRING_KEY = "resolution";
 
+    /*
+     * In the case of MediaPreparer error, the default maximum resolution to push to the device.
+     * Pushing higher resolutions may lead to insufficient storage for installing test APKs.
+     * TODO(aaronholden): When the new detection of max resolution is proven stable, throw
+     * a TargetSetupError when detection results in error
+     */
     protected static final Resolution DEFAULT_MAX_RESOLUTION = new Resolution(480, 360);
 
     protected static final Resolution[] RESOLUTIONS = {
diff --git a/tests/tests/net/src/android/net/cts/LocalSocketTest.java b/tests/tests/net/src/android/net/cts/LocalSocketTest.java
index 77f0a44..0ff4a30 100644
--- a/tests/tests/net/src/android/net/cts/LocalSocketTest.java
+++ b/tests/tests/net/src/android/net/cts/LocalSocketTest.java
@@ -22,12 +22,18 @@
 import android.net.LocalServerSocket;
 import android.net.LocalSocket;
 import android.net.LocalSocketAddress;
+import android.system.Os;
+import android.system.OsConstants;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.concurrent.Callable;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 
 public class LocalSocketTest extends TestCase {
@@ -177,58 +183,114 @@
         socket.close();
     }
 
+    // http://b/31205169
+    public void testSetSoTimeout_readTimeout() throws Exception {
+        String address = ADDRESS_PREFIX + "_testSetSoTimeout_readTimeout";
+
+        try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) {
+            final LocalSocket clientSocket = socketPair.clientSocket;
+
+            // Set the timeout in millis.
+            int timeoutMillis = 1000;
+            clientSocket.setSoTimeout(timeoutMillis);
+
+            // Avoid blocking the test run if timeout doesn't happen by using a separate thread.
+            Callable<Result> reader = () -> {
+                try {
+                    clientSocket.getInputStream().read();
+                    return Result.noException("Did not block");
+                } catch (IOException e) {
+                    return Result.exception(e);
+                }
+            };
+            // Allow the configured timeout, plus some slop.
+            int allowedTime = timeoutMillis + 2000;
+            Result result = runInSeparateThread(allowedTime, reader);
+
+            // Check the message was a timeout, it's all we have to go on.
+            String expectedMessage = Os.strerror(OsConstants.EAGAIN);
+            result.assertThrewIOException(expectedMessage);
+        }
+    }
+
+    // http://b/31205169
+    public void testSetSoTimeout_writeTimeout() throws Exception {
+        String address = ADDRESS_PREFIX + "_testSetSoTimeout_writeTimeout";
+
+        try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) {
+            final LocalSocket clientSocket = socketPair.clientSocket;
+
+            // Set the timeout in millis.
+            int timeoutMillis = 1000;
+            clientSocket.setSoTimeout(timeoutMillis);
+
+            // Set a small buffer size so we know we can flood it.
+            clientSocket.setSendBufferSize(100);
+            final int bufferSize = clientSocket.getSendBufferSize();
+
+            // Avoid blocking the test run if timeout doesn't happen by using a separate thread.
+            Callable<Result> writer = () -> {
+                try {
+                    byte[] toWrite = new byte[bufferSize * 2];
+                    clientSocket.getOutputStream().write(toWrite);
+                    return Result.noException("Did not block");
+                } catch (IOException e) {
+                    return Result.exception(e);
+                }
+            };
+            // Allow the configured timeout, plus some slop.
+            int allowedTime = timeoutMillis + 2000;
+
+            Result result = runInSeparateThread(allowedTime, writer);
+
+            // Check the message was a timeout, it's all we have to go on.
+            String expectedMessage = Os.strerror(OsConstants.EAGAIN);
+            result.assertThrewIOException(expectedMessage);
+        }
+    }
+
     public void testAvailable() throws Exception {
         String address = ADDRESS_PREFIX + "_testAvailable";
-        LocalServerSocket localServerSocket = new LocalServerSocket(address);
-        LocalSocket clientSocket = new LocalSocket();
 
-        // establish connection between client and server
-        LocalSocketAddress locSockAddr = new LocalSocketAddress(address);
-        clientSocket.connect(locSockAddr);
-        assertTrue(clientSocket.isConnected());
-        LocalSocket serverSocket = localServerSocket.accept();
+        try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) {
+            LocalSocket clientSocket = socketPair.clientSocket;
+            LocalSocket serverSocket = socketPair.serverSocket.accept();
 
-        OutputStream clientOutputStream = clientSocket.getOutputStream();
-        InputStream serverInputStream = serverSocket.getInputStream();
-        assertEquals(0, serverInputStream.available());
+            OutputStream clientOutputStream = clientSocket.getOutputStream();
+            InputStream serverInputStream = serverSocket.getInputStream();
+            assertEquals(0, serverInputStream.available());
 
-        byte[] buffer = new byte[50];
-        clientOutputStream.write(buffer);
-        assertEquals(50, serverInputStream.available());
+            byte[] buffer = new byte[50];
+            clientOutputStream.write(buffer);
+            assertEquals(50, serverInputStream.available());
 
-        InputStream clientInputStream = clientSocket.getInputStream();
-        OutputStream serverOutputStream = serverSocket.getOutputStream();
-        assertEquals(0, clientInputStream.available());
-        serverOutputStream.write(buffer);
-        assertEquals(50, serverInputStream.available());
+            InputStream clientInputStream = clientSocket.getInputStream();
+            OutputStream serverOutputStream = serverSocket.getOutputStream();
+            assertEquals(0, clientInputStream.available());
+            serverOutputStream.write(buffer);
+            assertEquals(50, serverInputStream.available());
 
-        clientSocket.close();
-        serverSocket.close();
-        localServerSocket.close();
+            serverSocket.close();
+        }
     }
 
     public void testFlush() throws Exception {
         String address = ADDRESS_PREFIX + "_testFlush";
-        LocalServerSocket localServerSocket = new LocalServerSocket(address);
-        LocalSocket clientSocket = new LocalSocket();
 
-        // establish connection between client and server
-        LocalSocketAddress locSockAddr = new LocalSocketAddress(address);
-        clientSocket.connect(locSockAddr);
-        assertTrue(clientSocket.isConnected());
-        LocalSocket serverSocket = localServerSocket.accept();
+        try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) {
+            LocalSocket clientSocket = socketPair.clientSocket;
+            LocalSocket serverSocket = socketPair.serverSocket.accept();
 
-        OutputStream clientOutputStream = clientSocket.getOutputStream();
-        InputStream serverInputStream = serverSocket.getInputStream();
-        testFlushWorks(clientOutputStream, serverInputStream);
+            OutputStream clientOutputStream = clientSocket.getOutputStream();
+            InputStream serverInputStream = serverSocket.getInputStream();
+            testFlushWorks(clientOutputStream, serverInputStream);
 
-        OutputStream serverOutputStream = serverSocket.getOutputStream();
-        InputStream clientInputStream = clientSocket.getInputStream();
-        testFlushWorks(serverOutputStream, clientInputStream);
+            OutputStream serverOutputStream = serverSocket.getOutputStream();
+            InputStream clientInputStream = clientSocket.getInputStream();
+            testFlushWorks(serverOutputStream, clientInputStream);
 
-        clientSocket.close();
-        serverSocket.close();
-        localServerSocket.close();
+            serverSocket.close();
+        }
     }
 
     private void testFlushWorks(OutputStream outputStream, InputStream inputStream)
@@ -296,4 +358,64 @@
             assertEquals(expected, bytesRead);
         }
     }
+
+    private static class Result {
+        private final String type;
+        private final Exception e;
+
+        private Result(String type, Exception e) {
+            this.type = type;
+            this.e = e;
+        }
+
+        static Result noException(String description) {
+            return new Result(description, null);
+        }
+
+        static Result exception(Exception e) {
+            return new Result(e.getClass().getName(), e);
+        }
+
+        void assertThrewIOException(String expectedMessage) {
+            assertEquals("Unexpected result type", IOException.class.getName(), type);
+            assertEquals("Unexpected exception message", expectedMessage, e.getMessage());
+        }
+    }
+
+    private static Result runInSeparateThread(int allowedTime, final Callable<Result> callable)
+            throws Exception {
+        ExecutorService service = Executors.newSingleThreadScheduledExecutor();
+        Future<Result> future = service.submit(callable);
+        Result result = future.get(allowedTime, TimeUnit.MILLISECONDS);
+        if (!future.isDone()) {
+            fail("Worker thread appears blocked");
+        }
+        return result;
+    }
+
+    private static class LocalSocketPair implements AutoCloseable {
+        static LocalSocketPair createConnectedSocketPair(String address) throws Exception {
+            LocalServerSocket localServerSocket = new LocalServerSocket(address);
+            final LocalSocket clientSocket = new LocalSocket();
+
+            // Establish connection between client and server
+            LocalSocketAddress locSockAddr = new LocalSocketAddress(address);
+            clientSocket.connect(locSockAddr);
+            assertTrue(clientSocket.isConnected());
+            return new LocalSocketPair(localServerSocket, clientSocket);
+        }
+
+        final LocalServerSocket serverSocket;
+        final LocalSocket clientSocket;
+
+        LocalSocketPair(LocalServerSocket serverSocket, LocalSocket clientSocket) {
+            this.serverSocket = serverSocket;
+            this.clientSocket = clientSocket;
+        }
+
+        public void close() throws Exception {
+            serverSocket.close();
+            clientSocket.close();
+        }
+    }
 }
diff --git a/tests/tests/os/src/android/os/cts/AsyncTaskTest.java b/tests/tests/os/src/android/os/cts/AsyncTaskTest.java
index efd1eed..1c9aaba 100644
--- a/tests/tests/os/src/android/os/cts/AsyncTaskTest.java
+++ b/tests/tests/os/src/android/os/cts/AsyncTaskTest.java
@@ -16,11 +16,14 @@
 
 package android.os.cts;
 
+import android.support.annotation.NonNull;
 
 import android.cts.util.PollingCheck;
 import android.os.AsyncTask;
 import android.test.InstrumentationTestCase;
 
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
 
 public class AsyncTaskTest extends InstrumentationTestCase {
@@ -30,7 +33,8 @@
     private static final long DURATION = 2000;
     private static final String[] PARAM = { "Test" };
 
-    private static MyAsyncTask mAsyncTask;
+    private static AsyncTask mAsyncTask;
+    private static MyAsyncTask mMyAsyncTask;
 
     public void testAsyncTask() throws Throwable {
         doTestAsyncTask(0);
@@ -43,51 +47,51 @@
     private void doTestAsyncTask(final long timeout) throws Throwable {
         startAsyncTask();
         if (timeout > 0) {
-            assertEquals(RESULT, mAsyncTask.get(DURATION, TimeUnit.MILLISECONDS).longValue());
+            assertEquals(RESULT, mMyAsyncTask.get(DURATION, TimeUnit.MILLISECONDS).longValue());
         } else {
-            assertEquals(RESULT, mAsyncTask.get().longValue());
+            assertEquals(RESULT, mMyAsyncTask.get().longValue());
         }
 
         // wait for the task to finish completely (including onPostResult()).
         new PollingCheck(DURATION) {
             protected boolean check() {
-                return mAsyncTask.getStatus() == AsyncTask.Status.FINISHED;
+                return mMyAsyncTask.getStatus() == AsyncTask.Status.FINISHED;
             }
         }.run();
 
-        assertTrue(mAsyncTask.isOnPreExecuteCalled);
-        assert(mAsyncTask.hasRun);
-        assertEquals(PARAM.length, mAsyncTask.parameters.length);
+        assertTrue(mMyAsyncTask.isOnPreExecuteCalled);
+        assert(mMyAsyncTask.hasRun);
+        assertEquals(PARAM.length, mMyAsyncTask.parameters.length);
         for (int i = 0; i < PARAM.length; i++) {
-            assertEquals(PARAM[i], mAsyncTask.parameters[i]);
+            assertEquals(PARAM[i], mMyAsyncTask.parameters[i]);
         }
         // even though the background task has run, the onPostExecute() may not have been
         // executed yet and the progress update may not have been processed. Wait until the task
         // has completed, which guarantees that onPostExecute has been called.
 
-        assertEquals(RESULT, mAsyncTask.postResult.longValue());
-        assertEquals(AsyncTask.Status.FINISHED, mAsyncTask.getStatus());
+        assertEquals(RESULT, mMyAsyncTask.postResult.longValue());
+        assertEquals(AsyncTask.Status.FINISHED, mMyAsyncTask.getStatus());
 
-        if (mAsyncTask.exception != null) {
-            throw mAsyncTask.exception;
+        if (mMyAsyncTask.exception != null) {
+            throw mMyAsyncTask.exception;
         }
 
         // wait for progress update to be processed (happens asynchronously)
         new PollingCheck(DURATION) {
             protected boolean check() {
-                return mAsyncTask.updateValue != null;
+                return mMyAsyncTask.updateValue != null;
             }
         }.run();
-        assertEquals(UPDATE_VALUE.length, mAsyncTask.updateValue.length);
+        assertEquals(UPDATE_VALUE.length, mMyAsyncTask.updateValue.length);
         for (int i = 0; i < UPDATE_VALUE.length; i++) {
-            assertEquals(UPDATE_VALUE[i], mAsyncTask.updateValue[i]);
+            assertEquals(UPDATE_VALUE[i], mMyAsyncTask.updateValue[i]);
         }
 
         runTestOnUiThread(new Runnable() {
             public void run() {
                 try {
                     // task should not be allowed to execute twice
-                    mAsyncTask.execute(PARAM);
+                    mMyAsyncTask.execute(PARAM);
                     fail("Failed to throw exception!");
                 } catch (IllegalStateException e) {
                     // expected
@@ -99,44 +103,122 @@
     public void testCancelWithInterrupt() throws Throwable {
         startAsyncTask();
         Thread.sleep(COMPUTE_TIME / 2);
-        assertTrue(mAsyncTask.cancel(true));
+        assertTrue(mMyAsyncTask.cancel(true));
         // already cancelled
-        assertFalse(mAsyncTask.cancel(true));
+        assertFalse(mMyAsyncTask.cancel(true));
         Thread.sleep(DURATION);
-        assertTrue(mAsyncTask.isCancelled());
-        assertTrue(mAsyncTask.isOnCancelledCalled);
-        assertNotNull(mAsyncTask.exception);
-        assertTrue(mAsyncTask.exception instanceof InterruptedException);
+        assertTrue(mMyAsyncTask.isCancelled());
+        assertTrue(mMyAsyncTask.isOnCancelledCalled);
+        assertNotNull(mMyAsyncTask.exception);
+        assertTrue(mMyAsyncTask.exception instanceof InterruptedException);
     }
 
     public void testCancel() throws Throwable {
         startAsyncTask();
         Thread.sleep(COMPUTE_TIME / 2);
-        assertTrue(mAsyncTask.cancel(false));
+        assertTrue(mMyAsyncTask.cancel(false));
         // already cancelled
-        assertFalse(mAsyncTask.cancel(false));
+        assertFalse(mMyAsyncTask.cancel(false));
         Thread.sleep(DURATION);
-        assertTrue(mAsyncTask.isCancelled());
-        assertTrue(mAsyncTask.isOnCancelledCalled);
-        assertNull(mAsyncTask.exception);
+        assertTrue(mMyAsyncTask.isCancelled());
+        assertTrue(mMyAsyncTask.isOnCancelledCalled);
+        assertNull(mMyAsyncTask.exception);
     }
 
     public void testCancelTooLate() throws Throwable {
         startAsyncTask();
         Thread.sleep(DURATION);
-        assertFalse(mAsyncTask.cancel(false));
-        assertTrue(mAsyncTask.isCancelled());
-        assertFalse(mAsyncTask.isOnCancelledCalled);
-        assertNull(mAsyncTask.exception);
+        assertFalse(mMyAsyncTask.cancel(false));
+        assertTrue(mMyAsyncTask.isCancelled());
+        assertFalse(mMyAsyncTask.isOnCancelledCalled);
+        assertNull(mMyAsyncTask.exception);
+    }
+
+    public void testCancellationWithException() throws Throwable {
+        final CountDownLatch readyToCancel = new CountDownLatch(1);
+        final CountDownLatch readyToThrow = new CountDownLatch(1);
+        final CountDownLatch calledOnCancelled = new CountDownLatch(1);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mAsyncTask = new AsyncTask() {
+                    @Override
+                    protected Object doInBackground(Object... params) {
+                        readyToCancel.countDown();
+                        try {
+                            readyToThrow.await();
+                        } catch (InterruptedException e) {}
+                        // This exception is expected to be caught and ignored
+                        throw new RuntimeException();
+                    }
+
+                    @Override
+                    protected void onCancelled(Object o) {
+                        calledOnCancelled.countDown();
+                    }
+                };
+            }
+        });
+
+        mAsyncTask.execute();
+        if (!readyToCancel.await(5, TimeUnit.SECONDS)) {
+            fail("Test failure: doInBackground did not run in time.");
+        }
+        mAsyncTask.cancel(false);
+        readyToThrow.countDown();
+        if (!calledOnCancelled.await(5, TimeUnit.SECONDS)) {
+            fail("onCancelled not called!");
+        }
+    }
+
+    public void testException() throws Throwable {
+        final CountDownLatch calledOnCancelled = new CountDownLatch(1);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mAsyncTask = new AsyncTask() {
+                    @Override
+                    protected Object doInBackground(Object... params) {
+                        throw new RuntimeException();
+                    }
+
+                    @Override
+                    protected void onPostExecute(Object o) {
+                        fail("onPostExecute should not be called");
+                    }
+
+                    @Override
+                    protected void onCancelled(Object o) {
+                        calledOnCancelled.countDown();
+                    }
+                };
+            }
+        });
+
+        mAsyncTask.executeOnExecutor(new Executor() {
+            @Override
+            public void execute(@NonNull Runnable command) {
+                try {
+                    command.run();
+                    fail("Exception not thrown");
+                } catch (Throwable tr) {
+                    // expected
+                }
+            }
+        });
+
+        if (!calledOnCancelled.await(5, TimeUnit.SECONDS)) {
+            fail("onCancelled not called!");
+        }
     }
 
     private void startAsyncTask() throws Throwable {
         runTestOnUiThread(new Runnable() {
             public void run() {
-                mAsyncTask = new MyAsyncTask();
-                assertEquals(AsyncTask.Status.PENDING, mAsyncTask.getStatus());
-                assertEquals(mAsyncTask, mAsyncTask.execute(PARAM));
-                assertEquals(AsyncTask.Status.RUNNING, mAsyncTask.getStatus());
+                mMyAsyncTask = new MyAsyncTask();
+                assertEquals(AsyncTask.Status.PENDING, mMyAsyncTask.getStatus());
+                assertEquals(mMyAsyncTask, mMyAsyncTask.execute(PARAM));
+                assertEquals(AsyncTask.Status.RUNNING, mMyAsyncTask.getStatus());
             }
         });
     }
diff --git a/tests/tests/os/src/android/os/cts/BuildVersionTest.java b/tests/tests/os/src/android/os/cts/BuildVersionTest.java
index 75c8db5..66066e9 100644
--- a/tests/tests/os/src/android/os/cts/BuildVersionTest.java
+++ b/tests/tests/os/src/android/os/cts/BuildVersionTest.java
@@ -30,7 +30,7 @@
 
     private static final String LOG_TAG = "BuildVersionTest";
     private static final Set<String> EXPECTED_RELEASES =
-            new HashSet<String>(Arrays.asList("7.1"));
+            new HashSet<String>(Arrays.asList("7.1","7.1.1"));
     private static final int EXPECTED_SDK = 25;
     private static final String EXPECTED_BUILD_VARIANT = "user";
     private static final String EXPECTED_TAG = "release-keys";
diff --git a/tests/tests/os/src/android/os/cts/SecurityPatchTest.java b/tests/tests/os/src/android/os/cts/SecurityPatchTest.java
index f7cbcc4..4531aa6 100644
--- a/tests/tests/os/src/android/os/cts/SecurityPatchTest.java
+++ b/tests/tests/os/src/android/os/cts/SecurityPatchTest.java
@@ -31,8 +31,8 @@
             "ro.build.version.security_patch should be in the format \"YYYY-MM-DD\". Found \"%s\"";
     private static final String SECURITY_PATCH_DATE_ERROR =
             "ro.build.version.security_patch should be \"%d-%02d\" or later. Found \"%s\"";
-    private static final int SECURITY_PATCH_YEAR = 2017;
-    private static final int SECURITY_PATCH_MONTH = 03;
+    private static final int SECURITY_PATCH_YEAR = 2016;
+    private static final int SECURITY_PATCH_MONTH = 12;
 
     private boolean mSkipTests = false;
 
diff --git a/tests/tests/security/src/android/security/cts/BrowserTest.java b/tests/tests/security/src/android/security/cts/BrowserTest.java
index 0948713..f468d66 100644
--- a/tests/tests/security/src/android/security/cts/BrowserTest.java
+++ b/tests/tests/security/src/android/security/cts/BrowserTest.java
@@ -172,7 +172,13 @@
 
             // do a file request
             intent.setData(Uri.fromFile(htmlFile));
-            mContext.startActivity(intent);
+
+            try {
+                mContext.startActivity(intent);
+            } catch (SecurityException e) {
+                // If browser activity cannot be started, skip the test.
+                continue;
+            }
 
             /*
              * Wait 5 seconds for the browser to contact the server, but
diff --git a/tests/tests/security/src/android/security/cts/DeviceIdleControllerTest.java b/tests/tests/security/src/android/security/cts/DeviceIdleControllerTest.java
new file mode 100644
index 0000000..0b183aa
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/DeviceIdleControllerTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.ServiceManager;
+import android.test.AndroidTestCase;
+
+import java.io.FileDescriptor;
+
+/**
+ * Check past exploits of DeviceIdleController.
+ */
+public class DeviceIdleControllerTest extends AndroidTestCase {
+    int mResult;
+
+    /**
+     * Verify that the command line interface can not be used to add an app to the whitelist.
+     */
+    public void testAddWhiteList() {
+        final IBinder service = ServiceManager.getService("deviceidle");
+        final Object mSync = new Object();
+        mResult = 0;
+        try {
+            service.shellCommand(FileDescriptor.in, FileDescriptor.out, FileDescriptor.err,
+                    new String[]{"whitelist", "+" + mContext.getPackageName()},
+                    new ResultReceiver(null) {
+                        @Override
+                        protected void onReceiveResult(int resultCode, Bundle resultData) {
+                            mResult = resultCode;
+                            synchronized (mSync) {
+                                mSync.notifyAll();
+                            }
+                        }
+                    });
+        } catch (RemoteException e) {
+        }
+        try {
+            synchronized (mSync) {
+                mSync.wait();
+            }
+        } catch (InterruptedException e) {
+        }
+        assertEquals(-1, mResult);
+        PowerManager pm = mContext.getSystemService(PowerManager.class);
+        assertFalse(pm.isIgnoringBatteryOptimizations(mContext.getPackageName()));
+    }
+}
+
diff --git a/tests/tests/security/src/android/security/cts/STKFrameworkTest.java b/tests/tests/security/src/android/security/cts/STKFrameworkTest.java
index 284ad82..a30387f 100644
--- a/tests/tests/security/src/android/security/cts/STKFrameworkTest.java
+++ b/tests/tests/security/src/android/security/cts/STKFrameworkTest.java
@@ -17,16 +17,16 @@
 
 import android.content.ComponentName;
 import android.content.Intent;
-import android.test.AndroidTestCase;
 import android.content.pm.PackageManager;
+import android.test.AndroidTestCase;
 
 public class STKFrameworkTest extends AndroidTestCase {
-   private boolean mHasTelephony;
+    private boolean mHasTelephony;
 
-   @Override
+    @Override
     protected void setUp() throws Exception {
         super.setUp();
-	mHasTelephony = getContext().getPackageManager().hasSystemFeature(
+        mHasTelephony = getContext().getPackageManager().hasSystemFeature(
                 PackageManager.FEATURE_TELEPHONY);
     }
 
@@ -41,10 +41,10 @@
      */
     public void testInterceptedSIMCommandsToTelephony() {
         if (!mHasTelephony) {
-		return;
-	}
+            return;
+        }
 
-	Intent intent = new Intent();
+        Intent intent = new Intent();
         intent.setAction("android.intent.action.stk.command");
         intent.putExtra("STK CMD", "test");
         ComponentName cn =
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutLaunchedActivity.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutLaunchedActivity.java
index 61f94d4..fdedc45 100644
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutLaunchedActivity.java
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutLaunchedActivity.java
@@ -22,7 +22,9 @@
 import android.util.Log;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
@@ -36,9 +38,14 @@
 
     private final int mInstanceId = sNextInstanceId.getAndIncrement();
 
-    // @GuardedBy("sReceivedIntents")
+    private static final Object sLock = new Object();
+
+    // @GuardedBy("sLock")
     private static final ArrayList<Intent> sReceivedIntents = new ArrayList<>();
 
+    // @GuardedBy("sLock")
+    private static final ArrayList<String> sExpectedVisibleOrder = new ArrayList<>();
+
     private Handler mHandler = new Handler();
 
     private Intent mIntentToAdd;
@@ -48,6 +55,10 @@
                 mInstanceId, action, getIntent()));
     }
 
+    public ShortcutLaunchedActivity() {
+        log("ctor");
+    }
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -63,22 +74,27 @@
 
         log("onResume");
 
-        synchronized (sReceivedIntents) {
+        synchronized (sLock) {
+            if (!Objects.equals(getIntent().getAction(), sExpectedVisibleOrder.get(0))) {
+                log("Not my turn yet.");
+                return;
+            }
+            sExpectedVisibleOrder.remove(0);
+
             // Make sure we only add it once, ever.
             if (mIntentToAdd != null) {
                 sReceivedIntents.add(new Intent(getIntent()));
                 mIntentToAdd = null;
             }
         }
-        mHandler.post(() -> {
-            onBackPressed();
-        });
+        finish();
     }
 
     @Override
-    public void onBackPressed() {
-        log("onBackPressed");
-        super.onBackPressed();
+    protected void onPause() {
+        log("onPause");
+
+        super.onPause();
     }
 
     @Override
@@ -88,14 +104,17 @@
         super.onDestroy();
     }
 
-    public static void clearIntents() {
-        synchronized (sReceivedIntents) {
+    public static void setExpectedOrder(String[] actions) {
+        synchronized (sLock) {
             sReceivedIntents.clear();
+
+            sExpectedVisibleOrder.clear();
+            sExpectedVisibleOrder.addAll(Arrays.asList(actions));
         }
     }
 
     public static List<Intent> getIntents() {
-        synchronized (sReceivedIntents) {
+        synchronized (sLock) {
             return new ArrayList(sReceivedIntents);
         }
     }
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerStartShortcutTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerStartShortcutTest.java
index e80b66e..9cf1f89 100644
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerStartShortcutTest.java
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerStartShortcutTest.java
@@ -20,7 +20,6 @@
 import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.retryUntil;
 import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.setDefaultLauncher;
 
-import android.app.ActivityOptions;
 import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
 import android.content.Context;
@@ -29,8 +28,6 @@
 import android.os.Bundle;
 import android.test.suitebuilder.annotation.SmallTest;
 
-import org.junit.internal.runners.statements.ExpectException;
-
 import java.util.List;
 
 @SmallTest
@@ -45,14 +42,16 @@
     }
 
     private List<Intent> launchShortcutAndGetIntents(Context launcher, Context client,
-            String id, int expectedNumIntents) {
-        return launchShortcutAndGetIntents(launcher, client, id, expectedNumIntents, null, null);
+            String id, int expectedNumIntents, String[] expectedActions) {
+        return launchShortcutAndGetIntents(launcher, client, id, expectedNumIntents, null, null,
+                expectedActions);
     }
 
     private List<Intent> launchShortcutAndGetIntents(Context launcher, Context client,
-            String id, int expectedNumIntents, Rect rect, Bundle options) {
+            String id, int expectedNumIntents, Rect rect, Bundle options,
+            String[] expectedActions) {
 
-        ShortcutLaunchedActivity.clearIntents();
+        ShortcutLaunchedActivity.setExpectedOrder(expectedActions);
 
         runWithCaller(launcher, () -> {
             getLauncherApps().startShortcut(client.getPackageName(), id, rect, options,
@@ -65,8 +64,10 @@
         return ShortcutLaunchedActivity.getIntents();
     }
 
-    private void assertShortcutStarts(Context launcher, Context client, String id) {
-        final List<Intent> launched = launchShortcutAndGetIntents(launcher, client, id, 1);
+    private void assertShortcutStarts(Context launcher, Context client, String id,
+            String[] expectedActions) {
+        final List<Intent> launched = launchShortcutAndGetIntents(launcher, client, id, 1,
+                expectedActions);
         assertTrue(launched.size() > 0);
     }
 
@@ -81,6 +82,9 @@
         });
     }
 
+    private static final String[] EXPECTED_ACTIONS_SINGLE = new String[]{Intent.ACTION_MAIN};
+    private static final String[] EXPECTED_ACTIONS_MULTI = new String[]{"a3", "a2", "a1"};
+
     /**
      * Start a single activity.
      */
@@ -100,7 +104,7 @@
         });
 
         List<Intent> launched = launchShortcutAndGetIntents(mLauncherContext1, mPackageContext1,
-                "s1", 1);
+                "s1", 1, EXPECTED_ACTIONS_SINGLE);
         assertEquals(1, launched.size());
         assertEquals(Intent.ACTION_MAIN, launched.get(0).getAction());
         assertTrue((launched.get(0).getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0);
@@ -132,7 +136,7 @@
         });
 
         List<Intent> launched = launchShortcutAndGetIntents(mLauncherContext1, mPackageContext1,
-                "s1", 3);
+                "s1", 3, EXPECTED_ACTIONS_MULTI);
         assertEquals(3, launched.size());
 
         Intent i = launched.get(2);
@@ -164,7 +168,8 @@
         setDefaultLauncher(getInstrumentation(), mLauncherContext2);
 
         // L2 can start it.
-        assertShortcutStarts(mLauncherContext2, mPackageContext1, "s1");
+        assertShortcutStarts(mLauncherContext2, mPackageContext1, "s1",
+                EXPECTED_ACTIONS_SINGLE);
 
         // L1 no longer can start it.
         assertShortcutCantStart(mLauncherContext1, mPackageContext1, "s1",
@@ -225,7 +230,7 @@
         });
 
         // Should still be launchable.
-        assertShortcutStarts(mLauncherContext1, mPackageContext1, "s1");
+        assertShortcutStarts(mLauncherContext1, mPackageContext1, "s1", EXPECTED_ACTIONS_SINGLE);
     }
 
     public void testPinnedShortcut_differentLauncher() {
@@ -249,7 +254,7 @@
         setDefaultLauncher(getInstrumentation(), mLauncherContext2);
 
         // L2 can now launch it.
-        assertShortcutStarts(mLauncherContext2, mPackageContext1, "s1");
+        assertShortcutStarts(mLauncherContext2, mPackageContext1, "s1", EXPECTED_ACTIONS_SINGLE);
 
         // Then remove it.
         runWithCaller(mPackageContext1, () -> {
@@ -261,14 +266,14 @@
                 ActivityNotFoundException.class);
 
         // But launcher 1 can still launch it too, because it's pinned by this launcher.
-        assertShortcutStarts(mLauncherContext1, mPackageContext1, "s1");
+        assertShortcutStarts(mLauncherContext1, mPackageContext1, "s1", EXPECTED_ACTIONS_SINGLE);
     }
 
     public void testStartSingleWithOptions() {
         testStartSingle();
 
         List<Intent> launched = launchShortcutAndGetIntents(mLauncherContext1, mPackageContext1,
-                "s1", 1, new Rect(1, 1, 2, 2), new Bundle());
+                "s1", 1, new Rect(1, 1, 2, 2), new Bundle(), EXPECTED_ACTIONS_SINGLE);
 
         Intent i = launched.get(0);
         assertEquals(1, i.getSourceBounds().left);
@@ -280,7 +285,7 @@
         testStartMultiple();
 
         List<Intent> launched = launchShortcutAndGetIntents(mLauncherContext1, mPackageContext1,
-                "s1", 3, new Rect(1, 1, 2, 2), new Bundle());
+                "s1", 3, new Rect(1, 1, 2, 2), new Bundle(), EXPECTED_ACTIONS_MULTI);
 
         Intent i = launched.get(2);
         assertEquals(1, i.getSourceBounds().left);
@@ -309,7 +314,7 @@
         assertExpectException(
                 ActivityNotFoundException.class, "Shortcut could not be started", () -> {
             launchShortcutAndGetIntents(mLauncherContext1, mPackageContext1,
-                    "s1", 1);
+                    "s1", 1, new String[0]);
         });
     }
 
@@ -334,7 +339,7 @@
         assertExpectException(
                 ActivityNotFoundException.class, "Shortcut could not be started", () -> {
                     launchShortcutAndGetIntents(mLauncherContext1, mPackageContext1,
-                            "s1", 1);
+                            "s1", 1, new String[0]);
                 });
     }
 }
diff --git a/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechTest.java b/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechTest.java
index 43b0fe3..c117745 100644
--- a/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechTest.java
+++ b/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechTest.java
@@ -144,6 +144,9 @@
     }
 
     public void testSpeakStop() throws Exception {
+        if (mTts == null) {
+            return;
+        }
         getTts().stop();
         final int iterations = 20;
         for (int i = 0; i < iterations; i++) {
diff --git a/tests/tests/systemintents/Android.mk b/tests/tests/systemintents/Android.mk
new file mode 100644
index 0000000..1af6702
--- /dev/null
+++ b/tests/tests/systemintents/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsSystemIntentTestCases
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+
+LOCAL_SDK_VERSION := test_current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/systemintents/AndroidManifest.xml b/tests/tests/systemintents/AndroidManifest.xml
new file mode 100644
index 0000000..da0cbac
--- /dev/null
+++ b/tests/tests/systemintents/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android.systemintents.cts">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="android.systemintents.cts"
+                     android:label="System intent tests"/>
+</manifest>
\ No newline at end of file
diff --git a/tests/tests/systemintents/AndroidTest.xml b/tests/tests/systemintents/AndroidTest.xml
new file mode 100644
index 0000000..eceb909
--- /dev/null
+++ b/tests/tests/systemintents/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<configuration description="Config for CTS system intent test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsSystemIntentTestCases.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.systemintents.cts" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/systemintents/src/android/systemintents/cts/TestSystemIntents.java b/tests/tests/systemintents/src/android/systemintents/cts/TestSystemIntents.java
new file mode 100644
index 0000000..c572629
--- /dev/null
+++ b/tests/tests/systemintents/src/android/systemintents/cts/TestSystemIntents.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.systemintents.cts;
+
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
+import android.net.Uri;
+import android.provider.Settings;
+import android.support.test.filters.MediumTest;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+@MediumTest
+public class TestSystemIntents extends AndroidTestCase {
+    /*
+     * List of activity intents defined by the system.  Activities to handle each of these
+     * intents must all exist.
+     *
+     * They are Intents here rather than simply action strings so that the test can
+     * easily accommodate data URIs or similar for correct resolution.
+     *
+     * The flags associated with each intent indicate kinds of device on which the given
+     * UI intent is *not* applicable.
+     */
+
+    private static final int EXCLUDE_TV = 1 << 0;
+    private static final int EXCLUDE_WATCH = 1 << 1;
+    private static final int EXCLUDE_NON_TELEPHONY = 1 << 2;
+
+    class IntentEntry {
+        public int flags;
+        public Intent intent;
+
+        public IntentEntry(int f, Intent i) {
+            flags = f;
+            intent = i;
+        }
+    }
+
+    @Rule
+    private final IntentEntry[] mTestIntents = {
+            /* Settings-namespace intent actions */
+            new IntentEntry(0, new Intent(Settings.ACTION_SETTINGS)),
+            new IntentEntry(0, new Intent(Settings.ACTION_WEBVIEW_SETTINGS)),
+            new IntentEntry(0, new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS)),
+            new IntentEntry(0, new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS)),
+            new IntentEntry(0, new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
+                    .setData(Uri.parse("package:android.systemintents.cts"))),
+            new IntentEntry(0, new Intent(Settings.ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS)
+                    .setData(Uri.parse("package:android.systemintents.cts"))),
+            new IntentEntry(0, new Intent(Settings.ACTION_HOME_SETTINGS)),
+            new IntentEntry(EXCLUDE_NON_TELEPHONY,
+                    new Intent(Settings.ACTION_APN_SETTINGS)),
+            new IntentEntry(EXCLUDE_TV|EXCLUDE_WATCH,
+                    new Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS))
+    };
+
+    @Test
+    public void testSystemIntents() {
+        final PackageManager pm = getContext().getPackageManager();
+        int productFlags = 0;
+
+        if (pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
+            productFlags |= EXCLUDE_TV;
+        }
+
+        if (!pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+            productFlags |= EXCLUDE_NON_TELEPHONY;
+        }
+
+        final Configuration config = getContext().getResources().getConfiguration();
+        if ((config.uiMode & Configuration.UI_MODE_TYPE_WATCH) != 0) {
+            productFlags |= EXCLUDE_WATCH;
+        }
+
+        for (IntentEntry e : mTestIntents) {
+            if ((productFlags & e.flags) == 0) {
+                final ResolveInfo ri = pm.resolveActivity(e.intent, PackageManager.MATCH_DEFAULT_ONLY);
+                assertTrue("API intent " + e.intent + " not implemented by any activity", ri != null);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java b/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java
index ff84655..d167249 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java
@@ -445,6 +445,10 @@
      * {@link android.telecom.Call.Callback#onDetailsChanged(Call, Call.Details)}.
      */
     public void testConnectionRemoveExtras() {
+        if (!mShouldTestTelecom) {
+            return;
+        }
+
         testConnectionPutExtras();
 
         mConnection.removeExtras(Arrays.asList(TEST_EXTRA_KEY));
@@ -458,6 +462,10 @@
      * {@link android.telecom.Call.Callback#onDetailsChanged(Call, Call.Details)}.
      */
     public void testConnectionRemoveExtras2() {
+        if (!mShouldTestTelecom) {
+            return;
+        }
+
         testConnectionPutExtras();
 
         mConnection.removeExtras(TEST_EXTRA_KEY);
diff --git a/tests/tests/telecom/src/android/telecom/cts/MockConference.java b/tests/tests/telecom/src/android/telecom/cts/MockConference.java
index d84610d..302f91f 100644
--- a/tests/tests/telecom/src/android/telecom/cts/MockConference.java
+++ b/tests/tests/telecom/src/android/telecom/cts/MockConference.java
@@ -143,6 +143,10 @@
 
     public void setRemoteConference(RemoteConference remoteConference) {
         mRemoteConference = remoteConference;
+        Bundle bundle = remoteConference.getExtras();
+        if (bundle != null) {
+            this.putExtras(bundle);
+        }
     }
 
     public RemoteConference getRemoteConference() {
@@ -155,6 +159,7 @@
 
     @Override
     public void onExtrasChanged(Bundle extras) {
+        setExtras(extras);
         mOnExtrasChanged.invoke(extras);
     }
 }
diff --git a/tests/tests/telecom/src/android/telecom/cts/RemoteConferenceTest.java b/tests/tests/telecom/src/android/telecom/cts/RemoteConferenceTest.java
index 3246b9c..57654f40 100644
--- a/tests/tests/telecom/src/android/telecom/cts/RemoteConferenceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/RemoteConferenceTest.java
@@ -455,7 +455,8 @@
         mRemoteConference.setExtras(extras);
         callbackInvoker.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
         assertEquals(mRemoteConferenceObject, callbackInvoker.getArgs(0)[0]);
-        assertTrue(areBundlesEqual(extras, (Bundle) callbackInvoker.getArgs(0)[1]));
+        assertTrue(((Bundle) callbackInvoker.getArgs(0)[1]).containsKey(
+                TelecomManager.EXTRA_CALL_DISCONNECT_MESSAGE));
         mRemoteConferenceObject.unregisterCallback(callback);
     }
 
@@ -469,8 +470,9 @@
             remoteConnections.add(((MockConnection)c).getRemoteConnection());
         }
         assertEquals(remoteConnections, remoteConferenceObject.getConnections());
-        assertEquals(remoteConference.getDisconnectCause(), remoteConferenceObject.getDisconnectCause());
-        assertEquals(remoteConference.getExtras(), remoteConferenceObject.getExtras());
+        assertEquals(remoteConference.getDisconnectCause(),
+                remoteConferenceObject.getDisconnectCause());
+        assertTrue(areBundlesEqual(remoteConferenceObject.getExtras(), conference.getExtras()));
     }
 
     private void addRemoteConnectionOutgoingCalls() {
@@ -572,7 +574,7 @@
             setupConnectionServices(managerConnectionService, remoteConnectionService,
                     FLAG_REGISTER | FLAG_ENABLE);
         } catch(Exception e) {
-            fail("Error in setting up the connection services");
+            fail("Error in setting up the connection services: " + e.toString());
         }
 
         placeAndVerifyCall();
diff --git a/tests/tests/telephony/src/android/telephony/cts/SmsMessageTest.java b/tests/tests/telephony/src/android/telephony/cts/SmsMessageTest.java
index 2406ad8..e247775 100644
--- a/tests/tests/telephony/src/android/telephony/cts/SmsMessageTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/SmsMessageTest.java
@@ -114,7 +114,7 @@
 
         // Test create from null Pdu
         sms = SmsMessage.createFromPdu(null, SmsMessage.FORMAT_3GPP);
-        assertNotNull(sms);
+        assertNull(sms);
 
         // Test create from long Pdu
         pdu = "07912160130310F2040B915121927786F300036060924180008A0DA"
diff --git a/tests/tests/toast/Android.mk b/tests/tests/toast/Android.mk
new file mode 100644
index 0000000..d9f15eb
--- /dev/null
+++ b/tests/tests/toast/Android.mk
@@ -0,0 +1,33 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsToastTestCases
+
+include $(BUILD_CTS_PACKAGE)
+
diff --git a/tests/tests/toast/AndroidManifest.xml b/tests/tests/toast/AndroidManifest.xml
new file mode 100644
index 0000000..1fa71c4
--- /dev/null
+++ b/tests/tests/toast/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="android.widget.toast.cts">
+
+    <uses-sdk android:minSdkVersion="25" android:targetSdkVersion="26" />
+
+    <application>
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.widget.toast.cts"
+        android:label="CTS tests for toast windows">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
+
+</manifest>
+
diff --git a/tests/tests/toast/AndroidTest.xml b/tests/tests/toast/AndroidTest.xml
new file mode 100644
index 0000000..d0a5eed
--- /dev/null
+++ b/tests/tests/toast/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for Toast test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsToastTestCases.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.widget.toast.cts" />
+    </test>
+</configuration>
diff --git a/tests/tests/toast/src/android/widget/toast/cts/BaseToastTest.java b/tests/tests/toast/src/android/widget/toast/cts/BaseToastTest.java
new file mode 100644
index 0000000..fd75309
--- /dev/null
+++ b/tests/tests/toast/src/android/widget/toast/cts/BaseToastTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.toast.cts;
+
+import android.app.Instrumentation;
+import android.app.UiAutomation;
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.os.SystemClock;
+import android.support.test.InstrumentationRegistry;
+import android.view.WindowManager;
+import android.widget.TextView;
+import android.widget.Toast;
+import org.junit.Before;
+
+/**
+ * Base class for toast tests.
+ */
+public abstract class BaseToastTest {
+    protected static final long TOAST_TIMEOUT_MILLIS = 5000; // 5 sec
+    protected static final long EVENT_TIMEOUT_MILLIS = 5000; // 5 sec
+
+    protected Context mContext;
+    protected Instrumentation mInstrumentation;
+    protected UiAutomation mUiAutomation;
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getContext();
+        mInstrumentation = InstrumentationRegistry.getInstrumentation();
+        mUiAutomation = mInstrumentation.getUiAutomation();
+        waitForToastTimeout();
+    }
+
+    protected void waitForToastTimeout() {
+        SystemClock.sleep(TOAST_TIMEOUT_MILLIS);
+    }
+
+    protected void showToastsViaToastApis(int count) throws Exception {
+        Exception[] exceptions = new Exception[1];
+        mInstrumentation.runOnMainSync(
+                () -> {
+                    try {
+                        for (int i = 0; i < count; i++) {
+                            Toast.makeText(mContext, getClass().getName(),
+                                    Toast.LENGTH_LONG).show();
+                        }
+                    } catch (Exception e) {
+                        exceptions[0] = e;
+                    }
+                });
+        if (exceptions[0] != null) {
+            throw exceptions[0];
+        }
+    }
+
+    protected void showToastsViaAddingWindow(int count, boolean focusable) throws Exception {
+        Exception[] exceptions = new Exception[1];
+        mInstrumentation.runOnMainSync(() -> {
+            try {
+                for (int i = 0; i < count; i++) {
+                    WindowManager.LayoutParams params = new WindowManager.LayoutParams();
+                    params.height = WindowManager.LayoutParams.WRAP_CONTENT;
+                    params.width = WindowManager.LayoutParams.WRAP_CONTENT;
+                    params.format = PixelFormat.TRANSLUCENT;
+                    params.type = WindowManager.LayoutParams.TYPE_TOAST;
+                    params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
+                    if (!focusable) {
+                        params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+                    }
+
+                    TextView textView = new TextView(mContext);
+                    textView.setText(BaseToastTest.class.getName());
+
+                    WindowManager windowManager = mContext
+                            .getSystemService(WindowManager.class);
+                    windowManager.addView(textView, params);
+                }
+            } catch (Exception e) {
+                exceptions[0] = e;
+            }
+        });
+        if (exceptions[0] != null) {
+            throw exceptions[0];
+        }
+    }
+}
diff --git a/tests/tests/toast/src/android/widget/toast/cts/LegacyToastTest.java b/tests/tests/toast/src/android/widget/toast/cts/LegacyToastTest.java
new file mode 100644
index 0000000..4ac88b3
--- /dev/null
+++ b/tests/tests/toast/src/android/widget/toast/cts/LegacyToastTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.toast.cts;
+
+import android.support.test.runner.AndroidJUnit4;
+import android.view.WindowManager;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.fail;
+
+/**
+ * Test whether toasts are properly shown. For apps targeting API 25+
+ * like this app the only way to add toast windows is via the dedicated
+ * toast APIs.
+ */
+@RunWith(AndroidJUnit4.class)
+public class LegacyToastTest extends BaseToastTest {
+    @Test
+    public void testAddSingleToastViaTestApisWhenUidFocused() throws Exception {
+        // Normal toast windows cannot be obtained vie the accessibility APIs because
+        // they are not touchable. In this case not crashing is good enough.
+        showToastsViaToastApis(1);
+    }
+
+    @Test
+    public void testAddTwoToastViaTestApisWhenUidFocused() throws Exception {
+        // Normal toast windows cannot be obtained vie the accessibility APIs because
+        // they are not touchable. In this case not crashing is good enough.
+        showToastsViaToastApis(2);
+
+        // Wait for the first one to expire
+        waitForToastTimeout();
+    }
+
+    @Test
+    public void testAddSingleToastViaAddingWindowApisWhenUidFocused() throws Exception {
+        try {
+            showToastsViaAddingWindow(1, false);
+            fail("Shouldn't be able to add toast windows directly");
+        } catch (WindowManager.BadTokenException e) {
+            /* expected */
+        }
+    }
+}
diff --git a/tests/tests/toastlegacy/Android.mk b/tests/tests/toastlegacy/Android.mk
new file mode 100644
index 0000000..ac5825d
--- /dev/null
+++ b/tests/tests/toastlegacy/Android.mk
@@ -0,0 +1,34 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+    ../toast/src/android/widget/toast/cts/BaseToastTest.java
+
+LOCAL_PACKAGE_NAME := CtsToastLegacyTestCases
+
+include $(BUILD_CTS_PACKAGE)
+
diff --git a/tests/tests/toastlegacy/AndroidManifest.xml b/tests/tests/toastlegacy/AndroidManifest.xml
new file mode 100644
index 0000000..8529b5c
--- /dev/null
+++ b/tests/tests/toastlegacy/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="android.widget.toast.legacy.cts">
+
+    <uses-sdk android:minSdkVersion="25" android:targetSdkVersion="25" />
+
+    <application>
+        <activity android:name="android.widget.toast.cts.legacy.ToastActivity">
+        </activity>
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.widget.toast.legacy.cts"
+        android:label="CTS tests for legacy toast windows">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
+
+</manifest>
+
diff --git a/tests/tests/toastlegacy/AndroidTest.xml b/tests/tests/toastlegacy/AndroidTest.xml
new file mode 100644
index 0000000..a208077
--- /dev/null
+++ b/tests/tests/toastlegacy/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for Toast legacy test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsToastLegacyTestCases.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.widget.toast.legacy.cts" />
+    </test>
+</configuration>
diff --git a/tests/tests/toastlegacy/src/android/widget/toast/cts/legacy/ToastActivity.java b/tests/tests/toastlegacy/src/android/widget/toast/cts/legacy/ToastActivity.java
new file mode 100644
index 0000000..745385e
--- /dev/null
+++ b/tests/tests/toastlegacy/src/android/widget/toast/cts/legacy/ToastActivity.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.toast.cts.legacy;
+
+import android.app.Activity;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * Activity that shows toasts on demand.
+ */
+public class ToastActivity extends Activity {
+
+    @Override
+    public void onCreate(Bundle bundle) {
+        super.onCreate(bundle);
+        View view = new View(this);
+        view.setBackgroundColor(Color.BLUE);
+        view.setLayoutParams(new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.MATCH_PARENT));
+        setContentView(view);
+    }
+}
diff --git a/tests/tests/toastlegacy/src/android/widget/toast/cts/legacy/ToastTest.java b/tests/tests/toastlegacy/src/android/widget/toast/cts/legacy/ToastTest.java
new file mode 100644
index 0000000..207e6ea
--- /dev/null
+++ b/tests/tests/toastlegacy/src/android/widget/toast/cts/legacy/ToastTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.toast.cts.legacy;
+
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.WindowManager;
+import android.view.accessibility.AccessibilityEvent;
+import android.widget.toast.cts.BaseToastTest;
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test whether toasts are properly shown. For apps targeting SDK
+ * 25 and below a toast window can be added via the window APIs
+ * but it will be removed after a timeout if the UID that added
+ * the window is not focused. Also only a single toast window
+ * is allowed at a time.
+ */
+@RunWith(AndroidJUnit4.class)
+public class ToastTest extends BaseToastTest {
+    @Rule
+    public final ActivityTestRule<ToastActivity> mActivityRule =
+            new ActivityTestRule<>(ToastActivity.class);
+
+    @Test
+    public void testAddSingleNotFocusableToastViaAddingWindowApisWhenUidFocused() throws Exception {
+        // Show a toast on top of the focused activity
+        showToastsViaAddingWindow(1, false);
+
+        // Wait for the toast to timeout
+        waitForToastTimeout();
+
+        // Finish the activity so the UID loses focus
+        finishActivity(false);
+
+        // Wait for the toast to timeout
+        waitForToastTimeout();
+
+        // Show another toast
+        showToastsViaAddingWindow(1, false);
+    }
+
+    @Test
+    public void testAddSingleFocusableToastViaAddingWindowApisWhenUidFocused() throws Exception {
+        // Show a toast on top of our activity
+        showToastsViaAddingWindow(1, true);
+
+        // Wait for the toast to timeout
+        waitForToastTimeout();
+
+        // Show a toast on top of our activity
+        showToastsViaAddingWindow(1, true);
+    }
+
+    @Test
+    public void testAddSingleToastViaAddingWindowApisWhenUidNotFocused() throws Exception {
+        // Finish the activity so the UID loses focus
+        finishActivity(false);
+
+        // Show a toast
+        showToastsViaAddingWindow(1, true);
+
+        // Wait for the toast to timeout
+        waitForToastTimeout();
+
+        // Show a toast on top of our activity
+        showToastsViaAddingWindow(1, true);
+    }
+
+    @Test
+    public void testAddTwoToastsViaToastApisWhenUidFocused() throws Exception {
+        // Finish the activity so the UID loses focus
+        finishActivity(false);
+
+        // Normal toast windows cannot be obtained vie the accessibility APIs because
+        // they are not touchable. In this case not crashing is good enough.
+        showToastsViaToastApis(2);
+
+        // Wait for the first one to expire
+        waitForToastTimeout();
+    }
+
+    @Test
+    public void testAddTwoToastsViaToastApisWhenUidNotFocused() throws Exception {
+        // Normal toast windows cannot be obtained vie the accessibility APIs because
+        // they are not touchable. In this case not crashing is good enough.
+        showToastsViaToastApis(2);
+
+        // Wait for the first one to expire
+        waitForToastTimeout();
+    }
+
+    @Test
+    public void testAddTwoToastsViaAddingWindowApisWhenUidFocusedQuickly() throws Exception {
+        try {
+            showToastsViaAddingWindow(2, false);
+            Assert.fail("Only one custom toast window at a time should be allowed");
+        } catch (WindowManager.BadTokenException e) {
+            /* expected */
+        } catch (Exception ex) {
+            Assert.fail("Unexpected exception when adding second toast window" + ex);
+        }
+    }
+
+    @Test
+    public void testAddTwoToastsViaAddingWindowApisWhenUidFocusedSlowly() throws Exception {
+        // Add one window
+        showToastsViaAddingWindow(1, true);
+
+        // Wait for the toast to timeout
+        waitForToastTimeout();
+
+        // Add another window
+        showToastsViaAddingWindow(1, true);
+    }
+
+    private void finishActivity(boolean waitForEvent) throws Exception {
+        if (waitForEvent) {
+            mUiAutomation.executeAndWaitForEvent(
+                    () -> mActivityRule.getActivity().finish(),
+                    (event) -> event.getEventType() == AccessibilityEvent.TYPE_WINDOWS_CHANGED
+                    , EVENT_TIMEOUT_MILLIS);
+        } else {
+            mActivityRule.getActivity().finish();
+        }
+    }
+}
diff --git a/tests/tests/transition/src/android/transition/cts/BaseTransitionTest.java b/tests/tests/transition/src/android/transition/cts/BaseTransitionTest.java
index 944ff91..a3a8cad 100644
--- a/tests/tests/transition/src/android/transition/cts/BaseTransitionTest.java
+++ b/tests/tests/transition/src/android/transition/cts/BaseTransitionTest.java
@@ -27,7 +27,9 @@
 import android.view.Choreographer.FrameCallback;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
 import android.widget.FrameLayout;
+import junit.framework.Assert;
 
 import java.util.ArrayList;
 import java.util.concurrent.CountDownLatch;
@@ -139,13 +141,31 @@
     }
 
     protected void enterScene(final Scene scene) throws Throwable {
-        runTestOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                scene.enter();
-            }
+        final CountDownLatch latch = new CountDownLatch(1);
+
+        runTestOnUiThread(() -> {
+            final ViewTreeObserver.OnGlobalLayoutListener listener =
+                    new ViewTreeObserver.OnGlobalLayoutListener() {
+                @Override
+                public void onGlobalLayout() {
+                    mActivity.getWindow().getDecorView().
+                            getViewTreeObserver().removeOnGlobalLayoutListener(this);
+                    latch.countDown();
+                }
+            };
+
+            mActivity.getWindow().getDecorView().
+                    getViewTreeObserver().addOnGlobalLayoutListener(listener);
+
+            scene.enter();
         });
-        getInstrumentation().waitForIdleSync();
+
+        try {
+            Assert.assertTrue("Expected layout pass within 5 seconds",
+                    latch.await(5, TimeUnit.SECONDS));
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        }
     }
 
     protected void exitScene(final Scene scene) throws Throwable {
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 42c2225..d03cbfc 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java
@@ -160,7 +160,8 @@
                 mView.postInvalidate();
             } else {
                 synchronized (mLock) {
-                    mLock.set(mViewWrapper.getLeft(), mViewWrapper.getTop());
+                    final int[] locationOnScreen = mViewWrapper.getLocationOnScreen();
+                    mLock.set(locationOnScreen[0], locationOnScreen[1]);
                     mLock.notify();
                 }
                 mView.getViewTreeObserver().removeOnPreDrawListener(this);
diff --git a/tests/tests/view/AndroidManifest.xml b/tests/tests/view/AndroidManifest.xml
index ba1f3d2..43a448a 100644
--- a/tests/tests/view/AndroidManifest.xml
+++ b/tests/tests/view/AndroidManifest.xml
@@ -19,6 +19,8 @@
     package="android.view.cts">
 
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
     <application android:label="Android TestCase"
                 android:icon="@drawable/size_48x48"
                 android:maxRecents="1"
@@ -239,8 +241,18 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="android.view.cts.DragDropActivity"
+                  android:label="DragDropActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
         <activity android:name="android.view.cts.surfacevalidator.CapturedActivity"
-                  android:theme="@style/WhiteBackgroundTheme">
+            android:configChanges="orientation|screenSize"
+            android:screenOrientation="portrait"
+            android:theme="@style/WhiteBackgroundTheme">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
diff --git a/tests/tests/view/res/layout/drag_drop_layout.xml b/tests/tests/view/res/layout/drag_drop_layout.xml
new file mode 100644
index 0000000..3800d99
--- /dev/null
+++ b/tests/tests/view/res/layout/drag_drop_layout.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<LinearLayout
+        android:id="@+id/drag_drop_activity_main"
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+    <FrameLayout
+            android:id="@+id/container"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_margin="64px"
+            android:background="#BBBBBB">
+        <FrameLayout
+                android:id="@+id/subcontainer"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_margin="64px"
+                android:background="#666666">
+            <View
+                    android:id="@+id/inner"
+                    android:layout_width="64px"
+                    android:layout_height="64px"
+                    android:layout_margin="64px"
+                    android:background="#00FF00" />
+        </FrameLayout>
+    </FrameLayout>
+    <View
+            android:id="@+id/draggable"
+            android:layout_width="64px"
+            android:layout_height="64px"
+            android:layout_margin="64px"
+            android:background="#0000FF" />
+</LinearLayout>
diff --git a/tests/tests/view/src/android/view/animation/cts/AnimatorInflaterTest.java b/tests/tests/view/src/android/view/animation/cts/AnimatorInflaterTest.java
index 3851e94..e8cd62c 100644
--- a/tests/tests/view/src/android/view/animation/cts/AnimatorInflaterTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/AnimatorInflaterTest.java
@@ -128,6 +128,7 @@
         WindowManager mWindowManager = (WindowManager) getActivity()
                 .getSystemService(Context.WINDOW_SERVICE);
         Display display = mWindowManager.getDefaultDisplay();
+        int orientation = getActivity().getResources().getConfiguration().orientation;
 
         Instrumentation.ActivityMonitor monitor = new Instrumentation.ActivityMonitor(
                 getActivity().getClass().getName(), null, false);
@@ -160,6 +161,10 @@
             Log.e(TAG, "New activity orientation does not match. Canceling test");
             return false;
         }
+        if (getActivity().getResources().getConfiguration().orientation == orientation) {
+            Log.e(TAG, "Screen orientation didn't change, test is canceled");
+            return false;
+        }
         return true;
     }
 
diff --git a/tests/tests/view/src/android/view/cts/DragDropActivity.java b/tests/tests/view/src/android/view/cts/DragDropActivity.java
new file mode 100644
index 0000000..b4324e3
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/DragDropActivity.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.cts;
+
+import android.view.cts.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class DragDropActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.drag_drop_layout);
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/view/src/android/view/cts/DragDropTest.java b/tests/tests/view/src/android/view/cts/DragDropTest.java
new file mode 100644
index 0000000..968dc7b
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/DragDropTest.java
@@ -0,0 +1,592 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.cts;
+
+import com.android.internal.util.ArrayUtils;
+
+import android.app.Instrumentation;
+import android.app.UiAutomation;
+import android.content.pm.PackageManager;
+import android.os.SystemClock;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.DragEvent;
+import android.view.InputDevice;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.InterruptedException;
+import java.lang.StringBuilder;
+import java.lang.Thread;
+import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.Objects;
+
+import static junit.framework.TestCase.*;
+
+@RunWith(AndroidJUnit4.class)
+public class DragDropTest {
+    static final String TAG = "DragDropTest";
+
+    final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
+    final UiAutomation mAutomation = mInstrumentation.getUiAutomation();
+
+    @Rule
+    public ActivityTestRule<DragDropActivity> mActivityRule =
+            new ActivityTestRule<>(DragDropActivity.class);
+
+    private DragDropActivity mActivity;
+
+    private CountDownLatch mEndReceived;
+
+    static boolean equal(DragEvent ev1, DragEvent ev2) {
+        return ev1.getAction() == ev2.getAction() &&
+                ev1.getX() == ev2.getX() &&
+                ev1.getY() == ev2.getY() &&
+                Objects.equals(ev1.getClipData(), ev2.getClipData()) &&
+                Objects.equals(ev1.getClipDescription(), ev2.getClipDescription()) &&
+                Objects.equals(ev1.getDragAndDropPermissions(), ev2.getDragAndDropPermissions()) &&
+                Objects.equals(ev1.getLocalState(), ev2.getLocalState()) &&
+                ev1.getResult() == ev2.getResult();
+    }
+
+    class LogEntry {
+        public View v;
+        public DragEvent ev;
+
+        public LogEntry(View v, DragEvent ev) {
+            this.v = v;
+            this.ev = DragEvent.obtain(ev);
+        }
+
+        public boolean eq(LogEntry other) {
+            return v == other.v && equal(ev, other.ev);
+        }
+    }
+
+    // Actual and expected sequences of events.
+    // While the test is running, logs should be accessed only from the main thread.
+    final private ArrayList<LogEntry> mActual = new ArrayList<LogEntry> ();
+    final private ArrayList<LogEntry> mExpected = new ArrayList<LogEntry> ();
+
+    static private DragEvent obtainDragEvent(int action, int x, int y, boolean result) {
+        return DragEvent.obtain(action, x, y, null, null, null, null, result);
+    }
+
+    private void logEvent(View v, DragEvent ev) {
+        if (ev.getAction() == DragEvent.ACTION_DRAG_ENDED) {
+            mEndReceived.countDown();
+        }
+        mActual.add(new LogEntry(v, ev));
+    }
+
+    // Add expected event for a view, with zero coordinates.
+    private void expectEvent5(int action, int viewId) {
+        View v = mActivity.findViewById(viewId);
+        mExpected.add(new LogEntry(v, obtainDragEvent(action, 0, 0, false)));
+    }
+
+    // Add expected event for a view.
+    private void expectEndEvent(int viewId, int x, int y, boolean result) {
+        View v = mActivity.findViewById(viewId);
+        mExpected.add(new LogEntry(v, obtainDragEvent(DragEvent.ACTION_DRAG_ENDED, x, y, result)));
+    }
+
+    // Add expected successful-end event for a view.
+    private void expectEndEventSuccess(int viewId) {
+        expectEndEvent(viewId, 0, 0, true);
+    }
+
+    // Add expected failed-end event for a view, with the release coordinates shifted by 6 relative
+    // to the left-upper corner of a view with id releaseViewId.
+    private void expectEndEventFailure6(int viewId, int releaseViewId) {
+        View v = mActivity.findViewById(viewId);
+        View release = mActivity.findViewById(releaseViewId);
+        int [] releaseLoc = release.getLocationOnScreen();
+        mExpected.add(new LogEntry(v, obtainDragEvent(DragEvent.ACTION_DRAG_ENDED,
+                releaseLoc[0] + 6, releaseLoc[1] + 6, false)));
+    }
+
+    // Add expected event for a view, with coordinates over view locationViewId, with the specified
+    // offset from the location view's upper-left corner.
+    private void expectEventWithOffset(int action, int viewId, int locationViewId, int offset) {
+        View v = mActivity.findViewById(viewId);
+        View locationView = mActivity.findViewById(locationViewId);
+        int [] viewLocation = v.getLocationOnScreen();
+        int [] locationViewLocation = locationView.getLocationOnScreen();
+        mExpected.add(new LogEntry(v, obtainDragEvent(action,
+                locationViewLocation[0] - viewLocation[0] + offset,
+                locationViewLocation[1] - viewLocation[1] + offset, false)));
+    }
+
+    private void expectEvent5(int action, int viewId, int locationViewId) {
+        expectEventWithOffset(action, viewId, locationViewId, 5);
+    }
+
+    // See comment for injectMouse6 on why we need both *5 and *6 methods.
+    private void expectEvent6(int action, int viewId, int locationViewId) {
+        expectEventWithOffset(action, viewId, locationViewId, 6);
+    }
+
+    // Inject mouse event over a given view, with specified offset from its left-upper corner.
+    private void injectMouseWithOffset(int viewId, int action, int offset) {
+        runOnMain(() -> {
+            View v = mActivity.findViewById(viewId);
+            int [] destLoc = v.getLocationOnScreen();
+            long downTime = SystemClock.uptimeMillis();
+            MotionEvent event = MotionEvent.obtain(downTime, downTime, action,
+                    destLoc[0] + offset, destLoc[1] + offset, 1);
+            event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+            mAutomation.injectInputEvent(event, false);
+        });
+
+        // Wait till the mouse event generates drag events. Also, some waiting needed because the
+        // system seems to collapse too frequent mouse events.
+        try {
+            Thread.sleep(100);
+        } catch (Exception e) {
+            fail("Exception while wait: " + e);
+        }
+    }
+
+    // Inject mouse event over a given view, with offset 5 from its left-upper corner.
+    private void injectMouse5(int viewId, int action) {
+        injectMouseWithOffset(viewId, action, 5);
+    }
+
+    // Inject mouse event over a given view, with offset 6 from its left-upper corner.
+    // We need both injectMouse5 and injectMouse6 if we want to inject 2 events in a row in the same
+    // view, and want them to produce distinct drag events or simply drag events with different
+    // coordinates.
+    private void injectMouse6(int viewId, int action) {
+        injectMouseWithOffset(viewId, action, 6);
+    }
+
+    private String logToString(ArrayList<LogEntry> log) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < log.size(); ++i) {
+            LogEntry e = log.get(i);
+            sb.append("#").append(i + 1).append(": ").append(e.ev).append(" @ ").
+                    append(e.v.toString()).append('\n');
+        }
+        return sb.toString();
+    }
+
+    private void failWithLogs(String message) {
+        fail(message + ":\nExpected event sequence:\n" + logToString(mExpected) +
+                "\nActual event sequence:\n" + logToString(mActual));
+    }
+
+    private void verifyEventLog() {
+        try {
+            assertTrue("Timeout while waiting for END event",
+                    mEndReceived.await(1, TimeUnit.SECONDS));
+        } catch (InterruptedException e) {
+            fail("Got InterruptedException while waiting for END event");
+        }
+
+        // Verify the log.
+        runOnMain(() -> {
+            if (mExpected.size() != mActual.size()) {
+                failWithLogs("Actual log has different size than expected");
+            }
+
+            for (int i = 0; i < mActual.size(); ++i) {
+                if (!mActual.get(i).eq(mExpected.get(i))) {
+                    failWithLogs("Actual event #" + (i + 1) + " is different from expected");
+                }
+            }
+        });
+    }
+
+    private boolean init() {
+        // Only run for non-watch devices
+        if (mActivity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Before
+    public void setUp() {
+        mActivity = mActivityRule.getActivity();
+        mEndReceived = new CountDownLatch(1);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        mActual.clear();
+        mExpected.clear();
+    }
+
+    // Sets handlers on all views in a tree, which log the event and return false.
+    private void setRejectingHandlersOnTree(View v) {
+        v.setOnDragListener((_v, ev) -> {
+            logEvent(_v, ev);
+            return false;
+        });
+
+        if (v instanceof ViewGroup) {
+            ViewGroup group = (ViewGroup) v;
+            for (int i = 0; i < group.getChildCount(); ++i) {
+                setRejectingHandlersOnTree(group.getChildAt(i));
+            }
+        }
+    }
+
+    private void runOnMain(Runnable runner) {
+        mInstrumentation.runOnMainSync(runner);
+    }
+
+    private void startDrag() {
+        // Mouse down. Required for the drag to start.
+        injectMouse5(R.id.draggable, MotionEvent.ACTION_DOWN);
+
+        runOnMain(() -> {
+            // Start drag.
+            View v = mActivity.findViewById(R.id.draggable);
+            assertTrue("Couldn't start drag",
+                    v.startDragAndDrop(null, new View.DragShadowBuilder(v), null, 0));
+        });
+    }
+
+    /**
+     * Tests that no drag-drop events are sent to views that aren't supposed to receive them.
+     */
+    @Test
+    public void testNoExtraEvents() throws Exception {
+        if (!init()) {
+            return;
+        }
+
+        runOnMain(() -> {
+            // Tell all views in layout to return false to all events, and log them.
+            setRejectingHandlersOnTree(mActivity.findViewById(R.id.drag_drop_activity_main));
+
+            // Override handlers for the inner view and its parent to return true.
+            mActivity.findViewById(R.id.inner).setOnDragListener((v, ev) -> {
+                logEvent(v, ev);
+                return true;
+            });
+            mActivity.findViewById(R.id.subcontainer).setOnDragListener((v, ev) -> {
+                logEvent(v, ev);
+                return true;
+            });
+        });
+
+        startDrag();
+
+        // Move mouse to the outmost view. This shouldn't generate any events since it returned
+        // false to STARTED.
+        injectMouse5(R.id.container, MotionEvent.ACTION_MOVE);
+        // Release mouse over the inner view. This produces DROP there.
+        injectMouse5(R.id.inner, MotionEvent.ACTION_UP);
+
+        expectEvent5(DragEvent.ACTION_DRAG_STARTED, R.id.inner, R.id.draggable);
+        expectEvent5(DragEvent.ACTION_DRAG_STARTED, R.id.subcontainer, R.id.draggable);
+        expectEvent5(DragEvent.ACTION_DRAG_STARTED, R.id.container, R.id.draggable);
+        expectEvent5(DragEvent.ACTION_DRAG_STARTED, R.id.draggable, R.id.draggable);
+        expectEvent5(DragEvent.ACTION_DRAG_STARTED, R.id.drag_drop_activity_main, R.id.draggable);
+
+        expectEvent5(DragEvent.ACTION_DRAG_ENTERED, R.id.inner);
+        expectEvent5(DragEvent.ACTION_DROP, R.id.inner, R.id.inner);
+
+        expectEndEventSuccess(R.id.inner);
+        expectEndEventSuccess(R.id.subcontainer);
+
+        verifyEventLog();
+    }
+
+    /**
+     * Tests events over a non-accepting view with an accepting child get delivered to that view's
+     * parent.
+     */
+    @Test
+    public void testBlackHole() throws Exception {
+        if (!init()) {
+            return;
+        }
+
+        runOnMain(() -> {
+            // Accepting child.
+            mActivity.findViewById(R.id.inner).setOnDragListener((v, ev) -> {
+                logEvent(v, ev);
+                return true;
+            });
+            // Non-accepting parent of that child.
+            mActivity.findViewById(R.id.subcontainer).setOnDragListener((v, ev) -> {
+                logEvent(v, ev);
+                return false;
+            });
+            // Accepting parent of the previous view.
+            mActivity.findViewById(R.id.container).setOnDragListener((v, ev) -> {
+                logEvent(v, ev);
+                return true;
+            });
+        });
+
+        startDrag();
+
+        // Move mouse to the non-accepting view.
+        injectMouse5(R.id.subcontainer, MotionEvent.ACTION_MOVE);
+        // Release mouse over the non-accepting view, with different coordinates.
+        injectMouse6(R.id.subcontainer, MotionEvent.ACTION_UP);
+
+        expectEvent5(DragEvent.ACTION_DRAG_STARTED, R.id.inner, R.id.draggable);
+        expectEvent5(DragEvent.ACTION_DRAG_STARTED, R.id.subcontainer, R.id.draggable);
+        expectEvent5(DragEvent.ACTION_DRAG_STARTED, R.id.container, R.id.draggable);
+
+        expectEvent5(DragEvent.ACTION_DRAG_ENTERED, R.id.container);
+        expectEvent5(DragEvent.ACTION_DRAG_LOCATION, R.id.container, R.id.subcontainer);
+        expectEvent6(DragEvent.ACTION_DROP, R.id.container, R.id.subcontainer);
+
+        expectEndEventSuccess(R.id.inner);
+        expectEndEventSuccess(R.id.container);
+
+        verifyEventLog();
+    }
+
+    /**
+     * Tests generation of ENTER/EXIT events.
+     */
+    @Test
+    public void testEnterExit() throws Exception {
+        if (!init()) {
+            return;
+        }
+
+        runOnMain(() -> {
+            // The setup is same as for testBlackHole.
+
+            // Accepting child.
+            mActivity.findViewById(R.id.inner).setOnDragListener((v, ev) -> {
+                logEvent(v, ev);
+                return true;
+            });
+            // Non-accepting parent of that child.
+            mActivity.findViewById(R.id.subcontainer).setOnDragListener((v, ev) -> {
+                logEvent(v, ev);
+                return false;
+            });
+            // Accepting parent of the previous view.
+            mActivity.findViewById(R.id.container).setOnDragListener((v, ev) -> {
+                logEvent(v, ev);
+                return true;
+            });
+
+        });
+
+        startDrag();
+
+        // Move mouse to the non-accepting view, then to the inner one, then back to the
+        // non-accepting view, then release over the inner.
+        injectMouse5(R.id.subcontainer, MotionEvent.ACTION_MOVE);
+        injectMouse5(R.id.inner, MotionEvent.ACTION_MOVE);
+        injectMouse5(R.id.subcontainer, MotionEvent.ACTION_MOVE);
+        injectMouse5(R.id.inner, MotionEvent.ACTION_UP);
+
+        expectEvent5(DragEvent.ACTION_DRAG_STARTED, R.id.inner, R.id.draggable);
+        expectEvent5(DragEvent.ACTION_DRAG_STARTED, R.id.subcontainer, R.id.draggable);
+        expectEvent5(DragEvent.ACTION_DRAG_STARTED, R.id.container, R.id.draggable);
+
+        expectEvent5(DragEvent.ACTION_DRAG_ENTERED, R.id.container);
+        expectEvent5(DragEvent.ACTION_DRAG_LOCATION, R.id.container, R.id.subcontainer);
+        expectEvent5(DragEvent.ACTION_DRAG_EXITED, R.id.container);
+
+        expectEvent5(DragEvent.ACTION_DRAG_ENTERED, R.id.inner);
+        expectEvent5(DragEvent.ACTION_DRAG_LOCATION, R.id.inner, R.id.inner);
+        expectEvent5(DragEvent.ACTION_DRAG_EXITED, R.id.inner);
+
+        expectEvent5(DragEvent.ACTION_DRAG_ENTERED, R.id.container);
+        expectEvent5(DragEvent.ACTION_DRAG_LOCATION, R.id.container, R.id.subcontainer);
+        expectEvent5(DragEvent.ACTION_DRAG_EXITED, R.id.container);
+
+        expectEvent5(DragEvent.ACTION_DRAG_ENTERED, R.id.inner);
+        expectEvent5(DragEvent.ACTION_DROP, R.id.inner, R.id.inner);
+
+        expectEndEventSuccess(R.id.inner);
+        expectEndEventSuccess(R.id.container);
+
+        verifyEventLog();
+    }
+    /**
+     * Tests events over a non-accepting view that has no accepting ancestors.
+     */
+    @Test
+    public void testOverNowhere() throws Exception {
+        if (!init()) {
+            return;
+        }
+
+        runOnMain(() -> {
+            // Accepting child.
+            mActivity.findViewById(R.id.inner).setOnDragListener((v, ev) -> {
+                logEvent(v, ev);
+                return true;
+            });
+            // Non-accepting parent of that child.
+            mActivity.findViewById(R.id.subcontainer).setOnDragListener((v, ev) -> {
+                logEvent(v, ev);
+                return false;
+            });
+        });
+
+        startDrag();
+
+        // Move mouse to the non-accepting view, then to accepting view, and back, and drop there.
+        injectMouse5(R.id.subcontainer, MotionEvent.ACTION_MOVE);
+        injectMouse5(R.id.inner, MotionEvent.ACTION_MOVE);
+        injectMouse5(R.id.subcontainer, MotionEvent.ACTION_MOVE);
+        injectMouse6(R.id.subcontainer, MotionEvent.ACTION_UP);
+
+        expectEvent5(DragEvent.ACTION_DRAG_STARTED, R.id.inner, R.id.draggable);
+        expectEvent5(DragEvent.ACTION_DRAG_STARTED, R.id.subcontainer, R.id.draggable);
+
+        expectEvent5(DragEvent.ACTION_DRAG_ENTERED, R.id.inner);
+        expectEvent5(DragEvent.ACTION_DRAG_LOCATION, R.id.inner, R.id.inner);
+        expectEvent5(DragEvent.ACTION_DRAG_EXITED, R.id.inner);
+
+        expectEndEventFailure6(R.id.inner, R.id.subcontainer);
+
+        verifyEventLog();
+    }
+
+    /**
+     * Tests that events are properly delivered to a view that is in the middle of the accepting
+     * hierarchy.
+     */
+    @Test
+    public void testAcceptingGroupInTheMiddle() throws Exception {
+        if (!init()) {
+            return;
+        }
+
+        runOnMain(() -> {
+            // Set accepting handlers to the inner view and its 2 ancestors.
+            mActivity.findViewById(R.id.inner).setOnDragListener((v, ev) -> {
+                logEvent(v, ev);
+                return true;
+            });
+            mActivity.findViewById(R.id.subcontainer).setOnDragListener((v, ev) -> {
+                logEvent(v, ev);
+                return true;
+            });
+            mActivity.findViewById(R.id.container).setOnDragListener((v, ev) -> {
+                logEvent(v, ev);
+                return true;
+            });
+        });
+
+        startDrag();
+
+        // Move mouse to the outmost container, then move to the subcontainer and drop there.
+        injectMouse5(R.id.container, MotionEvent.ACTION_MOVE);
+        injectMouse5(R.id.subcontainer, MotionEvent.ACTION_MOVE);
+        injectMouse6(R.id.subcontainer, MotionEvent.ACTION_UP);
+
+        expectEvent5(DragEvent.ACTION_DRAG_STARTED, R.id.inner, R.id.draggable);
+        expectEvent5(DragEvent.ACTION_DRAG_STARTED, R.id.subcontainer, R.id.draggable);
+        expectEvent5(DragEvent.ACTION_DRAG_STARTED, R.id.container, R.id.draggable);
+
+        expectEvent5(DragEvent.ACTION_DRAG_ENTERED, R.id.container);
+        expectEvent5(DragEvent.ACTION_DRAG_LOCATION, R.id.container, R.id.container);
+        expectEvent5(DragEvent.ACTION_DRAG_EXITED, R.id.container);
+
+        expectEvent5(DragEvent.ACTION_DRAG_ENTERED, R.id.subcontainer);
+        expectEvent5(DragEvent.ACTION_DRAG_LOCATION, R.id.subcontainer, R.id.subcontainer);
+        expectEvent6(DragEvent.ACTION_DROP, R.id.subcontainer, R.id.subcontainer);
+
+        expectEndEventSuccess(R.id.inner);
+        expectEndEventSuccess(R.id.subcontainer);
+        expectEndEventSuccess(R.id.container);
+
+        verifyEventLog();
+    }
+
+    /**
+     * Tests that state_drag_hovered and state_drag_can_accept are set correctly.
+     */
+    @Test
+    public void testDrawableState() throws Exception {
+        if (!init()) {
+            return;
+        }
+
+        runOnMain(() -> {
+            // Set accepting handler for the inner view.
+            mActivity.findViewById(R.id.inner).setOnDragListener((v, ev) -> {
+                logEvent(v, ev);
+                return true;
+            });
+            assertFalse(ArrayUtils.contains(
+                    mActivity.findViewById(R.id.inner).getDrawableState(),
+                    android.R.attr.state_drag_can_accept));
+        });
+
+        startDrag();
+
+        runOnMain(() -> {
+            assertFalse(ArrayUtils.contains(
+                    mActivity.findViewById(R.id.inner).getDrawableState(),
+                    android.R.attr.state_drag_hovered));
+            assertTrue(ArrayUtils.contains(
+                    mActivity.findViewById(R.id.inner).getDrawableState(),
+                    android.R.attr.state_drag_can_accept));
+        });
+
+        // Move mouse into the view.
+        injectMouse5(R.id.inner, MotionEvent.ACTION_MOVE);
+        runOnMain(() -> {
+            assertTrue(ArrayUtils.contains(
+                    mActivity.findViewById(R.id.inner).getDrawableState(),
+                    android.R.attr.state_drag_hovered));
+        });
+
+        // Move out.
+        injectMouse5(R.id.subcontainer, MotionEvent.ACTION_MOVE);
+        runOnMain(() -> {
+            assertFalse(ArrayUtils.contains(
+                    mActivity.findViewById(R.id.inner).getDrawableState(),
+                    android.R.attr.state_drag_hovered));
+        });
+
+        // Move in.
+        injectMouse5(R.id.inner, MotionEvent.ACTION_MOVE);
+        runOnMain(() -> {
+            assertTrue(ArrayUtils.contains(
+                    mActivity.findViewById(R.id.inner).getDrawableState(),
+                    android.R.attr.state_drag_hovered));
+        });
+
+        // Release there.
+        injectMouse5(R.id.inner, MotionEvent.ACTION_UP);
+        runOnMain(() -> {
+            assertFalse(ArrayUtils.contains(
+                    mActivity.findViewById(R.id.inner).getDrawableState(),
+                    android.R.attr.state_drag_hovered));
+        });
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/view/src/android/view/cts/PixelCopyTests.java b/tests/tests/view/src/android/view/cts/PixelCopyTests.java
index 3fa3634..f8bf79a 100644
--- a/tests/tests/view/src/android/view/cts/PixelCopyTests.java
+++ b/tests/tests/view/src/android/view/cts/PixelCopyTests.java
@@ -23,9 +23,12 @@
 import android.graphics.SurfaceTexture;
 import android.opengl.GLSurfaceView;
 import android.opengl.GLSurfaceView.Renderer;
+import android.os.Debug;
+import android.os.Debug.MemoryInfo;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
 import android.support.test.filters.MediumTest;
 import android.support.test.rule.ActivityTestRule;
 import android.util.Log;
@@ -171,6 +174,61 @@
     }
 
     @Test
+    @LargeTest
+    public void testNotLeaking() {
+        try {
+            CountDownLatch swapFence = new CountDownLatch(2);
+            GLSurfaceViewCtsActivity.setGlVersion(2);
+            GLSurfaceViewCtsActivity.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
+            GLSurfaceViewCtsActivity.setFixedSize(100, 100);
+            GLSurfaceViewCtsActivity.setRenderer(new QuadColorGLRenderer(
+                    Color.RED, Color.GREEN, Color.BLUE, Color.BLACK, swapFence));
+
+            GLSurfaceViewCtsActivity activity =
+                    mGLSurfaceViewActivityRule.launchActivity(null);
+
+            while (!swapFence.await(5, TimeUnit.MILLISECONDS)) {
+                activity.getView().requestRender();
+            }
+
+            // Test a fullsize copy
+            Bitmap bitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
+
+            MemoryInfo meminfoStart = new MemoryInfo();
+            MemoryInfo meminfoEnd = new MemoryInfo();
+
+            for (int i = 0; i < 1000; i++) {
+                if (i == 2) {
+                    // Not really the "start" but by having done a couple
+                    // we've fully initialized any state that may be required,
+                    // so memory usage should be stable now
+                    Debug.getMemoryInfo(meminfoStart);
+                }
+                if (i % 10 == 5) {
+                    Debug.getMemoryInfo(meminfoEnd);
+                    if (meminfoEnd.getTotalPss() - meminfoStart.getTotalPss() > 1000 /* kb */) {
+                        assertEquals("Memory leaked, iteration=" + i,
+                                meminfoStart.getTotalPss(), meminfoEnd.getTotalPss(),
+                                1000 /* kb */);
+                    }
+                }
+                SynchronousPixelCopy copyHelper = new SynchronousPixelCopy();
+                int result = copyHelper.request(activity.getView(), bitmap);
+                assertEquals("Copy request failed", PixelCopy.SUCCESS, result);
+                // Make sure nothing messed with the bitmap
+                assertEquals(100, bitmap.getWidth());
+                assertEquals(100, bitmap.getHeight());
+                assertEquals(Config.ARGB_8888, bitmap.getConfig());
+                assertBitmapQuadColor(bitmap,
+                        Color.RED, Color.GREEN, Color.BLUE, Color.BLACK);
+            }
+
+        } catch (InterruptedException e) {
+            fail("Interrupted, error=" + e.getMessage());
+        }
+    }
+
+    @Test
     public void testVideoProducer() throws InterruptedException {
         PixelCopyVideoSourceActivity activity =
                 mVideoSourceActivityRule.launchActivity(null);
diff --git a/tests/tests/view/src/android/view/cts/SurfaceViewSyncTests.java b/tests/tests/view/src/android/view/cts/SurfaceViewSyncTests.java
index da453dd..776e650 100644
--- a/tests/tests/view/src/android/view/cts/SurfaceViewSyncTests.java
+++ b/tests/tests/view/src/android/view/cts/SurfaceViewSyncTests.java
@@ -19,19 +19,18 @@
 import android.animation.PropertyValuesHolder;
 import android.animation.ValueAnimator;
 import android.annotation.SuppressLint;
+import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.media.MediaPlayer;
-import android.support.test.InstrumentationRegistry;
+import android.os.Environment;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject;
 import android.support.test.uiautomator.UiObjectNotFoundException;
-import android.support.test.uiautomator.UiSelector;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.util.Log;
+import android.util.SparseArray;
 import android.view.Gravity;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
@@ -44,11 +43,18 @@
 import android.view.cts.surfacevalidator.ViewFactory;
 import android.widget.FrameLayout;
 
-import org.junit.Before;
+import libcore.io.IoUtils;
+import org.junit.After;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TestName;
 import org.junit.runner.RunWith;
 
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
 import static org.junit.Assert.*;
 
 @RunWith(AndroidJUnit4.class)
@@ -56,23 +62,20 @@
 @SuppressLint("RtlHardcoded")
 public class SurfaceViewSyncTests {
     private static final String TAG = "SurfaceViewSyncTests";
-    private static final int PERMISSION_DIALOG_WAIT_MS = 500;
-
-    @Before
-    public void setUp() throws UiObjectNotFoundException {
-        // The permission dialog will be auto-opened by the activity - find it and accept
-        UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
-        UiSelector acceptButtonSelector = new UiSelector().resourceId("android:id/button1");
-        UiObject acceptButton = uiDevice.findObject(acceptButtonSelector);
-        if (acceptButton.waitForExists(PERMISSION_DIALOG_WAIT_MS)) {
-            assertTrue(acceptButton.click());
-        }
-    }
 
     private CapturedActivity getActivity() {
         return (CapturedActivity) mActivityRule.getActivity();
     }
 
+    /**
+     * Want to be especially sure we don't leave up the permission dialog, so try and dismiss
+     * after test.
+     */
+    @After
+    public void setUp() throws UiObjectNotFoundException {
+        getActivity().dismissPermissionDialog();
+    }
+
     private MediaPlayer getMediaPlayer() {
         return getActivity().getMediaPlayer();
     }
@@ -80,6 +83,9 @@
     @Rule
     public ActivityTestRule mActivityRule = new ActivityTestRule<>(CapturedActivity.class);
 
+    @Rule
+    public TestName mName = new TestName();
+
     static ValueAnimator makeInfinite(ValueAnimator a) {
         a.setRepeatMode(ObjectAnimator.REVERSE);
         a.setRepeatCount(ObjectAnimator.INFINITE);
@@ -165,13 +171,76 @@
     };
 
     ///////////////////////////////////////////////////////////////////////////
+    // Bad frame capture
+    ///////////////////////////////////////////////////////////////////////////
+
+    private void saveFailureCaptures(SparseArray<Bitmap> failFrames) {
+        if (failFrames.size() == 0) return;
+
+        String directoryName = Environment.getExternalStorageDirectory()
+                + "/" + getClass().getSimpleName()
+                + "/" + mName.getMethodName();
+        File testDirectory = new File(directoryName);
+        if (testDirectory.exists()) {
+            String[] children = testDirectory.list();
+            if (children == null) {
+                return;
+            }
+            for (String file : children) {
+                new File(testDirectory, file).delete();
+            }
+        } else {
+            testDirectory.mkdirs();
+        }
+
+        for (int i = 0; i < failFrames.size(); i++) {
+            int frameNr = failFrames.keyAt(i);
+            Bitmap bitmap = failFrames.valueAt(i);
+
+            String bitmapName =  "frame_" + frameNr + ".png";
+            Log.d(TAG, "Saving file : " + bitmapName + " in directory : " + directoryName);
+
+            File file = new File(directoryName, bitmapName);
+            FileOutputStream fileStream = null;
+            try {
+                fileStream = new FileOutputStream(file);
+                bitmap.compress(Bitmap.CompressFormat.PNG, 85, fileStream);
+                fileStream.flush();
+            } catch (IOException e) {
+                e.printStackTrace();
+            } finally {
+                IoUtils.closeQuietly(fileStream);
+            }
+        }
+    }
+
+
+    ///////////////////////////////////////////////////////////////////////////
     // Tests
     ///////////////////////////////////////////////////////////////////////////
 
+    public void verifyTest(AnimationTestCase testCase) throws Throwable {
+        CapturedActivity.TestResult result = getActivity().runTest(testCase);
+        saveFailureCaptures(result.failures);
+
+        float failRatio = 1.0f * result.failFrames / (result.failFrames + result.passFrames);
+        assertTrue("Error: " + failRatio + " fail ratio - extremely high, is activity obstructed?",
+                failRatio < 0.95f);
+        assertTrue("Error: " + result.failFrames
+                + " incorrect frames observed - incorrect positioning",
+                result.failFrames == 0);
+        float framesPerSecond = 1.0f * result.passFrames
+                / TimeUnit.MILLISECONDS.toSeconds(CapturedActivity.CAPTURE_DURATION_MS);
+        assertTrue("Error, only " + result.passFrames
+                + " frames observed, virtual display only capturing at "
+                + framesPerSecond + " frames per second",
+                result.passFrames > 100);
+    }
+
     /** Draws a moving 10x10 black rectangle, validates 100 pixels of black are seen each frame */
     @Test
-    public void testSmallRect() {
-        CapturedActivity.TestResult result = getActivity().runTest(new AnimationTestCase(
+    public void testSmallRect() throws Throwable {
+        verifyTest(new AnimationTestCase(
                 context -> new View(context) {
                     // draw a single pixel
                     final Paint sBlackPaint = new Paint();
@@ -190,9 +259,8 @@
                 },
                 new FrameLayout.LayoutParams(100, 100, Gravity.LEFT | Gravity.TOP),
                 view -> makeInfinite(ObjectAnimator.ofInt(view, "offset", 10, 30)),
-                (blackishPixelCount, width, height) -> blackishPixelCount == 100));
-        assertTrue(result.passFrames > 100);
-        assertTrue(result.failFrames == 0);
+                (blackishPixelCount, width, height) ->
+                        blackishPixelCount >= 90 && blackishPixelCount <= 110));
     }
 
     /**
@@ -200,53 +268,45 @@
      * approximate to avoid rounding brittleness.
      */
     @Test
-    public void testEmptySurfaceView() {
-        CapturedActivity.TestResult result = getActivity().runTest(new AnimationTestCase(
+    public void testEmptySurfaceView() throws Throwable {
+        verifyTest(new AnimationTestCase(
                 sEmptySurfaceViewFactory,
                 new FrameLayout.LayoutParams(100, 100, Gravity.LEFT | Gravity.TOP),
                 sTranslateAnimationFactory,
                 (blackishPixelCount, width, height) ->
                         blackishPixelCount > 9000 && blackishPixelCount < 11000));
-        assertTrue(result.passFrames > 100);
-        assertTrue(result.failFrames == 0);
     }
 
     @Test
-    public void testSurfaceViewSmallScale() {
-        CapturedActivity.TestResult result = getActivity().runTest(new AnimationTestCase(
+    public void testSurfaceViewSmallScale() throws Throwable {
+        verifyTest(new AnimationTestCase(
                 sGreenSurfaceViewFactory,
                 new FrameLayout.LayoutParams(640, 480, Gravity.LEFT | Gravity.TOP),
                 sSmallScaleAnimationFactory,
                 (blackishPixelCount, width, height) -> blackishPixelCount == 0));
-        assertTrue(result.passFrames > 100);
-        assertTrue(result.failFrames == 0);
     }
 
     @Test
-    public void testSurfaceViewBigScale() {
-        CapturedActivity.TestResult result = getActivity().runTest(new AnimationTestCase(
+    public void testSurfaceViewBigScale() throws Throwable {
+        verifyTest(new AnimationTestCase(
                 sGreenSurfaceViewFactory,
                 new FrameLayout.LayoutParams(640, 480, Gravity.LEFT | Gravity.TOP),
                 sBigScaleAnimationFactory,
                 (blackishPixelCount, width, height) -> blackishPixelCount == 0));
-        assertTrue(result.passFrames > 100);
-        assertTrue(result.failFrames == 0);
     }
 
     @Test
-    public void testVideoSurfaceViewTranslate() {
-        CapturedActivity.TestResult result = getActivity().runTest(new AnimationTestCase(
+    public void testVideoSurfaceViewTranslate() throws Throwable {
+        verifyTest(new AnimationTestCase(
                 sVideoViewFactory,
                 new FrameLayout.LayoutParams(640, 480, Gravity.LEFT | Gravity.TOP),
                 sTranslateAnimationFactory,
                 (blackishPixelCount, width, height) -> blackishPixelCount == 0));
-        assertTrue(result.passFrames > 100);
-        assertTrue(result.failFrames == 0);
     }
 
     @Test
-    public void testVideoSurfaceViewRotated() {
-        CapturedActivity.TestResult result = getActivity().runTest(new AnimationTestCase(
+    public void testVideoSurfaceViewRotated() throws Throwable {
+        verifyTest(new AnimationTestCase(
                 sVideoViewFactory,
                 new FrameLayout.LayoutParams(100, 100, Gravity.LEFT | Gravity.TOP),
                 view -> makeInfinite(ObjectAnimator.ofPropertyValuesHolder(view,
@@ -254,13 +314,11 @@
                         PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, 10f, 30f),
                         PropertyValuesHolder.ofFloat(View.ROTATION, 45f, 45f))),
                 (blackishPixelCount, width, height) -> blackishPixelCount == 0));
-        assertTrue(result.passFrames > 100);
-        assertTrue(result.failFrames == 0);
     }
 
     @Test
-    public void testVideoSurfaceViewEdgeCoverage() {
-        CapturedActivity.TestResult result = getActivity().runTest(new AnimationTestCase(
+    public void testVideoSurfaceViewEdgeCoverage() throws Throwable {
+        verifyTest(new AnimationTestCase(
                 sVideoViewFactory,
                 new FrameLayout.LayoutParams(640, 480, Gravity.CENTER),
                 view -> {
@@ -274,13 +332,11 @@
                             PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, 0, -y, 0, y, 0)));
                 },
                 (blackishPixelCount, width, height) -> blackishPixelCount == 0));
-        assertTrue(result.passFrames > 100);
-        assertTrue(result.failFrames == 0);
     }
 
     @Test
-    public void testVideoSurfaceViewCornerCoverage() {
-        CapturedActivity.TestResult result = getActivity().runTest(new AnimationTestCase(
+    public void testVideoSurfaceViewCornerCoverage() throws Throwable {
+        verifyTest(new AnimationTestCase(
                 sVideoViewFactory,
                 new FrameLayout.LayoutParams(640, 480, Gravity.CENTER),
                 view -> {
@@ -294,7 +350,5 @@
                             PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, -y, -y, y, y, -y)));
                 },
                 (blackishPixelCount, width, height) -> blackishPixelCount == 0));
-        assertTrue(result.passFrames > 100);
-        assertTrue(result.failFrames == 0);
     }
 }
diff --git a/tests/tests/view/src/android/view/cts/ViewTest.java b/tests/tests/view/src/android/view/cts/ViewTest.java
index 19e267d..3006ddf 100644
--- a/tests/tests/view/src/android/view/cts/ViewTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewTest.java
@@ -37,6 +37,7 @@
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.StateListDrawable;
+import android.hardware.display.DisplayManager;
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.os.SystemClock;
@@ -76,7 +77,6 @@
 import android.view.ViewGroup;
 import android.view.ViewParent;
 import android.view.ViewTreeObserver;
-import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.AlphaAnimation;
 import android.view.animation.Animation;
@@ -3374,8 +3374,9 @@
         Rect outRect = new Rect();
         View view = new View(mActivity);
         // mAttachInfo is null
-        WindowManager wm = (WindowManager)mActivity.getSystemService(Context.WINDOW_SERVICE);
-        Display d = wm.getDefaultDisplay();
+        DisplayManager dm = (DisplayManager) mActivity.getApplicationContext().getSystemService(
+                Context.DISPLAY_SERVICE);
+        Display d = dm.getDisplay(Display.DEFAULT_DISPLAY);
         view.getWindowVisibleDisplayFrame(outRect);
         assertEquals(0, outRect.left);
         assertEquals(0, outRect.top);
diff --git a/tests/tests/view/src/android/view/cts/surfacevalidator/CapturedActivity.java b/tests/tests/view/src/android/view/cts/surfacevalidator/CapturedActivity.java
index 6a23e02..7d08fcd 100644
--- a/tests/tests/view/src/android/view/cts/surfacevalidator/CapturedActivity.java
+++ b/tests/tests/view/src/android/view/cts/surfacevalidator/CapturedActivity.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
 import android.graphics.Point;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.VirtualDisplay;
@@ -28,22 +29,34 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiObjectNotFoundException;
+import android.support.test.uiautomator.UiSelector;
 import android.util.DisplayMetrics;
 import android.util.Log;
+import android.util.SparseArray;
 import android.view.Display;
 import android.view.View;
 import android.widget.FrameLayout;
 
 import android.view.cts.R;
 
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import static org.junit.Assert.*;
+
+
 public class CapturedActivity extends Activity {
     public static class TestResult {
         public int passFrames;
         public int failFrames;
+        public final SparseArray<Bitmap> failures = new SparseArray<>();
     }
 
     private static final String TAG = "CapturedActivity";
-    private static final long TIME_OUT_MS = 10000;
+    private static final long TIME_OUT_MS = 25000;
     private static final int PERMISSION_CODE = 1;
     private MediaProjectionManager mProjectionManager;
     private MediaProjection mMediaProjection;
@@ -52,30 +65,51 @@
     private SurfacePixelValidator mSurfacePixelValidator;
     private final Object mLock = new Object();
 
-    private static final long START_CAPTURE_DELAY_MS = 1000;
-    private static final long END_CAPTURE_DELAY_MS = START_CAPTURE_DELAY_MS + 4000;
-    private static final long END_DELAY_MS = END_CAPTURE_DELAY_MS + 500;
+    public static final long CAPTURE_DURATION_MS = 10000;
+    private static final int PERMISSION_DIALOG_WAIT_MS = 1000;
+    private static final int RETRY_COUNT = 2;
+
+    private static final long START_CAPTURE_DELAY_MS = 4000;
+    private static final long END_CAPTURE_DELAY_MS = START_CAPTURE_DELAY_MS + CAPTURE_DURATION_MS;
+    private static final long END_DELAY_MS = END_CAPTURE_DELAY_MS + 1000;
 
     private MediaPlayer mMediaPlayer;
 
     private final Handler mHandler = new Handler(Looper.getMainLooper());
     private volatile boolean mOnWatch;
+    private CountDownLatch mCountDownLatch;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        mOnWatch = getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
+        if (mOnWatch) {
+            // Don't try and set up test/capture infrastructure - they're not supported
+            return;
+        }
+
         getWindow().getDecorView().setSystemUiVisibility(
                 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN);
 
         mProjectionManager =
                 (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
 
+        mCountDownLatch = new CountDownLatch(1);
         startActivityForResult(mProjectionManager.createScreenCaptureIntent(), PERMISSION_CODE);
 
         mMediaPlayer = MediaPlayer.create(this, R.raw.colors_video);
         mMediaPlayer.setLooping(true);
+    }
 
-        mOnWatch = getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
+    public void dismissPermissionDialog() throws UiObjectNotFoundException {
+        // The permission dialog will be auto-opened by the activity - find it and accept
+        UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+        UiSelector acceptButtonSelector = new UiSelector().resourceId("android:id/button1");
+        UiObject acceptButton = uiDevice.findObject(acceptButtonSelector);
+            if (acceptButton.waitForExists(PERMISSION_DIALOG_WAIT_MS)) {
+            boolean success = acceptButton.click();
+            Log.d(TAG, "found permission dialog, click attempt success = " + success);
+        }
     }
 
     /**
@@ -97,17 +131,23 @@
 
     @Override
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (mOnWatch) return;
+        getWindow().getDecorView().setSystemUiVisibility(
+                View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN);
+
         if (requestCode != PERMISSION_CODE) {
             throw new IllegalStateException("Unknown request code: " + requestCode);
         }
         if (resultCode != RESULT_OK) {
             throw new IllegalStateException("User denied screen sharing permission");
         }
+        Log.d(TAG, "onActivityResult");
         mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data);
         mMediaProjection.registerCallback(new MediaProjectionCallback(), null);
+        mCountDownLatch.countDown();
     }
 
-    public TestResult runTest(AnimationTestCase animationTestCase) {
+    public TestResult runTest(AnimationTestCase animationTestCase) throws Throwable {
         TestResult testResult = new TestResult();
         if (mOnWatch) {
             /**
@@ -122,6 +162,18 @@
             return testResult;
         }
 
+        int count = 0;
+        // Sometimes system decides to rotate the permission activity to another orientation
+        // right after showing it. This results in: uiautomation thinks that accept button appears,
+        // we successfully click it in terms of uiautomation, but nothing happens,
+        // because permission activity is already recreated.
+        // Thus, we try to click that button multiple times.
+        do {
+            assertTrue("Can't get the permission", count <= RETRY_COUNT);
+            dismissPermissionDialog();
+            count++;
+        } while (!mCountDownLatch.await(TIME_OUT_MS, TimeUnit.MILLISECONDS));
+
         mHandler.post(() -> {
             Log.d(TAG, "Setting up test case");
 
@@ -143,6 +195,7 @@
             display.getRealSize(size);
             display.getMetrics(metrics);
 
+
             mSurfacePixelValidator = new SurfacePixelValidator(CapturedActivity.this,
                     size, animationTestCase.getChecker());
             Log.d("MediaProjection", "Size is " + size.toString());
@@ -172,11 +225,7 @@
         }, END_DELAY_MS);
 
         synchronized (mLock) {
-            try {
-                mLock.wait(TIME_OUT_MS);
-            } catch (InterruptedException e) {
-                e.printStackTrace();
-            }
+            mLock.wait(TIME_OUT_MS);
         }
         Log.d(TAG, "Test finished, passFrames " + testResult.passFrames
                 + ", failFrames " + testResult.failFrames);
diff --git a/tests/tests/view/src/android/view/cts/surfacevalidator/PixelCounter.rs b/tests/tests/view/src/android/view/cts/surfacevalidator/PixelCounter.rs
index 55bc251..f58b9cb 100644
--- a/tests/tests/view/src/android/view/cts/surfacevalidator/PixelCounter.rs
+++ b/tests/tests/view/src/android/view/cts/surfacevalidator/PixelCounter.rs
@@ -15,22 +15,18 @@
  */
 #pragma version(1)
 #pragma rs java_package_name(android.view.cts.surfacevalidator)
+#pragma rs reduce(countBlackishPixels) accumulator(countBlackishPixelsAccum) combiner(countBlackishPixelsCombiner)
 
-int WIDTH;
 uchar THRESHOLD;
 
-rs_allocation image;
-
-void countBlackishPixels(const int32_t *v_in, int *v_out){
-    int y = v_in[0];
-    v_out[0] = 0;
-
-    for(int i = 0 ; i < WIDTH; i++){
-        uchar4 pixel = rsGetElementAt_uchar4(image, i, y);
-        if (pixel.r < THRESHOLD
-                && pixel.g < THRESHOLD
-                && pixel.b < THRESHOLD) {
-            v_out[0]++;
-        }
+static void countBlackishPixelsAccum(int *accum, uchar4 pixel){
+    if (pixel.r < THRESHOLD
+            && pixel.g < THRESHOLD
+            && pixel.b < THRESHOLD) {
+        *accum += 1;
     }
 }
+
+static void countBlackishPixelsCombiner(int *accum, const int *other){
+    *accum += *other;
+}
diff --git a/tests/tests/view/src/android/view/cts/surfacevalidator/SurfacePixelValidator.java b/tests/tests/view/src/android/view/cts/surfacevalidator/SurfacePixelValidator.java
index c9bff1d..5a30b77 100644
--- a/tests/tests/view/src/android/view/cts/surfacevalidator/SurfacePixelValidator.java
+++ b/tests/tests/view/src/android/view/cts/surfacevalidator/SurfacePixelValidator.java
@@ -16,6 +16,7 @@
 package android.view.cts.surfacevalidator;
 
 import android.content.Context;
+import android.graphics.Bitmap;
 import android.graphics.Point;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -25,11 +26,13 @@
 import android.renderscript.RenderScript;
 import android.renderscript.Type;
 import android.util.Log;
+import android.util.SparseArray;
 import android.view.Surface;
 import android.view.cts.surfacevalidator.PixelChecker;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.ArrayList;
 
 public class SurfacePixelValidator {
     private static final String TAG = "SurfacePixelValidator";
@@ -43,6 +46,8 @@
     // If no channel is greater than this value, pixel will be considered 'blackish'.
     private static final short PIXEL_CHANNEL_THRESHOLD = 4;
 
+    private static final int MAX_CAPTURED_FAILURES = 5;
+
     private final int mWidth;
     private final int mHeight;
 
@@ -54,14 +59,13 @@
     private final RenderScript mRS;
 
     private final Allocation mInPixelsAllocation;
-    private final Allocation mInRowsAllocation;
-    private final Allocation mOutRowsAllocation;
     private final ScriptC_PixelCounter mScript;
 
 
     private final Object mResultLock = new Object();
     private int mResultSuccessFrames;
     private int mResultFailureFrames;
+    private SparseArray<Bitmap> mFirstFailures = new SparseArray<>(MAX_CAPTURED_FAILURES);
 
     private Runnable mConsumeRunnable = new Runnable() {
         int numSkipped = 0;
@@ -69,15 +73,10 @@
         public void run() {
             Trace.beginSection("consume buffer");
             mInPixelsAllocation.ioReceive();
-            mScript.set_image(mInPixelsAllocation);
             Trace.endSection();
 
-            Trace.beginSection("compare");
-            mScript.forEach_countBlackishPixels(mInRowsAllocation, mOutRowsAllocation);
-            Trace.endSection();
-
-            Trace.beginSection("sum");
-            int blackishPixelCount = sum1DIntAllocation(mOutRowsAllocation, mHeight);
+            Trace.beginSection("compare and sum");
+            int blackishPixelCount = mScript.reduce_countBlackishPixels(mInPixelsAllocation).get();
             Trace.endSection();
 
             boolean success = mPixelChecker.checkPixels(blackishPixelCount, mWidth, mHeight);
@@ -85,7 +84,6 @@
                 if (numSkipped < NUM_FIRST_FRAMES_SKIPPED) {
                     numSkipped++;
                 } else {
-
                     if (success) {
                         mResultSuccessFrames++;
                     } else {
@@ -93,6 +91,15 @@
                         int totalFramesSeen = mResultSuccessFrames + mResultFailureFrames;
                         Log.d(TAG, "Failure (pixel count = " + blackishPixelCount
                                 + ") occurred on frame " + totalFramesSeen);
+
+                        if (mFirstFailures.size() < MAX_CAPTURED_FAILURES) {
+                            Log.d(TAG, "Capturing bitmap #" + mFirstFailures.size());
+                            // error, worth looking at...
+                            Bitmap capture = Bitmap.createBitmap(mWidth, mHeight,
+                                    Bitmap.Config.ARGB_8888);
+                            mInPixelsAllocation.copyTo(capture);
+                            mFirstFailures.put(totalFramesSeen, capture);
+                        }
                     }
                 }
             }
@@ -113,9 +120,6 @@
         mScript = new ScriptC_PixelCounter(mRS);
 
         mInPixelsAllocation = createBufferQueueAllocation();
-        mInRowsAllocation = createInputRowIndexAllocation();
-        mOutRowsAllocation = createOutputRowAllocation();
-        mScript.set_WIDTH(mWidth);
         mScript.set_THRESHOLD(PIXEL_CHANNEL_THRESHOLD);
 
         mInPixelsAllocation.setOnBufferAvailableListener(
@@ -126,41 +130,10 @@
         return mInPixelsAllocation.getSurface();
     }
 
-    static private int sum1DIntAllocation(Allocation array, int length) {
-        //Get the values returned from the function
-        int[] returnValue = new int[length];
-        array.copyTo(returnValue);
-        int sum = 0;
-        //If any row had any different pixels, then it fails
-        for (int i = 0; i < length; i++) {
-            sum += returnValue[i];
-        }
-        return sum;
-    }
-
-    /**
-     * Creates an allocation where the values in it are the indices of each row
-     */
-    private Allocation createInputRowIndexAllocation() {
-        //Create an array with the index of each row
-        int[] inputIndices = new int[mHeight];
-        for (int i = 0; i < mHeight; i++) {
-            inputIndices[i] = i;
-        }
-        //Create the allocation from that given array
-        Allocation inputAllocation = Allocation.createSized(mRS, Element.I32(mRS),
-                inputIndices.length, Allocation.USAGE_SCRIPT);
-        inputAllocation.copyFrom(inputIndices);
-        return inputAllocation;
-    }
-
-    private Allocation createOutputRowAllocation() {
-        return Allocation.createSized(mRS, Element.I32(mRS), mHeight, Allocation.USAGE_SCRIPT);
-    }
-
     private Allocation createBufferQueueAllocation() {
         return Allocation.createAllocations(mRS, Type.createXY(mRS,
-                Element.U8_4(mRS), mWidth, mHeight),
+                Element.RGBA_8888(mRS)
+                /*Element.U32(mRS)*/, mWidth, mHeight),
                 Allocation.USAGE_SCRIPT | Allocation.USAGE_IO_INPUT,
                 1)[0];
     }
@@ -177,6 +150,10 @@
             // Caller should only call this
             testResult.failFrames = mResultFailureFrames;
             testResult.passFrames = mResultSuccessFrames;
+
+            for (int i = 0; i < mFirstFailures.size(); i++) {
+                testResult.failures.put(mFirstFailures.keyAt(i), mFirstFailures.valueAt(i));
+            }
         }
         mWorkerThread.quitSafely();
     }
diff --git a/tests/tests/webkit/src/android/webkit/cts/ServiceWorkerClientTest.java b/tests/tests/webkit/src/android/webkit/cts/ServiceWorkerClientTest.java
index a77d648..e09e0d6 100644
--- a/tests/tests/webkit/src/android/webkit/cts/ServiceWorkerClientTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/ServiceWorkerClientTest.java
@@ -16,6 +16,7 @@
 
 package android.webkit.cts;
 
+import android.cts.util.NullWebViewUtils;
 import android.cts.util.PollingCheck;
 import android.test.ActivityInstrumentationTestCase2;
 
@@ -136,6 +137,10 @@
 
     // Test correct invocation of shouldInterceptRequest for Service Workers.
     public void testServiceWorkerClientInterceptCallback() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
         final InterceptServiceWorkerClient mInterceptServiceWorkerClient =
                 new InterceptServiceWorkerClient();
         ServiceWorkerController swController = ServiceWorkerController.getInstance();
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java
index a4ebaca..3b67d84 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java
@@ -20,7 +20,6 @@
 import android.content.Context;
 import android.cts.util.NullWebViewUtils;
 import android.cts.util.PollingCheck;
-import android.os.StrictMode;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
 import android.util.Log;
@@ -89,21 +88,4 @@
         assertTrue(m.matches());
         assertEquals("42", m.group(1)); // value got incremented
     }
-
-    @UiThreadTest
-    public void testStrictModeNotViolatedOnStartup() throws Throwable {
-        StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
-        StrictMode.ThreadPolicy testPolicy = new StrictMode.ThreadPolicy.Builder()
-            .detectDiskReads()
-            .penaltyLog()
-            .penaltyDeath()
-            .build();
-        StrictMode.setThreadPolicy(testPolicy);
-        try {
-            mActivity.createAndAttachWebView();
-        } finally {
-            StrictMode.setThreadPolicy(oldPolicy);
-        }
-    }
-
 }
diff --git a/tests/tests/widget/AndroidManifest.xml b/tests/tests/widget/AndroidManifest.xml
index 224966d..5d41337 100644
--- a/tests/tests/widget/AndroidManifest.xml
+++ b/tests/tests/widget/AndroidManifest.xml
@@ -222,7 +222,8 @@
         </activity>
 
         <activity android:name="android.widget.cts.PopupWindowCtsActivity"
-            android:label="PopupWindowCtsActivity">
+            android:label="PopupWindowCtsActivity"
+            android:theme="@style/Theme.PopupWindowCtsActivity">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
@@ -380,6 +381,14 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="android.widget.cts.TimePickerDialogCtsActivity"
+                  android:label="TimePickerDialogCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
         <activity android:name="android.widget.cts.CalendarViewCtsActivity"
                   android:label="CalendarViewCtsActivity">
             <intent-filter>
diff --git a/tests/tests/widget/res/values-w320dp-h426dp/integers.xml b/tests/tests/widget/res/values-w320dp-h426dp/integers.xml
new file mode 100644
index 0000000..a9d049c
--- /dev/null
+++ b/tests/tests/widget/res/values-w320dp-h426dp/integers.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <integer name="date_picker_mode">2</integer>
+    <integer name="time_picker_mode">2</integer>
+</resources>
diff --git a/tests/tests/widget/res/values-w426dp-h320dp/integers.xml b/tests/tests/widget/res/values-w426dp-h320dp/integers.xml
new file mode 100644
index 0000000..a9d049c
--- /dev/null
+++ b/tests/tests/widget/res/values-w426dp-h320dp/integers.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <integer name="date_picker_mode">2</integer>
+    <integer name="time_picker_mode">2</integer>
+</resources>
diff --git a/tests/tests/widget/res/values/integers.xml b/tests/tests/widget/res/values/integers.xml
new file mode 100644
index 0000000..b2c1e65
--- /dev/null
+++ b/tests/tests/widget/res/values/integers.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <integer name="date_picker_mode">1</integer>
+    <integer name="time_picker_mode">1</integer>
+</resources>
diff --git a/tests/tests/widget/res/values/styles.xml b/tests/tests/widget/res/values/styles.xml
index 345b450..d2e8e48 100644
--- a/tests/tests/widget/res/values/styles.xml
+++ b/tests/tests/widget/res/values/styles.xml
@@ -193,6 +193,11 @@
         <item name="android:windowSwipeToDismiss">false</item>
     </style>
 
+    <style name="Theme_Holo_With_Material_Pickers" parent="@android:style/Theme.Holo">
+        <item name="android:timePickerStyle">@android:style/Widget.Material.TimePicker</item>
+        <item name="android:datePickerStyle">@android:style/Widget.Material.DatePicker</item>
+    </style>
+
     <style name="PopupEmptyStyle" />
 
     <style name="TabWidgetCustomStyle" parent="android:Widget.TabWidget">
@@ -202,4 +207,9 @@
     </style>
 
     <style name="ToolbarPopupTheme_Test" parent="@android:style/ThemeOverlay.Material.Light" />
+
+    <style name="Theme.PopupWindowCtsActivity" parent="@android:style/Theme.Holo">
+        <!-- Force swipe-to-dismiss to false. -->
+        <item name="android:windowSwipeToDismiss">false</item>
+    </style>
 </resources>
diff --git a/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java b/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java
index cf8012e..2a6883f 100644
--- a/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java
@@ -33,6 +33,7 @@
 import android.graphics.drawable.Drawable;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.TouchUtils;
+import android.test.UiThreadTest;
 import android.text.Editable;
 import android.text.SpannableStringBuilder;
 import android.util.AttributeSet;
@@ -109,14 +110,37 @@
          */
     }
 
-    public void testAccessFastScrollEnabled() {
+    @UiThreadTest
+    public void testAccessFastScrollEnabled_UiThread() {
+        mListView.setFastScrollAlwaysVisible(false);
         mListView.setFastScrollEnabled(false);
         assertFalse(mListView.isFastScrollEnabled());
 
+        mListView.setFastScrollAlwaysVisible(true);
         mListView.setFastScrollEnabled(true);
         assertTrue(mListView.isFastScrollEnabled());
     }
 
+    public void testAccessFastScrollEnabled() {
+        mListView.setFastScrollAlwaysVisible(false);
+        mListView.setFastScrollEnabled(false);
+        new PollingCheck() {
+            @Override
+            protected boolean check() {
+                return !mListView.isFastScrollEnabled();
+            }
+        }.run();
+
+        mListView.setFastScrollAlwaysVisible(true);
+        mListView.setFastScrollEnabled(true);
+        new PollingCheck() {
+            @Override
+            protected boolean check() {
+                return mListView.isFastScrollEnabled();
+            }
+        }.run();
+    }
+
     public void testAccessSmoothScrollbarEnabled() {
         mListView.setSmoothScrollbarEnabled(false);
         assertFalse(mListView.isSmoothScrollbarEnabled());
diff --git a/tests/tests/widget/src/android/widget/cts/DatePickerDialogTest.java b/tests/tests/widget/src/android/widget/cts/DatePickerDialogTest.java
index 1477f73..74d0ff5 100644
--- a/tests/tests/widget/src/android/widget/cts/DatePickerDialogTest.java
+++ b/tests/tests/widget/src/android/widget/cts/DatePickerDialogTest.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
+import android.widget.DatePicker;
 
 /**
  * Test {@link DatePickerDialog}.
@@ -48,7 +49,16 @@
 
         new DatePickerDialog(mActivity, AlertDialog.THEME_TRADITIONAL, null, 1970, 1, 1);
 
-        new DatePickerDialog(mActivity, AlertDialog.THEME_HOLO_DARK, null, 1970, 1, 1);
+        // Ensure the picker is shown using the Holo-style layout.
+        DatePickerDialog holoDialog = new DatePickerDialog(mActivity, AlertDialog.THEME_HOLO_DARK,
+                null, 1970, 1, 1);
+        assertEquals(DatePicker.MODE_SPINNER, holoDialog.getDatePicker().getMode());
+
+        // Ensure the picker is shown using the Material-style layout where available.
+        DatePickerDialog holoCalendarDialog = new DatePickerDialog(mActivity,
+                R.style.Theme_Holo_With_Material_Pickers, null, 1970, 1, 1);
+        final int expectedMode = mActivity.getResources().getInteger(R.integer.date_picker_mode);
+        assertEquals(expectedMode, holoCalendarDialog.getDatePicker().getMode());
 
         new DatePickerDialog(mActivity,
                 android.R.style.Theme_Material_Dialog_Alert, null, 1970, 1, 1);
diff --git a/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java b/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
index b50f8c9..73e2aeb 100644
--- a/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
@@ -219,6 +219,14 @@
                 Gravity.getAbsoluteGravity(gravity, upperAnchor.getLayoutDirection());
         if (absoluteGravity == Gravity.RIGHT) {
             expectedListViewOnScreenX -= (listView.getWidth() - upperAnchor.getWidth());
+        } else {
+            // On narrow screens, it's possible for the popup to reach the edge
+            // of the screen.
+            int rightmostX =
+                    getDisplay().getWidth() - mPopupWindow.getWidth() + listViewInWindowXY[0];
+            if (expectedListViewOnScreenX > rightmostX) {
+                expectedListViewOnScreenX = rightmostX;
+            }
         }
         int expectedListViewOnScreenY = anchorXY[1] + listViewInWindowXY[1]
                 + upperAnchor.getHeight() + verticalOffset;
@@ -508,7 +516,10 @@
         final int[] lastChildOnScreenXY = new int[2];
         lastListChild.getLocationOnScreen(lastChildOnScreenXY);
 
-        assertTrue(lastChildOnScreenXY[1] + lastListChild.getHeight() <= promptViewOnScreenXY[1]);
+        // The child is above the prompt. They may overlap, as in the case
+        // when the list items do not all fit on screen, but this is still
+        // correct.
+        assertTrue(lastChildOnScreenXY[1] <= promptViewOnScreenXY[1]);
     }
 
     @Presubmit
diff --git a/tests/tests/widget/src/android/widget/cts/TimePickerDialogCtsActivity.java b/tests/tests/widget/src/android/widget/cts/TimePickerDialogCtsActivity.java
new file mode 100644
index 0000000..f5c544b
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/TimePickerDialogCtsActivity.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * A minimal application for TimePickerDialog test.
+ */
+public class TimePickerDialogCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/TimePickerDialogTest.java b/tests/tests/widget/src/android/widget/cts/TimePickerDialogTest.java
new file mode 100644
index 0000000..73ddc04
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/TimePickerDialogTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.DatePickerDialog;
+import android.app.TimePickerDialog;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.widget.TimePicker;
+
+/**
+ * Test {@link TimePickerDialog}.
+ */
+public class TimePickerDialogTest extends
+        ActivityInstrumentationTestCase2<TimePickerDialogCtsActivity> {
+
+    private Activity mActivity;
+
+    public TimePickerDialogTest() {
+        super(TimePickerDialogCtsActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+    }
+
+    @UiThreadTest
+    public void testConstructor() {
+        new TimePickerDialog(mActivity, null, 7, 0, true);
+
+        new TimePickerDialog(mActivity, AlertDialog.THEME_TRADITIONAL, null, 7, 0, true);
+
+        // Ensure the picker is shown using the Holo-style layout.
+        TimePickerDialog holoDialog = new TimePickerDialog(mActivity, AlertDialog.THEME_HOLO_DARK,
+                null, 7, 0, true);
+        assertEquals(TimePicker.MODE_SPINNER, holoDialog.getTimePicker().getMode());
+
+        // Ensure the picker is shown using the Material-style layout where available.
+        TimePickerDialog holoClockDialog = new TimePickerDialog(mActivity,
+                R.style.Theme_Holo_With_Material_Pickers, null, 7, 0, true);
+        final int expectedMode = mActivity.getResources().getInteger(R.integer.time_picker_mode);
+        assertEquals(expectedMode, holoClockDialog.getTimePicker().getMode());
+
+        new TimePickerDialog(mActivity,
+                android.R.style.Theme_Material_Dialog_Alert, null, 7, 0, true);
+
+        try {
+            new TimePickerDialog(null, null, 7, 0, true);
+            fail("should throw NullPointerException");
+        } catch (Exception e) {
+        }
+    }
+
+}
diff --git a/tools/cts-api-coverage/src/Android.mk b/tools/cts-api-coverage/src/Android.mk
index d1fe4ed..8c038dc 100644
--- a/tools/cts-api-coverage/src/Android.mk
+++ b/tools/cts-api-coverage/src/Android.mk
@@ -23,6 +23,10 @@
 LOCAL_JAVA_RESOURCE_DIRS := res 
 LOCAL_JAR_MANIFEST := MANIFEST.mf
 
+LOCAL_STATIC_JAVA_LIBRARIES := \
+  compatibility-host-util \
+  dexlib2
+
 LOCAL_MODULE := cts-api-coverage
 LOCAL_MODULE_TAGS := optional
 
diff --git a/tools/cts-api-coverage/src/MANIFEST.mf b/tools/cts-api-coverage/src/MANIFEST.mf
index b6aa831..63d6674 100644
--- a/tools/cts-api-coverage/src/MANIFEST.mf
+++ b/tools/cts-api-coverage/src/MANIFEST.mf
@@ -1,2 +1,3 @@
 Manifest-Version: 1.0
 Main-Class: com.android.cts.apicoverage.CtsApiCoverage
+Class-Path: tradefed-prebuilt.jar
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/CddCoverage.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/CddCoverage.java
new file mode 100644
index 0000000..3d1a07d
--- /dev/null
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/CddCoverage.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.apicoverage;
+
+import java.lang.String;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.List;
+import java.util.Set;
+
+/** Representation of the entire CDD. */
+class CddCoverage {
+
+    private final Map<String, CddRequirement> requirements = new HashMap<>();
+
+    public void addCddRequirement(CddRequirement cddRequirement) {
+        requirements.put(cddRequirement.getRequirementId(), cddRequirement);
+    }
+
+    public Collection<CddRequirement> getCddRequirements() {
+        return Collections.unmodifiableCollection(requirements.values());
+    }
+
+    public void addCoverage(String cddRequirementId, TestMethod testMethod) {
+        if (!requirements.containsKey(cddRequirementId)) {
+            requirements.put(cddRequirementId, new CddRequirement(cddRequirementId));
+        }
+
+        requirements.get(cddRequirementId).addTestMethod(testMethod);
+    }
+
+    static class CddRequirement {
+        private final String mRequirementId;
+        private final List<TestMethod> mtestMethods;
+
+        CddRequirement(String requirementId) {
+            this.mRequirementId = requirementId;
+            this.mtestMethods = new ArrayList<>();
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (other == null) {
+                return false;
+            } else if (!(other instanceof CddRequirement)) {
+                return false;
+            } else {
+                return mRequirementId.equals(((CddRequirement)other).mRequirementId);
+            }
+        }
+
+        @Override
+        public int hashCode() {
+            return mRequirementId.hashCode();
+        }
+
+        @Override
+        public String toString() {
+            return String.format("Requirement %s %s", mRequirementId, mtestMethods);
+        }
+
+        public String getRequirementId() { return mRequirementId; }
+
+        public void addTestMethod(TestMethod testMethod) {
+            mtestMethods.add(testMethod);
+        }
+
+        public Collection<TestMethod> getTestMethods() {
+            return Collections.unmodifiableCollection(mtestMethods);
+        }
+    }
+
+    static class TestMethod {
+        private final String mTestModule;
+        private final String mTestClass;
+        private final String mTestMethod;
+
+        TestMethod(String testModule, String testClass, String testMethod) {
+            this.mTestModule = testModule;
+            this.mTestClass = testClass;
+            this.mTestMethod = testMethod;
+        }
+
+        public String getTestModule() { return mTestModule; }
+
+        public String getTestClass() { return mTestClass; }
+
+        public String getTestMethod() { return mTestMethod; }
+
+        @Override
+        public String toString() {
+            return String.format("%s %s#%s", mTestModule, mTestClass, mTestMethod);
+        }
+    }
+}
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsApiCoverage.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsApiCoverage.java
index 6b69a57..2b57c76 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsApiCoverage.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsApiCoverage.java
@@ -16,6 +16,19 @@
 
 package com.android.cts.apicoverage;
 
+import com.android.compatibility.common.util.CddTest;
+
+import org.jf.dexlib2.DexFileFactory;
+import org.jf.dexlib2.DexFileFactory.DexFileNotFound;
+import org.jf.dexlib2.DexFileFactory.MultipleDexFilesException;
+import org.jf.dexlib2.Opcodes;
+import org.jf.dexlib2.iface.Annotation;
+import org.jf.dexlib2.iface.AnnotationElement;
+import org.jf.dexlib2.iface.ClassDef;
+import org.jf.dexlib2.iface.DexFile;
+import org.jf.dexlib2.iface.Method;
+import org.jf.dexlib2.iface.value.StringEncodedValue;
+
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 import org.xml.sax.XMLReader;
@@ -29,7 +42,9 @@
 import java.io.OutputStream;
 import java.util.Arrays;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
+import java.util.Set;
 
 import javax.xml.transform.TransformerException;
 
@@ -52,6 +67,10 @@
 
     private static final int FORMAT_HTML = 2;
 
+    private static final String CDD_REQUIREMENT_ANNOTATION = "Lcom/android/compatibility/common/util/CddTest;";
+
+    private static final String CDD_REQUIREMENT_ELEMENT_NAME = "requirement";
+
     private static void printUsage() {
         System.out.println("Usage: cts-api-coverage [OPTION]... [APK]...");
         System.out.println();
@@ -70,6 +89,7 @@
         System.out.println("  -a PATH                path to the API XML file");
         System.out.println("  -p PACKAGENAMEPREFIX   report coverage only for package that start with");
         System.out.println("  -t TITLE               report title");
+        System.out.println("  -a API                 the Android API Level");
         System.out.println();
         System.exit(1);
     }
@@ -82,6 +102,7 @@
         String apiXmlPath = "";
         PackageFilter packageFilter = new PackageFilter();
         String reportTitle = "CTS API Coverage";
+        int apiLevel = Integer.MAX_VALUE;
 
         for (int i = 0; i < args.length; i++) {
             if (args[i].startsWith("-")) {
@@ -106,6 +127,8 @@
                     packageFilter.addPrefixToFilter(getExpectedArg(args, ++i));
                 } else if ("-t".equals(args[i])) {
                     reportTitle = getExpectedArg(args, ++i);
+                } else if ("-a".equals(args[i])) {
+                    apiLevel = Integer.parseInt(getExpectedArg(args, ++i));
                 } else {
                     printUsage();
                 }
@@ -131,12 +154,16 @@
          */
 
         ApiCoverage apiCoverage = getEmptyApiCoverage(apiXmlPath);
+        CddCoverage cddCoverage = getEmptyCddCoverage();
         // Add superclass information into api coverage.
         apiCoverage.resolveSuperClasses();
         for (File testApk : testApks) {
             addApiCoverage(apiCoverage, testApk, dexDeps);
+            addCddCoverage(cddCoverage, testApk, apiLevel);
         }
-        outputCoverageReport(apiCoverage, testApks, outputFile, format, packageFilter, reportTitle);
+
+        outputCoverageReport(apiCoverage, cddCoverage, testApks, outputFile,
+            format, packageFilter, reportTitle);
     }
 
     /** Get the argument or print out the usage and exit. */
@@ -202,8 +229,106 @@
         }
     }
 
-    private static void outputCoverageReport(ApiCoverage apiCoverage, List<File> testApks,
-            File outputFile, int format, PackageFilter packageFilter, String reportTitle)
+    private static void addCddCoverage(CddCoverage cddCoverage, File testSource, int api)
+            throws IOException {
+
+        if (testSource.getName().endsWith(".apk")) {
+            addCddApkCoverage(cddCoverage, testSource, api);
+        } else if (testSource.getName().endsWith(".jar")) {
+            addCddJarCoverage(cddCoverage, testSource);
+        } else {
+            System.err.println("Unsupported file type for CDD coverage: " + testSource.getPath());
+        }
+    }
+
+    private static void addCddJarCoverage(CddCoverage cddCoverage, File testSource)
+            throws IOException {
+
+        Collection<Class<?>> classes = JarTestFinder.getClasses(testSource);
+        for (Class<?> c : classes) {
+            for (java.lang.reflect.Method m : c.getMethods()) {
+                if (m.isAnnotationPresent(CddTest.class)) {
+                    CddTest cddTest = m.getAnnotation(CddTest.class);
+                    CddCoverage.TestMethod testMethod =
+                            new CddCoverage.TestMethod(
+                                    testSource.getName(), c.getName(), m.getName());
+                    cddCoverage.addCoverage(cddTest.requirement(), testMethod);
+                }
+            }
+        }
+    }
+
+    private static void addCddApkCoverage(
+        CddCoverage cddCoverage, File testSource, int api)
+            throws IOException {
+
+        DexFile dexFile = null;
+        try {
+            dexFile = DexFileFactory.loadDexFile(
+                testSource, null /*dexEntry*/, Opcodes.forApi(api));
+        } catch (IOException | DexFileFactory.DexFileNotFound e) {
+            System.err.println("Unable to load dex file: " + testSource.getPath());
+            return;
+        }
+
+        String moduleName = testSource.getName();
+        for (ClassDef classDef : dexFile.getClasses()) {
+            String className = classDef.getType();
+            handleAnnotations(
+                cddCoverage, moduleName, className, null /*methodName*/,
+                classDef.getAnnotations());
+
+            for (Method method : classDef.getMethods()) {
+                String methodName = method.getName();
+                handleAnnotations(
+                    cddCoverage, moduleName, className, methodName, method.getAnnotations());
+            }
+        }
+    }
+
+    private static void handleAnnotations(
+            CddCoverage cddCoverage, String moduleName, String className,
+                    String methodName, Set<? extends Annotation> annotations) {
+        for (Annotation annotation : annotations) {
+            if (annotation.getType().equals(CDD_REQUIREMENT_ANNOTATION)) {
+                for (AnnotationElement annotationElement : annotation.getElements()) {
+                    if (annotationElement.getName().equals(CDD_REQUIREMENT_ELEMENT_NAME)) {
+                        String cddRequirement =
+                                ((StringEncodedValue) annotationElement.getValue()).getValue();
+                        CddCoverage.TestMethod testMethod =
+                                new CddCoverage.TestMethod(
+                                        moduleName, dexToJavaName(className), methodName);
+                        cddCoverage.addCoverage(cddRequirement, testMethod);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Given a string like Landroid/app/cts/DownloadManagerTest;
+     * return android.app.cts.DownloadManagerTest.
+     */
+    private static String dexToJavaName(String dexName) {
+        if (!dexName.startsWith("L") || !dexName.endsWith(";")) {
+            return dexName;
+        }
+        dexName = dexName.replace('/', '.');
+        if (dexName.length() > 2) {
+            dexName = dexName.substring(1, dexName.length() - 1);
+        }
+        return dexName;
+    }
+
+    private static CddCoverage getEmptyCddCoverage() {
+        CddCoverage cddCoverage = new CddCoverage();
+        // TODO(nicksauer): Read in the valid list of requirements
+        return cddCoverage;
+    }
+
+    private static void outputCoverageReport(ApiCoverage apiCoverage, CddCoverage cddCoverage,
+            List<File> testApks, File outputFile, int format, PackageFilter packageFilter,
+            String reportTitle)
                 throws IOException, TransformerException, InterruptedException {
 
         OutputStream out = outputFile != null
@@ -213,15 +338,17 @@
         try {
             switch (format) {
                 case FORMAT_TXT:
-                    TextReport.printTextReport(apiCoverage, packageFilter, out);
+                    TextReport.printTextReport(apiCoverage, cddCoverage, packageFilter, out);
                     break;
 
                 case FORMAT_XML:
-                    XmlReport.printXmlReport(testApks, apiCoverage, packageFilter, reportTitle, out);
+                    XmlReport.printXmlReport(testApks, apiCoverage, cddCoverage,
+                        packageFilter, reportTitle, out);
                     break;
 
                 case FORMAT_HTML:
-                    HtmlReport.printHtmlReport(testApks, apiCoverage, packageFilter, reportTitle, out);
+                    HtmlReport.printHtmlReport(testApks, apiCoverage, cddCoverage,
+                        packageFilter, reportTitle, out);
                     break;
             }
         } finally {
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/HtmlReport.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/HtmlReport.java
index 0e6b54a..f53a884 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicoverage/HtmlReport.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/HtmlReport.java
@@ -37,7 +37,8 @@
 class HtmlReport {
 
     public static void printHtmlReport(final List<File> testApks, final ApiCoverage apiCoverage,
-            final PackageFilter packageFilter, final String reportTitle, final OutputStream out)
+            final CddCoverage cddCoverage, final PackageFilter packageFilter,
+            final String reportTitle, final OutputStream out)
                 throws IOException, TransformerException {
         final PipedOutputStream xmlOut = new PipedOutputStream();
         final PipedInputStream xmlIn = new PipedInputStream(xmlOut);
@@ -45,7 +46,8 @@
         Thread t = new Thread(new Runnable() {
             @Override
             public void run() {
-                XmlReport.printXmlReport(testApks, apiCoverage, packageFilter, reportTitle, xmlOut);
+                XmlReport.printXmlReport(
+                    testApks, apiCoverage, cddCoverage, packageFilter, reportTitle, xmlOut);
 
                 // Close the output stream to avoid "Write dead end" errors.
                 try {
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/JarTestFinder.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/JarTestFinder.java
new file mode 100644
index 0000000..2aa3e72
--- /dev/null
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/JarTestFinder.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.apicoverage;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+/** Representation of the entire CDD. */
+class JarTestFinder {
+
+    public static Collection<Class<?>> getClasses(File jarTestFile)
+            throws IllegalArgumentException  {
+        List<Class<?>> classes = new ArrayList<>();
+
+        try (JarFile jarFile = new JarFile(jarTestFile)) {
+            Enumeration<JarEntry> e = jarFile.entries();
+
+            URL[] urls = {
+                new URL(String.format("jar:file:%s!/", jarTestFile.getAbsolutePath()))
+            };
+            URLClassLoader cl = URLClassLoader.newInstance(urls, JarTestFinder.class.getClassLoader());
+
+            while (e.hasMoreElements()) {
+                JarEntry je = e.nextElement();
+                if (je.isDirectory() || !je.getName().endsWith(".class")
+                        || je.getName().contains("$")) {
+                    continue;
+                }
+                String className = getClassName(je.getName());
+                if (!className.endsWith("Test")) {
+                    continue;
+                }
+                try {
+                    Class<?> cls = cl.loadClass(className);
+                    int modifiers = cls.getModifiers();
+                    if (!Modifier.isStatic(modifiers)
+                            && !Modifier.isPrivate(modifiers)
+                            && !Modifier.isProtected(modifiers)
+                            && !Modifier.isInterface(modifiers)
+                            && !Modifier.isAbstract(modifiers)) {
+
+                        classes.add(cls);
+                    }
+                } catch (ClassNotFoundException | Error x) {
+                    System.err.println(
+                            String.format("Cannot find test class %s from %s",
+                                    className, jarTestFile.getName()));
+                    x.printStackTrace();
+                }
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return classes;
+    }
+
+    private static String getClassName(String name) {
+        // -6 because of .class
+        return name.substring(0, name.length() - 6).replace('/', '.');
+    }
+}
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/TextReport.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/TextReport.java
index 3adc020..978a652 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicoverage/TextReport.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/TextReport.java
@@ -27,8 +27,8 @@
  */
 class TextReport {
 
-    public static void printTextReport(ApiCoverage api, PackageFilter packageFilter,
-            OutputStream outputStream) {
+    public static void printTextReport(ApiCoverage api, CddCoverage CddCoverage,
+            PackageFilter packageFilter, OutputStream outputStream) {
         PrintStream out = new PrintStream(outputStream);
 
         CoverageComparator comparator = new CoverageComparator();
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/XmlReport.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/XmlReport.java
index 2ba16cf..e6ac3af 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicoverage/XmlReport.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/XmlReport.java
@@ -33,7 +33,8 @@
 class XmlReport {
 
     public static void printXmlReport(List<File> testApks, ApiCoverage apiCoverage,
-            PackageFilter packageFilter, String reportTitle, OutputStream outputStream) {
+            CddCoverage cddCoverage, PackageFilter packageFilter, String reportTitle,
+            OutputStream outputStream) {
         PrintStream out = new PrintStream(outputStream);
         out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
         out.println("<?xml-stylesheet type=\"text/xsl\"  href=\"api-coverage.xsl\"?>");
@@ -137,6 +138,20 @@
         }
 
         out.println("</api>");
+        out.println("<cdd>");
+        for (CddCoverage.CddRequirement requirement : cddCoverage.getCddRequirements()) {
+            out.println("<requirement id=\"" + requirement.getRequirementId() + "\">");
+            for (CddCoverage.TestMethod method : requirement.getTestMethods()) {
+                out.print("<test module=\"" + method.getTestModule()
+                        + "\" class=\"" + method.getTestClass() + "\" ");
+                if (method.getTestMethod() != null) {
+                    out.print("method=\"" + method.getTestMethod() + "\"");
+                }
+                out.println("/>" );
+            }
+            out.println("</requirement>");
+        }
+        out.println("</cdd>");
         out.println("<total numCovered=\"" + totalCoveredMethods + "\" "
                 + "numTotal=\"" + totalMethods + "\" "
                 + "coveragePercentage=\""
diff --git a/tools/cts-device-info/src/com/android/cts/deviceinfo/SampleDeviceInfo.java b/tools/cts-device-info/src/com/android/cts/deviceinfo/SampleDeviceInfo.java
index 8d3d7ada..67db187 100644
--- a/tools/cts-device-info/src/com/android/cts/deviceinfo/SampleDeviceInfo.java
+++ b/tools/cts-device-info/src/com/android/cts/deviceinfo/SampleDeviceInfo.java
@@ -33,6 +33,7 @@
         double[] doubles = {Double.MAX_VALUE, Double.MIN_VALUE};
         int[] ints = {Integer.MAX_VALUE, Integer.MIN_VALUE};
         long[] longs = {Long.MAX_VALUE, Long.MIN_VALUE};
+        float[] floats = {Float.MAX_VALUE, Float.MIN_VALUE, Float.NaN};
 
         // Group Foo
         store.startGroup("foo");
@@ -49,12 +50,16 @@
         store.addArrayResult("bar_double", doubles);
         store.addArrayResult("bar_int", ints);
         store.addArrayResult("bar_long", longs);
+        store.addArrayResult("bar_float", floats);
         store.endGroup(); // bar
 
         store.addResult("foo_double", Double.MAX_VALUE);
         store.addResult("foo_int", Integer.MAX_VALUE);
         store.addResult("foo_long", Long.MAX_VALUE);
         store.addResult("foo_string", "foo-string");
+        store.addResult("foo_float_nan", Float.NaN);
+        store.addResult("foo_float_max", Float.MAX_VALUE + 1);
+        store.addResult("foo_float_min", Float.MIN_VALUE - 1);
         store.endGroup(); // foo
     }
 }
diff --git a/tools/cts-tradefed/Android.mk b/tools/cts-tradefed/Android.mk
index bb4b934..c2afbae 100644
--- a/tools/cts-tradefed/Android.mk
+++ b/tools/cts-tradefed/Android.mk
@@ -25,7 +25,7 @@
 LOCAL_SUITE_TARGET_ARCH := $(TARGET_ARCH)
 LOCAL_SUITE_NAME := CTS
 LOCAL_SUITE_FULLNAME := "Compatibility Test Suite"
-LOCAL_SUITE_VERSION := 7.1_r1
+LOCAL_SUITE_VERSION := 7.1_r201702s
 
 LOCAL_MODULE := cts-tradefed
 
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index 7983c75..0eb366f 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -26,6 +26,9 @@
     <!-- b/23776083 -->
     <option name="compatibility:exclude-filter" value="CtsAlarmClockTestCases" />
 
+    <!-- b/31156007 will need framework fix https://android.googlesource.com/platform/frameworks/base/+/20488d97cdc9aa7e98f6fd75c2890ba18781654a -->
+    <option name="compatibility:exclude-filter" value="CtsAppSecurityHostTestCases android.appsecurity.cts.ScopedDirectoryAccessTest#testDeniesOnceForAllClearedWhenPackageRemoved" />
+
     <!-- b/17993121 -->
     <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testAppWidgetProviderCallbacks" />
     <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testBindAppWidget" />
@@ -70,6 +73,15 @@
     <option name="compatibility:exclude-filter" value="CtsDumpsysHostTestCases android.dumpsys.cts.DumpsysHostTest#testBatterystatsOutput" />
     <option name="compatibility:exclude-filter" value="CtsDumpsysHostTestCases android.dumpsys.cts.DumpsysHostTest#testGfxinfoFramestats" />
 
+    <!-- b/31199016 will need platform fix https://android.googlesource.com/platform/frameworks/base/+/11a84b8429c2cf395b99c852d232a490ba1c9975 to pass -->
+    <option name="compatibility:exclude-filter" value="CtsGraphicsTestCases android.graphics.drawable.cts.ThemedDrawableTest#testLayerDrawable" />
+
+    <!-- b/31306911 will need platform fixes
+         https://android.googlesource.com/platform/frameworks/base/+/0a815bb94fa2aad016a10fe23633efc5682d2a7c and
+         https://android.googlesource.com/platform/frameworks/base/+/0c03664fa6acbe5c3fd11d54ab9a6792f43dda07 to pass -->
+    <option name="compatibility:exclude-filter" value="CtsGraphicsTestCases android.graphics.drawable.cts.CustomAnimationScaleListDrawableTest#testNonZeroDurationScale" />
+    <option name="compatibility:exclude-filter" value="CtsGraphicsTestCases android.graphics.drawable.cts.CustomAnimationScaleListDrawableTest#testZeroDurationScale" />
+
     <!-- b/22922206 b/27534791 -->
     <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SensorBatchingTests#testAccelerometer_50hz_batching" />
     <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SensorBatchingTests#testAccelerometer_fastest_batching" />
@@ -100,31 +112,19 @@
     <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SingleSensorTests#testMagneticFieldUncalibrated_200hz" />
     <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SingleSensorTests#testOrientation_5hz" />
 
-    <!-- b/16720689 -->
-    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowDebuggerLaunchTest#testDebuggerLaunch001" />
-    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowDebuggerLaunchTest#testDebuggerLaunch002" />
-    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowDebuggerLaunchTest#testDebuggerLaunch003" />
-    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowDebuggerLaunchTest#testDebuggerLaunch004" />
-    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowLaunchDebugger001#testDebugger002" />
-    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowLaunchDebugger002#testDebugger" />
-    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.Events.ClassUnloadTest#testClassUnloadEvent" />
-    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.Events.MonitorContendedEnteredTest#testMonitorContendedEnteredForClassMatch" />
-    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.Events.MonitorContendedEnterTest#testMonitorContendedEnterForClassMatch" />
-    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitedTest#testMonitorWaitedForClassExclude" />
-    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitedTest#testMonitorWaitedForClassMatchExact" />
-    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitedTest#testMonitorWaitedForClassMatchFirst" />
-    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitedTest#testMonitorWaitedForClassMatchSecond" />
-    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitedTest#testMonitorWaitedForClassOnly" />
-    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitTest#testMonitorWaitForClassExclude" />
-    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitTest#testMonitorWaitForClassMatchExact" />
-    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitTest#testMonitorWaitForClassMatchFirst" />
-    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitTest#testMonitorWaitForClassMatchSecond" />
-    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitTest#testMonitorWaitForClassOnly" />
-    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.ReferenceType.ClassFileVersionTest#testClassFileVersion001" />
-    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.ReferenceType.NestedTypesTest#testNestedTypes001" />
-    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.ThreadReference.StopTest#testStop001" />
-    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.VirtualMachine.HoldEventsTest#testHoldEvents001" />
-    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.VirtualMachine.ReleaseEventsTest#testReleaseEvents001" />
+    <!-- b/31153233 will need platform fix https://android.googlesource.com/platform/external/apache-harmony/+/5617ae1cb798e58748946c0fa4299f5d982c7b8b to pass -->
+    <option name="compatibility:exclude-filter" value="CtsJdwpTestCases org.apache.harmony.jpda.tests.jdwp.ClassType.NewInstanceStringTest#testNewInstanceString_ByteArrayArgConstructor" />
+    <option name="compatibility:exclude-filter" value="CtsJdwpTestCases org.apache.harmony.jpda.tests.jdwp.ClassType.NewInstanceStringTest#testNewInstanceString_ByteArrayCharsetConstructor" />
+    <option name="compatibility:exclude-filter" value="CtsJdwpTestCases org.apache.harmony.jpda.tests.jdwp.ClassType.NewInstanceStringTest#testNewInstanceString_ByteArrayIntIntCharsetConstructor" />
+    <option name="compatibility:exclude-filter" value="CtsJdwpTestCases org.apache.harmony.jpda.tests.jdwp.ClassType.NewInstanceStringTest#testNewInstanceString_ByteArrayIntIntConstructor" />
+    <option name="compatibility:exclude-filter" value="CtsJdwpTestCases org.apache.harmony.jpda.tests.jdwp.ClassType.NewInstanceStringTest#testNewInstanceString_ByteArrayIntIntStringConstructor" />
+    <option name="compatibility:exclude-filter" value="CtsJdwpTestCases org.apache.harmony.jpda.tests.jdwp.ClassType.NewInstanceStringTest#testNewInstanceString_ByteArrayStringConstructor" />
+    <option name="compatibility:exclude-filter" value="CtsJdwpTestCases org.apache.harmony.jpda.tests.jdwp.ClassType.NewInstanceStringTest#testNewInstanceString_CharArrayConstructor" />
+    <option name="compatibility:exclude-filter" value="CtsJdwpTestCases org.apache.harmony.jpda.tests.jdwp.ClassType.NewInstanceStringTest#testNewInstanceString_CharArrayIntIntConstructor" />
+    <option name="compatibility:exclude-filter" value="CtsJdwpTestCases org.apache.harmony.jpda.tests.jdwp.ClassType.NewInstanceStringTest#testNewInstanceString_IntArrayIntIntConstructor" />
+    <option name="compatibility:exclude-filter" value="CtsJdwpTestCases org.apache.harmony.jpda.tests.jdwp.ClassType.NewInstanceStringTest#testNewInstanceString_StringBufferConstructor" />
+    <option name="compatibility:exclude-filter" value="CtsJdwpTestCases org.apache.harmony.jpda.tests.jdwp.ClassType.NewInstanceStringTest#testNewInstanceString_StringBuilderConstructor" />
+    <option name="compatibility:exclude-filter" value="CtsJdwpTestCases org.apache.harmony.jpda.tests.jdwp.ClassType.NewInstanceStringTest#testNewInstanceString_StringConstructor" />
 
     <!-- b/18117279 b/21262226 b/23144425 -->
     <option name="compatibility:exclude-filter" value="CtsJobSchedulerTestCases android.jobscheduler.cts.ConnectivityConstraintTest#testConnectivityConstraintExecutes_withMobile" />
@@ -133,6 +133,24 @@
     <option name="compatibility:exclude-filter" value="CtsJobSchedulerTestCases android.jobscheduler.cts.ConnectivityConstraintTest#testUnmeteredConstraintFails_withMobile" />
     <option name="compatibility:exclude-filter" value="CtsJobSchedulerTestCases android.jobscheduler.cts.TimingConstraintsTest#testJobParameters_unexpiredDeadline" />
 
+    <!-- b/31157079 will need platform fix https://android.googlesource.com/platform/libcore/+/4149edc81ea22ef954aa443e0c70e5d3cb55341b to pass -->
+    <option name="compatibility:exclude-filter" value="CtsLibcoreTestCases libcore.java.util.TimeZoneTest#testDisplayNamesWithScript" />
+
+    <!-- b/31157557 will need platform fix https://android.googlesource.com/platform/libcore/+/7b7ce9368f104eef4cf337a8a2067e5cf345ccc0 to pass -->
+    <option name="compatibility:exclude-filter" value="CtsLibcoreTestCases libcore.java.net.SocketTest#testSocketTestAllAddresses" />
+
+    <!-- b/31305368 will need platform fix https://android.googlesource.com/platform/external/conscrypt/+/f24631e45c6bef8135cd9e82bfb30cf56fd8acb6 to pass -->
+    <option name="compatibility:exclude-filter" value="CtsLibcoreTestCases libcore.javax.crypto.MacTest#testMac_correctAlias" />
+
+    <!-- b/31151341 will need platform fix https://android.googlesource.com/platform/libcore/+/4a2b94a98213fcf628f6d4de034a109695d908cc to pass -->
+    <option name="compatibility:exclude-filter" value="CtsLibcoreTestCases libcore.net.MimeUtilsTest#test_30793548" />
+
+    <!-- b/31155940 will need platform fix https://android.googlesource.com/platform/libcore/+/08e9e364940586cb242839c8f0e303b82438f58b to pass -->
+    <option name="compatibility:exclude-filter" value="CtsLibcoreTestCases org.apache.harmony.tests.java.util.VectorTest#test_listIterator_addAndPrevious" />
+
+    <!-- b/31535558 will need platform fix https://android.googlesource.com/platform/frameworks/base/+/4e82fe51207bbd8ceaec356b4215e338ec63a31e to pass -->
+    <option name="compatibility:exclude-filter" value="CtsLocationTestCases android.location.cts.GnssStatusTest#testGnssStatusChanges" />
+
     <!-- b/25850508 -->
     <option name="compatibility:exclude-filter" value="CtsMediaStressTestCases android.mediastress.cts.preconditions.MediaPreparerTest#testCopyMediaFiles" />
     <option name="compatibility:exclude-filter" value="CtsMediaStressTestCases android.mediastress.cts.preconditions.MediaPreparerTest#testMediaFilesExistOnDeviceFalse" />
@@ -161,6 +179,9 @@
     <!-- b/18091590 -->
     <option name="compatibility:exclude-filter" value="CtsOpenGlPerfTestCases android.openglperf.cts.GlVboPerfTest#testVboWithVaryingIndexBufferNumbers" />
 
+    <!-- b/31306874 will need platform fix https://android.googlesource.com/platform/frameworks/base/+/5eb91a437c551ed0c66b38299f988f8159ada207 to pass -->
+    <option name="compatibility:exclude-filter" value="CtsOsTestCases android.os.cts.AsyncTaskTest#testCancellationWithException" />
+
     <!-- b/23192492 -->
     <option name="compatibility:exclude-filter" value="CtsPermission2TestCases android.permission2.cts.ProtectedBroadcastsTest#testSendProtectedBroadcasts" />
 
@@ -205,6 +226,9 @@
     <option name="compatibility:exclude-filter" value="CtsUsageStatsTestCases android.app.usage.cts.UsageStatsTest#testPackageUsageStatsIntervals" />
     <option name="compatibility:exclude-filter" value="CtsUsageStatsTestCases android.app.usage.cts.UsageStatsTest#testUsageEventsParceling" />
 
+    <!-- b/31469490 -->
+    <option name="compatibility:exclude-filter" value="CtsViewTestCases android.view.cts.DragDropTest" />
+
     <!-- b/23238984 -->
     <option name="compatibility:exclude-filter" value="CtsVoiceSettingsTestCases android.voicesettings.cts.ZenModeTest#testAll" />