Merge "CTS Tests for DreamService#onWindowStartingActionMode" into mnc-dev
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index ae6c16c..c66341d 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -167,7 +167,6 @@
     CtsUtilTestCases \
     CtsViewTestCases \
     CtsWebkitTestCases \
-    CtsWebGLTestCases \
     CtsWidgetTestCases
 
 # All APKs that need to be scanned by the coverage utilities.
diff --git a/apps/CameraITS/pymodules/its/objects.py b/apps/CameraITS/pymodules/its/objects.py
index f6d2e2d..bc77a62 100644
--- a/apps/CameraITS/pymodules/its/objects.py
+++ b/apps/CameraITS/pymodules/its/objects.py
@@ -70,7 +70,8 @@
     else:
         return float(r["numerator"]) / float(r["denominator"])
 
-def manual_capture_request(sensitivity, exp_time, linear_tonemap=False):
+def manual_capture_request(
+        sensitivity, exp_time, linear_tonemap=False, props=None):
     """Return a capture request with everything set to manual.
 
     Uses identity/unit color correction, and the default tonemap curve.
@@ -82,6 +83,9 @@
             with.
         linear_tonemap: [Optional] whether a linear tonemap should be used
             in this request.
+        props: [Optional] the object returned from
+            its.device.get_camera_properties(). Must present when
+            linear_tonemap is True.
 
     Returns:
         The default manual capture request, ready to be passed to the
@@ -105,10 +109,20 @@
         "android.shading.mode": 1
         }
     if linear_tonemap:
-        req["android.tonemap.mode"] = 0
-        req["android.tonemap.curveRed"] = [0.0,0.0, 1.0,1.0]
-        req["android.tonemap.curveGreen"] = [0.0,0.0, 1.0,1.0]
-        req["android.tonemap.curveBlue"] = [0.0,0.0, 1.0,1.0]
+        assert(props is not None)
+        #CONTRAST_CURVE mode
+        if 0 in props["android.tonemap.availableToneMapModes"]:
+            req["android.tonemap.mode"] = 0
+            req["android.tonemap.curveRed"] = [0.0,0.0, 1.0,1.0]
+            req["android.tonemap.curveGreen"] = [0.0,0.0, 1.0,1.0]
+            req["android.tonemap.curveBlue"] = [0.0,0.0, 1.0,1.0]
+        #GAMMA_VALUE mode
+        elif 3 in props["android.tonemap.availableToneMapModes"]:
+            req["android.tonemap.mode"] = 3
+            req["android.tonemap.gamma"] = 1.0
+        else:
+            print "Linear tonemap is not supported"
+            assert(False)
     return req
 
 def auto_capture_request():
diff --git a/apps/CameraITS/tests/scene1/test_crop_region_raw.py b/apps/CameraITS/tests/scene1/test_crop_region_raw.py
index 189e987..7973755 100644
--- a/apps/CameraITS/tests/scene1/test_crop_region_raw.py
+++ b/apps/CameraITS/tests/scene1/test_crop_region_raw.py
@@ -64,7 +64,7 @@
         # Use a manual request with a linear tonemap so that the YUV and RAW
         # should look the same (once converted by the its.image module).
         e, s = its.target.get_target_exposure_combos(cam)["minSensitivity"]
-        req = its.objects.manual_capture_request(s,e, True)
+        req = its.objects.manual_capture_request(s,e, True, props)
         cap1_raw, cap1_yuv = cam.do_capture(req, cam.CAP_RAW_YUV)
 
         # Capture with a crop region.
diff --git a/apps/CameraITS/tests/scene1/test_jpeg.py b/apps/CameraITS/tests/scene1/test_jpeg.py
index 25c2038..7bc038d 100644
--- a/apps/CameraITS/tests/scene1/test_jpeg.py
+++ b/apps/CameraITS/tests/scene1/test_jpeg.py
@@ -33,7 +33,7 @@
                              its.caps.per_frame_control(props))
 
         e, s = its.target.get_target_exposure_combos(cam)["midExposureTime"]
-        req = its.objects.manual_capture_request(s, e, True)
+        req = its.objects.manual_capture_request(s, e, True, props)
 
         # YUV
         size = its.objects.get_available_output_sizes("yuv", props)[0]
diff --git a/apps/CameraITS/tests/scene1/test_latching.py b/apps/CameraITS/tests/scene1/test_latching.py
index 3bc4356..176f01b 100644
--- a/apps/CameraITS/tests/scene1/test_latching.py
+++ b/apps/CameraITS/tests/scene1/test_latching.py
@@ -45,20 +45,20 @@
         b_means = []
 
         reqs = [
-            its.objects.manual_capture_request(s,  e,   True),
-            its.objects.manual_capture_request(s,  e,   True),
-            its.objects.manual_capture_request(s*2,e,   True),
-            its.objects.manual_capture_request(s*2,e,   True),
-            its.objects.manual_capture_request(s,  e,   True),
-            its.objects.manual_capture_request(s,  e,   True),
-            its.objects.manual_capture_request(s,  e*2, True),
-            its.objects.manual_capture_request(s,  e,   True),
-            its.objects.manual_capture_request(s*2,e,   True),
-            its.objects.manual_capture_request(s,  e,   True),
-            its.objects.manual_capture_request(s,  e*2, True),
-            its.objects.manual_capture_request(s,  e,   True),
-            its.objects.manual_capture_request(s,  e*2, True),
-            its.objects.manual_capture_request(s,  e*2, True),
+            its.objects.manual_capture_request(s,  e,   True, props),
+            its.objects.manual_capture_request(s,  e,   True, props),
+            its.objects.manual_capture_request(s*2,e,   True, props),
+            its.objects.manual_capture_request(s*2,e,   True, props),
+            its.objects.manual_capture_request(s,  e,   True, props),
+            its.objects.manual_capture_request(s,  e,   True, props),
+            its.objects.manual_capture_request(s,  e*2, True, props),
+            its.objects.manual_capture_request(s,  e,   True, props),
+            its.objects.manual_capture_request(s*2,e,   True, props),
+            its.objects.manual_capture_request(s,  e,   True, props),
+            its.objects.manual_capture_request(s,  e*2, True, props),
+            its.objects.manual_capture_request(s,  e,   True, props),
+            its.objects.manual_capture_request(s,  e*2, True, props),
+            its.objects.manual_capture_request(s,  e*2, True, props),
             ]
 
         caps = cam.do_capture(reqs, fmt)
diff --git a/apps/CameraITS/tests/scene1/test_locked_burst.py b/apps/CameraITS/tests/scene1/test_locked_burst.py
index 958fc72..6552c73 100644
--- a/apps/CameraITS/tests/scene1/test_locked_burst.py
+++ b/apps/CameraITS/tests/scene1/test_locked_burst.py
@@ -32,7 +32,8 @@
     NAME = os.path.basename(__file__).split(".")[0]
 
     BURST_LEN = 8
-    SPREAD_THRESH = 0.005
+    SPREAD_THRESH_MANUAL_SENSOR = 0.005
+    SPREAD_THRESH = 0.03
     FPS_MAX_DIFF = 2.0
 
     with its.device.ItsSession() as cam:
@@ -67,8 +68,10 @@
         for means in [r_means, g_means, b_means]:
             spread = max(means) - min(means)
             print "Patch mean spread", spread, \
-                   " (min/max: ",  min(means), "/", max(means), ")"
-            assert(spread < SPREAD_THRESH)
+                    " (min/max: ",  min(means), "/", max(means), ")"
+            threshold = SPREAD_THRESH_MANUAL_SENSOR \
+                    if its.caps.manual_sensor(props) else SPREAD_THRESH
+            assert(spread < threshold)
 
 if __name__ == '__main__':
     main()
diff --git a/apps/CameraITS/tests/scene1/test_param_color_correction.py b/apps/CameraITS/tests/scene1/test_param_color_correction.py
index b7fdc7b..09b3707 100644
--- a/apps/CameraITS/tests/scene1/test_param_color_correction.py
+++ b/apps/CameraITS/tests/scene1/test_param_color_correction.py
@@ -42,7 +42,7 @@
 
         # Baseline request
         e, s = its.target.get_target_exposure_combos(cam)["midSensitivity"]
-        req = its.objects.manual_capture_request(s, e, True)
+        req = its.objects.manual_capture_request(s, e, True, props)
         req["android.colorCorrection.mode"] = 0
 
         # Transforms:
diff --git a/apps/CameraITS/tests/scene1/test_param_exposure_time.py b/apps/CameraITS/tests/scene1/test_param_exposure_time.py
index e6078d9..0c0aab1 100644
--- a/apps/CameraITS/tests/scene1/test_param_exposure_time.py
+++ b/apps/CameraITS/tests/scene1/test_param_exposure_time.py
@@ -39,7 +39,7 @@
 
         e,s = its.target.get_target_exposure_combos(cam)["midExposureTime"]
         for i,e_mult in enumerate([0.8, 0.9, 1.0, 1.1, 1.2]):
-            req = its.objects.manual_capture_request(s, e * e_mult, True)
+            req = its.objects.manual_capture_request(s, e * e_mult, True, props)
             cap = cam.do_capture(req)
             img = its.image.convert_capture_to_rgb_image(cap)
             its.image.write_image(
diff --git a/apps/CameraITS/tests/scene1/test_param_flash_mode.py b/apps/CameraITS/tests/scene1/test_param_flash_mode.py
index aae56aa..38f864f 100644
--- a/apps/CameraITS/tests/scene1/test_param_flash_mode.py
+++ b/apps/CameraITS/tests/scene1/test_param_flash_mode.py
@@ -39,7 +39,7 @@
         # linear tonemap.
         e, s = its.target.get_target_exposure_combos(cam)["midExposureTime"]
         e /= 4
-        req = its.objects.manual_capture_request(s, e, True)
+        req = its.objects.manual_capture_request(s, e, True, props)
 
         for f in [0,1,2]:
             req["android.flash.mode"] = f
diff --git a/apps/CameraITS/tests/scene1/test_param_shading_mode.py b/apps/CameraITS/tests/scene1/test_param_shading_mode.py
new file mode 100644
index 0000000..65b7e97
--- /dev/null
+++ b/apps/CameraITS/tests/scene1/test_param_shading_mode.py
@@ -0,0 +1,109 @@
+# 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 its.caps
+import its.device
+import its.objects
+import matplotlib
+import numpy
+import os
+import os.path
+import pylab
+
+def main():
+    """Test that the android.shading.mode param is applied.
+
+    Switching shading modes and checks that the lens shading maps are
+    modified as expected.
+    """
+    NAME = os.path.basename(__file__).split(".")[0]
+
+    NUM_SHADING_MODE_SWITCH_LOOPS = 3
+    THRESHOLD_DIFF_RATIO = 0.15
+
+    with its.device.ItsSession() as cam:
+        props = cam.get_camera_properties()
+
+        its.caps.skip_unless(its.caps.per_frame_control(props))
+
+        assert(props.has_key("android.lens.info.shadingMapSize") and
+               props["android.lens.info.shadingMapSize"] != None)
+
+        num_map_gains = props["android.lens.info.shadingMapSize"]["width"] * \
+                        props["android.lens.info.shadingMapSize"]["height"] * 4
+
+        # Test 1: Switching shading modes several times and verify:
+        #   1. Lens shading maps with mode OFF are all 1.0
+        #   2. Lens shading maps with mode FAST are similar after switching
+        #      shading modes.
+        #   3. Lens shading maps with mode HIGH_QUALITY are similar after
+        #      switching shading modes.
+        cam.do_3a();
+
+        # Get the reference lens shading maps for OFF, FAST, and HIGH_QUALITY
+        # in different sessions.
+        # reference_maps[mode]
+        reference_maps = [[] for mode in range(3)]
+        reference_maps[0] = [1.0] * num_map_gains
+        for mode in range(1, 3):
+            req = its.objects.auto_capture_request();
+            req["android.statistics.lensShadingMapMode"] = 1
+            req["android.shading.mode"] = mode
+            reference_maps[mode] = cam.do_capture(req)["metadata"] \
+                    ["android.statistics.lensShadingMap"]
+
+        # Get the lens shading maps while switching modes in one session.
+        reqs = []
+        for i in range(NUM_SHADING_MODE_SWITCH_LOOPS):
+            for mode in range(3):
+                req = its.objects.auto_capture_request();
+                req["android.statistics.lensShadingMapMode"] = 1
+                req["android.shading.mode"] = mode
+                reqs.append(req);
+
+        caps = cam.do_capture(reqs)
+
+        # shading_maps[mode][loop]
+        shading_maps = [[[] for loop in range(NUM_SHADING_MODE_SWITCH_LOOPS)]
+                for mode in range(3)]
+
+        # Get the shading maps out of capture results
+        for i in range(len(caps)):
+            shading_maps[i % 3][i / 3] = \
+                    caps[i]["metadata"]["android.statistics.lensShadingMap"]
+
+        # Draw the maps
+        for mode in range(3):
+            for i in range(NUM_SHADING_MODE_SWITCH_LOOPS):
+                pylab.clf()
+                pylab.plot(range(num_map_gains), shading_maps[mode][i], 'r')
+                pylab.plot(range(num_map_gains), reference_maps[mode], 'g')
+                pylab.xlim([0, num_map_gains])
+                pylab.ylim([0.9, 4.0])
+                matplotlib.pyplot.savefig("%s_ls_maps_mode_%d_loop_%d.png" %
+                                          (NAME, mode, i))
+
+        print "Verifying lens shading maps with mode OFF are all 1.0"
+        for i in range(NUM_SHADING_MODE_SWITCH_LOOPS):
+            assert(numpy.allclose(shading_maps[0][i], reference_maps[0]))
+
+        for mode in range(1, 3):
+            print "Verifying lens shading maps with mode", mode, "are similar"
+            for i in range(NUM_SHADING_MODE_SWITCH_LOOPS):
+                assert(numpy.allclose(shading_maps[mode][i],
+                                      reference_maps[mode],
+                                      THRESHOLD_DIFF_RATIO))
+
+if __name__ == '__main__':
+    main()
diff --git a/apps/CameraITS/tests/scene1/test_tonemap_sequence.py b/apps/CameraITS/tests/scene1/test_tonemap_sequence.py
index 18ca506..7c87ca2 100644
--- a/apps/CameraITS/tests/scene1/test_tonemap_sequence.py
+++ b/apps/CameraITS/tests/scene1/test_tonemap_sequence.py
@@ -40,7 +40,7 @@
         means = []
 
         # Capture 3 manual shots with a linear tonemap.
-        req = its.objects.manual_capture_request(sens, exp_time, True)
+        req = its.objects.manual_capture_request(sens, exp_time, True, props)
         for i in [0,1,2]:
             cap = cam.do_capture(req)
             img = its.image.convert_capture_to_rgb_image(cap)
diff --git a/apps/CameraITS/tests/scene1/test_yuv_jpeg_all.py b/apps/CameraITS/tests/scene1/test_yuv_jpeg_all.py
index 1b278ef..0c428fc 100644
--- a/apps/CameraITS/tests/scene1/test_yuv_jpeg_all.py
+++ b/apps/CameraITS/tests/scene1/test_yuv_jpeg_all.py
@@ -35,7 +35,7 @@
         # Use a manual request with a linear tonemap so that the YUV and JPEG
         # should look the same (once converted by the its.image module).
         e, s = its.target.get_target_exposure_combos(cam)["midExposureTime"]
-        req = its.objects.manual_capture_request(s, e, True)
+        req = its.objects.manual_capture_request(s, e, True, props)
 
         rgbs = []
 
diff --git a/apps/CameraITS/tests/scene1/test_yuv_plus_jpeg.py b/apps/CameraITS/tests/scene1/test_yuv_plus_jpeg.py
index 6daa243..9ce8d76 100644
--- a/apps/CameraITS/tests/scene1/test_yuv_plus_jpeg.py
+++ b/apps/CameraITS/tests/scene1/test_yuv_plus_jpeg.py
@@ -37,7 +37,7 @@
         # Use a manual request with a linear tonemap so that the YUV and JPEG
         # should look the same (once converted by the its.image module).
         e, s = its.target.get_target_exposure_combos(cam)["midExposureTime"]
-        req = its.objects.manual_capture_request(s, e, True)
+        req = its.objects.manual_capture_request(s, e, True, props)
 
         cap_yuv, cap_jpeg = cam.do_capture(req, [fmt_yuv, fmt_jpeg])
 
diff --git a/apps/CameraITS/tests/scene1/test_yuv_plus_raw.py b/apps/CameraITS/tests/scene1/test_yuv_plus_raw.py
index eb01c1a..f13801b 100644
--- a/apps/CameraITS/tests/scene1/test_yuv_plus_raw.py
+++ b/apps/CameraITS/tests/scene1/test_yuv_plus_raw.py
@@ -36,7 +36,7 @@
         # Use a manual request with a linear tonemap so that the YUV and RAW
         # should look the same (once converted by the its.image module).
         e, s = its.target.get_target_exposure_combos(cam)["midExposureTime"]
-        req = its.objects.manual_capture_request(s, e, True)
+        req = its.objects.manual_capture_request(s, e, True, props)
 
         cap_raw, cap_yuv = cam.do_capture(req, cam.CAP_RAW_YUV)
 
diff --git a/apps/CameraITS/tests/scene1/test_yuv_plus_raw10.py b/apps/CameraITS/tests/scene1/test_yuv_plus_raw10.py
index 910a8ea..e52946d 100644
--- a/apps/CameraITS/tests/scene1/test_yuv_plus_raw10.py
+++ b/apps/CameraITS/tests/scene1/test_yuv_plus_raw10.py
@@ -36,7 +36,7 @@
         # Use a manual request with a linear tonemap so that the YUV and RAW
         # should look the same (once converted by the its.image module).
         e, s = its.target.get_target_exposure_combos(cam)["midExposureTime"]
-        req = its.objects.manual_capture_request(s, e, True)
+        req = its.objects.manual_capture_request(s, e, True, props)
 
         cap_raw, cap_yuv = cam.do_capture(req,
                 [{"format":"raw10"}, {"format":"yuv"}])
diff --git a/apps/CameraITS/tests/scene1/test_yuv_plus_raw12.py b/apps/CameraITS/tests/scene1/test_yuv_plus_raw12.py
index bbd9144..c5c3c73 100644
--- a/apps/CameraITS/tests/scene1/test_yuv_plus_raw12.py
+++ b/apps/CameraITS/tests/scene1/test_yuv_plus_raw12.py
@@ -36,7 +36,7 @@
         # Use a manual request with a linear tonemap so that the YUV and RAW
         # should look the same (once converted by the its.image module).
         e, s = its.target.get_target_exposure_combos(cam)["midExposureTime"]
-        req = its.objects.manual_capture_request(s, e, True)
+        req = its.objects.manual_capture_request(s, e, True, props)
 
         cap_raw, cap_yuv = cam.do_capture(req,
                 [{"format":"raw12"}, {"format":"yuv"}])
diff --git a/apps/CtsVerifier/Android.mk b/apps/CtsVerifier/Android.mk
index 37f1f90..b6a7b71 100644
--- a/apps/CtsVerifier/Android.mk
+++ b/apps/CtsVerifier/Android.mk
@@ -26,6 +26,7 @@
 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_v2 \
                                cts-sensors-tests \
                                ctstestrunner \
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 5380601..4226bf2 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -1306,10 +1306,23 @@
                 <action android:name="com.android.cts.verifier.managedprovisioning.BYOD_REMOVE" />
                 <action android:name="com.android.cts.verifier.managedprovisioning.BYOD_INSTALL_APK" />
                 <action android:name="com.android.cts.verifier.managedprovisioning.action.CHECK_INTENT_FILTERS" />
+                <action android:name="com.android.cts.verifier.managedprovisioning.BYOD_CAPTURE_AND_CHECK_IMAGE" />
+                <action android:name="com.android.cts.verifier.managedprovisioning.BYOD_CAPTURE_AND_CHECK_VIDEO" />
+                <action android:name="com.android.cts.verifier.managedprovisioning.BYOD_CAPTURE_AND_CHECK_AUDIO" />
                 <category android:name="android.intent.category.DEFAULT"></category>
             </intent-filter>
         </activity>
 
+        <provider
+            android:name="android.support.v4.content.FileProvider"
+            android:authorities="com.android.cts.verifier.managedprovisioning.fileprovider"
+            android:grantUriPermissions="true"
+            android:exported="false">
+            <meta-data
+                android:name="android.support.FILE_PROVIDER_PATHS"
+                android:resource="@xml/filepaths" />
+        </provider>
+
         <activity android:name=".managedprovisioning.ByodIconSamplerActivity">
             <intent-filter>
                 <action android:name="com.android.cts.verifier.managedprovisioning.BYOD_SAMPLE_ICON" />
diff --git a/apps/CtsVerifier/res/layout/byod_present_media.xml b/apps/CtsVerifier/res/layout/byod_present_media.xml
new file mode 100644
index 0000000..f6c7eb3
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/byod_present_media.xml
@@ -0,0 +1,52 @@
+<?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"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical">
+
+    <ImageView android:id="@+id/imageView"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:scaleType="fitCenter"
+        android:minHeight="300dp"
+        android:minWidth="300dp"
+        android:visibility="gone"/>
+
+    <VideoView android:id="@+id/videoView"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:minHeight="300dp"
+        android:minWidth="300dp"
+        android:layout_gravity="center"
+        android:visibility="gone"/>
+
+    <Button android:id="@+id/playButton"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="0"
+        android:text="@string/provisioning_byod_play"
+        android:visibility="gone"/>
+
+    <Button android:id="@+id/dismissButton"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="0"
+        android:text="@string/provisioning_byod_dismiss_result_dialog"/>
+
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 1b0ca68..9f8f4c1 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -1152,6 +1152,39 @@
         2. Verify that the installation of the package is refused.
     </string>
 
+    <string name="provisioning_byod_capture_image_support">Camera support cross profile image capture</string>
+    <string name="provisioning_byod_capture_image_support_info">
+        This test verifies that images can be captured from the managed profile using the primary profile camera.\n
+        1. Capture a picture using the camera.\n
+        2. Verify that the captured picture is shown.\n
+        3. Click on the close button.
+    </string>
+    <string name="provisioning_byod_capture_video_support">Camera support cross profile video capture</string>
+    <string name="provisioning_byod_capture_video_support_info">
+        This test verifies that videos can be captured from the managed profile using the primary profile camera.\n
+        1. Capture a video using the camera.\n
+        2. Click on the play button.\n
+        3. Verify that the captured video is played.\n
+        4. Click on the close button.
+    </string>
+    <string name="provisioning_byod_capture_audio_support">Sound recorder support cross profile audio capture</string>
+    <string name="provisioning_byod_capture_audio_support_info">
+        This test verifies that audio can be captured from the managed profile using the primary profile sound recorder.\n
+        1. Capture audio.\n
+        2. Click on the play button.\n
+        3. Verify that the captured audio is played.\n
+        4. Click on the close button.\n
+    </string>
+    <string name="provisioning_byod_dismiss_result_dialog">Close</string>
+    <string name="provisioning_byod_play">Play</string>
+    <string name="provisioning_byod_verify_image_title">Verify captured image</string>
+    <string name="provisioning_byod_verify_video_title">Verify captured video</string>
+    <string name="provisioning_byod_verify_audio_title">Verify captured audio</string>
+    <string name="provisioning_byod_no_image_capture_resolver">No image capture app present. Skip test.</string>
+    <string name="provisioning_byod_no_video_capture_resolver">No video capture app present. Skip test.</string>
+    <string name="provisioning_byod_no_audio_capture_resolver">No audio capture app present. Skip test.</string>
+    <string name="provisioning_byod_capture_media_error">Error while capturing media from managed profile.</string>
+
     <!-- Strings for DeskClock -->
     <string name="deskclock_tests">Alarms and Timers Tests</string>
     <string name="deskclock_tests_info">
@@ -1464,6 +1497,14 @@
     Overlay view must be shown. Verify that there is a text view displaying \"Overlay View Dummy Text\"
     when you tune to the \"Dummy\" channel.
     </string>
+    <string name="tv_input_discover_test_go_to_epg">
+    Press the \"Launch EPG\" button, and locate the channel named \"Dummy\".
+    </string>
+    <string name="tv_input_discover_test_verify_epg">
+    Do you see the programs named \"Dummy Program\" and its description
+    "Dummy Program Description" in the EPG?
+    </string>
+    <string name="tv_input_discover_test_yes">Yes</string>
 
     <string name="tv_parental_control_test">Live Channels app parental control test</string>
     <string name="tv_parental_control_test_info">
@@ -1491,14 +1532,15 @@
     </string>
 
     <string name="tv_launch_tv_app">Launch Live Channels</string>
+    <string name="tv_launch_epg">Launch EPG</string>
     <string name="tv_channel_not_found">
     CtsVerifier channel is not set up. Please set up before proceeding.
     </string>
 
-    <string name="tv_multiple_tracks_test">Live Channels app multiple tracks / subtitle test</string>
+    <string name="tv_multiple_tracks_test">Live Channels app closed captions and multi-audio test</string>
     <string name="tv_multiple_tracks_test_info">
-    This test verifies that the default Live Channels app invokes proper mulitple tracks / subtitle
-    APIs in the framework.
+    This test verifies that the default Live Channels app invokes proper mulitple tracks APIs in the
+    framework.
     </string>
     <string name="tv_multiple_tracks_test_select_subtitle">
     Press the \"Launch Live Channels\" button. Verify that the closed caption is off by default.
diff --git a/apps/CtsVerifier/res/xml/filepaths.xml b/apps/CtsVerifier/res/xml/filepaths.xml
new file mode 100644
index 0000000..2d555a2
--- /dev/null
+++ b/apps/CtsVerifier/res/xml/filepaths.xml
@@ -0,0 +1,3 @@
+<paths xmlns:android="http://schemas.android.com/apk/res/android">
+    <files-path path="images/" name="images" />
+</paths>
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 628ff3e..e41c6d0 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
@@ -82,6 +82,9 @@
     private TestItem mCredSettingsVisibleTest;
     private TestItem mPrintSettingsVisibleTest;
     private TestItem mIntentFiltersTest;
+    private TestItem mCrossProfileImageCaptureSupportTest;
+    private TestItem mCrossProfileVideoCaptureSupportTest;
+    private TestItem mCrossProfileAudioCaptureSupportTest;
 
     private int mCurrentTestPosition;
 
@@ -256,6 +259,50 @@
         mTests.add(mDisableNonMarketTest);
         mTests.add(mEnableNonMarketTest);
         mTests.add(mIntentFiltersTest);
+
+        if (canResolveIntent(ByodHelperActivity.getCaptureImageIntent())) {
+            // Capture image intent can be resolved in primary profile, so test.
+            mCrossProfileImageCaptureSupportTest = new TestItem(this,
+                    R.string.provisioning_byod_capture_image_support,
+                    R.string.provisioning_byod_capture_image_support_info,
+                    new Intent(ByodHelperActivity.ACTION_CAPTURE_AND_CHECK_IMAGE));
+            mTests.add(mCrossProfileImageCaptureSupportTest);
+        } else {
+            // Capture image intent cannot be resolved in primary profile, so skip test.
+            Toast.makeText(ByodFlowTestActivity.this,
+                    R.string.provisioning_byod_no_image_capture_resolver, Toast.LENGTH_SHORT)
+                    .show();
+        }
+
+        if (canResolveIntent(ByodHelperActivity.getCaptureVideoIntent())) {
+            // Capture video intent can be resolved in primary profile, so test.
+            mCrossProfileVideoCaptureSupportTest = new TestItem(this,
+                    R.string.provisioning_byod_capture_video_support,
+                    R.string.provisioning_byod_capture_video_support_info,
+                    new Intent(ByodHelperActivity.ACTION_CAPTURE_AND_CHECK_VIDEO));
+            mTests.add(mCrossProfileVideoCaptureSupportTest);
+        } else {
+            // Capture video intent cannot be resolved in primary profile, so skip test.
+            Toast.makeText(ByodFlowTestActivity.this,
+                    R.string.provisioning_byod_no_video_capture_resolver, Toast.LENGTH_SHORT)
+                    .show();
+        }
+
+        /* TODO: reinstate when bug b/20131958 is fixed
+        if (canResolveIntent(ByodHelperActivity.getCaptureAudioIntent())) {
+            // Capture audio intent can be resolved in primary profile, so test.
+            mCrossProfileAudioCaptureSupportTest = new TestItem(this,
+                    R.string.provisioning_byod_capture_audio_support,
+                    R.string.provisioning_byod_capture_audio_support_info,
+                    new Intent(ByodHelperActivity.ACTION_CAPTURE_AND_CHECK_AUDIO));
+            mTests.add(mCrossProfileAudioCaptureSupportTest);
+        } else {
+            // Capture audio intent cannot be resolved in primary profile, so skip test.
+            Toast.makeText(ByodFlowTestActivity.this,
+                    R.string.provisioning_byod_no_audio_capture_resolver, Toast.LENGTH_SHORT)
+                    .show();
+        }
+        */
     }
 
     @Override
@@ -266,6 +313,11 @@
         test.performTest(this);
     }
 
+    // Return whether the intent can be resolved in the current profile
+    private boolean canResolveIntent(Intent intent) {
+        return intent.resolveActivity(getPackageManager()) != null;
+    }
+
     private void showManualTestDialog(final TestItem test) {
         AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this)
                 .setIcon(android.R.drawable.ic_dialog_info)
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
index 13af890..d8a3387 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
@@ -18,6 +18,7 @@
 
 import android.app.Activity;
 import android.app.admin.DevicePolicyManager;
+import android.app.Dialog;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -26,24 +27,31 @@
 import android.content.pm.PackageManager;
 import android.net.Uri;
 import android.os.Bundle;
+import android.provider.MediaStore;
 import android.provider.Settings;
+import android.support.v4.content.FileProvider;
 import android.util.Log;
 import android.widget.Toast;
 
 import static android.provider.Settings.Secure.INSTALL_NON_MARKET_APPS;
 
+import java.io.File;
+import java.util.ArrayList;
+
 import com.android.cts.verifier.R;
 import com.android.cts.verifier.managedprovisioning.ByodFlowTestActivity.TestResult;
+import com.android.cts.verifier.managedprovisioning.ByodPresentMediaDialog.DialogCallback;
 
 /**
  * A helper activity from the managed profile side that responds to requests from CTS verifier in
  * primary user. Profile owner APIs are accessible inside this activity (given this activity is
  * started within the work profile). Its current functionalities include making sure the profile
- * owner is setup correctly, and removing the work profile upon request.
+ * owner is setup correctly, removing the work profile upon request, and verifying the image and
+ * video capture functionality.
  *
  * Note: We have to use a dummy activity because cross-profile intents only work for activities.
  */
-public class ByodHelperActivity extends Activity {
+public class ByodHelperActivity extends Activity implements DialogCallback {
     static final String TAG = "ByodHelperActivity";
 
     // Primary -> managed intent: query if the profile owner has been set up.
@@ -54,6 +62,12 @@
     public static final String ACTION_REMOVE_PROFILE_OWNER = "com.android.cts.verifier.managedprovisioning.BYOD_REMOVE";
     // Managed -> managed intent: provisioning completed successfully
     public static final String ACTION_PROFILE_PROVISIONED = "com.android.cts.verifier.managedprovisioning.BYOD_PROVISIONED";
+    // Primage -> managed intent: request to capture and check an image
+    public static final String ACTION_CAPTURE_AND_CHECK_IMAGE = "com.android.cts.verifier.managedprovisioning.BYOD_CAPTURE_AND_CHECK_IMAGE";
+    // Primage -> managed intent: request to capture and check a video
+    public static final String ACTION_CAPTURE_AND_CHECK_VIDEO = "com.android.cts.verifier.managedprovisioning.BYOD_CAPTURE_AND_CHECK_VIDEO";
+    // Primage -> managed intent: request to capture and check an audio recording
+    public static final String ACTION_CAPTURE_AND_CHECK_AUDIO = "com.android.cts.verifier.managedprovisioning.BYOD_CAPTURE_AND_CHECK_AUDIO";
 
     public static final String EXTRA_PROVISIONED = "extra_provisioned";
 
@@ -68,6 +82,9 @@
     public static final int RESULT_FAILED = RESULT_FIRST_USER;
 
     private static final int REQUEST_INSTALL_PACKAGE = 1;
+    private static final int REQUEST_IMAGE_CAPTURE = 2;
+    private static final int REQUEST_VIDEO_CAPTURE = 3;
+    private static final int REQUEST_AUDIO_CAPTURE = 4;
 
     private static final String ORIGINAL_SETTINGS_NAME = "original settings";
     private Bundle mOriginalSettings;
@@ -75,6 +92,11 @@
     private ComponentName mAdminReceiverComponent;
     private DevicePolicyManager mDevicePolicyManager;
 
+    private Uri mImageUri;
+    private Uri mVideoUri;
+
+    private ArrayList<File> mTempFiles = new ArrayList<File>();
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -132,6 +154,40 @@
                     new IntentFiltersTestHelper(this).checkCrossProfileIntentFilters(
                             IntentFiltersTestHelper.FLAG_INTENTS_FROM_MANAGED);
             setResult(intentFiltersSetForManagedIntents? RESULT_OK : RESULT_FAILED, null);
+        } else if (action.equals(ACTION_CAPTURE_AND_CHECK_IMAGE)) {
+            Intent captureImageIntent = getCaptureImageIntent();
+            mImageUri = getTempUri("image.jpg");
+            captureImageIntent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
+            if (captureImageIntent.resolveActivity(getPackageManager()) != null) {
+                startActivityForResult(captureImageIntent, REQUEST_IMAGE_CAPTURE);
+            } else {
+                Log.e(TAG, "Capture image intent could not be resolved in managed profile.");
+                showToast(R.string.provisioning_byod_capture_media_error);
+                finish();
+            }
+            return;
+        } else if (action.equals(ACTION_CAPTURE_AND_CHECK_VIDEO)) {
+            Intent captureVideoIntent = getCaptureVideoIntent();
+            mVideoUri = getTempUri("video.mp4");
+            captureVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT, mVideoUri);
+            if (captureVideoIntent.resolveActivity(getPackageManager()) != null) {
+                startActivityForResult(captureVideoIntent, REQUEST_VIDEO_CAPTURE);
+            } else {
+                Log.e(TAG, "Capture video intent could not be resolved in managed profile.");
+                showToast(R.string.provisioning_byod_capture_media_error);
+                finish();
+            }
+            return;
+        } else if (action.equals(ACTION_CAPTURE_AND_CHECK_AUDIO)) {
+            Intent captureAudioIntent = getCaptureAudioIntent();
+            if (captureAudioIntent.resolveActivity(getPackageManager()) != null) {
+                startActivityForResult(captureAudioIntent, REQUEST_AUDIO_CAPTURE);
+            } else {
+                Log.e(TAG, "Capture audio intent could not be resolved in managed profile.");
+                showToast(R.string.provisioning_byod_capture_media_error);
+                finish();
+            }
+            return;
         }
         // This activity has no UI and is only used to respond to CtsVerifier in the primary side.
         finish();
@@ -157,6 +213,36 @@
                 finish();
                 break;
             }
+            case REQUEST_IMAGE_CAPTURE: {
+                if (resultCode == RESULT_OK) {
+                    ByodPresentMediaDialog.newImageInstance(mImageUri)
+                            .show(getFragmentManager(), "ViewImageDialogFragment");
+                } else {
+                    // Failed capturing image.
+                    finish();
+                }
+                break;
+            }
+            case REQUEST_VIDEO_CAPTURE: {
+                if (resultCode == RESULT_OK) {
+                    ByodPresentMediaDialog.newVideoInstance(mVideoUri)
+                            .show(getFragmentManager(), "PlayVideoDialogFragment");
+                } else {
+                    // Failed capturing video.
+                    finish();
+                }
+                break;
+            }
+            case REQUEST_AUDIO_CAPTURE: {
+                if (resultCode == RESULT_OK) {
+                    ByodPresentMediaDialog.newAudioInstance(data.getData())
+                            .show(getFragmentManager(), "PlayAudioDialogFragment");
+                } else {
+                    // Failed capturing audio.
+                    finish();
+                }
+                break;
+            }
             default: {
                 Log.wtf(TAG, "Unknown requestCode " + requestCode + "; data = " + data);
                 break;
@@ -164,6 +250,39 @@
         }
     }
 
+    @Override
+    protected void onDestroy() {
+        cleanUpTempUris();
+        super.onDestroy();
+    }
+
+    public static Intent getCaptureImageIntent() {
+        return new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
+    }
+
+    public static Intent getCaptureVideoIntent() {
+        return new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
+    }
+
+    public static Intent getCaptureAudioIntent() {
+        return new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
+    }
+
+    private Uri getTempUri(String fileName) {
+        final File file = new File(getFilesDir() + File.separator + "images"
+                + File.separator + fileName);
+        file.getParentFile().mkdirs(); //if the folder doesn't exists it is created
+        mTempFiles.add(file);
+        return FileProvider.getUriForFile(this,
+                    "com.android.cts.verifier.managedprovisioning.fileprovider", file);
+    }
+
+    private void cleanUpTempUris() {
+        for (File file : mTempFiles) {
+            file.delete();
+        }
+    }
+
     private boolean isProfileOwner() {
         return mDevicePolicyManager.isAdminActive(mAdminReceiverComponent) &&
                 mDevicePolicyManager.isProfileOwnerApp(mAdminReceiverComponent.getPackageName());
@@ -193,4 +312,9 @@
         String message = getString(messageId);
         Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
     }
+
+    @Override
+    public void onDialogClose() {
+        finish();
+    }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodPresentMediaDialog.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodPresentMediaDialog.java
new file mode 100644
index 0000000..b3f126b
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodPresentMediaDialog.java
@@ -0,0 +1,167 @@
+/*
+ * 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.
+ */
+
+package com.android.cts.verifier.managedprovisioning;
+
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.DialogInterface;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.media.MediaPlayer;
+import android.media.MediaPlayer.OnPreparedListener;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.Toast;
+import android.widget.VideoView;
+
+import com.android.cts.verifier.R;
+
+import java.io.IOException;
+
+/**
+ * This dialog shows/plays an image, video or audio uri.
+ */
+public class ByodPresentMediaDialog extends DialogFragment {
+    static final String TAG = "ByodPresentMediaDialog";
+
+    private static final String KEY_VIDEO_URI = "video";
+    private static final String KEY_IMAGE_URI = "image";
+    private static final String KEY_AUDIO_URI = "audio";
+
+    /**
+     * Get a dialogFragment showing an image.
+     */
+    public static ByodPresentMediaDialog newImageInstance(Uri uri) {
+        ByodPresentMediaDialog dialog = new ByodPresentMediaDialog();
+        Bundle args = new Bundle();
+        args.putParcelable(KEY_IMAGE_URI, uri);
+        dialog.setArguments(args);
+        return dialog;
+    }
+
+    /**
+     * Get a dialogFragment playing a video.
+     */
+    public static ByodPresentMediaDialog newVideoInstance(Uri uri) {
+        ByodPresentMediaDialog dialog = new ByodPresentMediaDialog();
+        Bundle args = new Bundle();
+        args.putParcelable(KEY_VIDEO_URI, uri);
+        dialog.setArguments(args);
+        return dialog;
+    }
+
+    /**
+     * Get a dialogFragment playing audio.
+     */
+    public static ByodPresentMediaDialog newAudioInstance(Uri uri) {
+        ByodPresentMediaDialog dialog = new ByodPresentMediaDialog();
+        Bundle args = new Bundle();
+        args.putParcelable(KEY_AUDIO_URI, uri);
+        dialog.setArguments(args);
+        return dialog;
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        final Dialog dialog = new Dialog(getActivity());
+        dialog.setContentView(R.layout.byod_present_media);
+
+        Button dismissButton = (Button) dialog.findViewById(R.id.dismissButton);
+        dismissButton.setOnClickListener(new View.OnClickListener() {
+            public void onClick(View v) {
+                dismiss();
+                ((DialogCallback) getActivity()).onDialogClose();
+            }
+        });
+
+        Bundle arguments = getArguments();
+
+        // Initially all video and image specific UI is invisible.
+        if (arguments.containsKey(KEY_VIDEO_URI)) {
+            // Show video UI.
+            dialog.setTitle(getString(R.string.provisioning_byod_verify_video_title));
+
+            Uri uri = (Uri) getArguments().getParcelable(KEY_VIDEO_URI);
+            final VideoView videoView = (VideoView) dialog.findViewById(R.id.videoView);
+            videoView.setVisibility(View.VISIBLE);
+            videoView.setVideoURI(uri);
+
+            Button playButton = (Button) dialog.findViewById(R.id.playButton);
+            playButton.setVisibility(View.VISIBLE);
+            playButton.setOnClickListener(new View.OnClickListener() {
+                public void onClick(View v) {
+                    videoView.start();
+                }
+            });
+        } else if (arguments.containsKey(KEY_IMAGE_URI)) {
+            // Show image UI.
+            dialog.setTitle(getString(R.string.provisioning_byod_verify_image_title));
+
+            Uri uri = (Uri) getArguments().getParcelable(KEY_IMAGE_URI);
+            ImageView imageView = (ImageView) dialog.findViewById(R.id.imageView);
+            imageView.setVisibility(View.VISIBLE);
+            imageView.setImageURI(uri);
+        } else if (arguments.containsKey(KEY_AUDIO_URI)) {
+            // Show audio playback UI.
+            dialog.setTitle(getString(R.string.provisioning_byod_verify_audio_title));
+
+            Uri uri = (Uri) getArguments().getParcelable(KEY_AUDIO_URI);
+            final MediaPlayer mediaPlayer = new MediaPlayer();
+            final Button playButton = (Button) dialog.findViewById(R.id.playButton);
+            playButton.setVisibility(View.VISIBLE);
+            playButton.setEnabled(false);
+
+            try {
+                mediaPlayer.setDataSource(getActivity(), uri);
+                mediaPlayer.prepare();
+            } catch (IllegalArgumentException|SecurityException|IllegalStateException
+                    |IOException e) {
+                Log.e(TAG, "Cannot play given audio with media player.", e);
+                Toast.makeText(getActivity(), R.string.provisioning_byod_capture_media_error,
+                        Toast.LENGTH_SHORT).show();
+                getActivity().finish();
+            }
+
+            mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
+                @Override
+                public void onPrepared(MediaPlayer mp) {
+                    playButton.setEnabled(true);
+                    playButton.setOnClickListener(new View.OnClickListener() {
+                        public void onClick(View v) {
+                            mediaPlayer.start();
+                        }
+                    });
+                }
+            });
+        }
+
+        return dialog;
+    }
+
+    @Override
+    public void onCancel(DialogInterface dialog) {
+        ((DialogCallback) getActivity()).onDialogClose();
+    }
+
+    public interface DialogCallback {
+        public abstract void onDialogClose();
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
index 58c068f..e95752e 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
@@ -50,6 +50,9 @@
             filter.addAction(ByodHelperActivity.ACTION_REMOVE_PROFILE_OWNER);
             filter.addAction(ByodHelperActivity.ACTION_INSTALL_APK);
             filter.addAction(ByodHelperActivity.ACTION_CHECK_INTENT_FILTERS);
+            filter.addAction(ByodHelperActivity.ACTION_CAPTURE_AND_CHECK_IMAGE);
+            filter.addAction(ByodHelperActivity.ACTION_CAPTURE_AND_CHECK_VIDEO);
+            filter.addAction(ByodHelperActivity.ACTION_CAPTURE_AND_CHECK_AUDIO);
             filter.addAction(CrossProfileTestActivity.ACTION_CROSS_PROFILE);
             filter.addAction(WorkNotificationTestActivity.ACTION_WORK_NOTIFICATION);
             filter.addAction(WorkNotificationTestActivity.ACTION_CLEAR_WORK_NOTIFICATION);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputService.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputService.java
index f4460de..e7d1d79 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputService.java
@@ -33,15 +33,11 @@
 import android.media.tv.TvTrackInfo;
 import android.net.Uri;
 import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
 import android.view.Surface;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.TextView;
 
-import com.android.cts.verifier.R;
-
 import java.util.ArrayList;
 import java.util.List;
 
@@ -78,9 +74,9 @@
             new TvTrackInfo.Builder(TvTrackInfo.TYPE_SUBTITLE, "subtitle_eng")
             .setLanguage("eng")
             .build();
-    static final TvTrackInfo sSpaSubtitleTrack =
-            new TvTrackInfo.Builder(TvTrackInfo.TYPE_SUBTITLE, "subtitle_spa")
-            .setLanguage("spa")
+    static final TvTrackInfo sKorSubtitleTrack =
+            new TvTrackInfo.Builder(TvTrackInfo.TYPE_SUBTITLE, "subtitle_kor")
+            .setLanguage("kor")
             .build();
 
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -179,7 +175,7 @@
             mTracks.add(sEngAudioTrack);
             mTracks.add(sSpaAudioTrack);
             mTracks.add(sEngSubtitleTrack);
-            mTracks.add(sSpaSubtitleTrack);
+            mTracks.add(sKorSubtitleTrack);
         }
 
         @Override
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputSetupActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputSetupActivity.java
index 81a8edc..1d3fd40 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputSetupActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputSetupActivity.java
@@ -21,18 +21,26 @@
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.media.tv.TvContract;
+import android.media.tv.TvContract.Programs;
 import android.media.tv.TvInputInfo;
 import android.net.Uri;
 import android.os.Bundle;
 import android.util.Pair;
 import android.view.View;
 
+import java.util.ArrayList;
+
 public class MockTvInputSetupActivity extends Activity {
     private static final String TAG = "MockTvInputSetupActivity";
 
     private static final String CHANNEL_NUMBER = "999-0";
     private static final String CHANNEL_NAME = "Dummy";
 
+    private static final String PROGRAM_TITLE = "Dummy Program";
+    private static final String PROGRAM_DESCRIPTION = "Dummy Program Description";
+    private static final long PROGRAM_LENGTH_MILLIS = 60 * 60 * 1000;
+    private static final int PROGRAM_COUNT = 24;
+
     private static Object sLock = new Object();
     private static Pair<View, Runnable> sLaunchCallback = null;
 
@@ -55,6 +63,8 @@
                     return;
                 }
             }
+
+            // Add a channel.
             ContentValues values = new ContentValues();
             values.put(TvContract.Channels.COLUMN_INPUT_ID, inputId);
             values.put(TvContract.Channels.COLUMN_DISPLAY_NUMBER, CHANNEL_NUMBER);
@@ -62,9 +72,27 @@
             Uri channelUri = getContentResolver().insert(uri, values);
             // If the channel's ID happens to be zero, we add another and delete the one.
             if (ContentUris.parseId(channelUri) == 0) {
-                getContentResolver().insert(uri, values);
                 getContentResolver().delete(channelUri, null, null);
+                channelUri = getContentResolver().insert(uri, values);
             }
+
+            // Add Programs.
+            values = new ContentValues();
+            values.put(Programs.COLUMN_CHANNEL_ID, ContentUris.parseId(channelUri));
+            values.put(Programs.COLUMN_TITLE, PROGRAM_TITLE);
+            values.put(Programs.COLUMN_SHORT_DESCRIPTION, PROGRAM_DESCRIPTION);
+            long nowMs = System.currentTimeMillis();
+            long startTimeMs = nowMs - nowMs % PROGRAM_LENGTH_MILLIS;
+            ArrayList<ContentValues> list = new ArrayList<>();
+            for (int i = 0; i < PROGRAM_COUNT; ++i) {
+                values.put(Programs.COLUMN_START_TIME_UTC_MILLIS, startTimeMs);
+                values.put(Programs.COLUMN_END_TIME_UTC_MILLIS,
+                        startTimeMs + PROGRAM_LENGTH_MILLIS);
+                startTimeMs += PROGRAM_LENGTH_MILLIS;
+                list.add(new ContentValues(values));
+            }
+            getContentResolver().bulkInsert(Programs.CONTENT_URI, list.toArray(
+                    new ContentValues[0]));
         } finally {
             Pair<View, Runnable> launchCallback = null;
             synchronized (sLock) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvInputDiscoveryTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvInputDiscoveryTestActivity.java
index 3d17a1a..4d12d52 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvInputDiscoveryTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvInputDiscoveryTestActivity.java
@@ -30,7 +30,9 @@
     private static final String TAG = "TvInputDiscoveryTestActivity";
 
     private static final Intent TV_APP_INTENT = new Intent(Intent.ACTION_VIEW,
-            TvContract.buildChannelUri(0));
+            TvContract.Channels.CONTENT_URI);
+    private static final Intent EPG_INTENT = new Intent(Intent.ACTION_VIEW,
+            TvContract.Programs.CONTENT_URI);
 
     private static final long TIMEOUT_MS = 5l * 60l * 1000l;  // 5 mins.
 
@@ -39,6 +41,8 @@
     private View mTuneToChannelItem;
     private View mVerifyTuneItem;
     private View mVerifyOverlayViewItem;
+    private View mGoToEpgItem;
+    private View mVerifyEpgItem;
     private boolean mTuneVerified;
     private boolean mOverlayViewVerified;
 
@@ -63,6 +67,7 @@
                     setButtonEnabled(mTuneToChannelItem, true);
                 }
             });
+            startActivity(TV_APP_INTENT);
         } else if (containsButton(mTuneToChannelItem, v)) {
             final Runnable failCallback = new Runnable() {
                 @Override
@@ -78,7 +83,7 @@
                     setPassState(mVerifyTuneItem, true);
 
                     mTuneVerified = true;
-                    updatePassState(postTarget, failCallback);
+                    goToNextState(postTarget, failCallback);
                 }
             });
             MockTvInputService.expectOverlayView(postTarget, new Runnable() {
@@ -88,11 +93,18 @@
                     setPassState(mVerifyOverlayViewItem, true);
 
                     mOverlayViewVerified = true;
-                    updatePassState(postTarget, failCallback);
+                    goToNextState(postTarget, failCallback);
                 }
             });
+            startActivity(TV_APP_INTENT);
+        } else if (containsButton(mGoToEpgItem, v)) {
+            startActivity(EPG_INTENT);
+            setPassState(mGoToEpgItem, true);
+            setButtonEnabled(mVerifyEpgItem, true);
+        } else if (containsButton(mVerifyEpgItem, v)) {
+            setPassState(mVerifyEpgItem, true);
+            getPassButton().setEnabled(true);
         }
-        startActivity(TV_APP_INTENT);
     }
 
     @Override
@@ -106,12 +118,16 @@
         mVerifyTuneItem = createAutoItem(R.string.tv_input_discover_test_verify_tune);
         mVerifyOverlayViewItem = createAutoItem(
                 R.string.tv_input_discover_test_verify_overlay_view);
+        mGoToEpgItem = createUserItem(R.string.tv_input_discover_test_go_to_epg,
+                R.string.tv_launch_epg, this);
+        mVerifyEpgItem = createUserItem(R.string.tv_input_discover_test_verify_epg,
+                R.string.tv_input_discover_test_yes, this);
     }
 
-    private void updatePassState(View postTarget, Runnable failCallback) {
+    private void goToNextState(View postTarget, Runnable failCallback) {
         if (mTuneVerified && mOverlayViewVerified) {
             postTarget.removeCallbacks(failCallback);
-            getPassButton().setEnabled(true);
+            setButtonEnabled(mGoToEpgItem, true);
         }
     }
 
diff --git a/build/test_executable.mk b/build/test_executable.mk
index 3a2cb8e..979f59e 100644
--- a/build/test_executable.mk
+++ b/build/test_executable.mk
@@ -25,6 +25,7 @@
 
 LOCAL_CXX_STL := libc++
 include $(BUILD_EXECUTABLE)
+include $(BUILD_CTS_MODULE_TEST_CONFIG)
 
 cts_executable_bin :=
 $(foreach fp, $(ALL_MODULES.$(LOCAL_MODULE).BUILT) $(ALL_MODULES.$(LOCAL_MODULE)$(TARGET_2ND_ARCH_MODULE_SUFFIX).BUILT),\
@@ -38,6 +39,7 @@
 $(cts_executable_xml): PRIVATE_LIST_EXECUTABLE := $(HOST_OUT_EXECUTABLES)/$(LOCAL_MODULE)_list
 $(cts_executable_xml): $(HOST_OUT_EXECUTABLES)/$(LOCAL_MODULE)_list
 $(cts_executable_xml): $(cts_executable_bin)
+$(cts_executable_xml): $(cts_module_test_config)
 $(cts_executable_xml): $(addprefix $(LOCAL_PATH)/,$(LOCAL_SRC_FILES)) $(CTS_EXPECTATIONS) $(CTS_UNSUPPORTED_ABIS) $(CTS_NATIVE_TEST_SCANNER) $(CTS_XML_GENERATOR)
 	$(hide) echo Generating test description for native package $(PRIVATE_TEST_PACKAGE)
 	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
@@ -52,4 +54,4 @@
 						-o $@
 
 # Have the module name depend on the cts files; so the cts files get generated when you run mm/mmm/mma/mmma.
-$(my_register_name) : $(cts_executable_bin) $(cts_executable_xml)
+$(my_register_name) : $(cts_executable_bin) $(cts_executable_xml) $(cts_module_test_config)
diff --git a/build/test_gtest_package.mk b/build/test_gtest_package.mk
index fc468d0..6f71830 100644
--- a/build/test_gtest_package.mk
+++ b/build/test_gtest_package.mk
@@ -24,6 +24,7 @@
 LOCAL_PROGUARD_ENABLED := disabled
 
 include $(BUILD_CTS_SUPPORT_PACKAGE)
+include $(BUILD_CTS_MODULE_TEST_CONFIG)
 
 cts_package_xml := $(CTS_TESTCASES_OUT)/$(LOCAL_PACKAGE_NAME).xml
 $(cts_package_xml): PRIVATE_PATH := $(LOCAL_PATH)
@@ -33,6 +34,7 @@
 $(cts_package_xml): PRIVATE_TEST_LIST := $(LOCAL_PATH)/$(LOCAL_MODULE)_list.txt
 $(cts_package_xml): $(LOCAL_PATH)/$(LOCAL_MODULE)_list.txt
 $(cts_package_xml): $(cts_support_apks)
+$(cts_package_xml): $(cts_module_test_config)
 $(cts_package_xml): $(addprefix $(LOCAL_PATH)/,$(LOCAL_SRC_FILES))  $(CTS_NATIVE_TEST_SCANNER) $(CTS_XML_GENERATOR)
 	$(hide) echo Generating test description for wrapped native package $(PRIVATE_EXECUTABLE)
 	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
@@ -48,4 +50,4 @@
 						-o $@
 
 # Have the module name depend on the cts files; so the cts files get generated when you run mm/mmm/mma/mmma.
-$(my_register_name) : $(cts_package_xml)
+$(my_register_name) : $(cts_package_xml) $(cts_module_test_config)
diff --git a/build/test_host_java_library.mk b/build/test_host_java_library.mk
index 7e86ac9..7fdefb5 100644
--- a/build/test_host_java_library.mk
+++ b/build/test_host_java_library.mk
@@ -18,6 +18,7 @@
 #
 
 include $(BUILD_HOST_JAVA_LIBRARY)
+include $(BUILD_CTS_MODULE_TEST_CONFIG)
 
 cts_library_jar := $(CTS_TESTCASES_OUT)/$(LOCAL_MODULE).jar
 $(cts_library_jar): $(LOCAL_BUILT_MODULE)
@@ -33,6 +34,7 @@
 $(cts_library_xml): PRIVATE_LIBRARY := $(LOCAL_MODULE)
 $(cts_library_xml): PRIVATE_JAR_PATH := $(LOCAL_MODULE).jar
 $(cts_library_xml): $(cts_library_jar)
+$(cts_library_xml): $(cts_module_test_config)
 $(cts_library_xml): $(CTS_EXPECTATIONS) $(CTS_UNSUPPORTED_ABIS) $(CTS_JAVA_TEST_SCANNER_DOCLET) $(CTS_JAVA_TEST_SCANNER) $(CTS_XML_GENERATOR)
 	$(hide) echo Generating test description for host library $(PRIVATE_LIBRARY)
 	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
@@ -48,4 +50,4 @@
 						-o $@
 
 # Have the module name depend on the cts files; so the cts files get generated when you run mm/mmm/mma/mmma.
-$(my_register_name) : $(cts_library_jar) $(cts_library_xml)
+$(my_register_name) : $(cts_library_jar) $(cts_library_xml) $(cts_module_test_config)
diff --git a/build/test_uiautomator.mk b/build/test_uiautomator.mk
index b573d25..a191d72 100644
--- a/build/test_uiautomator.mk
+++ b/build/test_uiautomator.mk
@@ -20,6 +20,7 @@
 LOCAL_DEX_PREOPT := false
 
 include $(BUILD_JAVA_LIBRARY)
+include $(BUILD_CTS_MODULE_TEST_CONFIG)
 
 cts_library_jar := $(CTS_TESTCASES_OUT)/$(LOCAL_MODULE).jar
 $(cts_library_jar): $(LOCAL_BUILT_MODULE)
@@ -37,6 +38,7 @@
 $(cts_library_xml): PRIVATE_LIBRARY := $(LOCAL_MODULE)
 $(cts_library_xml): PRIVATE_JAR_PATH := $(LOCAL_MODULE).jar
 $(cts_library_xml): $(cts_library_jar)
+$(cts_library_xml): $(cts_module_test_config)
 $(cts_library_xml): $(CTS_EXPECTATIONS) $(CTS_UNSUPPORTED_ABIS) $(CTS_JAVA_TEST_SCANNER_DOCLET) $(CTS_JAVA_TEST_SCANNER) $(CTS_XML_GENERATOR)
 	$(hide) echo Generating test description for uiautomator library $(PRIVATE_LIBRARY)
 	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
@@ -55,4 +57,4 @@
 						-o $@
 
 # Have the module name depend on the cts files; so the cts files get generated when you run mm/mmm/mma/mmma.
-$(my_register_name) : $(cts_library_jar) $(cts_library_xml)
+$(my_register_name) : $(cts_library_jar) $(cts_library_xml) $(cts_module_test_config)
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SilentPackageInstallerTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SilentPackageInstallerTest.java
new file mode 100644
index 0000000..8e63543
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SilentPackageInstallerTest.java
@@ -0,0 +1,160 @@
+/*
+ * 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.deviceowner;
+
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.IntentSender;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageInstaller;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * This class tests silent package install and uninstall by a device owner.
+ */
+public class SilentPackageInstallerTest extends BaseDeviceOwnerTest {
+    private static final String TEST_APP_LOCATION = "/data/local/tmp/CtsSimpleApp.apk";
+    private static final String TEST_APP_PKG = "com.android.cts.launcherapps.simpleapp";
+    private static final int PACKAGE_INSTALLER_TIMEOUT_MS = 60000; // 60 seconds
+    private static final String ACTION_INSTALL_COMMIT =
+            "com.android.cts.deviceowner.INTENT_PACKAGE_INSTALL_COMMIT";
+
+    private PackageManager mPackageManager;
+    private PackageInstaller mPackageInstaller;
+    private PackageInstaller.Session mSession;
+    private boolean mCallbackReceived;
+
+    private final Object mPackageInstallerTimeoutLock = new Object();
+
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            assertEquals(PackageInstaller.STATUS_SUCCESS, intent.getIntExtra(
+                    PackageInstaller.EXTRA_STATUS,
+                    PackageInstaller.STATUS_FAILURE));
+            assertEquals(TEST_APP_PKG, intent.getStringExtra(PackageInstaller.EXTRA_PACKAGE_NAME));
+            mContext.unregisterReceiver(this);
+            synchronized (mPackageInstallerTimeoutLock) {
+                mCallbackReceived = true;
+                mPackageInstallerTimeoutLock.notify();
+            }
+        }
+    };
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mPackageManager = mContext.getPackageManager();
+        mPackageInstaller = mPackageManager.getPackageInstaller();
+        assertNotNull(mPackageInstaller);
+        mCallbackReceived = false;
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        try {
+            mContext.unregisterReceiver(mBroadcastReceiver);
+        } catch (IllegalArgumentException e) {
+            // ignore
+        }
+        if (mSession != null) {
+            mSession.abandon();
+        }
+        super.tearDown();
+    }
+
+    public void testSilentInstallUninstall() throws Exception {
+        // check that app is not already installed
+        assertFalse(isPackageInstalled(TEST_APP_PKG));
+
+        // install the app
+        installPackage(TEST_APP_LOCATION);
+        synchronized (mPackageInstallerTimeoutLock) {
+            try {
+                mPackageInstallerTimeoutLock.wait(PACKAGE_INSTALLER_TIMEOUT_MS);
+            } catch (InterruptedException e) {
+            }
+            assertTrue(mCallbackReceived);
+        }
+        assertTrue(isPackageInstalled(TEST_APP_PKG));
+
+        // uninstall the app again
+        synchronized (mPackageInstallerTimeoutLock) {
+            mCallbackReceived = false;
+            mPackageInstaller.uninstall(TEST_APP_PKG, getCommitCallback(0));
+            try {
+                mPackageInstallerTimeoutLock.wait(PACKAGE_INSTALLER_TIMEOUT_MS);
+            } catch (InterruptedException e) {
+            }
+            assertTrue(mCallbackReceived);
+        }
+        assertFalse(isPackageInstalled(TEST_APP_PKG));
+    }
+
+    private void installPackage(String packageLocation) throws Exception {
+        PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
+                PackageInstaller.SessionParams.MODE_FULL_INSTALL);
+        int sessionId = mPackageInstaller.createSession(params);
+        mSession = mPackageInstaller.openSession(sessionId);
+
+        File file = new File(packageLocation);
+        InputStream in = new FileInputStream(file);
+        OutputStream out = mSession.openWrite("SilentPackageInstallerTest", 0, file.length());
+        byte[] buffer = new byte[65536];
+        int c;
+        while ((c = in.read(buffer)) != -1) {
+            out.write(buffer, 0, c);
+        }
+        mSession.fsync(out);
+        out.close();
+        mSession.commit(getCommitCallback(sessionId));
+        mSession.close();
+    }
+
+    private IntentSender getCommitCallback(int sessionId) {
+        // Create an intent-filter and register the receiver
+        String action = ACTION_INSTALL_COMMIT + "." + sessionId;
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(action);
+        mContext.registerReceiver(mBroadcastReceiver, intentFilter);
+
+        // Create a PendingIntent and use it to generate the IntentSender
+        Intent broadcastIntent = new Intent(action);
+        PendingIntent pendingIntent = PendingIntent.getBroadcast(
+                mContext,
+                sessionId,
+                broadcastIntent,
+                PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);
+        return pendingIntent.getIntentSender();
+    }
+
+    private boolean isPackageInstalled(String packageName) {
+        try {
+            PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0);
+            return pi != null;
+        } catch (PackageManager.NameNotFoundException e) {
+            return false;
+        }
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ContactsTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ContactsTest.java
index 093a402..b76d9e4 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ContactsTest.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ContactsTest.java
@@ -28,6 +28,7 @@
 import android.os.Build;
 import android.os.RemoteException;
 import android.provider.ContactsContract;
+import android.provider.ContactsContract.CommonDataKinds.Email;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.ContactsContract.CommonDataKinds.Photo;
 import android.provider.ContactsContract.PhoneLookup;
@@ -44,10 +45,19 @@
 
     private static final String TEST_ACCOUNT_NAME = "CTS";
     private static final String TEST_ACCOUNT_TYPE = "com.android.cts.test";
+    // details of a sample primary contact
     private static final String PRIMARY_CONTACT_DISPLAY_NAME = "Primary";
     private static final String PRIMARY_CONTACT_PHONE = "00000001";
+    private static final String PRIMARY_CONTACT_EMAIL = "one@primary.com";
+    // details of a sample managed contact
     private static final String MANAGED_CONTACT_DISPLAY_NAME = "Managed";
     private static final String MANAGED_CONTACT_PHONE = "6891999";
+    private static final String MANAGED_CONTACT_EMAIL = "one@managed.com";
+    // details of a sample primary and a sample managed contact, with the same phone & email
+    private static final String PRIMARY_CONTACT_DISPLAY_NAME_2 = "PrimaryShared";
+    private static final String MANAGED_CONTACT_DISPLAY_NAME_2 = "ManagedShared";
+    private static final String SHARED_CONTACT_PHONE = "00000002";
+    private static final String SHARED_CONTACT_EMAIL = "shared@shared.com";
 
     private DevicePolicyManager mDevicePolicyManager;
     private ContentResolver mResolver;
@@ -85,11 +95,12 @@
                 .getSystemService(Context.DEVICE_POLICY_SERVICE);
     }
 
-    public void testPrimaryProfilePhoneLookup_insertedAndfound() throws RemoteException,
+    public void testPrimaryProfilePhoneAndEmailLookup_insertedAndfound() throws RemoteException,
             OperationApplicationException, NotFoundException, IOException {
         assertFalse(isManagedProfile());
         // Do not insert to primary contact
-        insertContact(PRIMARY_CONTACT_DISPLAY_NAME, PRIMARY_CONTACT_PHONE, 0);
+        insertContact(PRIMARY_CONTACT_DISPLAY_NAME, PRIMARY_CONTACT_PHONE,
+                PRIMARY_CONTACT_EMAIL, 0);
 
         ContactInfo contactInfo = getContactInfo(PRIMARY_CONTACT_PHONE);
         assertNotNull(contactInfo);
@@ -97,13 +108,23 @@
         assertFalse(contactInfo.hasPhotoUri());
         assertFalse(contactInfo.hasPhotoId());
         assertFalse(isEnterpriseContactId(contactInfo.contactId));
+
+        contactInfo = getContactInfoFromEmail(PRIMARY_CONTACT_EMAIL);
+        assertNotNull(contactInfo);
+        assertEquals(PRIMARY_CONTACT_DISPLAY_NAME, contactInfo.displayName);
+        assertFalse(contactInfo.hasPhotoUri());
+        assertFalse(contactInfo.hasPhotoId());
+        assertFalse(isEnterpriseContactId(contactInfo.contactId));
+
     }
 
-    public void testManagedProfilePhoneLookup_insertedAndfound() throws RemoteException,
+    public void testManagedProfilePhoneAndEmailLookup_insertedAndfound() throws RemoteException,
             OperationApplicationException, NotFoundException, IOException {
         assertTrue(isManagedProfile());
         // Insert ic_contact_picture as photo in managed contact
-        insertContact(MANAGED_CONTACT_DISPLAY_NAME, MANAGED_CONTACT_PHONE,
+        insertContact(MANAGED_CONTACT_DISPLAY_NAME,
+                MANAGED_CONTACT_PHONE,
+                MANAGED_CONTACT_EMAIL,
                 com.android.cts.managedprofile.R.raw.ic_contact_picture);
 
         ContactInfo contactInfo = getContactInfo(MANAGED_CONTACT_PHONE);
@@ -112,6 +133,56 @@
         assertTrue(contactInfo.hasPhotoUri());
         assertTrue(contactInfo.hasPhotoId());
         assertFalse(isEnterpriseContactId(contactInfo.contactId));
+
+        contactInfo = getContactInfoFromEmail(MANAGED_CONTACT_EMAIL);
+        assertNotNull(contactInfo);
+        assertEquals(MANAGED_CONTACT_DISPLAY_NAME, contactInfo.displayName);
+        assertTrue(contactInfo.hasPhotoUri());
+        assertTrue(contactInfo.hasPhotoId());
+        assertFalse(isEnterpriseContactId(contactInfo.contactId));
+    }
+
+    public void testPrimaryProfileDuplicatedPhoneEmailContact_insertedAndfound() throws
+            RemoteException, OperationApplicationException, NotFoundException, IOException {
+        assertFalse(isManagedProfile());
+        insertContact(PRIMARY_CONTACT_DISPLAY_NAME_2, SHARED_CONTACT_PHONE,
+                SHARED_CONTACT_EMAIL,
+                com.android.cts.managedprofile.R.raw.ic_contact_picture);
+
+        ContactInfo contactInfo = getContactInfo(SHARED_CONTACT_PHONE);
+        assertNotNull(contactInfo);
+        assertEquals(PRIMARY_CONTACT_DISPLAY_NAME_2, contactInfo.displayName);
+        assertTrue(contactInfo.hasPhotoUri());
+        assertTrue(contactInfo.hasPhotoId());
+        assertFalse(isEnterpriseContactId(contactInfo.contactId));
+
+        contactInfo = getContactInfoFromEmail(SHARED_CONTACT_EMAIL);
+        assertNotNull(contactInfo);
+        assertEquals(PRIMARY_CONTACT_DISPLAY_NAME_2, contactInfo.displayName);
+        assertTrue(contactInfo.hasPhotoUri());
+        assertTrue(contactInfo.hasPhotoId());
+        assertFalse(isEnterpriseContactId(contactInfo.contactId));
+    }
+
+    public void testManagedProfileDuplicatedPhoneEmailContact_insertedAndfound() throws
+            RemoteException, OperationApplicationException, NotFoundException, IOException {
+        assertTrue(isManagedProfile());
+        insertContact(MANAGED_CONTACT_DISPLAY_NAME_2, SHARED_CONTACT_PHONE,
+                SHARED_CONTACT_EMAIL, 0);
+
+        ContactInfo contactInfo = getContactInfo(SHARED_CONTACT_PHONE);
+        assertNotNull(contactInfo);
+        assertEquals(MANAGED_CONTACT_DISPLAY_NAME_2, contactInfo.displayName);
+        assertFalse(contactInfo.hasPhotoUri());
+        assertFalse(contactInfo.hasPhotoId());
+        assertFalse(isEnterpriseContactId(contactInfo.contactId));
+
+        contactInfo = getContactInfoFromEmail(SHARED_CONTACT_EMAIL);
+        assertNotNull(contactInfo);
+        assertEquals(MANAGED_CONTACT_DISPLAY_NAME_2, contactInfo.displayName);
+        assertFalse(contactInfo.hasPhotoUri());
+        assertFalse(contactInfo.hasPhotoId());
+        assertFalse(isEnterpriseContactId(contactInfo.contactId));
     }
 
     public void testPrimaryProfileEnterprisePhoneLookup_canAccessEnterpriseContact() {
@@ -124,7 +195,66 @@
         assertTrue(isEnterpriseContactId(contactInfo.contactId));
     }
 
-    public void testPrimaryProfilePhoneLookup_canAccessPrimaryContact() {
+    public void testPrimaryProfileEnterpriseEmailLookup_canAccessEnterpriseContact() {
+        assertFalse(isManagedProfile());
+        ContactInfo contactInfo = getEnterpriseContactInfoFromEmail(MANAGED_CONTACT_EMAIL);
+        assertEquals(MANAGED_CONTACT_DISPLAY_NAME, contactInfo.displayName);
+        assertTrue(contactInfo.hasPhotoUri());
+        // Cannot get photo id in ENTERPRISE_CONTENT_FILTER_URI
+        assertFalse(contactInfo.hasPhotoId());
+        assertTrue(isEnterpriseContactId(contactInfo.contactId));
+    }
+
+    public void testPrimaryProfileEnterprisePhoneLookupDuplicated_canAccessPrimaryContact() {
+        assertFalse(isManagedProfile());
+        ContactInfo contactInfo = getEnterpriseContactInfo(SHARED_CONTACT_PHONE);
+        assertEquals(PRIMARY_CONTACT_DISPLAY_NAME_2, contactInfo.displayName);
+        assertTrue(contactInfo.hasPhotoUri());
+        assertTrue(contactInfo.hasPhotoId());
+        assertFalse(isEnterpriseContactId(contactInfo.contactId));
+    }
+
+    public void testPrimaryProfileEnterpriseEmailLookupDuplicated_canAccessPrimaryContact() {
+        assertFalse(isManagedProfile());
+        ContactInfo contactInfo = getEnterpriseContactInfoFromEmail(SHARED_CONTACT_EMAIL);
+        assertEquals(PRIMARY_CONTACT_DISPLAY_NAME_2, contactInfo.displayName);
+        assertTrue(contactInfo.hasPhotoUri());
+        assertTrue(contactInfo.hasPhotoId());
+        assertFalse(isEnterpriseContactId(contactInfo.contactId));
+    }
+
+    public void testManagedProfileEnterprisePhoneLookupDuplicated_canAccessEnterpriseContact() {
+        assertTrue(isManagedProfile());
+        ContactInfo contactInfo = getEnterpriseContactInfo(SHARED_CONTACT_PHONE);
+        assertEquals(MANAGED_CONTACT_DISPLAY_NAME_2, contactInfo.displayName);
+        assertFalse(contactInfo.hasPhotoUri());
+        assertFalse(contactInfo.hasPhotoId());
+        assertFalse(isEnterpriseContactId(contactInfo.contactId));
+    }
+
+    public void testManagedProfileEnterpriseEmailLookupDuplicated_canAccessEnterpriseContact() {
+        assertTrue(isManagedProfile());
+        ContactInfo contactInfo = getEnterpriseContactInfoFromEmail(SHARED_CONTACT_EMAIL);
+        assertEquals(MANAGED_CONTACT_DISPLAY_NAME_2, contactInfo.displayName);
+        assertFalse(contactInfo.hasPhotoUri());
+        assertFalse(contactInfo.hasPhotoId());
+        assertFalse(isEnterpriseContactId(contactInfo.contactId));
+    }
+
+
+    public void testPrimaryProfilePhoneLookup_canNotAccessEnterpriseContact() {
+        assertFalse(isManagedProfile());
+        ContactInfo contactInfo = getContactInfo(MANAGED_CONTACT_PHONE);
+        assertNull(contactInfo);
+    }
+
+    public void testPrimaryProfileEmailLookup_canNotAccessEnterpriseContact() {
+        assertFalse(isManagedProfile());
+        ContactInfo contactInfo = getContactInfoFromEmail(MANAGED_CONTACT_EMAIL);
+        assertNull(contactInfo);
+    }
+
+    public void testPrimaryProfileEnterprisePhoneLookup_canAccessPrimaryContact() {
         assertFalse(isManagedProfile());
         ContactInfo contactInfo = getEnterpriseContactInfo(PRIMARY_CONTACT_PHONE);
         assertEquals(PRIMARY_CONTACT_DISPLAY_NAME, contactInfo.displayName);
@@ -133,7 +263,16 @@
         assertFalse(isEnterpriseContactId(contactInfo.contactId));
     }
 
-    public void testManagedProfilePhoneLookup_canAccessEnterpriseContact() {
+    public void testPrimaryProfileEnterpriseEmailLookup_canAccessPrimaryContact() {
+        assertFalse(isManagedProfile());
+        ContactInfo contactInfo = getEnterpriseContactInfoFromEmail(PRIMARY_CONTACT_EMAIL);
+        assertEquals(PRIMARY_CONTACT_DISPLAY_NAME, contactInfo.displayName);
+        assertFalse(contactInfo.hasPhotoUri());
+        assertFalse(contactInfo.hasPhotoId());
+        assertFalse(isEnterpriseContactId(contactInfo.contactId));
+    }
+
+    public void testManagedProfileEnterprisePhoneLookup_canAccessEnterpriseContact() {
         assertTrue(isManagedProfile());
         ContactInfo contactInfo = getEnterpriseContactInfo(MANAGED_CONTACT_PHONE);
         assertEquals(MANAGED_CONTACT_DISPLAY_NAME, contactInfo.displayName);
@@ -142,15 +281,48 @@
         assertFalse(isEnterpriseContactId(contactInfo.contactId));
     }
 
-    public void testPrimaryProfilePhoneLookup_canNotAccessEnterpriseContact() {
-        assertFalse(isManagedProfile());
-        ContactInfo contactInfo = getEnterpriseContactInfo(MANAGED_CONTACT_PHONE);
+    public void testManagedProfileEnterpriseEmailLookup_canAccessEnterpriseContact() {
+        assertTrue(isManagedProfile());
+        ContactInfo contactInfo = getEnterpriseContactInfoFromEmail(MANAGED_CONTACT_EMAIL);
+        assertEquals(MANAGED_CONTACT_DISPLAY_NAME, contactInfo.displayName);
+        assertTrue(contactInfo.hasPhotoUri());
+        assertTrue(contactInfo.hasPhotoId());
+        assertFalse(isEnterpriseContactId(contactInfo.contactId));
+    }
+
+    public void testManagedProfileEnterprisePhoneLookup_canNotAccessPrimaryContact() {
+        assertTrue(isManagedProfile());
+        ContactInfo contactInfo = getEnterpriseContactInfo(PRIMARY_CONTACT_PHONE);
+        assertNull(contactInfo);
+    }
+
+    public void testManagedProfileEnterpriseEmailLookup_canNotAccessPrimaryContact() {
+        assertTrue(isManagedProfile());
+        ContactInfo contactInfo = getEnterpriseContactInfoFromEmail(PRIMARY_CONTACT_EMAIL);
         assertNull(contactInfo);
     }
 
     public void testManagedProfilePhoneLookup_canNotAccessPrimaryContact() {
         assertTrue(isManagedProfile());
-        ContactInfo contactInfo = getEnterpriseContactInfo(PRIMARY_CONTACT_PHONE);
+        ContactInfo contactInfo = getContactInfo(PRIMARY_CONTACT_PHONE);
+        assertNull(contactInfo);
+    }
+
+    public void testManagedProfileEmailLookup_canNotAccessPrimaryContact() {
+        assertTrue(isManagedProfile());
+        ContactInfo contactInfo = getContactInfoFromEmail(PRIMARY_CONTACT_EMAIL);
+        assertNull(contactInfo);
+    }
+
+    public void testPrimaryProfileEnterpriseEmailLookup_canNotAccessEnterpriseContact() {
+        assertFalse(isManagedProfile());
+        ContactInfo contactInfo = getEnterpriseContactInfoFromEmail(MANAGED_CONTACT_EMAIL);
+        assertNull(contactInfo);
+    }
+
+    public void testPrimaryProfileEnterprisePhoneLookup_canNotAccessEnterpriseContact() {
+        assertFalse(isManagedProfile());
+        ContactInfo contactInfo = getEnterpriseContactInfo(MANAGED_CONTACT_PHONE);
         assertNull(contactInfo);
     }
 
@@ -186,9 +358,13 @@
         return mDevicePolicyManager.isProfileOwnerApp(adminPackage);
     }
 
-    private void insertContact(String displayName, String phoneNumber, int photoResId)
-            throws RemoteException,
-            OperationApplicationException, NotFoundException, IOException {
+    private void insertContact(String displayName, String phoneNumber, int photoResId) throws
+            RemoteException, OperationApplicationException, NotFoundException, IOException {
+        insertContact(displayName, phoneNumber, null, photoResId);
+    }
+
+    private void insertContact(String displayName, String phoneNumber, String email, int photoResId)
+            throws RemoteException, OperationApplicationException, NotFoundException, IOException {
         ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
         ops.add(ContentProviderOperation
                 .newInsert(ContactsContract.RawContacts.CONTENT_URI)
@@ -216,6 +392,18 @@
                 .withValue(ContactsContract.CommonDataKinds.Phone.TYPE,
                         Phone.TYPE_MOBILE)
                 .build());
+        ops.add(ContentProviderOperation
+                .newInsert(ContactsContract.Data.CONTENT_URI)
+                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
+                .withValue(
+                        ContactsContract.Data.MIMETYPE,
+                        ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
+                .withValue(ContactsContract.CommonDataKinds.Email.ADDRESS,
+                        email)
+                .withValue(ContactsContract.CommonDataKinds.Email.TYPE,
+                        Email.TYPE_WORK)
+                .build());
+
         if (photoResId != 0) {
             InputStream phoneInputStream = mContext.getResources().openRawResource(photoResId);
             byte[] rawPhoto = getByteFromStream(phoneInputStream);
@@ -256,17 +444,56 @@
         return result;
     }
 
+    private ContactInfo getContactInfoFromEmailUri(Uri emailLookupUri, String email) {
+        Uri uri = Uri.withAppendedPath(emailLookupUri, Uri.encode(email));
+        Cursor cursor = mResolver.query(uri,
+                new String[] {
+                        Email.CONTACT_ID,
+                        Email.DISPLAY_NAME_PRIMARY,
+                        Email.PHOTO_URI,
+                        Email.PHOTO_ID,
+                        Email.PHOTO_THUMBNAIL_URI,
+                }, null, null, null);
+        if (cursor == null) {
+            return null;
+        }
+        ContactInfo result = null;
+        if (cursor.moveToFirst()) {
+            result = new ContactInfo(
+                    cursor.getString(cursor.getColumnIndexOrThrow(
+                        Email.CONTACT_ID)),
+                    cursor.getString(cursor.getColumnIndexOrThrow(
+                        Email.DISPLAY_NAME_PRIMARY)),
+                    cursor.getString(cursor.getColumnIndexOrThrow(
+                        Email.PHOTO_URI)),
+                    cursor.getString(cursor.getColumnIndexOrThrow(
+                        Email.PHOTO_THUMBNAIL_URI)),
+                    cursor.getString(cursor.getColumnIndexOrThrow(
+                        Email.PHOTO_ID)));
+        }
+        cursor.close();
+        return result;
+    }
+
     private ContactInfo getContactInfo(String phoneNumber) {
         return getContactInfoFromUri(PhoneLookup.CONTENT_FILTER_URI,
                 phoneNumber);
     }
 
+    private ContactInfo getContactInfoFromEmail(String email) {
+        return getContactInfoFromEmailUri(Email.CONTENT_LOOKUP_URI, email);
+    }
+
     private ContactInfo getEnterpriseContactInfo(String phoneNumber) {
         return getContactInfoFromUri(
                 PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI,
                 phoneNumber);
     }
 
+    private ContactInfo getEnterpriseContactInfoFromEmail(String email) {
+        return getContactInfoFromEmailUri(Email.ENTERPRISE_CONTENT_LOOKUP_URI, email);
+    }
+
     private void removeAllTestContactsInProfile() {
         ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
         ops.add(ContentProviderOperation.newDelete(RawContacts.CONTENT_URI)
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index c0e6479..7e0d9595 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -54,7 +54,7 @@
     protected static final String ADMIN_RECEIVER_TEST_CLASS =
             MANAGED_PROFILE_PKG + ".BaseManagedProfileTest$BasicAdminReceiver";
 
-    private CtsBuildHelper mCtsBuild;
+    protected CtsBuildHelper mCtsBuild;
 
     private HashSet<String> mAvailableFeatures;
     protected boolean mHasFeature;
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index b84e9fe..65bb877 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -20,6 +20,8 @@
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.log.LogUtil.CLog;
 
+import java.io.File;
+
 /**
  * Set of tests for Device Owner use cases.
  */
@@ -28,6 +30,10 @@
     private static final String DEVICE_OWNER_PKG = "com.android.cts.deviceowner";
     private static final String DEVICE_OWNER_APK = "CtsDeviceOwnerApp.apk";
 
+    private static final String TEST_APP_APK = "CtsSimpleApp.apk";
+    private static final String TEST_APP_PKG = "com.android.cts.launcherapps.simpleapp";
+    private static final String TEST_APP_LOCATION = "/data/local/tmp/";
+
     private static final String ADMIN_RECEIVER_TEST_CLASS =
             DEVICE_OWNER_PKG + ".BaseDeviceOwnerTest$BasicAdminReceiver";
     private static final String CLEAR_DEVICE_OWNER_TEST_CLASS =
@@ -81,6 +87,19 @@
         executeDeviceOwnerTest("ScreenCaptureDisabledTest");
     }
 
+    public void testSilentPackageInstaller() throws Exception {
+        final File apk = mCtsBuild.getTestApp(TEST_APP_APK);
+        try {
+            getDevice().uninstallPackage(TEST_APP_PKG);
+            assertTrue(getDevice().pushFile(apk, TEST_APP_LOCATION + apk.getName()));
+            executeDeviceOwnerTest("SilentPackageInstallerTest");
+        } finally {
+            String command = "rm " + TEST_APP_LOCATION + apk.getName();
+            String commandOutput = getDevice().executeShellCommand(command);
+            getDevice().uninstallPackage(TEST_APP_PKG);
+        }
+    }
+
     private void executeDeviceOwnerTest(String testClassName) throws Exception {
         if (!mHasFeature) {
             return;
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/LauncherAppsProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/LauncherAppsProfileTest.java
index f8c2e7d..43f1f5a 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/LauncherAppsProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/LauncherAppsProfileTest.java
@@ -32,10 +32,7 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-
-        // We need multi user to be supported in order to create a profile of the user owner.
-        mHasFeature = mHasFeature && (getMaxNumberOfUsersSupported() > 1);
-
+        mHasFeature = mHasFeature && hasDeviceFeature("android.software.managed_users");
         if (mHasFeature) {
             removeTestUsers();
             installTestApps();
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
index 5c0126d..bb8cd3f 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
@@ -20,6 +20,8 @@
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.log.LogUtil.CLog;
 
+import junit.framework.AssertionFailedError;
+
 /**
  * Set of tests for Managed Profile use cases.
  */
@@ -45,7 +47,7 @@
         super.setUp();
 
         // We need multi user to be supported in order to create a profile of the user owner.
-        mHasFeature = mHasFeature && (getMaxNumberOfUsersSupported() > 1) && hasDeviceFeature(
+        mHasFeature = mHasFeature && hasDeviceFeature(
                 "android.software.managed_users");
 
         if (mHasFeature) {
@@ -91,11 +93,16 @@
         assertFalse(listUsers().contains(mUserId));
     }
 
-    public void testMaxUsersStrictlyMoreThanOne() throws Exception {
-        if (hasDeviceFeature("android.software.managed_users")) {
-            assertTrue("Device must support more than 1 user "
-                    + "if android.software.managed_users feature is available",
-            getMaxNumberOfUsersSupported() > 1);
+    public void testMaxOneManagedProfile() throws Exception {
+        int newUserId = -1;
+        try {
+            newUserId = createManagedProfile();
+        } catch (AssertionFailedError expected) {
+        }
+        if (newUserId > 0) {
+            removeUser(newUserId);
+            fail(mHasFeature ? "Device must allow creating only one managed profile"
+                    : "Device must not allow creating a managed profile");
         }
     }
 
@@ -247,39 +254,111 @@
         try {
             // Insert Primary profile Contacts
             assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
-                    "testPrimaryProfilePhoneLookup_insertedAndfound", 0));
+                    "testPrimaryProfilePhoneAndEmailLookup_insertedAndfound", 0));
             // Insert Managed profile Contacts
             assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
-                    "testManagedProfilePhoneLookup_insertedAndfound", mUserId));
+                    "testManagedProfilePhoneAndEmailLookup_insertedAndfound", mUserId));
+            // Insert a primary contact with same phone & email as other enterprise contacts
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+                    "testPrimaryProfileDuplicatedPhoneEmailContact_insertedAndfound", 0));
+            // Insert a enterprise contact with same phone & email as other primary contacts
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+                    "testManagedProfileDuplicatedPhoneEmailContact_insertedAndfound", mUserId));
+
 
             // Set cross profile caller id to enabled
             assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
                     "testSetCrossProfileCallerIdDisabled_false", mUserId));
 
-            // Managed user can use ENTERPRISE_CONTENT_FILTER_URI
-            // To access managed contacts but not primary contacts
+            // Primary user cannot use ordinary phone/email lookup api to access managed contacts
             assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
-                    "testManagedProfilePhoneLookup_canAccessEnterpriseContact", mUserId));
+                    "testPrimaryProfilePhoneLookup_canNotAccessEnterpriseContact", 0));
             assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
-                    "testManagedProfilePhoneLookup_canNotAccessPrimaryContact", mUserId));
-
-            // Primary user can use ENTERPRISE_CONTENT_FILTER_URI
-            // To access both primary and managed contacts
+                    "testPrimaryProfileEmailLookup_canNotAccessEnterpriseContact", 0));
+            // Primary user can use ENTERPRISE_CONTENT_FILTER_URI to access primary contacts
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+                    "testPrimaryProfileEnterprisePhoneLookup_canAccessPrimaryContact", 0));
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+                    "testPrimaryProfileEnterpriseEmailLookup_canAccessPrimaryContact", 0));
+            // Primary user can use ENTERPRISE_CONTENT_FILTER_URI to access managed profile contacts
             assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
                     "testPrimaryProfileEnterprisePhoneLookup_canAccessEnterpriseContact", 0));
             assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
-                    "testPrimaryProfilePhoneLookup_canAccessPrimaryContact", 0));
+                    "testPrimaryProfileEnterpriseEmailLookup_canAccessEnterpriseContact", 0));
+            // When there exist contacts with the same phone/email in primary & enterprise,
+            // primary user can use ENTERPRISE_CONTENT_FILTER_URI to access the primary contact.
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+                    "testPrimaryProfileEnterpriseEmailLookupDuplicated_canAccessPrimaryContact",
+                    0));
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+                    "testPrimaryProfileEnterprisePhoneLookupDuplicated_canAccessPrimaryContact",
+                    0));
+
+            // Managed user cannot use ordinary phone/email lookup api to access primary contacts
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+                    "testManagedProfilePhoneLookup_canNotAccessPrimaryContact", mUserId));
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+                    "testManagedProfileEmailLookup_canNotAccessPrimaryContact", mUserId));
+            // Managed user can use ENTERPRISE_CONTENT_FILTER_URI to access enterprise contacts
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+                    "testManagedProfileEnterprisePhoneLookup_canAccessEnterpriseContact", mUserId));
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+                    "testManagedProfileEnterpriseEmailLookup_canAccessEnterpriseContact", mUserId));
+            // Managed user cannot use ENTERPRISE_CONTENT_FILTER_URI to access primary contacts
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+                    "testManagedProfileEnterprisePhoneLookup_canNotAccessPrimaryContact", mUserId));
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+                    "testManagedProfileEnterpriseEmailLookup_canNotAccessPrimaryContact", mUserId));
+            // When there exist contacts with the same phone/email in primary & enterprise,
+            // managed user can use ENTERPRISE_CONTENT_FILTER_URI to access the enterprise contact.
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+                    "testManagedProfileEnterpriseEmailLookupDuplicated_canAccessEnterpriseContact",
+                    mUserId));
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+                    "testManagedProfileEnterprisePhoneLookupDuplicated_canAccessEnterpriseContact",
+                    mUserId));
 
             // Set cross profile caller id to disabled
             assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
                     "testSetCrossProfileCallerIdDisabled_true", mUserId));
 
-            // Primary user cannot use ENTERPRISE_CONTENT_FILTER_URI to access managed contacts
+            // Primary user cannot use ordinary phone/email lookup api to access managed contacts
             assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
                     "testPrimaryProfilePhoneLookup_canNotAccessEnterpriseContact", 0));
-            // Managed user cannot use ENTERPRISE_CONTENT_FILTER_URI to access primary contacts
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+                    "testPrimaryProfileEmailLookup_canNotAccessEnterpriseContact", 0));
+            // Primary user cannot use ENTERPRISE_CONTENT_FILTER_URI to access managed contacts
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+                    "testPrimaryProfileEnterprisePhoneLookup_canNotAccessEnterpriseContact", 0));
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+                    "testPrimaryProfileEnterpriseEmailLookup_canNotAccessEnterpriseContact", 0));
+            // When there exist contacts with the same phone/email in primary & enterprise,
+            // primary user can use ENTERPRISE_CONTENT_FILTER_URI to access primary contacts
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+                    "testPrimaryProfileEnterpriseEmailLookupDuplicated_canAccessPrimaryContact",
+                    0));
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+                    "testPrimaryProfileEnterprisePhoneLookupDuplicated_canAccessPrimaryContact",
+                    0));
+
+            // Managed user cannot use ordinary phone/email lookup api to access primary contacts
             assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
                     "testManagedProfilePhoneLookup_canNotAccessPrimaryContact", mUserId));
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+                    "testManagedProfileEmailLookup_canNotAccessPrimaryContact", mUserId));
+            // Managed user cannot use ENTERPRISE_CONTENT_FILTER_URI to access primary contacts
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+                    "testManagedProfileEnterprisePhoneLookup_canNotAccessPrimaryContact", mUserId));
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+                    "testManagedProfileEnterpriseEmailLookup_canNotAccessPrimaryContact", mUserId));
+            // When there exist contacts with the same phone/email in primary & enterprise,
+            // managed user can use ENTERPRISE_CONTENT_FILTER_URI to access enterprise contacts
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+                    "testManagedProfileEnterpriseEmailLookupDuplicated_canAccessEnterpriseContact",
+                    mUserId));
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+                    "testManagedProfileEnterprisePhoneLookupDuplicated_canAccessEnterpriseContact",
+                    mUserId));
         } finally {
             // Clean up in managed profile and primary profile
             runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
diff --git a/hostsidetests/security/src/android/cts/security/SELinuxHostTest.java b/hostsidetests/security/src/android/cts/security/SELinuxHostTest.java
index 6e2c90e..a0d3167 100644
--- a/hostsidetests/security/src/android/cts/security/SELinuxHostTest.java
+++ b/hostsidetests/security/src/android/cts/security/SELinuxHostTest.java
@@ -106,32 +106,27 @@
         /* obtain sepolicy file from running device */
         devicePolicyFile = File.createTempFile("sepolicy", ".tmp");
         devicePolicyFile.deleteOnExit();
-        mDevice.executeAdbCommand("pull", "/sys/fs/selinux/policy",
-                devicePolicyFile.getAbsolutePath());
+        mDevice.pullFile("/sys/fs/selinux/policy", devicePolicyFile);
 
         /* obtain seapp_contexts file from running device */
         deviceSeappFile = File.createTempFile("seapp_contexts", ".tmp");
         deviceSeappFile.deleteOnExit();
-        mDevice.executeAdbCommand("pull", "/seapp_contexts",
-                deviceSeappFile.getAbsolutePath());
+        mDevice.pullFile("/seapp_contexts", deviceSeappFile);
 
         /* obtain file_contexts file from running device */
         deviceFcFile = File.createTempFile("file_contexts", ".tmp");
         deviceFcFile.deleteOnExit();
-        mDevice.executeAdbCommand("pull", "/file_contexts",
-                deviceFcFile.getAbsolutePath());
+        mDevice.pullFile("/file_contexts", deviceFcFile);
 
         /* obtain property_contexts file from running device */
         devicePcFile = File.createTempFile("property_contexts", ".tmp");
         devicePcFile.deleteOnExit();
-        mDevice.executeAdbCommand("pull", "/property_contexts",
-                devicePcFile.getAbsolutePath());
+        mDevice.pullFile("/property_contexts", devicePcFile);
 
         /* obtain service_contexts file from running device */
         deviceSvcFile = File.createTempFile("service_contexts", ".tmp");
         deviceSvcFile.deleteOnExit();
-        mDevice.executeAdbCommand("pull", "/service_contexts",
-                deviceSvcFile.getAbsolutePath());
+        mDevice.pullFile("/service_contexts", deviceSvcFile);
 
         /* retrieve the AOSP *_contexts files from jar */
         aospSeappFile = copyResourceToTempFile("/general_seapp_contexts");
diff --git a/hostsidetests/theme/app/Android.mk b/hostsidetests/theme/app/Android.mk
index 1be2983..70623cb 100644
--- a/hostsidetests/theme/app/Android.mk
+++ b/hostsidetests/theme/app/Android.mk
@@ -26,8 +26,6 @@
 
 LOCAL_PROGUARD_ENABLED := disabled
 
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
-
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 #Flags to tell the Android Asset Packaging Tool not to strip for some densities
diff --git a/hostsidetests/theme/app/AndroidManifest.xml b/hostsidetests/theme/app/AndroidManifest.xml
index 2f8fb3b..81a4d9d 100755
--- a/hostsidetests/theme/app/AndroidManifest.xml
+++ b/hostsidetests/theme/app/AndroidManifest.xml
@@ -24,7 +24,7 @@
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <application>
         <uses-library android:name="android.test.runner" />
-        <activity android:name=".HoloDeviceActivity" >
+        <activity android:name=".HoloDeviceActivity">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
@@ -37,13 +37,6 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
-        <activity android:name=".CaptureActivity" />
     </application>
 
-    <!--  self-instrumenting test package. -->
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
-                     android:targetPackage="android.theme.app"
-                     android:label="Generates Theme reference images"/>
-
 </manifest>
-
diff --git a/hostsidetests/theme/app/res/layout/holo_test.xml b/hostsidetests/theme/app/res/layout/holo_test.xml
index 0aef953..3eed4ba 100644
--- a/hostsidetests/theme/app/res/layout/holo_test.xml
+++ b/hostsidetests/theme/app/res/layout/holo_test.xml
@@ -15,6 +15,8 @@
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:orientation="vertical"
+        android:focusable="true"
+        android:keepScreenOn="true"
         android:layout_width="match_parent"
         android:layout_height="match_parent">
     <android.theme.app.ReferenceViewGroup
diff --git a/hostsidetests/theme/app/src/android/theme/app/CaptureActivity.java b/hostsidetests/theme/app/src/android/theme/app/CaptureActivity.java
deleted file mode 100644
index d241ff6..0000000
--- a/hostsidetests/theme/app/src/android/theme/app/CaptureActivity.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.theme.app;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-
-import java.util.concurrent.CountDownLatch;
-
-/**
- * Iterates through all themes and all layouts, starting the Activity to capture the images.
- */
-public class CaptureActivity extends Activity {
-
-    private static final int REQUEST_CODE = 1;
-
-    private static final int NUM_THEMES = 24;
-
-    private static final int NUM_LAYOUTS = 47;
-
-    private final CountDownLatch mLatch = new CountDownLatch(1);
-
-    private int mCurrentTheme = 0;
-
-    private int mCurrentLayout = 0;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        generateNextImage();
-    }
-
-    /**
-     * Starts the activity to generate the next image.
-     */
-    private void generateNextImage() {
-        Intent intent = new Intent(this, HoloDeviceActivity.class);
-        intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
-        intent.putExtra(HoloDeviceActivity.EXTRA_THEME, mCurrentTheme);
-        intent.putExtra(HoloDeviceActivity.EXTRA_LAYOUT, mCurrentLayout);
-        startActivityForResult(intent, REQUEST_CODE);
-    }
-
-    @Override
-    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-        if (requestCode == REQUEST_CODE) {
-            if (resultCode == RESULT_OK) {
-                mCurrentLayout++;
-                if (mCurrentLayout >= NUM_LAYOUTS) {
-                    mCurrentLayout = 0;
-                    mCurrentTheme++;
-                }
-                if (mCurrentTheme < NUM_THEMES) {
-                    generateNextImage();
-                } else {
-                    finish();
-                }
-            } else {
-                finish();
-            }
-        }
-    }
-
-    public void finish() {
-        mLatch.countDown();
-        super.finish();
-    }
-
-    public void waitForCompletion() throws InterruptedException {
-        mLatch.await();
-    }
-}
diff --git a/hostsidetests/theme/app/src/android/theme/app/CaptureHolo.java b/hostsidetests/theme/app/src/android/theme/app/CaptureHolo.java
deleted file mode 100644
index 7e2b2c9..0000000
--- a/hostsidetests/theme/app/src/android/theme/app/CaptureHolo.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.theme.app;
-
-import android.app.KeyguardManager;
-import android.content.Context;
-import android.test.ActivityInstrumentationTestCase2;
-
-public class CaptureHolo extends ActivityInstrumentationTestCase2<CaptureActivity> {
-
-    public CaptureHolo() {
-        super(CaptureActivity.class);
-    }
-
-    public void testCaptureHolo() throws Exception {
-        setActivityInitialTouchMode(true);
-        CaptureActivity activity = getActivity();
-        KeyguardManager keyguardManager =
-                (KeyguardManager) activity.getSystemService(Context.KEYGUARD_SERVICE);
-        keyguardManager.newKeyguardLock("holo_capture").disableKeyguard();
-        activity.waitForCompletion();
-    }
-}
diff --git a/hostsidetests/theme/app/src/android/theme/app/HoloDeviceActivity.java b/hostsidetests/theme/app/src/android/theme/app/HoloDeviceActivity.java
index 3939979..8ae9fc8 100644
--- a/hostsidetests/theme/app/src/android/theme/app/HoloDeviceActivity.java
+++ b/hostsidetests/theme/app/src/android/theme/app/HoloDeviceActivity.java
@@ -36,6 +36,7 @@
 import android.util.Log;
 import android.view.View;
 import android.widget.CheckBox;
+import android.widget.DatePicker;
 import android.widget.LinearLayout;
 
 import java.io.File;
@@ -50,65 +51,88 @@
 
     public static final String EXTRA_THEME = "holo_theme_extra";
 
-    public static final String EXTRA_LAYOUT = "holo_layout_extra";
-
-    public static final String EXTRA_TIMEOUT = "holo_timeout_extra";
-
     private static final String TAG = HoloDeviceActivity.class.getSimpleName();
 
-    private static final int TIMEOUT = 1 * 1000;//1 sec
+    /**
+     * The duration of the CalendarView adjustement to settle to its final position.
+     */
+    private static final long CALENDAR_VIEW_ADJUSTMENT_DURATION = 540;
 
-    private View mView;
-
-    private String mName;
-
-    private Bitmap mBitmap;
+    private Theme mTheme;
 
     private ReferenceViewGroup mViewGroup;
 
+    private int mLayoutIndex;
+
     @Override
-    public void onCreate(Bundle icicle) {
+    protected void onCreate(Bundle icicle) {
         super.onCreate(icicle);
-        setUpUi(getIntent());
+
+        mTheme = THEMES[getIntent().getIntExtra(EXTRA_THEME, 0)];
+        setTheme(mTheme.mId);
+        setContentView(R.layout.holo_test);
+        mViewGroup = (ReferenceViewGroup) findViewById(R.id.reference_view_group);
     }
 
     @Override
-    public void onNewIntent(Intent intent) {
-        super.onNewIntent(intent);
-        setUpUi(intent);
+    protected void onResume() {
+        super.onResume();
+        setNextLayout();
+    }
+
+    @Override
+    protected void onPause() {
+        if (!isFinishing()) {
+            // The Activity got paused for some reasons, for finish it as the host won't move on to
+            // the next theme otherwise.
+            Log.w(TAG, "onPause called without a call to finish().");
+            finish();
+        }
+        super.onPause();
+    }
+
+    @Override
+    protected void onDestroy() {
+        if (mLayoutIndex != LAYOUTS.length) {
+            Log.w(TAG, "Not all layouts got rendered: " + mLayoutIndex);
+        }
+        Log.i(TAG, "OKAY:" + mTheme.mName);
+        super.onDestroy();
     }
 
     /**
-     * Configures the UI with the given intent
+     * Sets the next layout in the UI.
      */
-    private void setUpUi(Intent intent) {
-        final Theme theme = themes[intent.getIntExtra(EXTRA_THEME, 0)];
-        final Layout layout = layouts[intent.getIntExtra(EXTRA_LAYOUT, 0)];
-        final int timeout = intent.getIntExtra(EXTRA_TIMEOUT, TIMEOUT);
-
-        setTheme(theme.mId);
-        setContentView(R.layout.holo_test);
-
-        mViewGroup = (ReferenceViewGroup) findViewById(R.id.reference_view_group);
-
-        mView = getLayoutInflater().inflate(layout.mId, mViewGroup, false);
-        mViewGroup.addView(mView);
-        if (layout.mModifier != null) {
-            layout.mModifier.modifyView(mView);
+    private void setNextLayout() {
+        if (mLayoutIndex >= LAYOUTS.length) {
+            finish();
+            return;
         }
-        mViewGroup.measure(0, 0);
-        mViewGroup.layout(0, 0, mViewGroup.getMeasuredWidth(), mViewGroup.getMeasuredHeight());
-        mView.setFocusable(false);
-        mName = String.format("%s_%s", theme.mName, layout.mName);
+        final Layout layout = LAYOUTS[mLayoutIndex++];
+        final String layoutName = String.format("%s_%s", mTheme.mName, layout.mName);
 
-        final Handler handler = new Handler();
-        handler.postDelayed(new Runnable() {
+        mViewGroup.removeAllViews();
+        final View view = getLayoutInflater().inflate(layout.mId, mViewGroup, false);
+        if (layout.mModifier != null) {
+            layout.mModifier.modifyView(view);
+        }
+        mViewGroup.addView(view);
+        view.setFocusable(false);
+
+        final Runnable generateBitmapRunnable = new Runnable() {
             @Override
             public void run() {
-                new GenerateBitmapTask().execute();
+                new GenerateBitmapTask(view, layoutName).execute();
             }
-        }, timeout);
-        setResult(RESULT_CANCELED);//On success will be changed to OK
+        };
+
+        if (view instanceof DatePicker) {
+            // DatePicker uses a CalendarView that has a non-configurable adjustment duration of
+            // 540ms
+            view.postDelayed(generateBitmapRunnable, CALENDAR_VIEW_ADJUSTMENT_DURATION);
+        } else {
+            view.post(generateBitmapRunnable);
+        }
     }
 
     /**
@@ -117,12 +141,14 @@
      */
     private class GenerateBitmapTask extends AsyncTask<Void, Void, Boolean> {
 
-        @Override
-        protected void onPreExecute() {
-            final View v = mView;
-            mBitmap = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);
-            final Canvas canvas = new Canvas(mBitmap);
-            v.draw(canvas);
+        private final View mView;
+
+        private final String mName;
+
+        public GenerateBitmapTask(final View view, final String name) {
+            super();
+            mView = view;
+            mName = name;
         }
 
         @Override
@@ -131,6 +157,16 @@
                 Log.i(TAG, "External storage for saving bitmaps is not mounted");
                 return false;
             }
+            if (mView.getWidth() == 0 || mView.getHeight() == 0) {
+                Log.w(TAG, "Unable to draw View due to incorrect size: " + mName);
+                return false;
+            }
+
+            final Bitmap bitmap = Bitmap.createBitmap(
+                    mView.getWidth(), mView.getHeight(), Bitmap.Config.ARGB_8888);
+            final Canvas canvas = new Canvas(bitmap);
+
+            mView.draw(canvas);
             final File dir = new File(Environment.getExternalStorageDirectory(), "cts-holo-assets");
             dir.mkdirs();
             boolean success = false;
@@ -139,27 +175,23 @@
                 FileOutputStream stream = null;
                 try {
                     stream = new FileOutputStream(file);
-                    mBitmap.compress(CompressFormat.PNG, 100, stream);
+                    success = bitmap.compress(CompressFormat.PNG, 100, stream);
                 } finally {
                     if (stream != null) {
                         stream.close();
                     }
                 }
-                success = true;
             } catch (Exception e) {
                 Log.e(TAG, e.getMessage());
             } finally {
-                mBitmap.recycle();
-                mBitmap = null;
+                bitmap.recycle();
             }
             return success;
         }
 
         @Override
         protected void onPostExecute(Boolean success) {
-            Log.i(TAG, (success ? "OKAY" : "ERROR") + ":" + mName);
-            setResult(RESULT_OK);
-            finish();
+            setNextLayout();
         }
     }
 
@@ -178,7 +210,7 @@
         }
     }
 
-    private static final Theme[] themes = {
+    private static final Theme[] THEMES = {
             new Theme(android.R.style.Theme_Holo,
                     "holo"),
             new Theme(android.R.style.Theme_Holo_Dialog,
@@ -247,7 +279,7 @@
         }
     }
 
-    private static final Layout[] layouts = {
+    private static final Layout[] LAYOUTS = {
             new Layout(R.layout.button, "button", null),
             new Layout(R.layout.button, "button_pressed", new ViewPressedModifier()),
             new Layout(R.layout.checkbox, "checkbox", null),
diff --git a/hostsidetests/theme/app/src/android/theme/app/ReferenceViewGroup.java b/hostsidetests/theme/app/src/android/theme/app/ReferenceViewGroup.java
index 077d8d7..8d2461b 100644
--- a/hostsidetests/theme/app/src/android/theme/app/ReferenceViewGroup.java
+++ b/hostsidetests/theme/app/src/android/theme/app/ReferenceViewGroup.java
@@ -72,10 +72,6 @@
 
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        if (!changed) {
-            return;
-        }
-
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
             View child = getChildAt(i);
diff --git a/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java b/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java
index da94b15..8326b1f 100644
--- a/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java
+++ b/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java
@@ -52,8 +52,6 @@
 
     private static final String TAG = ThemeHostTest.class.getSimpleName();
 
-    private static final int CAPTURE_TIMEOUT = 500;//0.5sec in ms
-
     private static final int ADB_TIMEOUT = 60 * 60 * 1000;//60mins in ms
 
     /** The package name of the APK. */
@@ -69,6 +67,8 @@
     private static final String START_CMD = String.format(
             "am start -W -a android.intent.action.MAIN -n %s/%s.%s", PACKAGE, PACKAGE, CLASS);
 
+    private static final String CLEAR_GENERATED_CMD = "rm -rf /sdcard/cts-holo-assets/*.png";
+
     private static final String STOP_CMD = String.format("am force-stop %s", PACKAGE);
 
     private static final String HARDWARE_TYPE_CMD = "dumpsys | grep android.hardware.type";
@@ -87,10 +87,6 @@
     // Intent extra keys
     private static final String EXTRA_THEME = "holo_theme_extra";
 
-    private static final String EXTRA_LAYOUT = "holo_layout_extra";
-
-    private static final String EXTRA_TIMEOUT = "holo_timeout_extra";
-
     private static final String[] THEMES = {
             "holo",
             "holo_dialog",
@@ -211,7 +207,8 @@
         String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
         // Install the APK on the device.
         mDevice.installPackage(app, false, options);
-
+        // Remove previously generated images.
+        mDevice.executeShellCommand(CLEAR_GENERATED_CMD);
         final String densityProp;
 
         if (mDevice.getSerialNumber().startsWith("emulator-")) {
@@ -261,6 +258,8 @@
         mExecutionService.shutdown();
         // Remove the APK.
         mDevice.uninstallPackage(PACKAGE);
+        // Remove generated images.
+        mDevice.executeShellCommand(CLEAR_GENERATED_CMD);
         super.tearDown();
     }
 
@@ -272,7 +271,6 @@
             return;
         }
 
-
         if (mReferences.isEmpty()) {
             Log.logAndDisplay(LogLevel.INFO, TAG,
                     "Skipped HoloThemes test due to no reference images");
@@ -282,20 +280,18 @@
         int numTasks = 0;
         for (int i = 0; i < NUM_THEMES; i++) {
             final String themeName = THEMES[i];
+            runCapture(i, themeName);
             for (int j = 0; j < NUM_LAYOUTS; j++) {
                 final String name = String.format("%s_%s", themeName, LAYOUTS[j]);
-                if (runCapture(i, j, name)) {
-                    final File ref = mReferences.get(name + ".png");
-                    if (!ref.exists()) {
-                        Log.logAndDisplay(LogLevel.INFO, TAG,
-                                "Skipping theme test due to missing reference for reference image " + name);
-                        continue;
-                    }
-                    mCompletionService.submit(new ComparisonTask(mDevice, ref, name));
-                    numTasks++;
-                } else {
-                    Log.logAndDisplay(LogLevel.ERROR, TAG, "Capture failed: " + name);
+                final File ref = mReferences.get(name + ".png");
+                if (!ref.exists()) {
+                    Log.logAndDisplay(LogLevel.INFO, TAG,
+                            "Skipping theme test due to missing reference for reference image " +
+                            name);
+                    continue;
                 }
+                mCompletionService.submit(new ComparisonTask(mDevice, ref, name));
+                numTasks++;
             }
         }
         int failures = 0;
@@ -305,11 +301,9 @@
         assertTrue(failures + " failures in theme test", failures == 0);
     }
 
-    private boolean runCapture(int themeId, int layoutId, String imageName) throws Exception {
+    private void runCapture(int themeId, String themeName) throws Exception {
         final StringBuilder sb = new StringBuilder(START_CMD);
         sb.append(String.format(INTENT_INTEGER_EXTRA, EXTRA_THEME, themeId));
-        sb.append(String.format(INTENT_INTEGER_EXTRA, EXTRA_LAYOUT, layoutId));
-        sb.append(String.format(INTENT_INTEGER_EXTRA, EXTRA_TIMEOUT, CAPTURE_TIMEOUT));
         final String startCommand = sb.toString();
         // Clear logcat
         mDevice.executeAdbCommand("logcat", "-c");
@@ -318,9 +312,8 @@
         // Start activity
         mDevice.executeShellCommand(startCommand);
 
-        boolean success = false;
         boolean waiting = true;
-        while (waiting) {
+        do {
             // Dump logcat.
             final String logs = mDevice.executeAdbCommand(
                     "logcat", "-v", "brief", "-d", CLASS + ":I", "*:S");
@@ -331,20 +324,14 @@
                 if (line.startsWith("I/" + CLASS)) {
                     final String[] lineSplit = line.split(":");
                     final String s = lineSplit[1].trim();
-                    final String imageNameGenerated = lineSplit[2].trim();
-                    if (s.equals("OKAY") && imageNameGenerated.equals(imageName)) {
-                        success = true;
-                        waiting = false;
-                    } else if (s.equals("ERROR") && imageNameGenerated.equals(imageName)) {
-                        success = false;
+                    final String themeNameGenerated = lineSplit[2].trim();
+                    if (s.equals("OKAY") && themeNameGenerated.equals(themeName)) {
                         waiting = false;
                     }
                 }
             }
             in.close();
-        }
-
-        return success;
+        } while (waiting);
     }
 
     private static String getDensityBucket(int density) {
diff --git a/libs/deviceutillegacy/src/android/webkit/cts/WebViewOnUiThread.java b/libs/deviceutillegacy/src/android/webkit/cts/WebViewOnUiThread.java
index adcc06f..2933b0b 100644
--- a/libs/deviceutillegacy/src/android/webkit/cts/WebViewOnUiThread.java
+++ b/libs/deviceutillegacy/src/android/webkit/cts/WebViewOnUiThread.java
@@ -319,11 +319,11 @@
         });
     }
 
-    public void postMessageToMainFrame(final WebMessage message, final Uri targetOrigin) {
+    public void postWebMessage(final WebMessage message, final Uri targetOrigin) {
         runOnUiThread(new Runnable() {
             @Override
             public void run() {
-                mWebView.postMessageToMainFrame(message, targetOrigin);
+                mWebView.postWebMessage(message, targetOrigin);
             }
         });
     }
diff --git a/tests/JobScheduler/src/android/jobscheduler/MockJobService.java b/tests/JobScheduler/src/android/jobscheduler/MockJobService.java
index 38a753d..4f549f8 100644
--- a/tests/JobScheduler/src/android/jobscheduler/MockJobService.java
+++ b/tests/JobScheduler/src/android/jobscheduler/MockJobService.java
@@ -46,7 +46,7 @@
     public boolean onStartJob(JobParameters params) {
         Log.i(TAG, "Test job executing: " + params.getJobId());
 
-        TestEnvironment.getTestEnvironment().notifyExecution(params.getJobId());
+        TestEnvironment.getTestEnvironment().notifyExecution(params);
         return false;  // No work to do.
     }
 
@@ -63,10 +63,10 @@
     public static final class TestEnvironment {
 
         private static TestEnvironment kTestEnvironment;
-        public static final int INVALID_JOB_ID = -1;
+        //public static final int INVALID_JOB_ID = -1;
 
         private CountDownLatch mLatch;
-        private int mExecutedJobId;
+        private JobParameters mExecutedJobParameters;
 
         public static TestEnvironment getTestEnvironment() {
             if (kTestEnvironment == null) {
@@ -75,6 +75,10 @@
             return kTestEnvironment;
         }
 
+        public JobParameters getLastJobParameters() {
+            return mExecutedJobParameters;
+        }
+
         /**
          * Block the test thread, waiting on the JobScheduler to execute some previously scheduled
          * job on this service.
@@ -93,9 +97,9 @@
             return !mLatch.await(DEFAULT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
         }
 
-        private void notifyExecution(int jobId) {
-            Log.d(TAG, "Job executed:" + jobId);
-            mExecutedJobId = jobId;
+        private void notifyExecution(JobParameters params) {
+            Log.d(TAG, "Job executed:" + params.getJobId());
+            mExecutedJobParameters = params;
             mLatch.countDown();
         }
 
@@ -111,7 +115,7 @@
         /** Called in each testCase#setup */
         public void setUp() {
             mLatch = null;
-            mExecutedJobId = INVALID_JOB_ID;
+            mExecutedJobParameters = null;
         }
 
     }
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/TimingConstraintsTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/TimingConstraintsTest.java
index ed9cadd..40b67c8 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/TimingConstraintsTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/TimingConstraintsTest.java
@@ -17,6 +17,7 @@
 
 import android.annotation.TargetApi;
 import android.app.job.JobInfo;
+import android.app.job.JobParameters;
 
 /**
  * Schedules jobs with various timing constraints and ensures that they are executed when
@@ -26,6 +27,8 @@
 public class TimingConstraintsTest extends ConstraintTest {
     private static final int TIMING_JOB_ID = TimingConstraintsTest.class.hashCode() + 0;
     private static final int CANCEL_JOB_ID = TimingConstraintsTest.class.hashCode() + 1;
+    private static final int EXPIRED_JOB_ID = TimingConstraintsTest.class.hashCode() + 2;
+    private static final int UNEXPIRED_JOB_ID = TimingConstraintsTest.class.hashCode() + 3;
 
     public void testScheduleOnce() throws Exception {
         JobInfo oneTimeJob = new JobInfo.Builder(TIMING_JOB_ID, kJobServiceComponent)
@@ -63,4 +66,44 @@
         assertTrue("Cancel failed: job executed when it shouldn't have.",
                 kTestEnvironment.awaitTimeout());
     }
+
+    /**
+     * Ensure that when a job is executed because its deadline has expired, that
+     * {@link JobParameters#isOverrideDeadlineExpired()} returns the correct value.
+     */
+    public void testJobParameters_expiredDeadline() throws Exception {
+
+        JobInfo deadlineJob =
+                new JobInfo.Builder(EXPIRED_JOB_ID, kJobServiceComponent)
+                        .setOverrideDeadline(2000L)
+                        .build();
+        kTestEnvironment.setExpectedExecutions(1);
+        mJobScheduler.schedule(deadlineJob);
+        assertTrue("Failed to execute deadline job", kTestEnvironment.awaitExecution());
+        assertTrue("Job that had its deadline expire didn't have" +
+                        " JobParameters#isOverrideDeadlineExpired=true",
+                kTestEnvironment.getLastJobParameters().isOverrideDeadlineExpired());
+    }
+
+
+    /**
+     * Ensure that when a job is executed and its deadline hasn't expired, that
+     * {@link JobParameters#isOverrideDeadlineExpired()} returns the correct value.
+     */
+    public void testJobParameters_unexpiredDeadline() throws Exception {
+
+        JobInfo deadlineJob =
+                new JobInfo.Builder(UNEXPIRED_JOB_ID, kJobServiceComponent)
+                        .setMinimumLatency(500L)
+                        .setRequiresCharging(true)
+                        .build();
+        kTestEnvironment.setExpectedExecutions(1);
+        mJobScheduler.schedule(deadlineJob);
+        // Run everything by pretending the device was just plugged in.
+        sendExpediteStableChargingBroadcast();
+        assertTrue("Failed to execute non-deadline job", kTestEnvironment.awaitExecution());
+        assertFalse("Job that ran early (unexpired) didn't have" +
+                        " JobParameters#isOverrideDeadlineExpired=false",
+                kTestEnvironment.getLastJobParameters().isOverrideDeadlineExpired());
+    }
 }
\ No newline at end of file
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index 1e29e10..ecb7050 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -89,31 +89,6 @@
   bug: 17993121
 },
 {
-  description: "A few WebGL tests are known to fail in WebView",
-  names: [
-    "android.webgl.cts.WebGLTest#test_conformance_extensions_oes_texture_float_with_video_html",
-    "android.webgl.cts.WebGLTest#test_conformance_renderbuffers_framebuffer_object_attachment_html",
-    "android.webgl.cts.WebGLTest#test_conformance_rendering_multisample_corruption_html",
-    "android.webgl.cts.WebGLTest#test_conformance_textures_tex_image_and_sub_image_2d_with_video_html",
-    "android.webgl.cts.WebGLTest#test_conformance_textures_tex_image_and_sub_image_2d_with_video_rgb565_html",
-    "android.webgl.cts.WebGLTest#test_conformance_textures_tex_image_and_sub_image_2d_with_video_rgba4444_html",
-    "android.webgl.cts.WebGLTest#test_conformance_textures_tex_image_and_sub_image_2d_with_video_rgba5551_html",
-    "android.webgl.cts.WebGLTest#test_conformance_textures_texture_npot_html",
-    "android.webgl.cts.WebGLTest#test_conformance_textures_texture_npot_video_html",
-    "android.webgl.cts.WebGLTest#test_conformance_glsl_misc_empty_main_vert_html",
-    "android.webgl.cts.WebGLTest#test_conformance_glsl_misc_gl_position_unset_vert_html",
-    "android.webgl.cts.WebGLTest#test_conformance_misc_webgl_specific_html"
-  ],
-  bug: 17748398
-},
-{
-  description: "WebGL test uniformMatrixBadArgs is too strict. Disabled until it's fixed upstream.",
-  names: [
-    "android.webgl.cts.WebGLTest#test_conformance_more_functions_uniformMatrixBadArgs_html"
-  ],
-  bug: 18638404
-},
-{
   description: "permissions for the API previously used in the test has changed, making it impossible to pass",
   names: [
     "android.openglperf.cts.GlAppSwitchTest#testGlActivitySwitchingFast",
diff --git a/tests/tests/app/src/android/app/cts/ActivityManagerTest.java b/tests/tests/app/src/android/app/cts/ActivityManagerTest.java
index e633f1f..998a005 100644
--- a/tests/tests/app/src/android/app/cts/ActivityManagerTest.java
+++ b/tests/tests/app/src/android/app/cts/ActivityManagerTest.java
@@ -219,7 +219,8 @@
                 hasTestProcess = true;
             }
         }
-        assertTrue(hasSystemProcess && hasTestProcess);
+        // For security reasons the system process is not exposed.
+        assertTrue(!hasSystemProcess && hasTestProcess);
 
         for (RunningAppProcessInfo ra : list) {
             if (ra.processName.equals("com.android.cts.app.stub:remote")) {
diff --git a/tests/tests/deqp/gles31-temporary-failures.txt b/tests/tests/deqp/gles31-temporary-failures.txt
index d921091..c3986eb 100644
--- a/tests/tests/deqp/gles31-temporary-failures.txt
+++ b/tests/tests/deqp/gles31-temporary-failures.txt
@@ -387,6 +387,38 @@
 dEQP-GLES31.functional.copy_image.compressed.viewclass_etc2_rgb.srgb8_etc2_srgb8_etc2#cubemap_to_cubemap
 dEQP-GLES31.functional.copy_image.compressed.viewclass_etc2_rgb.srgb8_etc2_srgb8_etc2#cubemap_to_texture2d
 dEQP-GLES31.functional.copy_image.compressed.viewclass_etc2_rgb.srgb8_etc2_srgb8_etc2#texture2d_to_cubemap
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_10x10_khr_rgba32i#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_10x10_khr_rgba32ui#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_10x5_khr_rgba32i#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_10x5_khr_rgba32ui#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_10x6_khr_rgba32i#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_10x6_khr_rgba32ui#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_10x8_khr_rgba32i#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_10x8_khr_rgba32ui#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_12x10_khr_rgba32i#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_12x10_khr_rgba32ui#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_12x12_khr_rgba32i#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_12x12_khr_rgba32ui#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_4x4_khr_rgba32i#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_4x4_khr_rgba32ui#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_5x4_khr_rgba32i#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_5x4_khr_rgba32ui#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_5x5_khr_rgba32i#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_5x5_khr_rgba32ui#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_6x5_khr_rgba32i#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_6x5_khr_rgba32ui#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_6x6_khr_rgba32i#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_6x6_khr_rgba32ui#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_8x5_khr_rgba32i#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_8x5_khr_rgba32ui#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_8x6_khr_rgba32i#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_8x6_khr_rgba32ui#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_8x8_khr_rgba32i#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_astc_8x8_khr_rgba32ui#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_etc2_eac_rgba32i#cubemap_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_etc2_eac_rgba32i#texture2d_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_etc2_eac_rgba32ui#cubemap_to_renderbuffer
+dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.srgb8_alpha8_etc2_eac_rgba32ui#texture2d_to_renderbuffer
 dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.rg11_eac_rgba32f#cubemap_to_cubemap
 dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.rg11_eac_rgba32f#cubemap_to_texture2d
 dEQP-GLES31.functional.copy_image.mixed.viewclass_128_bits_mixed.rg11_eac_rgba32f#cubemap_to_texture2d_array
@@ -3240,6 +3272,30 @@
 dEQP-GLES31.functional.copy_image.mixed.viewclass_64_bits_mixed.signed_r11_eac_rgba16ui#texture2d_to_texture2d
 dEQP-GLES31.functional.copy_image.mixed.viewclass_64_bits_mixed.signed_r11_eac_rgba16ui#texture2d_to_texture2d_array
 dEQP-GLES31.functional.copy_image.mixed.viewclass_64_bits_mixed.signed_r11_eac_rgba16ui#texture2d_to_texture3d
+dEQP-GLES31.functional.copy_image.non_compressed.viewclass_24_bits.srgb8_rgb8#cubemap_to_renderbuffer
+dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.r11f_g11f_b10f_srgb8_alpha8#cubemap_to_renderbuffer
+dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.r32f_srgb8_alpha8#cubemap_to_renderbuffer
+dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.r32i_srgb8_alpha8#cubemap_to_renderbuffer
+dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.r32ui_srgb8_alpha8#cubemap_to_renderbuffer
+dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rg16f_srgb8_alpha8#cubemap_to_renderbuffer
+dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rg16i_srgb8_alpha8#cubemap_to_renderbuffer
+dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rg16ui_srgb8_alpha8#cubemap_to_renderbuffer
+dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2_srgb8_alpha8#cubemap_to_renderbuffer
+dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb10_a2ui_srgb8_alpha8#cubemap_to_renderbuffer
+dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgb9_e5_srgb8_alpha8#cubemap_to_renderbuffer
+dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8_srgb8_alpha8#cubemap_to_renderbuffer
+dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8i_srgb8_alpha8#cubemap_to_renderbuffer
+dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.rgba8ui_srgb8_alpha8#cubemap_to_renderbuffer
+dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.srgb8_alpha8_r32i#cubemap_to_renderbuffer
+dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.srgb8_alpha8_r32ui#cubemap_to_renderbuffer
+dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.srgb8_alpha8_rg16i#cubemap_to_renderbuffer
+dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.srgb8_alpha8_rg16ui#cubemap_to_renderbuffer
+dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.srgb8_alpha8_rgb10_a2#cubemap_to_renderbuffer
+dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.srgb8_alpha8_rgb10_a2ui#cubemap_to_renderbuffer
+dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.srgb8_alpha8_rgba8#cubemap_to_renderbuffer
+dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.srgb8_alpha8_rgba8i#cubemap_to_renderbuffer
+dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.srgb8_alpha8_rgba8ui#cubemap_to_renderbuffer
+dEQP-GLES31.functional.copy_image.non_compressed.viewclass_32_bits.srgb8_alpha8_srgb8_alpha8#cubemap_to_renderbuffer
 dEQP-GLES31.functional.copy_image.non_compressed.viewclass_128_bits.rgba32f_rgba32f#cubemap_to_cubemap
 dEQP-GLES31.functional.copy_image.non_compressed.viewclass_128_bits.rgba32f_rgba32f#cubemap_to_texture2d
 dEQP-GLES31.functional.copy_image.non_compressed.viewclass_128_bits.rgba32f_rgba32f#cubemap_to_texture2d_array
@@ -6697,20 +6753,24 @@
 dEQP-GLES31.functional.draw_buffers_indexed.overwrite_common#common_color_mask_buffer_color_mask
 dEQP-GLES31.functional.draw_buffers_indexed.overwrite_common#common_separate_blend_func_buffer_blend_func
 dEQP-GLES31.functional.draw_buffers_indexed.overwrite_common#common_separate_blend_func_buffer_separate_blend_func
-dEQP-GLES31.functional.draw_buffers_indexed.overwrite_indexed#common_blend_eq_buffer_advanced_blend_eq
+dEQP-GLES31.functional.draw_buffers_indexed.overwrite_indexed#common_enable_buffer_enable
+dEQP-GLES31.functional.draw_buffers_indexed.overwrite_indexed#common_disable_buffer_disable
+dEQP-GLES31.functional.draw_buffers_indexed.overwrite_indexed#common_disable_buffer_enable
+dEQP-GLES31.functional.draw_buffers_indexed.overwrite_indexed#common_enable_buffer_disable
 dEQP-GLES31.functional.draw_buffers_indexed.overwrite_indexed#common_blend_eq_buffer_blend_eq
 dEQP-GLES31.functional.draw_buffers_indexed.overwrite_indexed#common_blend_eq_buffer_separate_blend_eq
-dEQP-GLES31.functional.draw_buffers_indexed.overwrite_indexed#common_blend_func_buffer_blend_func
-dEQP-GLES31.functional.draw_buffers_indexed.overwrite_indexed#common_blend_func_buffer_separate_blend_func
-dEQP-GLES31.functional.draw_buffers_indexed.overwrite_indexed#common_color_mask_buffer_color_mask
-dEQP-GLES31.functional.draw_buffers_indexed.overwrite_indexed#common_disable_buffer_disable
-dEQP-GLES31.functional.draw_buffers_indexed.overwrite_indexed#common_enable_buffer_disable
-dEQP-GLES31.functional.draw_buffers_indexed.overwrite_indexed#common_enable_buffer_enable
-dEQP-GLES31.functional.draw_buffers_indexed.overwrite_indexed#common_separate_blend_eq_buffer_advanced_blend_eq
+dEQP-GLES31.functional.draw_buffers_indexed.overwrite_indexed#common_blend_eq_buffer_advanced_blend_eq
 dEQP-GLES31.functional.draw_buffers_indexed.overwrite_indexed#common_separate_blend_eq_buffer_blend_eq
 dEQP-GLES31.functional.draw_buffers_indexed.overwrite_indexed#common_separate_blend_eq_buffer_separate_blend_eq
+dEQP-GLES31.functional.draw_buffers_indexed.overwrite_indexed#common_separate_blend_eq_buffer_advanced_blend_eq
+dEQP-GLES31.functional.draw_buffers_indexed.overwrite_indexed#common_advanced_blend_eq_buffer_blend_eq
+dEQP-GLES31.functional.draw_buffers_indexed.overwrite_indexed#common_advanced_blend_eq_buffer_separate_blend_eq
+dEQP-GLES31.functional.draw_buffers_indexed.overwrite_indexed#common_advanced_blend_eq_buffer_advanced_blend_eq
+dEQP-GLES31.functional.draw_buffers_indexed.overwrite_indexed#common_blend_func_buffer_blend_func
+dEQP-GLES31.functional.draw_buffers_indexed.overwrite_indexed#common_blend_func_buffer_separate_blend_func
 dEQP-GLES31.functional.draw_buffers_indexed.overwrite_indexed#common_separate_blend_func_buffer_blend_func
 dEQP-GLES31.functional.draw_buffers_indexed.overwrite_indexed#common_separate_blend_func_buffer_separate_blend_func
+dEQP-GLES31.functional.draw_buffers_indexed.overwrite_indexed#common_color_mask_buffer_color_mask
 dEQP-GLES31.functional.draw_buffers_indexed.random.max_implementation_draw_buffers#0
 dEQP-GLES31.functional.draw_buffers_indexed.random.max_implementation_draw_buffers#1
 dEQP-GLES31.functional.draw_buffers_indexed.random.max_implementation_draw_buffers#14
@@ -8687,6 +8747,10 @@
 dEQP-GLES31.functional.shaders.uniform_block.invalid#repeated_block_vertex
 dEQP-GLES31.functional.shaders.uniform_block.invalid#too_long_block_name_fragment
 dEQP-GLES31.functional.shaders.uniform_block.invalid#too_long_block_name_vertex
+dEQP-GLES31.functional.shaders.uniform_block.invalid#global_layout_std430_fragment
+dEQP-GLES31.functional.shaders.uniform_block.invalid#global_layout_std430_vertex
+dEQP-GLES31.functional.shaders.uniform_block.invalid#structure_definition_fragment
+dEQP-GLES31.functional.shaders.uniform_block.invalid#structure_definition_vertex
 dEQP-GLES31.functional.shaders.uniform_block.valid#member_layout_all_8_times_fragment
 dEQP-GLES31.functional.shaders.uniform_block.valid#member_layout_all_8_times_vertex
 dEQP-GLES31.functional.shaders.uniform_block.valid#member_layout_all_fragment
diff --git a/tests/tests/graphics/src/android/graphics/cts/ColorMatrixColorFilterTest.java b/tests/tests/graphics/src/android/graphics/cts/ColorMatrixColorFilterTest.java
index fdef54c..2657d15 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ColorMatrixColorFilterTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ColorMatrixColorFilterTest.java
@@ -70,7 +70,10 @@
         paint.setColor(Color.RED);
         bitmap.eraseColor(Color.TRANSPARENT);
         canvas.drawPoint(0, 0, paint);
-        assertColor(Color.argb(128, 255, 0, 64), bitmap.getPixel(0, 0));
+        // the bitmap stores the result in premul colors and we read out an
+        // unpremultiplied result, which causes us to need a bigger tolerance in
+        // this case (due to the fact that scaling by 1/255 is not exact).
+        assertColor(Color.argb(128, 255, 0, 64), bitmap.getPixel(0, 0), 2);
         paint.setColor(Color.CYAN);
         canvas.drawPoint(0, 0, paint);
         // blue gets clipped
@@ -89,9 +92,13 @@
     }
 
     private void assertColor(int expected, int actual) {
-        assertEquals(Color.red(expected), Color.red(actual), TOLERANCE);
-        assertEquals(Color.green(expected), Color.green(actual), TOLERANCE);
-        assertEquals(Color.blue(expected), Color.blue(actual), TOLERANCE);
-        assertEquals(Color.alpha(expected), Color.alpha(actual), TOLERANCE);
+        assertColor(expected, actual, TOLERANCE);
+    }
+    
+    private void assertColor(int expected, int actual, int tolerance) {
+        assertEquals(Color.red(expected), Color.red(actual), tolerance);
+        assertEquals(Color.green(expected), Color.green(actual), tolerance);
+        assertEquals(Color.blue(expected), Color.blue(actual), tolerance);
+        assertEquals(Color.alpha(expected), Color.alpha(actual), tolerance);
     }
 }
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/BurstCaptureTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/BurstCaptureTest.java
index da8ea65..5a66fa7 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/BurstCaptureTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/BurstCaptureTest.java
@@ -32,6 +32,7 @@
 
 import java.util.List;
 import java.util.ArrayList;
+import java.util.Arrays;
 
 public class BurstCaptureTest extends Camera2SurfaceViewTestCase {
     private static final String TAG = "BurstCaptureTest";
@@ -74,7 +75,8 @@
         final Size previewSize = mOrderedPreviewSizes.get(0);
 
         // Get maximum YUV_420_888 size
-        final Size stillSize = getMaxPreviewSize(cameraId, mCameraManager);
+        final Size stillSize = getSortedSizesForFormat(
+                cameraId, mCameraManager, ImageFormat.YUV_420_888, /*bound*/null).get(0);
 
         // Find max pipeline depth and sync latency
         final int maxPipelineDepth = mStaticInfo.getCharacteristics().get(
@@ -89,24 +91,34 @@
                 config.getOutputMinFrameDuration(ImageFormat.YUV_420_888, stillSize);
 
         // Find suitable target FPS range - as high as possible
-        Range<Integer>[] fpsRanges = mStaticInfo.getAeAvailableTargetFpsRangesChecked();
-        int minBurstFps = (int) Math.floor(1e9 / minStillFrameDuration);
-        Range<Integer> targetRange = null;
-        for (Range<Integer> candidateRange : fpsRanges) {
-            if (candidateRange.getLower() >= minBurstFps) {
-                if (targetRange == null) {
-                    targetRange = candidateRange;
-                } else if (candidateRange.getLower() > targetRange.getLower()) {
-                    targetRange = candidateRange;
-                } else if (candidateRange.getUpper() > targetRange.getUpper()) {
-                    targetRange = candidateRange;
-                }
+        List<Range<Integer> > fpsRanges = Arrays.asList(
+                mStaticInfo.getAeAvailableTargetFpsRangesChecked());
+        Range<Integer> targetRange = mStaticInfo.getAeMaxTargetFpsRange();
+        // Add 0.05 here so Fps like 29.99 evaluated to 30
+        int minBurstFps = (int) Math.floor(1e9 / minStillFrameDuration + 0.05f);
+        boolean foundConstantMaxYUVRange = false;
+        boolean foundYUVStreamingRange = false;
+
+        for (Range<Integer> fpsRange : fpsRanges) {
+            if (fpsRange.getLower() == minBurstFps && fpsRange.getUpper() == minBurstFps) {
+                foundConstantMaxYUVRange = true;
             }
+            if (fpsRange.getLower() <= 15 && fpsRange.getUpper() == minBurstFps) {
+                foundYUVStreamingRange = true;
+            }
+        }
+
+        if (mStaticInfo.isHardwareLevelLimitedOrBetter()) {
+            assertTrue(String.format("Cam %s: Target FPS range of (%d, %d) must be supported",
+                    cameraId, minBurstFps, minBurstFps), foundConstantMaxYUVRange);
+            assertTrue(String.format(
+                    "Cam %s: Target FPS range of (x, %d) where x <= 15 must be supported",
+                    cameraId, minBurstFps), foundYUVStreamingRange);
         }
         assertTrue(String.format("Cam %s: No target FPS range found with minimum FPS above " +
                         " 1/minFrameDuration (%d fps, duration %d ns) for full-resolution YUV",
-                cameraId, minBurstFps, minStillFrameDuration),
-            targetRange != null);
+                        cameraId, minBurstFps, minStillFrameDuration),
+                targetRange.getLower() >= minBurstFps);
 
         Log.i(TAG, String.format("Selected frame rate range %d - %d for YUV burst",
                         targetRange.getLower(), targetRange.getUpper()));
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraDeviceTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraDeviceTest.java
index 53ca31f..be80eea 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraDeviceTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraDeviceTest.java
@@ -23,6 +23,7 @@
 import static android.hardware.camera2.CaptureRequest.*;
 
 import android.content.Context;
+import android.graphics.SurfaceTexture;
 import android.graphics.ImageFormat;
 import android.hardware.camera2.CameraAccessException;
 import android.hardware.camera2.CameraCaptureSession;
@@ -380,11 +381,7 @@
                 closeSession();
             }
             finally {
-                try {
-
-                } finally {
-                    closeDevice(mCameraIds[i], mCameraMockListener);
-                }
+                closeDevice(mCameraIds[i], mCameraMockListener);
             }
         }
     }
@@ -581,6 +578,146 @@
         }
     }
 
+    /**
+     * Verify basic semantics and error conditions of the prepare call.
+     *
+     */
+    public void testPrepare() throws Exception {
+        for (int i = 0; i < mCameraIds.length; i++) {
+            try {
+                openDevice(mCameraIds[i], mCameraMockListener);
+                waitForDeviceState(STATE_OPENED, CAMERA_OPEN_TIMEOUT_MS);
+
+                prepareTestByCamera();
+            }
+            finally {
+                closeDevice(mCameraIds[i], mCameraMockListener);
+            }
+        }
+    }
+
+    private void prepareTestByCamera() throws Exception {
+        final int PREPARE_TIMEOUT_MS = 10000;
+
+        mSessionMockListener = spy(new BlockingSessionCallback());
+
+        SurfaceTexture output1 = new SurfaceTexture(1);
+        Surface output1Surface = new Surface(output1);
+        SurfaceTexture output2 = new SurfaceTexture(2);
+        Surface output2Surface = new Surface(output2);
+
+        List<Surface> outputSurfaces = new ArrayList<>(
+            Arrays.asList(output1Surface, output2Surface));
+        mCamera.createCaptureSession(outputSurfaces, mSessionMockListener, mHandler);
+
+        mSession = mSessionMockListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
+
+        // Try basic prepare
+
+        mSession.prepare(output1Surface);
+
+        verify(mSessionMockListener, timeout(PREPARE_TIMEOUT_MS).times(1))
+                .onSurfacePrepared(eq(mSession), eq(output1Surface));
+
+        // Should not complain if preparing already prepared stream
+
+        mSession.prepare(output1Surface);
+
+        verify(mSessionMockListener, timeout(PREPARE_TIMEOUT_MS).times(2))
+                .onSurfacePrepared(eq(mSession), eq(output1Surface));
+
+        // Check surface not included in session
+
+        SurfaceTexture output3 = new SurfaceTexture(3);
+        Surface output3Surface = new Surface(output3);
+        try {
+            mSession.prepare(output3Surface);
+            fail("Preparing surface not part of session must throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        // Ensure second prepare also works
+
+        mSession.prepare(output2Surface);
+
+        verify(mSessionMockListener, timeout(PREPARE_TIMEOUT_MS).times(1))
+                .onSurfacePrepared(eq(mSession), eq(output2Surface));
+
+        // Use output1
+
+        CaptureRequest.Builder r = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        r.addTarget(output1Surface);
+
+        mSession.capture(r.build(), null, null);
+
+        try {
+            mSession.prepare(output1Surface);
+            fail("Preparing already-used surface must throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        // Create new session with outputs 1 and 3, ensure output1Surface still can't be prepared
+        // again
+
+        mSessionMockListener = spy(new BlockingSessionCallback());
+
+        outputSurfaces = new ArrayList<>(
+            Arrays.asList(output1Surface, output3Surface));
+        mCamera.createCaptureSession(outputSurfaces, mSessionMockListener, mHandler);
+
+        mSession = mSessionMockListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
+
+        try {
+            mSession.prepare(output1Surface);
+            fail("Preparing surface used in previous session must throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        // Use output3, wait for result, then make sure prepare still doesn't work
+
+        r = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        r.addTarget(output3Surface);
+
+        SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
+        mSession.capture(r.build(), resultListener, mHandler);
+
+        resultListener.getCaptureResult(CAPTURE_RESULT_TIMEOUT_MS);
+
+        try {
+            mSession.prepare(output3Surface);
+            fail("Preparing already-used surface must throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        // Create new session with outputs 1 and 2, ensure output2Surface can be prepared again
+
+        mSessionMockListener = spy(new BlockingSessionCallback());
+
+        outputSurfaces = new ArrayList<>(
+            Arrays.asList(output1Surface, output2Surface));
+        mCamera.createCaptureSession(outputSurfaces, mSessionMockListener, mHandler);
+
+        mSession = mSessionMockListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
+
+        mSession.prepare(output2Surface);
+
+        verify(mSessionMockListener, timeout(PREPARE_TIMEOUT_MS).times(1))
+                .onSurfacePrepared(eq(mSession), eq(output2Surface));
+
+        try {
+            mSession.prepare(output1Surface);
+            fail("Preparing surface used in previous session must throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+    }
+
+
     private void invalidRequestCaptureTestByCamera() throws Exception {
         if (VERBOSE) Log.v(TAG, "invalidRequestCaptureTestByCamera");
 
@@ -888,7 +1025,7 @@
         mSession = mSessionMockListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
         waitForSessionState(SESSION_CONFIGURED, SESSION_CONFIGURE_TIMEOUT_MS);
         waitForSessionState(SESSION_READY, SESSION_READY_TIMEOUT_MS);
-}
+    }
 
     private void waitForDeviceState(int state, long timeoutMs) {
         mCameraMockListener.waitForState(state, timeoutMs);
@@ -1298,6 +1435,10 @@
             if (mStaticInfo.areKeysAvailable(TONEMAP_MODE)) {
                 mCollector.expectKeyValueNotEquals(request, TONEMAP_MODE,
                         CaptureRequest.TONEMAP_MODE_CONTRAST_CURVE);
+                mCollector.expectKeyValueNotEquals(request, TONEMAP_MODE,
+                        CaptureRequest.TONEMAP_MODE_GAMMA_VALUE);
+                mCollector.expectKeyValueNotEquals(request, TONEMAP_MODE,
+                        CaptureRequest.TONEMAP_MODE_PRESET_CURVE);
             }
             if (mStaticInfo.areKeysAvailable(STATISTICS_LENS_SHADING_MAP_MODE)) {
                 mCollector.expectKeyValueNotNull(request, STATISTICS_LENS_SHADING_MAP_MODE);
@@ -1333,7 +1474,7 @@
                     // OK
                 } else if (template == CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG &&
                         !mStaticInfo.isCapabilitySupported(CameraCharacteristics.
-                                REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING)) {
+                                REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING)) {
                     // OK.
                 } else if (sLegacySkipTemplates.contains(template) &&
                         mStaticInfo.isHardwareLevelLegacy()) {
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraManagerTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraManagerTest.java
index 27ff6d1..77a0c8e 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraManagerTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraManagerTest.java
@@ -422,38 +422,23 @@
                         new BlockingStateCallback(mockFailListener);
 
                 mCameraManager.openCamera(ids[i], successListener, mHandler);
-
-                try {
-                    mCameraManager.openCamera(ids[i], failListener,
-                            mHandler);
-                } catch (CameraAccessException e) {
-                    // Optional (but common). Camera might fail asynchronously only.
-                    // Don't assert here, otherwise, all subsequent tests will fail because the
-                    // opened camera is never closed.
-                    mCollector.expectEquals(
-                            "If second camera open fails immediately, must be due to"
-                            + "camera being busy for ID: " + ids[i],
-                            CameraAccessException.CAMERA_ERROR, e.getReason());
-                }
+                mCameraManager.openCamera(ids[i], failListener,
+                        mHandler);
 
                 successListener.waitForState(BlockingStateCallback.STATE_OPENED,
                         CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
-                // Have to get the successCamera here, otherwise, it won't be
-                // closed if STATE_ERROR timeout exception occurs.
                 ArgumentCaptor<CameraDevice> argument =
                         ArgumentCaptor.forClass(CameraDevice.class);
                 verify(mockSuccessListener, atLeastOnce()).onOpened(argument.capture());
+                verify(mockSuccessListener, atLeastOnce()).onDisconnected(argument.capture());
 
-                failListener.waitForState(BlockingStateCallback.STATE_ERROR,
+                failListener.waitForState(BlockingStateCallback.STATE_OPENED,
                         CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
+                verify(mockFailListener, atLeastOnce()).onOpened(argument.capture());
 
                 successCamera = verifyCameraStateOpened(
-                        ids[i], mockSuccessListener);
+                        ids[i], mockFailListener);
 
-                verify(mockFailListener)
-                        .onError(
-                                and(notNull(CameraDevice.class), not(eq(successCamera))),
-                                eq(StateCallback.ERROR_CAMERA_IN_USE));
                 verifyNoMoreInteractions(mockFailListener);
             } finally {
                 if (successCamera != null) {
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
index 08f628f..d39ff1f 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -109,13 +109,8 @@
     public static ImageReader makeImageReader(Size size, int format, int maxNumImages,
             ImageReader.OnImageAvailableListener listener, Handler handler) {
         ImageReader reader;
-        if (format == ImageFormat.PRIVATE) {
-            reader = ImageReader.newOpaqueInstance(size.getWidth(), size.getHeight(),
-                    maxNumImages);
-        } else {
-            reader = ImageReader.newInstance(size.getWidth(), size.getHeight(), format,
-                    maxNumImages);
-        }
+        reader = ImageReader.newInstance(size.getWidth(), size.getHeight(), format,
+                maxNumImages);
         reader.setOnImageAvailableListener(listener, handler);
         if (VERBOSE) Log.v(TAG, "Created ImageReader size " + size);
         return reader;
@@ -132,9 +127,9 @@
      */
     public static ImageWriter makeImageWriter(
             Surface inputSurface, int maxImages,
-            ImageWriter.ImageListener listener, Handler handler) {
+            ImageWriter.OnImageReleasedListener listener, Handler handler) {
         ImageWriter writer = ImageWriter.newInstance(inputSurface, maxImages);
-        writer.setImageListener(listener, handler);
+        writer.setOnImageReleasedListener(listener, handler);
         return writer;
     }
 
@@ -286,11 +281,11 @@
         }
     }
 
-    public static class SimpleImageWriterListener implements ImageWriter.ImageListener {
+    public static class SimpleImageWriterListener implements ImageWriter.OnImageReleasedListener {
         private final Semaphore mImageReleasedSema = new Semaphore(0);
         private final ImageWriter mWriter;
         @Override
-        public void onInputImageReleased(ImageWriter writer) {
+        public void onImageReleased(ImageWriter writer) {
             if (writer != mWriter) {
                 return;
             }
@@ -565,19 +560,26 @@
             throws CameraAccessException {
         BlockingSessionCallback sessionListener = new BlockingSessionCallback(listener);
         camera.createCaptureSession(outputSurfaces, sessionListener, handler);
+        CameraCaptureSession session =
+                sessionListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
+        assertFalse("Camera session should not be a reprocessable session",
+                session.isReprocessable());
 
-        return sessionListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
+        return session;
     }
 
-    public static CameraCaptureSession configureReprocessibleCameraSession(CameraDevice camera,
+    public static CameraCaptureSession configureReprocessableCameraSession(CameraDevice camera,
             InputConfiguration inputConfiguration, List<Surface> outputSurfaces,
             CameraCaptureSession.StateCallback listener, Handler handler)
             throws CameraAccessException {
         BlockingSessionCallback sessionListener = new BlockingSessionCallback(listener);
-        camera.createReprocessibleCaptureSession(inputConfiguration, outputSurfaces,
+        camera.createReprocessableCaptureSession(inputConfiguration, outputSurfaces,
                 sessionListener, handler);
+        CameraCaptureSession session =
+                sessionListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
+        assertTrue("Camera session should be a reprocessable session", session.isReprocessable());
 
-        return sessionListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
+        return session;
     }
 
     public static <T> void assertArrayNotEmpty(T arr, String message) {
@@ -1270,8 +1272,9 @@
         if (src.getFormat() != dst.getFormat()) {
             throw new IllegalArgumentException("Src and dst images should have the same format");
         }
-        if (src.isOpaque() || dst.isOpaque()) {
-            throw new IllegalArgumentException("Opaque image is not copyable");
+        if (src.getFormat() == ImageFormat.PRIVATE ||
+                dst.getFormat() == ImageFormat.PRIVATE) {
+            throw new IllegalArgumentException("PRIVATE format images are not copyable");
         }
 
         // TODO: check the owner of the dst image, it must be from ImageWriter, other source may
@@ -1298,9 +1301,9 @@
      * Checks whether the two images are strongly equal.
      * </p>
      * <p>
-     * Two images are strongly equal if and only if the data, formats, sizes, and
-     * timestamps are same. For opaque images ({@link Image#isOpaque()} returns
-     * true), the image data is not not accessible thus the data comparison is
+     * Two images are strongly equal if and only if the data, formats, sizes,
+     * and timestamps are same. For {@link ImageFormat#PRIVATE PRIVATE} format
+     * images, the image data is not not accessible thus the data comparison is
      * effectively skipped as the number of planes is zero.
      * </p>
      * <p>
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
index 68c8077..f3acf4c 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
@@ -1389,73 +1389,70 @@
             return;
         }
 
-        SimpleCaptureCallback listener;
         CaptureRequest.Builder requestBuilder =
                 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
-
-        Size maxPreviewSz = mOrderedPreviewSizes.get(0); // Max preview size.
-
         int[] toneMapModes = mStaticInfo.getAvailableToneMapModesChecked();
         for (int mode : toneMapModes) {
-            requestBuilder.set(CaptureRequest.TONEMAP_MODE, mode);
             if (VERBOSE) {
                 Log.v(TAG, "Testing tonemap mode " + mode);
             }
 
-            if (mode == CaptureRequest.TONEMAP_MODE_CONTRAST_CURVE) {
-                TonemapCurve tcLinear = new TonemapCurve(
-                        TONEMAP_CURVE_LINEAR, TONEMAP_CURVE_LINEAR, TONEMAP_CURVE_LINEAR);
-                requestBuilder.set(CaptureRequest.TONEMAP_CURVE, tcLinear);
-                // Create a new listener for each run to avoid the results from one run spill
-                // into another run.
-                listener = new SimpleCaptureCallback();
-                startPreview(requestBuilder, maxPreviewSz, listener);
-                waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
-                verifyToneMapModeResults(listener, NUM_FRAMES_VERIFIED, mode,
-                        TONEMAP_CURVE_LINEAR);
+            requestBuilder.set(CaptureRequest.TONEMAP_MODE, mode);
+            switch (mode) {
+                case CaptureRequest.TONEMAP_MODE_CONTRAST_CURVE:
+                    TonemapCurve toneCurve = new TonemapCurve(TONEMAP_CURVE_LINEAR,
+                            TONEMAP_CURVE_LINEAR, TONEMAP_CURVE_LINEAR);
+                    requestBuilder.set(CaptureRequest.TONEMAP_CURVE, toneCurve);
+                    testToneMapMode(NUM_FRAMES_VERIFIED, requestBuilder);
 
-                TonemapCurve tcSrgb = new TonemapCurve(
-                        TONEMAP_CURVE_SRGB, TONEMAP_CURVE_SRGB, TONEMAP_CURVE_SRGB);
-                requestBuilder.set(CaptureRequest.TONEMAP_CURVE, tcSrgb);
-                // Create a new listener for each run to avoid the results from one run spill
-                // into another run.
-                listener = new SimpleCaptureCallback();
-                startPreview(requestBuilder, maxPreviewSz, listener);
-                waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
-                verifyToneMapModeResults(listener, NUM_FRAMES_VERIFIED, mode,
-                        TONEMAP_CURVE_SRGB);
-            } else {
-                // Create a new listener for each run to avoid the results from one run spill
-                // into another run.
-                listener = new SimpleCaptureCallback();
-                startPreview(requestBuilder, maxPreviewSz, listener);
-                waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
-                verifyToneMapModeResults(listener, NUM_FRAMES_VERIFIED, mode,
-                        /*inputToneCurve*/null);
+                    toneCurve = new TonemapCurve(TONEMAP_CURVE_SRGB,
+                            TONEMAP_CURVE_SRGB, TONEMAP_CURVE_SRGB);
+                    requestBuilder.set(CaptureRequest.TONEMAP_CURVE, toneCurve);
+                    testToneMapMode(NUM_FRAMES_VERIFIED, requestBuilder);
+                    break;
+                case CaptureRequest.TONEMAP_MODE_GAMMA_VALUE:
+                    requestBuilder.set(CaptureRequest.TONEMAP_GAMMA, 1.0f);
+                    testToneMapMode(NUM_FRAMES_VERIFIED, requestBuilder);
+                    requestBuilder.set(CaptureRequest.TONEMAP_GAMMA, 2.2f);
+                    testToneMapMode(NUM_FRAMES_VERIFIED, requestBuilder);
+                    requestBuilder.set(CaptureRequest.TONEMAP_GAMMA, 5.0f);
+                    testToneMapMode(NUM_FRAMES_VERIFIED, requestBuilder);
+                    break;
+                case CaptureRequest.TONEMAP_MODE_PRESET_CURVE:
+                    requestBuilder.set(CaptureRequest.TONEMAP_PRESET_CURVE,
+                            CaptureRequest.TONEMAP_PRESET_CURVE_REC709);
+                    testToneMapMode(NUM_FRAMES_VERIFIED, requestBuilder);
+                    requestBuilder.set(CaptureRequest.TONEMAP_PRESET_CURVE,
+                            CaptureRequest.TONEMAP_PRESET_CURVE_SRGB);
+                    testToneMapMode(NUM_FRAMES_VERIFIED, requestBuilder);
+                    break;
+                default:
+                    testToneMapMode(NUM_FRAMES_VERIFIED, requestBuilder);
+                    break;
             }
         }
 
-        stopPreview();
+
     }
 
     /**
-     * Verify tonemap results.
-     * <p>
-     * Assumes R,G,B channels use the same tone curve
-     * </p>
+     * Test tonemap mode with speficied request settings
      *
-     * @param listener The capture listener used to get the capture results
      * @param numFramesVerified Number of results to be verified
-     * @param tonemapMode Tonemap mode to verify
-     * @param inputToneCurve Tonemap curve used by all 3 channels, ignored when
-     * map mode is not CONTRAST_CURVE.
+     * @param requestBuilder the request builder of settings to be tested
      */
-    private void verifyToneMapModeResults(SimpleCaptureCallback listener, int numFramesVerified,
-            int tonemapMode, float[] inputToneCurve) {
+    private void testToneMapMode (int numFramesVerified,
+            CaptureRequest.Builder requestBuilder)  throws Exception  {
         final int MIN_TONEMAP_CURVE_POINTS = 2;
         final Float ZERO = new Float(0);
         final Float ONE = new Float(1.0f);
 
+        SimpleCaptureCallback listener = new SimpleCaptureCallback();
+        int tonemapMode = requestBuilder.get(CaptureRequest.TONEMAP_MODE);
+        Size maxPreviewSz = mOrderedPreviewSizes.get(0); // Max preview size.
+        startPreview(requestBuilder, maxPreviewSz, listener);
+        waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+
         int maxCurvePoints = mStaticInfo.getMaxTonemapCurvePointChecked();
         for (int i = 0; i < numFramesVerified; i++) {
             CaptureResult result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
@@ -1477,6 +1474,14 @@
                  * between request and result, as they may have different array
                  * size.
                  */
+            } else if (tonemapMode == CaptureResult.TONEMAP_MODE_GAMMA_VALUE) {
+                mCollector.expectEquals("Capture result gamma value should match request",
+                        requestBuilder.get(CaptureRequest.TONEMAP_GAMMA),
+                        result.get(CaptureResult.TONEMAP_GAMMA));
+            } else if (tonemapMode == CaptureResult.TONEMAP_MODE_PRESET_CURVE) {
+                mCollector.expectEquals("Capture result preset curve should match request",
+                        requestBuilder.get(CaptureRequest.TONEMAP_PRESET_CURVE),
+                        result.get(CaptureResult.TONEMAP_PRESET_CURVE));
             }
 
             // Tonemap curve result availability and basic sanity check for all modes.
@@ -1493,6 +1498,7 @@
             mCollector.expectInRange("Tonemap curve blue length is out of range",
                     mapBlue.length, MIN_TONEMAP_CURVE_POINTS, maxCurvePoints * 2);
         }
+        stopPreview();
     }
 
     /**
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureResultTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureResultTest.java
index ec9e41b..2430dd0 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureResultTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureResultTest.java
@@ -440,17 +440,21 @@
 
         // Keys only present when corresponding control is on are being
         // verified in its own functional test
-        // Only present when tone mapping mode is CONTRAST_CURVE
+        // Only present in certain tonemap mode. Test in CaptureRequestTest.
         waiverKeys.add(CaptureResult.TONEMAP_CURVE);
+        waiverKeys.add(CaptureResult.TONEMAP_GAMMA);
+        waiverKeys.add(CaptureResult.TONEMAP_PRESET_CURVE);
         // Only present when test pattern mode is SOLID_COLOR.
         // TODO: verify this key in test pattern test later
         waiverKeys.add(CaptureResult.SENSOR_TEST_PATTERN_DATA);
         // Only present when STATISTICS_LENS_SHADING_MAP_MODE is ON
         waiverKeys.add(CaptureResult.STATISTICS_LENS_SHADING_CORRECTION_MAP);
-        //  Only present when STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES is ON
+        // Only present when STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES is ON
         waiverKeys.add(CaptureResult.STATISTICS_HOT_PIXEL_MAP);
-        //  Only present when face detection is on
+        // Only present when face detection is on
         waiverKeys.add(CaptureResult.STATISTICS_FACES);
+        // Only present in reprocessing capture result.
+        waiverKeys.add(CaptureResult.REPROCESS_EFFECTIVE_EXPOSURE_FACTOR);
 
         //Keys not required if RAW is not supported
         if (!mStaticInfo.isCapabilitySupported(
@@ -460,6 +464,13 @@
             waiverKeys.add(CaptureResult.SENSOR_NOISE_PROFILE);
         }
 
+        //Keys for depth output capability
+        if (!mStaticInfo.isCapabilitySupported(
+                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT)) {
+            waiverKeys.add(CaptureResult.LENS_POSE_ROTATION);
+            waiverKeys.add(CaptureResult.LENS_POSE_TRANSLATION);
+        }
+
         if (mStaticInfo.getAeMaxRegionsChecked() == 0) {
             waiverKeys.add(CaptureResult.CONTROL_AE_REGIONS);
         }
@@ -687,6 +698,8 @@
         resultKeys.add(CaptureResult.LENS_FOCAL_LENGTH);
         resultKeys.add(CaptureResult.LENS_FOCUS_DISTANCE);
         resultKeys.add(CaptureResult.LENS_OPTICAL_STABILIZATION_MODE);
+        resultKeys.add(CaptureResult.LENS_POSE_ROTATION);
+        resultKeys.add(CaptureResult.LENS_POSE_TRANSLATION);
         resultKeys.add(CaptureResult.LENS_FOCUS_RANGE);
         resultKeys.add(CaptureResult.LENS_STATE);
         resultKeys.add(CaptureResult.NOISE_REDUCTION_MODE);
@@ -712,7 +725,10 @@
         resultKeys.add(CaptureResult.STATISTICS_LENS_SHADING_MAP_MODE);
         resultKeys.add(CaptureResult.TONEMAP_CURVE);
         resultKeys.add(CaptureResult.TONEMAP_MODE);
+        resultKeys.add(CaptureResult.TONEMAP_GAMMA);
+        resultKeys.add(CaptureResult.TONEMAP_PRESET_CURVE);
         resultKeys.add(CaptureResult.BLACK_LEVEL_LOCK);
+        resultKeys.add(CaptureResult.REPROCESS_EFFECTIVE_EXPOSURE_FACTOR);
 
         return resultKeys;
     }
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
index 00a5d66..38332a1 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
@@ -87,7 +87,7 @@
     private static final int YUV_REPROCESS =
             CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING;
     private static final int OPAQUE_REPROCESS =
-            CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING;
+            CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING;
 
     @Override
     public void setContext(Context context) {
@@ -204,11 +204,13 @@
                 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES          , LEGACY   ,   BC                   );
                 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE                   , LEGACY   ,   BC                   );
                 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AE_COMPENSATION_STEP                    , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.CONTROL_AE_LOCK_AVAILABLE                       , LEGACY   ,   BC                   );
                 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES                      , LEGACY   ,   BC                   );
                 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AVAILABLE_EFFECTS                       , LEGACY   ,   BC                   );
                 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES                   , LEGACY   ,   BC                   );
                 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES     , LEGACY   ,   BC                   );
                 expectKeyAvailable(c, CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES                     , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.CONTROL_AWB_LOCK_AVAILABLE                      , LEGACY   ,   BC                   );
                 expectKeyAvailable(c, CameraCharacteristics.CONTROL_MAX_REGIONS_AE                          , LEGACY   ,   BC                   );
                 expectKeyAvailable(c, CameraCharacteristics.CONTROL_MAX_REGIONS_AF                          , LEGACY   ,   BC                   );
                 expectKeyAvailable(c, CameraCharacteristics.CONTROL_MAX_REGIONS_AWB                         , LEGACY   ,   BC                   );
@@ -335,6 +337,10 @@
             BlackLevelPattern blackLevel = mCollector.expectKeyValueNotNull(c,
                     CameraCharacteristics.SENSOR_BLACK_LEVEL_PATTERN);
             if (blackLevel != null) {
+                String blackLevelPatternString = blackLevel.toString();
+                if (VERBOSE) {
+                    Log.v(TAG, "Black level pattern: " + blackLevelPatternString);
+                }
                 int[] blackLevelPattern = new int[BlackLevelPattern.COUNT];
                 blackLevel.copyTo(blackLevelPattern, /*offset*/0);
                 Integer whitelevel = c.get(CameraCharacteristics.SENSOR_INFO_WHITE_LEVEL);
@@ -491,7 +497,7 @@
             boolean supportYUV = arrayContains(capabilities,
                     CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING);
             boolean supportOpaque = arrayContains(capabilities,
-                    CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING);
+                    CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING);
             StreamConfigurationMap configs =
                     c.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
             Integer maxNumInputStreams =
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/ImageWriterTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/ImageWriterTest.java
index d9e5cdf..b081660 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/ImageWriterTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/ImageWriterTest.java
@@ -28,7 +28,6 @@
 import android.media.Image.Plane;
 import android.media.ImageReader;
 import android.media.ImageWriter;
-import android.os.ConditionVariable;
 import android.util.Log;
 import android.util.Size;
 import android.view.Surface;
@@ -51,7 +50,7 @@
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     // Max number of images can be accessed simultaneously from ImageReader.
     private static final int MAX_NUM_IMAGES = 3;
-    private static final int CAMERA_OPAQUE_FORMAT = ImageFormat.PRIVATE;
+    private static final int CAMERA_PRIVATE_FORMAT = ImageFormat.PRIVATE;
     private ImageReader mReaderForWriter;
     private ImageWriter mWriter;
 
@@ -125,7 +124,7 @@
             try {
                 Log.i(TAG, "Testing Camera " + id);
                 openDevice(id);
-                readerWriterFormatTestByCamera(CAMERA_OPAQUE_FORMAT);
+                readerWriterFormatTestByCamera(CAMERA_PRIVATE_FORMAT);
             } finally {
                 closeDevice(id);
             }
@@ -158,7 +157,7 @@
         assertNotNull("Surface from ImageReader shouldn't be null", surface);
         mWriter = ImageWriter.newInstance(surface, MAX_NUM_IMAGES);
         SimpleImageWriterListener writerImageListener = new SimpleImageWriterListener(mWriter);
-        mWriter.setImageListener(writerImageListener, mHandler);
+        mWriter.setOnImageReleasedListener(writerImageListener, mHandler);
 
         // Start capture: capture 2 images.
         List<Surface> outputSurfaces = new ArrayList<Surface>();
@@ -182,17 +181,17 @@
         Image outputImage = null;
         assertTrue("ImageWriter max images should be " + MAX_NUM_IMAGES,
                 mWriter.getMaxImages() == MAX_NUM_IMAGES);
-        if (format == CAMERA_OPAQUE_FORMAT) {
-            assertTrue("First ImageReader should be opaque",
-                    mReader.isOpaque());
-            assertTrue("Second ImageReader should be opaque",
-                    mReaderForWriter.isOpaque());
-            assertTrue("Format of first ImageReader should be opaque",
-                    mReader.getImageFormat() == CAMERA_OPAQUE_FORMAT);
-            assertTrue(" Format of second ImageReader should be opaque",
-                    mReaderForWriter.getImageFormat() == CAMERA_OPAQUE_FORMAT);
-            assertTrue(" Format of ImageWriter should be opaque",
-                    mWriter.getFormat() == CAMERA_OPAQUE_FORMAT);
+        if (format == CAMERA_PRIVATE_FORMAT) {
+            assertTrue("First ImageReader format should be PRIVATE",
+                    mReader.getImageFormat() == CAMERA_PRIVATE_FORMAT);
+            assertTrue("Second ImageReader should be PRIVATE",
+                    mReaderForWriter.getImageFormat() == CAMERA_PRIVATE_FORMAT);
+            assertTrue("Format of first ImageReader should be PRIVATE",
+                    mReader.getImageFormat() == CAMERA_PRIVATE_FORMAT);
+            assertTrue(" Format of second ImageReader should be PRIVATE",
+                    mReaderForWriter.getImageFormat() == CAMERA_PRIVATE_FORMAT);
+            assertTrue(" Format of ImageWriter should be PRIVATE",
+                    mWriter.getFormat() == CAMERA_PRIVATE_FORMAT);
 
             // Validate 2 images
             validateOpaqueImages(maxSize, listenerForCamera, listenerForWriter, captureListener,
@@ -307,7 +306,7 @@
     private void validateOpaqueImage(Image image, String msg, Size imageSize,
             CaptureResult result) {
         assertNotNull("Opaque image Capture result should not be null", result != null);
-        mCollector.expectImageProperties(msg + "Opaque ", image, CAMERA_OPAQUE_FORMAT,
+        mCollector.expectImageProperties(msg + "Opaque ", image, CAMERA_PRIVATE_FORMAT,
                 imageSize, result.get(CaptureResult.SENSOR_TIMESTAMP));
         mCollector.expectTrue(msg + "Opaque image number planes should be zero",
                 image.getPlanes().length == 0);
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/PerformanceTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/PerformanceTest.java
index 56eee0e..3f54a39 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/PerformanceTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/PerformanceTest.java
@@ -626,7 +626,7 @@
         InputConfiguration inputConfig = new InputConfiguration(maxInputSize.getWidth(),
                 maxInputSize.getHeight(), inputFormat);
         mSessionListener = new BlockingSessionCallback();
-        mSession = CameraTestUtils.configureReprocessibleCameraSession(
+        mSession = CameraTestUtils.configureReprocessableCameraSession(
                 mCamera, inputConfig, outSurfaces, mSessionListener, mHandler);
 
         // 3. Create ImageWriter for input
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java
index 005d948..ed43b06 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java
@@ -24,6 +24,7 @@
 import android.util.Size;
 import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
 import android.media.CamcorderProfile;
+import android.media.MediaCodec;
 import android.media.MediaCodecInfo;
 import android.media.MediaCodecInfo.CodecCapabilities;
 import android.media.MediaCodecInfo.CodecProfileLevel;
@@ -46,6 +47,7 @@
 
 import java.io.File;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -82,6 +84,7 @@
     private static final int MAX_NUM_FRAME_DROP_INTERVAL_ALLOWED = 4;
     private List<Size> mSupportedVideoSizes;
     private Surface mRecordingSurface;
+    private Surface mPersistentSurface;
     private MediaRecorder mMediaRecorder;
     private String mOutMediaFileName;
     private int mVideoFrameRate;
@@ -98,19 +101,7 @@
         super.tearDown();
     }
 
-    /**
-     * <p>
-     * Test basic camera recording.
-     * </p>
-     * <p>
-     * This test covers the typical basic use case of camera recording.
-     * MediaRecorder is used to record the audio and video, CamcorderProfile is
-     * used to configure the MediaRecorder. It goes through the pre-defined
-     * CamcorderProfile list, test each profile configuration and validate the
-     * recorded video. Preview is set to the video size.
-     * </p>
-     */
-    public void testBasicRecording() throws Exception {
+    private void doBasicRecording() throws Exception {
         for (int i = 0; i < mCameraIds.length; i++) {
             try {
                 Log.i(TAG, "Testing basic recording for camera " + mCameraIds[i]);
@@ -130,6 +121,43 @@
 
     /**
      * <p>
+     * Test basic camera recording.
+     * </p>
+     * <p>
+     * This test covers the typical basic use case of camera recording.
+     * MediaRecorder is used to record the audio and video, CamcorderProfile is
+     * used to configure the MediaRecorder. It goes through the pre-defined
+     * CamcorderProfile list, test each profile configuration and validate the
+     * recorded video. Preview is set to the video size.
+     * </p>
+     */
+    public void testBasicRecording() throws Exception {
+        doBasicRecording();
+    }
+
+    /**
+     * <p>
+     * Test basic camera recording from a persistent input surface.
+     * </p>
+     * <p>
+     * This test is similar to testBasicRecording except that MediaRecorder records
+     * from a persistent input surface that's used across multiple recording sessions.
+     * </p>
+     */
+    public void testRecordingFromPersistentSurface() throws Exception {
+        mPersistentSurface = MediaCodec.createPersistentInputSurface();
+        assertNotNull("Failed to create persistent input surface!", mPersistentSurface);
+
+        try {
+            doBasicRecording();
+        } finally {
+            mPersistentSurface.release();
+            mPersistentSurface = null;
+        }
+    }
+
+    /**
+     * <p>
      * Test camera recording for all supported sizes by using MediaRecorder.
      * </p>
      * <p>
@@ -368,7 +396,7 @@
         Range<Integer> maxRange = availableFpsRanges[0];
         boolean foundRange = false;
         for (Range<Integer> range : availableFpsRanges) {
-            if (range.getLower() == range.getUpper() && range.getLower() >= maxRange.getLower()) {
+            if (range.getLower().equals(range.getUpper()) && range.getLower() >= maxRange.getLower()) {
                 foundRange = true;
                 maxRange = range;
             }
@@ -439,8 +467,10 @@
      */
     private void basicRecordingTestByCamera(int[] camcorderProfileList) throws Exception {
         Size maxPreviewSize = mOrderedPreviewSizes.get(0);
+        List<Range<Integer> > fpsRanges = Arrays.asList(
+                mStaticInfo.getAeAvailableTargetFpsRangesChecked());
+        int cameraId = Integer.valueOf(mCamera.getId());
         for (int profileId : camcorderProfileList) {
-            int cameraId = Integer.valueOf(mCamera.getId());
             if (!CamcorderProfile.hasProfile(cameraId, profileId) ||
                     allowedUnsupported(cameraId, profileId)) {
                 continue;
@@ -448,6 +478,7 @@
 
             CamcorderProfile profile = CamcorderProfile.get(cameraId, profileId);
             Size videoSz = new Size(profile.videoFrameWidth, profile.videoFrameHeight);
+            Range<Integer> fpsRange = new Range(profile.videoFrameRate, profile.videoFrameRate);
             if (mStaticInfo.isHardwareLevelLegacy() &&
                     (videoSz.getWidth() > maxPreviewSize.getWidth() ||
                      videoSz.getHeight() > maxPreviewSize.getHeight())) {
@@ -457,6 +488,9 @@
             assertTrue("Video size " + videoSz.toString() + " for profile ID " + profileId +
                             " must be one of the camera device supported video size!",
                             mSupportedVideoSizes.contains(videoSz));
+            assertTrue("Frame rate range " + fpsRange + " (for profile ID " + profileId +
+                    ") must be one of the camera device available FPS range!",
+                    fpsRanges.contains(fpsRange));
 
             if (VERBOSE) {
                 Log.v(TAG, "Testing camera recording with video size " + videoSz.toString());
@@ -631,6 +665,13 @@
 
             Size maxPreviewSize = mOrderedPreviewSizes.get(0);
 
+            if (mStaticInfo.isHardwareLevelLegacy() &&
+                    (videoSz.getWidth() > maxPreviewSize.getWidth() ||
+                     videoSz.getHeight() > maxPreviewSize.getHeight())) {
+                // Skip. Legacy mode can only do recording up to max preview size
+                continue;
+            }
+
             // For LEGACY, find closest supported smaller or equal JPEG size to the current video
             // size; if no size is smaller than the video, pick the smallest JPEG size.  The assert
             // for video size above guarantees that for LIMITED or FULL, we select videoSz here.
@@ -812,8 +853,14 @@
         mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
         mMediaRecorder.setProfile(profile);
         mMediaRecorder.setOutputFile(mOutMediaFileName);
+        if (mPersistentSurface != null) {
+            mMediaRecorder.setInputSurface(mPersistentSurface);
+            mRecordingSurface = mPersistentSurface;
+        }
         mMediaRecorder.prepare();
-        mRecordingSurface = mMediaRecorder.getSurface();
+        if (mPersistentSurface == null) {
+            mRecordingSurface = mMediaRecorder.getSurface();
+        }
         assertNotNull("Recording surface must be non-null!", mRecordingSurface);
         mVideoFrameRate = profile.videoFrameRate;
         mVideoSize = new Size(profile.videoFrameWidth, profile.videoFrameHeight);
@@ -837,8 +884,14 @@
         mMediaRecorder.setVideoSize(sz.getWidth(), sz.getHeight());
         mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
         mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
+        if (mPersistentSurface != null) {
+            mMediaRecorder.setInputSurface(mPersistentSurface);
+            mRecordingSurface = mPersistentSurface;
+        }
         mMediaRecorder.prepare();
-        mRecordingSurface = mMediaRecorder.getSurface();
+        if (mPersistentSurface == null) {
+            mRecordingSurface = mMediaRecorder.getSurface();
+        }
         assertNotNull("Recording surface must be non-null!", mRecordingSurface);
         mVideoFrameRate = videoFrameRate;
         mVideoSize = sz;
@@ -901,7 +954,7 @@
         } else {
             // TODO: need implement MediaCodec path.
         }
-        if (mRecordingSurface != null) {
+        if (mPersistentSurface == null && mRecordingSurface != null) {
             mRecordingSurface.release();
             mRecordingSurface = null;
         }
@@ -1018,7 +1071,7 @@
                         ));
                     }
 
-                    durationMs = (int) (nextTS - currentTS) / 1000000;
+                    durationMs = (nextTS - currentTS) / 1000000.0;
                     mCollector.expectTrue(
                             String.format(
                                     "Video %dx%d Frame drop detected after video snapshot: " +
@@ -1032,7 +1085,7 @@
                     if (durationMs >= expectedDurationMs * 2) {
                         Log.w(TAG, String.format(
                                 "Video %dx%d Frame drop detected after video snapshot: " +
-                                        "duration %dms (expected %dms)",
+                                        "duration %fms (expected %fms)",
                                 mVideoSize.getWidth(), mVideoSize.getHeight(),
                                 durationMs, expectedDurationMs
                         ));
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/ReprocessCaptureTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/ReprocessCaptureTest.java
index 7d6ab55..94cbbf7 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/ReprocessCaptureTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/ReprocessCaptureTest.java
@@ -247,7 +247,7 @@
 
                 setupImageReaders(inputSize, inputFormat, reprocessOutputSize,
                         reprocessOutputFormat, /*maxImages*/1);
-                setupReprocessibleSession(/*previewSurface*/null, /*numImageWriterImages*/1);
+                setupReprocessableSession(/*previewSurface*/null, /*numImageWriterImages*/1);
 
                 TotalCaptureResult result = submitCaptureRequest(mFirstImageReader.getSurface(),
                         /*inputResult*/null);
@@ -258,7 +258,7 @@
 
                 // recreate the session
                 closeReprossibleSession();
-                setupReprocessibleSession(/*previewSurface*/null, /*numImageWriterImages*/1);
+                setupReprocessableSession(/*previewSurface*/null, /*numImageWriterImages*/1);
                 try {
                     TotalCaptureResult reprocessResult;
                     // issue and wait on reprocess capture request
@@ -429,7 +429,7 @@
 
             setupImageReaders(inputSize, inputFormat, reprocessOutputSize, reprocessOutputFormat,
                 totalNumBurst);
-            setupReprocessibleSession(mPreviewSurface, /*numImageWriterImages*/numBurst);
+            setupReprocessableSession(mPreviewSurface, /*numImageWriterImages*/numBurst);
 
             if (enablePreview) {
                 startPreview(mPreviewSurface);
@@ -498,7 +498,7 @@
 
             setupImageReaders(inputSize, inputFormat, reprocessOutputSize, reprocessOutputFormat,
                 numBurst);
-            setupReprocessibleSession(mPreviewSurface, numBurst);
+            setupReprocessableSession(mPreviewSurface, numBurst);
 
             if (enablePreview) {
                 startPreview(mPreviewSurface);
@@ -556,7 +556,7 @@
 
             setupImageReaders(inputSize, inputFormat, reprocessOutputSize, reprocessOutputFormat,
                     /*maxImages*/1);
-            setupReprocessibleSession(mPreviewSurface, /*numImageWriterImages*/1);
+            setupReprocessableSession(mPreviewSurface, /*numImageWriterImages*/1);
 
             if (enablePreview) {
                 startPreview(mPreviewSurface);
@@ -635,11 +635,11 @@
     }
 
     /**
-     * Set up a reprocessible session and create an ImageWriter with the sessoin's input surface.
+     * Set up a reprocessable session and create an ImageWriter with the sessoin's input surface.
      */
-    private void setupReprocessibleSession(Surface previewSurface, int numImageWriterImages)
+    private void setupReprocessableSession(Surface previewSurface, int numImageWriterImages)
             throws Exception {
-        // create a reprocessible capture session
+        // create a reprocessable capture session
         List<Surface> outSurfaces = new ArrayList<Surface>();
         outSurfaces.add(mFirstImageReader.getSurface());
         if (!mShareOneImageReader) {
@@ -651,6 +651,10 @@
 
         InputConfiguration inputConfig = new InputConfiguration(mFirstImageReader.getWidth(),
                 mFirstImageReader.getHeight(), mFirstImageReader.getImageFormat());
+        String inputConfigString = inputConfig.toString();
+        if (VERBOSE) {
+            Log.v(TAG, "InputConfiguration: " + inputConfigString);
+        }
         assertTrue(String.format("inputConfig is wrong: %dx%d format %d. Expect %dx%d format %d",
                 inputConfig.getWidth(), inputConfig.getHeight(), inputConfig.getFormat(),
                 mFirstImageReader.getWidth(), mFirstImageReader.getHeight(),
@@ -660,7 +664,7 @@
                 inputConfig.getFormat() == mFirstImageReader.getImageFormat());
 
         mSessionListener = new BlockingSessionCallback();
-        mSession = configureReprocessibleCameraSession(mCamera, inputConfig, outSurfaces,
+        mSession = configureReprocessableCameraSession(mCamera, inputConfig, outSurfaces,
                 mSessionListener, mHandler);
 
         // create an ImageWriter
@@ -669,11 +673,11 @@
                 numImageWriterImages);
 
         mImageWriterListener = new SimpleImageWriterListener(mImageWriter);
-        mImageWriter.setImageListener(mImageWriterListener, mHandler);
+        mImageWriter.setOnImageReleasedListener(mImageWriterListener, mHandler);
     }
 
     /**
-     * Close the reprocessible session and ImageWriter.
+     * Close the reprocessable session and ImageWriter.
      */
     private void closeReprossibleSession() {
         mInputSurface = null;
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/RobustnessTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/RobustnessTest.java
index 61860a7..3d5ceaa 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/RobustnessTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/RobustnessTest.java
@@ -49,6 +49,7 @@
  */
 public class RobustnessTest extends Camera2AndroidTestCase {
     private static final String TAG = "RobustnessTest";
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
 
     private static final int CONFIGURE_TIMEOUT = 5000; //ms
     private static final int CAPTURE_TIMEOUT = 1000; //ms
@@ -223,6 +224,11 @@
             MaxOutputSizes maxSizes = new MaxOutputSizes(cc, id);
 
             final StaticMetadata staticInfo = new StaticMetadata(cc);
+            String streamConfigurationMapString =
+                    cc.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).toString();
+            if (VERBOSE) {
+                Log.v(TAG, "StreamConfigurationMap: " + streamConfigurationMapString);
+            }
 
             openDevice(id);
 
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/StaticMetadataTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/StaticMetadataTest.java
index 3076d09..0dba61e 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/StaticMetadataTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/StaticMetadataTest.java
@@ -321,6 +321,7 @@
 
                 // Legacy mode always doesn't support these requirements
                 Boolean contrastCurveModeSupported = false;
+                Boolean gammaAndPresetModeSupported = false;
                 Boolean offColorAberrationModeSupported = false;
                 if (mStaticInfo.isHardwareLevelLimitedOrBetter()) {
                     int[] tonemapModes = mStaticInfo.getAvailableToneMapModesChecked();
@@ -329,6 +330,10 @@
                             Arrays.asList(CameraTestUtils.toObject(tonemapModes));
                     contrastCurveModeSupported =
                             modeList.contains(CameraMetadata.TONEMAP_MODE_CONTRAST_CURVE);
+                    gammaAndPresetModeSupported =
+                            modeList.contains(CameraMetadata.TONEMAP_MODE_GAMMA_VALUE) &&
+                            modeList.contains(CameraMetadata.TONEMAP_MODE_PRESET_CURVE);
+
                     int[] colorAberrationModes =
                             mStaticInfo.getAvailableColorAberrationModesChecked();
                     modeList = (colorAberrationModes.length == 0) ?
@@ -337,8 +342,12 @@
                     offColorAberrationModeSupported =
                             modeList.contains(CameraMetadata.COLOR_CORRECTION_ABERRATION_MODE_OFF);
                 }
+                Boolean tonemapModeQualified =
+                        contrastCurveModeSupported || gammaAndPresetModeSupported;
                 additionalRequirements.add(new Pair<String, Boolean>(
-                        "Tonemap mode must include CONTRAST_CURVE", contrastCurveModeSupported));
+                        "Tonemap mode must include {CONTRAST_CURVE} and/or " +
+                        "{GAMMA_VALUE, PRESET_CURVE}",
+                        tonemapModeQualified));
                 additionalRequirements.add(new Pair<String, Boolean>(
                         "Color aberration mode must include OFF", offColorAberrationModeSupported));
                 additionalRequirements.add(new Pair<String, Boolean>(
@@ -380,7 +389,7 @@
                 break;
 
             case REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING:
-            case REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING:
+            case REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING:
                 // Tested in ExtendedCameraCharacteristicsTest
                 return;
             default:
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java
index 01da4c8..7d377d6 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java
@@ -18,6 +18,8 @@
 
 import static android.hardware.camera2.cts.CameraTestUtils.*;
 
+import android.graphics.ImageFormat;
+import android.view.Surface;
 import android.hardware.camera2.CameraCaptureSession;
 import android.hardware.camera2.CameraCaptureSession.CaptureCallback;
 import android.hardware.camera2.CameraDevice;
@@ -29,6 +31,7 @@
 import android.hardware.camera2.cts.CameraTestUtils.SimpleCaptureCallback;
 import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
 import android.util.Log;
+import android.util.Pair;
 import android.util.Range;
 
 import org.mockito.ArgumentCaptor;
@@ -36,6 +39,7 @@
 
 import static org.mockito.Mockito.*;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
@@ -118,6 +122,192 @@
     }
 
     /**
+     * Test to verify the {@link CameraCaptureSession#prepare} method works correctly, and has the
+     * expected effects on performance.
+     *
+     * - Ensure that prepare() results in onSurfacePrepared() being invoked
+     * - Ensure that prepare() does not cause preview glitches while operating
+     * - Ensure that starting to use a newly-prepared output does not cause additional
+     *   preview glitches to occur
+     */
+    public void testPreparePerformance() throws Throwable {
+        for (int i = 0; i < mCameraIds.length; i++) {
+            try {
+                openDevice(mCameraIds[i]);
+
+                preparePerformanceTestByCamera(mCameraIds[i]);
+            }
+            finally {
+                closeDevice();
+            }
+        }
+    }
+
+    private void preparePerformanceTestByCamera(String cameraId) throws Exception {
+        final int MAX_IMAGES_TO_PREPARE = 10;
+        final int UNKNOWN_LATENCY_RESULT_WAIT = 5;
+        final int MAX_RESULTS_TO_WAIT = 10;
+        final int FRAMES_FOR_AVERAGING = 100;
+        final int PREPARE_TIMEOUT_MS = 10000; // 10 s
+        final float PREPARE_FRAME_RATE_BOUNDS = 0.05f; // fraction allowed difference
+        final float PREPARE_PEAK_RATE_BOUNDS = 0.5f; // fraction allowed difference
+
+        Size maxYuvSize = getSupportedPreviewSizes(cameraId, mCameraManager, null).get(0);
+        Size maxPreviewSize = mOrderedPreviewSizes.get(0);
+
+        // Don't need image data, just drop it right away to minimize overhead
+        ImageDropperListener imageListener = new ImageDropperListener();
+
+        SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
+
+        CaptureRequest.Builder previewRequest =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+
+        // Configure outputs and session
+
+        updatePreviewSurface(maxPreviewSize);
+
+        createImageReader(maxYuvSize, ImageFormat.YUV_420_888, MAX_IMAGES_TO_PREPARE, imageListener);
+
+        List<Surface> outputSurfaces = new ArrayList<Surface>();
+        outputSurfaces.add(mPreviewSurface);
+        outputSurfaces.add(mReaderSurface);
+
+        CameraCaptureSession.StateCallback mockSessionListener =
+                mock(CameraCaptureSession.StateCallback.class);
+
+        mSession = configureCameraSession(mCamera, outputSurfaces, mockSessionListener, mHandler);
+
+        previewRequest.addTarget(mPreviewSurface);
+        Range<Integer> maxFpsTarget = mStaticInfo.getAeMaxTargetFpsRange();
+        previewRequest.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, maxFpsTarget);
+
+        mSession.setRepeatingRequest(previewRequest.build(), resultListener, mHandler);
+
+        // Converge AE
+        waitForAeStable(resultListener, UNKNOWN_LATENCY_RESULT_WAIT);
+
+        if (mStaticInfo.isAeLockSupported()) {
+            // Lock AE if possible to improve stability
+            previewRequest.set(CaptureRequest.CONTROL_AE_LOCK, true);
+            mSession.setRepeatingRequest(previewRequest.build(), resultListener, mHandler);
+            waitForResultValue(resultListener, CaptureResult.CONTROL_AE_STATE,
+                    CaptureResult.CONTROL_AE_STATE_LOCKED, MAX_RESULTS_TO_WAIT);
+        }
+
+        // Measure frame rate for a bit
+        Pair<Long, Long> frameDurationStats =
+                measureMeanFrameInterval(resultListener, FRAMES_FOR_AVERAGING, /*prevTimestamp*/ 0);
+
+        Log.i(TAG, String.format("Frame interval avg during normal preview: %f ms, peak %f ms",
+                        frameDurationStats.first / 1e6, frameDurationStats.second / 1e6));
+
+        // Drain results, do prepare
+        resultListener.drain();
+
+        mSession.prepare(mReaderSurface);
+
+        verify(mockSessionListener,
+                timeout(PREPARE_TIMEOUT_MS).times(1)).
+                onSurfacePrepared(eq(mSession), eq(mReaderSurface));
+
+        // Calculate frame rate during prepare
+
+        int resultsReceived = (int) resultListener.getTotalNumFrames();
+        if (resultsReceived > 2) {
+            // Only verify frame rate if there are a couple of results
+            Pair<Long, Long> whilePreparingFrameDurationStats =
+                    measureMeanFrameInterval(resultListener, resultsReceived, /*prevTimestamp*/ 0);
+
+            Log.i(TAG, String.format("Frame interval during prepare avg: %f ms, peak %f ms",
+                            whilePreparingFrameDurationStats.first / 1e6,
+                            whilePreparingFrameDurationStats.second / 1e6));
+
+            if (mStaticInfo.isHardwareLevelLimitedOrBetter()) {
+                mCollector.expectTrue(
+                    String.format("Camera %s: Preview peak frame interval affected by prepare " +
+                            "call: preview avg frame duration: %f ms, peak during prepare: %f ms",
+                            cameraId,
+                            frameDurationStats.first / 1e6,
+                            whilePreparingFrameDurationStats.second / 1e6),
+                    (whilePreparingFrameDurationStats.second <=
+                            frameDurationStats.first * (1 + PREPARE_PEAK_RATE_BOUNDS)));
+                mCollector.expectTrue(
+                    String.format("Camera %s: Preview average frame interval affected by prepare " +
+                            "call: preview avg frame duration: %f ms, during prepare: %f ms",
+                            cameraId,
+                            frameDurationStats.first / 1e6,
+                            whilePreparingFrameDurationStats.first / 1e6),
+                    (whilePreparingFrameDurationStats.first <=
+                            frameDurationStats.first * (1 + PREPARE_FRAME_RATE_BOUNDS)));
+            }
+        }
+
+        resultListener.drain();
+
+        // Get at least one more preview result without prepared target
+        CaptureResult result = resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+        long prevTimestamp = result.get(CaptureResult.SENSOR_TIMESTAMP);
+
+        // Now use the prepared stream and ensure there are no hiccups from using it
+        previewRequest.addTarget(mReaderSurface);
+
+        mSession.setRepeatingRequest(previewRequest.build(), resultListener, mHandler);
+
+        Pair<Long, Long> preparedFrameDurationStats =
+                measureMeanFrameInterval(resultListener, MAX_IMAGES_TO_PREPARE*2, prevTimestamp);
+
+        Log.i(TAG, String.format("Frame interval with prepared stream added avg: %f ms, peak %f ms",
+                        preparedFrameDurationStats.first / 1e6,
+                        preparedFrameDurationStats.second / 1e6));
+
+        if (mStaticInfo.isHardwareLevelLimitedOrBetter()) {
+            mCollector.expectTrue(
+                String.format("Camera %s: Preview peak frame interval affected by use of new " +
+                        " stream: preview avg frame duration: %f ms, peak with new stream: %f ms",
+                        cameraId,
+                        frameDurationStats.first / 1e6, preparedFrameDurationStats.second / 1e6),
+                (preparedFrameDurationStats.second <=
+                        frameDurationStats.first * (1 + PREPARE_PEAK_RATE_BOUNDS)));
+            mCollector.expectTrue(
+                String.format("Camera %s: Preview average frame interval affected by use of new " +
+                        "stream: preview avg frame duration: %f ms, with new stream: %f ms",
+                        cameraId,
+                        frameDurationStats.first / 1e6, preparedFrameDurationStats.first / 1e6),
+                (preparedFrameDurationStats.first <=
+                        frameDurationStats.first * (1 + PREPARE_FRAME_RATE_BOUNDS)));
+        }
+    }
+
+    /**
+     * Measure the inter-frame interval based on SENSOR_TIMESTAMP for frameCount frames from the
+     * provided capture listener.  If prevTimestamp is positive, it is used for the first interval
+     * calculation; otherwise, the first result is used to establish the starting time.
+     *
+     * Returns the mean interval in the first pair entry, and the largest interval in the second
+     * pair entry
+     */
+    Pair<Long, Long> measureMeanFrameInterval(SimpleCaptureCallback resultListener, int frameCount,
+            long prevTimestamp) throws Exception {
+        long summedIntervals = 0;
+        long maxInterval = 0;
+        int measurementCount = frameCount - ((prevTimestamp > 0) ? 0 : 1);
+
+        for (int i = 0; i < frameCount; i++) {
+            CaptureResult result = resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+            long timestamp = result.get(CaptureResult.SENSOR_TIMESTAMP);
+            if (prevTimestamp > 0) {
+                long interval = timestamp - prevTimestamp;
+                if (interval > maxInterval) maxInterval = interval;
+                summedIntervals += interval;
+            }
+            prevTimestamp = timestamp;
+        }
+        return new Pair<Long, Long>(summedIntervals / measurementCount, maxInterval);
+    }
+
+
+    /**
      * Test preview fps range for all supported ranges. The exposure time are frame duration are
      * validated.
      */
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/StaticMetadata.java b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
index 538864d..b63541b 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
@@ -678,13 +678,8 @@
         List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes));
         checkTrueForKey(key, " Camera devices must always support FAST mode",
                 modeList.contains(CameraMetadata.TONEMAP_MODE_FAST));
-        if (isCapabilitySupported(
-                CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING)) {
-            checkTrueForKey(key, "MANUAL_POST_PROCESSING supported camera devices must support"
-                    + "CONTRAST_CURVE mode",
-                    modeList.contains(CameraMetadata.TONEMAP_MODE_CONTRAST_CURVE) &&
-                    modeList.contains(CameraMetadata.TONEMAP_MODE_FAST));
-        }
+        // Qualification check for MANUAL_POSTPROCESSING capability is in
+        // StaticMetadataTest#testCapabilities
 
         if (isHardwareLevelLimitedOrBetter()) {
             // FAST and HIGH_QUALITY mode must be both present or both not present
@@ -698,7 +693,7 @@
         }
         checkElementDistinct(key, modeList);
         checkArrayValuesInRange(key, modes, CameraMetadata.TONEMAP_MODE_CONTRAST_CURVE,
-                CameraMetadata.TONEMAP_MODE_HIGH_QUALITY);
+                CameraMetadata.TONEMAP_MODE_PRESET_CURVE);
 
         return modes;
     }
@@ -711,16 +706,23 @@
     public int getMaxTonemapCurvePointChecked() {
         Key<Integer> key = CameraCharacteristics.TONEMAP_MAX_CURVE_POINTS;
         Integer count = getValueFromKeyNonNull(key);
+        List<Integer> modeList =
+                Arrays.asList(CameraTestUtils.toObject(getAvailableToneMapModesChecked()));
+        boolean tonemapCurveOutputSupported =
+                modeList.contains(CameraMetadata.TONEMAP_MODE_CONTRAST_CURVE) ||
+                modeList.contains(CameraMetadata.TONEMAP_MODE_GAMMA_VALUE) ||
+                modeList.contains(CameraMetadata.TONEMAP_MODE_PRESET_CURVE);
 
         if (count == null) {
+            if (tonemapCurveOutputSupported) {
+                Assert.fail("Tonemap curve output is supported but MAX_CURVE_POINTS is null");
+            }
             return 0;
         }
 
-        List<Integer> modeList =
-                Arrays.asList(CameraTestUtils.toObject(getAvailableToneMapModesChecked()));
-        if (modeList.contains(CameraMetadata.TONEMAP_MODE_CONTRAST_CURVE)) {
-            checkTrueForKey(key, "Full-capability camera device must support maxCurvePoints "
-                    + ">= " + TONEMAP_MAX_CURVE_POINTS_AT_LEAST,
+        if (tonemapCurveOutputSupported) {
+            checkTrueForKey(key, "Tonemap curve output supported camera device must support "
+                    + "maxCurvePoints >= " + TONEMAP_MAX_CURVE_POINTS_AT_LEAST,
                     count >= TONEMAP_MAX_CURVE_POINTS_AT_LEAST);
         }
 
@@ -1282,9 +1284,17 @@
         int fpsRangeLength = fpsRanges.length;
         int minFps, maxFps;
         long maxFrameDuration = getMaxFrameDurationChecked();
+        boolean foundConstant30Range = false;
+        boolean foundPreviewStreamingRange = false;
         for (int i = 0; i < fpsRangeLength; i += 1) {
             minFps = fpsRanges[i].getLower();
             maxFps = fpsRanges[i].getUpper();
+            if (minFps == 30 && maxFps == 30) {
+                foundConstant30Range = true;
+            }
+            if (minFps <= 15 && maxFps >= 30) {
+                foundPreviewStreamingRange = true;
+            }
             checkTrueForKey(key, " min fps must be no larger than max fps!",
                     minFps > 0 && maxFps >= minFps);
             long maxDuration = (long) (1e9 / minFps);
@@ -1292,11 +1302,38 @@
                     " the frame duration %d for min fps %d must smaller than maxFrameDuration %d",
                     maxDuration, minFps, maxFrameDuration), maxDuration <= maxFrameDuration);
         }
-
+        checkTrueForKey(key, String.format(" (30, 30) must be included"), foundConstant30Range);
+        checkTrueForKey(key, String.format(
+                " (min, max) where min <= 15 and max >= 30 must be included"),
+                foundPreviewStreamingRange);
         return fpsRanges;
     }
 
     /**
+     * Get the highest supported target FPS range.
+     * Prioritizes maximizing the min FPS, then the max FPS without lowering min FPS.
+     */
+    public Range<Integer> getAeMaxTargetFpsRange() {
+        Range<Integer>[] fpsRanges = getAeAvailableTargetFpsRangesChecked();
+
+        Range<Integer> targetRange = fpsRanges[0];
+        // Assume unsorted list of target FPS ranges, so use two passes, first maximize min FPS
+        for (Range<Integer> candidateRange : fpsRanges) {
+            if (candidateRange.getLower() > targetRange.getLower()) {
+                targetRange = candidateRange;
+            }
+        }
+        // Then maximize max FPS while not lowering min FPS
+        for (Range<Integer> candidateRange : fpsRanges) {
+            if (candidateRange.getLower() >= targetRange.getLower() &&
+                    candidateRange.getUpper() > targetRange.getUpper()) {
+                targetRange = candidateRange;
+            }
+        }
+        return targetRange;
+    }
+
+    /**
      * Get max frame duration.
      *
      * @return 0 if maxFrameDuration is null
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestCase.java b/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestCase.java
index e7f1e7a..78370b3 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestCase.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestCase.java
@@ -294,13 +294,8 @@
             ImageReader.OnImageAvailableListener listener) throws Exception {
 
         ImageReader reader = null;
-        if (format == ImageFormat.PRIVATE) {
-            // Create opaque ImageReader
-            reader = ImageReader.newOpaqueInstance(size.getWidth(), size.getHeight(), maxNumImages);
-        } else {
-            reader = ImageReader.newInstance(size.getWidth(), size.getHeight(),
-                    format, maxNumImages);
-        }
+        reader = ImageReader.newInstance(size.getWidth(), size.getHeight(),
+                format, maxNumImages);
 
         reader.setOnImageAvailableListener(listener, mHandler);
         if (VERBOSE) Log.v(TAG, "Created ImageReader size " + size.toString());
@@ -462,15 +457,6 @@
             // Expected.
         }
 
-        // Image#isOpaque test
-        try {
-            closedImage.isOpaque();
-            fail("Image should throw IllegalStateException when calling isOpaque"
-                    + " after the image is closed");
-        } catch (IllegalStateException e) {
-            // Expected.
-        }
-
         // Image#getCropRect test
         try {
             closedImage.getCropRect();
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java b/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
index c6c0250..3ca696b 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
@@ -707,7 +707,7 @@
                                    CheckLevel.ASSERT, /*collector*/ null);
         int cap = CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING;
         if (format == ImageFormat.PRIVATE) {
-            cap = CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING;
+            cap = CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING;
         }
         return info.isCapabilitySupported(cap);
     }
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyPairGeneratorSpecTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyPairGeneratorSpecTest.java
index a923844..33c8955 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyPairGeneratorSpecTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyPairGeneratorSpecTest.java
@@ -25,11 +25,6 @@
 import javax.security.auth.x500.X500Principal;
 
 public class KeyPairGeneratorSpecTest extends AndroidTestCase {
-    private static final X500Principal DEFAULT_CERT_SUBJECT = new X500Principal("CN=fake");
-    private static final BigInteger DEFAULT_CERT_SERIAL_NUMBER = new BigInteger("1");
-    private static final Date DEFAULT_CERT_NOT_BEFORE = new Date(0L); // Jan 1 1980
-    private static final Date DEFAULT_CERT_NOT_AFTER = new Date(2461449600000L); // Jan 1 2048
-
     private static final String TEST_ALIAS_1 = "test1";
 
     private static final X500Principal TEST_DN_1 = new X500Principal("CN=test1");
@@ -110,44 +105,56 @@
         }
     }
 
-    public void testBuilder_MissingSubjectDN_Success() throws Exception {
-        KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(getContext())
-                .setAlias(TEST_ALIAS_1)
-                .setSerialNumber(SERIAL_1)
-                .setStartDate(NOW)
-                .setEndDate(NOW_PLUS_10_YEARS)
-                .build();
-        assertEquals(DEFAULT_CERT_SUBJECT, spec.getSubjectDN());
+    public void testBuilder_MissingSubjectDN_Failure() throws Exception {
+        try {
+            new KeyPairGeneratorSpec.Builder(getContext())
+                    .setAlias(TEST_ALIAS_1)
+                    .setSerialNumber(SERIAL_1)
+                    .setStartDate(NOW)
+                    .setEndDate(NOW_PLUS_10_YEARS)
+                    .build();
+            fail("Should throw IllegalArgumentException when subject is missing");
+        } catch (IllegalArgumentException expected) {
+        }
     }
 
-    public void testBuilder_MissingSerialNumber_Success() throws Exception {
-        KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(getContext())
-                .setAlias(TEST_ALIAS_1)
-                .setSubject(TEST_DN_1)
-                .setStartDate(NOW)
-                .setEndDate(NOW_PLUS_10_YEARS)
-                .build();
-        assertEquals(DEFAULT_CERT_SERIAL_NUMBER, spec.getSerialNumber());
+    public void testBuilder_MissingSerialNumber_Failure() throws Exception {
+        try {
+            new KeyPairGeneratorSpec.Builder(getContext())
+                    .setAlias(TEST_ALIAS_1)
+                    .setSubject(TEST_DN_1)
+                    .setStartDate(NOW)
+                    .setEndDate(NOW_PLUS_10_YEARS)
+                    .build();
+            fail("Should throw IllegalArgumentException when serialNumber is missing");
+        } catch (IllegalArgumentException expected) {
+        }
     }
 
-    public void testBuilder_MissingStartDate_Success() throws Exception {
-        KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(getContext())
-                .setAlias(TEST_ALIAS_1)
-                .setSubject(TEST_DN_1)
-                .setSerialNumber(SERIAL_1)
-                .setEndDate(NOW_PLUS_10_YEARS)
-                .build();
-        assertEquals(DEFAULT_CERT_NOT_BEFORE, spec.getStartDate());
+    public void testBuilder_MissingStartDate_Failure() throws Exception {
+        try {
+            new KeyPairGeneratorSpec.Builder(getContext())
+                    .setAlias(TEST_ALIAS_1)
+                    .setSubject(TEST_DN_1)
+                    .setSerialNumber(SERIAL_1)
+                    .setEndDate(NOW_PLUS_10_YEARS)
+                    .build();
+            fail("Should throw IllegalArgumentException when startDate is missing");
+        } catch (IllegalArgumentException expected) {
+        }
     }
 
-    public void testBuilder_MissingEndDate_Success() throws Exception {
-        KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(getContext())
-                .setAlias(TEST_ALIAS_1)
-                .setSubject(TEST_DN_1)
-                .setSerialNumber(SERIAL_1)
-                .setStartDate(NOW)
-                .build();
-        assertEquals(DEFAULT_CERT_NOT_AFTER, spec.getEndDate());
+    public void testBuilder_MissingEndDate_Failure() throws Exception {
+        try {
+            new KeyPairGeneratorSpec.Builder(getContext())
+                    .setAlias(TEST_ALIAS_1)
+                    .setSubject(TEST_DN_1)
+                    .setSerialNumber(SERIAL_1)
+                    .setStartDate(NOW)
+                    .build();
+            fail("Should throw IllegalArgumentException when endDate is missing");
+        } catch (IllegalArgumentException expected) {
+        }
     }
 
     public void testBuilder_EndBeforeStart_Failure() throws Exception {
diff --git a/tests/tests/location/src/android/location/cts/CriteriaTest.java b/tests/tests/location/src/android/location/cts/CriteriaTest.java
index d812965f..422f561 100644
--- a/tests/tests/location/src/android/location/cts/CriteriaTest.java
+++ b/tests/tests/location/src/android/location/cts/CriteriaTest.java
@@ -113,6 +113,19 @@
         assertTrue(criteria.isAltitudeRequired());
     }
 
+    public void testAccessBearingAccuracy() {
+        Criteria criteria = new Criteria();
+
+        criteria.setBearingAccuracy(Criteria.ACCURACY_LOW);
+        assertEquals(Criteria.ACCURACY_LOW, criteria.getBearingAccuracy());
+
+        criteria.setBearingAccuracy(Criteria.ACCURACY_HIGH);
+        assertEquals(Criteria.ACCURACY_HIGH, criteria.getBearingAccuracy());
+
+        criteria.setBearingAccuracy(Criteria.NO_REQUIREMENT);
+        assertEquals(Criteria.NO_REQUIREMENT, criteria.getBearingAccuracy());
+      }
+
     public void testAccessBearingRequired() {
         Criteria criteria = new Criteria();
 
@@ -133,6 +146,35 @@
         assertTrue(criteria.isCostAllowed());
     }
 
+    public void testAccessHorizontalAccuracy() {
+        Criteria criteria = new Criteria();
+
+        criteria.setHorizontalAccuracy(Criteria.ACCURACY_LOW);
+        assertEquals(Criteria.ACCURACY_LOW, criteria.getHorizontalAccuracy());
+
+        criteria.setHorizontalAccuracy(Criteria.ACCURACY_MEDIUM);
+        assertEquals(Criteria.ACCURACY_MEDIUM, criteria.getHorizontalAccuracy());
+
+        criteria.setHorizontalAccuracy(Criteria.ACCURACY_HIGH);
+        assertEquals(Criteria.ACCURACY_HIGH, criteria.getHorizontalAccuracy());
+
+        criteria.setHorizontalAccuracy(Criteria.NO_REQUIREMENT);
+        assertEquals(Criteria.NO_REQUIREMENT, criteria.getHorizontalAccuracy());
+    }
+
+    public void testAccessSpeedAccuracy() {
+        Criteria criteria = new Criteria();
+
+        criteria.setSpeedAccuracy(Criteria.ACCURACY_LOW);
+        assertEquals(Criteria.ACCURACY_LOW, criteria.getSpeedAccuracy());
+
+        criteria.setSpeedAccuracy(Criteria.ACCURACY_HIGH);
+        assertEquals(Criteria.ACCURACY_HIGH, criteria.getSpeedAccuracy());
+
+        criteria.setSpeedAccuracy(Criteria.NO_REQUIREMENT);
+        assertEquals(Criteria.NO_REQUIREMENT, criteria.getSpeedAccuracy());
+    }
+
     public void testAccessSpeedRequired() {
         Criteria criteria = new Criteria();
 
@@ -143,6 +185,19 @@
         assertTrue(criteria.isSpeedRequired());
     }
 
+    public void testAccessVerticalAccuracy() {
+        Criteria criteria = new Criteria();
+
+        criteria.setVerticalAccuracy(Criteria.ACCURACY_LOW);
+        assertEquals(Criteria.ACCURACY_LOW, criteria.getVerticalAccuracy());
+
+       criteria.setVerticalAccuracy(Criteria.ACCURACY_HIGH);
+        assertEquals(Criteria.ACCURACY_HIGH, criteria.getVerticalAccuracy());
+
+        criteria.setVerticalAccuracy(Criteria.NO_REQUIREMENT);
+        assertEquals(Criteria.NO_REQUIREMENT, criteria.getVerticalAccuracy());
+    }
+
     public void testWriteToParcel() {
         Criteria criteria = new Criteria();
         criteria.setAltitudeRequired(true);
diff --git a/tests/tests/location/src/android/location/cts/LocationManagerTest.java b/tests/tests/location/src/android/location/cts/LocationManagerTest.java
index a985aee..3168335 100644
--- a/tests/tests/location/src/android/location/cts/LocationManagerTest.java
+++ b/tests/tests/location/src/android/location/cts/LocationManagerTest.java
@@ -27,6 +27,7 @@
 import android.location.Criteria;
 import android.location.GpsStatus;
 import android.location.GpsStatus.Listener;
+import android.location.GpsStatus.NmeaListener;
 import android.location.Location;
 import android.location.LocationListener;
 import android.location.LocationManager;
@@ -537,6 +538,358 @@
         }
     }
 
+    public void testSingleUpdateWithLocationListenerAndLooper() throws InterruptedException {
+        double latitude1 = 60;
+        double longitude1 = 20;
+        double latitude2 = 40;
+        double longitude2 = 30;
+        double latitude3 = 10;
+        double longitude3 = 50;
+        final MockLocationListener listener = new MockLocationListener();
+
+        // update location and notify listener
+        HandlerThread handlerThread = new HandlerThread("testLocationUpdates4");
+        handlerThread.start();
+        mManager.requestSingleUpdate(TEST_MOCK_PROVIDER_NAME, listener, handlerThread.getLooper());
+
+        updateLocation(latitude1, longitude1);
+        assertTrue(listener.hasCalledOnLocationChanged(TEST_TIME_OUT));
+        Location location = listener.getLocation();
+        assertEquals(TEST_MOCK_PROVIDER_NAME, location.getProvider());
+        assertEquals(latitude1, location.getLatitude());
+        assertEquals(longitude1, location.getLongitude());
+        assertEquals(true, location.isFromMockProvider());
+
+        // Any further location change doesn't trigger an update.
+        updateLocation(latitude2, longitude2);
+        assertEquals(latitude1, location.getLatitude());
+        assertEquals(longitude1, location.getLongitude());
+
+        // update location without notifying listener
+        mManager.removeUpdates(listener);
+        listener.reset();
+        updateLocation(latitude3, longitude3);
+        assertFalse(listener.hasCalledOnLocationChanged(TEST_TIME_OUT));
+
+        try {
+            mManager.requestSingleUpdate(LocationManager.GPS_PROVIDER, (LocationListener) null,
+                    Looper.myLooper());
+            fail("Should throw IllegalArgumentException if param listener is null!");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            mManager.requestSingleUpdate((String) null, listener, Looper.myLooper());
+            fail("Should throw IllegalArgumentException if param provider is null!");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            mManager.removeUpdates( (LocationListener) null );
+            fail("Should throw IllegalArgumentException if listener is null!");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    public void testLocationUpdatesWithCriteriaAndPendingIntent() throws InterruptedException {
+        double latitude1 = 10;
+        double longitude1 = 20;
+        double latitude2 = 30;
+        double longitude2 = 40;
+
+        registerIntentReceiver();
+        mockFusedLocation();
+
+        // Update location and receive broadcast.
+        Criteria criteria = createLocationCriteria();
+        mManager.requestLocationUpdates(0, 0 , criteria, mPendingIntent);
+        updateFusedLocation(latitude1, longitude1);
+        waitForReceiveBroadcast();
+
+        assertNotNull(mIntentReceiver.getLastReceivedIntent());
+        Location location = (Location) mIntentReceiver.getLastReceivedIntent().getExtras()
+                .get(LocationManager.KEY_LOCATION_CHANGED);
+        assertEquals(latitude1, location.getLatitude());
+        assertEquals(longitude1, location.getLongitude());
+        assertTrue(location.hasAccuracy());
+        assertEquals(1.0f, location.getAccuracy());
+        assertEquals(true, location.isFromMockProvider());
+
+        // Update location without receiving broadcast.
+        mManager.removeUpdates(mPendingIntent);
+        mIntentReceiver.clearReceivedIntents();
+        updateFusedLocation(latitude2, longitude2);
+        waitForReceiveBroadcast();
+        assertNull(mIntentReceiver.getLastReceivedIntent());
+
+        // Missing arguments throw exceptions.
+        try {
+            mManager.requestLocationUpdates(0, 0, criteria, (PendingIntent) null);
+            fail("Should throw IllegalArgumentException if param intent is null!");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            mManager.requestLocationUpdates(0, 0, null, mPendingIntent);
+            fail("Should throw IllegalArgumentException if param criteria is null!");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            mManager.removeUpdates( (PendingIntent) null );
+            fail("Should throw IllegalArgumentException if param PendingIntent is null!");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        unmockFusedLocation();
+    }
+
+    public void testSingleUpdateWithCriteriaAndPendingIntent() throws InterruptedException {
+        double latitude1 = 10;
+        double longitude1 = 20;
+        double latitude2 = 30;
+        double longitude2 = 40;
+        double latitude3 = 50;
+        double longitude3 = 60;
+
+        registerIntentReceiver();
+        mockFusedLocation();
+
+        // Update location and receive broadcast.
+        Criteria criteria = createLocationCriteria();
+        mManager.requestSingleUpdate(criteria, mPendingIntent);
+        updateFusedLocation(latitude1, longitude1);
+        waitForReceiveBroadcast();
+
+        assertNotNull(mIntentReceiver.getLastReceivedIntent());
+        Location location = (Location) mIntentReceiver.getLastReceivedIntent().getExtras()
+                .get(LocationManager.KEY_LOCATION_CHANGED);
+        assertEquals(latitude1, location.getLatitude());
+        assertEquals(longitude1, location.getLongitude());
+        assertTrue(location.hasAccuracy());
+        assertEquals(1.0f, location.getAccuracy());
+        assertEquals(true, location.isFromMockProvider());
+
+        // Any further location change doesn't trigger an update.
+        updateFusedLocation(latitude2, longitude2);
+        assertEquals(latitude1, location.getLatitude());
+        assertEquals(longitude1, location.getLongitude());
+
+        // Update location without receiving broadcast.
+        mManager.removeUpdates(mPendingIntent);
+        mIntentReceiver.clearReceivedIntents();
+        updateFusedLocation(latitude3, longitude3);
+        waitForReceiveBroadcast();
+        assertNull(mIntentReceiver.getLastReceivedIntent());
+
+        // Missing arguments throw exceptions.
+        try {
+            mManager.requestSingleUpdate(criteria, (PendingIntent) null);
+            fail("Should throw IllegalArgumentException if param intent is null!");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            mManager.requestSingleUpdate((Criteria) null, mPendingIntent);
+            fail("Should throw IllegalArgumentException if param criteria is null!");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            mManager.removeUpdates( (PendingIntent) null );
+            fail("Should throw IllegalArgumentException if param PendingIntent is null!");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        unmockFusedLocation();
+    }
+
+    public void testLocationUpdatesWithCriteriaAndLocationListenerAndLooper()
+            throws InterruptedException {
+        double latitude1 = 40;
+        double longitude1 = 10;
+        double latitude2 = 20;
+        double longitude2 = 30;
+       final MockLocationListener listener = new MockLocationListener();
+        mockFusedLocation();
+
+        // update location and notify listener
+        HandlerThread handlerThread = new HandlerThread("testLocationUpdates1");
+        handlerThread.start();
+        Criteria criteria = createLocationCriteria();
+        mManager.requestLocationUpdates(0, 0, criteria, listener, handlerThread.getLooper());
+
+        updateFusedLocation(latitude1, longitude1);
+        assertTrue(listener.hasCalledOnLocationChanged(TEST_TIME_OUT));
+        Location location = listener.getLocation();
+        assertEquals(latitude1, location.getLatitude());
+        assertEquals(longitude1, location.getLongitude());
+        assertTrue(location.hasAccuracy());
+        assertEquals(1.0f, location.getAccuracy());
+        assertEquals(true, location.isFromMockProvider());
+
+        // update location without notifying listener
+        mManager.removeUpdates(listener);
+        listener.reset();
+        updateFusedLocation(latitude2, longitude2);
+        assertFalse(listener.hasCalledOnLocationChanged(TEST_TIME_OUT));
+
+        // Missing arguments throw exceptions.
+        try {
+            mManager.requestLocationUpdates(0, 0, criteria, (LocationListener) null,
+                    Looper.myLooper());
+            fail("Should throw IllegalArgumentException if param listener is null!");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            mManager.requestLocationUpdates(0, 0, null, listener, Looper.myLooper());
+            fail("Should throw IllegalArgumentException if param criteria is null!");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            mManager.removeUpdates( (LocationListener) null );
+            fail("Should throw IllegalArgumentException if listener is null!");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        unmockFusedLocation();
+    }
+
+    public void testSingleUpdateWithCriteriaAndLocationListenerAndLooper()
+            throws InterruptedException {
+        double latitude1 = 40;
+        double longitude1 = 10;
+        double latitude2 = 20;
+        double longitude2 = 30;
+        double latitude3 = 60;
+        double longitude3 = 50;
+        final MockLocationListener listener = new MockLocationListener();
+        mockFusedLocation();
+
+        // update location and notify listener
+        HandlerThread handlerThread = new HandlerThread("testLocationUpdates2");
+        handlerThread.start();
+        Criteria criteria = createLocationCriteria();
+        mManager.requestSingleUpdate(criteria, listener, handlerThread.getLooper());
+
+        updateFusedLocation(latitude1, longitude1);
+        assertTrue(listener.hasCalledOnLocationChanged(TEST_TIME_OUT));
+        Location location = listener.getLocation();
+        assertEquals(FUSED_PROVIDER_NAME, location.getProvider());
+        assertEquals(latitude1, location.getLatitude());
+        assertEquals(longitude1, location.getLongitude());
+        assertTrue(location.hasAccuracy());
+        assertEquals(1.0f, location.getAccuracy());
+        assertEquals(true, location.isFromMockProvider());
+
+        // Any further location change doesn't trigger an update.
+        updateFusedLocation(latitude2, longitude2);
+        assertEquals(latitude1, location.getLatitude());
+        assertEquals(longitude1, location.getLongitude());
+
+        // update location without notifying listener
+        mManager.removeUpdates(listener);
+        listener.reset();
+        updateFusedLocation(latitude3, longitude3);
+        assertFalse(listener.hasCalledOnLocationChanged(TEST_TIME_OUT));
+
+        // Missing arguments throw exceptions.
+        try {
+            mManager.requestLocationUpdates(0, 0, criteria, (LocationListener) null,
+                    Looper.myLooper());
+            fail("Should throw IllegalArgumentException if param listener is null!");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            mManager.requestLocationUpdates(0, 0, null, listener, Looper.myLooper());
+            fail("Should throw IllegalArgumentException if param criteria is null!");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            mManager.removeUpdates( (LocationListener) null );
+            fail("Should throw IllegalArgumentException if listener is null!");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        unmockFusedLocation();
+    }
+
+    public void testSingleUpdateWithPendingIntent() throws InterruptedException {
+        double latitude1 = 20;
+        double longitude1 = 40;
+        double latitude2 = 30;
+        double longitude2 = 50;
+        double latitude3 = 10;
+        double longitude3 = 60;
+
+        // update location and receive broadcast.
+        registerIntentReceiver();
+        mManager.requestLocationUpdates(TEST_MOCK_PROVIDER_NAME, 0, 0, mPendingIntent);
+        updateLocation(latitude1, longitude1);
+        waitForReceiveBroadcast();
+
+        assertNotNull(mIntentReceiver.getLastReceivedIntent());
+        Location location = mManager.getLastKnownLocation(TEST_MOCK_PROVIDER_NAME);
+        assertEquals(TEST_MOCK_PROVIDER_NAME, location.getProvider());
+        assertEquals(latitude1, location.getLatitude());
+        assertEquals(longitude1, location.getLongitude());
+        assertEquals(true, location.isFromMockProvider());
+
+        // Any further location change doesn't trigger an update.
+        updateLocation(latitude2, longitude2);
+        assertEquals(latitude1, location.getLatitude());
+        assertEquals(longitude1, location.getLongitude());
+
+        // update location without receiving broadcast.
+        mManager.removeUpdates(mPendingIntent);
+        mIntentReceiver.clearReceivedIntents();
+        updateLocation(latitude3, longitude3);
+        waitForReceiveBroadcast();
+        assertEquals(latitude1, location.getLatitude());
+        assertEquals(longitude1, location.getLongitude());
+
+        try {
+            mManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
+                    (PendingIntent) null);
+            fail("Should throw IllegalArgumentException if param intent is null!");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            mManager.requestLocationUpdates(null, 0, 0, mPendingIntent);
+            fail("Should throw IllegalArgumentException if param provider is null!");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            mManager.removeUpdates( (PendingIntent) null );
+            fail("Should throw IllegalArgumentException if intent is null!");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
     public void testAddProximityAlert() {
         Intent i = new Intent();
         i.setAction("android.location.cts.TEST_GET_GPS_STATUS_ACTION");
@@ -546,6 +899,17 @@
         mManager.removeProximityAlert(pi);
     }
 
+
+    @UiThreadTest
+    public void testNmeaListener() {
+        MockNmeaListener listener = new MockNmeaListener();
+        mManager.addNmeaListener(listener);
+        mManager.removeNmeaListener(listener);
+
+        mManager.addNmeaListener(null);
+        mManager.removeNmeaListener(null);
+    }
+
     public void testIsProviderEnabled() {
         // this test assumes enabled TEST_MOCK_PROVIDER_NAME was created in setUp.
         assertNotNull(mManager.getProvider(TEST_MOCK_PROVIDER_NAME));
@@ -840,6 +1204,21 @@
         updateLocation(TEST_MOCK_PROVIDER_NAME, latitude, longitude);
     }
 
+    private void updateFusedLocation(final double latitude, final double longitude) {
+      updateLocation(FUSED_PROVIDER_NAME, latitude, longitude);
+ }
+
+    private Criteria createLocationCriteria() {
+        Criteria criteria = new Criteria();
+        criteria.setAccuracy(Criteria.ACCURACY_FINE);
+        criteria.setPowerRequirement(Criteria.POWER_MEDIUM);
+        criteria.setAltitudeRequired(false);
+        criteria.setBearingRequired(false);
+        criteria.setCostAllowed(false);
+        criteria.setSpeedRequired(false);
+        return criteria;
+     }
+
     private void mockFusedLocation() {
         addTestProvider(FUSED_PROVIDER_NAME);
     }
@@ -1003,6 +1382,23 @@
         }
     }
 
+    private static class MockNmeaListener implements NmeaListener {
+        private boolean mIsNmeaReceived;
+
+        @Override
+        public void onNmeaReceived(long timestamp, String nmea) {
+            mIsNmeaReceived = true;
+        }
+
+        public boolean isNmeaRecevied() {
+            return mIsNmeaReceived;
+        }
+
+        public void reset() {
+            mIsNmeaReceived = false;
+        }
+    }
+
     private static class MockGpsStatusListener implements Listener {
         private boolean mHasCallOnGpsStatusChanged;
 
diff --git a/tests/tests/media/AndroidManifest.xml b/tests/tests/media/AndroidManifest.xml
index e913f05..cdc0e60 100644
--- a/tests/tests/media/AndroidManifest.xml
+++ b/tests/tests/media/AndroidManifest.xml
@@ -52,6 +52,21 @@
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
             </intent-filter>
         </activity>
+        <activity android:name="android.media.cts.ResourceManagerStubActivity"
+            android:label="ResourceManagerStubActivity">
+            <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.media.cts.ResourceManagerTestActivity1"
+            android:label="ResourceManagerTestActivity1"
+            android:process=":mediaCodecTestProcess1">
+        </activity>
+        <activity android:name="android.media.cts.ResourceManagerTestActivity2"
+            android:label="ResourceManagerTestActivity2"
+            android:process=":mediaCodecTestProcess2">
+        </activity>
         <activity android:name="android.media.cts.RingtonePickerActivity"
             android:label="RingtonePickerActivity">
             <intent-filter>
@@ -65,6 +80,11 @@
                 <action android:name="android.intent.action.MAIN"/>
             </intent-filter>
         </service>
+        <service android:name="android.media.cts.StubMediaBrowserService">
+            <intent-filter>
+                <action android:name="android.media.browse.MediaBrowserService" />
+            </intent-filter>
+        </service>
     </application>
 
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java b/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
index dbb609d..1fb3ea7 100644
--- a/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
+++ b/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
@@ -862,6 +862,15 @@
             mCodec.configure(format, mSurface.getSurface(), null /* crypto */, 0 /* flags */);
             Log.i(TAG, "start");
             mCodec.start();
+
+            // inject some minimal setOutputSurface test
+            // TODO: change this test to also change the surface midstream
+            try {
+                mCodec.setOutputSurface(null);
+                fail("should not be able to set surface to NULL");
+            } catch (IllegalArgumentException e) {}
+            mCodec.setOutputSurface(mSurface.getSurface());
+
             mInputBuffers = mCodec.getInputBuffers();
             mOutputBuffers = mCodec.getOutputBuffers();
             Log.i(TAG, "configured " + mInputBuffers.length + " input[" +
diff --git a/tests/tests/media/src/android/media/cts/AudioHelper.java b/tests/tests/media/src/android/media/cts/AudioHelper.java
index 6f3d4d0..efee024 100644
--- a/tests/tests/media/src/android/media/cts/AudioHelper.java
+++ b/tests/tests/media/src/android/media/cts/AudioHelper.java
@@ -17,6 +17,7 @@
 package android.media.cts;
 
 import java.nio.ByteBuffer;
+
 import org.junit.Assert;
 
 import android.media.AudioAttributes;
@@ -29,6 +30,43 @@
 // Used for statistics and loopers in listener tests.
 // See AudioRecordTest.java and AudioTrack_ListenerTest.java.
 public class AudioHelper {
+
+    // create sine waves or chirps for data arrays
+    public static byte[] createSoundDataInByteArray(int bufferSamples, final int sampleRate,
+            final double frequency, double sweep) {
+        final double rad = 2 * Math.PI * frequency / sampleRate;
+        byte[] vai = new byte[bufferSamples];
+        sweep = Math.PI * sweep / ((double)sampleRate * vai.length);
+        for (int j = 0; j < vai.length; j++) {
+            int unsigned =  (int)(Math.sin(j * (rad + j * sweep)) * Byte.MAX_VALUE)
+                    + Byte.MAX_VALUE & 0xFF;
+            vai[j] = (byte) unsigned;
+        }
+        return vai;
+    }
+
+    public static short[] createSoundDataInShortArray(int bufferSamples, final int sampleRate,
+            final double frequency, double sweep) {
+        final double rad = 2 * Math.PI * frequency / sampleRate;
+        short[] vai = new short[bufferSamples];
+        sweep = Math.PI * sweep / ((double)sampleRate * vai.length);
+        for (int j = 0; j < vai.length; j++) {
+            vai[j] = (short)(Math.sin(j * (rad + j * sweep)) * Short.MAX_VALUE);
+        }
+        return vai;
+    }
+
+    public static float[] createSoundDataInFloatArray(int bufferSamples, final int sampleRate,
+            final double frequency, double sweep) {
+        final double rad = 2 * Math.PI * frequency / sampleRate;
+        float[] vaf = new float[bufferSamples];
+        sweep = Math.PI * sweep / ((double)sampleRate * vaf.length);
+        for (int j = 0; j < vaf.length; j++) {
+            vaf[j] = (float)(Math.sin(j * (rad + j * sweep)));
+        }
+        return vaf;
+    }
+
     public static int frameSizeFromFormat(AudioFormat format) {
         return format.getChannelCount()
                 * format.getBytesPerSample(format.getEncoding());
diff --git a/tests/tests/media/src/android/media/cts/AudioRecordTest.java b/tests/tests/media/src/android/media/cts/AudioRecordTest.java
index d390c14..56d2b68 100644
--- a/tests/tests/media/src/android/media/cts/AudioRecordTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioRecordTest.java
@@ -25,7 +25,9 @@
 import android.media.AudioManager;
 import android.media.AudioRecord;
 import android.media.AudioRecord.OnRecordPositionUpdateListener;
+import android.media.AudioTrack;
 import android.media.MediaRecorder;
+import android.media.MediaSyncEvent;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -414,16 +416,153 @@
         assertEquals(TEST_NAME + ": state", expectedState, observedState);
     }
 
+    public void testSynchronizedRecord() throws Exception {
+        if (!hasMicrophone()) {
+            return;
+        }
+        final String TEST_NAME = "testSynchronizedRecord";
+        AudioTrack track = null;
+        AudioRecord record = null;
+
+        try {
+            // 1. create a static AudioTrack.
+            final int PLAYBACK_TIME_IN_MS = 2000; /* ms duration. */
+            final int PLAYBACK_SAMPLE_RATE = 8000; /* in hz */
+            AudioFormat format = new AudioFormat.Builder()
+                    .setChannelMask(AudioFormat.CHANNEL_OUT_MONO)
+                    .setEncoding(AudioFormat.ENCODING_PCM_8BIT)
+                    .setSampleRate(PLAYBACK_SAMPLE_RATE)
+                    .build();
+            final int frameCount = AudioHelper.frameCountFromMsec(PLAYBACK_TIME_IN_MS, format);
+            final int frameSize = AudioHelper.frameSizeFromFormat(format);
+            track = new AudioTrack.Builder()
+                    .setAudioFormat(format)
+                    .setBufferSizeInBytes(frameCount * frameSize)
+                    .setTransferMode(AudioTrack.MODE_STATIC)
+                    .build();
+            // create float array and write it
+            final int sampleCount = frameCount * format.getChannelCount();
+            byte[] vab = AudioHelper.createSoundDataInByteArray(
+                    sampleCount, PLAYBACK_SAMPLE_RATE, 600 /* frequency */, 0 /* sweep */);
+            assertEquals(TEST_NAME, vab.length,
+                    track.write(vab, 0 /* offsetInBytes */, vab.length,
+                            AudioTrack.WRITE_NON_BLOCKING));
+            final int trackSessionId = track.getAudioSessionId();
+
+            // 2. create an AudioRecord to sync off of AudioTrack completion.
+            final int RECORD_TIME_IN_MS = 2000;
+            final int RECORD_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
+            final int RECORD_CHANNEL_MASK = AudioFormat.CHANNEL_IN_STEREO;
+            final int RECORD_SAMPLE_RATE = 44100;
+            record = new AudioRecord.Builder()
+                    .setAudioFormat(new AudioFormat.Builder()
+                            .setSampleRate(RECORD_SAMPLE_RATE)
+                            .setChannelMask(RECORD_CHANNEL_MASK)
+                            .setEncoding(RECORD_ENCODING)
+                            .build())
+                    .build();
+            // AudioRecord creation may have silently failed, check state now
+            assertEquals(TEST_NAME, AudioRecord.STATE_INITIALIZED, record.getState());
+
+            // 3. create a MediaSyncEvent
+            // This MediaSyncEvent checks playback completion of an AudioTrack
+            // (or MediaPlayer, or ToneGenerator) based on its audio session id.
+            //
+            // Note: when synchronizing record from a MediaSyncEvent
+            // (1) You need to be "close" to the end of the associated AudioTrack.
+            // If the track does not complete in 30 seconds, recording begins regardless.
+            // (actual delay limit may vary).
+            //
+            // (2) Track completion may be triggered by pause() as well as stop()
+            // or when a static AudioTrack completes playback.
+            //
+            final int eventType = MediaSyncEvent.SYNC_EVENT_PRESENTATION_COMPLETE;
+            MediaSyncEvent event = MediaSyncEvent.createEvent(eventType)
+                    .setAudioSessionId(trackSessionId);
+            assertEquals(TEST_NAME, trackSessionId, event.getAudioSessionId());
+            assertEquals(TEST_NAME, eventType, event.getType());
+
+            // 4. now set the AudioTrack playing and start the recording synchronized
+            track.play();
+            // start recording.  Recording state turns to RECORDSTATE_RECORDING immediately
+            // but the data read() only occurs after the AudioTrack completes.
+            record.startRecording(event);
+            assertEquals(TEST_NAME,
+                    AudioRecord.RECORDSTATE_RECORDING, record.getRecordingState());
+            long startTime = System.currentTimeMillis();
+
+            // 5. get record data.
+            // For our tests, we could set test duration by timed sleep or by # frames received.
+            // Since we don't know *exactly* when AudioRecord actually begins recording,
+            // we end the test by # frames read.
+            final int numChannels =
+                    AudioFormat.channelCountFromInChannelMask(RECORD_CHANNEL_MASK);
+            final int bytesPerSample = AudioFormat.getBytesPerSample(RECORD_ENCODING);
+            final int bytesPerFrame = numChannels * bytesPerSample;
+            // careful about integer overflow in the formula below:
+            final int targetSamples =
+                    (int)((long)RECORD_TIME_IN_MS * RECORD_SAMPLE_RATE * numChannels / 1000);
+            final int BUFFER_FRAMES = 512;
+            final int BUFFER_SAMPLES = BUFFER_FRAMES * numChannels;
+
+            // After starting, there is no guarantee when the first frame of data is read.
+            long firstSampleTime = 0;
+            int samplesRead = 0;
+
+            // For 16 bit data, use shorts
+            short[] shortData = new short[BUFFER_SAMPLES];
+            while (samplesRead < targetSamples) {
+                // the first time through, we read a single frame.
+                // this sets the recording anchor position.
+                int amount = samplesRead == 0 ? numChannels :
+                    Math.min(BUFFER_SAMPLES, targetSamples - samplesRead);
+                int ret = record.read(shortData, 0, amount);
+                assertEquals(TEST_NAME, amount, ret);
+                if (samplesRead == 0 && ret > 0) {
+                    firstSampleTime = System.currentTimeMillis();
+                }
+                samplesRead += ret;
+                // sanity check: elapsed time cannot be more than a second
+                // than what we expect.
+                assertTrue(System.currentTimeMillis() - startTime <=
+                        PLAYBACK_TIME_IN_MS + RECORD_TIME_IN_MS + 1000);
+            }
+
+            // 6. We've read all the frames, now check the timing.
+            final long endTime = System.currentTimeMillis();
+            //Log.d(TEST_NAME, "first sample time " + (firstSampleTime - startTime)
+            //        + " test time " + (endTime - firstSampleTime));
+            //
+            // Verify recording starts within 400 ms of AudioTrack completion (typical 180ms)
+            // Verify recording completes within 50 ms of expected test time (typical 20ms)
+            assertEquals(TEST_NAME, PLAYBACK_TIME_IN_MS, firstSampleTime - startTime, 400);
+            assertEquals(TEST_NAME, RECORD_TIME_IN_MS, endTime - firstSampleTime, 50);
+
+            record.stop();
+            assertEquals(TEST_NAME, AudioRecord.RECORDSTATE_STOPPED, record.getRecordingState());
+        } finally {
+            if (record != null) {
+                record.release();
+                record = null;
+            }
+            if (track != null) {
+                track.release();
+                track = null;
+            }
+        }
+    }
+
     private AudioRecord createAudioRecord(
             int audioSource, int sampleRateInHz,
             int channelConfig, int audioFormat, int bufferSizeInBytes,
             boolean auditRecording, boolean isChannelIndex) {
+        final AudioRecord record;
         if (auditRecording) {
-            return new AudioHelper.AudioRecordAudit(
+            record = new AudioHelper.AudioRecordAudit(
                     audioSource, sampleRateInHz, channelConfig,
                     audioFormat, bufferSizeInBytes, isChannelIndex);
         } else if (isChannelIndex) {
-            return new AudioRecord.Builder()
+            record = new AudioRecord.Builder()
                     .setAudioFormat(new AudioFormat.Builder()
                             .setChannelIndexMask(channelConfig)
                             .setEncoding(audioFormat)
@@ -432,9 +571,23 @@
                     .setBufferSizeInBytes(bufferSizeInBytes)
                     .build();
         } else {
-            return new AudioRecord(audioSource, sampleRateInHz, channelConfig,
+            record = new AudioRecord(audioSource, sampleRateInHz, channelConfig,
                     audioFormat, bufferSizeInBytes);
         }
+
+        // did we get the AudioRecord we expected?
+        final AudioFormat format = record.getFormat();
+        assertEquals(isChannelIndex ? channelConfig : AudioFormat.CHANNEL_INVALID,
+                format.getChannelIndexMask());
+        assertEquals(isChannelIndex ? AudioFormat.CHANNEL_INVALID : channelConfig,
+                format.getChannelMask());
+        assertEquals(audioFormat, format.getEncoding());
+        assertEquals(sampleRateInHz, format.getSampleRate());
+        final int frameSize =
+                format.getChannelCount() * AudioFormat.getBytesPerSample(audioFormat);
+        // our native frame count cannot be smaller than our minimum buffer size request.
+        assertTrue(record.getBufferSizeInFrames() * frameSize >= bufferSizeInBytes);
+        return record;
     }
 
     private void doTest(String reportName, boolean localRecord, boolean customHandler,
diff --git a/tests/tests/media/src/android/media/cts/AudioTrackTest.java b/tests/tests/media/src/android/media/cts/AudioTrackTest.java
index 403d714..dfb83eb 100644
--- a/tests/tests/media/src/android/media/cts/AudioTrackTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioTrackTest.java
@@ -1391,6 +1391,7 @@
             frameCount /= 2;
         }
         assertTrue(TEST_NAME, track.getNativeFrameCount() >= frameCount);
+        assertEquals(TEST_NAME, track.getNativeFrameCount(), track.getBufferSizeInFrames());
     }
 
     public void testReloadStaticData() throws Exception {
@@ -1404,7 +1405,8 @@
 
         // -------- initialization --------------
         int bufferSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
-        byte data[] = createSoundDataInByteArray(bufferSize, TEST_SR, 1024);
+        byte data[] = AudioHelper.createSoundDataInByteArray(
+                bufferSize, TEST_SR, 1024 /* frequency */, 0 /* sweep */);
         AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT,
                 bufferSize, TEST_MODE);
         // -------- test --------------
@@ -1422,56 +1424,6 @@
         track.release();
     }
 
-    public static byte[] createSoundDataInByteArray(int bufferSamples, final int sampleRate,
-            final double frequency, double sweep) {
-        final double rad = 2 * Math.PI * frequency / sampleRate;
-        byte[] vai = new byte[bufferSamples];
-        sweep = Math.PI * sweep / ((double)sampleRate * vai.length);
-        for (int j = 0; j < vai.length; j++) {
-            int unsigned =  (int)(Math.sin(j * (rad + j * sweep)) * Byte.MAX_VALUE)
-                    + Byte.MAX_VALUE & 0xFF;
-            vai[j] = (byte) unsigned;
-        }
-        return vai;
-    }
-
-    public static short[] createSoundDataInShortArray(int bufferSamples, final int sampleRate,
-            final double frequency, double sweep) {
-        final double rad = 2 * Math.PI * frequency / sampleRate;
-        short[] vai = new short[bufferSamples];
-        sweep = Math.PI * sweep / ((double)sampleRate * vai.length);
-        for (int j = 0; j < vai.length; j++) {
-            vai[j] = (short)(Math.sin(j * (rad + j * sweep)) * Short.MAX_VALUE);
-        }
-        return vai;
-    }
-
-    public static float[] createSoundDataInFloatArray(int bufferSamples, final int sampleRate,
-            final double frequency, double sweep) {
-        final double rad = 2 * Math.PI * frequency / sampleRate;
-        float[] vaf = new float[bufferSamples];
-        sweep = Math.PI * sweep / ((double)sampleRate * vaf.length);
-        for (int j = 0; j < vaf.length; j++) {
-            vaf[j] = (float)(Math.sin(j * (rad + j * sweep)));
-        }
-        return vaf;
-    }
-
-    public static byte[] createSoundDataInByteArray(int bufferSamples, final int sampleRate,
-            final double frequency) {
-        return createSoundDataInByteArray(bufferSamples, sampleRate, frequency, 0 /*sweep*/);
-    }
-
-    public static short[] createSoundDataInShortArray(int bufferSamples, final int sampleRate,
-            final double frequency) {
-        return createSoundDataInShortArray(bufferSamples, sampleRate, frequency, 0 /*sweep*/);
-    }
-
-    public static float[] createSoundDataInFloatArray(int bufferSamples, final int sampleRate,
-            final double frequency) {
-        return createSoundDataInFloatArray(bufferSamples, sampleRate, frequency, 0 /*sweep*/);
-    }
-
     public void testPlayStaticData() throws Exception {
         if (!hasAudioOutput()) {
             Log.w(TAG,"AUDIO_OUTPUT feature not found. This system might not have a valid "
@@ -1529,7 +1481,7 @@
                     // only need to write once to the static track
                     switch (TEST_FORMAT) {
                     case AudioFormat.ENCODING_PCM_8BIT: {
-                        byte data[] = createSoundDataInByteArray(
+                        byte data[] = AudioHelper.createSoundDataInByteArray(
                                 bufferSamples, TEST_SR,
                                 testFrequency, TEST_SWEEP);
                         assertEquals(TEST_NAME,
@@ -1537,7 +1489,7 @@
                                 track.write(data, 0 /*offsetInBytes*/, data.length));
                         } break;
                     case AudioFormat.ENCODING_PCM_16BIT: {
-                        short data[] = createSoundDataInShortArray(
+                        short data[] = AudioHelper.createSoundDataInShortArray(
                                 bufferSamples, TEST_SR,
                                 testFrequency, TEST_SWEEP);
                         assertEquals(TEST_NAME,
@@ -1545,7 +1497,7 @@
                                 track.write(data, 0 /*offsetInBytes*/, data.length));
                         } break;
                     case AudioFormat.ENCODING_PCM_FLOAT: {
-                        float data[] = createSoundDataInFloatArray(
+                        float data[] = AudioHelper.createSoundDataInFloatArray(
                                 bufferSamples, TEST_SR,
                                 testFrequency, TEST_SWEEP);
                         assertEquals(TEST_NAME,
@@ -1611,6 +1563,7 @@
         };
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        final float TEST_SWEEP = 0; // sine wave only
 
         for (int TEST_FORMAT : TEST_FORMAT_ARRAY) {
             double frequency = 400; // frequency changes for each test
@@ -1649,12 +1602,12 @@
                     // We choose a value here which simulates double buffer writes.
                     final int buffers = 2; // double buffering mode
                     final int samplesPerWrite =
-                            (track.getNativeFrameCount() / buffers) * channelCount;
+                            (track.getBufferSizeInFrames() / buffers) * channelCount;
                     switch (TEST_FORMAT) {
                     case AudioFormat.ENCODING_PCM_8BIT: {
-                        byte data[] = createSoundDataInByteArray(
+                        byte data[] = AudioHelper.createSoundDataInByteArray(
                                 sourceSamples, TEST_SR,
-                                testFrequency);
+                                testFrequency, TEST_SWEEP);
                         while (written < data.length) {
                             int samples = Math.min(data.length - written, samplesPerWrite);
                             int ret = track.write(data, written, samples);
@@ -1663,9 +1616,9 @@
                         }
                         } break;
                     case AudioFormat.ENCODING_PCM_16BIT: {
-                        short data[] = createSoundDataInShortArray(
+                        short data[] = AudioHelper.createSoundDataInShortArray(
                                 sourceSamples, TEST_SR,
-                                testFrequency);
+                                testFrequency, TEST_SWEEP);
                         while (written < data.length) {
                             int samples = Math.min(data.length - written, samplesPerWrite);
                             int ret = track.write(data, written, samples);
@@ -1674,9 +1627,9 @@
                         }
                         } break;
                     case AudioFormat.ENCODING_PCM_FLOAT: {
-                        float data[] = createSoundDataInFloatArray(
+                        float data[] = AudioHelper.createSoundDataInFloatArray(
                                 sourceSamples, TEST_SR,
-                                testFrequency);
+                                testFrequency, TEST_SWEEP);
                         while (written < data.length) {
                             int samples = Math.min(data.length - written, samplesPerWrite);
                             int ret = track.write(data, written, samples,
@@ -1719,6 +1672,7 @@
         };
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        final float TEST_SWEEP = 0; // sine wave only
 
         for (int TEST_FORMAT : TEST_FORMAT_ARRAY) {
             double frequency = 800; // frequency changes for each test
@@ -1732,10 +1686,19 @@
                             int bufferSize = 12 * minBufferSize;
                             int bufferSamples = bufferSize
                                     / AudioFormat.getBytesPerSample(TEST_FORMAT);
+
+                            // create audio track and confirm settings
                             AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR,
                                     TEST_CONF, TEST_FORMAT, minBufferSize, TEST_MODE);
-                            assertTrue(TEST_NAME,
-                                    track.getState() == AudioTrack.STATE_INITIALIZED);
+                            assertEquals(TEST_NAME + ": state",
+                                    AudioTrack.STATE_INITIALIZED, track.getState());
+                            assertEquals(TEST_NAME + ": sample rate",
+                                    TEST_SR, track.getSampleRate());
+                            assertEquals(TEST_NAME + ": channel mask",
+                                    TEST_CONF, track.getChannelConfiguration());
+                            assertEquals(TEST_NAME + ": encoding",
+                                    TEST_FORMAT, track.getAudioFormat());
+
                             ByteBuffer bb = (useDirect == 1)
                                     ? ByteBuffer.allocateDirect(bufferSize)
                                             : ByteBuffer.allocate(bufferSize);
@@ -1744,24 +1707,24 @@
                             // -------- test --------------
                             switch (TEST_FORMAT) {
                                 case AudioFormat.ENCODING_PCM_8BIT: {
-                                    byte data[] = createSoundDataInByteArray(
+                                    byte data[] = AudioHelper.createSoundDataInByteArray(
                                             bufferSamples, TEST_SR,
-                                            frequency);
+                                            frequency, TEST_SWEEP);
                                     bb.put(data);
                                     bb.flip();
                                 } break;
                                 case AudioFormat.ENCODING_PCM_16BIT: {
-                                    short data[] = createSoundDataInShortArray(
+                                    short data[] = AudioHelper.createSoundDataInShortArray(
                                             bufferSamples, TEST_SR,
-                                            frequency);
+                                            frequency, TEST_SWEEP);
                                     ShortBuffer sb = bb.asShortBuffer();
                                     sb.put(data);
                                     bb.limit(sb.limit() * 2);
                                 } break;
                                 case AudioFormat.ENCODING_PCM_FLOAT: {
-                                    float data[] = createSoundDataInFloatArray(
+                                    float data[] = AudioHelper.createSoundDataInFloatArray(
                                             bufferSamples, TEST_SR,
-                                            frequency);
+                                            frequency, TEST_SWEEP);
                                     FloatBuffer fb = bb.asFloatBuffer();
                                     fb.put(data);
                                     bb.limit(fb.limit() * 4);
@@ -1823,6 +1786,7 @@
                 AudioTrack.WRITE_BLOCKING,
                 AudioTrack.WRITE_NON_BLOCKING,
         };
+        final float TEST_SWEEP = 0;
 
         for (int TEST_FORMAT : TEST_FORMAT_ARRAY) {
             for (int TEST_CONF : TEST_CONF_ARRAY) {
@@ -1854,24 +1818,24 @@
 
                             switch (TEST_FORMAT) {
                             case AudioFormat.ENCODING_PCM_8BIT: {
-                                byte data[] = createSoundDataInByteArray(
+                                byte data[] = AudioHelper.createSoundDataInByteArray(
                                         bufferSamples, TEST_SR,
-                                        frequency);
+                                        frequency, TEST_SWEEP);
                                 bb.put(data);
                                 bb.flip();
                             } break;
                             case AudioFormat.ENCODING_PCM_16BIT: {
-                                short data[] = createSoundDataInShortArray(
+                                short data[] = AudioHelper.createSoundDataInShortArray(
                                         bufferSamples, TEST_SR,
-                                        frequency);
+                                        frequency, TEST_SWEEP);
                                 ShortBuffer sb = bb.asShortBuffer();
                                 sb.put(data);
                                 bb.limit(sb.limit() * 2);
                             } break;
                             case AudioFormat.ENCODING_PCM_FLOAT: {
-                                float data[] = createSoundDataInFloatArray(
+                                float data[] = AudioHelper.createSoundDataInFloatArray(
                                         bufferSamples, TEST_SR,
-                                        frequency);
+                                        frequency, TEST_SWEEP);
                                 FloatBuffer fb = bb.asFloatBuffer();
                                 fb.put(data);
                                 bb.limit(fb.limit() * 4);
@@ -2081,7 +2045,8 @@
                 TEST_FORMAT, bufferSizeInBytes, TEST_MODE);
 
         // create byte array and write it
-        byte[] vai = createSoundDataInByteArray(bufferSizeInBytes, TEST_SR, 600);
+        byte[] vai = AudioHelper.createSoundDataInByteArray(bufferSizeInBytes, TEST_SR,
+                600 /* frequency */, 0 /* sweep */);
         assertEquals(vai.length, track.write(vai, 0 /* offsetInBytes */, vai.length));
 
         // sweep up test and sweep down test
@@ -2149,7 +2114,8 @@
 
         // create float array and write it
         final int sampleCount = frameCount * format.getChannelCount();
-        float[] vaf = createSoundDataInFloatArray(sampleCount, TEST_SR, 600);
+        float[] vaf = AudioHelper.createSoundDataInFloatArray(
+                sampleCount, TEST_SR, 600 /* frequency */, 0 /* sweep */);
         assertEquals(vaf.length, track.write(vaf, 0 /* offsetInFloats */, vaf.length,
                 AudioTrack.WRITE_NON_BLOCKING));
 
@@ -2161,6 +2127,39 @@
                 { {1.0f, 0.5f}, {1.0f, 2.0f} },  // pitch by SR conversion (chirp)
         };
 
+        // sanity test that playback params works as expected
+        PlaybackParams params = new PlaybackParams().allowDefaults();
+        assertEquals(TEST_NAME, 1.0f, params.getSpeed());
+        assertEquals(TEST_NAME, 1.0f, params.getPitch());
+        assertEquals(TEST_NAME,
+                params.AUDIO_FALLBACK_MODE_DEFAULT,
+                params.getAudioFallbackMode());
+        track.setPlaybackParams(params); // OK
+        params.setAudioFallbackMode(params.AUDIO_FALLBACK_MODE_FAIL);
+        assertEquals(TEST_NAME,
+                params.AUDIO_FALLBACK_MODE_FAIL, params.getAudioFallbackMode());
+        params.setPitch(0.0f);
+        try {
+            track.setPlaybackParams(params);
+            fail("IllegalArgumentException should be thrown on out of range data");
+        } catch (IllegalArgumentException e) {
+            ; // expect this is invalid
+        }
+        // on failure, the AudioTrack params should not change.
+        PlaybackParams paramCheck = track.getPlaybackParams();
+        assertEquals(TEST_NAME,
+                paramCheck.AUDIO_FALLBACK_MODE_DEFAULT, paramCheck.getAudioFallbackMode());
+        assertEquals(TEST_NAME,
+                1.0f, paramCheck.getPitch());
+
+        // now try to see if we can do extreme pitch correction that should probably be muted.
+        params.setAudioFallbackMode(params.AUDIO_FALLBACK_MODE_MUTE);
+        assertEquals(TEST_NAME,
+                params.AUDIO_FALLBACK_MODE_MUTE, params.getAudioFallbackMode());
+        params.setPitch(0.1f);
+        track.setPlaybackParams(params); // OK
+
+        // now do our actual playback
         final int TEST_TIME_MS = 2000;
         final int TEST_DELTA_MS = 100;
         final int testSteps = TEST_TIME_MS / TEST_DELTA_MS;
@@ -2238,6 +2237,7 @@
     }
 */
 
+    /* MockAudioTrack allows testing of protected getNativeFrameCount() and setState(). */
     private class MockAudioTrack extends AudioTrack {
 
         public MockAudioTrack(int streamType, int sampleRateInHz, int channelConfig,
diff --git a/tests/tests/media/src/android/media/cts/AudioTrack_ListenerTest.java b/tests/tests/media/src/android/media/cts/AudioTrack_ListenerTest.java
index 353dbcb..e059e36 100644
--- a/tests/tests/media/src/android/media/cts/AudioTrack_ListenerTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioTrack_ListenerTest.java
@@ -119,19 +119,29 @@
             listener = new MockOnPlaybackPositionUpdateListener(track);
         }
 
-        byte[] vai = AudioTrackTest.createSoundDataInByteArray(bufferSizeInBytes, TEST_SR, 1024);
+        byte[] vai = AudioHelper.createSoundDataInByteArray(
+                bufferSizeInBytes, TEST_SR, 1024 /* frequency */, 0 /* sweep */);
         int markerPeriods = Math.max(3, mFrameCount * markerPeriodsPerSecond / TEST_SR);
         mMarkerPeriodInFrames = mFrameCount / markerPeriods;
         markerPeriods = mFrameCount / mMarkerPeriodInFrames; // recalculate due to round-down
         mMarkerPosition = mMarkerPeriodInFrames;
+
+        // check that we can get and set notification marker position
+        assertEquals(0, track.getNotificationMarkerPosition());
         assertEquals(AudioTrack.SUCCESS,
                 track.setNotificationMarkerPosition(mMarkerPosition));
+        assertEquals(mMarkerPosition, track.getNotificationMarkerPosition());
+
         int updatePeriods = Math.max(3, mFrameCount * periodsPerSecond / TEST_SR);
         final int updatePeriodInFrames = mFrameCount / updatePeriods;
         updatePeriods = mFrameCount / updatePeriodInFrames; // recalculate due to round-down
+
+        // we set the notification period before running for better period positional accuracy.
+        // check that we can get and set notification periods
+        assertEquals(0, track.getPositionNotificationPeriod());
         assertEquals(AudioTrack.SUCCESS,
                 track.setPositionNotificationPeriod(updatePeriodInFrames));
-        // set NotificationPeriod before running to ensure better period positional accuracy.
+        assertEquals(updatePeriodInFrames, track.getPositionNotificationPeriod());
 
         if (mode == AudioTrack.MODE_STATIC && TEST_LOOP_FACTOR > 1) {
             track.setLoopPoints(0, vai.length, TEST_LOOP_FACTOR - 1);
diff --git a/tests/tests/media/src/android/media/cts/EnumDevicesTest.java b/tests/tests/media/src/android/media/cts/EnumDevicesTest.java
new file mode 100644
index 0000000..0e1621d
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/EnumDevicesTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.cts;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+import android.media.AudioDeviceCallback;
+import android.media.AudioDeviceInfo;
+import android.media.AudioManager;
+
+import android.os.Handler;
+import android.os.Looper;
+
+import android.test.AndroidTestCase;
+
+/**
+ * TODO: Insert description here. (generated by pmclean)
+ */
+public class EnumDevicesTest extends AndroidTestCase {
+    private AudioManager mAudioManager;
+
+    boolean mAddCallbackCalled = false;
+    boolean mRemoveCallbackCalled = false;
+
+    static {
+        // We're going to use a Handler
+        Looper.prepare();
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        // get the AudioManager
+        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+        assertNotNull(mAudioManager);
+    }
+
+    public void test_getDevices() {
+        AudioDeviceInfo[] deviceList;
+
+        // test an empty flags set
+        deviceList = mAudioManager.getDevices(0);
+        assertTrue(deviceList != null);
+        assertTrue(deviceList.length == 0);
+
+        int numOutputDevices = 0;
+        if (mContext.getPackageManager().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"
+            for(int index = 0; index < numOutputDevices; index++) {
+                assertTrue(deviceList[index].isSink());
+            }
+        }
+
+        int numInputDevices = 0;
+        if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MICROPHONE)) {
+            // test INPUTS
+            deviceList = mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS);
+            assertTrue(deviceList != null);
+            numInputDevices = deviceList.length;
+            assertTrue(numInputDevices != 0);
+
+            // all should be "sources"
+            for(int index = 0; index < numInputDevices; index++) {
+                assertTrue(deviceList[index].isSource());
+            }
+        }
+
+        // INPUTS & OUTPUTS
+        if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT) &&
+                mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MICROPHONE)) {
+            deviceList = mAudioManager.getDevices(AudioManager.GET_DEVICES_ALL);
+            assertTrue(deviceList.length == (numOutputDevices + numInputDevices));
+        }
+    }
+
+    private class EmptyDeviceCallback extends AudioDeviceCallback {
+        public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) {
+            mAddCallbackCalled = true;
+        }
+
+        public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) {
+            mRemoveCallbackCalled = true;
+        }
+    }
+
+    public void test_deviceCallback() {
+        mAudioManager.registerAudioDeviceCallback(null,null);
+        assertTrue(true);
+
+        AudioDeviceCallback callback =  new EmptyDeviceCallback();
+        mAudioManager.registerAudioDeviceCallback(callback, null);
+        assertTrue(true);
+
+        mAudioManager.registerAudioDeviceCallback(callback, new Handler());
+        assertTrue(true);
+    }
+
+    //TODO - Need tests for device connect/disconnect callbacks
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaBrowserTest.java b/tests/tests/media/src/android/media/cts/MediaBrowserTest.java
new file mode 100644
index 0000000..b53aa92
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaBrowserTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media.cts;
+
+import android.content.ComponentName;
+import android.cts.util.PollingCheck;
+import android.media.browse.MediaBrowser;
+import android.test.InstrumentationTestCase;
+
+/**
+ * Test {@link android.media.browse.MediaBrowser}.
+ */
+public class MediaBrowserTest extends InstrumentationTestCase {
+    // The maximum time to wait for an operation.
+    private static final long TIME_OUT_MS = 1000L;
+    private static final ComponentName TEST_BROWSER_SERVICE = new ComponentName(
+            "com.android.cts.media", "android.media.cts.StubMediaBrowserService");
+    private final StubConnectionCallback mConnectionCallback = new StubConnectionCallback();
+
+    private MediaBrowser mMediaBrowser;
+
+    public void testMediaBrowser() {
+        mConnectionCallback.resetCounts();
+        createMediaBrowser(TEST_BROWSER_SERVICE);
+        assertEquals(false, mMediaBrowser.isConnected());
+
+        connectMediaBrowserService();
+        assertEquals(true, mMediaBrowser.isConnected());
+
+        assertEquals(TEST_BROWSER_SERVICE, mMediaBrowser.getServiceComponent());
+        assertEquals(StubMediaBrowserService.MEDIA_ID_ROOT, mMediaBrowser.getRoot());
+        assertEquals(StubMediaBrowserService.EXTRAS_VALUE,
+                mMediaBrowser.getExtras().getString(StubMediaBrowserService.EXTRAS_KEY));
+        assertEquals(StubMediaBrowserService.sSession.getSessionToken(),
+                mMediaBrowser.getSessionToken());
+
+        mMediaBrowser.disconnect();
+        assertEquals(false, mMediaBrowser.isConnected());
+    }
+
+    public void testConnectTwice() {
+        mConnectionCallback.resetCounts();
+        createMediaBrowser(TEST_BROWSER_SERVICE);
+        connectMediaBrowserService();
+        try {
+            mMediaBrowser.connect();
+            fail();
+        } catch (IllegalStateException e) {
+            // expected
+        }
+    }
+
+    public void testGetServiceComponentBeforeConnection() {
+        mConnectionCallback.resetCounts();
+        createMediaBrowser(TEST_BROWSER_SERVICE);
+        try {
+            ComponentName serviceComponent = mMediaBrowser.getServiceComponent();
+            fail();
+        } catch (IllegalStateException e) {
+            // expected
+        }
+    }
+
+    private void createMediaBrowser(final ComponentName component) {
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                mMediaBrowser = new MediaBrowser(getInstrumentation().getTargetContext(),
+                        component, mConnectionCallback, null);
+            }
+        });
+    }
+
+    private void connectMediaBrowserService() {
+        mMediaBrowser.connect();
+        new PollingCheck(TIME_OUT_MS) {
+            @Override
+            protected boolean check() {
+                return mConnectionCallback.mConnectedCount > 0;
+            }
+        }.run();
+    }
+
+    private static class StubConnectionCallback extends MediaBrowser.ConnectionCallback {
+        volatile int mConnectedCount;
+        volatile int mConnectionFailedCount;
+        volatile int mConnectionSuspendedCount;
+
+        public void resetCounts() {
+            mConnectedCount = 0;
+            mConnectionFailedCount = 0;
+            mConnectionSuspendedCount = 0;
+        }
+
+        @Override
+        public void onConnected() {
+            mConnectedCount++;
+        }
+
+        @Override
+        public void onConnectionFailed() {
+            mConnectionFailedCount++;
+        }
+
+        @Override
+        public void onConnectionSuspended() {
+            mConnectionSuspendedCount++;
+        }
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaDrmMockTest.java b/tests/tests/media/src/android/media/cts/MediaDrmMockTest.java
index 52fd395..a197cca 100644
--- a/tests/tests/media/src/android/media/cts/MediaDrmMockTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaDrmMockTest.java
@@ -17,10 +17,10 @@
 package android.media.cts;
 
 import android.media.MediaDrm;
-import android.media.MediaDrm.ProvisionRequest;
+import android.media.MediaDrm.CryptoSession;
 import android.media.MediaDrm.KeyRequest;
 import android.media.MediaDrm.KeyStatus;
-import android.media.MediaDrm.CryptoSession;
+import android.media.MediaDrm.ProvisionRequest;
 import android.media.MediaDrmException;
 import android.media.NotProvisionedException;
 import android.media.ResourceBusyException;
@@ -245,7 +245,7 @@
                                                       optionalParameters);
         assertTrue(Arrays.equals(request.getData(), testRequest));
         assertTrue(request.getDefaultUrl().equals(testDefaultUrl));
-        assertEquals(request.getRequestType(), MediaDrm.REQUEST_TYPE_INITIAL);
+        assertEquals(request.getRequestType(), MediaDrm.KeyRequest.REQUEST_TYPE_INITIAL);
 
         assertTrue(Arrays.equals(initData, md.getPropertyByteArray("mock-initdata")));
         assertTrue(mimeType.equals(md.getPropertyString("mock-mimetype")));
@@ -278,7 +278,7 @@
                                                       null);
         assertTrue(Arrays.equals(request.getData(), testRequest));
         assertTrue(request.getDefaultUrl().equals(testDefaultUrl));
-        assertEquals(request.getRequestType(), MediaDrm.REQUEST_TYPE_INITIAL);
+        assertEquals(request.getRequestType(), MediaDrm.KeyRequest.REQUEST_TYPE_INITIAL);
 
         assertTrue(Arrays.equals(initData, md.getPropertyByteArray("mock-initdata")));
         assertTrue(mimeType.equals(md.getPropertyString("mock-mimetype")));
@@ -310,7 +310,7 @@
                                               null);
         assertTrue(Arrays.equals(request.getData(), testRequest));
         assertTrue(request.getDefaultUrl().equals(testDefaultUrl));
-        assertEquals(request.getRequestType(), MediaDrm.REQUEST_TYPE_RENEWAL);
+        assertEquals(request.getRequestType(), MediaDrm.KeyRequest.REQUEST_TYPE_RENEWAL);
 
         assertTrue(Arrays.equals(initData, md.getPropertyByteArray("mock-initdata")));
         assertTrue(mimeType.equals(md.getPropertyString("mock-mimetype")));
@@ -340,7 +340,7 @@
                                               null);
         assertTrue(Arrays.equals(request.getData(), testRequest));
         assertTrue(request.getDefaultUrl().equals(testDefaultUrl));
-        assertEquals(request.getRequestType(), MediaDrm.REQUEST_TYPE_RELEASE);
+        assertEquals(request.getRequestType(), MediaDrm.KeyRequest.REQUEST_TYPE_RELEASE);
 
         assertTrue(mimeType.equals(md.getPropertyString("mock-mimetype")));
         assertTrue(md.getPropertyString("mock-keytype").equals("2"));
@@ -862,7 +862,7 @@
         assertTrue(mGotEvent);
     }
 
-    public void testKeysChange() throws Exception {
+    public void testKeyStatusChange() throws Exception {
         if (!isMockPluginInstalled()) {
             return;
         }
@@ -893,30 +893,30 @@
                 synchronized(mLock) {
                     mLock.notify();
 
-                    mMediaDrm.setOnKeysChangeListener(new MediaDrm.OnKeysChangeListener() {
+                    mMediaDrm.setOnKeyStatusChangeListener(new MediaDrm.OnKeyStatusChangeListener() {
                             @Override
-                            public void onKeysChange(MediaDrm md, byte[] sessionId,
+                            public void onKeyStatusChange(MediaDrm md, byte[] sessionId,
                                     List<KeyStatus> keyInformation, boolean hasNewUsableKey) {
                                 synchronized(mLock) {
-                                    Log.d(TAG,"testKeysChange.onKeysChange");
+                                    Log.d(TAG,"testKeyStatusChange.onKeyStatusChange");
                                     assertTrue(md == mMediaDrm);
                                     assertTrue(Arrays.equals(sessionId, expected_sessionId));
                                     try {
                                         KeyStatus keyStatus = keyInformation.get(0);
                                         assertTrue(Arrays.equals(keyStatus.getKeyId(), "key1".getBytes()));
-                                        assertTrue(keyStatus.getStatusCode() == MediaDrm.KEY_STATUS_USABLE);
+                                        assertTrue(keyStatus.getStatusCode() == MediaDrm.KeyStatus.STATUS_USABLE);
                                         keyStatus = keyInformation.get(1);
                                         assertTrue(Arrays.equals(keyStatus.getKeyId(), "key2".getBytes()));
-                                        assertTrue(keyStatus.getStatusCode() == MediaDrm.KEY_STATUS_EXPIRED);
+                                        assertTrue(keyStatus.getStatusCode() == MediaDrm.KeyStatus.STATUS_EXPIRED);
                                         keyStatus = keyInformation.get(2);
                                         assertTrue(Arrays.equals(keyStatus.getKeyId(), "key3".getBytes()));
-                                        assertTrue(keyStatus.getStatusCode() == MediaDrm.KEY_STATUS_OUTPUT_NOT_ALLOWED);
+                                        assertTrue(keyStatus.getStatusCode() == MediaDrm.KeyStatus.STATUS_OUTPUT_NOT_ALLOWED);
                                         keyStatus = keyInformation.get(3);
                                         assertTrue(Arrays.equals(keyStatus.getKeyId(), "key4".getBytes()));
-                                        assertTrue(keyStatus.getStatusCode() == MediaDrm.KEY_STATUS_PENDING);
+                                        assertTrue(keyStatus.getStatusCode() == MediaDrm.KeyStatus.STATUS_PENDING);
                                         keyStatus = keyInformation.get(4);
                                         assertTrue(Arrays.equals(keyStatus.getKeyId(), "key5".getBytes()));
-                                        assertTrue(keyStatus.getStatusCode() == MediaDrm.KEY_STATUS_INTERNAL_ERROR);
+                                        assertTrue(keyStatus.getStatusCode() == MediaDrm.KeyStatus.STATUS_INTERNAL_ERROR);
                                         assertTrue(hasNewUsableKey);
                                         mGotEvent = true;
                                     } catch (IndexOutOfBoundsException e) {
diff --git a/tests/tests/media/src/android/media/cts/MediaExtractorTest.java b/tests/tests/media/src/android/media/cts/MediaExtractorTest.java
index 7ca498f..9db54ff 100644
--- a/tests/tests/media/src/android/media/cts/MediaExtractorTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaExtractorTest.java
@@ -83,7 +83,7 @@
 
     public void testExtractorFailsIfMediaDataSourceReturnsAnError() throws Exception {
         TestMediaDataSource dataSource = getDataSourceFor(R.raw.testvideo);
-        dataSource.returnFromReadAt(-1);
+        dataSource.returnFromReadAt(-2);
         try {
             mExtractor.setDataSource(dataSource);
             fail("Expected IOException.");
diff --git a/tests/tests/media/src/android/media/cts/MediaItemTest.java b/tests/tests/media/src/android/media/cts/MediaItemTest.java
new file mode 100644
index 0000000..4eefaa7
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaItemTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media.cts;
+
+import android.media.MediaDescription;
+import android.media.browse.MediaBrowser.MediaItem;
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+
+/**
+ * Test {@link android.media.browse.MediaBrowser.MediaItem}.
+ */
+public class MediaItemTest extends AndroidTestCase {
+    private static final String DESCRIPTION = "test_description";
+    private static final String MEDIA_ID = "test_media_id";
+    private static final String TITLE = "test_title";
+    private static final String SUBTITLE = "test_subtitle";
+
+    public void testBrowsableMediaItem() {
+        MediaDescription description = new MediaDescription.Builder()
+                .setDescription(DESCRIPTION).setMediaId(MEDIA_ID)
+                .setTitle(TITLE).setSubtitle(SUBTITLE).build();
+        MediaItem mediaItem = new MediaItem(description, MediaItem.FLAG_BROWSABLE);
+
+        assertEquals(description.toString(), mediaItem.getDescription().toString());
+        assertEquals(MEDIA_ID, mediaItem.getMediaId());
+        assertEquals(MediaItem.FLAG_BROWSABLE, mediaItem.getFlags());
+        assertTrue(mediaItem.isBrowsable());
+        assertFalse(mediaItem.isPlayable());
+
+        // Test writeToParcel
+        Parcel p = Parcel.obtain();
+        mediaItem.writeToParcel(p, 0);
+        p.setDataPosition(0);
+        assertEquals(mediaItem.getFlags(), p.readInt());
+        assertEquals(description.toString(),
+                MediaDescription.CREATOR.createFromParcel(p).toString());
+        p.recycle();
+    }
+
+    public void testPlayableMediaItem() {
+        MediaDescription description = new MediaDescription.Builder()
+                .setDescription(DESCRIPTION).setMediaId(MEDIA_ID)
+                .setTitle(TITLE).setSubtitle(SUBTITLE).build();
+        MediaItem mediaItem = new MediaItem(description, MediaItem.FLAG_PLAYABLE);
+
+        assertEquals(description.toString(), mediaItem.getDescription().toString());
+        assertEquals(MEDIA_ID, mediaItem.getMediaId());
+        assertEquals(MediaItem.FLAG_PLAYABLE, mediaItem.getFlags());
+        assertFalse(mediaItem.isBrowsable());
+        assertTrue(mediaItem.isPlayable());
+
+        // Test writeToParcel
+        Parcel p = Parcel.obtain();
+        mediaItem.writeToParcel(p, 0);
+        p.setDataPosition(0);
+        assertEquals(mediaItem.getFlags(), p.readInt());
+        assertEquals(description.toString(),
+                MediaDescription.CREATOR.createFromParcel(p).toString());
+        p.recycle();
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java b/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
index 622c0ec..562656b 100644
--- a/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
@@ -146,7 +146,7 @@
 
     public void testRetrieveFailsIfMediaDataSourceReturnsAnError() throws Exception {
         TestMediaDataSource dataSource = setDataSourceCallback(R.raw.testvideo);
-        dataSource.returnFromReadAt(-1);
+        dataSource.returnFromReadAt(-2);
         assertTrue(mRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE) == null);
     }
 }
diff --git a/tests/tests/media/src/android/media/cts/MediaMuxerTest.java b/tests/tests/media/src/android/media/cts/MediaMuxerTest.java
index 67eeca0..0f664a5 100644
--- a/tests/tests/media/src/android/media/cts/MediaMuxerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaMuxerTest.java
@@ -104,6 +104,8 @@
             fail("should throw IllegalStateException.");
         } catch (IllegalStateException e) {
             // expected
+        } finally {
+            muxer.release();
         }
 
         // Throws exception b/c 2 video tracks were added.
@@ -115,6 +117,8 @@
             fail("should throw IllegalStateException.");
         } catch (IllegalStateException e) {
             // expected
+        } finally {
+            muxer.release();
         }
 
         // Throws exception b/c 2 audio tracks were added.
@@ -125,6 +129,8 @@
             fail("should throw IllegalStateException.");
         } catch (IllegalStateException e) {
             // expected
+        } finally {
+            muxer.release();
         }
 
         // Throws exception b/c 3 tracks were added.
@@ -137,6 +143,8 @@
             fail("should throw IllegalStateException.");
         } catch (IllegalStateException e) {
             // expected
+        } finally {
+            muxer.release();
         }
 
         // Throws exception b/c no tracks was added.
@@ -146,6 +154,8 @@
             fail("should throw IllegalStateException.");
         } catch (IllegalStateException e) {
             // expected
+        } finally {
+            muxer.release();
         }
 
         // Throws exception b/c a wrong format.
@@ -155,6 +165,8 @@
             fail("should throw IllegalStateException.");
         } catch (IllegalStateException e) {
             // expected
+        } finally {
+            muxer.release();
         }
         new File(outputFile).delete();
     }
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerFlakyNetworkTest.java b/tests/tests/media/src/android/media/cts/MediaPlayerFlakyNetworkTest.java
index 32fbfb5..640083f 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerFlakyNetworkTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerFlakyNetworkTest.java
@@ -23,6 +23,8 @@
 import android.os.SystemClock;
 import android.webkit.cts.CtsTestServer;
 
+import com.android.cts.util.TimeoutReq;
+
 import org.apache.http.HttpServerConnection;
 
 import org.apache.http.impl.DefaultHttpServerConnection;
@@ -67,30 +69,37 @@
         super.tearDown();
     }
 
+    @TimeoutReq(minutes = 5)
     public void test_S0P0() throws Throwable {
         doPlayStreams(0, 0);
     }
 
+    @TimeoutReq(minutes = 10)
     public void test_S1P000005() throws Throwable {
         doPlayStreams(1, 0.000005f);
     }
 
+    @TimeoutReq(minutes = 10)
     public void test_S2P00001() throws Throwable {
         doPlayStreams(2, 0.00001f);
     }
 
+    @TimeoutReq(minutes = 10)
     public void test_S3P00001() throws Throwable {
         doPlayStreams(3, 0.00001f);
     }
 
+    @TimeoutReq(minutes = 10)
     public void test_S4P00001() throws Throwable {
         doPlayStreams(4, 0.00001f);
     }
 
+    @TimeoutReq(minutes = 10)
     public void test_S5P00001() throws Throwable {
         doPlayStreams(5, 0.00001f);
     }
 
+    @TimeoutReq(minutes = 10)
     public void test_S6P00002() throws Throwable {
         doPlayStreams(6, 0.00002f);
     }
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
index 661b815..18cd353 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
@@ -26,10 +26,13 @@
 import android.media.MediaDataSource;
 import android.media.MediaExtractor;
 import android.media.MediaFormat;
+import android.media.MediaMetadataRetriever;
 import android.media.MediaPlayer;
 import android.media.MediaPlayer.OnErrorListener;
 import android.media.MediaRecorder;
-import android.media.MediaMetadataRetriever;
+import android.media.MediaTimestamp;
+import android.media.PlaybackParams;
+import android.media.SyncParams;
 import android.media.TimedText;
 import android.media.audiofx.AudioEffect;
 import android.media.audiofx.Visualizer;
@@ -68,6 +71,8 @@
     private static final int  RECORDED_VIDEO_WIDTH  = 176;
     private static final int  RECORDED_VIDEO_HEIGHT = 144;
     private static final long RECORDED_DURATION_MS  = 3000;
+    private static final float FLOAT_TOLERANCE = .0001f;
+
     private Vector<Integer> mTimedTextTrackIndex = new Vector<Integer>();
     private int mSelectedTimedTextIndex;
     private Monitor mOnTimedTextCalled = new Monitor();
@@ -840,15 +845,22 @@
 
         mMediaPlayer.setDisplay(mActivity.getSurfaceHolder());
         mMediaPlayer.prepare();
+        SyncParams sync = new SyncParams().allowDefaults();
+        mMediaPlayer.setSyncParams(sync);
+        sync = mMediaPlayer.getSyncParams();
+
         float[] rates = { 0.25f, 0.5f, 1.0f, 2.0f };
         for (float playbackRate : rates) {
             mMediaPlayer.seekTo(0);
             Thread.sleep(1000);
             int playTime = 4000;  // The testing clip is about 10 second long.
-            mMediaPlayer.setPlaybackRate(playbackRate,
-                                         MediaPlayer.PLAYBACK_RATE_AUDIO_MODE_RESAMPLE);
+            mMediaPlayer.setPlaybackParams(new PlaybackParams().setSpeed(playbackRate));
             mMediaPlayer.start();
             Thread.sleep(playTime);
+            PlaybackParams pbp = mMediaPlayer.getPlaybackParams();
+            assertEquals(
+                    playbackRate, pbp.getSpeed(),
+                    FLOAT_TOLERANCE + playbackRate * sync.getTolerance());
             assertTrue("MediaPlayer should still be playing", mMediaPlayer.isPlaying());
 
             int playedMediaDurationMs = mMediaPlayer.getCurrentPosition();
@@ -858,10 +870,58 @@
                      + ", play time is " + playTime + " vs expected " + playedMediaDurationMs);
             }
             mMediaPlayer.pause();
+            pbp = mMediaPlayer.getPlaybackParams();
+            assertEquals(0.f, pbp.getSpeed(), FLOAT_TOLERANCE);
         }
         mMediaPlayer.stop();
     }
 
+    public void testGetTimestamp() throws Exception {
+        final int toleranceUs = 100000;
+        final float playbackRate = 1.0f;
+        if (!checkLoadResource(
+                R.raw.video_480x360_mp4_h264_1000kbps_30fps_aac_stereo_128kbps_44100hz)) {
+            return; // skip
+        }
+
+        mMediaPlayer.setDisplay(mActivity.getSurfaceHolder());
+        mMediaPlayer.prepare();
+        mMediaPlayer.start();
+        mMediaPlayer.setPlaybackParams(new PlaybackParams().setSpeed(playbackRate));
+        Thread.sleep(SLEEP_TIME);  // let player get into stable state.
+        long nt1 = System.nanoTime();
+        MediaTimestamp ts1 = mMediaPlayer.getTimestamp();
+        long nt2 = System.nanoTime();
+        assertTrue("Media player should return a valid time stamp", ts1 != null);
+        assertEquals("MediaPlayer had error in clockRate " + ts1.getMediaClockRate(),
+                playbackRate, ts1.getMediaClockRate(), 0.001f);
+        assertTrue("The nanoTime of Media timestamp should be taken when getTimestamp is called.",
+                nt1 <= ts1.nanoTime && ts1.nanoTime <= nt2);
+
+        mMediaPlayer.pause();
+        ts1 = mMediaPlayer.getTimestamp();
+        assertTrue("Media player should return a valid time stamp", ts1 != null);
+        assertTrue("Media player should have play rate of 0.0f when paused",
+                ts1.getMediaClockRate() == 0.0f);
+
+        mMediaPlayer.seekTo(0);
+        mMediaPlayer.start();
+        Thread.sleep(SLEEP_TIME);  // let player get into stable state.
+        int playTime = 4000;  // The testing clip is about 10 second long.
+        ts1 = mMediaPlayer.getTimestamp();
+        assertTrue("Media player should return a valid time stamp", ts1 != null);
+        Thread.sleep(playTime);
+        MediaTimestamp ts2 = mMediaPlayer.getTimestamp();
+        assertTrue("Media player should return a valid time stamp", ts2 != null);
+        assertTrue("The clockRate should not be changed.",
+                ts1.getMediaClockRate() == ts2.getMediaClockRate());
+        assertEquals("MediaPlayer had error in timestamp.",
+                ts1.getAnchorMediaTimeUs() + (long)(playTime * ts1.getMediaClockRate() * 1000),
+                ts2.getAnchorMediaTimeUs(), toleranceUs);
+
+        mMediaPlayer.stop();
+    }
+
     public void testLocalVideo_MP4_H264_480x360_500kbps_25fps_AAC_Stereo_128kbps_44110Hz()
             throws Exception {
         playVideoTest(
@@ -1589,7 +1649,7 @@
         mMediaPlayer.setDataSource(dataSource);
         mMediaPlayer.prepare();
 
-        dataSource.returnFromReadAt(-1);
+        dataSource.returnFromReadAt(-2);
         mMediaPlayer.start();
         assertTrue(mOnErrorCalled.waitForSignal());
     }
diff --git a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
index 78b5cfd..b6ee1db 100644
--- a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
@@ -18,10 +18,16 @@
 
 import android.content.pm.PackageManager;
 import android.cts.util.MediaUtils;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
 import android.hardware.Camera;
+import android.media.EncoderCapabilities;
+import android.media.MediaCodec;
 import android.media.MediaFormat;
 import android.media.MediaMetadataRetriever;
 import android.media.MediaRecorder;
+import android.media.EncoderCapabilities.VideoEncoderCap;
 import android.media.MediaRecorder.OnErrorListener;
 import android.media.MediaRecorder.OnInfoListener;
 import android.media.MediaMetadataRetriever;
@@ -38,6 +44,7 @@
 import java.io.FileOutputStream;
 import java.lang.InterruptedException;
 import java.lang.Runnable;
+import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -62,6 +69,12 @@
     private static final int MAX_DURATION_MSEC = 2000;
     private static final float LATITUDE = 0.0000f;
     private static final float LONGITUDE  = -180.0f;
+    private static final int NORMAL_FPS = 30;
+    private static final int TIME_LAPSE_FPS = 5;
+    private static final int SLOW_MOTION_FPS = 120;
+    private static final List<VideoEncoderCap> mVideoEncoders =
+            EncoderCapabilities.getVideoEncoders();
+
     private boolean mOnInfoCalled;
     private boolean mOnErrorCalled;
     private File mOutFile;
@@ -138,8 +151,10 @@
 
     @Override
     protected void tearDown() throws Exception {
-        mMediaRecorder.release();
-        mMediaRecorder = null;
+        if (mMediaRecorder != null) {
+            mMediaRecorder.release();
+            mMediaRecorder = null;
+        }
         if (mOutFile != null && mOutFile.exists()) {
             mOutFile.delete();
         }
@@ -477,6 +492,441 @@
         assertFalse(mOnErrorCalled);
     }
 
+    private void setupRecorder(String filename, boolean useSurface, boolean hasAudio)
+            throws Exception {
+        int codec = MediaRecorder.VideoEncoder.H264;
+        int frameRate = getMaxFrameRateForCodec(codec);
+        if (mMediaRecorder == null) {
+            mMediaRecorder = new MediaRecorder();
+        }
+
+        if (!useSurface) {
+            mCamera = Camera.open(0);
+            Camera.Parameters params = mCamera.getParameters();
+            frameRate = params.getPreviewFrameRate();
+            mCamera.unlock();
+            mMediaRecorder.setCamera(mCamera);
+            mMediaRecorder.setPreviewDisplay(mActivity.getSurfaceHolder().getSurface());
+        }
+
+        mMediaRecorder.setVideoSource(useSurface ?
+                MediaRecorder.VideoSource.SURFACE : MediaRecorder.VideoSource.CAMERA);
+
+        if (hasAudio) {
+            mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
+        }
+
+        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
+        mMediaRecorder.setOutputFile(filename);
+
+        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
+        mMediaRecorder.setVideoFrameRate(frameRate);
+        mMediaRecorder.setVideoSize(VIDEO_WIDTH, VIDEO_HEIGHT);
+
+        if (hasAudio) {
+            mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
+        }
+    }
+
+    private Surface tryGetSurface(boolean shouldThrow) throws Exception {
+        Surface surface = null;
+        try {
+            surface = mMediaRecorder.getSurface();
+            assertFalse("failed to throw IllegalStateException", shouldThrow);
+        } catch (IllegalStateException e) {
+            assertTrue("threw unexpected exception: " + e, shouldThrow);
+        }
+        return surface;
+    }
+
+    private boolean validateGetSurface(boolean useSurface) {
+        Log.v(TAG,"validateGetSurface, useSurface=" + useSurface);
+        if (!useSurface && !hasCamera()) {
+            // pass if testing camera source but no hardware
+            return true;
+        }
+        Surface surface = null;
+        boolean success = true;
+        try {
+            setupRecorder(OUTPUT_PATH, useSurface, false /* hasAudio */);
+
+            /* Test: getSurface() before prepare()
+             * should throw IllegalStateException
+             */
+            surface = tryGetSurface(true /* shouldThow */);
+
+            mMediaRecorder.prepare();
+
+            /* Test: getSurface() after prepare()
+             * should succeed for surface source
+             * should fail for camera source
+             */
+            surface = tryGetSurface(!useSurface);
+
+            mMediaRecorder.start();
+
+            /* Test: getSurface() after start()
+             * should succeed for surface source
+             * should fail for camera source
+             */
+            surface = tryGetSurface(!useSurface);
+
+            try {
+                mMediaRecorder.stop();
+            } catch (Exception e) {
+                // stop() could fail if the recording is empty, as we didn't render anything.
+                // ignore any failure in stop, we just want it stopped.
+            }
+
+            /* Test: getSurface() after stop()
+             * should throw IllegalStateException
+             */
+            surface = tryGetSurface(true /* shouldThow */);
+        } catch (Exception e) {
+            Log.d(TAG, e.toString());
+            success = false;
+        } finally {
+            // reset to clear states, as stop() might have failed
+            mMediaRecorder.reset();
+
+            if (mCamera != null) {
+                mCamera.release();
+                mCamera = null;
+            }
+            if (surface != null) {
+                surface.release();
+                surface = null;
+            }
+        }
+
+        return success;
+    }
+
+    private void trySetInputSurface(Surface surface) throws Exception {
+        boolean testBadArgument = (surface == null);
+        try {
+            mMediaRecorder.setInputSurface(testBadArgument ? new Surface() : surface);
+            fail("failed to throw exception");
+        } catch (IllegalArgumentException e) {
+            // OK only if testing bad arg
+            assertTrue("threw unexpected exception: " + e, testBadArgument);
+        } catch (IllegalStateException e) {
+            // OK only if testing error case other than bad arg
+            assertFalse("threw unexpected exception: " + e, testBadArgument);
+        }
+    }
+
+    private boolean validatePersistentSurface(boolean errorCase) {
+        Log.v(TAG, "validatePersistentSurface, errorCase=" + errorCase);
+
+        Surface surface = MediaCodec.createPersistentInputSurface();
+        if (surface == null) {
+            return false;
+        }
+        Surface dummy = null;
+
+        boolean success = true;
+        try {
+            setupRecorder(OUTPUT_PATH, true /* useSurface */, false /* hasAudio */);
+
+            if (errorCase) {
+                /*
+                 * Test: should throw if called with non-persistent surface
+                 */
+                trySetInputSurface(null);
+            } else {
+                /*
+                 * Test: should succeed if called with a persistent surface before prepare()
+                 */
+                mMediaRecorder.setInputSurface(surface);
+            }
+
+            /*
+             * Test: getSurface() should fail before prepare
+             */
+            dummy = tryGetSurface(true /* shouldThow */);
+
+            mMediaRecorder.prepare();
+
+            /*
+             * Test: setInputSurface() should fail after prepare
+             */
+            trySetInputSurface(surface);
+
+            /*
+             * Test: getSurface() should fail if setInputSurface() succeeded
+             */
+            dummy = tryGetSurface(!errorCase /* shouldThow */);
+
+            mMediaRecorder.start();
+
+            /*
+             * Test: setInputSurface() should fail after start
+             */
+            trySetInputSurface(surface);
+
+            /*
+             * Test: getSurface() should fail if setInputSurface() succeeded
+             */
+            dummy = tryGetSurface(!errorCase /* shouldThow */);
+
+            try {
+                mMediaRecorder.stop();
+            } catch (Exception e) {
+                // stop() could fail if the recording is empty, as we didn't render anything.
+                // ignore any failure in stop, we just want it stopped.
+            }
+
+            /*
+             * Test: getSurface() should fail after stop
+             */
+            dummy = tryGetSurface(true /* shouldThow */);
+        } catch (Exception e) {
+            Log.d(TAG, e.toString());
+            success = false;
+        } finally {
+            // reset to clear states, as stop() might have failed
+            mMediaRecorder.reset();
+
+            if (mCamera != null) {
+                mCamera.release();
+                mCamera = null;
+            }
+            if (surface != null) {
+                surface.release();
+                surface = null;
+            }
+            if (dummy != null) {
+                dummy.release();
+                dummy = null;
+            }
+        }
+
+        return success;
+    }
+
+    public void testGetSurfaceApi() {
+        if (!hasH264()) {
+            MediaUtils.skipTest("no codecs");
+            return;
+        }
+
+        if (hasCamera()) {
+            // validate getSurface() with CAMERA source
+            assertTrue(validateGetSurface(false /* useSurface */));
+        }
+
+        // validate getSurface() with SURFACE source
+        assertTrue(validateGetSurface(true /* useSurface */));
+    }
+
+    public void testPersistentSurfaceApi() {
+        if (!hasH264()) {
+            MediaUtils.skipTest("no codecs");
+            return;
+        }
+
+        // test valid use case
+        assertTrue(validatePersistentSurface(false /* errorCase */));
+
+        // test invalid use case
+        assertTrue(validatePersistentSurface(true /* errorCase */));
+    }
+
+    private static int getMaxFrameRateForCodec(int codec) {
+        for (VideoEncoderCap cap : mVideoEncoders) {
+            if (cap.mCodec == codec) {
+                return cap.mMaxFrameRate < NORMAL_FPS ? cap.mMaxFrameRate : NORMAL_FPS;
+            }
+        }
+        fail("didn't find max FPS for codec");
+        return -1;
+    }
+
+    private boolean recordFromSurface(
+            String filename,
+            int captureRate,
+            boolean hasAudio,
+            Surface persistentSurface) {
+        Log.v(TAG, "recordFromSurface");
+        Surface surface = null;
+        try {
+            setupRecorder(filename, true /* useSurface */, hasAudio);
+
+            int sleepTimeMs;
+            if (captureRate > 0) {
+                mMediaRecorder.setCaptureRate(captureRate);
+                sleepTimeMs = 1000 / captureRate;
+            } else {
+                sleepTimeMs = 1000 / getMaxFrameRateForCodec(MediaRecorder.VideoEncoder.H264);
+            }
+
+            if (persistentSurface != null) {
+                Log.v(TAG, "using persistent surface");
+                surface = persistentSurface;
+                mMediaRecorder.setInputSurface(surface);
+            }
+
+            mMediaRecorder.prepare();
+
+            if (persistentSurface == null) {
+                surface = mMediaRecorder.getSurface();
+            }
+
+            Paint paint = new Paint();
+            paint.setTextSize(16);
+            paint.setColor(Color.RED);
+            int i;
+
+            /* Test: draw 10 frames at 30fps before start
+             * these should be dropped and not causing malformed stream.
+             */
+            for(i = 0; i < 10; i++) {
+                Canvas canvas = surface.lockCanvas(null);
+                int background = (i * 255 / 99);
+                canvas.drawARGB(255, background, background, background);
+                String text = "Frame #" + i;
+                canvas.drawText(text, 50, 50, paint);
+                surface.unlockCanvasAndPost(canvas);
+                Thread.sleep(sleepTimeMs);
+            }
+
+            Log.v(TAG, "start");
+            mMediaRecorder.start();
+
+            /* Test: draw another 90 frames at 30fps after start */
+            for(i = 10; i < 100; i++) {
+                Canvas canvas = surface.lockCanvas(null);
+                int background = (i * 255 / 99);
+                canvas.drawARGB(255, background, background, background);
+                String text = "Frame #" + i;
+                canvas.drawText(text, 50, 50, paint);
+                surface.unlockCanvasAndPost(canvas);
+                Thread.sleep(sleepTimeMs);
+            }
+
+            Log.v(TAG, "stop");
+            mMediaRecorder.stop();
+        } catch (Exception e) {
+            Log.v(TAG, "record video failed: " + e.toString());
+            return false;
+        } finally {
+            // We need to test persistent surface across multiple MediaRecorder
+            // instances, so must destroy mMediaRecorder here.
+            if (mMediaRecorder != null) {
+                mMediaRecorder.release();
+                mMediaRecorder = null;
+            }
+
+            // release surface if not using persistent surface
+            if (persistentSurface == null && surface != null) {
+                surface.release();
+                surface = null;
+            }
+        }
+        return true;
+    }
+
+    private boolean checkCaptureFps(String filename, int captureRate) {
+        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+
+        retriever.setDataSource(filename);
+
+        // verify capture rate meta key is present and correct
+        String captureFps = retriever.extractMetadata(
+                MediaMetadataRetriever.METADATA_KEY_CAPTURE_FRAMERATE);
+
+        if (captureFps == null) {
+            Log.d(TAG, "METADATA_KEY_CAPTURE_FRAMERATE is missing");
+            return false;
+        }
+
+        if (Math.abs(Float.parseFloat(captureFps) - captureRate) > 0.001) {
+            Log.d(TAG, "METADATA_KEY_CAPTURE_FRAMERATE is incorrect: "
+                    + captureFps + "vs. " + captureRate);
+            return false;
+        }
+
+        // verify other meta keys here if necessary
+        return true;
+    }
+
+    private boolean testRecordFromSurface(boolean persistent, boolean timelapse) {
+        Log.v(TAG, "testRecordFromSurface: " +
+                   "persistent=" + persistent + ", timelapse=" + timelapse);
+        boolean success = false;
+        Surface surface = null;
+        int noOfFailure = 0;
+        try {
+            if (persistent) {
+                surface = MediaCodec.createPersistentInputSurface();
+            }
+
+            for (int k = 0; k < 2; k++) {
+                String filename = (k == 0) ? OUTPUT_PATH : OUTPUT_PATH2;
+                boolean hasAudio = false;
+                int captureRate = 0;
+
+                if (timelapse) {
+                    // if timelapse/slow-mo, k chooses between low/high capture fps
+                    captureRate = (k == 0) ? TIME_LAPSE_FPS : SLOW_MOTION_FPS;
+                } else {
+                    // otherwise k chooses between no-audio and audio
+                    hasAudio = (k == 0) ? false : true;
+                }
+
+                if (hasAudio && (!hasMicrophone() || !hasAmrNb())) {
+                    // audio test waived if no audio support
+                    continue;
+                }
+
+                Log.v(TAG, "testRecordFromSurface - round " + k);
+                success = recordFromSurface(filename, captureRate, hasAudio, surface);
+                if (success) {
+                    checkTracksAndDuration(0, true /* hasVideo */, hasAudio, filename);
+
+                    // verify capture fps meta key
+                    if (timelapse && !checkCaptureFps(filename, captureRate)) {
+                        noOfFailure++;
+                    }
+                }
+                if (!success) {
+                    noOfFailure++;
+                }
+            }
+        } catch (Exception e) {
+            Log.v(TAG, e.toString());
+            noOfFailure++;
+        } finally {
+            if (surface != null) {
+                Log.v(TAG, "releasing persistent surface");
+                surface.release();
+                surface = null;
+            }
+        }
+        return (noOfFailure == 0);
+    }
+
+    // Test recording from surface source with/without audio)
+    public void testSurfaceRecording() {
+        assertTrue(testRecordFromSurface(false /* persistent */, false /* timelapse */));
+    }
+
+    // Test recording from persistent surface source with/without audio
+    public void testPersistentSurfaceRecording() {
+        assertTrue(testRecordFromSurface(true /* persistent */, false /* timelapse */));
+    }
+
+    // Test timelapse recording from surface without audio
+    public void testSurfaceRecordingTimeLapse() {
+        assertTrue(testRecordFromSurface(false /* persistent */, true /* timelapse */));
+    }
+
+    // Test timelapse recording from persisent surface without audio
+    public void testPersistentSurfaceRecordingTimeLapse() {
+        assertTrue(testRecordFromSurface(true /* persistent */, true /* timelapse */));
+    }
+
     private void recordMedia(long maxFileSize, File outFile) throws Exception {
         mMediaRecorder.setMaxFileSize(maxFileSize);
         mMediaRecorder.prepare();
diff --git a/tests/tests/media/src/android/media/cts/MediaSyncTest.java b/tests/tests/media/src/android/media/cts/MediaSyncTest.java
index 96bed7d..6f9e2a2 100644
--- a/tests/tests/media/src/android/media/cts/MediaSyncTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaSyncTest.java
@@ -31,6 +31,8 @@
 import android.media.MediaFormat;
 import android.media.MediaSync;
 import android.media.MediaTimestamp;
+import android.media.PlaybackParams;
+import android.media.SyncParams;
 import android.test.ActivityInstrumentationTestCase2;
 import android.util.Log;
 import android.view.Surface;
@@ -60,6 +62,7 @@
             R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_192kbps_44100hz;
     private final int APPLICATION_AUDIO_PERIOD_MS = 200;
     private final int TEST_MAX_SPEED = 2;
+    private static final float FLOAT_TOLERANCE = .00001f;
 
     private Context mContext;
     private Resources mResources;
@@ -151,12 +154,12 @@
     }
 
     /**
-     * Tests setPlaybackRate is handled correctly for wrong rate.
+     * Tests setPlaybackParams is handled correctly for wrong rate.
      */
-    public void testSetPlaybackRateFail() throws InterruptedException {
+    public void testSetPlaybackParamsFail() throws InterruptedException {
         final float rate = -1.0f;
         try {
-            mMediaSync.setPlaybackRate(rate, MediaSync.PLAYBACK_RATE_AUDIO_MODE_RESAMPLE);
+            mMediaSync.setPlaybackParams(new PlaybackParams().setSpeed(rate));
             fail("playback rate " + rate + " is not handled correctly");
         } catch (IllegalArgumentException e) {
         }
@@ -170,7 +173,7 @@
         mMediaSync.setAudioTrack(mAudioTrack);
 
         try {
-            mMediaSync.setPlaybackRate(rate, MediaSync.PLAYBACK_RATE_AUDIO_MODE_RESAMPLE);
+            mMediaSync.setPlaybackParams(new PlaybackParams().setSpeed(rate));
             fail("With audio track set, playback rate " + rate
                     + " is not handled correctly");
         } catch (IllegalArgumentException e) {
@@ -178,13 +181,15 @@
     }
 
     /**
-     * Tests setPlaybackRate is handled correctly for good rate without audio track set.
+     * Tests setPlaybackParams is handled correctly for good rate without audio track set.
      * The case for good rate with audio track set is tested in testPlaybackRate*.
      */
-    public void testSetPlaybackRateSucceed() throws InterruptedException {
+    public void testSetPlaybackParamsSucceed() throws InterruptedException {
         final float rate = (float)TEST_MAX_SPEED;
         try {
-            mMediaSync.setPlaybackRate(rate, MediaSync.PLAYBACK_RATE_AUDIO_MODE_RESAMPLE);
+            mMediaSync.setPlaybackParams(new PlaybackParams().setSpeed(rate));
+            PlaybackParams pbp = mMediaSync.getPlaybackParams();
+            assertEquals(rate, pbp.getSpeed(), FLOAT_TOLERANCE);
         } catch (IllegalArgumentException e) {
             fail("playback rate " + rate + " is not handled correctly");
         }
@@ -201,6 +206,9 @@
         }
     }
 
+    private PlaybackParams PAUSED_RATE = new PlaybackParams().setSpeed(0.f);
+    private PlaybackParams NORMAL_RATE = new PlaybackParams().setSpeed(1.f);
+
     private boolean runCheckAudioBuffer(int inputResourceId, int timeOutMs) {
         final int NUM_LOOPS = 10;
         final Object condition = new Object();
@@ -233,7 +241,7 @@
             }
         }, null);
 
-        mMediaSync.setPlaybackRate(1.0f, MediaSync.PLAYBACK_RATE_AUDIO_MODE_RESAMPLE);
+        mMediaSync.setPlaybackParams(NORMAL_RATE);
 
         synchronized (condition) {
             mDecoderAudio.start();
@@ -296,7 +304,7 @@
             }
         }, null);
 
-        mMediaSync.setPlaybackRate(0.0f, MediaSync.PLAYBACK_RATE_AUDIO_MODE_DEFAULT);
+        mMediaSync.setPlaybackParams(PAUSED_RATE);
 
         ByteBuffer buffer1 = ByteBuffer.allocate(BUFFER_SIZE);
         ByteBuffer buffer2 = ByteBuffer.allocate(BUFFER_SIZE);
@@ -305,7 +313,7 @@
         mMediaSync.queueAudio(buffer2, INDEX_AFTER_FLUSH, 0 /* presentationTimeUs */);
 
         synchronized (condition) {
-            mMediaSync.setPlaybackRate(1.0f, MediaSync.PLAYBACK_RATE_AUDIO_MODE_DEFAULT);
+            mMediaSync.setPlaybackParams(NORMAL_RATE);
 
             try {
                 condition.wait(timeOutMs);
@@ -438,7 +446,11 @@
             mHasAudio = true;
         }
 
-        mMediaSync.setPlaybackRate(playbackRate, MediaSync.PLAYBACK_RATE_AUDIO_MODE_RESAMPLE);
+        SyncParams sync = new SyncParams().allowDefaults();
+        mMediaSync.setSyncParams(sync);
+        sync = mMediaSync.getSyncParams();
+
+        mMediaSync.setPlaybackParams(new PlaybackParams().setSpeed(playbackRate));
 
         synchronized (conditionFirstAudioBuffer) {
             if (video) {
@@ -488,7 +500,10 @@
                     + ", play time is " + playTimeUs + " vs expected " + mediaDurationUs,
                     mediaDurationUs,
                     playTimeUs * playbackRate,
-                    mediaDurationUs * PLAYBACK_RATE_TOLERANCE_PERCENT / 100
+                    // sync.getTolerance() is MediaSync's tolerance of the playback rate, whereas
+                    // PLAYBACK_RATE_TOLERANCE_PERCENT / 100 is our test's tolerance.
+                    // We need to add both to get an upperbound for allowable error.
+                    mediaDurationUs * (sync.getTolerance() + PLAYBACK_RATE_TOLERANCE_PERCENT / 100)
                             + TIME_MEASUREMENT_TOLERANCE_US);
         }
 
diff --git a/tests/tests/media/src/android/media/cts/ParamsTest.java b/tests/tests/media/src/android/media/cts/ParamsTest.java
new file mode 100644
index 0000000..4e42004
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/ParamsTest.java
@@ -0,0 +1,351 @@
+/*
+ * 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.
+ */
+
+package android.media.cts;
+
+import com.android.cts.media.R;
+
+import android.media.PlaybackParams;
+import android.media.SyncParams;
+import android.test.AndroidTestCase;
+
+/**
+ * General Params tests.
+ *
+ * In particular, check Params objects' behavior.
+ */
+public class ParamsTest extends AndroidTestCase {
+    private static final String TAG = "ParamsTest";
+    private static final float FLOAT_TOLERANCE = .00001f;
+    private static final float MAX_DEFAULT_TOLERANCE = 1/24.f;
+
+    public void testSyncParamsConstants() {
+        assertEquals(0, SyncParams.SYNC_SOURCE_DEFAULT);
+        assertEquals(1, SyncParams.SYNC_SOURCE_SYSTEM_CLOCK);
+        assertEquals(2, SyncParams.SYNC_SOURCE_AUDIO);
+        assertEquals(3, SyncParams.SYNC_SOURCE_VSYNC);
+
+        assertEquals(0, SyncParams.AUDIO_ADJUST_MODE_DEFAULT);
+        assertEquals(1, SyncParams.AUDIO_ADJUST_MODE_STRETCH);
+        assertEquals(2, SyncParams.AUDIO_ADJUST_MODE_RESAMPLE);
+    }
+
+    public void testSyncParamsDefaults() {
+        SyncParams p = new SyncParams();
+        try { fail("got " + p.getAudioAdjustMode()); } catch (IllegalStateException e) {}
+        try { fail("got " + p.getSyncSource());      } catch (IllegalStateException e) {}
+        try { fail("got " + p.getTolerance());       } catch (IllegalStateException e) {}
+        try { fail("got " + p.getFrameRate());       } catch (IllegalStateException e) {}
+
+        SyncParams q = p.allowDefaults();
+        assertSame(p, q);
+        assertEquals(p.AUDIO_ADJUST_MODE_DEFAULT, p.getAudioAdjustMode());
+        assertEquals(p.SYNC_SOURCE_DEFAULT,       p.getSyncSource());
+        assertTrue(p.getTolerance() >= 0.f
+                && p.getTolerance() < MAX_DEFAULT_TOLERANCE + FLOAT_TOLERANCE);
+        try { fail("got " + p.getFrameRate());       } catch (IllegalStateException e) {}
+    }
+
+    public void testSyncParamsAudioAdjustMode() {
+        // setting this cannot fail
+        SyncParams p = new SyncParams();
+        for (int i : new int[] {
+                SyncParams.AUDIO_ADJUST_MODE_STRETCH,
+                SyncParams.AUDIO_ADJUST_MODE_RESAMPLE,
+                -1 /* invalid */}) {
+            SyncParams q = p.setAudioAdjustMode(i); // verify both initial set and update
+            assertSame(p, q);
+            assertEquals(i, p.getAudioAdjustMode());
+            try { fail("got " + p.getSyncSource());      } catch (IllegalStateException e) {}
+            try { fail("got " + p.getTolerance());       } catch (IllegalStateException e) {}
+            try { fail("got " + p.getFrameRate());       } catch (IllegalStateException e) {}
+        }
+    }
+
+    public void testSyncParamsSyncSource() {
+        // setting this cannot fail
+        SyncParams p = new SyncParams();
+        for (int i : new int[] {
+                SyncParams.SYNC_SOURCE_SYSTEM_CLOCK,
+                SyncParams.SYNC_SOURCE_AUDIO,
+                -1 /* invalid */}) {
+            SyncParams q = p.setSyncSource(i); // verify both initial set and update
+            assertSame(p, q);
+            try { fail("got " + p.getAudioAdjustMode()); } catch (IllegalStateException e) {}
+            assertEquals(i, p.getSyncSource());
+            try { fail("got " + p.getTolerance());       } catch (IllegalStateException e) {}
+            try { fail("got " + p.getFrameRate());       } catch (IllegalStateException e) {}
+        }
+    }
+
+    public void testSyncParamsTolerance() {
+        // this can fail on values not in [0, 1)
+
+        // test good values
+        SyncParams p = new SyncParams();
+        float lastValue = 2.f; /* some initial value to avoid compile error */
+        for (float f : new float[] { 0.f, .1f, .9999f }) {
+            SyncParams q = p.setTolerance(f); // verify both initial set and update
+            assertSame(p, q);
+            try { fail("got " + p.getAudioAdjustMode()); } catch (IllegalStateException e) {}
+            try { fail("got " + p.getSyncSource());      } catch (IllegalStateException e) {}
+            assertEquals(f, p.getTolerance(), FLOAT_TOLERANCE);
+            try { fail("got " + p.getFrameRate());       } catch (IllegalStateException e) {}
+            lastValue = f;
+        }
+
+        // test bad values - these should have no effect
+        boolean update = true;
+        for (float f : new float[] { -.0001f, 1.f }) {
+            try {
+                p.setTolerance(f);
+                fail("set tolerance to " + f);
+            } catch (IllegalArgumentException e) {}
+            try { fail("got " + p.getAudioAdjustMode()); } catch (IllegalStateException e) {}
+            try { fail("got " + p.getSyncSource());      } catch (IllegalStateException e) {}
+            if (update) {
+                // if updating, last value should remain
+                assertEquals(lastValue, p.getTolerance(), FLOAT_TOLERANCE);
+            } else {
+                // otherwise, it should remain undefined
+                try { fail("got " + p.getTolerance());       } catch (IllegalStateException e) {}
+            }
+            try { fail("got " + p.getFrameRate());       } catch (IllegalStateException e) {}
+
+            // no longer updating in subsequent iterations
+            p = new SyncParams();
+            update = false;
+        }
+    }
+
+    public void testSyncParamsFrameRate() {
+        // setting this cannot fail, but negative values may be normalized to some negative value
+        SyncParams p = new SyncParams();
+        for (float f : new float[] { 0.f, .0001f, 30.f, 300.f, -.0001f, -1.f }) {
+            SyncParams q = p.setFrameRate(f);
+            assertSame(p, q);
+            try { fail("got " + p.getAudioAdjustMode()); } catch (IllegalStateException e) {}
+            try { fail("got " + p.getSyncSource());      } catch (IllegalStateException e) {}
+            try { fail("got " + p.getTolerance());       } catch (IllegalStateException e) {}
+            if (f >= 0) {
+                assertEquals(f, p.getFrameRate(), FLOAT_TOLERANCE);
+            } else {
+                assertTrue(p.getFrameRate() < 0.f);
+            }
+        }
+    }
+
+    public void testSyncParamsMultipleSettings() {
+        {
+            SyncParams p = new SyncParams();
+            p.setAudioAdjustMode(p.AUDIO_ADJUST_MODE_STRETCH);
+            SyncParams q = p.setTolerance(.5f);
+            assertSame(p, q);
+
+            assertEquals(p.AUDIO_ADJUST_MODE_STRETCH, p.getAudioAdjustMode());
+            try { fail("got " + p.getSyncSource());      } catch (IllegalStateException e) {}
+            assertEquals(.5f, p.getTolerance(), FLOAT_TOLERANCE);
+            try { fail("got " + p.getFrameRate());       } catch (IllegalStateException e) {}
+
+            // allowDefaults should not change set values
+            q = p.allowDefaults();
+            assertSame(p, q);
+
+            assertEquals(p.AUDIO_ADJUST_MODE_STRETCH, p.getAudioAdjustMode());
+            assertEquals(p.SYNC_SOURCE_DEFAULT, p.getSyncSource());
+            assertEquals(.5f, p.getTolerance(), FLOAT_TOLERANCE);
+            try { fail("got " + p.getFrameRate());       } catch (IllegalStateException e) {}
+        }
+
+        {
+            SyncParams p = new SyncParams();
+            p.setSyncSource(p.SYNC_SOURCE_VSYNC);
+            SyncParams q = p.setFrameRate(25.f);
+            assertSame(p, q);
+
+            try { fail("got " + p.getAudioAdjustMode()); } catch (IllegalStateException e) {}
+            assertEquals(p.SYNC_SOURCE_VSYNC, p.getSyncSource());
+            try { fail("got " + p.getTolerance());       } catch (IllegalStateException e) {}
+            assertEquals(25.f, p.getFrameRate(), FLOAT_TOLERANCE);
+
+            // allowDefaults should not change set values
+            q = p.allowDefaults();
+            assertSame(p, q);
+
+            assertEquals(p.AUDIO_ADJUST_MODE_DEFAULT, p.getAudioAdjustMode());
+            assertEquals(p.SYNC_SOURCE_VSYNC, p.getSyncSource());
+            assertTrue(p.getTolerance() >= 0.f
+                    && p.getTolerance() < MAX_DEFAULT_TOLERANCE + FLOAT_TOLERANCE);
+            assertEquals(25.f, p.getFrameRate(), FLOAT_TOLERANCE);
+        }
+    }
+
+    public void testPlaybackParamsConstants() {
+        assertEquals(0, PlaybackParams.AUDIO_STRETCH_MODE_DEFAULT);
+        assertEquals(1, PlaybackParams.AUDIO_STRETCH_MODE_VOICE);
+
+        assertEquals(0, PlaybackParams.AUDIO_FALLBACK_MODE_DEFAULT);
+        assertEquals(1, PlaybackParams.AUDIO_FALLBACK_MODE_MUTE);
+        assertEquals(2, PlaybackParams.AUDIO_FALLBACK_MODE_FAIL);
+    }
+
+    public void testPlaybackParamsDefaults() {
+        PlaybackParams p = new PlaybackParams();
+        try { fail("got " + p.getAudioFallbackMode()); } catch (IllegalStateException e) {}
+        try { fail("got " + p.getAudioStretchMode());  } catch (IllegalStateException e) {}
+        try { fail("got " + p.getPitch());             } catch (IllegalStateException e) {}
+        try { fail("got " + p.getSpeed());             } catch (IllegalStateException e) {}
+
+        PlaybackParams q = p.allowDefaults();
+        assertSame(p, q);
+        assertEquals(p.AUDIO_FALLBACK_MODE_DEFAULT, p.getAudioFallbackMode());
+        assertEquals(p.AUDIO_STRETCH_MODE_DEFAULT,  p.getAudioStretchMode());
+        assertEquals(1.f, p.getPitch(), FLOAT_TOLERANCE);
+        assertEquals(1.f, p.getSpeed(), FLOAT_TOLERANCE);
+    }
+
+    public void testPlaybackParamsAudioFallbackMode() {
+        // setting this cannot fail
+        PlaybackParams p = new PlaybackParams();
+        for (int i : new int[] {
+                PlaybackParams.AUDIO_FALLBACK_MODE_MUTE,
+                PlaybackParams.AUDIO_FALLBACK_MODE_FAIL,
+                -1 /* invalid */}) {
+            PlaybackParams q = p.setAudioFallbackMode(i); // verify both initial set and update
+            assertSame(p, q);
+            assertEquals(i, p.getAudioFallbackMode());
+            try { fail("got " + p.getAudioStretchMode());  } catch (IllegalStateException e) {}
+            try { fail("got " + p.getPitch());             } catch (IllegalStateException e) {}
+            try { fail("got " + p.getSpeed());             } catch (IllegalStateException e) {}
+        }
+    }
+
+    public void testPlaybackParamsAudioStretchMode() {
+        // setting this cannot fail
+        PlaybackParams p = new PlaybackParams();
+        for (int i : new int[] {
+                PlaybackParams.AUDIO_STRETCH_MODE_DEFAULT,
+                PlaybackParams.AUDIO_STRETCH_MODE_VOICE,
+                -1 /* invalid */}) {
+            PlaybackParams q = p.setAudioStretchMode(i); // verify both initial set and update
+            assertSame(p, q);
+            try { fail("got " + p.getAudioFallbackMode()); } catch (IllegalStateException e) {}
+            assertEquals(i, p.getAudioStretchMode());
+            try { fail("got " + p.getPitch());             } catch (IllegalStateException e) {}
+            try { fail("got " + p.getSpeed());             } catch (IllegalStateException e) {}
+        }
+    }
+
+    public void testPlaybackParamsPitch() {
+        // this can fail on values not in [0, Inf)
+
+        // test good values
+        PlaybackParams p = new PlaybackParams();
+        float lastValue = 2.f; /* some initial value to avoid compile error */
+        for (float f : new float[] { 0.f, .1f, 9999.f }) {
+            PlaybackParams q = p.setPitch(f); // verify both initial set and update
+            assertSame(p, q);
+            try { fail("got " + p.getAudioFallbackMode()); } catch (IllegalStateException e) {}
+            try { fail("got " + p.getAudioStretchMode());  } catch (IllegalStateException e) {}
+            assertEquals(f, p.getPitch(), FLOAT_TOLERANCE);
+            try { fail("got " + p.getSpeed());             } catch (IllegalStateException e) {}
+            lastValue = f;
+        }
+
+        // test bad values - these should have no effect
+        boolean update = true;
+        for (float f : new float[] { -.0001f, -1.f }) {
+            try {
+                p.setPitch(f);
+                fail("set tolerance to " + f);
+            } catch (IllegalArgumentException e) {}
+            try { fail("got " + p.getAudioFallbackMode()); } catch (IllegalStateException e) {}
+            try { fail("got " + p.getAudioStretchMode());  } catch (IllegalStateException e) {}
+            if (update) {
+                // if updating, last value should remain
+                assertEquals(lastValue, p.getPitch(), FLOAT_TOLERANCE);
+            } else {
+                // otherwise, it should remain undefined
+                try { fail("got " + p.getPitch());             } catch (IllegalStateException e) {}
+            }
+            try { fail("got " + p.getSpeed());             } catch (IllegalStateException e) {}
+
+            // no longer updating in subsequent iterations
+            p = new PlaybackParams();
+            update = false;
+        }
+    }
+
+    public void testPlaybackParamsSpeed() {
+        // setting this cannot fail
+        PlaybackParams p = new PlaybackParams();
+        for (float f : new float[] { 0.f, .0001f, 30.f, 300.f, -.0001f, -1.f, -300.f }) {
+            PlaybackParams q = p.setSpeed(f);
+            assertSame(p, q);
+            try { fail("got " + p.getAudioFallbackMode()); } catch (IllegalStateException e) {}
+            try { fail("got " + p.getAudioStretchMode());  } catch (IllegalStateException e) {}
+            try { fail("got " + p.getPitch());             } catch (IllegalStateException e) {}
+            assertEquals(f, p.getSpeed(), FLOAT_TOLERANCE);
+        }
+    }
+
+    public void testPlaybackParamsMultipleSettings() {
+        {
+            PlaybackParams p = new PlaybackParams();
+            p.setAudioFallbackMode(p.AUDIO_FALLBACK_MODE_MUTE);
+            PlaybackParams q = p.setPitch(.5f);
+            assertSame(p, q);
+
+            assertEquals(p.AUDIO_FALLBACK_MODE_MUTE, p.getAudioFallbackMode());
+            try { fail("got " + p.getAudioStretchMode());  } catch (IllegalStateException e) {}
+            assertEquals(.5f, p.getPitch(), FLOAT_TOLERANCE);
+            try { fail("got " + p.getSpeed());             } catch (IllegalStateException e) {}
+
+            // allowDefaults should not change set values
+            q = p.allowDefaults();
+            assertSame(p, q);
+
+            assertEquals(p.AUDIO_FALLBACK_MODE_MUTE, p.getAudioFallbackMode());
+            assertEquals(p.AUDIO_STRETCH_MODE_DEFAULT, p.getAudioStretchMode());
+            assertEquals(.5f, p.getPitch(), FLOAT_TOLERANCE);
+            assertEquals(1.f, p.getSpeed(), FLOAT_TOLERANCE);
+        }
+
+        {
+            PlaybackParams p = new PlaybackParams();
+            p.setAudioStretchMode(p.AUDIO_STRETCH_MODE_VOICE);
+            PlaybackParams q = p.setSpeed(25.f);
+            assertSame(p, q);
+
+            try { fail("got " + p.getAudioFallbackMode()); } catch (IllegalStateException e) {}
+            assertEquals(p.AUDIO_STRETCH_MODE_VOICE, p.getAudioStretchMode());
+            try { fail("got " + p.getPitch());             } catch (IllegalStateException e) {}
+            assertEquals(25.f, p.getSpeed(), FLOAT_TOLERANCE);
+
+            // allowDefaults should not change set values
+            q = p.allowDefaults();
+            assertSame(p, q);
+
+            assertEquals(p.AUDIO_FALLBACK_MODE_DEFAULT, p.getAudioFallbackMode());
+            assertEquals(p.AUDIO_STRETCH_MODE_VOICE, p.getAudioStretchMode());
+            assertEquals(1.f, p.getPitch(), FLOAT_TOLERANCE);
+            assertEquals(25.f, p.getSpeed(), FLOAT_TOLERANCE);
+        }
+    }
+
+
+
+}
diff --git a/tests/tests/media/src/android/media/cts/ResourceManagerStubActivity.java b/tests/tests/media/src/android/media/cts/ResourceManagerStubActivity.java
new file mode 100644
index 0000000..214ced4
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/ResourceManagerStubActivity.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+package android.media.cts;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import junit.framework.Assert;
+
+public class ResourceManagerStubActivity extends Activity {
+    private static final String TAG = "ResourceManagerStubActivity";
+    private final Object mFinishEvent = new Object();
+    private int[] mRequestCodes = {0, 1};
+    private boolean[] mResults = {false, false};
+    private int mNumResults = 0;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        Log.d(TAG, "Activity " + requestCode + " finished.");
+        mResults[requestCode] = (resultCode == RESULT_OK);
+        if (++mNumResults == mResults.length) {
+            synchronized (mFinishEvent) {
+                mFinishEvent.notify();
+            }
+        }
+    }
+
+    public boolean testReclaimResource() throws InterruptedException {
+        Thread thread = new Thread() {
+            @Override
+            public void run() {
+                try {
+                    Context context = getApplicationContext();
+                    Intent intent1 = new Intent(context, ResourceManagerTestActivity1.class);
+                    startActivityForResult(intent1, mRequestCodes[0]);
+                    Thread.sleep(2000);  // wait for process to launch.
+
+                    Intent intent2 = new Intent(context, ResourceManagerTestActivity2.class);
+                    startActivityForResult(intent2, mRequestCodes[1]);
+
+                    synchronized (mFinishEvent) {
+                        mFinishEvent.wait();
+                    }
+                } catch(Exception e) {
+                    Log.d(TAG, "testReclaimResource got exception " + e.toString());
+                }
+            }
+        };
+        thread.start();
+        thread.join(10000);
+
+        for (int i = 0; i < mResults.length; ++i) {
+            Assert.assertTrue("Result from activity " + i + " is a fail.", mResults[i]);
+        }
+        return true;
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/ResourceManagerTest.java b/tests/tests/media/src/android/media/cts/ResourceManagerTest.java
new file mode 100644
index 0000000..5170aac
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/ResourceManagerTest.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+package android.media.cts;
+
+import android.os.Bundle;
+import android.test.ActivityInstrumentationTestCase2;
+
+public class ResourceManagerTest
+        extends ActivityInstrumentationTestCase2<ResourceManagerStubActivity> {
+
+    public ResourceManagerTest() {
+        super("com.android.cts.media", ResourceManagerStubActivity.class);
+    }
+
+    public void testReclaimResource() throws Exception {
+        Bundle extras = new Bundle();
+        ResourceManagerStubActivity activity = launchActivity(
+                "com.android.cts.media", ResourceManagerStubActivity.class, extras);
+        activity.testReclaimResource();
+        activity.finish();
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/ResourceManagerTestActivity1.java b/tests/tests/media/src/android/media/cts/ResourceManagerTestActivity1.java
new file mode 100644
index 0000000..aff3f03
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/ResourceManagerTestActivity1.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+package android.media.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+
+public class ResourceManagerTestActivity1 extends ResourceManagerTestActivityBase {
+    private static final int MAX_INSTANCES = 32;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        TAG = "ResourceManagerTestActivity1";
+
+        Log.d(TAG, "onCreate called.");
+        super.onCreate(savedInstanceState);
+        moveTaskToBack(true);
+
+        if (allocateCodecs(MAX_INSTANCES) == MAX_INSTANCES) {
+            // haven't reached the limit with MAX_INSTANCES, report RESULT_OK directly and
+            // skip additional test.
+            setResult(Activity.RESULT_OK);
+            finish();
+        }
+        useCodecs();
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/ResourceManagerTestActivity2.java b/tests/tests/media/src/android/media/cts/ResourceManagerTestActivity2.java
new file mode 100644
index 0000000..f4c57f5
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/ResourceManagerTestActivity2.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+package android.media.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+
+public class ResourceManagerTestActivity2 extends ResourceManagerTestActivityBase {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        TAG = "ResourceManagerTestActivity2";
+
+        Log.d(TAG, "onCreate called.");
+        super.onCreate(savedInstanceState);
+
+        if (allocateCodecs(1) == 1) {
+          setResult(Activity.RESULT_OK);
+          finish();
+        }
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/ResourceManagerTestActivityBase.java b/tests/tests/media/src/android/media/cts/ResourceManagerTestActivityBase.java
new file mode 100644
index 0000000..9c48fc4
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/ResourceManagerTestActivityBase.java
@@ -0,0 +1,176 @@
+/*
+ * 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.
+ */
+
+package android.media.cts;
+
+import android.app.Activity;
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecInfo.CodecCapabilities;
+import android.media.MediaCodecInfo.VideoCapabilities;
+import android.media.MediaCodecList;
+import android.media.MediaFormat;
+import android.os.Bundle;
+import android.util.Log;
+import java.io.IOException;
+import java.util.Vector;
+
+public class ResourceManagerTestActivityBase extends Activity {
+    protected String TAG;
+    private static final int IFRAME_INTERVAL = 10;  // 10 seconds between I-frames
+    private static final String MIME = MediaFormat.MIMETYPE_VIDEO_AVC;
+
+    private Vector<MediaCodec> mCodecs = new Vector<MediaCodec>();
+
+    private class TestCodecCallback extends MediaCodec.Callback {
+        @Override
+        public void onInputBufferAvailable(MediaCodec codec, int index) {
+            Log.d(TAG, "onInputBufferAvailable " + codec.toString());
+        }
+
+        @Override
+        public void onOutputBufferAvailable(
+                MediaCodec codec, int index, MediaCodec.BufferInfo info) {
+            Log.d(TAG, "onOutputBufferAvailable " + codec.toString());
+        }
+
+        @Override
+        public void onError(MediaCodec codec, MediaCodec.CodecException e) {
+            Log.d(TAG, "onError " + codec.toString() + " errorCode " + e.getErrorCode());
+        }
+
+        @Override
+        public void onOutputFormatChanged(MediaCodec codec, MediaFormat format) {
+            Log.d(TAG, "onOutputFormatChanged " + codec.toString());
+        }
+    }
+
+    private MediaCodec.Callback mCallback = new TestCodecCallback();
+
+    private static MediaFormat getTestFormat(VideoCapabilities vcaps) {
+        int maxWidth = vcaps.getSupportedWidths().getUpper();
+        int maxHeight = vcaps.getSupportedHeightsFor(maxWidth).getUpper();
+        int maxBitrate = vcaps.getBitrateRange().getUpper();
+        int maxFramerate = vcaps.getSupportedFrameRatesFor(maxWidth, maxHeight)
+                .getUpper().intValue();
+
+        MediaFormat format = MediaFormat.createVideoFormat(MIME, maxWidth, maxHeight);
+        format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
+                CodecCapabilities.COLOR_FormatYUV420Flexible);
+        format.setInteger(MediaFormat.KEY_BIT_RATE, maxBitrate);
+        format.setInteger(MediaFormat.KEY_FRAME_RATE, maxFramerate);
+        format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
+        return format;
+    }
+
+    private MediaCodecInfo getTestCodecInfo() {
+        // Use avc decoder for testing.
+        boolean isEncoder = false;
+
+        MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+        for (MediaCodecInfo info : mcl.getCodecInfos()) {
+            if (info.isEncoder() != isEncoder) {
+                continue;
+            }
+            CodecCapabilities caps;
+            try {
+                caps = info.getCapabilitiesForType(MIME);
+            } catch (IllegalArgumentException e) {
+                // mime is not supported
+                continue;
+            }
+            return info;
+        }
+
+        return null;
+    }
+
+    protected int allocateCodecs(int max) {
+        MediaCodecInfo info = getTestCodecInfo();
+        if (info == null) {
+            // skip the test
+            return 0;
+        }
+
+        String name = info.getName();
+        VideoCapabilities vcaps = info.getCapabilitiesForType(MIME).getVideoCapabilities();
+        MediaFormat format = getTestFormat(vcaps);
+        for (int i = 0; i < max; ++i) {
+            try {
+                Log.d(TAG, "Create codec " + name + " #" + i);
+                MediaCodec codec = MediaCodec.createByCodecName(name);
+                codec.setCallback(mCallback);
+                Log.d(TAG, "Configure codec " + format);
+                codec.configure(format, null, null, 0);
+                Log.d(TAG, "Start codec " + format);
+                codec.start();
+                mCodecs.add(codec);
+            } catch (IllegalArgumentException e) {
+                Log.d(TAG, "IllegalArgumentException " + e.getMessage());
+                break;
+            } catch (IOException e) {
+                Log.d(TAG, "IOException " + e.getMessage());
+                break;
+            } catch (MediaCodec.CodecException e) {
+                Log.d(TAG, "CodecException 0x" + Integer.toHexString(e.getErrorCode()));
+                break;
+            }
+        }
+
+        return mCodecs.size();
+    }
+
+    private void doUseCodecs() {
+        int current = 0;
+        try {
+            for (current = 0; current < mCodecs.size(); ++current) {
+                mCodecs.get(current).getName();
+            }
+        } catch (MediaCodec.CodecException e) {
+            Log.d(TAG, "useCodecs got CodecException 0x" + Integer.toHexString(e.getErrorCode()));
+            if (e.getErrorCode() == MediaCodec.CodecException.ERROR_RECLAIMED) {
+                Log.d(TAG, "Remove codec " + current + " from the list");
+                mCodecs.remove(current);
+                setResult(Activity.RESULT_OK);
+                finish();
+            }
+            return;
+        }
+    }
+
+    private Thread mWorkerThread;
+    protected void useCodecs() {
+        mWorkerThread = new Thread(new Runnable() {
+            @Override
+            public void run() {
+                while (true) {
+                    doUseCodecs();
+                }
+            }
+        });
+        mWorkerThread.start();
+    }
+
+    @Override
+    protected void onDestroy() {
+        Log.d(TAG, "onDestroy called.");
+        super.onDestroy();
+
+        for (int i = 0; i < mCodecs.size(); ++i) {
+            mCodecs.get(i).release();
+        }
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/RoutingTest.java b/tests/tests/media/src/android/media/cts/RoutingTest.java
new file mode 100644
index 0000000..fcb61dd
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/RoutingTest.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.cts;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+import android.media.AudioDeviceInfo;
+import android.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.AudioRecord;
+import android.media.AudioTrack;
+import android.media.MediaRecorder;
+
+import android.test.AndroidTestCase;
+
+import android.util.Log;
+
+/**
+ * TODO: Insert description here. (generated by pmclean)
+ */
+public class RoutingTest extends AndroidTestCase {
+    private static final String TAG = "RoutingTest";
+
+    private AudioManager mAudioManager;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        // get the AudioManager
+        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+        assertNotNull(mAudioManager);
+    }
+
+    public void test_audioTrack_preferredDevice() {
+        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT)) {
+            // Can't do it so skip this test
+            return;
+        }
+
+        int bufferSize =
+            AudioTrack.getMinBufferSize(
+                41000,
+                AudioFormat.CHANNEL_OUT_STEREO,
+                AudioFormat.ENCODING_PCM_16BIT);
+        AudioTrack audioTrack =
+            new AudioTrack(
+                AudioManager.STREAM_MUSIC,
+                41000,
+                AudioFormat.CHANNEL_OUT_STEREO,
+                AudioFormat.ENCODING_PCM_16BIT,
+                bufferSize,
+                AudioTrack.MODE_STREAM);
+        assertNotNull(audioTrack);
+
+        // None selected (new AudioTrack), so check for default
+        assertNull(audioTrack.getPreferredDevice());
+
+        // resets to default
+        assertTrue(audioTrack.setPreferredDevice(null));
+
+        // test each device
+        AudioDeviceInfo[] deviceList = mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
+        for(int index = 0; index < deviceList.length; index++) {
+            assertTrue(audioTrack.setPreferredDevice(deviceList[index]));
+            assertTrue(audioTrack.getPreferredDevice() == deviceList[index]);
+        }
+
+        // Check defaults again
+        assertTrue(audioTrack.setPreferredDevice(null));
+        assertNull(audioTrack.getPreferredDevice());
+    }
+
+    public void test_audioRecord_preferredDevice() {
+        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MICROPHONE)) {
+            // Can't do it so skip this test
+            return;
+        }
+
+        int bufferSize =
+            AudioRecord.getMinBufferSize(
+                41000,
+                AudioFormat.CHANNEL_OUT_DEFAULT,
+                AudioFormat.ENCODING_PCM_16BIT);
+        AudioRecord audioRecord =
+            new AudioRecord(
+                MediaRecorder.AudioSource.DEFAULT,
+                41000, AudioFormat.CHANNEL_OUT_DEFAULT,
+                AudioFormat.ENCODING_PCM_16BIT,
+                bufferSize);
+        assertNotNull(audioRecord);
+
+        // None selected (new AudioRecord), so check for default
+        assertNull(audioRecord.getPreferredDevice());
+
+        // resets to default
+        assertTrue(audioRecord.setPreferredDevice(null));
+
+        // test each device
+        AudioDeviceInfo[] deviceList = mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS);
+        for(int index = 0; index < deviceList.length; index++) {
+            assertTrue(audioRecord.setPreferredDevice(deviceList[index]));
+            assertTrue(audioRecord.getPreferredDevice() == deviceList[index]);
+        }
+
+        // Check defaults again
+        assertTrue(audioRecord.setPreferredDevice(null));
+        assertNull(audioRecord.getPreferredDevice());
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/SoundPoolTest.java b/tests/tests/media/src/android/media/cts/SoundPoolTest.java
index 15d18a0..23c4a7c 100644
--- a/tests/tests/media/src/android/media/cts/SoundPoolTest.java
+++ b/tests/tests/media/src/android/media/cts/SoundPoolTest.java
@@ -21,6 +21,7 @@
 
 import android.content.Context;
 import android.content.res.AssetFileDescriptor;
+import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.media.SoundPool;
 import android.test.AndroidTestCase;
@@ -29,6 +30,8 @@
 import java.io.FileDescriptor;
 import java.io.FileOutputStream;
 import java.io.InputStream;
+import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicInteger;
 
 abstract class SoundPoolTest extends AndroidTestCase {
 
@@ -230,6 +233,104 @@
         mSoundPool.release();
     }
 
+    public void testAutoPauseResume() throws Exception {
+        // The number of possible SoundPool streams simultaneously active is limited by
+        // track resources. Generally this is no greater than 32, but the actual
+        // amount may be less depending on concurrently running applications.
+        // Here we attempt to create more streams than what is normally possible;
+        // SoundPool should gracefully degrade to play those streams it can.
+        //
+        // Try to keep the maxStreams less than the number required to be active
+        // and certainly less than 20 to be cooperative to other applications.
+        final int TEST_STREAMS = 40;
+        SoundPool soundPool = null;
+        try {
+            soundPool = new SoundPool.Builder()
+                    .setAudioAttributes(new AudioAttributes.Builder().build())
+                    .setMaxStreams(TEST_STREAMS)
+                    .build();
+
+            // get our sounds
+            final int[] sounds = getSounds();
+
+            // set our completion listener
+            final int[] loadIds = new int[TEST_STREAMS];
+            final Object done = new Object();
+            final int[] loaded = new int[1]; // used as a "pointer" to an integer
+            final SoundPool fpool = soundPool; // final reference in scope of try block
+            soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
+                    @Override
+                    public void onLoadComplete(SoundPool pool, int sampleId, int status) {
+                        assertEquals(fpool, pool);
+                        assertEquals(0 /* success */, status);
+                        synchronized(done) {
+                            loadIds[loaded[0]++] = sampleId;
+                            if (loaded[0] == loadIds.length) {
+                                done.notify();
+                            }
+                        }
+                    }
+                });
+
+            // initiate loading
+            final int[] soundIds = new int[TEST_STREAMS];
+            for (int i = 0; i < soundIds.length; i++) {
+                soundIds[i] = soundPool.load(mContext, sounds[i % sounds.length], PRIORITY);
+            }
+
+            // wait for all sounds to load
+            final long LOAD_TIMEOUT_IN_MS = 10000;
+            final long startTime = System.currentTimeMillis();
+            synchronized(done) {
+                while (loaded[0] != soundIds.length) {
+                    final long waitTime =
+                            LOAD_TIMEOUT_IN_MS - (System.currentTimeMillis() - startTime);
+                    assertTrue(waitTime > 0);
+                    done.wait(waitTime);
+                }
+            }
+
+            // verify the Ids match (actually does sorting too)
+            Arrays.sort(loadIds);
+            Arrays.sort(soundIds);
+            assertTrue(Arrays.equals(loadIds, soundIds));
+
+            // play - should hear the following:
+            // 1 second of sound
+            // 1 second of silence
+            // 1 second of sound.
+            int[] streamIds = new int[soundIds.length];
+            for (int i = 0; i < soundIds.length; i++) {
+                streamIds[i] = soundPool.play(soundIds[i],
+                        0.5f /* leftVolume */, 0.5f /* rightVolume */, PRIORITY,
+                        -1 /* loop (infinite) */, 1.0f /* rate */);
+            }
+            Thread.sleep(1000 /* millis */);
+            soundPool.autoPause();
+            Thread.sleep(1000 /* millis */);
+            soundPool.autoResume();
+            Thread.sleep(1000 /* millis */);
+
+            // clean up
+            for (int stream : streamIds) {
+                assertTrue(stream != 0);
+                soundPool.stop(stream);
+            }
+            for (int sound : soundIds) {
+                assertEquals(true, soundPool.unload(sound));
+            }
+            // check to see we're really unloaded
+            for (int sound : soundIds) {
+                assertEquals(false, soundPool.unload(sound));
+            }
+        } finally {
+            if (soundPool != null) {
+                soundPool.release();
+                soundPool = null;
+            }
+        }
+    }
+
     /**
      * Load a sample and wait until it is ready to be played.
      * @return The sample ID.
diff --git a/tests/tests/media/src/android/media/cts/StubMediaBrowserService.java b/tests/tests/media/src/android/media/cts/StubMediaBrowserService.java
new file mode 100644
index 0000000..d559c72
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/StubMediaBrowserService.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.cts;
+
+import android.media.browse.MediaBrowser.MediaItem;
+import android.media.session.MediaSession;
+import android.os.Bundle;
+import android.service.media.MediaBrowserService;
+
+import java.util.List;
+
+/**
+ * Stub implementation of (@link android.service.media.MediaBrowserService}.
+ */
+public class StubMediaBrowserService extends MediaBrowserService {
+    static final String MEDIA_ID_ROOT = "test_media_id_root";
+    static final String EXTRAS_KEY = "test_extras_key";
+    static final String EXTRAS_VALUE = "test_extras_value";
+
+    /* package private */ static MediaSession sSession;
+    private Bundle mExtras;
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        sSession = new MediaSession(this, "MediaBrowserStubService");
+        setSessionToken(sSession.getSessionToken());
+    }
+
+    @Override
+    public BrowserRoot onGetRoot(String clientPackageName, int clientUid, Bundle rootHints) {
+        mExtras = new Bundle();
+        mExtras.putString(EXTRAS_KEY, EXTRAS_VALUE);
+        return new BrowserRoot(MEDIA_ID_ROOT, mExtras);
+    }
+
+    @Override
+    public void onLoadChildren(final String parentMediaId, final Result<List<MediaItem>> result) {
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/TestMediaDataSource.java b/tests/tests/media/src/android/media/cts/TestMediaDataSource.java
index 87b4c59..a10840b 100644
--- a/tests/tests/media/src/android/media/cts/TestMediaDataSource.java
+++ b/tests/tests/media/src/android/media/cts/TestMediaDataSource.java
@@ -28,7 +28,7 @@
 /**
  * A MediaDataSource that reads from a byte array for use in tests.
  */
-public class TestMediaDataSource implements MediaDataSource {
+public class TestMediaDataSource extends MediaDataSource {
     private static final String TAG = "TestMediaDataSource";
 
     private byte[] mData;
@@ -62,29 +62,30 @@
     }
 
     @Override
-    public synchronized int readAt(long offset, byte[] buffer, int size) {
+    public synchronized int readAt(long position, byte[] buffer, int offset, int size)
+            throws IOException {
         if (mThrowFromReadAt) {
-            throw new RuntimeException("Test exception from readAt()");
+            throw new IOException("Test exception from readAt()");
         }
         if (mReturnFromReadAt != null) {
             return mReturnFromReadAt;
         }
 
         // Clamp reads past the end of the source.
-        if (offset >= mData.length) {
-            return 0;
+        if (position >= mData.length) {
+            return -1; // -1 indicates EOF
         }
-        if (offset + size > mData.length) {
-            size -= (offset + size) - mData.length;
+        if (position + size > mData.length) {
+            size -= (position + size) - mData.length;
         }
-        System.arraycopy(mData, (int)offset, buffer, 0, size);
+        System.arraycopy(mData, (int)position, buffer, offset, size);
         return size;
     }
 
     @Override
-    public synchronized long getSize() {
+    public synchronized long getSize() throws IOException {
         if (mThrowFromGetSize) {
-            throw new RuntimeException("Test exception from getSize()");
+            throw new IOException("Test exception from getSize()");
         }
         if (mReturnFromGetSize != null) {
             return mReturnFromGetSize;
diff --git a/tests/tests/net/src/android/net/ipv6/cts/PingTest.java b/tests/tests/net/src/android/net/ipv6/cts/PingTest.java
index eddb416..c23ad30 100644
--- a/tests/tests/net/src/android/net/ipv6/cts/PingTest.java
+++ b/tests/tests/net/src/android/net/ipv6/cts/PingTest.java
@@ -155,7 +155,7 @@
     public void testLoopbackPing() throws ErrnoException, IOException {
         // Generate a random ping packet and send it to localhost.
         InetAddress ipv6Loopback = InetAddress.getByName(null);
-        assertEquals("localhost/::1", ipv6Loopback.toString());
+        assertEquals("::1", ipv6Loopback.getHostAddress());
 
         for (int i = 0; i < NUM_PACKETS; i++) {
             byte[] packet = pingPacket((int) (Math.random() * (MAX_SIZE - ICMP_HEADER_SIZE)));
diff --git a/tests/tests/os/jni/Android.mk b/tests/tests/os/jni/Android.mk
index dd3bb51..fab1ec2 100644
--- a/tests/tests/os/jni/Android.mk
+++ b/tests/tests/os/jni/Android.mk
@@ -27,7 +27,30 @@
 		android_os_cts_TaggedPointer.cpp \
 		android_os_cts_HardwareName.cpp \
 		android_os_cts_OSFeatures.cpp \
-		android_os_cts_NoExecutePermissionTest.cpp
+		android_os_cts_NoExecutePermissionTest.cpp \
+		android_os_cts_SeccompTest.cpp
+
+# Select the architectures on which seccomp-bpf are supported. This is used to
+# include extra test files that will not compile on architectures where it is
+# not supported.
+ARCH_SUPPORTS_SECCOMP := 0
+ifeq ($(strip $(TARGET_ARCH)),arm)
+	ARCH_SUPPORTS_SECCOMP = 1
+endif
+
+ifeq ($(strip $(TARGET_ARCH)),x86)
+	ARCH_SUPPORTS_SECCOMP = 1
+endif
+
+ifeq ($(strip $(TARGET_ARCH)),x86_64)
+	ARCH_SUPPORTS_SECCOMP = 1
+endif
+
+ifeq ($(ARCH_SUPPORTS_SECCOMP),1)
+	LOCAL_SRC_FILES += seccomp-tests/tests/seccomp_bpf_tests.c
+	# This define controls the behavior of OSFeatures.needsSeccompSupport().
+	LOCAL_CFLAGS += -DARCH_SUPPORTS_SECCOMP
+endif
 
 LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
 
diff --git a/tests/tests/os/jni/CtsOsJniOnLoad.cpp b/tests/tests/os/jni/CtsOsJniOnLoad.cpp
index e4a0dc0..cac750f 100644
--- a/tests/tests/os/jni/CtsOsJniOnLoad.cpp
+++ b/tests/tests/os/jni/CtsOsJniOnLoad.cpp
@@ -29,6 +29,8 @@
 
 extern int register_android_os_cts_NoExecutePermissionTest(JNIEnv*);
 
+extern int register_android_os_cts_SeccompTest(JNIEnv*);
+
 jint JNI_OnLoad(JavaVM *vm, void *reserved) {
     JNIEnv *env = NULL;
 
@@ -60,5 +62,9 @@
         return JNI_ERR;
     }
 
+    if (register_android_os_cts_SeccompTest(env)) {
+        return JNI_ERR;
+    }
+
     return JNI_VERSION_1_4;
 }
diff --git a/tests/tests/os/jni/android_os_cts_OSFeatures.cpp b/tests/tests/os/jni/android_os_cts_OSFeatures.cpp
index 2ee31b1..153fb27 100644
--- a/tests/tests/os/jni/android_os_cts_OSFeatures.cpp
+++ b/tests/tests/os/jni/android_os_cts_OSFeatures.cpp
@@ -84,8 +84,9 @@
 
 jboolean android_os_cts_OSFeatures_needsSeccompSupport(JNIEnv*, jobject)
 {
-#if !defined(__arm__) && !defined(__i386__) && !defined(__x86_64__)
+#if !defined(ARCH_SUPPORTS_SECCOMP)
     // Seccomp support is only available for ARM, x86, x86_64.
+    // This define is controlled by the Android.mk.
     return false;
 #endif
 
diff --git a/tests/tests/os/jni/android_os_cts_SeccompTest.cpp b/tests/tests/os/jni/android_os_cts_SeccompTest.cpp
new file mode 100644
index 0000000..cd1543d
--- /dev/null
+++ b/tests/tests/os/jni/android_os_cts_SeccompTest.cpp
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#include <android/log.h>
+#include <jni.h>
+#include <string.h>
+
+#include "seccomp-tests/tests/test_harness.h"
+
+// Forward declare from seccomp_bpf_tests.c.
+extern "C" {
+struct __test_metadata* get_seccomp_test_list();
+}
+
+static const char TAG[] = "SecompBpfTest-Native";
+
+jboolean android_security_cts_SeccompBpfTest_runKernelUnitTest(
+      JNIEnv* env, jobject thiz __unused, jstring name) {
+#if defined(ARCH_SUPPORTS_SECCOMP)
+    const char* nameStr = env->GetStringUTFChars(name, nullptr);
+
+    for (struct __test_metadata* t = get_seccomp_test_list(); t; t = t->next) {
+        if (strcmp(t->name, nameStr) == 0) {
+            __android_log_print(ANDROID_LOG_INFO, TAG, "Start: %s", t->name);
+            __run_test(t);
+            __android_log_print(ANDROID_LOG_INFO, TAG, "%s: %s",
+                t->passed ? "PASS" : "FAIL", t->name);
+            return t->passed;
+        }
+    }
+#endif  // ARCH_SUPPORTS_SECCOMP
+
+    return false;
+}
+
+static JNINativeMethod methods[] = {
+    { "runKernelUnitTest", "(Ljava/lang/String;)Z",
+        (void*)android_security_cts_SeccompBpfTest_runKernelUnitTest },
+};
+
+int register_android_os_cts_SeccompTest(JNIEnv* env) {
+    jclass clazz = env->FindClass("android/os/cts/SeccompTest");
+    return env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(JNINativeMethod));
+}
diff --git a/tests/tests/os/jni/seccomp-tests/LICENSE b/tests/tests/os/jni/seccomp-tests/LICENSE
new file mode 100644
index 0000000..b9e779f
--- /dev/null
+++ b/tests/tests/os/jni/seccomp-tests/LICENSE
@@ -0,0 +1,27 @@
+// Copyright 2014 The Chromium OS Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/tests/tests/os/jni/seccomp-tests/README b/tests/tests/os/jni/seccomp-tests/README
new file mode 100644
index 0000000..c8cd2ad
--- /dev/null
+++ b/tests/tests/os/jni/seccomp-tests/README
@@ -0,0 +1,4 @@
+seccomp
+-------
+
+Landing place for code relating to seccomp_filter work for the Linux kernel.
diff --git a/tests/tests/os/jni/seccomp-tests/README.android b/tests/tests/os/jni/seccomp-tests/README.android
new file mode 100644
index 0000000..4c5bb83
--- /dev/null
+++ b/tests/tests/os/jni/seccomp-tests/README.android
@@ -0,0 +1,13 @@
+This is the kernel unittest for seccomp-bpf sandboxing.
+
+URL: https://github.com/redpig/seccomp
+Revision: e65c79a14dc2bbb6d8dbf12ebf71905e2253a4b2
+License: BSD
+
+Local modifications:
+- Remove usage of pthread_cancel()
+- Use __android_log_print() instead of fprintf()
+- Rename main() to seccomp_test_main()
+- Add get_seccomp_test_list()
+
+The diff of modifications can be found in local-modifications-android.diff.
diff --git a/tests/tests/os/jni/seccomp-tests/local-modifications-android.diff b/tests/tests/os/jni/seccomp-tests/local-modifications-android.diff
new file mode 100644
index 0000000..288261a
--- /dev/null
+++ b/tests/tests/os/jni/seccomp-tests/local-modifications-android.diff
@@ -0,0 +1,59 @@
+diff --git a/tests/seccomp_bpf_tests.c b/tests/seccomp_bpf_tests.c
+index deb78d1..98b0231 100644
+--- a/tests/seccomp_bpf_tests.c
++++ b/tests/seccomp_bpf_tests.c
+@@ -1457,7 +1457,7 @@ FIXTURE_TEARDOWN(TSYNC) {
+ 		if (!s->tid)
+ 			continue;
+ 		if (pthread_kill(s->tid, 0)) {
+-			pthread_cancel(s->tid);
++			//pthread_cancel(s->tid);  // ANDROID
+ 			pthread_join(s->tid, &status);
+ 		}
+ 	}
+@@ -1940,4 +1940,10 @@ TEST(syscall_restart) {
+  * - ...
+  */
+ 
++// ANDROID:begin
++struct __test_metadata* get_seccomp_test_list() {
++  return __test_list;
++}
++// ANDROID:end
++
+ TEST_HARNESS_MAIN
+diff --git a/tests/test_harness.h b/tests/test_harness.h
+index 47ee027..597e40c 100644
+--- a/tests/test_harness.h
++++ b/tests/test_harness.h
+@@ -49,6 +49,8 @@
+ #include <sys/wait.h>
+ #include <unistd.h>
+ 
++#include <android/log.h>  // ANDROID
++
+ /* All exported functionality should be declared through this macro. */
+ #define TEST_API(x) _##x
+ 
+@@ -206,9 +208,11 @@
+ } while (0)
+ 
+ /* Unconditional logger for internal use. */
++// ANDROID:begin
+ #define __TH_LOG(fmt, ...) \
+-    fprintf(TH_LOG_STREAM, "%s:%d:%s:" fmt "\n", \
++    __android_log_print(ANDROID_LOG_ERROR, "SeccompBpfTest-KernelUnit", "%s:%d:%s:" fmt "\n", \
+             __FILE__, __LINE__, _metadata->name, ##__VA_ARGS__)
++// ANDROID:end
+ 
+ /* Defines the test function and creates the registration stub. */
+ #define _TEST(test_name) __TEST_IMPL(test_name, -1)
+@@ -292,7 +296,7 @@
+     if (!__constructor_order) \
+       __constructor_order = _CONSTRUCTOR_ORDER_BACKWARD; \
+   } \
+-  int main(int argc, char **argv) { return test_harness_run(argc, argv); }
++  int seccomp_test_main(int argc, char **argv) { return test_harness_run(argc, argv); }  // ANDROID
+ 
+ #define _ASSERT_EQ(_expected, _seen) \
+   __EXPECT(_expected, _seen, ==, 1)
diff --git a/tests/tests/os/jni/seccomp-tests/tests/.gitignore b/tests/tests/os/jni/seccomp-tests/tests/.gitignore
new file mode 100644
index 0000000..cdfc7c6
--- /dev/null
+++ b/tests/tests/os/jni/seccomp-tests/tests/.gitignore
@@ -0,0 +1,3 @@
+sigsegv
+resumption
+seccomp_bpf_tests
diff --git a/tests/tests/os/jni/seccomp-tests/tests/Makefile b/tests/tests/os/jni/seccomp-tests/tests/Makefile
new file mode 100644
index 0000000..88994b3
--- /dev/null
+++ b/tests/tests/os/jni/seccomp-tests/tests/Makefile
@@ -0,0 +1,23 @@
+CFLAGS += -Wall
+EXEC=resumption seccomp_bpf_tests sigsegv
+
+all: $(EXEC)
+
+clean:
+	rm -f $(EXEC)
+
+seccomp_bpf_tests: seccomp_bpf_tests.c test_harness.h
+	$(CC) seccomp_bpf_tests.c -o seccomp_bpf_tests $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -pthread
+
+resumption: resumption.c test_harness.h
+	$(CC) $^ -o $@ $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -ggdb3
+
+sigsegv: sigsegv.c test_harness.h
+	$(CC) $^ -o $@ $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -ggdb3
+
+run_tests: $(EXEC)
+	./seccomp_bpf_tests
+	./resumption
+	./sigsegv
+
+.PHONY: clean run_tests
diff --git a/tests/tests/os/jni/seccomp-tests/tests/resumption.c b/tests/tests/os/jni/seccomp-tests/tests/resumption.c
new file mode 100644
index 0000000..41795c0
--- /dev/null
+++ b/tests/tests/os/jni/seccomp-tests/tests/resumption.c
@@ -0,0 +1,217 @@
+/* seccomp_bpf_tests.c
+ * Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Test code for seccomp bpf.
+ */
+
+#include <asm/siginfo.h>
+#define __have_siginfo_t 1
+#define __have_sigval_t 1
+#define __have_sigevent_t 1
+
+#include <linux/filter.h>
+#include <sys/prctl.h>
+#include <linux/prctl.h>
+#include <linux/seccomp.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <string.h>
+#include <syscall.h>
+#define __USE_GNU 1
+#include <sys/ucontext.h>
+#include <sys/mman.h>
+
+#include "test_harness.h"
+
+#ifndef PR_SET_NO_NEW_PRIVS
+#define PR_SET_NO_NEW_PRIVS 38
+#define PR_GET_NO_NEW_PRIVS 39
+#endif
+
+#if defined(__i386__)
+#define REG_IP	REG_EIP
+#define REG_SP	REG_ESP
+#define REG_RESULT	REG_EAX
+#define REG_SYSCALL	REG_EAX
+#define REG_ARG0	REG_EBX
+#define REG_ARG1	REG_ECX
+#define REG_ARG2	REG_EDX
+#define REG_ARG3	REG_ESI
+#define REG_ARG4	REG_EDI
+#define REG_ARG5	REG_EBP
+#elif defined(__x86_64__)
+#define REG_IP	REG_RIP
+#define REG_SP	REG_RSP
+#define REG_RESULT	REG_RAX
+#define REG_SYSCALL	REG_RAX
+#define REG_ARG0	REG_RDI
+#define REG_ARG1	REG_RSI
+#define REG_ARG2	REG_RDX
+#define REG_ARG3	REG_R10
+#define REG_ARG4	REG_R8
+#define REG_ARG5	REG_R9
+#endif
+
+FIXTURE_DATA(TRAP) {
+	struct sock_fprog prog;
+};
+
+/* XXX: will need one per arch, etc.
+ *      thankfully _arch can tell us the calling convention!
+ */
+extern void *thunk_ip;	/* label for the instruction _after_ syscall */
+static void syscall_thunk(void)
+{
+	asm("syscall; thunk_ip:");
+}
+
+static time_t vsyscall_time(time_t *p)
+{
+	register time_t t asm ("rax");
+	__attribute__((unused)) register time_t *p1 asm ("rdi") = p;
+	__asm__("call 0xffffffffff600400 \n");
+	return t;
+}
+
+
+#if 0
+/* For instance, we could jump here instead. */
+static void compat_thunk(void)
+{
+	asm("int 0x80");
+}
+#endif
+
+FIXTURE_SETUP(TRAP) {
+	/* instruction after the syscall. Will be arch specific, of course. */
+	unsigned long thunk_addr = (unsigned long)&thunk_ip;
+	TH_LOG("Thunk: 0x%lX\n", thunk_addr);
+	{
+		struct sock_filter filter[] = {
+			BPF_STMT(BPF_LD+BPF_W+BPF_ABS,
+				offsetof(struct seccomp_data, nr)),
+			/* Whitelist anything you might need in the sigaction */
+#ifdef __NR_sigreturn
+			BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_sigreturn, 3, 0),
+#endif
+			BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_exit, 2, 0),
+			BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_rt_sigreturn, 1, 0),
+			/* Allow __NR_write so easy logging. */
+			BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_write, 0, 1),
+			BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
+			/* Check if we're within the thunk. */
+			BPF_STMT(BPF_LD+BPF_W+BPF_ABS,
+				offsetof(struct seccomp_data, instruction_pointer)),
+			/* XXX: make this 32-bit friendly. */
+			BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ((__u32*)&thunk_addr)[0], 0, 3),
+			BPF_STMT(BPF_LD+BPF_W+BPF_ABS,
+				offsetof(struct seccomp_data, instruction_pointer)+sizeof(int)),
+			BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ((__u32*)&thunk_addr)[1], 0, 1),
+			BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
+			BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_TRAP),
+		};
+		memset(&self->prog, 0, sizeof(self->prog));
+		self->prog.filter = malloc(sizeof(filter));
+		ASSERT_NE(NULL, self->prog.filter);
+		memcpy(self->prog.filter, filter, sizeof(filter));
+		self->prog.len = (unsigned short)(sizeof(filter)/sizeof(filter[0]));
+	}
+}
+
+FIXTURE_TEARDOWN(TRAP) {
+	if (self->prog.filter)
+		free(self->prog.filter);
+};
+
+struct arch_sigsys {
+		void *_call_addr; /* calling user insn */
+		int _syscall;	/* triggering system call number */
+		unsigned int _arch;	/* AUDIT_ARCH_* of syscall */
+};
+
+static void TRAP_action(int nr, siginfo_t *info, void *void_context)
+{
+	ucontext_t *ctx = (ucontext_t *)void_context;
+	char buf[256];
+	int len;
+	int do_ret = 1;
+	struct arch_sigsys *sys = (struct arch_sigsys *)
+#ifdef si_syscall
+		&(info->si_call_addr);
+#else
+		&(info->si_pid);
+#endif
+
+	if (info->si_code != SYS_SECCOMP)
+		return;
+	if (!ctx)
+		return;
+	len = snprintf(buf, sizeof(buf),
+			"@0x%lX:%X:%d:0x%lX:0x%lX:0x%lX:0x%lX:0x%lX:0x%lX\n",
+			(unsigned long)sys->_call_addr,
+			sys->_arch,
+			sys->_syscall,
+			(unsigned long)ctx->uc_mcontext.gregs[REG_ARG0],
+			(unsigned long)ctx->uc_mcontext.gregs[REG_ARG1],
+			(unsigned long)ctx->uc_mcontext.gregs[REG_ARG2],
+			(unsigned long)ctx->uc_mcontext.gregs[REG_ARG3],
+			(unsigned long)ctx->uc_mcontext.gregs[REG_ARG4],
+			(unsigned long)ctx->uc_mcontext.gregs[REG_ARG5]);
+	/* Send the soft-fail to our "listener" */
+	syscall(__NR_write, STDOUT_FILENO, buf, len);
+	if (ctx->uc_mcontext.gregs[REG_IP] >= 0xffffffffff600000ULL &&
+	    ctx->uc_mcontext.gregs[REG_IP] < 0xffffffffff601000ULL)
+		do_ret = 0;
+	if (do_ret) {
+		/* push [REG_IP] */
+		ctx->uc_mcontext.gregs[REG_SP] -= sizeof(unsigned long);
+		*((unsigned long *)ctx->uc_mcontext.gregs[REG_SP]) =
+		    ctx->uc_mcontext.gregs[REG_IP];
+	}
+	/* jmp syscall_thunk */
+	ctx->uc_mcontext.gregs[REG_IP] = (unsigned long)syscall_thunk;
+	return;
+}
+
+TEST_F(TRAP, handler) {
+	int ret;
+	struct sigaction act;
+	pid_t pid;
+	sigset_t mask;
+	memset(&act, 0, sizeof(act));
+	sigemptyset(&mask);
+	sigaddset(&mask, SIGSYS);
+
+	act.sa_sigaction = &TRAP_action;
+	act.sa_flags = SA_SIGINFO;
+	ret = sigaction(SIGSYS, &act, NULL);
+	ASSERT_EQ(0, ret) {
+		TH_LOG("sigaction failed");
+	}
+	ret = sigprocmask(SIG_UNBLOCK, &mask, NULL);
+	ASSERT_EQ(0, ret) {
+		TH_LOG("sigprocmask failed");
+	}
+
+	/* Get the pid to compare against. */
+	pid = getpid();
+
+	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog);
+	ASSERT_EQ(0, ret);
+
+	/* Call anything! */
+	ret = syscall(__NR_getpid);
+	ASSERT_EQ(pid, ret);
+	ret = syscall(__NR_close, 0);
+	ASSERT_EQ(0, ret);
+	ret = syscall(__NR_close, 0);
+	ASSERT_EQ(-1, ret);
+	printf("The time is %ld\n", vsyscall_time(NULL));
+	ASSERT_LT(0, vsyscall_time(NULL));
+}
+
+TEST_HARNESS_MAIN
diff --git a/tests/tests/os/jni/seccomp-tests/tests/seccomp_bpf_tests.c b/tests/tests/os/jni/seccomp-tests/tests/seccomp_bpf_tests.c
new file mode 100644
index 0000000..98b0231
--- /dev/null
+++ b/tests/tests/os/jni/seccomp-tests/tests/seccomp_bpf_tests.c
@@ -0,0 +1,1949 @@
+/* seccomp_bpf_tests.c
+ * Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Test code for seccomp bpf.
+ */
+
+#include <asm/siginfo.h>
+#define __have_siginfo_t 1
+#define __have_sigval_t 1
+#define __have_sigevent_t 1
+
+#include <errno.h>
+#include <linux/filter.h>
+#include <sys/prctl.h>
+#include <sys/ptrace.h>
+#include <sys/user.h>
+#include <linux/prctl.h>
+#include <linux/ptrace.h>
+#include <linux/seccomp.h>
+#include <poll.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <string.h>
+#include <linux/elf.h>
+#include <sys/uio.h>
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <sys/syscall.h>
+
+#include "test_harness.h"
+
+#ifndef PR_SET_PTRACER
+# define PR_SET_PTRACER 0x59616d61
+#endif
+
+#ifndef PR_SET_NO_NEW_PRIVS
+#define PR_SET_NO_NEW_PRIVS 38
+#define PR_GET_NO_NEW_PRIVS 39
+#endif
+
+#ifndef PR_SECCOMP_EXT
+#define PR_SECCOMP_EXT 43
+#endif
+
+#ifndef SECCOMP_EXT_ACT
+#define SECCOMP_EXT_ACT 1
+#endif
+
+#ifndef SECCOMP_EXT_ACT_TSYNC
+#define SECCOMP_EXT_ACT_TSYNC 1
+#endif
+
+#ifndef SECCOMP_MODE_STRICT
+#define SECCOMP_MODE_STRICT 1
+#endif
+
+#ifndef SECCOMP_MODE_FILTER
+#define SECCOMP_MODE_FILTER 2
+#endif
+
+#ifndef SECCOMP_RET_KILL
+#define SECCOMP_RET_KILL        0x00000000U // kill the task immediately
+#define SECCOMP_RET_TRAP        0x00030000U // disallow and force a SIGSYS
+#define SECCOMP_RET_ERRNO       0x00050000U // returns an errno
+#define SECCOMP_RET_TRACE       0x7ff00000U // pass to a tracer or disallow
+#define SECCOMP_RET_ALLOW       0x7fff0000U // allow
+
+/* Masks for the return value sections. */
+#define SECCOMP_RET_ACTION      0x7fff0000U
+#define SECCOMP_RET_DATA        0x0000ffffU
+
+struct seccomp_data {
+	int nr;
+	__u32 arch;
+	__u64 instruction_pointer;
+	__u64 args[6];
+};
+#endif
+
+#define syscall_arg(_n) (offsetof(struct seccomp_data, args[_n]))
+
+#define SIBLING_EXIT_UNKILLED	0xbadbeef
+#define SIBLING_EXIT_FAILURE	0xbadface
+#define SIBLING_EXIT_NEWPRIVS	0xbadfeed
+
+TEST(mode_strict_support) {
+	long ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT, NULL, NULL, NULL);
+	ASSERT_EQ(0, ret) {
+		TH_LOG("Kernel does not support CONFIG_SECCOMP");
+	}
+	syscall(__NR_exit, 1);
+}
+
+TEST_SIGNAL(mode_strict_cannot_call_prctl, SIGKILL) {
+	long ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT, NULL, NULL, NULL);
+	ASSERT_EQ(0, ret) {
+		TH_LOG("Kernel does not support CONFIG_SECCOMP");
+	}
+	syscall(__NR_prctl, PR_SET_SECCOMP, SECCOMP_MODE_FILTER, NULL, NULL, NULL);
+	EXPECT_FALSE(true) {
+		TH_LOG("Unreachable!");
+	}
+}
+
+/* Note! This doesn't test no new privs behavior */
+TEST(no_new_privs_support) {
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	EXPECT_EQ(0, ret) {
+		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
+	}
+}
+
+/* Tests kernel support by checking for a copy_from_user() fault on * NULL. */
+TEST(mode_filter_support) {
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, NULL, 0, 0);
+	ASSERT_EQ(0, ret) {
+		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
+	}
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, NULL, NULL, NULL);
+	EXPECT_EQ(-1, ret);
+	EXPECT_EQ(EFAULT, errno) {
+		TH_LOG("Kernel does not support CONFIG_SECCOMP_FILTER!");
+	}
+}
+
+TEST(mode_filter_without_nnp) {
+	struct sock_filter filter[] = {
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+	};
+	struct sock_fprog prog = {
+		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
+		.filter = filter,
+	};
+	long ret = prctl(PR_GET_NO_NEW_PRIVS, 0, NULL, 0, 0);
+	ASSERT_LE(0, ret) {
+		TH_LOG("Expected 0 or unsupported for NO_NEW_PRIVS");
+	}
+	errno = 0;
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
+	/* Succeeds with CAP_SYS_ADMIN, fails without */
+	/* TODO(wad) check caps not euid */
+	if (geteuid()) {
+		EXPECT_EQ(-1, ret);
+		EXPECT_EQ(EACCES, errno);
+	} else {
+		EXPECT_EQ(0, ret);
+	}
+}
+
+#define MAX_INSNS_PER_PATH 32768
+
+TEST(filter_size_limits) {
+	int i;
+	int count = BPF_MAXINSNS + 1;
+	struct sock_filter allow[] = {
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+	};
+	struct sock_filter *filter;
+	struct sock_fprog prog = { };
+
+	filter = calloc(count, sizeof(*filter));
+	ASSERT_NE(NULL, filter);
+
+	for (i = 0; i < count; i++) {
+		filter[i] = allow[0];
+	}
+
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	prog.filter = filter;
+	prog.len = count;
+
+	/* Too many filter instructions in a single filter. */
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
+	ASSERT_NE(0, ret) {
+		TH_LOG("Installing %d insn filter was allowed", prog.len);
+	}
+
+	/* One less is okay, though. */
+	prog.len -= 1;
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
+	ASSERT_EQ(0, ret) {
+		TH_LOG("Installing %d insn filter wasn't allowed", prog.len);
+	}
+}
+
+TEST(filter_chain_limits) {
+	int i;
+	int count = BPF_MAXINSNS;
+	struct sock_filter allow[] = {
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+	};
+	struct sock_filter *filter;
+	struct sock_fprog prog = { };
+
+	filter = calloc(count, sizeof(*filter));
+	ASSERT_NE(NULL, filter);
+
+	for (i = 0; i < count; i++) {
+		filter[i] = allow[0];
+	}
+
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	prog.filter = filter;
+	prog.len = 1;
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	prog.len = count;
+
+	/* Too many total filter instructions. */
+	for (i = 0; i < MAX_INSNS_PER_PATH; i++) {
+		ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
+		if (ret != 0)
+			break;
+	}
+	ASSERT_NE(0, ret) {
+		TH_LOG("Allowed %d %d-insn filters (total with penalties:%d)",
+		       i, count, i * (count + 4));
+	}
+}
+
+TEST(mode_filter_cannot_move_to_strict) {
+	struct sock_filter filter[] = {
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+	};
+	struct sock_fprog prog = {
+		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
+		.filter = filter,
+	};
+
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT, NULL, 0, 0);
+	EXPECT_EQ(-1, ret);
+	EXPECT_EQ(EINVAL, errno);
+}
+
+
+TEST(mode_filter_get_seccomp) {
+	struct sock_filter filter[] = {
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+	};
+	struct sock_fprog prog = {
+		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
+		.filter = filter,
+	};
+
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_GET_SECCOMP, 0, 0, 0, 0);
+	EXPECT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_GET_SECCOMP, 0, 0, 0, 0);
+	EXPECT_EQ(2, ret);
+}
+
+
+TEST(ALLOW_all) {
+	struct sock_filter filter[] = {
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+	};
+	struct sock_fprog prog = {
+		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
+		.filter = filter,
+	};
+
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
+	ASSERT_EQ(0, ret);
+}
+
+TEST(empty_prog) {
+	struct sock_filter filter[] = {
+	};
+	struct sock_fprog prog = {
+		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
+		.filter = filter,
+	};
+
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
+	EXPECT_EQ(-1, ret);
+	EXPECT_EQ(EINVAL, errno);
+}
+
+TEST_SIGNAL(unknown_ret_is_kill_inside, SIGSYS) {
+	struct sock_filter filter[] = {
+		BPF_STMT(BPF_RET|BPF_K, 0x10000000U),
+	};
+	struct sock_fprog prog = {
+		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
+		.filter = filter,
+	};
+
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
+	ASSERT_EQ(0, ret);
+	EXPECT_EQ(0, syscall(__NR_getpid)) {
+		TH_LOG("getpid() shouldn't ever return");
+	}
+}
+
+/* return code >= 0x80000000 is unused. */
+TEST_SIGNAL(unknown_ret_is_kill_above_allow, SIGSYS) {
+	struct sock_filter filter[] = {
+		BPF_STMT(BPF_RET|BPF_K, 0x90000000U),
+	};
+	struct sock_fprog prog = {
+		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
+		.filter = filter,
+	};
+
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
+	ASSERT_EQ(0, ret);
+	EXPECT_EQ(0, syscall(__NR_getpid)) {
+		TH_LOG("getpid() shouldn't ever return");
+	}
+}
+
+TEST_SIGNAL(KILL_all, SIGSYS) {
+	struct sock_filter filter[] = {
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
+	};
+	struct sock_fprog prog = {
+		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
+		.filter = filter,
+	};
+
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
+	ASSERT_EQ(0, ret);
+}
+
+TEST_SIGNAL(KILL_one, SIGSYS) {
+	struct sock_filter filter[] = {
+		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
+			offsetof(struct seccomp_data, nr)),
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 0, 1),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+	};
+	struct sock_fprog prog = {
+		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
+		.filter = filter,
+	};
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	pid_t parent = getppid();
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
+	ASSERT_EQ(0, ret);
+
+	EXPECT_EQ(parent, syscall(__NR_getppid));
+	/* getpid() should never return. */
+	EXPECT_EQ(0, syscall(__NR_getpid));
+}
+
+TEST_SIGNAL(KILL_one_arg_one, SIGSYS) {
+	struct sock_filter filter[] = {
+		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
+			offsetof(struct seccomp_data, nr)),
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+		/* Only both with lower 32-bit for now. */
+		BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_arg(0)),
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0x0C0FFEE, 0, 1),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+	};
+	struct sock_fprog prog = {
+		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
+		.filter = filter,
+	};
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	pid_t parent = getppid();
+	pid_t pid = getpid();
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
+	ASSERT_EQ(0, ret);
+
+	EXPECT_EQ(parent, syscall(__NR_getppid));
+	EXPECT_EQ(pid, syscall(__NR_getpid));
+	/* getpid() should never return. */
+	EXPECT_EQ(0, syscall(__NR_getpid, 0x0C0FFEE));
+}
+
+TEST_SIGNAL(KILL_one_arg_six, SIGSYS) {
+	struct sock_filter filter[] = {
+		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
+			offsetof(struct seccomp_data, nr)),
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+		/* Only both with lower 32-bit for now. */
+		BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_arg(5)),
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0x0C0FFEE, 0, 1),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+	};
+	struct sock_fprog prog = {
+		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
+		.filter = filter,
+	};
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	pid_t parent = getppid();
+	pid_t pid = getpid();
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
+	ASSERT_EQ(0, ret);
+
+	EXPECT_EQ(parent, syscall(__NR_getppid));
+	EXPECT_EQ(pid, syscall(__NR_getpid));
+	/* getpid() should never return. */
+	EXPECT_EQ(0, syscall(__NR_getpid, 1, 2, 3, 4, 5, 0x0C0FFEE));
+}
+
+/* TODO(wad) add 64-bit versus 32-bit arg tests. */
+
+TEST(arg_out_of_range) {
+	struct sock_filter filter[] = {
+		BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_arg(6)),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+	};
+	struct sock_fprog prog = {
+		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
+		.filter = filter,
+	};
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
+	EXPECT_EQ(-1, ret);
+	EXPECT_EQ(EINVAL, errno);
+}
+
+TEST(ERRNO_one) {
+	struct sock_filter filter[] = {
+		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
+			offsetof(struct seccomp_data, nr)),
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | E2BIG),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+	};
+	struct sock_fprog prog = {
+		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
+		.filter = filter,
+	};
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	pid_t parent = getppid();
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
+	ASSERT_EQ(0, ret);
+
+	EXPECT_EQ(parent, syscall(__NR_getppid));
+	EXPECT_EQ(-1, read(0, NULL, 0));
+	EXPECT_EQ(E2BIG, errno);
+}
+
+TEST(ERRNO_one_ok) {
+	struct sock_filter filter[] = {
+		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
+			offsetof(struct seccomp_data, nr)),
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | 0),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+	};
+	struct sock_fprog prog = {
+		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
+		.filter = filter,
+	};
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	pid_t parent = getppid();
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
+	ASSERT_EQ(0, ret);
+
+	EXPECT_EQ(parent, syscall(__NR_getppid));
+	/* "errno" of 0 is ok. */
+	EXPECT_EQ(0, read(0, NULL, 0));
+}
+
+FIXTURE_DATA(TRAP) {
+	struct sock_fprog prog;
+};
+
+FIXTURE_SETUP(TRAP) {
+	struct sock_filter filter[] = {
+		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
+			offsetof(struct seccomp_data, nr)),
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 0, 1),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRAP),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+	};
+	memset(&self->prog, 0, sizeof(self->prog));
+	self->prog.filter = malloc(sizeof(filter));
+	ASSERT_NE(NULL, self->prog.filter);
+	memcpy(self->prog.filter, filter, sizeof(filter));
+	self->prog.len = (unsigned short)(sizeof(filter)/sizeof(filter[0]));
+}
+
+FIXTURE_TEARDOWN(TRAP) {
+	if (self->prog.filter)
+		free(self->prog.filter);
+};
+
+TEST_F_SIGNAL(TRAP, dfl, SIGSYS) {
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog);
+	ASSERT_EQ(0, ret);
+	syscall(__NR_getpid);
+}
+
+/* Ensure that SIGSYS overrides SIG_IGN */
+TEST_F_SIGNAL(TRAP, ign, SIGSYS) {
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	signal(SIGSYS, SIG_IGN);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog);
+	ASSERT_EQ(0, ret);
+	syscall(__NR_getpid);
+}
+
+static struct siginfo TRAP_info;
+static volatile int TRAP_nr;
+static void TRAP_action(int nr, siginfo_t *info, void *void_context)
+{
+	memcpy(&TRAP_info, info, sizeof(TRAP_info));
+	TRAP_nr = nr;
+	return;
+}
+
+TEST_F(TRAP, handler) {
+	int ret, test;
+	struct sigaction act;
+	sigset_t mask;
+	memset(&act, 0, sizeof(act));
+	sigemptyset(&mask);
+	sigaddset(&mask, SIGSYS);
+
+	act.sa_sigaction = &TRAP_action;
+	act.sa_flags = SA_SIGINFO;
+	ret = sigaction(SIGSYS, &act, NULL);
+	ASSERT_EQ(0, ret) {
+		TH_LOG("sigaction failed");
+	}
+	ret = sigprocmask(SIG_UNBLOCK, &mask, NULL);
+	ASSERT_EQ(0, ret) {
+		TH_LOG("sigprocmask failed");
+	}
+
+	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog);
+	ASSERT_EQ(0, ret);
+	TRAP_nr = 0;
+	memset(&TRAP_info, 0, sizeof(TRAP_info));
+	/* Expect the registers to be rolled back. (nr = error) may vary
+	 * based on arch. */
+	ret = syscall(__NR_getpid);
+	/* Silence gcc warning about volatile. */
+	test = TRAP_nr;
+	EXPECT_EQ(SIGSYS, test);
+	struct local_sigsys {
+			void *_call_addr; /* calling user insn */
+			int _syscall;	/* triggering system call number */
+			unsigned int _arch;	/* AUDIT_ARCH_* of syscall */
+	} *sigsys = (struct local_sigsys *)
+#ifdef si_syscall
+		&(TRAP_info.si_call_addr);
+#else
+		&TRAP_info.si_pid;
+#endif
+	EXPECT_EQ(__NR_getpid, sigsys->_syscall);
+	/* Make sure arch is non-zero. */
+	EXPECT_NE(0, sigsys->_arch);
+	EXPECT_NE(0, (unsigned long)sigsys->_call_addr);
+}
+
+FIXTURE_DATA(precedence) {
+	struct sock_fprog allow;
+	struct sock_fprog trace;
+	struct sock_fprog error;
+	struct sock_fprog trap;
+	struct sock_fprog kill;
+};
+
+FIXTURE_SETUP(precedence) {
+	struct sock_filter allow_insns[] = {
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+	};
+	struct sock_filter trace_insns[] = {
+		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
+			offsetof(struct seccomp_data, nr)),
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE),
+	};
+	struct sock_filter error_insns[] = {
+		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
+			offsetof(struct seccomp_data, nr)),
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO),
+	};
+	struct sock_filter trap_insns[] = {
+		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
+			offsetof(struct seccomp_data, nr)),
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRAP),
+	};
+	struct sock_filter kill_insns[] = {
+		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
+			offsetof(struct seccomp_data, nr)),
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
+	};
+	memset(self, 0, sizeof(*self));
+#define FILTER_ALLOC(_x) \
+	self->_x.filter = malloc(sizeof(_x##_insns)); \
+	ASSERT_NE(NULL, self->_x.filter); \
+	memcpy(self->_x.filter, &_x##_insns, sizeof(_x##_insns)); \
+	self->_x.len = (unsigned short)(sizeof(_x##_insns)/sizeof(_x##_insns[0]))
+	FILTER_ALLOC(allow);
+	FILTER_ALLOC(trace);
+	FILTER_ALLOC(error);
+	FILTER_ALLOC(trap);
+	FILTER_ALLOC(kill);
+}
+
+FIXTURE_TEARDOWN(precedence) {
+#define FILTER_FREE(_x) if (self->_x.filter) free(self->_x.filter)
+	FILTER_FREE(allow);
+	FILTER_FREE(trace);
+	FILTER_FREE(error);
+	FILTER_FREE(trap);
+	FILTER_FREE(kill);
+}
+
+TEST_F(precedence, allow_ok) {
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	pid_t parent = getppid();
+	pid_t res = 0;
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->kill);
+	ASSERT_EQ(0, ret);
+	/* Should work just fine. */
+	res = syscall(__NR_getppid);
+	EXPECT_EQ(parent, res);
+}
+
+TEST_F_SIGNAL(precedence, kill_is_highest, SIGSYS) {
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	pid_t parent = getppid();
+	pid_t res = 0;
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->kill);
+	ASSERT_EQ(0, ret);
+	/* Should work just fine. */
+	res = syscall(__NR_getppid);
+	EXPECT_EQ(parent, res);
+	/* getpid() should never return. */
+	res = syscall(__NR_getpid);
+	EXPECT_EQ(0, res);
+}
+
+TEST_F_SIGNAL(precedence, kill_is_highest_in_any_order, SIGSYS) {
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	pid_t parent = getppid();
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->kill);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
+	ASSERT_EQ(0, ret);
+	/* Should work just fine. */
+	EXPECT_EQ(parent, syscall(__NR_getppid));
+	/* getpid() should never return. */
+	EXPECT_EQ(0, syscall(__NR_getpid));
+}
+
+TEST_F_SIGNAL(precedence, trap_is_second, SIGSYS) {
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	pid_t parent = getppid();
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
+	ASSERT_EQ(0, ret);
+	/* Should work just fine. */
+	EXPECT_EQ(parent, syscall(__NR_getppid));
+	/* getpid() should never return. */
+	EXPECT_EQ(0, syscall(__NR_getpid));
+}
+
+TEST_F_SIGNAL(precedence, trap_is_second_in_any_order, SIGSYS) {
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	pid_t parent = getppid();
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
+	ASSERT_EQ(0, ret);
+	/* Should work just fine. */
+	EXPECT_EQ(parent, syscall(__NR_getppid));
+	/* getpid() should never return. */
+	EXPECT_EQ(0, syscall(__NR_getpid));
+}
+
+TEST_F(precedence, errno_is_third) {
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	pid_t parent = getppid();
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
+	ASSERT_EQ(0, ret);
+	/* Should work just fine. */
+	EXPECT_EQ(parent, syscall(__NR_getppid));
+	EXPECT_EQ(0, syscall(__NR_getpid));
+}
+
+TEST_F(precedence, errno_is_third_in_any_order) {
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	pid_t parent = getppid();
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
+	ASSERT_EQ(0, ret);
+	/* Should work just fine. */
+	EXPECT_EQ(parent, syscall(__NR_getppid));
+	EXPECT_EQ(0, syscall(__NR_getpid));
+}
+
+TEST_F(precedence, trace_is_fourth) {
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	pid_t parent = getppid();
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
+	ASSERT_EQ(0, ret);
+	/* Should work just fine. */
+	EXPECT_EQ(parent, syscall(__NR_getppid));
+	/* No ptracer */
+	EXPECT_EQ(-1, syscall(__NR_getpid));
+}
+
+TEST_F(precedence, trace_is_fourth_in_any_order) {
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	pid_t parent = getppid();
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
+	ASSERT_EQ(0, ret);
+	/* Should work just fine. */
+	EXPECT_EQ(parent, syscall(__NR_getppid));
+	/* No ptracer */
+	EXPECT_EQ(-1, syscall(__NR_getpid));
+}
+
+#ifndef PTRACE_O_TRACESECCOMP
+#define PTRACE_O_TRACESECCOMP	0x00000080
+#endif
+
+/* Catch the Ubuntu 12.04 value error. */
+#if PTRACE_EVENT_SECCOMP != 7
+#undef PTRACE_EVENT_SECCOMP
+#endif
+
+#ifndef PTRACE_EVENT_SECCOMP
+#define PTRACE_EVENT_SECCOMP 7
+#endif
+
+#define IS_SECCOMP_EVENT(status) ((status >> 16) == PTRACE_EVENT_SECCOMP)
+bool tracer_running;
+void tracer_stop(int sig)
+{
+	tracer_running = false;
+}
+
+typedef void tracer_func_t(struct __test_metadata *_metadata,
+			   pid_t tracee, int status, void *args);
+
+void tracer(struct __test_metadata *_metadata, int fd, pid_t tracee,
+	    tracer_func_t tracer_func, void *args) {
+	int ret = -1;
+	struct sigaction action = {
+		.sa_handler = tracer_stop,
+	};
+
+	/* Allow external shutdown. */
+	tracer_running = true;
+	ASSERT_EQ(0, sigaction(SIGUSR1, &action, NULL));
+
+	errno = 0;
+	while (ret == -1 && errno != EINVAL) {
+		ret = ptrace(PTRACE_ATTACH, tracee, NULL, 0);
+	}
+	ASSERT_EQ(0, ret) {
+		kill(tracee, SIGKILL);
+	}
+	/* Wait for attach stop */
+	wait(NULL);
+
+	ret = ptrace(PTRACE_SETOPTIONS, tracee, NULL, PTRACE_O_TRACESECCOMP);
+	ASSERT_EQ(0, ret) {
+		TH_LOG("Failed to set PTRACE_O_TRACESECCOMP");
+		kill(tracee, SIGKILL);
+	}
+	ptrace(PTRACE_CONT, tracee, NULL, 0);
+
+	/* Unblock the tracee */
+	ASSERT_EQ(1, write(fd, "A", 1));
+	ASSERT_EQ(0, close(fd));
+
+	/* Run until we're shut down. Must assert to stop execution. */
+	while (tracer_running) {
+		int status;
+		if (wait(&status) != tracee)
+			continue;
+		if (WIFSIGNALED(status) || WIFEXITED(status))
+			/* Child is dead. Time to go. */
+			return;
+
+		/* Make sure this is a seccomp event. */
+		ASSERT_EQ(true, IS_SECCOMP_EVENT(status));
+
+		tracer_func(_metadata, tracee, status, args);
+
+		ret = ptrace(PTRACE_CONT, tracee, NULL, NULL);
+		ASSERT_EQ(0, ret);
+	}
+	/* Directly report the status of our test harness results. */
+	syscall(__NR_exit, _metadata->passed ? EXIT_SUCCESS : EXIT_FAILURE);
+}
+
+/* Common tracer setup/teardown functions. */
+void cont_handler(int num) {
+}
+pid_t setup_trace_fixture(struct __test_metadata *_metadata,
+			  tracer_func_t func, void *args) {
+	char sync;
+	int pipefd[2];
+	pid_t tracer_pid;
+	pid_t tracee = getpid();
+
+	/* Setup a pipe for clean synchronization. */
+	ASSERT_EQ(0, pipe(pipefd));
+
+	/* Fork a child which we'll promote to tracer */
+	tracer_pid = fork();
+	ASSERT_LE(0, tracer_pid);
+	signal(SIGALRM, cont_handler);
+	if (tracer_pid == 0) {
+		close(pipefd[0]);
+		tracer(_metadata, pipefd[1], tracee, func, args);
+		syscall(__NR_exit, 0);
+	}
+	close(pipefd[1]);
+	prctl(PR_SET_PTRACER, tracer_pid, 0, 0, 0);
+	read(pipefd[0], &sync, 1);
+	close(pipefd[0]);
+
+	return tracer_pid;
+}
+void teardown_trace_fixture(struct __test_metadata *_metadata,
+			    pid_t tracer) {
+	if (tracer) {
+		int status;
+		/*
+		 * Extract the exit code from the other process and
+		 * adopt it for ourselves in case its asserts failed.
+		 */
+		ASSERT_EQ(0, kill(tracer, SIGUSR1));
+		ASSERT_EQ(tracer, waitpid(tracer, &status, 0));
+		if (WEXITSTATUS(status))
+			_metadata->passed = 0;
+	}
+}
+
+/* "poke" tracer arguments and function. */
+struct tracer_args_poke_t {
+	unsigned long poke_addr;
+};
+
+void tracer_poke(struct __test_metadata *_metadata, pid_t tracee, int status,
+		 void *args) {
+	int ret;
+	unsigned long msg;
+	struct tracer_args_poke_t *info = (struct tracer_args_poke_t *)args;
+
+	ret = ptrace(PTRACE_GETEVENTMSG, tracee, NULL, &msg);
+	EXPECT_EQ(0, ret);
+	/* If this fails, don't try to recover. */
+	ASSERT_EQ(0x1001, msg) {
+		kill(tracee, SIGKILL);
+	}
+	/*
+	 * Poke in the message.
+	 * Registers are not touched to try to keep this relatively arch
+	 * agnostic.
+	 */
+	ret = ptrace(PTRACE_POKEDATA, tracee, info->poke_addr, 0x1001);
+	EXPECT_EQ(0, ret);
+}
+
+FIXTURE_DATA(TRACE_poke) {
+	struct sock_fprog prog;
+	pid_t tracer;
+	long poked;
+	struct tracer_args_poke_t tracer_args;
+};
+
+FIXTURE_SETUP(TRACE_poke) {
+	struct sock_filter filter[] = {
+		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
+			offsetof(struct seccomp_data, nr)),
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1001),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+	};
+
+	self->poked = 0;
+	memset(&self->prog, 0, sizeof(self->prog));
+	self->prog.filter = malloc(sizeof(filter));
+	ASSERT_NE(NULL, self->prog.filter);
+	memcpy(self->prog.filter, filter, sizeof(filter));
+	self->prog.len = (unsigned short)(sizeof(filter)/sizeof(filter[0]));
+
+	/* Set up tracer args. */
+	self->tracer_args.poke_addr = (unsigned long)&self->poked;
+
+	/* Launch tracer. */
+	self->tracer = setup_trace_fixture(_metadata, tracer_poke,
+					   &self->tracer_args);
+}
+
+FIXTURE_TEARDOWN(TRACE_poke) {
+	teardown_trace_fixture(_metadata, self->tracer);
+	if (self->prog.filter)
+		free(self->prog.filter);
+};
+
+TEST_F(TRACE_poke, read_has_side_effects) {
+	ssize_t ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	EXPECT_EQ(0, self->poked);
+	ret = read(-1, NULL, 0);
+	EXPECT_EQ(-1, ret);
+	EXPECT_EQ(0x1001, self->poked);
+}
+
+TEST_F(TRACE_poke, getpid_runs_normally) {
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	EXPECT_EQ(0, self->poked);
+	EXPECT_NE(0, syscall(__NR_getpid));
+	EXPECT_EQ(0, self->poked);
+}
+
+#if defined(__x86_64__)
+# define ARCH_REGS	struct user_regs_struct
+# define SYSCALL_NUM	orig_rax
+# define SYSCALL_RET	rax
+#elif defined(__i386__)
+# define ARCH_REGS	struct user_regs_struct
+# define SYSCALL_NUM	orig_eax
+# define SYSCALL_RET	eax
+#elif defined(__arm__)
+# define ARCH_REGS	struct pt_regs
+# define SYSCALL_NUM	ARM_r7
+# define SYSCALL_RET	ARM_r0
+#elif defined(__aarch64__)
+# define ARCH_REGS	struct user_pt_regs
+# define SYSCALL_NUM	regs[8]
+# define SYSCALL_RET	regs[0]
+#else
+# error "Do not know how to find your architecture's registers and syscalls"
+#endif
+
+/* Architecture-specific syscall fetching routine. */
+int get_syscall(struct __test_metadata *_metadata, pid_t tracee) {
+	struct iovec iov;
+	ARCH_REGS regs;
+
+	iov.iov_base = &regs;
+	iov.iov_len = sizeof(regs);
+	EXPECT_EQ(0, ptrace(PTRACE_GETREGSET, tracee, NT_PRSTATUS, &iov)) {
+		TH_LOG("PTRACE_GETREGSET failed");
+		return -1;
+	}
+
+	return regs.SYSCALL_NUM;
+}
+
+/* Architecture-specific syscall changing routine. */
+void change_syscall(struct __test_metadata *_metadata,
+		    pid_t tracee, int syscall) {
+	struct iovec iov;
+	int ret;
+	ARCH_REGS regs;
+
+	iov.iov_base = &regs;
+	iov.iov_len = sizeof(regs);
+	ret = ptrace(PTRACE_GETREGSET, tracee, NT_PRSTATUS, &iov);
+	EXPECT_EQ(0, ret);
+
+#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__)
+	{
+		regs.SYSCALL_NUM = syscall;
+	}
+
+#elif defined(__arm__)
+# ifndef PTRACE_SET_SYSCALL
+#  define PTRACE_SET_SYSCALL   23
+# endif
+	{
+		ret = ptrace(PTRACE_SET_SYSCALL, tracee, NULL, syscall);
+		EXPECT_EQ(0, ret);
+	}
+
+#else
+	ASSERT_EQ(1, 0) {
+		TH_LOG("How is the syscall changed on this architecture?");
+	}
+#endif
+
+	/* If syscall is skipped, change return value. */
+	if (syscall == -1)
+		regs.SYSCALL_RET = 1;
+
+	ret = ptrace(PTRACE_SETREGSET, tracee, NT_PRSTATUS, &iov);
+	EXPECT_EQ(0, ret);
+}
+
+void tracer_syscall(struct __test_metadata *_metadata, pid_t tracee,
+		    int status, void *args) {
+	int ret;
+	unsigned long msg;
+
+	/* Make sure we got the right message. */
+	ret = ptrace(PTRACE_GETEVENTMSG, tracee, NULL, &msg);
+	EXPECT_EQ(0, ret);
+
+	switch (msg) {
+	case 0x1002:
+		/* change getpid to getppid. */
+		change_syscall(_metadata, tracee, __NR_getppid);
+		break;
+	case 0x1003:
+		/* skip gettid. */
+		change_syscall(_metadata, tracee, -1);
+		break;
+	case 0x1004:
+		/* do nothing (allow getppid) */
+		break;
+	default:
+		EXPECT_EQ(0, msg) {
+			TH_LOG("Unknown PTRACE_GETEVENTMSG: 0x%lx", msg);
+			kill(tracee, SIGKILL);
+		}
+	}
+
+}
+
+FIXTURE_DATA(TRACE_syscall) {
+	struct sock_fprog prog;
+	pid_t tracer, mytid, mypid, parent;
+};
+
+FIXTURE_SETUP(TRACE_syscall) {
+	struct sock_filter filter[] = {
+		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
+			offsetof(struct seccomp_data, nr)),
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 0, 1),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1002),
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_gettid, 0, 1),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1003),
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1004),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+	};
+
+	memset(&self->prog, 0, sizeof(self->prog));
+	self->prog.filter = malloc(sizeof(filter));
+	ASSERT_NE(NULL, self->prog.filter);
+	memcpy(self->prog.filter, filter, sizeof(filter));
+	self->prog.len = (unsigned short)(sizeof(filter)/sizeof(filter[0]));
+
+	/* Prepare some testable syscall results. */
+	self->mytid = syscall(__NR_gettid);
+	ASSERT_GT(self->mytid, 0);
+	ASSERT_NE(self->mytid, 1) {
+		TH_LOG("Running this test as init is not supported. :)");
+	}
+
+	self->mypid = getpid();
+	ASSERT_GT(self->mypid, 0);
+	ASSERT_EQ(self->mytid, self->mypid);
+
+	self->parent = getppid();
+	ASSERT_GT(self->parent, 0);
+	ASSERT_NE(self->parent, self->mypid);
+
+	/* Launch tracer. */
+	self->tracer = setup_trace_fixture(_metadata, tracer_syscall, NULL);
+}
+
+FIXTURE_TEARDOWN(TRACE_syscall) {
+	teardown_trace_fixture(_metadata, self->tracer);
+	if (self->prog.filter)
+		free(self->prog.filter);
+};
+
+TEST_F(TRACE_syscall, syscall_allowed) {
+	long ret;
+
+	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	/* getppid works as expected (no changes). */
+	EXPECT_EQ(self->parent, syscall(__NR_getppid));
+	EXPECT_NE(self->mypid, syscall(__NR_getppid));
+}
+
+TEST_F(TRACE_syscall, syscall_redirected) {
+	long ret;
+
+	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	/* getpid has been redirected to getppid as expected. */
+	EXPECT_EQ(self->parent, syscall(__NR_getpid));
+	EXPECT_NE(self->mypid, syscall(__NR_getpid));
+}
+
+TEST_F(TRACE_syscall, syscall_dropped) {
+	long ret;
+
+	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
+	ASSERT_EQ(0, ret);
+
+	/* gettid has been skipped and an altered return value stored. */
+	EXPECT_EQ(1, syscall(__NR_gettid));
+	EXPECT_NE(self->mytid, syscall(__NR_gettid));
+}
+
+#ifndef __NR_seccomp
+# if defined(__i386__)
+#  define __NR_seccomp 354
+# elif defined(__x86_64__)
+#  define __NR_seccomp 317
+# elif defined(__arm__)
+#  define __NR_seccomp 383
+# elif defined(__aarch64__)
+#  define __NR_seccomp 277
+# else
+#  warning "seccomp syscall number unknown for this architecture"
+#  define __NR_seccomp 0xffff
+# endif
+#endif
+
+#ifndef SECCOMP_SET_MODE_STRICT
+#define SECCOMP_SET_MODE_STRICT 0
+#endif
+
+#ifndef SECCOMP_SET_MODE_FILTER
+#define SECCOMP_SET_MODE_FILTER 1
+#endif
+
+#ifndef SECCOMP_FLAG_FILTER_TSYNC
+#define SECCOMP_FLAG_FILTER_TSYNC 1
+#endif
+
+#ifndef seccomp
+int seccomp(unsigned int op, unsigned int flags, struct sock_fprog *filter)
+{
+	errno = 0;
+	return syscall(__NR_seccomp, op, flags, filter);
+}
+#endif
+
+TEST(seccomp_syscall) {
+	struct sock_filter filter[] = {
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+	};
+	struct sock_fprog prog = {
+		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
+		.filter = filter,
+	};
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	ASSERT_EQ(0, ret) {
+		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
+	}
+
+	/* Reject insane operation. */
+	ret = seccomp(-1, 0, &prog);
+	EXPECT_EQ(EINVAL, errno) {
+		TH_LOG("Did not reject crazy op value!");
+	}
+
+	/* Reject strict with flags or pointer. */
+	ret = seccomp(SECCOMP_SET_MODE_STRICT, -1, NULL);
+	EXPECT_EQ(EINVAL, errno) {
+		TH_LOG("Did not reject mode strict with flags!");
+	}
+	ret = seccomp(SECCOMP_SET_MODE_STRICT, 0, &prog);
+	EXPECT_EQ(EINVAL, errno) {
+		TH_LOG("Did not reject mode strict with uargs!");
+	}
+
+	/* Reject insane args for filter. */
+	ret = seccomp(SECCOMP_SET_MODE_FILTER, -1, &prog);
+	EXPECT_EQ(EINVAL, errno) {
+		TH_LOG("Did not reject crazy filter flags!");
+	}
+	ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, NULL);
+	EXPECT_EQ(EFAULT, errno) {
+		TH_LOG("Did not reject NULL filter!");
+	}
+
+	ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog);
+	EXPECT_EQ(0, errno) {
+		TH_LOG("Kernel does not support SECCOMP_SET_MODE_FILTER: %s",
+			strerror(errno));
+	}
+}
+
+TEST(seccomp_syscall_mode_lock) {
+	struct sock_filter filter[] = {
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+	};
+	struct sock_fprog prog = {
+		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
+		.filter = filter,
+	};
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, NULL, 0, 0);
+	ASSERT_EQ(0, ret) {
+		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
+	}
+
+	ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog);
+	EXPECT_EQ(0, ret) {
+		TH_LOG("Could not install filter!");
+	}
+
+	/* Make sure neither entry point will switch to strict. */
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT, 0, 0, 0);
+	EXPECT_EQ(EINVAL, errno) {
+		TH_LOG("Switched to mode strict!");
+	}
+
+	ret = seccomp(SECCOMP_SET_MODE_STRICT, 0, NULL);
+	EXPECT_EQ(EINVAL, errno) {
+		TH_LOG("Switched to mode strict!");
+	}
+}
+
+TEST(TSYNC_first) {
+	struct sock_filter filter[] = {
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+	};
+	struct sock_fprog prog = {
+		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
+		.filter = filter,
+	};
+	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, NULL, 0, 0);
+	ASSERT_EQ(0, ret) {
+		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
+	}
+
+	ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FLAG_FILTER_TSYNC,
+		      &prog);
+	EXPECT_EQ(0, ret) {
+		TH_LOG("Could not install initial filter with TSYNC!");
+	}
+}
+
+#define TSYNC_SIBLINGS 2
+struct tsync_sibling {
+	pthread_t tid;
+	pid_t system_tid;
+	sem_t *started;
+	pthread_cond_t *cond;
+	pthread_mutex_t *mutex;
+	int diverge;
+	int num_waits;
+	struct sock_fprog *prog;
+	struct __test_metadata *metadata;
+};
+
+FIXTURE_DATA(TSYNC) {
+	struct sock_fprog root_prog, apply_prog;
+	struct tsync_sibling sibling[TSYNC_SIBLINGS];
+	sem_t started;
+	pthread_cond_t cond;
+	pthread_mutex_t mutex;
+	int sibling_count;
+};
+
+FIXTURE_SETUP(TSYNC) {
+	struct sock_filter root_filter[] = {
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+	};
+	struct sock_filter apply_filter[] = {
+		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
+			offsetof(struct seccomp_data, nr)),
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+	};
+	memset(&self->root_prog, 0, sizeof(self->root_prog));
+	memset(&self->apply_prog, 0, sizeof(self->apply_prog));
+	memset(&self->sibling, 0, sizeof(self->sibling));
+	self->root_prog.filter = malloc(sizeof(root_filter));
+	ASSERT_NE(NULL, self->root_prog.filter);
+	memcpy(self->root_prog.filter, &root_filter, sizeof(root_filter));
+	self->root_prog.len = (unsigned short)(sizeof(root_filter)/sizeof(root_filter[0]));
+
+	self->apply_prog.filter = malloc(sizeof(apply_filter));
+	ASSERT_NE(NULL, self->apply_prog.filter);
+	memcpy(self->apply_prog.filter, &apply_filter, sizeof(apply_filter));
+	self->apply_prog.len = (unsigned short)(sizeof(apply_filter)/sizeof(apply_filter[0]));
+
+	self->sibling_count = 0;
+	pthread_mutex_init(&self->mutex, NULL);
+	pthread_cond_init(&self->cond, NULL);
+	sem_init(&self->started, 0, 0);
+	self->sibling[0].tid = 0;
+	self->sibling[0].cond = &self->cond;
+	self->sibling[0].started = &self->started;
+	self->sibling[0].mutex = &self->mutex;
+	self->sibling[0].diverge = 0;
+	self->sibling[0].num_waits = 1;
+	self->sibling[0].prog = &self->root_prog;
+	self->sibling[0].metadata = _metadata;
+	self->sibling[1].tid = 0;
+	self->sibling[1].cond = &self->cond;
+	self->sibling[1].started = &self->started;
+	self->sibling[1].mutex = &self->mutex;
+	self->sibling[1].diverge = 0;
+	self->sibling[1].prog = &self->root_prog;
+	self->sibling[1].num_waits = 1;
+	self->sibling[1].metadata = _metadata;
+}
+
+FIXTURE_TEARDOWN(TSYNC) {
+	int sib = 0;
+	if (self->root_prog.filter)
+		free(self->root_prog.filter);
+	if (self->apply_prog.filter)
+		free(self->apply_prog.filter);
+
+	for ( ; sib < self->sibling_count; ++sib) {
+		struct tsync_sibling *s = &self->sibling[sib];
+		void *status;
+		if (!s->tid)
+			continue;
+		if (pthread_kill(s->tid, 0)) {
+			//pthread_cancel(s->tid);  // ANDROID
+			pthread_join(s->tid, &status);
+		}
+	}
+	pthread_mutex_destroy(&self->mutex);
+	pthread_cond_destroy(&self->cond);
+	sem_destroy(&self->started);
+};
+
+void *tsync_sibling(void *data)
+{
+	long ret = 0;
+	struct tsync_sibling *me = data;
+	me->system_tid = syscall(__NR_gettid);
+
+	pthread_mutex_lock(me->mutex);
+	if (me->diverge) {
+		/* Just re-apply the root prog to fork the tree */
+		ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER,
+				me->prog, 0, 0);
+	}
+	sem_post(me->started);
+	/* Return outside of started so parent notices failures. */
+	if (ret) {
+		pthread_mutex_unlock(me->mutex);
+		return (void *)SIBLING_EXIT_FAILURE;
+	}
+	do {
+		pthread_cond_wait(me->cond, me->mutex);
+		me->num_waits = me->num_waits - 1;
+	}
+	while (me->num_waits);
+	pthread_mutex_unlock(me->mutex);
+	long nnp = prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0);
+	if (!nnp)
+		return (void*)SIBLING_EXIT_NEWPRIVS;
+	read(0, NULL, 0);
+	return (void *)SIBLING_EXIT_UNKILLED;
+}
+
+void tsync_start_sibling(struct tsync_sibling *sibling)
+{
+	pthread_create(&sibling->tid, NULL, tsync_sibling, (void *)sibling);
+}
+
+TEST_F(TSYNC, siblings_fail_prctl) {
+	long ret;
+	void *status;
+	struct sock_filter filter[] = {
+		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
+			offsetof(struct seccomp_data, nr)),
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_prctl, 0, 1),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | EINVAL),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+	};
+	struct sock_fprog prog = {
+		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
+		.filter = filter,
+	};
+
+	ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
+		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
+	}
+
+	/* Check prctl failure detection by requesting sib 0 diverge. */
+	ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog);
+	ASSERT_EQ(0, ret) {
+		TH_LOG("setting filter failed");
+	}
+
+	self->sibling[0].diverge = 1;
+	tsync_start_sibling(&self->sibling[0]);
+	tsync_start_sibling(&self->sibling[1]);
+
+	while (self->sibling_count < TSYNC_SIBLINGS) {
+		sem_wait(&self->started);
+		self->sibling_count++;
+	}
+
+	/* Signal the threads to clean up*/
+	pthread_mutex_lock(&self->mutex);
+	ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
+		TH_LOG("cond broadcast non-zero");
+	}
+	pthread_mutex_unlock(&self->mutex);
+
+	/* Ensure diverging sibling failed to call prctl. */
+	pthread_join(self->sibling[0].tid, &status);
+	EXPECT_EQ(SIBLING_EXIT_FAILURE, (long)status);
+	pthread_join(self->sibling[1].tid, &status);
+	EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status);
+}
+
+TEST_F(TSYNC, two_siblings_with_ancestor) {
+	long ret;
+	void *status;
+
+	ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
+		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
+	}
+
+	ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &self->root_prog);
+	ASSERT_EQ(0, ret) {
+		TH_LOG("Kernel does not support SECCOMP_SET_MODE_FILTER!");
+	}
+	tsync_start_sibling(&self->sibling[0]);
+	tsync_start_sibling(&self->sibling[1]);
+
+	while (self->sibling_count < TSYNC_SIBLINGS) {
+		sem_wait(&self->started);
+		self->sibling_count++;
+	}
+
+	ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FLAG_FILTER_TSYNC,
+		      &self->apply_prog);
+	ASSERT_EQ(0, ret) {
+		TH_LOG("Could install filter on all threads!");
+	}
+	/* Tell the siblings to test the policy */
+	pthread_mutex_lock(&self->mutex);
+	ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
+		TH_LOG("cond broadcast non-zero");
+	}
+	pthread_mutex_unlock(&self->mutex);
+	/* Ensure they are both killed and don't exit cleanly. */
+	pthread_join(self->sibling[0].tid, &status);
+	EXPECT_EQ(0x0, (long)status);
+	pthread_join(self->sibling[1].tid, &status);
+	EXPECT_EQ(0x0, (long)status);
+}
+
+TEST_F(TSYNC, two_sibling_want_nnp) {
+	void *status;
+
+	/* start siblings before any prctl() operations */
+	tsync_start_sibling(&self->sibling[0]);
+	tsync_start_sibling(&self->sibling[1]);
+	while (self->sibling_count < TSYNC_SIBLINGS) {
+		sem_wait(&self->started);
+		self->sibling_count++;
+	}
+
+	/* Tell the siblings to test no policy */
+	pthread_mutex_lock(&self->mutex);
+	ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
+		TH_LOG("cond broadcast non-zero");
+	}
+	pthread_mutex_unlock(&self->mutex);
+
+	/* Ensure they are both upset about lacking nnp. */
+	pthread_join(self->sibling[0].tid, &status);
+	EXPECT_EQ(SIBLING_EXIT_NEWPRIVS, (long)status);
+	pthread_join(self->sibling[1].tid, &status);
+	EXPECT_EQ(SIBLING_EXIT_NEWPRIVS, (long)status);
+}
+
+TEST_F(TSYNC, two_siblings_with_no_filter) {
+	long ret;
+	void *status;
+
+	/* start siblings before any prctl() operations */
+	tsync_start_sibling(&self->sibling[0]);
+	tsync_start_sibling(&self->sibling[1]);
+	while (self->sibling_count < TSYNC_SIBLINGS) {
+		sem_wait(&self->started);
+		self->sibling_count++;
+	}
+
+	ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
+		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
+	}
+
+	ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FLAG_FILTER_TSYNC,
+		      &self->apply_prog);
+	ASSERT_EQ(0, ret) {
+		TH_LOG("Could install filter on all threads!");
+	}
+
+	/* Tell the siblings to test the policy */
+	pthread_mutex_lock(&self->mutex);
+	ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
+		TH_LOG("cond broadcast non-zero");
+	}
+	pthread_mutex_unlock(&self->mutex);
+
+	/* Ensure they are both killed and don't exit cleanly. */
+	pthread_join(self->sibling[0].tid, &status);
+	EXPECT_EQ(0x0, (long)status);
+	pthread_join(self->sibling[1].tid, &status);
+	EXPECT_EQ(0x0, (long)status);
+}
+
+TEST_F(TSYNC, two_siblings_with_one_divergence) {
+	long ret;
+	void *status;
+
+	ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
+		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
+	}
+
+	ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &self->root_prog);
+	ASSERT_EQ(0, ret) {
+		TH_LOG("Kernel does not support SECCOMP_SET_MODE_FILTER!");
+	}
+	self->sibling[0].diverge = 1;
+	tsync_start_sibling(&self->sibling[0]);
+	tsync_start_sibling(&self->sibling[1]);
+
+	while (self->sibling_count < TSYNC_SIBLINGS) {
+		sem_wait(&self->started);
+		self->sibling_count++;
+	}
+
+	ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FLAG_FILTER_TSYNC,
+		      &self->apply_prog);
+	ASSERT_EQ(self->sibling[0].system_tid, ret) {
+		TH_LOG("Did not fail on diverged sibling.");
+	}
+
+	/* Wake the threads */
+	pthread_mutex_lock(&self->mutex);
+	ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
+		TH_LOG("cond broadcast non-zero");
+	}
+	pthread_mutex_unlock(&self->mutex);
+
+	/* Ensure they are both unkilled. */
+	pthread_join(self->sibling[0].tid, &status);
+	EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status);
+	pthread_join(self->sibling[1].tid, &status);
+	EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status);
+}
+
+TEST_F(TSYNC, two_siblings_not_under_filter) {
+	long ret, sib;
+	void *status;
+
+	ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
+		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
+	}
+
+	/*
+	 * Sibling 0 will have its own seccomp policy
+	 * and Sibling 1 will not be under seccomp at
+	 * all. Sibling 1 will enter seccomp and 0
+	 * will cause failure.
+	 */
+	self->sibling[0].diverge = 1;
+	tsync_start_sibling(&self->sibling[0]);
+	tsync_start_sibling(&self->sibling[1]);
+
+	while (self->sibling_count < TSYNC_SIBLINGS) {
+		sem_wait(&self->started);
+		self->sibling_count++;
+	}
+
+	ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &self->root_prog);
+	ASSERT_EQ(0, ret) {
+		TH_LOG("Kernel does not support SECCOMP_SET_MODE_FILTER!");
+	}
+
+	ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FLAG_FILTER_TSYNC,
+		      &self->apply_prog);
+	ASSERT_EQ(ret, self->sibling[0].system_tid) {
+		TH_LOG("Did not fail on diverged sibling.");
+	}
+	sib = 1;
+	if (ret == self->sibling[0].system_tid)
+		sib = 0;
+
+	pthread_mutex_lock(&self->mutex);
+
+	/* Increment the other siblings num_waits so we can clean up
+	 * the one we just saw.
+	 */
+	self->sibling[!sib].num_waits += 1;
+
+	/* Signal the thread to clean up*/
+	ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
+		TH_LOG("cond broadcast non-zero");
+	}
+	pthread_mutex_unlock(&self->mutex);
+	pthread_join(self->sibling[sib].tid, &status);
+	EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status);
+	/* Poll for actual task death. pthread_join doesn't guarantee it. */
+	while (!kill(self->sibling[sib].system_tid, 0)) sleep(0.1);
+	/* Switch to the remaining sibling */
+	sib = !sib;
+
+	ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FLAG_FILTER_TSYNC,
+		      &self->apply_prog);
+	ASSERT_EQ(0, ret) {
+		TH_LOG("Expected the remaining sibling to sync");
+	};
+
+	pthread_mutex_lock(&self->mutex);
+
+	/* If remaining sibling didn't have a chance to wake up during
+	 * the first broadcast, manually reduce the num_waits now.
+	 */
+	if (self->sibling[sib].num_waits > 1)
+		self->sibling[sib].num_waits = 1;
+	ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
+		TH_LOG("cond broadcast non-zero");
+	}
+	pthread_mutex_unlock(&self->mutex);
+	pthread_join(self->sibling[sib].tid, &status);
+	EXPECT_EQ(0, (long)status);
+	/* Poll for actual task death. pthread_join doesn't guarantee it. */
+	while (!kill(self->sibling[sib].system_tid, 0)) sleep(0.1);
+
+	ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FLAG_FILTER_TSYNC,
+		      &self->apply_prog);
+	ASSERT_EQ(0, ret);  /* just us chickens */
+}
+
+/* Make sure restarted syscalls are seen directly as "restart_syscall". */
+TEST(syscall_restart) {
+	long ret;
+	unsigned long msg;
+	pid_t child_pid;
+	int pipefd[2];
+	int status;
+	siginfo_t info = { };
+	struct sock_filter filter[] = {
+		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
+			 offsetof(struct seccomp_data, nr)),
+
+#ifdef __NR_sigreturn
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_sigreturn, 6, 0),
+#endif
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 5, 0),
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_exit, 4, 0),
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_rt_sigreturn, 3, 0),
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_poll, 4, 0),
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_restart_syscall, 4, 0),
+
+		/* Allow __NR_write for easy logging. */
+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_write, 0, 1),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE|0x100), /* poll */
+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE|0x200), /* restart */
+	};
+	struct sock_fprog prog = {
+		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
+		.filter = filter,
+	};
+
+	ASSERT_EQ(0, pipe(pipefd));
+
+	child_pid = fork();
+	ASSERT_LE(0, child_pid);
+	if (child_pid == 0) {
+		/* Child uses EXPECT not ASSERT to deliver status correctly. */
+		char buf = ' ';
+		struct pollfd fds = {
+			.fd = pipefd[0],
+			.events = POLLIN,
+		};
+
+		/* Attach parent as tracer and stop. */
+		EXPECT_EQ(0, ptrace(PTRACE_TRACEME));
+		EXPECT_EQ(0, raise(SIGSTOP));
+
+		EXPECT_EQ(0, close(pipefd[1]));
+
+		EXPECT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
+			TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
+		}
+
+		ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
+		EXPECT_EQ(0, ret) {
+			TH_LOG("Failed to install filter!");
+		}
+
+		EXPECT_EQ(1, read(pipefd[0], &buf, 1)) {
+			TH_LOG("Failed to read() sync from parent");
+		}
+		EXPECT_EQ('.', buf) {
+			TH_LOG("Failed to get sync data from read()");
+		}
+
+		/* Start poll to be interrupted. */
+		errno = 0;
+		EXPECT_EQ(1, poll(&fds, 1, -1)) {
+			TH_LOG("Call to poll() failed (errno %d)", errno);
+		}
+
+		/* Read final sync from parent. */
+		EXPECT_EQ(1, read(pipefd[0], &buf, 1)) {
+			TH_LOG("Failed final read() from parent");
+		}
+		EXPECT_EQ('!', buf) {
+			TH_LOG("Failed to get final data from read()");
+		}
+
+		/* Directly report the status of our test harness results. */
+		syscall(__NR_exit, _metadata->passed ? EXIT_SUCCESS
+						     : EXIT_FAILURE);
+	}
+	EXPECT_EQ(0, close(pipefd[0]));
+
+	/* Attach to child, setup options, and release. */
+	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
+	ASSERT_EQ(true, WIFSTOPPED(status));
+	ASSERT_EQ(0, ptrace(PTRACE_SETOPTIONS, child_pid, NULL,
+			    PTRACE_O_TRACESECCOMP));
+	ASSERT_EQ(0, ptrace(PTRACE_CONT, child_pid, NULL, 0));
+	ASSERT_EQ(1, write(pipefd[1], ".", 1));
+
+	/* Wait for poll() to start. */
+	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
+	ASSERT_EQ(true, WIFSTOPPED(status));
+	ASSERT_EQ(SIGTRAP, WSTOPSIG(status));
+	ASSERT_EQ(PTRACE_EVENT_SECCOMP, (status >> 16));
+	ASSERT_EQ(0, ptrace(PTRACE_GETEVENTMSG, child_pid, NULL, &msg));
+	ASSERT_EQ(0x100, msg);
+	EXPECT_EQ(__NR_poll, get_syscall(_metadata, child_pid));
+
+	/* Might as well check siginfo for sanity while we're here. */
+	ASSERT_EQ(0, ptrace(PTRACE_GETSIGINFO, child_pid, NULL, &info));
+	ASSERT_EQ(SIGTRAP, info.si_signo);
+	ASSERT_EQ(SIGTRAP | (PTRACE_EVENT_SECCOMP << 8), info.si_code);
+	EXPECT_EQ(0, info.si_errno);
+	EXPECT_EQ(getuid(), info.si_uid);
+	/* Verify signal delivery came from child (seccomp-triggered). */
+	EXPECT_EQ(child_pid, info.si_pid);
+
+	/* Interrupt poll with SIGSTOP (which we'll need to handle). */
+	ASSERT_EQ(0, kill(child_pid, SIGSTOP));
+	ASSERT_EQ(0, ptrace(PTRACE_CONT, child_pid, NULL, 0));
+	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
+	ASSERT_EQ(true, WIFSTOPPED(status));
+	ASSERT_EQ(SIGSTOP, WSTOPSIG(status));
+	/* Verify signal delivery came from parent now. */
+	ASSERT_EQ(0, ptrace(PTRACE_GETSIGINFO, child_pid, NULL, &info));
+	EXPECT_EQ(getpid(), info.si_pid);
+
+	/* Restart poll with SIGCONT, which triggers restart_syscall. */
+	ASSERT_EQ(0, kill(child_pid, SIGCONT));
+	ASSERT_EQ(0, ptrace(PTRACE_CONT, child_pid, NULL, 0));
+	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
+	ASSERT_EQ(true, WIFSTOPPED(status));
+	ASSERT_EQ(SIGCONT, WSTOPSIG(status));
+	ASSERT_EQ(0, ptrace(PTRACE_CONT, child_pid, NULL, 0));
+
+	/* Wait for restart_syscall() to start. */
+	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
+	ASSERT_EQ(true, WIFSTOPPED(status));
+	ASSERT_EQ(SIGTRAP, WSTOPSIG(status));
+	ASSERT_EQ(PTRACE_EVENT_SECCOMP, (status >> 16));
+	ASSERT_EQ(0, ptrace(PTRACE_GETEVENTMSG, child_pid, NULL, &msg));
+	ASSERT_EQ(0x200, msg);
+	ret = get_syscall(_metadata, child_pid);
+#if defined(__arm__)
+	/* FIXME: ARM does not expose true syscall in registers. */
+	EXPECT_EQ(__NR_poll, ret);
+#else
+	EXPECT_EQ(__NR_restart_syscall, ret);
+#endif
+
+	/* Write again to end poll. */
+	ASSERT_EQ(0, ptrace(PTRACE_CONT, child_pid, NULL, 0));
+	ASSERT_EQ(1, write(pipefd[1], "!", 1));
+	EXPECT_EQ(0, close(pipefd[1]));
+
+	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
+	if (WIFSIGNALED(status) || WEXITSTATUS(status))
+		_metadata->passed = 0;
+}
+
+/*
+ * TODO:
+ * - add microbenchmarks
+ * - expand NNP testing
+ * - better arch-specific TRACE and TRAP handlers.
+ * - endianness checking when appropriate
+ * - 64-bit arg prodding
+ * - arch value testing (x86 modes especially)
+ * - ...
+ */
+
+// ANDROID:begin
+struct __test_metadata* get_seccomp_test_list() {
+  return __test_list;
+}
+// ANDROID:end
+
+TEST_HARNESS_MAIN
diff --git a/tests/tests/os/jni/seccomp-tests/tests/sigsegv.c b/tests/tests/os/jni/seccomp-tests/tests/sigsegv.c
new file mode 100644
index 0000000..a0d06e7
--- /dev/null
+++ b/tests/tests/os/jni/seccomp-tests/tests/sigsegv.c
@@ -0,0 +1,179 @@
+/* sigsegv.c
+ * Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Forces a denied system call to trigger a SIGSEGV at the instruction after
+ * the call using a SIGSYS handler.. This can be useful when debugging
+ * frameworks have trouble tracing through the SIGSYS handler.
+ * Proof of concept using amd64 registers and 'syscall'.
+ */
+
+#include <asm/siginfo.h>
+#define __have_siginfo_t 1
+#define __have_sigval_t 1
+#define __have_sigevent_t 1
+
+#include <linux/filter.h>
+#include <sys/prctl.h>
+#include <linux/prctl.h>
+#include <linux/seccomp.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <string.h>
+#include <syscall.h>
+#define __USE_GNU 1
+#include <sys/ucontext.h>
+#include <sys/mman.h>
+
+#include "test_harness.h"
+
+#ifndef PR_SET_NO_NEW_PRIVS
+#define PR_SET_NO_NEW_PRIVS 38
+#define PR_GET_NO_NEW_PRIVS 39
+#endif
+
+#if defined(__i386__)
+#define REG_IP	REG_EIP
+#define REG_SP	REG_ESP
+#define REG_RESULT	REG_EAX
+#define REG_SYSCALL	REG_EAX
+#define REG_ARG0	REG_EBX
+#define REG_ARG1	REG_ECX
+#define REG_ARG2	REG_EDX
+#define REG_ARG3	REG_ESI
+#define REG_ARG4	REG_EDI
+#define REG_ARG5	REG_EBP
+#elif defined(__x86_64__)
+#define REG_IP	REG_RIP
+#define REG_SP	REG_RSP
+#define REG_RESULT	REG_RAX
+#define REG_SYSCALL	REG_RAX
+#define REG_ARG0	REG_RDI
+#define REG_ARG1	REG_RSI
+#define REG_ARG2	REG_RDX
+#define REG_ARG3	REG_R10
+#define REG_ARG4	REG_R8
+#define REG_ARG5	REG_R9
+#endif
+
+FIXTURE_DATA(TRAP) {
+	struct sock_fprog prog;
+};
+
+FIXTURE_SETUP(TRAP) {
+	/* instruction after the syscall. Will be arch specific, of course. */
+	{
+		struct sock_filter filter[] = {
+			BPF_STMT(BPF_LD+BPF_W+BPF_ABS,
+				offsetof(struct seccomp_data, nr)),
+			/* Whitelist anything you might need in the sigaction */
+#ifdef __NR_sigreturn
+			BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_sigreturn, 4, 0),
+#endif
+			/* TODO: only allow PROT_NONE */
+			BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_mprotect, 3, 0),
+			BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_exit, 2, 0),
+			BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_rt_sigreturn, 1, 0),
+			/* Allow __NR_write so easy logging. */
+			BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_write, 0, 1),
+			BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
+			BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_TRAP),
+		};
+		memset(&self->prog, 0, sizeof(self->prog));
+		self->prog.filter = malloc(sizeof(filter));
+		ASSERT_NE(NULL, self->prog.filter);
+		memcpy(self->prog.filter, filter, sizeof(filter));
+		self->prog.len = (unsigned short)(sizeof(filter)/sizeof(filter[0]));
+	}
+}
+
+FIXTURE_TEARDOWN(TRAP) {
+	if (self->prog.filter)
+		free(self->prog.filter);
+};
+
+struct arch_sigsys {
+		void *_call_addr; /* calling user insn */
+		int _syscall;	/* triggering system call number */
+		unsigned int _arch;	/* AUDIT_ARCH_* of syscall */
+};
+
+#define _ALIGN(x,sz) (((x + ((sz)-1)) & ~((sz)-1)) - (sz))
+#define ALIGN(x,sz) ((typeof(x))_ALIGN((unsigned long)(x),(unsigned long)(sz)))
+static long local_mprotect(void *target, unsigned long sz)
+{
+	register unsigned long res asm ("rax") = __NR_mprotect;
+	__attribute__((unused)) register void *addr asm ("rdi") = ALIGN(target, sz);
+	__attribute__((unused)) register long len asm ("rsi") = sz;
+	__attribute__((unused)) register long num asm ("rdx") = PROT_NONE;
+	__asm__("syscall\n");
+	return res;
+}
+
+static void TRAP_action(int nr, siginfo_t *info, void *void_context)
+{
+	ucontext_t *ctx = (ucontext_t *)void_context;
+	char buf[256];
+	int len;
+	struct arch_sigsys *sys = (struct arch_sigsys *)
+#ifdef si_syscall
+		&(info->si_call_addr);
+#else
+		&(info->si_pid);
+#endif
+
+	if (info->si_code != SYS_SECCOMP)
+		return;
+	if (!ctx)
+		return;
+	len = snprintf(buf, sizeof(buf),
+			"@0x%lX:%X:%d:0x%lX:0x%lX:0x%lX:0x%lX:0x%lX:0x%lX [0x%lX]\n",
+			(unsigned long)sys->_call_addr,
+			sys->_arch,
+			sys->_syscall,
+			(unsigned long)ctx->uc_mcontext.gregs[REG_ARG0],
+			(unsigned long)ctx->uc_mcontext.gregs[REG_ARG1],
+			(unsigned long)ctx->uc_mcontext.gregs[REG_ARG2],
+			(unsigned long)ctx->uc_mcontext.gregs[REG_ARG3],
+			(unsigned long)ctx->uc_mcontext.gregs[REG_ARG4],
+			(unsigned long)ctx->uc_mcontext.gregs[REG_ARG5],
+			(unsigned long)ALIGN(ctx->uc_mcontext.gregs[REG_IP],
+			4096));
+	/* Emit some useful logs or whatever. */
+	syscall(__NR_write, STDOUT_FILENO, buf, len);
+	/* Make the calling page non-exec */
+	/* Careful on how it is called since it may make the syscall() instructions non-exec. */
+	local_mprotect((void *)ctx->uc_mcontext.gregs[REG_IP], sysconf(_SC_PAGE_SIZE));
+}
+
+TEST_F_SIGNAL(TRAP, sigsegv, SIGSEGV) {
+	int ret;
+	struct sigaction act;
+	sigset_t mask;
+	memset(&act, 0, sizeof(act));
+	sigemptyset(&mask);
+	sigaddset(&mask, SIGSYS);
+
+	act.sa_sigaction = &TRAP_action;
+	act.sa_flags = SA_SIGINFO;
+	ret = sigaction(SIGSYS, &act, NULL);
+	ASSERT_EQ(0, ret) {
+		TH_LOG("sigaction failed");
+	}
+	ret = sigprocmask(SIG_UNBLOCK, &mask, NULL);
+	ASSERT_EQ(0, ret) {
+		TH_LOG("sigprocmask failed");
+	}
+
+	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+	ASSERT_EQ(0, ret);
+	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog);
+	ASSERT_EQ(0, ret);
+
+	/* Call anything! */
+	ret = syscall(__NR_getpid);
+}
+
+TEST_HARNESS_MAIN
diff --git a/tests/tests/os/jni/seccomp-tests/tests/test_harness.h b/tests/tests/os/jni/seccomp-tests/tests/test_harness.h
new file mode 100644
index 0000000..597e40c
--- /dev/null
+++ b/tests/tests/os/jni/seccomp-tests/tests/test_harness.h
@@ -0,0 +1,521 @@
+/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * test_harness.h: simple C unit test helper.
+ *
+ * Usage:
+ *   #include "test_harness.h"
+ *   TEST(standalone_test) {
+ *     do_some_stuff;
+ *     EXPECT_GT(10, stuff) {
+ *        stuff_state_t state;
+ *        enumerate_stuff_state(&state);
+ *        TH_LOG("expectation failed with state: %s", state.msg);
+ *     }
+ *     more_stuff;
+ *     ASSERT_NE(some_stuff, NULL) TH_LOG("how did it happen?!");
+ *     last_stuff;
+ *     EXPECT_EQ(0, last_stuff);
+ *   }
+ *
+ *   FIXTURE(my_fixture) {
+ *     mytype_t *data;
+ *     int awesomeness_level;
+ *   };
+ *   FIXTURE_SETUP(my_fixture) {
+ *     self->data = mytype_new();
+ *     ASSERT_NE(NULL, self->data);
+ *   }
+ *   FIXTURE_TEARDOWN(my_fixture) {
+ *     mytype_free(self->data);
+ *   }
+ *   TEST_F(my_fixture, data_is_good) {
+ *     EXPECT_EQ(1, is_my_data_good(self->data));
+ *   }
+ *
+ *   TEST_HARNESS_MAIN
+ *
+ * API inspired by code.google.com/p/googletest
+ */
+#ifndef TEST_HARNESS_H_
+#define TEST_HARNESS_H_
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <android/log.h>  // ANDROID
+
+/* All exported functionality should be declared through this macro. */
+#define TEST_API(x) _##x
+
+/*
+ * Exported APIs
+ */
+
+/* TEST(name) { implementation }
+ * Defines a test by name.
+ * Names must be unique and tests must not be run in parallel.  The
+ * implementation containing block is a function and scoping should be treated
+ * as such.  Returning early may be performed with a bare "return;" statement.
+ *
+ * EXPECT_* and ASSERT_* are valid in a TEST() { } context.
+ */
+#define TEST TEST_API(TEST)
+
+/* TEST_SIGNAL(name, signal) { implementation }
+ * Defines a test by name and the expected term signal.
+ * Names must be unique and tests must not be run in parallel.  The
+ * implementation containing block is a function and scoping should be treated
+ * as such.  Returning early may be performed with a bare "return;" statement.
+ *
+ * EXPECT_* and ASSERT_* are valid in a TEST() { } context.
+ */
+#define TEST_SIGNAL TEST_API(TEST_SIGNAL)
+
+/* FIXTURE(datatype name) {
+ *   type property1;
+ *   ...
+ * };
+ * Defines the data provided to TEST_F()-defined tests as |self|.  It should be
+ * populated and cleaned up using FIXTURE_SETUP and FIXTURE_TEARDOWN.
+ */
+#define FIXTURE TEST_API(FIXTURE)
+
+/* FIXTURE_DATA(datatype name)
+ * This call may be used when the type of the fixture data
+ * is needed.  In general, this should not be needed unless
+ * the |self| is being passed to a helper directly.
+ */
+#define FIXTURE_DATA TEST_API(FIXTURE_DATA)
+
+/* FIXTURE_SETUP(fixture name) { implementation }
+ * Populates the required "setup" function for a fixture.  An instance of the
+ * datatype defined with _FIXTURE_DATA will be exposed as |self| for the
+ * implementation.
+ *
+ * ASSERT_* are valid for use in this context and will prempt the execution
+ * of any dependent fixture tests.
+ *
+ * A bare "return;" statement may be used to return early.
+ */
+#define FIXTURE_SETUP TEST_API(FIXTURE_SETUP)
+
+/* FIXTURE_TEARDOWN(fixture name) { implementation }
+ * Populates the required "teardown" function for a fixture.  An instance of the
+ * datatype defined with _FIXTURE_DATA will be exposed as |self| for the
+ * implementation to clean up.
+ *
+ * A bare "return;" statement may be used to return early.
+ */
+#define FIXTURE_TEARDOWN TEST_API(FIXTURE_TEARDOWN)
+
+/* TEST_F(fixture, name) { implementation }
+ * Defines a test that depends on a fixture (e.g., is part of a test case).
+ * Very similar to TEST() except that |self| is the setup instance of fixture's
+ * datatype exposed for use by the implementation.
+ */
+#define TEST_F TEST_API(TEST_F)
+
+#define TEST_F_SIGNAL TEST_API(TEST_F_SIGNAL)
+
+/* Use once to append a main() to the test file. E.g.,
+ *   TEST_HARNESS_MAIN
+ */
+#define TEST_HARNESS_MAIN TEST_API(TEST_HARNESS_MAIN)
+
+/*
+ * Operators for use in TEST and TEST_F.
+ * ASSERT_* calls will stop test execution immediately.
+ * EXPECT_* calls will emit a failure warning, note it, and continue.
+ */
+
+/* ASSERT_EQ(expected, measured): expected == measured */
+#define ASSERT_EQ TEST_API(ASSERT_EQ)
+/* ASSERT_NE(expected, measured): expected != measured */
+#define ASSERT_NE TEST_API(ASSERT_NE)
+/* ASSERT_LT(expected, measured): expected < measured */
+#define ASSERT_LT TEST_API(ASSERT_LT)
+/* ASSERT_LE(expected, measured): expected <= measured */
+#define ASSERT_LE TEST_API(ASSERT_LE)
+/* ASSERT_GT(expected, measured): expected > measured */
+#define ASSERT_GT TEST_API(ASSERT_GT)
+/* ASSERT_GE(expected, measured): expected >= measured */
+#define ASSERT_GE TEST_API(ASSERT_GE)
+/* ASSERT_NULL(measured): NULL == measured */
+#define ASSERT_NULL TEST_API(ASSERT_NULL)
+/* ASSERT_TRUE(measured): measured != 0 */
+#define ASSERT_TRUE TEST_API(ASSERT_TRUE)
+/* ASSERT_FALSE(measured): measured == 0 */
+#define ASSERT_FALSE TEST_API(ASSERT_FALSE)
+/* ASSERT_STREQ(expected, measured): !strcmp(expected, measured) */
+#define ASSERT_STREQ TEST_API(ASSERT_STREQ)
+/* ASSERT_STRNE(expected, measured): strcmp(expected, measured) */
+#define ASSERT_STRNE TEST_API(ASSERT_STRNE)
+/* EXPECT_EQ(expected, measured): expected == measured */
+#define EXPECT_EQ TEST_API(EXPECT_EQ)
+/* EXPECT_NE(expected, measured): expected != measured */
+#define EXPECT_NE TEST_API(EXPECT_NE)
+/* EXPECT_LT(expected, measured): expected < measured */
+#define EXPECT_LT TEST_API(EXPECT_LT)
+/* EXPECT_LE(expected, measured): expected <= measured */
+#define EXPECT_LE TEST_API(EXPECT_LE)
+/* EXPECT_GT(expected, measured): expected > measured */
+#define EXPECT_GT TEST_API(EXPECT_GT)
+/* EXPECT_GE(expected, measured): expected >= measured */
+#define EXPECT_GE TEST_API(EXPECT_GE)
+/* EXPECT_NULL(measured): NULL == measured */
+#define EXPECT_NULL TEST_API(EXPECT_NULL)
+/* EXPECT_TRUE(measured): 0 != measured */
+#define EXPECT_TRUE TEST_API(EXPECT_TRUE)
+/* EXPECT_FALSE(measured): 0 == measured */
+#define EXPECT_FALSE TEST_API(EXPECT_FALSE)
+/* EXPECT_STREQ(expected, measured): !strcmp(expected, measured) */
+#define EXPECT_STREQ TEST_API(EXPECT_STREQ)
+/* EXPECT_STRNE(expected, measured): strcmp(expected, measured) */
+#define EXPECT_STRNE TEST_API(EXPECT_STRNE)
+
+/* TH_LOG(format, ...)
+ * Optional debug logging function available for use in tests.
+ * Logging may be enabled or disabled by defining TH_LOG_ENABLED.
+ * E.g., #define TH_LOG_ENABLED 1
+ * If no definition is provided, logging is enabled by default.
+ */
+#define TH_LOG  TEST_API(TH_LOG)
+
+/*
+ * Internal implementation.
+ *
+ */
+
+/* Utilities exposed to the test definitions */
+#ifndef TH_LOG_STREAM
+#  define TH_LOG_STREAM stderr
+#endif
+
+#ifndef TH_LOG_ENABLED
+#  define TH_LOG_ENABLED 1
+#endif
+
+#define _TH_LOG(fmt, ...) do { \
+  if (TH_LOG_ENABLED) \
+    __TH_LOG(fmt, ##__VA_ARGS__); \
+} while (0)
+
+/* Unconditional logger for internal use. */
+// ANDROID:begin
+#define __TH_LOG(fmt, ...) \
+    __android_log_print(ANDROID_LOG_ERROR, "SeccompBpfTest-KernelUnit", "%s:%d:%s:" fmt "\n", \
+            __FILE__, __LINE__, _metadata->name, ##__VA_ARGS__)
+// ANDROID:end
+
+/* Defines the test function and creates the registration stub. */
+#define _TEST(test_name) __TEST_IMPL(test_name, -1)
+
+#define _TEST_SIGNAL(test_name, signal) __TEST_IMPL(test_name, signal)
+
+#define __TEST_IMPL(test_name, _signal) \
+  static void test_name(struct __test_metadata *_metadata); \
+  static struct __test_metadata _##test_name##_object = \
+    { name: "global." #test_name, fn: &test_name, termsig: _signal }; \
+  static void __attribute__((constructor)) _register_##test_name(void) { \
+    __register_test(&_##test_name##_object); \
+  } \
+  static void test_name( \
+    struct __test_metadata __attribute__((unused)) *_metadata)
+
+/* Wraps the struct name so we have one less argument to pass around. */
+#define _FIXTURE_DATA(fixture_name) struct _test_data_##fixture_name
+
+/* Called once per fixture to setup the data and register. */
+#define _FIXTURE(fixture_name) \
+  static void __attribute__((constructor)) \
+      _register_##fixture_name##_data(void) { \
+    __fixture_count++; \
+  } \
+  _FIXTURE_DATA(fixture_name)
+
+/* Prepares the setup function for the fixture.  |_metadata| is included
+ * so that ASSERT_* work as a convenience.
+ */
+#define _FIXTURE_SETUP(fixture_name) \
+  void fixture_name##_setup( \
+    struct __test_metadata __attribute__((unused)) *_metadata, \
+    _FIXTURE_DATA(fixture_name) __attribute__((unused)) *self)
+#define _FIXTURE_TEARDOWN(fixture_name) \
+  void fixture_name##_teardown( \
+    struct __test_metadata __attribute__((unused)) *_metadata, \
+    _FIXTURE_DATA(fixture_name) __attribute__((unused)) *self)
+
+/* Emits test registration and helpers for fixture-based test
+ * cases.
+ * TODO(wad) register fixtures on dedicated test lists.
+ */
+#define _TEST_F(fixture_name, test_name) \
+  __TEST_F_IMPL(fixture_name, test_name, -1)
+
+#define _TEST_F_SIGNAL(fixture_name, test_name, signal) \
+  __TEST_F_IMPL(fixture_name, test_name, signal)
+
+#define __TEST_F_IMPL(fixture_name, test_name, signal) \
+  static void fixture_name##_##test_name( \
+    struct __test_metadata *_metadata, \
+    _FIXTURE_DATA(fixture_name) *self); \
+  static inline void wrapper_##fixture_name##_##test_name( \
+    struct __test_metadata *_metadata) { \
+    /* fixture data is allocated, setup, and torn down per call. */ \
+    _FIXTURE_DATA(fixture_name) self; \
+    memset(&self, 0, sizeof(_FIXTURE_DATA(fixture_name))); \
+    fixture_name##_setup(_metadata, &self); \
+    /* Let setup failure terminate early. */ \
+    if (!_metadata->passed) return; \
+    fixture_name##_##test_name(_metadata, &self); \
+    fixture_name##_teardown(_metadata, &self); \
+  } \
+  static struct __test_metadata _##fixture_name##_##test_name##_object = { \
+    name: #fixture_name "." #test_name, \
+    fn: &wrapper_##fixture_name##_##test_name, \
+    termsig: signal, \
+   }; \
+  static void __attribute__((constructor)) \
+      _register_##fixture_name##_##test_name(void) { \
+    __register_test(&_##fixture_name##_##test_name##_object); \
+  } \
+  static void fixture_name##_##test_name( \
+    struct __test_metadata __attribute__((unused)) *_metadata, \
+    _FIXTURE_DATA(fixture_name) __attribute__((unused)) *self)
+
+/* Exports a simple wrapper to run the test harness. */
+#define _TEST_HARNESS_MAIN \
+  static void __attribute__((constructor)) __constructor_order_last(void) { \
+    if (!__constructor_order) \
+      __constructor_order = _CONSTRUCTOR_ORDER_BACKWARD; \
+  } \
+  int seccomp_test_main(int argc, char **argv) { return test_harness_run(argc, argv); }  // ANDROID
+
+#define _ASSERT_EQ(_expected, _seen) \
+  __EXPECT(_expected, _seen, ==, 1)
+#define _ASSERT_NE(_expected, _seen) \
+  __EXPECT(_expected, _seen, !=, 1)
+#define _ASSERT_LT(_expected, _seen) \
+  __EXPECT(_expected, _seen, <, 1)
+#define _ASSERT_LE(_expected, _seen) \
+  __EXPECT(_expected, _seen, <=, 1)
+#define _ASSERT_GT(_expected, _seen) \
+  __EXPECT(_expected, _seen, >, 1)
+#define _ASSERT_GE(_expected, _seen) \
+  __EXPECT(_expected, _seen, >=, 1)
+#define _ASSERT_NULL(_seen) \
+  __EXPECT(NULL, _seen, ==, 1)
+
+#define _ASSERT_TRUE(_seen) \
+  _ASSERT_NE(0, _seen)
+#define _ASSERT_FALSE(_seen) \
+  _ASSERT_EQ(0, _seen)
+#define _ASSERT_STREQ(_expected, _seen) \
+  __EXPECT_STR(_expected, _seen, ==, 1)
+#define _ASSERT_STRNE(_expected, _seen) \
+  __EXPECT_STR(_expected, _seen, !=, 1)
+
+#define _EXPECT_EQ(_expected, _seen) \
+  __EXPECT(_expected, _seen, ==, 0)
+#define _EXPECT_NE(_expected, _seen) \
+  __EXPECT(_expected, _seen, !=, 0)
+#define _EXPECT_LT(_expected, _seen) \
+  __EXPECT(_expected, _seen, <, 0)
+#define _EXPECT_LE(_expected, _seen) \
+  __EXPECT(_expected, _seen, <=, 0)
+#define _EXPECT_GT(_expected, _seen) \
+  __EXPECT(_expected, _seen, >, 0)
+#define _EXPECT_GE(_expected, _seen) \
+  __EXPECT(_expected, _seen, >=, 0)
+
+#define _EXPECT_NULL(_seen) \
+  __EXPECT(NULL, _seen, ==, 0)
+#define _EXPECT_TRUE(_seen) \
+  _EXPECT_NE(0, _seen)
+#define _EXPECT_FALSE(_seen) \
+  _EXPECT_EQ(0, _seen)
+
+#define _EXPECT_STREQ(_expected, _seen) \
+  __EXPECT_STR(_expected, _seen, ==, 0)
+#define _EXPECT_STRNE(_expected, _seen) \
+  __EXPECT_STR(_expected, _seen, !=, 0)
+
+/* Support an optional handler after and ASSERT_* or EXPECT_*.  The approach is
+ * not thread-safe, but it should be fine in most sane test scenarios.
+ *
+ * Using __bail(), which optionally abort()s, is the easiest way to early
+ * return while still providing an optional block to the API consumer.
+ */
+#define OPTIONAL_HANDLER(_assert) \
+  for (; _metadata->trigger;  _metadata->trigger = __bail(_assert))
+
+#define __EXPECT(_expected, _seen, _t, _assert) do { \
+  /* Avoid multiple evaluation of the cases */ \
+  __typeof__(_expected) __exp = (_expected); \
+  __typeof__(_seen) __seen = (_seen); \
+  if (!(__exp _t __seen)) { \
+    unsigned long long __exp_print = 0; \
+    unsigned long long __seen_print = 0; \
+    /* Avoid casting complaints the scariest way we can. */ \
+    memcpy(&__exp_print, &__exp, sizeof(__exp)); \
+    memcpy(&__seen_print, &__seen, sizeof(__seen)); \
+    __TH_LOG("Expected %s (%llu) %s %s (%llu)", \
+            #_expected, __exp_print, #_t, \
+            #_seen, __seen_print); \
+    _metadata->passed = 0; \
+    /* Ensure the optional handler is triggered */ \
+    _metadata->trigger = 1; \
+  } \
+} while (0); OPTIONAL_HANDLER(_assert)
+
+#define __EXPECT_STR(_expected, _seen, _t, _assert) do { \
+  const char *__exp = (_expected); \
+  const char *__seen = (_seen); \
+  if (!(strcmp(__exp, __seen) _t 0))  { \
+    __TH_LOG("Expected '%s' %s '%s'.", __exp, #_t, __seen); \
+    _metadata->passed = 0; \
+    _metadata->trigger = 1; \
+  } \
+} while (0); OPTIONAL_HANDLER(_assert)
+
+/* Contains all the information for test execution and status checking. */
+struct __test_metadata {
+  const char *name;
+  void (*fn)(struct __test_metadata *);
+  int termsig;
+  int passed;
+  int trigger; /* extra handler after the evaluation */
+  struct __test_metadata *prev, *next;
+};
+
+/* Storage for the (global) tests to be run. */
+static struct __test_metadata *__test_list = NULL;
+static unsigned int __test_count = 0;
+static unsigned int __fixture_count = 0;
+static int __constructor_order = 0;
+
+#define _CONSTRUCTOR_ORDER_FORWARD   1
+#define _CONSTRUCTOR_ORDER_BACKWARD -1
+
+/*
+ * Since constructors are called in reverse order, reverse the test
+ * list so tests are run in source declaration order.
+ * https://gcc.gnu.org/onlinedocs/gccint/Initialization.html
+ * However, it seems not all toolchains do this correctly, so use
+ * __constructor_order to detect which direction is called first
+ * and adjust list building logic to get things running in the right
+ * direction.
+ */
+static inline void __register_test(struct __test_metadata *t) {
+  __test_count++;
+  /* Circular linked list where only prev is circular. */
+  if (__test_list == NULL) {
+    __test_list = t;
+    t->next = NULL;
+    t->prev = t;
+    return;
+  }
+  if (__constructor_order == _CONSTRUCTOR_ORDER_FORWARD) {
+    t->next = NULL;
+    t->prev = __test_list->prev;
+    t->prev->next = t;
+    __test_list->prev = t;
+  } else {
+    t->next = __test_list;
+    t->next->prev = t;
+    t->prev = t;
+    __test_list = t;
+  }
+}
+
+static inline int __bail(int for_realz) {
+  if (for_realz)
+    abort();
+  return 0;
+}
+
+void __run_test(struct __test_metadata *t) {
+  pid_t child_pid;
+  int status;
+  t->passed = 1;
+  t->trigger = 0;
+  printf("[ RUN      ] %s\n", t->name);
+  child_pid = fork();
+  if (child_pid < 0) {
+    printf("ERROR SPAWNING TEST CHILD\n");
+    t->passed = 0;
+  } else if (child_pid == 0) {
+    t->fn(t);
+    _exit(t->passed);
+  } else {
+    /* TODO(wad) add timeout support. */
+    waitpid(child_pid, &status, 0);
+    if (WIFEXITED(status)) {
+      t->passed = t->termsig == -1 ? WEXITSTATUS(status) : 0;
+      if (t->termsig != -1) {
+       fprintf(TH_LOG_STREAM,
+                "%s: Test exited normally instead of by signal (code: %d)\n",
+               t->name,
+               WEXITSTATUS(status));
+      }
+    } else if (WIFSIGNALED(status)) {
+      t->passed = 0;
+      if (WTERMSIG(status) == SIGABRT) {
+        fprintf(TH_LOG_STREAM,
+                "%s: Test terminated by assertion\n",
+               t->name);
+      } else if (WTERMSIG(status) == t->termsig) {
+        t->passed = 1;
+      } else {
+        fprintf(TH_LOG_STREAM,
+                "%s: Test terminated unexpectedly by signal %d\n",
+               t->name,
+               WTERMSIG(status));
+      }
+    } else {
+        fprintf(TH_LOG_STREAM,
+                "%s: Test ended in some other way [%u]\n",
+               t->name,
+               status);
+    }
+  }
+  printf("[     %4s ] %s\n", (t->passed ? "OK" : "FAIL"), t->name);
+}
+
+static int test_harness_run(int __attribute__((unused)) argc,
+                            char __attribute__((unused)) **argv) {
+  struct __test_metadata *t;
+  int ret = 0;
+  unsigned int count = 0;
+  unsigned int pass_count = 0;
+
+  /* TODO(wad) add optional arguments similar to gtest. */
+  printf("[==========] Running %u tests from %u test cases.\n",
+          __test_count, __fixture_count + 1);
+  for (t = __test_list; t; t = t->next) {
+    count++;
+    __run_test(t);
+    if (t->passed)
+      pass_count++;
+    else
+      ret = 1;
+  }
+  /* TODO(wad) organize by fixtures since ordering is not guaranteed now. */
+  printf("[==========] %u / %u tests passed.\n", pass_count, count);
+  printf("[  %s  ]\n", (ret ? "FAILED" : "PASSED"));
+  return ret;
+}
+
+static void __attribute__((constructor)) __constructor_order_first(void) {
+  if (!__constructor_order)
+    __constructor_order = _CONSTRUCTOR_ORDER_FORWARD;
+}
+
+#endif  /* TEST_HARNESS_H_ */
diff --git a/tests/tests/os/src/android/os/cts/MessageQueueTest.java b/tests/tests/os/src/android/os/cts/MessageQueueTest.java
index f5d6415..8906c42 100644
--- a/tests/tests/os/src/android/os/cts/MessageQueueTest.java
+++ b/tests/tests/os/src/android/os/cts/MessageQueueTest.java
@@ -21,7 +21,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.MessageQueue;
-import android.os.MessageQueue.FileDescriptorCallback;
+import android.os.MessageQueue.OnFileDescriptorEventListener;
 import android.os.ParcelFileDescriptor;
 import android.os.ParcelFileDescriptor.AutoCloseInputStream;
 import android.os.ParcelFileDescriptor.AutoCloseOutputStream;
@@ -214,8 +214,13 @@
     public void testRegisterFileDescriptorCallbackThrowsWhenFdIsNull() {
         MessageQueue queue = Looper.getMainLooper().getQueue();
         try {
-            queue.registerFileDescriptorCallback(null, 0,
-                    new FileDescriptorCallback() { });
+            queue.addOnFileDescriptorEventListener(null, 0,
+                    new OnFileDescriptorEventListener() {
+                @Override
+                public int onFileDescriptorEvents(FileDescriptor fd, int events) {
+                    return 0;
+                }
+            });
             fail("Expected IllegalArgumentException");
         } catch (IllegalArgumentException ex) {
             // expected
@@ -228,7 +233,7 @@
         try (ParcelFileDescriptor reader = pipe[0];
                 ParcelFileDescriptor writer = pipe[1]) {
             try {
-                queue.registerFileDescriptorCallback(reader.getFileDescriptor(), 0, null);
+                queue.addOnFileDescriptorEventListener(reader.getFileDescriptor(), 0, null);
                 fail("Expected IllegalArgumentException");
             } catch (IllegalArgumentException ex) {
                 // expected
@@ -239,7 +244,7 @@
     public void testUnregisterFileDescriptorCallbackThrowsWhenFdIsNull() throws Exception {
         MessageQueue queue = Looper.getMainLooper().getQueue();
         try {
-            queue.unregisterFileDescriptorCallback(null);
+            queue.removeOnFileDescriptorEventListener(null);
             fail("Expected IllegalArgumentException");
         } catch (IllegalArgumentException ex) {
             // expected
@@ -252,7 +257,7 @@
         ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
         try (ParcelFileDescriptor reader = pipe[0];
                 ParcelFileDescriptor writer = pipe[1]) {
-            queue.unregisterFileDescriptorCallback(reader.getFileDescriptor());
+            queue.removeOnFileDescriptorEventListener(reader.getFileDescriptor());
         }
     }
 
@@ -272,7 +277,7 @@
                 // Prepare to write a lot of data to the pipe asynchronously.
                 // We don't actually care about the content (assume pipes work correctly)
                 // so we just write lots of zeros.
-                FileDescriptorCallback writerCallback = new FileDescriptorCallback() {
+                OnFileDescriptorEventListener writerCallback = new OnFileDescriptorEventListener() {
                     private byte[] mBuffer = new byte[4096];
                     private int mRemaining = size;
                     private boolean mDone;
@@ -283,14 +288,14 @@
                         if (!mDone) {
                             // When an error happens because the reader closed its end,
                             // signal the test, and remove the callback.
-                            if ((events & FileDescriptorCallback.EVENT_ERROR) != 0) {
+                            if ((events & OnFileDescriptorEventListener.EVENT_ERROR) != 0) {
                                 writerSawError.countDown();
                                 mDone = true;
                                 return 0;
                             }
 
                             // Write all output until an error is observed.
-                            if ((events & FileDescriptorCallback.EVENT_OUTPUT) != 0) {
+                            if ((events & OnFileDescriptorEventListener.EVENT_OUTPUT) != 0) {
                                 int count = Math.min(mBuffer.length, mRemaining);
                                 try {
                                     writer.write(mBuffer, 0, count);
@@ -309,7 +314,7 @@
                 };
 
                 // Prepare to read all of that data.
-                FileDescriptorCallback readerCallback = new FileDescriptorCallback() {
+                OnFileDescriptorEventListener readerCallback = new OnFileDescriptorEventListener() {
                     private byte[] mBuffer = new byte[4096];
                     private int mRemaining = size;
                     private boolean mDone;
@@ -319,14 +324,14 @@
                         assertEquals(pipe[0].getFileDescriptor(), fd);
                         if (!mDone) {
                             // Errors should not happen.
-                            if ((events & FileDescriptorCallback.EVENT_ERROR) != 0) {
+                            if ((events & OnFileDescriptorEventListener.EVENT_ERROR) != 0) {
                                 fail("Saw unexpected error.");
                                 return 0;
                             }
 
                             // Read until everything is read, signal the test,
                             // and remove the callback.
-                            if ((events & FileDescriptorCallback.EVENT_INPUT) != 0) {
+                            if ((events & OnFileDescriptorEventListener.EVENT_INPUT) != 0) {
                                 try {
                                     int count = reader.read(mBuffer, 0, mBuffer.length);
                                     mRemaining -= count;
@@ -349,10 +354,10 @@
                 };
 
                 // Register the callbacks.
-                queue.registerFileDescriptorCallback(reader.getFD(),
-                        FileDescriptorCallback.EVENT_INPUT, readerCallback);
-                queue.registerFileDescriptorCallback(writer.getFD(),
-                        FileDescriptorCallback.EVENT_OUTPUT, writerCallback);
+                queue.addOnFileDescriptorEventListener(reader.getFD(),
+                        OnFileDescriptorEventListener.EVENT_INPUT, readerCallback);
+                queue.addOnFileDescriptorEventListener(writer.getFD(),
+                        OnFileDescriptorEventListener.EVENT_OUTPUT, writerCallback);
 
                 // Wait for the reader to see all of the data that the writer
                 // is prepared to send.
@@ -368,8 +373,8 @@
 
                 // The reader and writer should already be unregistered.
                 // Try to unregistered them again to ensure nothing bad happens.
-                queue.unregisterFileDescriptorCallback(reader.getFD());
-                queue.unregisterFileDescriptorCallback(writer.getFD());
+                queue.removeOnFileDescriptorEventListener(reader.getFD());
+                queue.removeOnFileDescriptorEventListener(writer.getFD());
             }
         } finally {
             thread.quitAndRethrow();
@@ -401,8 +406,8 @@
                     final FileOutputStream writer = new AutoCloseOutputStream(pipe[1])) {
                 // Register the callback.
                 final boolean[] awoke = new boolean[1];
-                queue.registerFileDescriptorCallback(reader.getFD(),
-                        FileDescriptorCallback.EVENT_ERROR, new FileDescriptorCallback() {
+                queue.addOnFileDescriptorEventListener(reader.getFD(),
+                        OnFileDescriptorEventListener.EVENT_ERROR, new OnFileDescriptorEventListener() {
                     @Override
                     public int onFileDescriptorEvents(FileDescriptor fd, int events) {
                         awoke[0] = true;
@@ -438,8 +443,8 @@
                     final FileOutputStream writer2 = new AutoCloseOutputStream(pipe2[1])) {
                 // Register the callback.
                 final boolean[] awoke = new boolean[1];
-                queue.registerFileDescriptorCallback(reader2.getFD(),
-                        FileDescriptorCallback.EVENT_INPUT, new FileDescriptorCallback() {
+                queue.addOnFileDescriptorEventListener(reader2.getFD(),
+                        OnFileDescriptorEventListener.EVENT_INPUT, new OnFileDescriptorEventListener() {
                     @Override
                     public int onFileDescriptorEvents(FileDescriptor fd, int events) {
                         awoke[0] = true;
@@ -487,8 +492,8 @@
                     final FileOutputStream writer = new AutoCloseOutputStream(pipe[1])) {
                 // Register the callback.
                 final boolean[] awoke = new boolean[1];
-                queue.registerFileDescriptorCallback(reader.getFD(),
-                        FileDescriptorCallback.EVENT_ERROR, new FileDescriptorCallback() {
+                queue.addOnFileDescriptorEventListener(reader.getFD(),
+                        OnFileDescriptorEventListener.EVENT_ERROR, new OnFileDescriptorEventListener() {
                     @Override
                     public int onFileDescriptorEvents(FileDescriptor fd, int events) {
                         awoke[0] = true;
@@ -528,8 +533,8 @@
                     final FileOutputStream writer2 = new AutoCloseOutputStream(pipe[1])) {
                 // Register the callback.
                 final boolean[] awoke = new boolean[1];
-                queue.registerFileDescriptorCallback(reader2.getFD(),
-                        FileDescriptorCallback.EVENT_INPUT, new FileDescriptorCallback() {
+                queue.addOnFileDescriptorEventListener(reader2.getFD(),
+                        OnFileDescriptorEventListener.EVENT_INPUT, new OnFileDescriptorEventListener() {
                     @Override
                     public int onFileDescriptorEvents(FileDescriptor fd, int events) {
                         awoke[0] = true;
@@ -580,8 +585,8 @@
                     final FileOutputStream writer = new AutoCloseOutputStream(pipe[1])) {
                 // Register the callback.
                 final boolean[] awoke = new boolean[1];
-                queue.registerFileDescriptorCallback(reader.getFD(),
-                        FileDescriptorCallback.EVENT_ERROR, new FileDescriptorCallback() {
+                queue.addOnFileDescriptorEventListener(reader.getFD(),
+                        OnFileDescriptorEventListener.EVENT_ERROR, new OnFileDescriptorEventListener() {
                     @Override
                     public int onFileDescriptorEvents(FileDescriptor fd, int events) {
                         awoke[0] = true;
@@ -605,9 +610,9 @@
                         }
 
                         // Now we have a new pipe, make sure we can register it successfully.
-                        queue.registerFileDescriptorCallback(pipe[0].getFileDescriptor(),
-                                FileDescriptorCallback.EVENT_INPUT,
-                                new FileDescriptorCallback() {
+                        queue.addOnFileDescriptorEventListener(pipe[0].getFileDescriptor(),
+                                OnFileDescriptorEventListener.EVENT_INPUT,
+                                new OnFileDescriptorEventListener() {
                             @Override
                             public int onFileDescriptorEvents(FileDescriptor fd, int events) {
                                 awoke2[0] = true;
@@ -672,8 +677,8 @@
                         final FileOutputStream writer = new AutoCloseOutputStream(pipe[1])) {
                     // Register the callback.
                     final boolean[] awoke = new boolean[1];
-                    queue.registerFileDescriptorCallback(reader.getFD(),
-                            FileDescriptorCallback.EVENT_ERROR, new FileDescriptorCallback() {
+                    queue.addOnFileDescriptorEventListener(reader.getFD(),
+                            OnFileDescriptorEventListener.EVENT_ERROR, new OnFileDescriptorEventListener() {
                         @Override
                         public int onFileDescriptorEvents(FileDescriptor fd, int events) {
                             awoke[0] = true;
diff --git a/tests/tests/os/src/android/os/cts/SeccompTest.java b/tests/tests/os/src/android/os/cts/SeccompTest.java
index 6c49337..e8de783 100644
--- a/tests/tests/os/src/android/os/cts/SeccompTest.java
+++ b/tests/tests/os/src/android/os/cts/SeccompTest.java
@@ -19,6 +19,9 @@
 import junit.framework.TestCase;
 
 public class SeccompTest extends TestCase {
+    static {
+        System.loadLibrary("ctsos_jni");
+    }
 
     public void testSeccomp() {
         if (CpuFeatures.isArm64Cpu() || CpuFeatures.isArm64CpuIn32BitMode()) {
@@ -30,4 +33,116 @@
                        OSFeatures.hasSeccompSupport());
         }
     }
+
+    public void testKernelBasicTests() {
+        if (!OSFeatures.needsSeccompSupport())
+            return;
+
+        final String[] tests = {
+            "global.mode_strict_support",
+            "global.mode_strict_cannot_call_prctl",
+            "global.no_new_privs_support",
+            "global.mode_filter_support",
+            /* "global.mode_filter_without_nnp", // all Android processes already have nnp */
+            "global.filter_size_limits",
+            "global.filter_chain_limits",
+            "global.mode_filter_cannot_move_to_strict",
+            "global.mode_filter_get_seccomp",
+            "global.ALLOW_all",
+            "global.empty_prog",
+            "global.unknown_ret_is_kill_inside",
+            "global.unknown_ret_is_kill_above_allow",
+            "global.KILL_all",
+            "global.KILL_one",
+            "global.KILL_one_arg_one",
+            "global.KILL_one_arg_six",
+            "global.arg_out_of_range",
+            "global.ERRNO_one",
+            "global.ERRNO_one_ok",
+        };
+        runKernelUnitTestSuite(tests);
+    }
+
+    public void testKernelTrapTests() {
+        if (!OSFeatures.needsSeccompSupport())
+            return;
+
+        final String[] tests = {
+            "TRAP.dfl",
+            "TRAP.ign",
+            "TRAP.handler",
+        };
+        runKernelUnitTestSuite(tests);
+    }
+
+    public void testKernelPrecedenceTests() {
+        if (!OSFeatures.needsSeccompSupport())
+            return;
+
+        final String[] tests = {
+            "precedence.allow_ok",
+            "precedence.kill_is_highest",
+            "precedence.kill_is_highest_in_any_order",
+            "precedence.trap_is_second",
+            "precedence.trap_is_second_in_any_order",
+            "precedence.errno_is_third",
+            "precedence.errno_is_third_in_any_order",
+            "precedence.trace_is_fourth",
+            "precedence.trace_is_fourth_in_any_order",
+        };
+        runKernelUnitTestSuite(tests);
+    }
+
+    /* // The SECCOMP_RET_TRACE does not work under Android Arm32.
+    public void testKernelTraceTests() {
+        if (!OSFeatures.needsSeccompSupport())
+            return;
+
+        final String[] tests = {
+            "TRACE_poke.read_has_side_effects",
+            "TRACE_poke.getpid_runs_normally",
+            "TRACE_syscall.syscall_allowed",
+            "TRACE_syscall.syscall_redirected",
+            "TRACE_syscall.syscall_dropped",
+        };
+        runKernelUnitTestSuite(tests);
+    }
+    */
+
+    public void testKernelTSYNCTests() {
+        if (!OSFeatures.needsSeccompSupport())
+            return;
+
+        final String[] tests = {
+            "global.seccomp_syscall",
+            "global.seccomp_syscall_mode_lock",
+            "global.TSYNC_first",
+            "TSYNC.siblings_fail_prctl",
+            "TSYNC.two_siblings_with_ancestor",
+            /* "TSYNC.two_sibling_want_nnp", // all Android processes already have nnp */
+            "TSYNC.two_siblings_with_no_filter",
+            "TSYNC.two_siblings_with_one_divergence",
+            "TSYNC.two_siblings_not_under_filter",
+            /* "global.syscall_restart", // ptrace attach fails */
+        };
+        runKernelUnitTestSuite(tests);
+    }
+
+    /**
+     * Runs a kernel unit test suite (an array of kernel test names).
+     */
+    private void runKernelUnitTestSuite(final String[] tests) {
+        for (final String test : tests) {
+            // TODO: Replace the URL with the documentation when it's finished.
+            assertTrue(test + " failed. This test requires kernel functionality to pass. "
+                       + "Please go to http://XXXXX for instructions on how to enable or "
+                       + "backport the required functionality.",
+                       runKernelUnitTest(test));
+        }
+    }
+
+    /**
+     * Runs the seccomp_bpf_unittest of the given name.
+     */
+    private native boolean runKernelUnitTest(final String name);
 }
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_AuthorizationTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_AuthorizationTest.java
deleted file mode 100644
index 3fea65d..0000000
--- a/tests/tests/provider/src/android/provider/cts/ContactsContract_AuthorizationTest.java
+++ /dev/null
@@ -1,149 +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 android.provider.cts;
-
-import android.content.ContentProviderClient;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.StructuredName;
-import android.provider.ContactsContract.Contacts;
-import android.provider.ContactsContract.Contacts.AggregationSuggestions;
-import android.provider.ContactsContract.RawContacts;
-import android.provider.cts.ContactsContract_TestDataBuilder.TestContact;
-import android.provider.cts.ContactsContract_TestDataBuilder.TestRawContact;
-import android.provider.cts.contacts.DatabaseAsserts;
-import android.test.AndroidTestCase;
-
-/**
- * CTS tests for {@link android.provider.ContactsContract.Authorization} APIs.
- *
- * It isn't possible to fully test the Authorization API. Suppose this apk doesn't have
- * the necessary permissions. In this case, we can't call the authorization API in the first place.
- * On the other hand, suppose this apk does have the necessary permissions. In this case, we can't
- * check that the Authorization API added any permissions to the URI since we could already use the
- * URI anyway.
- */
-public class ContactsContract_AuthorizationTest extends AndroidTestCase {
-    private static final String[] TEST_PROJECTION = new String[] {Contacts.DISPLAY_NAME};
-
-    private ContentResolver mResolver;
-    private ContactsContract_TestDataBuilder mBuilder;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mResolver = getContext().getContentResolver();
-        ContentProviderClient provider =
-                mResolver.acquireContentProviderClient(ContactsContract.AUTHORITY);
-        mBuilder = new ContactsContract_TestDataBuilder(provider);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
-        mBuilder.cleanup();
-    }
-
-    public void testAuthorization_contact1() throws Exception {
-        // Setup
-        Uri [] contactUris = setupTwoContacts();
-
-        // Execute
-        Uri preAuthorizedUri = getPreAuthorizedUri(contactUris[0]);
-
-        // Verify: the pre-authorized URI is different than the original URI, but still works.
-        assertNotSame(preAuthorizedUri, contactUris[0]);
-        Cursor cursor = mResolver.query(preAuthorizedUri, TEST_PROJECTION, null, null, null);
-        assertEquals(1, cursor.getCount());
-        ContentValues values = new ContentValues();
-        values.put(Contacts.DISPLAY_NAME, "first1 last1");
-        DatabaseAsserts.assertCursorValuesMatchExactly(cursor, values);
-        cursor.close();
-    }
-
-    public void testAuthorization_contact2() throws Exception {
-        // Setup
-        Uri [] contactUris = setupTwoContacts();
-
-        // Execute
-        Uri preAuthorizedUri = getPreAuthorizedUri(contactUris[1]);
-
-        // Verify: the pre-authorized URI is different than the original URI, but still works.
-        assertNotSame(preAuthorizedUri, contactUris[1]);
-        Cursor cursor = mResolver.query(preAuthorizedUri, TEST_PROJECTION, null, null, null);
-        assertEquals(1, cursor.getCount());
-        ContentValues values = new ContentValues();
-        values.put(Contacts.DISPLAY_NAME, "first2 last2");
-        DatabaseAsserts.assertCursorValuesMatchExactly(cursor, values);
-        cursor.close();
-    }
-
-    public void testAuthorization_profile() throws Exception {
-        try {
-            getPreAuthorizedUri(ContactsContract.Profile.CONTENT_URI);
-            fail("getPreAuthorizedUri(ContactsContract.Profile.CONTENT_URI) did not throw"
-                    + "SecurityException as expected");
-        } catch (SecurityException se) {
-            // Verify: can't authorize a profile URI without the READ_PROFILE permission.
-        }
-    }
-
-    private Uri getPreAuthorizedUri(Uri uri) {
-        final Bundle uriBundle = new Bundle();
-        uriBundle.putParcelable(ContactsContract.Authorization.KEY_URI_TO_AUTHORIZE, uri);
-        final Bundle authResponse = mResolver.call(
-                ContactsContract.AUTHORITY_URI,
-                ContactsContract.Authorization.AUTHORIZATION_METHOD,
-                null,
-                uriBundle);
-        return authResponse.getParcelable(ContactsContract.Authorization.KEY_AUTHORIZED_URI);
-    }
-
-    private Uri[] setupTwoContacts() throws Exception {
-        TestRawContact rawContact1 = mBuilder.newRawContact()
-                .with(RawContacts.ACCOUNT_TYPE, "test_account")
-                .with(RawContacts.ACCOUNT_NAME, "test_name")
-                .insert();
-        rawContact1.newDataRow(StructuredName.CONTENT_ITEM_TYPE)
-                .with(StructuredName.GIVEN_NAME, "first1")
-                .with(StructuredName.FAMILY_NAME, "last1")
-                .insert();
-        rawContact1.load();
-        TestContact testContact1 = rawContact1.getContact().load();
-        Uri contactUri1 = testContact1.getUri();
-
-        TestRawContact rawContact2 = mBuilder.newRawContact()
-                .with(RawContacts.ACCOUNT_TYPE, "test_account")
-                .with(RawContacts.ACCOUNT_NAME, "test_name")
-                .insert();
-        rawContact2.newDataRow(StructuredName.CONTENT_ITEM_TYPE)
-                .with(StructuredName.GIVEN_NAME, "first2")
-                .with(StructuredName.FAMILY_NAME, "last2")
-                .insert();
-        rawContact2.load();
-        TestContact testContact2 = rawContact2.getContact().load();
-        Uri contactUri2 = testContact2.getUri();
-
-        return new Uri[] {contactUri1, contactUri2};
-    }
-
-}
-
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_IsSuperPrimaryName.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_IsSuperPrimaryName.java
index 4ff6a88..603cb619 100644
--- a/tests/tests/provider/src/android/provider/cts/ContactsContract_IsSuperPrimaryName.java
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_IsSuperPrimaryName.java
@@ -112,10 +112,10 @@
         //
 
         // Execute: make the non primary name IS_SUPER_PRIMARY
-        TestData nonPrimaryName = isFirstNamePrimary ? name1 : name2;
+        TestData nonPrimaryName = !isFirstNamePrimary ? name1 : name2;
         ContentValues values = new ContentValues();
         values.put(StructuredName.IS_SUPER_PRIMARY, 1);
-        mResolver.update(nonPrimaryName.getContentUri(), values, null, null);
+        mResolver.update(nonPrimaryName.getUri(), values, null, null);
 
         // Verify: the IS_SUPER_PRIMARY values swap
         name1.load();
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_ProviderStatus.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_ProviderStatus.java
deleted file mode 100644
index 54bea8e..0000000
--- a/tests/tests/provider/src/android/provider/cts/ContactsContract_ProviderStatus.java
+++ /dev/null
@@ -1,85 +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 android.provider.cts;
-
-import android.content.ContentProviderClient;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.StructuredName;
-import android.provider.ContactsContract.ProviderStatus;
-import android.provider.ContactsContract.RawContacts;
-import android.provider.cts.ContactsContract_TestDataBuilder.TestRawContact;
-import android.provider.cts.contacts.DatabaseAsserts;
-import android.test.AndroidTestCase;
-
-/**
- * CTS tests for {@link android.provider.ContactsContract.ProviderStatus}.
- *
- * Unfortunately, we can't check that the value of ProviderStatus equals
- * {@link ProviderStatus#STATUS_NO_ACCOUNTS_NO_CONTACTS} initially. Some carriers pre-install
- * accounts. As a result, the value STATUS_NO_ACCOUNTS_NO_CONTACTS will never be achieved.
- */
-public class ContactsContract_ProviderStatus extends AndroidTestCase {
-    private ContentResolver mResolver;
-    private ContactsContract_TestDataBuilder mBuilder;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mResolver = getContext().getContentResolver();
-        ContentProviderClient provider =
-                mResolver.acquireContentProviderClient(ContactsContract.AUTHORITY);
-        mBuilder = new ContactsContract_TestDataBuilder(provider);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
-        mBuilder.cleanup();
-    }
-
-    public void testProviderStatus_addedContacts() throws Exception {
-        // Setup: add a contact to CP2.
-        TestRawContact rawContact1 = mBuilder.newRawContact()
-                .with(RawContacts.ACCOUNT_TYPE, "test_account")
-                .with(RawContacts.ACCOUNT_NAME, "test_name")
-                .insert();
-        rawContact1.newDataRow(StructuredName.CONTENT_ITEM_TYPE)
-                .with(StructuredName.GIVEN_NAME, "first1")
-                .with(StructuredName.FAMILY_NAME, "last1")
-                .insert();
-
-        // Execute: fetch CP2 status
-        Cursor cursor = mResolver.query(ProviderStatus.CONTENT_URI, null, null, null, null);
-
-        // Verify: CP2 status is normal instead of STATUS_NO_ACCOUNTS_NO_CONTACTS.
-        try {
-            assertEquals(1, cursor.getCount());
-            cursor.moveToFirst();
-            ContentValues values = new ContentValues();
-            values.put(ProviderStatus.STATUS, ProviderStatus.STATUS_NORMAL);
-            DatabaseAsserts.assertCursorValuesMatchExactly(cursor, values);
-        } finally {
-            if (cursor != null) {
-                cursor.close();
-            }
-        }
-    }
-}
-
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/ElementTest.java b/tests/tests/renderscript/src/android/renderscript/cts/ElementTest.java
index 131b3fd4..9fa9c15 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/ElementTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/ElementTest.java
@@ -183,6 +183,13 @@
         // A_8 is in U8
         Element[] BOOLEAN = { Element.BOOLEAN(mRS) };
         Element[] ELEMENT = { Element.ELEMENT(mRS) };
+        Element[] F16 = { Element.F16(mRS) };
+        Element[] F16_2 = { Element.F16_2(mRS),
+            Element.createVector(mRS, Element.DataType.FLOAT_16, 2) };
+        Element[] F16_3 = { Element.F16_3(mRS),
+            Element.createVector(mRS, Element.DataType.FLOAT_16, 3) };
+        Element[] F16_4 = { Element.F16_4(mRS),
+            Element.createVector(mRS, Element.DataType.FLOAT_16, 4) };
         Element[] F32 = { Element.F32(mRS) };
         Element[] F32_2 = { Element.F32_2(mRS),
             Element.createVector(mRS, Element.DataType.FLOAT_32, 2) };
@@ -236,8 +243,10 @@
             Element.createPixel(mRS, Element.DataType.UNSIGNED_8,
                                 Element.DataKind.PIXEL_RGBA) };
 
-        Element[][] ElementArrs = { ALLOCATION, BOOLEAN, ELEMENT, F32, F32_2,
-                                    F32_3, F32_4, F64, I16, I32, I64, I8,
+        Element[][] ElementArrs = { ALLOCATION, BOOLEAN, ELEMENT,
+                                    F16, F16_2, F16_3, F16_4,
+                                    F32, F32_2, F32_3, F32_4,
+                                    F64, I16, I32, I64, I8,
                                     MATRIX_2X2, MATRIX_3X3, MATRIX_4X4, MESH,
                                     PROGRAM_FRAGMENT, PROGRAM_RASTER,
                                     PROGRAM_STORE, PROGRAM_VERTEX, RGBA_4444,
@@ -272,6 +281,10 @@
             eb.add(Element.RGB_565(mRS), "RGB_565", arraySize);
             eb.add(Element.RGB_888(mRS), "RGB_888", arraySize);
             eb.add(Element.RGBA_8888(mRS), "RGBA_8888", arraySize);
+            eb.add(Element.F16(mRS), "F16", arraySize);
+            eb.add(Element.F16_2(mRS), "F16_2", arraySize);
+            eb.add(Element.F16_3(mRS), "F16_3", arraySize);
+            eb.add(Element.F16_4(mRS), "F16_4", arraySize);
             eb.add(Element.F32(mRS), "F32", arraySize);
             eb.add(Element.F32_2(mRS), "F32_2", arraySize);
             eb.add(Element.F32_3(mRS), "F32_3", arraySize);
@@ -338,6 +351,10 @@
         assertFalse(Element.RGB_565(mRS).isComplex());
         assertFalse(Element.RGB_888(mRS).isComplex());
         assertFalse(Element.RGBA_8888(mRS).isComplex());
+        assertFalse(Element.F16(mRS).isComplex());
+        assertFalse(Element.F16_2(mRS).isComplex());
+        assertFalse(Element.F16_3(mRS).isComplex());
+        assertFalse(Element.F16_4(mRS).isComplex());
         assertFalse(Element.F32(mRS).isComplex());
         assertFalse(Element.F32_2(mRS).isComplex());
         assertFalse(Element.F32_3(mRS).isComplex());
@@ -416,6 +433,7 @@
         // Uncomment when NONE is no longer hidden.
         //assertEquals(DataType.NONE, DataType.valueOf("NONE"));
 
+        assertEquals(DataType.FLOAT_16, DataType.valueOf("FLOAT_16"));
         assertEquals(DataType.FLOAT_32, DataType.valueOf("FLOAT_32"));
         assertEquals(DataType.FLOAT_64, DataType.valueOf("FLOAT_64"));
         assertEquals(DataType.SIGNED_8, DataType.valueOf("SIGNED_8"));
@@ -452,6 +470,7 @@
 
         for (DataType dt : DataType.values()) {
             switch (dt) {
+            case FLOAT_16:
             case FLOAT_32:
             case FLOAT_64:
             case SIGNED_8:
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/Intrinsic3DLut.java b/tests/tests/renderscript/src/android/renderscript/cts/Intrinsic3DLut.java
index 87a03ad..4ec84ad 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/Intrinsic3DLut.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/Intrinsic3DLut.java
@@ -136,5 +136,12 @@
         checkError();
     }
 
+    public void test_ID() {
+        ScriptIntrinsic3DLUT s = ScriptIntrinsic3DLUT.create(mRS, Element.U8_4(mRS));
+        Script.KernelID kid = s.getKernelID();
+        if (kid == null) {
+            throw new IllegalStateException("kid must be valid");
+        }
+    }
 
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicBlur.java b/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicBlur.java
index 076dcd4..4e99391 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicBlur.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicBlur.java
@@ -141,5 +141,17 @@
         checkError();
     }
 
+    public void test_ID() {
+        ScriptIntrinsicBlur s = ScriptIntrinsicBlur.create(mRS, Element.U8_4(mRS));
+        Script.KernelID kid = s.getKernelID();
+        if (kid == null) {
+            throw new IllegalStateException("kid must be valid");
+        }
+
+        Script.FieldID fid = s.getFieldID_Input();
+        if (fid == null) {
+            throw new IllegalStateException("fid must be valid");
+        }
+    }
 
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicConvolve3x3.java b/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicConvolve3x3.java
index 8faeb22..8a2bc27 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicConvolve3x3.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicConvolve3x3.java
@@ -247,4 +247,17 @@
         checkError();
     }
 
+    public void test_ID() {
+        ScriptIntrinsicConvolve3x3 s = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS));
+        Script.KernelID kid = s.getKernelID();
+        if (kid == null) {
+            throw new IllegalStateException("kid must be valid");
+        }
+
+        Script.FieldID fid = s.getFieldID_Input();
+        if (fid == null) {
+            throw new IllegalStateException("fid must be valid");
+        }
+    }
+
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicConvolve5x5.java b/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicConvolve5x5.java
index 0753c62..410aebd 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicConvolve5x5.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicConvolve5x5.java
@@ -184,4 +184,17 @@
         checkError();
     }
 
+    public void test_ID() {
+        ScriptIntrinsicConvolve5x5 s = ScriptIntrinsicConvolve5x5.create(mRS, Element.U8_4(mRS));
+        Script.KernelID kid = s.getKernelID();
+        if (kid == null) {
+            throw new IllegalStateException("kid must be valid");
+        }
+
+        Script.FieldID fid = s.getFieldID_Input();
+        if (fid == null) {
+            throw new IllegalStateException("fid must be valid");
+        }
+    }
+
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicLut.java b/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicLut.java
index 1567639..3309bb0 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicLut.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicLut.java
@@ -83,5 +83,12 @@
     }
 
 
+    public void test_ID() {
+        ScriptIntrinsicLUT s = ScriptIntrinsicLUT.create(mRS, Element.U8_4(mRS));
+        Script.KernelID kid = s.getKernelID();
+        if (kid == null) {
+            throw new IllegalStateException("kid must be valid");
+        }
+    }
 
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TypeTest.java b/tests/tests/renderscript/src/android/renderscript/cts/TypeTest.java
index 13d4977..abb532d 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/TypeTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TypeTest.java
@@ -143,6 +143,14 @@
         assertTrue(t.getY() == 4);
     }
 
+    public void testGetYuv() {
+        Type.Builder b = new Type.Builder(mRS, Element.F32(mRS));
+        b.setX(64).setY(64);
+        b.setYuvFormat(android.graphics.ImageFormat.YV12);
+        Type t = b.create();
+        assertTrue(t.getYuv() == android.graphics.ImageFormat.YV12);
+    }
+
     public void testGetZ() {
         Type.Builder b = new Type.Builder(mRS, Element.F32(mRS));
         b.setX(3).setY(4);
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/intrinsic_blur.rs b/tests/tests/renderscript/src/android/renderscript/cts/intrinsic_blur.rs
index 88f9ca5..aea9745 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/intrinsic_blur.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/intrinsic_blur.rs
@@ -74,7 +74,7 @@
     float4 blurredPixel = 0;
     int gi = 0;
     for (int r = -radius; r <= radius; r ++) {
-        int validH = rsClamp((int)y + r, (int)0, (int)(height - 1));
+        int validH = clamp((int)y + r, (int)0, (int)(height - 1));
         float4 i = rsGetElementAt_float4(ScratchPixel2, x, validH);
         blurredPixel += i * gaussian[gi++];
     }
@@ -86,11 +86,9 @@
     int gi = 0;
     for (int r = -radius; r <= radius; r ++) {
         // Stepping left and right away from the pixel
-        int validX = rsClamp((int)x + r, (int)0, (int)(width - 1));
+        int validX = clamp((int)x + r, (int)0, (int)(width - 1));
         float4 i = rsGetElementAt_float4(ScratchPixel1, validX, y);
         blurredPixel += i * gaussian[gi++];
     }
     return blurredPixel;
 }
-
-
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/shared.rsh b/tests/tests/renderscript/src/android/renderscript/cts/shared.rsh
index b91611d..2ad81fc 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/shared.rsh
+++ b/tests/tests/renderscript/src/android/renderscript/cts/shared.rsh
@@ -3,11 +3,11 @@
 
 static int64_t g_time;
 
-static void start(void) {
+static inline void start(void) {
     g_time = rsUptimeMillis();
 }
 
-static float end(void) {
+static inline float end(void) {
     int64_t t = rsUptimeMillis() - g_time;
     return ((float)t) / 1000.f;
 }
@@ -24,4 +24,3 @@
 /* These constants must match those in UnitTest.java */
 static const int RS_MSG_TEST_PASSED = 100;
 static const int RS_MSG_TEST_FAILED = 101;
-
diff --git a/tests/tests/text/src/android/text/cts/BidiFormatterTest.java b/tests/tests/text/src/android/text/cts/BidiFormatterTest.java
index 645ab5b..5ace8b2 100644
--- a/tests/tests/text/src/android/text/cts/BidiFormatterTest.java
+++ b/tests/tests/text/src/android/text/cts/BidiFormatterTest.java
@@ -107,6 +107,9 @@
     }
 
     public void testUnicodeWrap() {
+        // Make sure an input of null doesn't crash anything.
+        assertNull(LTR_FMT.unicodeWrap(null));
+
         // Uniform directionality in opposite context.
         assertEquals("uniform dir opposite to LTR context",
                 RLE + "." + HE + "." + PDF + LRM,
diff --git a/tests/tests/tv/AndroidManifest.xml b/tests/tests/tv/AndroidManifest.xml
index c11694e..79406e0 100644
--- a/tests/tests/tv/AndroidManifest.xml
+++ b/tests/tests/tv/AndroidManifest.xml
@@ -67,6 +67,15 @@
                        android:resource="@xml/stub_tv_input_service" />
         </service>
 
+        <service android:name="android.media.tv.cts.TvInputManagerTest$StubTvInputService2"
+                 android:permission="android.permission.BIND_TV_INPUT">
+            <intent-filter>
+                <action android:name="android.media.tv.TvInputService" />
+            </intent-filter>
+            <meta-data android:name="android.media.tv.input"
+                       android:resource="@xml/stub_tv_input_service" />
+        </service>
+
         <service android:name="android.media.tv.cts.TvInputServiceTest$CountingTvInputService"
                  android:permission="android.permission.BIND_TV_INPUT">
             <intent-filter>
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java b/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java
index 2082d3f..b4bc6eb 100644
--- a/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java
@@ -26,6 +26,8 @@
 import android.graphics.BitmapFactory;
 import android.media.tv.TvContentRating;
 import android.media.tv.TvContract;
+import android.media.tv.TvContract.Channels;
+import android.media.tv.TvContract.Programs.Genres;
 import android.net.Uri;
 import android.test.AndroidTestCase;
 
@@ -33,6 +35,8 @@
 
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.List;
 
 /**
  * Test for {@link android.media.tv.TvContract}.
@@ -80,6 +84,11 @@
 
     private static long OPERATION_TIME = 1000l;
 
+    private static final String ENCODED_GENRE_STRING = Genres.ANIMAL_WILDLIFE + "," + Genres.COMEDY
+            + "," + Genres.DRAMA + "," + Genres.EDUCATION + "," + Genres.FAMILY_KIDS + ","
+            + Genres.GAMING + "," + Genres.MOVIES + "," + Genres.NEWS + "," + Genres.SHOPPING + ","
+            + Genres.SPORTS + "," + Genres.TRAVEL;
+
     private String mInputId;
     private ContentResolver mContentResolver;
     private Uri mChannelsUri;
@@ -510,7 +519,6 @@
         values.put(TvContract.Channels.COLUMN_INPUT_ID, mInputId);
         Uri channelUri = mContentResolver.insert(mChannelsUri, values);
         assertNotNull(channelUri);
-        long channelId = ContentUris.parseId(channelUri);
         try (Cursor cursor = mContentResolver.query(
                 channelUri, CHANNELS_PROJECTION, null, null, null)) {
             cursor.moveToNext();
@@ -522,4 +530,58 @@
         }
         values.clear();
     }
+
+    public void testChannelsGetVideoResolution() {
+        if (!Utils.hasTvInputFramework(getContext())) {
+            return;
+        }
+        assertEquals(Channels.VIDEO_RESOLUTION_SD, Channels.getVideoResolution(
+                Channels.VIDEO_FORMAT_480I));
+        assertEquals(Channels.VIDEO_RESOLUTION_ED, Channels.getVideoResolution(
+                Channels.VIDEO_FORMAT_480P));
+        assertEquals(Channels.VIDEO_RESOLUTION_SD, Channels.getVideoResolution(
+                Channels.VIDEO_FORMAT_576I));
+        assertEquals(Channels.VIDEO_RESOLUTION_ED, Channels.getVideoResolution(
+                Channels.VIDEO_FORMAT_576P));
+        assertEquals(Channels.VIDEO_RESOLUTION_HD, Channels.getVideoResolution(
+                Channels.VIDEO_FORMAT_720P));
+        assertEquals(Channels.VIDEO_RESOLUTION_HD, Channels.getVideoResolution(
+                Channels.VIDEO_FORMAT_1080I));
+        assertEquals(Channels.VIDEO_RESOLUTION_FHD, Channels.getVideoResolution(
+                Channels.VIDEO_FORMAT_1080P));
+        assertEquals(Channels.VIDEO_RESOLUTION_UHD, Channels.getVideoResolution(
+                Channels.VIDEO_FORMAT_2160P));
+        assertEquals(Channels.VIDEO_RESOLUTION_UHD, Channels.getVideoResolution(
+                Channels.VIDEO_FORMAT_4320P));
+        assertEquals(null, Channels.getVideoResolution("Unknown format"));
+    }
+
+    public void testProgramsGenresDecode() {
+        if (!Utils.hasTvInputFramework(getContext())) {
+            return;
+        }
+        List genres = Arrays.asList(Genres.decode(ENCODED_GENRE_STRING));
+        assertEquals(11, genres.size());
+        assertTrue(genres.contains(Genres.ANIMAL_WILDLIFE));
+        assertTrue(genres.contains(Genres.COMEDY));
+        assertTrue(genres.contains(Genres.DRAMA));
+        assertTrue(genres.contains(Genres.EDUCATION));
+        assertTrue(genres.contains(Genres.FAMILY_KIDS));
+        assertTrue(genres.contains(Genres.GAMING));
+        assertTrue(genres.contains(Genres.MOVIES));
+        assertTrue(genres.contains(Genres.NEWS));
+        assertTrue(genres.contains(Genres.SHOPPING));
+        assertTrue(genres.contains(Genres.SPORTS));
+        assertTrue(genres.contains(Genres.TRAVEL));
+        assertFalse(genres.contains(","));
+    }
+
+    public void testProgramsGenresEncode() {
+        if (!Utils.hasTvInputFramework(getContext())) {
+            return;
+        }
+        assertEquals(ENCODED_GENRE_STRING, Genres.encode(Genres.ANIMAL_WILDLIFE,
+                Genres.COMEDY, Genres.DRAMA, Genres.EDUCATION, Genres.FAMILY_KIDS, Genres.GAMING,
+                Genres.MOVIES, Genres.NEWS, Genres.SHOPPING, Genres.SPORTS, Genres.TRAVEL));
+    }
 }
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvInputInfoTest.java b/tests/tests/tv/src/android/media/tv/cts/TvInputInfoTest.java
index 440ecb2..de91916 100644
--- a/tests/tests/tv/src/android/media/tv/cts/TvInputInfoTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/TvInputInfoTest.java
@@ -20,8 +20,10 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.media.tv.TvContract;
 import android.media.tv.TvInputInfo;
 import android.media.tv.TvInputManager;
+import android.os.Parcel;
 import android.test.AndroidTestCase;
 
 /**
@@ -48,6 +50,53 @@
         mPackageManager = getContext().getPackageManager();
     }
 
+    public void testTvInputInfoOp() throws Exception {
+        if (!Utils.hasTvInputFramework(getContext())) {
+            return;
+        }
+        // Test describeContents
+        assertEquals(0, mStubInfo.describeContents());
+
+        // Test equals
+        assertTrue(mStubInfo.equals(mStubInfo));
+
+        // Test getId
+        final ComponentName componentName =
+                new ComponentName(getContext(), StubTunerTvInputService.class);
+        final String id = TvContract.buildInputId(componentName);
+        assertEquals(id, mStubInfo.getId());
+
+        // Test getServiceInfo
+        assertEquals(getContext().getPackageManager().getServiceInfo(componentName, 0).name,
+                mStubInfo.getServiceInfo().name);
+
+        // Test hashCode
+        assertEquals(id.hashCode(), mStubInfo.hashCode());
+
+        // Test writeToParcel
+        Parcel p = Parcel.obtain();
+        mStubInfo.writeToParcel(p, 0);
+        p.setDataPosition(0);
+        TvInputInfo infoFromParcel = TvInputInfo.CREATOR.createFromParcel(p);
+        assertEquals(mStubInfo.createSettingsIntent().getComponent(),
+                infoFromParcel.createSettingsIntent().getComponent());
+        assertEquals(mStubInfo.createSetupIntent().getComponent(),
+                infoFromParcel.createSetupIntent().getComponent());
+        assertEquals(mStubInfo.describeContents(), infoFromParcel.describeContents());
+        assertTrue(mStubInfo.equals(infoFromParcel));
+        assertEquals(mStubInfo.getId(), infoFromParcel.getId());
+        assertEquals(mStubInfo.getParentId(), infoFromParcel.getParentId());
+        assertEquals(mStubInfo.getServiceInfo().name, infoFromParcel.getServiceInfo().name);
+        assertEquals(mStubInfo.getType(), infoFromParcel.getType());
+        assertEquals(mStubInfo.hashCode(), infoFromParcel.hashCode());
+        assertEquals(mStubInfo.isPassthroughInput(), infoFromParcel.isPassthroughInput());
+        assertEquals(mStubInfo.loadIcon(getContext()).getConstantState(),
+                infoFromParcel.loadIcon(getContext()).getConstantState());
+        assertEquals(mStubInfo.loadLabel(getContext()), infoFromParcel.loadLabel(getContext()));
+        assertEquals(mStubInfo.toString(), infoFromParcel.toString());
+        p.recycle();
+    }
+
     public void testGetIntentForSettingsActivity() throws Exception {
         if (!Utils.hasTvInputFramework(getContext())) {
             return;
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvInputManagerTest.java b/tests/tests/tv/src/android/media/tv/cts/TvInputManagerTest.java
index 790adf9..ff66dc6 100644
--- a/tests/tests/tv/src/android/media/tv/cts/TvInputManagerTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/TvInputManagerTest.java
@@ -16,26 +16,38 @@
 
 package android.media.tv.cts;
 
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.pm.PackageManager;
+import android.cts.util.PollingCheck;
+import android.media.tv.TvContentRating;
 import android.media.tv.TvInputInfo;
 import android.media.tv.TvInputManager;
-import android.test.AndroidTestCase;
+import android.os.Handler;
+import android.test.ActivityInstrumentationTestCase2;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
  * Test for {@link android.media.tv.TvInputManager}.
  */
-public class TvInputManagerTest extends AndroidTestCase {
+public class TvInputManagerTest extends ActivityInstrumentationTestCase2<TvViewStubActivity> {
+    /** The maximum time to wait for an operation. */
+    private static final long TIME_OUT_MS = 15000L;
+
     private static final String[] VALID_TV_INPUT_SERVICES = {
         StubTunerTvInputService.class.getName()
     };
     private static final String[] INVALID_TV_INPUT_SERVICES = {
         NoMetadataTvInputService.class.getName(), NoPermissionTvInputService.class.getName()
     };
+    private static final TvContentRating DUMMY_RATING = TvContentRating.createRating(
+            "com.android.tv", "US_TV", "US_TV_PG", "US_TV_D", "US_TV_L");
 
     private String mStubId;
     private TvInputManager mManager;
+    private LoggingCallback mCallabck = new LoggingCallback();
 
     private static TvInputInfo getInfoForClassName(List<TvInputInfo> list, String name) {
         for (TvInputInfo info : list) {
@@ -46,33 +58,37 @@
         return null;
     }
 
+    public TvInputManagerTest() {
+        super(TvViewStubActivity.class);
+    }
+
     @Override
     public void setUp() throws Exception {
-        if (!Utils.hasTvInputFramework(getContext())) {
+        if (!Utils.hasTvInputFramework(getActivity())) {
             return;
         }
-        mManager = (TvInputManager) mContext.getSystemService(Context.TV_INPUT_SERVICE);
+        mManager = (TvInputManager) getActivity().getSystemService(Context.TV_INPUT_SERVICE);
         mStubId = getInfoForClassName(
-                mManager.getTvInputList(), StubTunerTvInputService.class.getName()).getId();
+                mManager.getTvInputList(), StubTvInputService2.class.getName()).getId();
     }
 
     public void testGetInputState() throws Exception {
-        if (!Utils.hasTvInputFramework(getContext())) {
+        if (!Utils.hasTvInputFramework(getActivity())) {
             return;
         }
         assertEquals(mManager.getInputState(mStubId), TvInputManager.INPUT_STATE_CONNECTED);
     }
 
     public void testGetTvInputInfo() throws Exception {
-        if (!Utils.hasTvInputFramework(getContext())) {
+        if (!Utils.hasTvInputFramework(getActivity())) {
             return;
         }
         assertEquals(mManager.getTvInputInfo(mStubId), getInfoForClassName(
-                mManager.getTvInputList(), StubTunerTvInputService.class.getName()));
+                mManager.getTvInputList(), StubTvInputService2.class.getName()));
     }
 
     public void testGetTvInputList() throws Exception {
-        if (!Utils.hasTvInputFramework(getContext())) {
+        if (!Utils.hasTvInputFramework(getActivity())) {
             return;
         }
         List<TvInputInfo> list = mManager.getTvInputList();
@@ -85,4 +101,130 @@
                     getInfoForClassName(list, name));
         }
     }
+
+    public void testIsParentalControlsEnabled() {
+        if (!Utils.hasTvInputFramework(getActivity())) {
+            return;
+        }
+        try {
+            mManager.isParentalControlsEnabled();
+        } catch (Exception e) {
+            fail();
+        }
+    }
+
+    public void testIsRatingBlocked() {
+        if (!Utils.hasTvInputFramework(getActivity())) {
+            return;
+        }
+        try {
+            mManager.isRatingBlocked(DUMMY_RATING);
+        } catch (Exception e) {
+            fail();
+        }
+    }
+
+    public void testRegisterUnregisterCallback() {
+        if (!Utils.hasTvInputFramework(getActivity())) {
+            return;
+        }
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    mManager.registerCallback(mCallabck, new Handler());
+                    mManager.unregisterCallback(mCallabck);
+                } catch (Exception e) {
+                    fail();
+                }
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+    }
+
+    public void testInputAddedAndRemoved() {
+        if (!Utils.hasTvInputFramework(getActivity())) {
+            return;
+        }
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mManager.registerCallback(mCallabck, new Handler());
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+
+        // Test if onInputRemoved() is called.
+        mCallabck.resetLogs();
+        PackageManager pm = getActivity().getPackageManager();
+        ComponentName component = new ComponentName(getActivity(), StubTvInputService2.class);
+        assertTrue(PackageManager.COMPONENT_ENABLED_STATE_DISABLED != pm.getComponentEnabledSetting(
+                component));
+        pm.setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+                PackageManager.DONT_KILL_APP);
+        new PollingCheck(TIME_OUT_MS) {
+            @Override
+            protected boolean check() {
+                return mCallabck.isInputRemoved(mStubId);
+            }
+        }.run();
+
+        // Test if onInputAdded() is called.
+        mCallabck.resetLogs();
+        assertEquals(PackageManager.COMPONENT_ENABLED_STATE_DISABLED, pm.getComponentEnabledSetting(
+                component));
+        pm.setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+                PackageManager.DONT_KILL_APP);
+        new PollingCheck(TIME_OUT_MS) {
+            @Override
+            protected boolean check() {
+                return mCallabck.isInputAdded(mStubId);
+            }
+        }.run();
+
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mManager.unregisterCallback(mCallabck);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+    }
+
+    private static class LoggingCallback extends TvInputManager.TvInputCallback {
+        private final List<String> mAddedInputs = new ArrayList<>();
+        private final List<String> mRemovedInputs = new ArrayList<>();
+
+        @Override
+        public synchronized void onInputAdded(String inputId) {
+            mAddedInputs.add(inputId);
+        }
+
+        @Override
+        public synchronized void onInputRemoved(String inputId) {
+            mRemovedInputs.add(inputId);
+        }
+
+        public synchronized void resetLogs() {
+            mAddedInputs.clear();
+            mRemovedInputs.clear();
+        }
+
+        public synchronized boolean isInputAdded(String inputId) {
+            return mRemovedInputs.isEmpty() && mAddedInputs.size() == 1 && mAddedInputs.contains(
+                    inputId);
+        }
+
+        public synchronized boolean isInputRemoved(String inputId) {
+            return mAddedInputs.isEmpty() && mRemovedInputs.size() == 1 && mRemovedInputs.contains(
+                    inputId);
+        }
+    }
+
+    public static class StubTvInputService2 extends StubTvInputService {
+        @Override
+        public Session onCreateSession(String inputId) {
+            return null;
+        }
+    }
 }
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvInputServiceTest.java b/tests/tests/tv/src/android/media/tv/cts/TvInputServiceTest.java
index f0ee2772..b4c863a 100644
--- a/tests/tests/tv/src/android/media/tv/cts/TvInputServiceTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/TvInputServiceTest.java
@@ -20,6 +20,7 @@
 import android.app.Instrumentation;
 import android.content.Context;
 import android.cts.util.PollingCheck;
+import android.media.PlaybackParams;
 import android.media.tv.TvContentRating;
 import android.media.tv.TvContract;
 import android.media.tv.TvInputInfo;
@@ -28,9 +29,15 @@
 import android.media.tv.TvView;
 import android.media.tv.cts.TvInputServiceTest.CountingTvInputService.CountingSession;
 import android.net.Uri;
+import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
+import android.view.InputDevice;
 import android.view.KeyEvent;
+import android.view.MotionEvent;
 import android.view.Surface;
+import android.view.SurfaceView;
+import android.view.View;
+import android.widget.LinearLayout;
 
 import com.android.cts.tv.R;
 
@@ -46,8 +53,8 @@
     private static final long TIME_OUT = 15000L;
     private static final String mDummyTrackId = "dummyTrackId";
     private static final TvTrackInfo mDummyTrack =
-            new TvTrackInfo.Builder(TvTrackInfo.TYPE_SUBTITLE, mDummyTrackId)
-            .setLanguage("und").build();
+            new TvTrackInfo.Builder(TvTrackInfo.TYPE_VIDEO, mDummyTrackId)
+            .setVideoWidth(1920).setVideoHeight(1080).setLanguage("und").build();
 
     private TvView mTvView;
     private Activity mActivity;
@@ -55,6 +62,8 @@
     private TvInputManager mManager;
     private TvInputInfo mStubInfo;
     private final StubCallback mCallback = new StubCallback();
+    private final StubTimeShiftPositionCallback mTimeShiftPositionCallback =
+            new StubTimeShiftPositionCallback();
 
     private static class StubCallback extends TvView.TvInputCallback {
         private int mChannelRetunedCount;
@@ -62,8 +71,10 @@
         private int mVideoUnavailableCount;
         private int mTrackSelectedCount;
         private int mTrackChangedCount;
+        private int mVideoSizeChanged;
         private int mContentAllowedCount;
         private int mContentBlockedCount;
+        private int mTimeShiftStatusChangedCount;
 
         @Override
         public void onChannelRetuned(String inputId, Uri channelUri) {
@@ -91,6 +102,11 @@
         }
 
         @Override
+        public void onVideoSizeChanged(String inputId, int width, int height) {
+            mVideoSizeChanged++;
+        }
+
+        @Override
         public void onContentAllowed(String inputId) {
             mContentAllowedCount++;
         }
@@ -99,6 +115,42 @@
         public void onContentBlocked(String inputId, TvContentRating rating) {
             mContentBlockedCount++;
         }
+
+        @Override
+        public void onTimeShiftStatusChanged(String inputId, int status) {
+            mTimeShiftStatusChangedCount++;
+        }
+
+        public void resetCounts() {
+            mChannelRetunedCount = 0;
+            mVideoAvailableCount = 0;
+            mVideoUnavailableCount = 0;
+            mTrackSelectedCount = 0;
+            mTrackChangedCount = 0;
+            mContentAllowedCount = 0;
+            mContentBlockedCount = 0;
+            mTimeShiftStatusChangedCount = 0;
+        }
+    }
+
+    private static class StubTimeShiftPositionCallback extends TvView.TimeShiftPositionCallback {
+        private int mTimeShiftStartPositionChanged;
+        private int mTimeShiftCurrentPositionChanged;
+
+        @Override
+        public void onTimeShiftStartPositionChanged(String inputId, long timeMs) {
+            mTimeShiftStartPositionChanged++;
+        }
+
+        @Override
+        public void onTimeShiftCurrentPositionChanged(String inputId, long timeMs) {
+            mTimeShiftCurrentPositionChanged++;
+        }
+
+        public void resetCounts() {
+            mTimeShiftStartPositionChanged = 0;
+            mTimeShiftCurrentPositionChanged = 0;
+        }
     }
 
     public TvInputServiceTest() {
@@ -135,7 +187,18 @@
         verifyCommandSetStreamVolume();
         verifyCommandSetCaptionEnabled();
         verifyCommandSelectTrack();
-        verifyCommandDispatchKeyEvent();
+        verifyCommandDispatchKeyDown();
+        verifyCommandDispatchKeyMultiple();
+        verifyCommandDispatchKeyUp();
+        verifyCommandDispatchTouchEvent();
+        verifyCommandDispatchTrackballEvent();
+        verifyCommandDispatchGenericMotionEvent();
+        verifyCommandTimeShiftPause();
+        verifyCommandTimeShiftResume();
+        verifyCommandTimeShiftSeekTo();
+        verifyCommandTimeShiftSetPlaybackParams();
+        verifyCommandSetTimeShiftPositionCallback();
+        verifyCommandOverlayViewSizeChanged();
         verifyCallbackChannelRetuned();
         verifyCallbackVideoAvailable();
         verifyCallbackVideoUnavailable();
@@ -143,6 +206,8 @@
         verifyCallbackTrackSelected();
         verifyCallbackContentAllowed();
         verifyCallbackContentBlocked();
+        verifyCallbackTimeShiftStatusChanged();
+        verifyCallbackLayoutSurface();
 
         runTestOnUiThread(new Runnable() {
             @Override
@@ -161,12 +226,13 @@
             @Override
             protected boolean check() {
                 CountingSession session = CountingTvInputService.sSession;
-                return session != null && session.mTuneCount > 0;
+                return session != null && session.mTuneCount > 0 && session.mCreateOverlayView > 0;
             }
         }.run();
     }
 
     public void verifyCommandSetStreamVolume() {
+        resetCounts();
         mTvView.setStreamVolume(1.0f);
         mInstrumentation.waitForIdleSync();
         new PollingCheck(TIME_OUT) {
@@ -179,6 +245,7 @@
     }
 
     public void verifyCommandSetCaptionEnabled() {
+        resetCounts();
         mTvView.setCaptionEnabled(true);
         mInstrumentation.waitForIdleSync();
         new PollingCheck(TIME_OUT) {
@@ -191,18 +258,21 @@
     }
 
     public void verifyCommandSelectTrack() {
-        mTvView.selectTrack(TvTrackInfo.TYPE_AUDIO, "dummyTrackId");
+        resetCounts();
+        verifyCallbackTracksChanged();
+        mTvView.selectTrack(mDummyTrack.getType(), mDummyTrack.getId());
         mInstrumentation.waitForIdleSync();
         new PollingCheck(TIME_OUT) {
             @Override
             protected boolean check() {
                 CountingSession session = CountingTvInputService.sSession;
-                return session != null && session.mSetStreamVolumeCount > 0;
+                return session != null && session.mSelectTrackCount > 0;
             }
         }.run();
     }
 
-    public void verifyCommandDispatchKeyEvent() {
+    public void verifyCommandDispatchKeyDown() {
+        resetCounts();
         mTvView.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_K));
         mInstrumentation.waitForIdleSync();
         new PollingCheck(TIME_OUT) {
@@ -214,7 +284,167 @@
         }.run();
     }
 
+    public void verifyCommandDispatchKeyMultiple() {
+        resetCounts();
+        mTvView.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_MULTIPLE, KeyEvent.KEYCODE_K));
+        mInstrumentation.waitForIdleSync();
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                CountingSession session = CountingTvInputService.sSession;
+                return session != null && session.mKeyMultipleCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCommandDispatchKeyUp() {
+        resetCounts();
+        mTvView.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_K));
+        mInstrumentation.waitForIdleSync();
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                CountingSession session = CountingTvInputService.sSession;
+                return session != null && session.mKeyUpCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCommandDispatchTouchEvent() {
+        resetCounts();
+        long now = SystemClock.uptimeMillis();
+        MotionEvent event = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, 1.0f, 1.0f,
+                1.0f, 1.0f, 0, 1.0f, 1.0f, 0, 0);
+        event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+        mTvView.dispatchTouchEvent(event);
+        mInstrumentation.waitForIdleSync();
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                CountingSession session = CountingTvInputService.sSession;
+                return session != null && session.mTouchEventCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCommandDispatchTrackballEvent() {
+        resetCounts();
+        long now = SystemClock.uptimeMillis();
+        MotionEvent event = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, 1.0f, 1.0f,
+                1.0f, 1.0f, 0, 1.0f, 1.0f, 0, 0);
+        event.setSource(InputDevice.SOURCE_TRACKBALL);
+        mTvView.dispatchTouchEvent(event);
+        mInstrumentation.waitForIdleSync();
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                CountingSession session = CountingTvInputService.sSession;
+                return session != null && session.mTrackballEventCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCommandDispatchGenericMotionEvent() {
+        resetCounts();
+        long now = SystemClock.uptimeMillis();
+        MotionEvent event = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, 1.0f, 1.0f,
+                1.0f, 1.0f, 0, 1.0f, 1.0f, 0, 0);
+        mTvView.dispatchGenericMotionEvent(event);
+        mInstrumentation.waitForIdleSync();
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                CountingSession session = CountingTvInputService.sSession;
+                return session != null && session.mGenricMotionEventCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCommandTimeShiftPause() {
+        resetCounts();
+        mTvView.timeShiftPause();
+        mInstrumentation.waitForIdleSync();
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                CountingSession session = CountingTvInputService.sSession;
+                return session != null && session.mTimeShiftPauseCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCommandTimeShiftResume() {
+        resetCounts();
+        mTvView.timeShiftResume();
+        mInstrumentation.waitForIdleSync();
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                CountingSession session = CountingTvInputService.sSession;
+                return session != null && session.mTimeShiftResumeCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCommandTimeShiftSeekTo() {
+        resetCounts();
+        mTvView.timeShiftSeekTo(0);
+        mInstrumentation.waitForIdleSync();
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                CountingSession session = CountingTvInputService.sSession;
+                return session != null && session.mTimeShiftSeekToCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCommandTimeShiftSetPlaybackParams() {
+        resetCounts();
+        mTvView.timeShiftSetPlaybackParams(new PlaybackParams().setSpeed(2.0f)
+                .setAudioFallbackMode(PlaybackParams.AUDIO_FALLBACK_MODE_DEFAULT));
+        mInstrumentation.waitForIdleSync();
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                CountingSession session = CountingTvInputService.sSession;
+                return session != null && session.mTimeShiftSetPlaybackParamsCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCommandSetTimeShiftPositionCallback() {
+        resetCounts();
+        mTvView.setTimeShiftPositionCallback(mTimeShiftPositionCallback);
+        mInstrumentation.waitForIdleSync();
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                return mTimeShiftPositionCallback.mTimeShiftCurrentPositionChanged > 0
+                        && mTimeShiftPositionCallback.mTimeShiftStartPositionChanged > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCommandOverlayViewSizeChanged() {
+        resetCounts();
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mTvView.setLayoutParams(new LinearLayout.LayoutParams(10, 20));
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                CountingSession session = CountingTvInputService.sSession;
+                return session != null && session.mOverlayViewSizeChangedCount > 0;
+            }
+        }.run();
+    }
+
     public void verifyCallbackChannelRetuned() {
+        resetCounts();
         CountingSession session = CountingTvInputService.sSession;
         assertNotNull(session);
         Uri fakeChannelUri = TvContract.buildChannelUri(0);
@@ -228,6 +458,7 @@
     }
 
     public void verifyCallbackVideoAvailable() {
+        resetCounts();
         CountingSession session = CountingTvInputService.sSession;
         assertNotNull(session);
         session.notifyVideoAvailable();
@@ -240,6 +471,7 @@
     }
 
     public void verifyCallbackVideoUnavailable() {
+        resetCounts();
         CountingSession session = CountingTvInputService.sSession;
         assertNotNull(session);
         session.notifyVideoUnavailable(TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING);
@@ -252,6 +484,7 @@
     }
 
     public void verifyCallbackTracksChanged() {
+        resetCounts();
         CountingSession session = CountingTvInputService.sSession;
         assertNotNull(session);
         ArrayList<TvTrackInfo> tracks = new ArrayList<>();
@@ -265,7 +498,23 @@
         }.run();
     }
 
+    public void verifyCallbackVideoSizeChanged() {
+        resetCounts();
+        CountingSession session = CountingTvInputService.sSession;
+        assertNotNull(session);
+        ArrayList<TvTrackInfo> tracks = new ArrayList<>();
+        tracks.add(mDummyTrack);
+        session.notifyTracksChanged(tracks);
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                return mCallback.mVideoSizeChanged > 0;
+            }
+        }.run();
+    }
+
     public void verifyCallbackTrackSelected() {
+        resetCounts();
         CountingSession session = CountingTvInputService.sSession;
         assertNotNull(session);
         session.notifyTrackSelected(mDummyTrack.getType(), mDummyTrack.getId());
@@ -278,6 +527,7 @@
     }
 
     public void verifyCallbackContentAllowed() {
+        resetCounts();
         CountingSession session = CountingTvInputService.sSession;
         assertNotNull(session);
         session.notifyContentAllowed();
@@ -290,6 +540,7 @@
     }
 
     public void verifyCallbackContentBlocked() {
+        resetCounts();
         CountingSession session = CountingTvInputService.sSession;
         assertNotNull(session);
         TvContentRating rating = TvContentRating.createRating("android.media.tv", "US_TVPG",
@@ -303,13 +554,59 @@
         }.run();
     }
 
+    public void verifyCallbackTimeShiftStatusChanged() {
+        resetCounts();
+        CountingSession session = CountingTvInputService.sSession;
+        assertNotNull(session);
+        session.notifyTimeShiftStatusChanged(TvInputManager.TIME_SHIFT_STATUS_AVAILABLE);
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                return mCallback.mTimeShiftStatusChangedCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCallbackLayoutSurface() {
+        resetCounts();
+        final int left = 10;
+        final int top = 20;
+        final int right = 30;
+        final int bottom = 40;
+        CountingSession session = CountingTvInputService.sSession;
+        assertNotNull(session);
+        session.layoutSurface(left, top, right, bottom);
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                int childCount = mTvView.getChildCount();
+                for (int i = 0; i < childCount; ++i) {
+                    View v = mTvView.getChildAt(i);
+                    if (v instanceof SurfaceView) {
+                        return v.getLeft() == left && v.getTop() == top && v.getRight() == right
+                                && v.getBottom() == bottom;
+                    }
+                }
+                return false;
+            }
+        }.run();
+    }
+
+    private void resetCounts() {
+        if (CountingTvInputService.sSession != null) {
+            CountingTvInputService.sSession.resetCounts();
+        }
+        mCallback.resetCounts();
+        mTimeShiftPositionCallback.resetCounts();
+    }
+
     public static class CountingTvInputService extends StubTvInputService {
-        static CountingTvInputService sInstance;
         static CountingSession sSession;
 
         @Override
         public Session onCreateSession(String inputId) {
             sSession = new CountingSession(this);
+            sSession.setOverlayViewEnabled(true);
             return sSession;
         }
 
@@ -318,12 +615,48 @@
             public volatile int mSetStreamVolumeCount;
             public volatile int mSetCaptionEnabledCount;
             public volatile int mSelectTrackCount;
+            public volatile int mCreateOverlayView;
             public volatile int mKeyDownCount;
+            public volatile int mKeyLongPressCount;
+            public volatile int mKeyMultipleCount;
+            public volatile int mKeyUpCount;
+            public volatile int mTouchEventCount;
+            public volatile int mTrackballEventCount;
+            public volatile int mGenricMotionEventCount;
+            public volatile int mOverlayViewSizeChangedCount;
+            public volatile int mTimeShiftPauseCount;
+            public volatile int mTimeShiftResumeCount;
+            public volatile int mTimeShiftSeekToCount;
+            public volatile int mTimeShiftSetPlaybackParamsCount;
+            public volatile long mTimeShiftGetCurrentPositionCount;
+            public volatile long mTimeShiftGetStartPositionCount;
 
             CountingSession(Context context) {
                 super(context);
             }
 
+            public void resetCounts() {
+                mTuneCount = 0;
+                mSetStreamVolumeCount = 0;
+                mSetCaptionEnabledCount = 0;
+                mSelectTrackCount = 0;
+                mCreateOverlayView = 0;
+                mKeyDownCount = 0;
+                mKeyLongPressCount = 0;
+                mKeyMultipleCount = 0;
+                mKeyUpCount = 0;
+                mTouchEventCount = 0;
+                mTrackballEventCount = 0;
+                mGenricMotionEventCount = 0;
+                mOverlayViewSizeChangedCount = 0;
+                mTimeShiftPauseCount = 0;
+                mTimeShiftResumeCount = 0;
+                mTimeShiftSeekToCount = 0;
+                mTimeShiftSetPlaybackParamsCount = 0;
+                mTimeShiftGetCurrentPositionCount = 0;
+                mTimeShiftGetStartPositionCount = 0;
+            }
+
             @Override
             public void onRelease() {
             }
@@ -356,10 +689,87 @@
             }
 
             @Override
+            public View onCreateOverlayView() {
+                mCreateOverlayView++;
+                return null;
+            }
+
+            @Override
             public boolean onKeyDown(int keyCode, KeyEvent event) {
                 mKeyDownCount++;
                 return false;
             }
+
+            @Override
+            public boolean onKeyLongPress(int keyCode, KeyEvent event) {
+                mKeyLongPressCount++;
+                return false;
+            }
+
+            @Override
+            public boolean onKeyMultiple(int keyCode, int count, KeyEvent event) {
+                mKeyMultipleCount++;
+                return false;
+            }
+
+            @Override
+            public boolean onKeyUp(int keyCode, KeyEvent event) {
+                mKeyUpCount++;
+                return false;
+            }
+
+            @Override
+            public boolean onTouchEvent(MotionEvent event) {
+                mTouchEventCount++;
+                return false;
+            }
+
+            @Override
+            public boolean onTrackballEvent(MotionEvent event) {
+                mTrackballEventCount++;
+                return false;
+            }
+
+            @Override
+            public boolean onGenericMotionEvent(MotionEvent event) {
+                mGenricMotionEventCount++;
+                return false;
+            }
+
+            @Override
+            public void onTimeShiftPause() {
+                mTimeShiftPauseCount++;
+            }
+
+            @Override
+            public void onTimeShiftResume() {
+                mTimeShiftResumeCount++;
+            }
+
+            @Override
+            public void onTimeShiftSeekTo(long timeMs) {
+                mTimeShiftSeekToCount++;
+            }
+
+            @Override
+            public void onTimeShiftSetPlaybackParams(PlaybackParams param) {
+                mTimeShiftSetPlaybackParamsCount++;
+            }
+
+            @Override
+            public long onTimeShiftGetCurrentPosition() {
+                return ++mTimeShiftGetCurrentPositionCount;
+            }
+
+            @Override
+            public long onTimeShiftGetStartPosition() {
+                return ++mTimeShiftGetStartPositionCount;
+            }
+
+            @Override
+            public void onOverlayViewSizeChanged(int width, int height) {
+                mOverlayViewSizeChangedCount++;
+            }
         }
     }
 }
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvTrackInfoTest.java b/tests/tests/tv/src/android/media/tv/cts/TvTrackInfoTest.java
new file mode 100644
index 0000000..a99bd77
--- /dev/null
+++ b/tests/tests/tv/src/android/media/tv/cts/TvTrackInfoTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.cts;
+
+import android.media.tv.TvTrackInfo;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+
+/**
+ * Test {@link android.media.tv.TvTrackInfo}.
+ */
+public class TvTrackInfoTest extends AndroidTestCase {
+
+    public void testAudioTrackInfoOp() {
+        if (!Utils.hasTvInputFramework(getContext())) {
+            return;
+        }
+        final Bundle bundle = new Bundle();
+        final TvTrackInfo info = new TvTrackInfo.Builder(TvTrackInfo.TYPE_AUDIO, "id_audio")
+                .setAudioChannelCount(2)
+                .setAudioSampleRate(48000)
+                .setLanguage("eng")
+                .setExtra(bundle)
+                .build();
+        assertEquals(TvTrackInfo.TYPE_AUDIO, info.getType());
+        assertEquals("id_audio", info.getId());
+        assertEquals(2, info.getAudioChannelCount());
+        assertEquals(48000, info.getAudioSampleRate());
+        assertEquals("eng", info.getLanguage());
+        assertEquals(bundle.get("testTrue"), info.getExtra().get("testTrue"));
+        assertEquals(0, info.describeContents());
+
+        // Test writeToParcel
+        Parcel p = Parcel.obtain();
+        info.writeToParcel(p, 0);
+        p.setDataPosition(0);
+        TvTrackInfo infoFromParcel = TvTrackInfo.CREATOR.createFromParcel(p);
+        assertEquals(TvTrackInfo.TYPE_AUDIO, infoFromParcel.getType());
+        assertEquals("id_audio", infoFromParcel.getId());
+        assertEquals(2, infoFromParcel.getAudioChannelCount());
+        assertEquals(48000, infoFromParcel.getAudioSampleRate());
+        assertEquals("eng", infoFromParcel.getLanguage());
+        assertEquals(bundle.get("testTrue"), infoFromParcel.getExtra().get("testTrue"));
+        assertEquals(0, infoFromParcel.describeContents());
+        p.recycle();
+    }
+
+    public void testVideoTrackInfoOp() {
+        if (!Utils.hasTvInputFramework(getContext())) {
+            return;
+        }
+        final Bundle bundle = new Bundle();
+        bundle.putBoolean("testTrue", true);
+        final TvTrackInfo info = new TvTrackInfo.Builder(TvTrackInfo.TYPE_VIDEO, "id_video")
+                .setVideoWidth(1920)
+                .setVideoHeight(1080)
+                .setVideoFrameRate(29.97f)
+                .setLanguage("eng")
+                .setExtra(bundle)
+                .build();
+        assertEquals(TvTrackInfo.TYPE_VIDEO, info.getType());
+        assertEquals("id_video", info.getId());
+        assertEquals(1920, info.getVideoWidth());
+        assertEquals(1080, info.getVideoHeight());
+        assertEquals(29.97f, info.getVideoFrameRate());
+        assertEquals("eng", info.getLanguage());
+        assertEquals(bundle.get("testTrue"), info.getExtra().get("testTrue"));
+        assertEquals(0, info.describeContents());
+
+        // Test writeToParcel
+        Parcel p = Parcel.obtain();
+        info.writeToParcel(p, 0);
+        p.setDataPosition(0);
+        TvTrackInfo infoFromParcel = TvTrackInfo.CREATOR.createFromParcel(p);
+        assertEquals(TvTrackInfo.TYPE_VIDEO, infoFromParcel.getType());
+        assertEquals("id_video", infoFromParcel.getId());
+        assertEquals(1920, infoFromParcel.getVideoWidth());
+        assertEquals(1080, infoFromParcel.getVideoHeight());
+        assertEquals(29.97f, infoFromParcel.getVideoFrameRate());
+        assertEquals("eng", infoFromParcel.getLanguage());
+        assertEquals(bundle.get("testTrue"), infoFromParcel.getExtra().get("testTrue"));
+        assertEquals(0, infoFromParcel.describeContents());
+        p.recycle();
+    }
+
+    public void testSubtitleTrackInfoOp() {
+        if (!Utils.hasTvInputFramework(getContext())) {
+            return;
+        }
+        final Bundle bundle = new Bundle();
+        bundle.putBoolean("testTrue", true);
+        final TvTrackInfo info = new TvTrackInfo.Builder(TvTrackInfo.TYPE_SUBTITLE, "id_subtitle")
+                .setLanguage("eng")
+                .setExtra(bundle)
+                .build();
+        assertEquals(TvTrackInfo.TYPE_SUBTITLE, info.getType());
+        assertEquals("id_subtitle", info.getId());
+        assertEquals("eng", info.getLanguage());
+        assertEquals(bundle.get("testTrue"), info.getExtra().get("testTrue"));
+        assertEquals(0, info.describeContents());
+
+        // Test writeToParcel
+        Parcel p = Parcel.obtain();
+        info.writeToParcel(p, 0);
+        p.setDataPosition(0);
+        TvTrackInfo infoFromParcel = TvTrackInfo.CREATOR.createFromParcel(p);
+        assertEquals(TvTrackInfo.TYPE_SUBTITLE, infoFromParcel.getType());
+        assertEquals("id_subtitle", infoFromParcel.getId());
+        assertEquals("eng", infoFromParcel.getLanguage());
+        assertEquals(bundle.get("testTrue"), infoFromParcel.getExtra().get("testTrue"));
+        assertEquals(0, infoFromParcel.describeContents());
+        p.recycle();
+    }
+}
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvViewTest.java b/tests/tests/tv/src/android/media/tv/cts/TvViewTest.java
index 930dd6a..1c59462 100644
--- a/tests/tests/tv/src/android/media/tv/cts/TvViewTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/TvViewTest.java
@@ -47,7 +47,7 @@
  */
 public class TvViewTest extends ActivityInstrumentationTestCase2<TvViewStubActivity> {
     /** The maximum time to wait for an operation. */
-    private static final long TIME_OUT = 15000L;
+    private static final long TIME_OUT_MS = 15000L;
 
     private TvView mTvView;
     private Activity mActivity;
@@ -61,6 +61,7 @@
         private final Map<String, SparseIntArray> mSelectedTrackGenerationMap = new ArrayMap<>();
         private final Map<String, Integer> mTracksGenerationMap = new ArrayMap<>();
         private final Object mLock = new Object();
+        private volatile int mConnectionFailedCount;
 
         public boolean isVideoAvailable(String inputId) {
             synchronized (mLock) {
@@ -80,6 +81,19 @@
             }
         }
 
+        public void resetConnectionFailedCount() {
+            mConnectionFailedCount = 0;
+        }
+
+        public int getConnectionFailedCount() {
+            return mConnectionFailedCount;
+        }
+
+        @Override
+        public void onConnectionFailed(String inputId) {
+            mConnectionFailedCount++;
+        }
+
         @Override
         public void onVideoAvailable(String inputId) {
             synchronized (mLock) {
@@ -201,7 +215,7 @@
                 Uri channelUri = TvContract.buildChannelUri(channelId);
                 mTvView.tune(mStubInfo.getId(), channelUri);
                 mInstrumentation.waitForIdleSync();
-                new PollingCheck(TIME_OUT) {
+                new PollingCheck(TIME_OUT_MS) {
                     @Override
                     protected boolean check() {
                         return mCallback.isVideoAvailable(mStubInfo.getId());
@@ -232,7 +246,7 @@
         if ((track == null && selectedTrackId != null)
                 || (track != null && !track.getId().equals(selectedTrackId))) {
             // Check generation change only if we're actually changing track.
-            new PollingCheck(TIME_OUT) {
+            new PollingCheck(TIME_OUT_MS) {
                 @Override
                 protected boolean check() {
                     return mCallback.getSelectedTrackGeneration(
@@ -258,6 +272,8 @@
                 case TvTrackInfo.TYPE_VIDEO:
                     assertEquals(track.getVideoHeight(), selectedTrack.getVideoHeight());
                     assertEquals(track.getVideoWidth(), selectedTrack.getVideoWidth());
+                    assertEquals(track.getVideoPixelAspectRatio(),
+                            selectedTrack.getVideoPixelAspectRatio(), 0.001f);
                     break;
                 case TvTrackInfo.TYPE_AUDIO:
                     assertEquals(track.getAudioChannelCount(),
@@ -267,6 +283,7 @@
                     break;
                 case TvTrackInfo.TYPE_SUBTITLE:
                     assertEquals(track.getLanguage(), selectedTrack.getLanguage());
+                    assertEquals(track.getDescription(), selectedTrack.getDescription());
                     break;
                 default:
                     fail("Unrecognized type: " + track.getType());
@@ -281,7 +298,7 @@
         TvTrackInfo videoTrack1 = new TvTrackInfo.Builder(TvTrackInfo.TYPE_VIDEO, "video-HD")
                 .setVideoHeight(1920).setVideoWidth(1080).build();
         TvTrackInfo videoTrack2 = new TvTrackInfo.Builder(TvTrackInfo.TYPE_VIDEO, "video-SD")
-                .setVideoHeight(640).setVideoWidth(360).build();
+                .setVideoHeight(640).setVideoWidth(360).setVideoPixelAspectRatio(1.09f).build();
         TvTrackInfo audioTrack1 =
                 new TvTrackInfo.Builder(TvTrackInfo.TYPE_AUDIO, "audio-stereo-eng")
                 .setLanguage("eng").setAudioChannelCount(2).setAudioSampleRate(48000).build();
@@ -293,17 +310,20 @@
         TvTrackInfo subtitleTrack2 =
                 new TvTrackInfo.Builder(TvTrackInfo.TYPE_SUBTITLE, "subtitle-esp")
                 .setLanguage("esp").build();
+        TvTrackInfo subtitleTrack3 =
+                new TvTrackInfo.Builder(TvTrackInfo.TYPE_SUBTITLE, "subtitle-eng2")
+                .setLanguage("eng").setDescription("audio commentary").build();
 
         StubTunerTvInputService.injectTrack(videoTrack1, videoTrack2, audioTrack1, audioTrack2,
                 subtitleTrack1, subtitleTrack2);
 
         final List<TvTrackInfo> tracks = new ArrayList<TvTrackInfo>();
         Collections.addAll(tracks, videoTrack1, videoTrack2, audioTrack1, audioTrack2,
-                subtitleTrack1, subtitleTrack2);
+                subtitleTrack1, subtitleTrack2, subtitleTrack3);
         tryTuneAllChannels(new Runnable() {
             @Override
             public void run() {
-                new PollingCheck(TIME_OUT) {
+                new PollingCheck(TIME_OUT_MS) {
                     @Override
                     protected boolean check() {
                         return mTvView.getTracks(TvTrackInfo.TYPE_AUDIO) != null;
@@ -325,7 +345,7 @@
         unhandledEvent[0] = null;
         mInstrumentation.sendKeySync(keyEvent);
         mInstrumentation.waitForIdleSync();
-        new PollingCheck(TIME_OUT) {
+        new PollingCheck(TIME_OUT_MS) {
             @Override
             protected boolean check() {
                 return unhandledEvent[0] != null;
@@ -362,7 +382,7 @@
             Uri channelUri = TvContract.buildChannelUri(channelId);
             mTvView.tune(mStubInfo.getId(), channelUri);
             mInstrumentation.waitForIdleSync();
-            new PollingCheck(TIME_OUT) {
+            new PollingCheck(TIME_OUT_MS) {
                 @Override
                 protected boolean check() {
                     return mCallback.isVideoAvailable(mStubInfo.getId());
@@ -382,4 +402,19 @@
         verifyKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_GUIDE), unhandledEvent);
         verifyKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_GUIDE), unhandledEvent);
     }
+
+    public void testConnectionFailed() throws Throwable {
+        if (!Utils.hasTvInputFramework(getActivity())) {
+            return;
+        }
+        mCallback.resetConnectionFailedCount();
+        mTvView.tune("invalid_input_id", TvContract.Channels.CONTENT_URI);
+        mInstrumentation.waitForIdleSync();
+        new PollingCheck(TIME_OUT_MS) {
+            @Override
+            protected boolean check() {
+                return mCallback.getConnectionFailedCount() > 0;
+            }
+        }.run();
+    }
 }
diff --git a/tests/tests/view/src/android/view/cts/ActionModeCallback2Test.java b/tests/tests/view/src/android/view/cts/ActionModeCallback2Test.java
new file mode 100644
index 0000000..e75b7ae
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/ActionModeCallback2Test.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.cts;
+
+import android.graphics.Rect;
+import android.test.AndroidTestCase;
+import android.view.ActionMode;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+
+public class ActionModeCallback2Test extends AndroidTestCase {
+    private static final int VIEW_WIDTH = 123;
+    private static final int VIEW_HEIGHT = 456;
+
+    public void testCallbackOnGetContentRectDefaultWithView() {
+        View view = new View(mContext);
+        view.setLeft(0);
+        view.setRight(VIEW_WIDTH);
+        view.setTop(0);
+        view.setBottom(VIEW_HEIGHT);
+
+        Rect outRect = new Rect();
+        MockActionModeCallback2 callback = new MockActionModeCallback2();
+        callback.onGetContentRect(null, view, outRect);
+
+        assertEquals(0, outRect.top);
+        assertEquals(0, outRect.left);
+        assertEquals(VIEW_HEIGHT, outRect.bottom);
+        assertEquals(VIEW_WIDTH, outRect.right);
+    }
+
+    public void testCallbackOnGetContentRectDefaultWithoutView() {
+        Rect outRect = new Rect();
+        MockActionModeCallback2 callback = new MockActionModeCallback2();
+        callback.onGetContentRect(null, null, outRect);
+
+        assertEquals(0, outRect.top);
+        assertEquals(0, outRect.left);
+        assertEquals(0, outRect.bottom);
+        assertEquals(0, outRect.right);
+    }
+
+    private static class MockActionModeCallback2 extends ActionMode.Callback2 {
+        @Override
+        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+            return false;
+        }
+
+        @Override
+        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+            return false;
+        }
+
+        @Override
+        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+            return false;
+        }
+
+        @Override
+        public void onDestroyActionMode(ActionMode mode) {}
+    }
+
+}
diff --git a/tests/tests/view/src/android/view/cts/ActionModeTest.java b/tests/tests/view/src/android/view/cts/ActionModeTest.java
new file mode 100644
index 0000000..61df9fe
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/ActionModeTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.cts;
+
+import android.test.AndroidTestCase;
+import android.view.ActionMode;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.View;
+
+public class ActionModeTest extends AndroidTestCase {
+
+    public void testSetType() {
+        ActionMode actionMode = new MockActionMode();
+        assertEquals(ActionMode.TYPE_PRIMARY, actionMode.getType());
+
+        actionMode.setType(ActionMode.TYPE_FLOATING);
+        assertEquals(ActionMode.TYPE_FLOATING, actionMode.getType());
+
+        actionMode.setType(ActionMode.TYPE_PRIMARY);
+        assertEquals(ActionMode.TYPE_PRIMARY, actionMode.getType());
+    }
+
+    public void testInvalidateContentRectDoesNotInvalidateFull() {
+        MockActionMode actionMode = new MockActionMode();
+
+        actionMode.invalidateContentRect();
+
+        assertFalse(actionMode.mInvalidateWasCalled);
+    }
+
+    private static class MockActionMode extends ActionMode {
+        boolean mInvalidateWasCalled = false;
+
+        @Override
+        public void setTitle(CharSequence title) {}
+
+        @Override
+        public void setTitle(int resId) {}
+
+        @Override
+        public void setSubtitle(CharSequence subtitle) {}
+
+        @Override
+        public void setSubtitle(int resId) {}
+
+        @Override
+        public void setCustomView(View view) {}
+
+        @Override
+        public void invalidate() {
+            mInvalidateWasCalled = true;
+        }
+
+        @Override
+        public void finish() {}
+
+        @Override
+        public Menu getMenu() {
+            return null;
+        }
+
+        @Override
+        public CharSequence getTitle() {
+            return null;
+        }
+
+        @Override
+        public CharSequence getSubtitle() {
+            return null;
+        }
+
+        @Override
+        public View getCustomView() {
+            return null;
+        }
+
+        @Override
+        public MenuInflater getMenuInflater() {
+            return null;
+        }
+    }
+}
diff --git a/tests/tests/view/src/android/view/cts/ViewTest.java b/tests/tests/view/src/android/view/cts/ViewTest.java
index 3024e40..34e4d09 100644
--- a/tests/tests/view/src/android/view/cts/ViewTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewTest.java
@@ -56,6 +56,8 @@
 import android.view.HapticFeedbackConstants;
 import android.view.InputDevice;
 import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuInflater;
 import android.view.MotionEvent;
 import android.view.SoundEffectConstants;
 import android.view.TouchDelegate;
@@ -3383,6 +3385,156 @@
                 bg.hasCalledSetTint());
     }
 
+    public void testStartActionModeWithParent() {
+        View view = new View(mActivity);
+        MockViewGroup parent = new MockViewGroup(mActivity);
+        parent.addView(view);
+
+        ActionMode mode = view.startActionMode(null);
+
+        assertNotNull(mode);
+        assertEquals(NO_OP_ACTION_MODE, mode);
+        assertTrue(parent.isStartActionModeForChildCalled);
+        assertEquals(ActionMode.TYPE_PRIMARY, parent.startActionModeForChildType);
+    }
+
+    public void testStartActionModeWithoutParent() {
+        View view = new View(mActivity);
+
+        ActionMode mode = view.startActionMode(null);
+
+        assertNull(mode);
+    }
+
+    public void testStartActionModeTypedWithParent() {
+        View view = new View(mActivity);
+        MockViewGroup parent = new MockViewGroup(mActivity);
+        parent.addView(view);
+
+        ActionMode mode = view.startActionMode(null, ActionMode.TYPE_FLOATING);
+
+        assertNotNull(mode);
+        assertEquals(NO_OP_ACTION_MODE, mode);
+        assertTrue(parent.isStartActionModeForChildCalled);
+        assertEquals(ActionMode.TYPE_FLOATING, parent.startActionModeForChildType);
+    }
+
+    public void testStartActionModeTypedWithoutParent() {
+        View view = new View(mActivity);
+
+        ActionMode mode = view.startActionMode(null, ActionMode.TYPE_FLOATING);
+
+        assertNull(mode);
+    }
+
+    private static class MockViewGroup extends ViewGroup {
+        boolean isStartActionModeForChildCalled = false;
+        int startActionModeForChildType = ActionMode.TYPE_PRIMARY;
+
+        public MockViewGroup(Context context) {
+            super(context);
+        }
+
+        @Override
+        public ActionMode startActionModeForChild(View originalView, ActionMode.Callback callback) {
+            isStartActionModeForChildCalled = true;
+            startActionModeForChildType = ActionMode.TYPE_PRIMARY;
+            return NO_OP_ACTION_MODE;
+        }
+
+        @Override
+        public ActionMode startActionModeForChild(
+                View originalView, ActionMode.Callback callback, int type) {
+            isStartActionModeForChildCalled = true;
+            startActionModeForChildType = type;
+            return NO_OP_ACTION_MODE;
+        }
+
+        @Override
+        protected void onLayout(boolean changed, int l, int t, int r, int b) {
+            // no-op
+        }
+    }
+
+    private static final ActionMode NO_OP_ACTION_MODE =
+            new ActionMode() {
+                @Override
+                public void setTitle(CharSequence title) {}
+
+                @Override
+                public void setTitle(int resId) {}
+
+                @Override
+                public void setSubtitle(CharSequence subtitle) {}
+
+                @Override
+                public void setSubtitle(int resId) {}
+
+                @Override
+                public void setCustomView(View view) {}
+
+                @Override
+                public void invalidate() {}
+
+                @Override
+                public void finish() {}
+
+                @Override
+                public Menu getMenu() {
+                    return null;
+                }
+
+                @Override
+                public CharSequence getTitle() {
+                    return null;
+                }
+
+                @Override
+                public CharSequence getSubtitle() {
+                    return null;
+                }
+
+                @Override
+                public View getCustomView() {
+                    return null;
+                }
+
+                @Override
+                public MenuInflater getMenuInflater() {
+                    return null;
+                }
+            };
+
+    public void testTranslationSetter() {
+        View view = new View(mActivity);
+        float offset = 10.0f;
+        view.setTranslationX(offset);
+        view.setTranslationY(offset);
+        view.setTranslationZ(offset);
+        view.setElevation(offset);
+
+        assertEquals("Incorrect translationX", offset, view.getTranslationX());
+        assertEquals("Incorrect translationY", offset, view.getTranslationY());
+        assertEquals("Incorrect translationZ", offset, view.getTranslationZ());
+        assertEquals("Incorrect elevation", offset, view.getElevation());
+    }
+
+    public void testXYZ() {
+        View view = new View(mActivity);
+        float offset = 10.0f;
+        float start = 15.0f;
+        view.setTranslationX(offset);
+        view.setLeft((int) start);
+        view.setTranslationY(offset);
+        view.setTop((int) start);
+        view.setTranslationZ(offset);
+        view.setElevation(start);
+
+        assertEquals("Incorrect X value", offset + start, view.getX());
+        assertEquals("Incorrect Y value", offset + start, view.getY());
+        assertEquals("Incorrect Z value", offset + start, view.getZ());
+    }
+
     private static class MockDrawable extends Drawable {
         private boolean mCalledSetTint = false;
 
diff --git a/tests/tests/webkit/src/android/webkit/cts/PostMessageTest.java b/tests/tests/webkit/src/android/webkit/cts/PostMessageTest.java
index e393bb6..2a6af6e 100644
--- a/tests/tests/webkit/src/android/webkit/cts/PostMessageTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/PostMessageTest.java
@@ -105,7 +105,7 @@
         }
         loadPage(TITLE_FROM_POST_MESSAGE);
         WebMessage message = new WebMessage(WEBVIEW_MESSAGE);
-        mOnUiThread.postMessageToMainFrame(message, Uri.parse(BASE_URI));
+        mOnUiThread.postWebMessage(message, Uri.parse(BASE_URI));
         waitForTitle(WEBVIEW_MESSAGE);
     }
 
@@ -117,7 +117,7 @@
         }
         loadPage(TITLE_FROM_POST_MESSAGE);
         for (int i = 0; i < 10; i++) {
-            mOnUiThread.postMessageToMainFrame(new WebMessage(Integer.toString(i)),
+            mOnUiThread.postWebMessage(new WebMessage(Integer.toString(i)),
                     Uri.parse(BASE_URI));
         }
         waitForTitle("0123456789");
@@ -131,7 +131,7 @@
         loadPage(CHANNEL_MESSAGE);
         final WebMessagePort[] channel = mOnUiThread.createWebMessageChannel();
         WebMessage message = new WebMessage(WEBVIEW_MESSAGE, new WebMessagePort[]{channel[1]});
-        mOnUiThread.postMessageToMainFrame(message, Uri.parse(BASE_URI));
+        mOnUiThread.postWebMessage(message, Uri.parse(BASE_URI));
         final int messageCount = 3;
         final CountDownLatch latch = new CountDownLatch(messageCount);
         runTestOnUiThread(new Runnable() {
@@ -162,7 +162,7 @@
         loadPage(CHANNEL_MESSAGE);
         final WebMessagePort[] channel = mOnUiThread.createWebMessageChannel();
         WebMessage message = new WebMessage(WEBVIEW_MESSAGE, new WebMessagePort[]{channel[1]});
-        mOnUiThread.postMessageToMainFrame(message, Uri.parse(BASE_URI));
+        mOnUiThread.postWebMessage(message, Uri.parse(BASE_URI));
         runTestOnUiThread(new Runnable() {
             @Override
             public void run() {
@@ -205,7 +205,7 @@
         loadPage(CHANNEL_FROM_JS);
         final WebMessagePort[] channel = mOnUiThread.createWebMessageChannel();
         WebMessage message = new WebMessage(WEBVIEW_MESSAGE, new WebMessagePort[]{channel[1]});
-        mOnUiThread.postMessageToMainFrame(message, Uri.parse(BASE_URI));
+        mOnUiThread.postWebMessage(message, Uri.parse(BASE_URI));
         runTestOnUiThread(new Runnable() {
             @Override
             public void run() {
diff --git a/tests/webgl/Android.mk b/tests/webgl/Android.mk
deleted file mode 100755
index ce22dd8..0000000
--- a/tests/webgl/Android.mk
+++ /dev/null
@@ -1,34 +0,0 @@
-# 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.
-# 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 := optional
-
-# When built, explicitly put it in the data partition.
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-# Must match the package name in CtsTestCaseList.mk
-LOCAL_PACKAGE_NAME := CtsWebGLTestCases
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/webgl/AndroidManifest.xml b/tests/webgl/AndroidManifest.xml
deleted file mode 100755
index d648032..0000000
--- a/tests/webgl/AndroidManifest.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?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.
- * 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.webgl.cts">
-
-    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
-    <uses-permission android:name="android.permission.INTERNET" />
-
-    <application android:maxRecents="1">
-        <uses-library android:name="android.test.runner" />
-        <activity android:name="android.webgl.WebGLActivity" >
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-    </application>
-
-
-    <!--  self-instrumenting test package. -->
-    <instrumentation
-        android:name="android.support.test.runner.AndroidJUnitRunner"
-        android:label="CTS WebGL tests"
-        android:targetPackage="android.webgl.cts" >
-        <meta-data
-            android:name="listener"
-            android:value="com.android.cts.runner.CtsTestRunListener" />
-    </instrumentation>
-</manifest>
-
diff --git a/tests/webgl/res/raw/extract_webgl_tests.py b/tests/webgl/res/raw/extract_webgl_tests.py
deleted file mode 100755
index 1511632..0000000
--- a/tests/webgl/res/raw/extract_webgl_tests.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# 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.
-# 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 sys
-import os
-
-if len(sys.argv) != 3:
-  raise Exception("Usage: extract_webgl_tests.py <webgl_sdk_tests_path> <version>")
-
-top_list = sys.argv[1] + "/00_test_list.txt"
-version = sys.argv[2]
-tests = []
-lists = []
-lists.append(top_list)
-
-def filter_by_version(lines):
-  version_lines = [ line for line in lines if "--min-version" in line ]
-  version_lines.extend([ line for line in lines if "--max-version" in line ])
-  lines = [ line for line in lines if not line in version_lines ]
-  for line in version_lines:
-    assert len(line.split()) == 3
-    min_version = line.split()[1] if line.split()[0] == "--min-version" else "0.0.0"
-    max_version = line.split()[1] if line.split()[0] == "--max-version" else "9.9.9"
-    test = line.split()[2]
-    if (version >= min_version and version <= max_version):
-      lines.append(test)
-  return lines
-
-while not len(lists) == 0:
-  lists2 = lists
-  lists = []
-  for list in lists2:
-    directory = os.path.dirname(os.path.realpath(list))
-    with open(list) as file:
-      # Filter out comments and --min-version
-      lines = [ line.strip() for line in file.readlines()]
-      lines = [ line for line in lines if not "//" in line ]
-      lines = [ line for line in lines if not "#" in line ]
-      lines = [ line.replace("--slow","") for line in lines ]
-      lines = filter_by_version(lines)
-      # Append lists and tests found in this list.
-      lines = [ directory + "/" + line for line in lines ]
-      lists.extend([ line for line in lines if "00_test_list.txt" in line ])
-      tests.extend([ line for line in lines if ".html" in line ])
-
-# Directories for formating test-names/relative-paths.
-name_directory = os.path.dirname(os.path.realpath(top_list))
-path_directory = os.path.realpath(os.path.join(name_directory, os.pardir))
-
-tests = sorted(tests)
-for test in tests:
-  test_path = test.replace(path_directory + "/", "")
-  test_name = test.replace(name_directory + "/", "")
-  test_name = test_name.replace("/","_")
-  test_name = test_name.replace(".","_")
-  test_name = test_name.replace("-","_")
-  print "    public void test_" + test_name + "() throws Exception { doTest(\"" + test_path + "\"); }"
-
diff --git a/tests/webgl/res/raw/harness.html b/tests/webgl/res/raw/harness.html
deleted file mode 100644
index 5ae56ef..0000000
--- a/tests/webgl/res/raw/harness.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!DOCTYPE html>
-<!-- saved from url=(0057)http://www.corp.google.com/~vollick/timing-functions.html -->
-<html>
-<head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
-
-<script type="text/javascript">
-    // Check for WebGL Support.
-    function supportsWebGL() {
-        var canvas = document.createElement('canvas');
-        gl = canvas.getContext("webgl");
-        return !!gl;
-    }
-
-    // Pass the WebGL harness calls through to the native app.
-    webglTestHarness = {
-        notifyFinished: function() {
-            WebGLCallback.notifyFinished();
-        },
-        reportResults: function(type, success, msg) {
-            WebGLCallback.reportResults(type, success, msg);
-        }
-    }
-    function navigateToTest() {
-        if (supportsWebGL())
-            window.open(WebGLCallback.getUrlToTest(), "TestFrame");
-        else
-            WebGLCallback.notifyFinished();
-    }
-    window.addEventListener('load', navigateToTest, false);
-</script>
-
-<style type="text/css">
-body, html { margin: 0; padding: 0; height: 100%; overflow: hidden; }
-#content { position:absolute; left: 0; right: 0; bottom: 0; top: 0px; }
-</style>
-
-</head>
-
-<body>
-  <div id="content">
-    <iframe name="TestFrame" width="100%" height="100%" frameborder="0"/>
-  </div>
-</body>
-</html>
diff --git a/tests/webgl/res/raw/webgl_sdk_tests.zip b/tests/webgl/res/raw/webgl_sdk_tests.zip
deleted file mode 100644
index a2086b0..0000000
--- a/tests/webgl/res/raw/webgl_sdk_tests.zip
+++ /dev/null
Binary files differ
diff --git a/tests/webgl/src/android/webgl/WebGLActivity.java b/tests/webgl/src/android/webgl/WebGLActivity.java
deleted file mode 100644
index 3f911c4..0000000
--- a/tests/webgl/src/android/webgl/WebGLActivity.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * 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.
- * 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.webgl;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.res.Resources;
-import android.cts.util.NullWebViewUtils;
-import android.os.Bundle;
-import android.util.Log;
-import android.webgl.cts.R;
-import android.webkit.WebView;
-import android.webkit.JavascriptInterface;
-import android.webkit.WebViewClient;
-import android.widget.Toast;
-import java.lang.Override;
-import java.io.InputStream;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-/**
- * A simple activity for testing WebGL Conformance with WebView.
- */
-public class WebGLActivity extends Activity {
-
-    Semaphore mFinished = new Semaphore(0, false);
-    Semaphore mDestroyed = new Semaphore(0, false);
-    String mWebGlHarnessUrl;
-    WebView mWebView;
-
-    // The following members are synchronized.
-    String mWebGLTestUrl;
-    boolean mPassed = true;
-    StringBuilder mMessage = new StringBuilder("\n");
-
-    @Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-
-        mWebGlHarnessUrl = "file://" + getCacheDir() + "/harness.html";
-        try {
-            mWebView = new WebView(this);
-        } catch (Exception e) {
-            NullWebViewUtils.determineIfWebViewAvailable(this, e);
-        }
-
-        if (mWebView == null) {
-            return;
-        }
-
-        mWebView.getSettings().setJavaScriptEnabled(true);
-        mWebView.getSettings().setAllowFileAccessFromFileURLs(true);
-        mWebView.getSettings().setMediaPlaybackRequiresUserGesture(false);
-        mWebView.setWebViewClient(new WebViewClient() {
-            @Override
-            public boolean shouldOverrideUrlLoading(WebView webView, String url) {
-                return false;
-            }
-        });
-
-        mWebView.addJavascriptInterface(new Object() {
-            @JavascriptInterface
-            public String getUrlToTest() {
-                synchronized(WebGLActivity.this) {
-                    return mWebGLTestUrl;
-                }
-            }
-
-            @JavascriptInterface
-            public void reportResults(String type, boolean success, String message) {
-                synchronized(WebGLActivity.this) {
-                    mMessage.append((success ? "PASS " : "FAIL ") + message + "\n");
-                    mPassed &= success;
-                }
-            }
-
-            @JavascriptInterface
-            public void notifyFinished() {
-                mFinished.release();
-            }
-
-            @JavascriptInterface
-            public void alert(String string) {
-                Log.i(mWebGLTestUrl, string);
-            }
-        }, "WebGLCallback");
-        setContentView(mWebView);
-    }
-
-    public void navigateToTest(String url) throws Exception {
-        if (!NullWebViewUtils.isWebViewAvailable()) {
-            return;
-        }
-
-        synchronized(WebGLActivity.this) {
-            mWebGLTestUrl = url;
-        }
-
-        // Load harness.html, which will load mWebGLTestUrl in an <iframe>.
-        runOnUiThread(new Runnable() {
-            public void run() {
-                mWebView.loadUrl(mWebGlHarnessUrl);
-            }
-        });
-
-        // Wait on test completion.
-        boolean finished = mFinished.tryAcquire(60, TimeUnit.SECONDS);
-        String message;
-        synchronized(WebGLActivity.this) {
-            message = mMessage.toString();
-        }
-
-        // Destroy the webview and wait for it.
-        runOnUiThread(new Runnable() {
-            public void run() {
-                mWebView.destroy();
-                finish();
-                mDestroyed.release();
-            }
-        });
-        mDestroyed.acquire();
-
-        if (!finished)
-            throw new Exception("\n" + url + "\n Test timed-out after 60 seconds: " + message);
-        if(!mPassed)
-            throw new Exception("\n" + url + "\n Test failed: " + message);
-    }
-}
diff --git a/tests/webgl/src/android/webgl/cts/WebGLConformanceSuite.java b/tests/webgl/src/android/webgl/cts/WebGLConformanceSuite.java
deleted file mode 100644
index 60f663a..0000000
--- a/tests/webgl/src/android/webgl/cts/WebGLConformanceSuite.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.
- * 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.webgl.cts;
-
-import android.util.Log;
-import android.webgl.cts.R;
-import android.webgl.WebGLActivity;
-import java.lang.Override;
-import java.io.File;
-import java.io.InputStream;
-
-/**
- * A Singleton class to wrap the WebGL Conformance Test Suite.
- */
-public class WebGLConformanceSuite {
-    private final String TAG = "WebGLConformanceSuite";
-    private static volatile WebGLConformanceSuite mInstance = null;
-
-    private WebGLConformanceSuite(WebGLActivity activity) throws Exception {
-        Log.i(TAG, "Unzipping WebGL Conformance Suite: "
-                + activity.getCacheDir().getPath());
-        InputStream suite = activity.getResources().openRawResource(R.raw.webgl_sdk_tests);
-        ZipUtil.unzipToPath(suite, activity.getCacheDir());
-        InputStream harness = activity.getResources().openRawResource(R.raw.harness);
-        ZipUtil.streamToPath(harness, activity.getCacheDir(), "harness.html");
-    }
-
-    public static WebGLConformanceSuite init(WebGLActivity activity)
-            throws Exception {
-        if (mInstance == null) {
-            synchronized (WebGLConformanceSuite.class) {
-                mInstance = new WebGLConformanceSuite(activity);
-            }
-        }
-        return mInstance;
-    }
-}
diff --git a/tests/webgl/src/android/webgl/cts/WebGLTest.java b/tests/webgl/src/android/webgl/cts/WebGLTest.java
deleted file mode 100644
index d45c190..0000000
--- a/tests/webgl/src/android/webgl/cts/WebGLTest.java
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- * 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.
- * 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.webgl.cts;
-
-import android.webgl.WebGLActivity;
-import android.webgl.cts.R;
-import android.test.ActivityInstrumentationTestCase2;
-import java.io.InputStream;
-
-/**
- * A simple wrapper to load each WebGL conformance test in WebView.
- *
- * This test uses {@link android.test.ActivityInstrumentationTestCase2} to instrument the
- * {@link android.webgl.WebGLActivity}.
- */
-public class WebGLTest extends ActivityInstrumentationTestCase2<WebGLActivity> {
-
-    /**
-     * A reference to the activity whose shared preferences are being tested.
-     */
-    private WebGLActivity mActivity;
-    private WebGLConformanceSuite mWebGL_1_0_1;
-
-    public WebGLTest() {
-        super(WebGLActivity.class);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        // Start the activity and get a reference to it.
-        mActivity = getActivity();
-        // Wait for the UI Thread to become idle.
-        getInstrumentation().waitForIdleSync();
-        mWebGL_1_0_1 = WebGLConformanceSuite.init(mActivity);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        // Scrub the activity so it can be freed. The next time the setUp will create a new activity
-        // rather than reusing the old one.
-        mActivity = null;
-        super.tearDown();
-    }
-
-    protected void doTest(String testPage) throws Exception {
-        mActivity.navigateToTest(testPage);
-    }
-
-    /**
-     * The remainder of this file is generated using this command:
-     * extract_webgl_tests.py tests 1.0.1
-     */
-    public void test_conformance_attribs_gl_enable_vertex_attrib_html() throws Exception { doTest("tests/conformance/attribs/gl-enable-vertex-attrib.html"); }
-    public void test_conformance_attribs_gl_vertex_attrib_zero_issues_html() throws Exception { doTest("tests/conformance/attribs/gl-vertex-attrib-zero-issues.html"); }
-    public void test_conformance_attribs_gl_vertex_attrib_html() throws Exception { doTest("tests/conformance/attribs/gl-vertex-attrib.html"); }
-    public void test_conformance_attribs_gl_vertexattribpointer_offsets_html() throws Exception { doTest("tests/conformance/attribs/gl-vertexattribpointer-offsets.html"); }
-    public void test_conformance_attribs_gl_vertexattribpointer_html() throws Exception { doTest("tests/conformance/attribs/gl-vertexattribpointer.html"); }
-    public void test_conformance_buffers_buffer_bind_test_html() throws Exception { doTest("tests/conformance/buffers/buffer-bind-test.html"); }
-    public void test_conformance_buffers_buffer_data_array_buffer_html() throws Exception { doTest("tests/conformance/buffers/buffer-data-array-buffer.html"); }
-    public void test_conformance_buffers_index_validation_copies_indices_html() throws Exception { doTest("tests/conformance/buffers/index-validation-copies-indices.html"); }
-    public void test_conformance_buffers_index_validation_crash_with_buffer_sub_data_html() throws Exception { doTest("tests/conformance/buffers/index-validation-crash-with-buffer-sub-data.html"); }
-    public void test_conformance_buffers_index_validation_verifies_too_many_indices_html() throws Exception { doTest("tests/conformance/buffers/index-validation-verifies-too-many-indices.html"); }
-    public void test_conformance_buffers_index_validation_with_resized_buffer_html() throws Exception { doTest("tests/conformance/buffers/index-validation-with-resized-buffer.html"); }
-    public void test_conformance_buffers_index_validation_html() throws Exception { doTest("tests/conformance/buffers/index-validation.html"); }
-    public void test_conformance_canvas_buffer_offscreen_test_html() throws Exception { doTest("tests/conformance/canvas/buffer-offscreen-test.html"); }
-    public void test_conformance_canvas_buffer_preserve_test_html() throws Exception { doTest("tests/conformance/canvas/buffer-preserve-test.html"); }
-    public void test_conformance_canvas_canvas_test_html() throws Exception { doTest("tests/conformance/canvas/canvas-test.html"); }
-    public void test_conformance_canvas_canvas_zero_size_html() throws Exception { doTest("tests/conformance/canvas/canvas-zero-size.html"); }
-    public void test_conformance_canvas_drawingbuffer_static_canvas_test_html() throws Exception { doTest("tests/conformance/canvas/drawingbuffer-static-canvas-test.html"); }
-    public void test_conformance_canvas_drawingbuffer_test_html() throws Exception { doTest("tests/conformance/canvas/drawingbuffer-test.html"); }
-    public void test_conformance_canvas_viewport_unchanged_upon_resize_html() throws Exception { doTest("tests/conformance/canvas/viewport-unchanged-upon-resize.html"); }
-    public void test_conformance_context_constants_and_properties_html() throws Exception { doTest("tests/conformance/context/constants-and-properties.html"); }
-    public void test_conformance_context_context_attributes_alpha_depth_stencil_antialias_html() throws Exception { doTest("tests/conformance/context/context-attributes-alpha-depth-stencil-antialias.html"); }
-    public void test_conformance_context_context_lost_restored_html() throws Exception { doTest("tests/conformance/context/context-lost-restored.html"); }
-    public void test_conformance_context_context_lost_html() throws Exception { doTest("tests/conformance/context/context-lost.html"); }
-    public void test_conformance_context_context_type_test_html() throws Exception { doTest("tests/conformance/context/context-type-test.html"); }
-    public void test_conformance_context_incorrect_context_object_behaviour_html() throws Exception { doTest("tests/conformance/context/incorrect-context-object-behaviour.html"); }
-    public void test_conformance_context_methods_html() throws Exception { doTest("tests/conformance/context/methods.html"); }
-    public void test_conformance_context_premultiplyalpha_test_html() throws Exception { doTest("tests/conformance/context/premultiplyalpha-test.html"); }
-    public void test_conformance_context_resource_sharing_test_html() throws Exception { doTest("tests/conformance/context/resource-sharing-test.html"); }
-    public void test_conformance_extensions_oes_standard_derivatives_html() throws Exception { doTest("tests/conformance/extensions/oes-standard-derivatives.html"); }
-    public void test_conformance_extensions_oes_texture_float_with_canvas_html() throws Exception { doTest("tests/conformance/extensions/oes-texture-float-with-canvas.html"); }
-    public void test_conformance_extensions_oes_texture_float_with_image_data_html() throws Exception { doTest("tests/conformance/extensions/oes-texture-float-with-image-data.html"); }
-    public void test_conformance_extensions_oes_texture_float_with_image_html() throws Exception { doTest("tests/conformance/extensions/oes-texture-float-with-image.html"); }
-    public void test_conformance_extensions_oes_texture_float_with_video_html() throws Exception { doTest("tests/conformance/extensions/oes-texture-float-with-video.html"); }
-    public void test_conformance_extensions_oes_texture_float_html() throws Exception { doTest("tests/conformance/extensions/oes-texture-float.html"); }
-    public void test_conformance_extensions_oes_vertex_array_object_html() throws Exception { doTest("tests/conformance/extensions/oes-vertex-array-object.html"); }
-    public void test_conformance_extensions_webgl_debug_renderer_info_html() throws Exception { doTest("tests/conformance/extensions/webgl-debug-renderer-info.html"); }
-    public void test_conformance_extensions_webgl_debug_shaders_html() throws Exception { doTest("tests/conformance/extensions/webgl-debug-shaders.html"); }
-    public void test_conformance_glsl_functions_glsl_function_abs_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-abs.html"); }
-    public void test_conformance_glsl_functions_glsl_function_acos_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-acos.html"); }
-    public void test_conformance_glsl_functions_glsl_function_asin_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-asin.html"); }
-    public void test_conformance_glsl_functions_glsl_function_atan_xy_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-atan-xy.html"); }
-    public void test_conformance_glsl_functions_glsl_function_atan_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-atan.html"); }
-    public void test_conformance_glsl_functions_glsl_function_ceil_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-ceil.html"); }
-    public void test_conformance_glsl_functions_glsl_function_clamp_float_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-clamp-float.html"); }
-    public void test_conformance_glsl_functions_glsl_function_clamp_gentype_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-clamp-gentype.html"); }
-    public void test_conformance_glsl_functions_glsl_function_cos_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-cos.html"); }
-    public void test_conformance_glsl_functions_glsl_function_cross_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-cross.html"); }
-    public void test_conformance_glsl_functions_glsl_function_distance_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-distance.html"); }
-    public void test_conformance_glsl_functions_glsl_function_dot_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-dot.html"); }
-    public void test_conformance_glsl_functions_glsl_function_faceforward_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-faceforward.html"); }
-    public void test_conformance_glsl_functions_glsl_function_floor_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-floor.html"); }
-    public void test_conformance_glsl_functions_glsl_function_fract_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-fract.html"); }
-    public void test_conformance_glsl_functions_glsl_function_length_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-length.html"); }
-    public void test_conformance_glsl_functions_glsl_function_max_float_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-max-float.html"); }
-    public void test_conformance_glsl_functions_glsl_function_max_gentype_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-max-gentype.html"); }
-    public void test_conformance_glsl_functions_glsl_function_min_float_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-min-float.html"); }
-    public void test_conformance_glsl_functions_glsl_function_min_gentype_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-min-gentype.html"); }
-    public void test_conformance_glsl_functions_glsl_function_mix_float_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-mix-float.html"); }
-    public void test_conformance_glsl_functions_glsl_function_mix_gentype_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-mix-gentype.html"); }
-    public void test_conformance_glsl_functions_glsl_function_mod_float_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-mod-float.html"); }
-    public void test_conformance_glsl_functions_glsl_function_mod_gentype_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-mod-gentype.html"); }
-    public void test_conformance_glsl_functions_glsl_function_normalize_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-normalize.html"); }
-    public void test_conformance_glsl_functions_glsl_function_reflect_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-reflect.html"); }
-    public void test_conformance_glsl_functions_glsl_function_sign_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-sign.html"); }
-    public void test_conformance_glsl_functions_glsl_function_sin_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-sin.html"); }
-    public void test_conformance_glsl_functions_glsl_function_smoothstep_float_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-smoothstep-float.html"); }
-    public void test_conformance_glsl_functions_glsl_function_smoothstep_gentype_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-smoothstep-gentype.html"); }
-    public void test_conformance_glsl_functions_glsl_function_step_float_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-step-float.html"); }
-    public void test_conformance_glsl_functions_glsl_function_step_gentype_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-step-gentype.html"); }
-    public void test_conformance_glsl_functions_glsl_function_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function.html"); }
-    public void test_conformance_glsl_implicit_add_int_float_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/add_int_float.vert.html"); }
-    public void test_conformance_glsl_implicit_add_int_mat2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/add_int_mat2.vert.html"); }
-    public void test_conformance_glsl_implicit_add_int_mat3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/add_int_mat3.vert.html"); }
-    public void test_conformance_glsl_implicit_add_int_mat4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/add_int_mat4.vert.html"); }
-    public void test_conformance_glsl_implicit_add_int_vec2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/add_int_vec2.vert.html"); }
-    public void test_conformance_glsl_implicit_add_int_vec3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/add_int_vec3.vert.html"); }
-    public void test_conformance_glsl_implicit_add_int_vec4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/add_int_vec4.vert.html"); }
-    public void test_conformance_glsl_implicit_add_ivec2_vec2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/add_ivec2_vec2.vert.html"); }
-    public void test_conformance_glsl_implicit_add_ivec3_vec3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/add_ivec3_vec3.vert.html"); }
-    public void test_conformance_glsl_implicit_add_ivec4_vec4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/add_ivec4_vec4.vert.html"); }
-    public void test_conformance_glsl_implicit_assign_int_to_float_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/assign_int_to_float.vert.html"); }
-    public void test_conformance_glsl_implicit_assign_ivec2_to_vec2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/assign_ivec2_to_vec2.vert.html"); }
-    public void test_conformance_glsl_implicit_assign_ivec3_to_vec3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/assign_ivec3_to_vec3.vert.html"); }
-    public void test_conformance_glsl_implicit_assign_ivec4_to_vec4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/assign_ivec4_to_vec4.vert.html"); }
-    public void test_conformance_glsl_implicit_construct_struct_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/construct_struct.vert.html"); }
-    public void test_conformance_glsl_implicit_divide_int_float_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/divide_int_float.vert.html"); }
-    public void test_conformance_glsl_implicit_divide_int_mat2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/divide_int_mat2.vert.html"); }
-    public void test_conformance_glsl_implicit_divide_int_mat3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/divide_int_mat3.vert.html"); }
-    public void test_conformance_glsl_implicit_divide_int_mat4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/divide_int_mat4.vert.html"); }
-    public void test_conformance_glsl_implicit_divide_int_vec2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/divide_int_vec2.vert.html"); }
-    public void test_conformance_glsl_implicit_divide_int_vec3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/divide_int_vec3.vert.html"); }
-    public void test_conformance_glsl_implicit_divide_int_vec4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/divide_int_vec4.vert.html"); }
-    public void test_conformance_glsl_implicit_divide_ivec2_vec2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/divide_ivec2_vec2.vert.html"); }
-    public void test_conformance_glsl_implicit_divide_ivec3_vec3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/divide_ivec3_vec3.vert.html"); }
-    public void test_conformance_glsl_implicit_divide_ivec4_vec4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/divide_ivec4_vec4.vert.html"); }
-    public void test_conformance_glsl_implicit_equal_int_float_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/equal_int_float.vert.html"); }
-    public void test_conformance_glsl_implicit_equal_ivec2_vec2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/equal_ivec2_vec2.vert.html"); }
-    public void test_conformance_glsl_implicit_equal_ivec3_vec3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/equal_ivec3_vec3.vert.html"); }
-    public void test_conformance_glsl_implicit_equal_ivec4_vec4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/equal_ivec4_vec4.vert.html"); }
-    public void test_conformance_glsl_implicit_function_int_float_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/function_int_float.vert.html"); }
-    public void test_conformance_glsl_implicit_function_ivec2_vec2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/function_ivec2_vec2.vert.html"); }
-    public void test_conformance_glsl_implicit_function_ivec3_vec3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/function_ivec3_vec3.vert.html"); }
-    public void test_conformance_glsl_implicit_function_ivec4_vec4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/function_ivec4_vec4.vert.html"); }
-    public void test_conformance_glsl_implicit_greater_than_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/greater_than.vert.html"); }
-    public void test_conformance_glsl_implicit_greater_than_equal_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/greater_than_equal.vert.html"); }
-    public void test_conformance_glsl_implicit_less_than_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/less_than.vert.html"); }
-    public void test_conformance_glsl_implicit_less_than_equal_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/less_than_equal.vert.html"); }
-    public void test_conformance_glsl_implicit_multiply_int_float_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/multiply_int_float.vert.html"); }
-    public void test_conformance_glsl_implicit_multiply_int_mat2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/multiply_int_mat2.vert.html"); }
-    public void test_conformance_glsl_implicit_multiply_int_mat3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/multiply_int_mat3.vert.html"); }
-    public void test_conformance_glsl_implicit_multiply_int_mat4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/multiply_int_mat4.vert.html"); }
-    public void test_conformance_glsl_implicit_multiply_int_vec2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/multiply_int_vec2.vert.html"); }
-    public void test_conformance_glsl_implicit_multiply_int_vec3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/multiply_int_vec3.vert.html"); }
-    public void test_conformance_glsl_implicit_multiply_int_vec4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/multiply_int_vec4.vert.html"); }
-    public void test_conformance_glsl_implicit_multiply_ivec2_vec2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/multiply_ivec2_vec2.vert.html"); }
-    public void test_conformance_glsl_implicit_multiply_ivec3_vec3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/multiply_ivec3_vec3.vert.html"); }
-    public void test_conformance_glsl_implicit_multiply_ivec4_vec4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/multiply_ivec4_vec4.vert.html"); }
-    public void test_conformance_glsl_implicit_not_equal_int_float_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/not_equal_int_float.vert.html"); }
-    public void test_conformance_glsl_implicit_not_equal_ivec2_vec2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/not_equal_ivec2_vec2.vert.html"); }
-    public void test_conformance_glsl_implicit_not_equal_ivec3_vec3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/not_equal_ivec3_vec3.vert.html"); }
-    public void test_conformance_glsl_implicit_not_equal_ivec4_vec4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/not_equal_ivec4_vec4.vert.html"); }
-    public void test_conformance_glsl_implicit_subtract_int_float_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/subtract_int_float.vert.html"); }
-    public void test_conformance_glsl_implicit_subtract_int_mat2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/subtract_int_mat2.vert.html"); }
-    public void test_conformance_glsl_implicit_subtract_int_mat3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/subtract_int_mat3.vert.html"); }
-    public void test_conformance_glsl_implicit_subtract_int_mat4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/subtract_int_mat4.vert.html"); }
-    public void test_conformance_glsl_implicit_subtract_int_vec2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/subtract_int_vec2.vert.html"); }
-    public void test_conformance_glsl_implicit_subtract_int_vec3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/subtract_int_vec3.vert.html"); }
-    public void test_conformance_glsl_implicit_subtract_int_vec4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/subtract_int_vec4.vert.html"); }
-    public void test_conformance_glsl_implicit_subtract_ivec2_vec2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/subtract_ivec2_vec2.vert.html"); }
-    public void test_conformance_glsl_implicit_subtract_ivec3_vec3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/subtract_ivec3_vec3.vert.html"); }
-    public void test_conformance_glsl_implicit_subtract_ivec4_vec4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/subtract_ivec4_vec4.vert.html"); }
-    public void test_conformance_glsl_implicit_ternary_int_float_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/ternary_int_float.vert.html"); }
-    public void test_conformance_glsl_implicit_ternary_ivec2_vec2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/ternary_ivec2_vec2.vert.html"); }
-    public void test_conformance_glsl_implicit_ternary_ivec3_vec3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/ternary_ivec3_vec3.vert.html"); }
-    public void test_conformance_glsl_implicit_ternary_ivec4_vec4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/ternary_ivec4_vec4.vert.html"); }
-    public void test_conformance_glsl_misc_attrib_location_length_limits_html() throws Exception { doTest("tests/conformance/glsl/misc/attrib-location-length-limits.html"); }
-    public void test_conformance_glsl_misc_embedded_struct_definitions_forbidden_html() throws Exception { doTest("tests/conformance/glsl/misc/embedded-struct-definitions-forbidden.html"); }
-    public void test_conformance_glsl_misc_empty_main_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/empty_main.vert.html"); }
-    public void test_conformance_glsl_misc_gl_position_unset_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/gl_position_unset.vert.html"); }
-    public void test_conformance_glsl_misc_glsl_function_nodes_html() throws Exception { doTest("tests/conformance/glsl/misc/glsl-function-nodes.html"); }
-    public void test_conformance_glsl_misc_glsl_long_variable_names_html() throws Exception { doTest("tests/conformance/glsl/misc/glsl-long-variable-names.html"); }
-    public void test_conformance_glsl_misc_non_ascii_comments_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/non-ascii-comments.vert.html"); }
-    public void test_conformance_glsl_misc_non_ascii_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/non-ascii.vert.html"); }
-    public void test_conformance_glsl_misc_shader_with_256_character_identifier_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-256-character-identifier.frag.html"); }
-    public void test_conformance_glsl_misc_shader_with_257_character_identifier_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-257-character-identifier.frag.html"); }
-    public void test_conformance_glsl_misc_shader_with__webgl_identifier_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-_webgl-identifier.vert.html"); }
-    public void test_conformance_glsl_misc_shader_with_arbitrary_indexing_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-arbitrary-indexing.frag.html"); }
-    public void test_conformance_glsl_misc_shader_with_arbitrary_indexing_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-arbitrary-indexing.vert.html"); }
-    public void test_conformance_glsl_misc_shader_with_attrib_array_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-attrib-array.vert.html"); }
-    public void test_conformance_glsl_misc_shader_with_attrib_struct_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-attrib-struct.vert.html"); }
-    public void test_conformance_glsl_misc_shader_with_clipvertex_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-clipvertex.vert.html"); }
-    public void test_conformance_glsl_misc_shader_with_default_precision_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-default-precision.frag.html"); }
-    public void test_conformance_glsl_misc_shader_with_default_precision_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-default-precision.vert.html"); }
-    public void test_conformance_glsl_misc_shader_with_define_line_continuation_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-define-line-continuation.frag.html"); }
-    public void test_conformance_glsl_misc_shader_with_dfdx_no_ext_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-dfdx-no-ext.frag.html"); }
-    public void test_conformance_glsl_misc_shader_with_dfdx_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-dfdx.frag.html"); }
-    public void test_conformance_glsl_misc_shader_with_error_directive_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-error-directive.html"); }
-    public void test_conformance_glsl_misc_shader_with_explicit_int_cast_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-explicit-int-cast.vert.html"); }
-    public void test_conformance_glsl_misc_shader_with_float_return_value_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-float-return-value.frag.html"); }
-    public void test_conformance_glsl_misc_shader_with_frag_depth_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-frag-depth.frag.html"); }
-    public void test_conformance_glsl_misc_shader_with_function_recursion_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-function-recursion.frag.html"); }
-    public void test_conformance_glsl_misc_shader_with_glcolor_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-glcolor.vert.html"); }
-    public void test_conformance_glsl_misc_shader_with_gles_1_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-gles-1.frag.html"); }
-    public void test_conformance_glsl_misc_shader_with_gles_symbol_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-gles-symbol.frag.html"); }
-    public void test_conformance_glsl_misc_shader_with_glprojectionmatrix_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-glprojectionmatrix.vert.html"); }
-    public void test_conformance_glsl_misc_shader_with_implicit_vec3_to_vec4_cast_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-implicit-vec3-to-vec4-cast.vert.html"); }
-    public void test_conformance_glsl_misc_shader_with_include_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-include.vert.html"); }
-    public void test_conformance_glsl_misc_shader_with_int_return_value_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-int-return-value.frag.html"); }
-    public void test_conformance_glsl_misc_shader_with_invalid_identifier_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-invalid-identifier.frag.html"); }
-    public void test_conformance_glsl_misc_shader_with_ivec2_return_value_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-ivec2-return-value.frag.html"); }
-    public void test_conformance_glsl_misc_shader_with_ivec3_return_value_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-ivec3-return-value.frag.html"); }
-    public void test_conformance_glsl_misc_shader_with_ivec4_return_value_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-ivec4-return-value.frag.html"); }
-    public void test_conformance_glsl_misc_shader_with_limited_indexing_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-limited-indexing.frag.html"); }
-    public void test_conformance_glsl_misc_shader_with_long_line_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-long-line.html"); }
-    public void test_conformance_glsl_misc_shader_with_non_ascii_error_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-non-ascii-error.frag.html"); }
-    public void test_conformance_glsl_misc_shader_with_precision_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-precision.frag.html"); }
-    public void test_conformance_glsl_misc_shader_with_quoted_error_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-quoted-error.frag.html"); }
-    public void test_conformance_glsl_misc_shader_with_undefined_preprocessor_symbol_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-undefined-preprocessor-symbol.frag.html"); }
-    public void test_conformance_glsl_misc_shader_with_uniform_in_loop_condition_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-uniform-in-loop-condition.vert.html"); }
-    public void test_conformance_glsl_misc_shader_with_vec2_return_value_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-vec2-return-value.frag.html"); }
-    public void test_conformance_glsl_misc_shader_with_vec3_return_value_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-vec3-return-value.frag.html"); }
-    public void test_conformance_glsl_misc_shader_with_vec4_return_value_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-vec4-return-value.frag.html"); }
-    public void test_conformance_glsl_misc_shader_with_version_100_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-version-100.frag.html"); }
-    public void test_conformance_glsl_misc_shader_with_version_100_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-version-100.vert.html"); }
-    public void test_conformance_glsl_misc_shader_with_version_120_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-version-120.vert.html"); }
-    public void test_conformance_glsl_misc_shader_with_version_130_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-version-130.vert.html"); }
-    public void test_conformance_glsl_misc_shader_with_webgl_identifier_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-webgl-identifier.vert.html"); }
-    public void test_conformance_glsl_misc_shader_without_precision_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-without-precision.frag.html"); }
-    public void test_conformance_glsl_misc_shared_html() throws Exception { doTest("tests/conformance/glsl/misc/shared.html"); }
-    public void test_conformance_glsl_misc_struct_nesting_exceeds_maximum_html() throws Exception { doTest("tests/conformance/glsl/misc/struct-nesting-exceeds-maximum.html"); }
-    public void test_conformance_glsl_misc_struct_nesting_under_maximum_html() throws Exception { doTest("tests/conformance/glsl/misc/struct-nesting-under-maximum.html"); }
-    public void test_conformance_glsl_misc_uniform_location_length_limits_html() throws Exception { doTest("tests/conformance/glsl/misc/uniform-location-length-limits.html"); }
-    public void test_conformance_glsl_reserved__webgl_field_vert_html() throws Exception { doTest("tests/conformance/glsl/reserved/_webgl_field.vert.html"); }
-    public void test_conformance_glsl_reserved__webgl_function_vert_html() throws Exception { doTest("tests/conformance/glsl/reserved/_webgl_function.vert.html"); }
-    public void test_conformance_glsl_reserved__webgl_struct_vert_html() throws Exception { doTest("tests/conformance/glsl/reserved/_webgl_struct.vert.html"); }
-    public void test_conformance_glsl_reserved__webgl_variable_vert_html() throws Exception { doTest("tests/conformance/glsl/reserved/_webgl_variable.vert.html"); }
-    public void test_conformance_glsl_reserved_webgl_field_vert_html() throws Exception { doTest("tests/conformance/glsl/reserved/webgl_field.vert.html"); }
-    public void test_conformance_glsl_reserved_webgl_function_vert_html() throws Exception { doTest("tests/conformance/glsl/reserved/webgl_function.vert.html"); }
-    public void test_conformance_glsl_reserved_webgl_struct_vert_html() throws Exception { doTest("tests/conformance/glsl/reserved/webgl_struct.vert.html"); }
-    public void test_conformance_glsl_reserved_webgl_variable_vert_html() throws Exception { doTest("tests/conformance/glsl/reserved/webgl_variable.vert.html"); }
-    public void test_conformance_glsl_variables_gl_fragcoord_html() throws Exception { doTest("tests/conformance/glsl/variables/gl-fragcoord.html"); }
-    public void test_conformance_glsl_variables_gl_frontfacing_html() throws Exception { doTest("tests/conformance/glsl/variables/gl-frontfacing.html"); }
-    public void test_conformance_glsl_variables_gl_pointcoord_html() throws Exception { doTest("tests/conformance/glsl/variables/gl-pointcoord.html"); }
-    public void test_conformance_limits_gl_max_texture_dimensions_html() throws Exception { doTest("tests/conformance/limits/gl-max-texture-dimensions.html"); }
-    public void test_conformance_limits_gl_min_attribs_html() throws Exception { doTest("tests/conformance/limits/gl-min-attribs.html"); }
-    public void test_conformance_limits_gl_min_textures_html() throws Exception { doTest("tests/conformance/limits/gl-min-textures.html"); }
-    public void test_conformance_limits_gl_min_uniforms_html() throws Exception { doTest("tests/conformance/limits/gl-min-uniforms.html"); }
-    public void test_conformance_misc_bad_arguments_test_html() throws Exception { doTest("tests/conformance/misc/bad-arguments-test.html"); }
-    public void test_conformance_misc_error_reporting_html() throws Exception { doTest("tests/conformance/misc/error-reporting.html"); }
-    public void test_conformance_misc_functions_returning_strings_html() throws Exception { doTest("tests/conformance/misc/functions-returning-strings.html"); }
-    public void test_conformance_misc_instanceof_test_html() throws Exception { doTest("tests/conformance/misc/instanceof-test.html"); }
-    public void test_conformance_misc_invalid_passed_params_html() throws Exception { doTest("tests/conformance/misc/invalid-passed-params.html"); }
-    public void test_conformance_misc_is_object_html() throws Exception { doTest("tests/conformance/misc/is-object.html"); }
-    public void test_conformance_misc_null_object_behaviour_html() throws Exception { doTest("tests/conformance/misc/null-object-behaviour.html"); }
-    public void test_conformance_misc_object_deletion_behaviour_html() throws Exception { doTest("tests/conformance/misc/object-deletion-behaviour.html"); }
-    public void test_conformance_misc_shader_precision_format_html() throws Exception { doTest("tests/conformance/misc/shader-precision-format.html"); }
-    public void test_conformance_misc_type_conversion_test_html() throws Exception { doTest("tests/conformance/misc/type-conversion-test.html"); }
-    public void test_conformance_misc_uninitialized_test_html() throws Exception { doTest("tests/conformance/misc/uninitialized-test.html"); }
-    public void test_conformance_misc_webgl_specific_html() throws Exception { doTest("tests/conformance/misc/webgl-specific.html"); }
-    public void test_conformance_more_conformance_constants_html() throws Exception { doTest("tests/conformance/more/conformance/constants.html"); }
-    public void test_conformance_more_conformance_getContext_html() throws Exception { doTest("tests/conformance/more/conformance/getContext.html"); }
-    public void test_conformance_more_conformance_methods_html() throws Exception { doTest("tests/conformance/more/conformance/methods.html"); }
-    public void test_conformance_more_conformance_quickCheckAPI_A_html() throws Exception { doTest("tests/conformance/more/conformance/quickCheckAPI-A.html"); }
-    public void test_conformance_more_conformance_quickCheckAPI_B1_html() throws Exception { doTest("tests/conformance/more/conformance/quickCheckAPI-B1.html"); }
-    public void test_conformance_more_conformance_quickCheckAPI_B2_html() throws Exception { doTest("tests/conformance/more/conformance/quickCheckAPI-B2.html"); }
-    public void test_conformance_more_conformance_quickCheckAPI_B3_html() throws Exception { doTest("tests/conformance/more/conformance/quickCheckAPI-B3.html"); }
-    public void test_conformance_more_conformance_quickCheckAPI_B4_html() throws Exception { doTest("tests/conformance/more/conformance/quickCheckAPI-B4.html"); }
-    public void test_conformance_more_conformance_quickCheckAPI_C_html() throws Exception { doTest("tests/conformance/more/conformance/quickCheckAPI-C.html"); }
-    public void test_conformance_more_conformance_quickCheckAPI_D_G_html() throws Exception { doTest("tests/conformance/more/conformance/quickCheckAPI-D_G.html"); }
-    public void test_conformance_more_conformance_quickCheckAPI_G_I_html() throws Exception { doTest("tests/conformance/more/conformance/quickCheckAPI-G_I.html"); }
-    public void test_conformance_more_conformance_quickCheckAPI_L_S_html() throws Exception { doTest("tests/conformance/more/conformance/quickCheckAPI-L_S.html"); }
-    public void test_conformance_more_conformance_quickCheckAPI_S_V_html() throws Exception { doTest("tests/conformance/more/conformance/quickCheckAPI-S_V.html"); }
-    public void test_conformance_more_conformance_webGLArrays_html() throws Exception { doTest("tests/conformance/more/conformance/webGLArrays.html"); }
-    public void test_conformance_more_functions_bindBuffer_html() throws Exception { doTest("tests/conformance/more/functions/bindBuffer.html"); }
-    public void test_conformance_more_functions_bindBufferBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/bindBufferBadArgs.html"); }
-    public void test_conformance_more_functions_bindFramebufferLeaveNonZero_html() throws Exception { doTest("tests/conformance/more/functions/bindFramebufferLeaveNonZero.html"); }
-    public void test_conformance_more_functions_bufferData_html() throws Exception { doTest("tests/conformance/more/functions/bufferData.html"); }
-    public void test_conformance_more_functions_bufferDataBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/bufferDataBadArgs.html"); }
-    public void test_conformance_more_functions_bufferSubData_html() throws Exception { doTest("tests/conformance/more/functions/bufferSubData.html"); }
-    public void test_conformance_more_functions_bufferSubDataBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/bufferSubDataBadArgs.html"); }
-    public void test_conformance_more_functions_copyTexImage2D_html() throws Exception { doTest("tests/conformance/more/functions/copyTexImage2D.html"); }
-    public void test_conformance_more_functions_copyTexImage2DBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/copyTexImage2DBadArgs.html"); }
-    public void test_conformance_more_functions_copyTexSubImage2D_html() throws Exception { doTest("tests/conformance/more/functions/copyTexSubImage2D.html"); }
-    public void test_conformance_more_functions_copyTexSubImage2DBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/copyTexSubImage2DBadArgs.html"); }
-    public void test_conformance_more_functions_deleteBufferBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/deleteBufferBadArgs.html"); }
-    public void test_conformance_more_functions_drawArrays_html() throws Exception { doTest("tests/conformance/more/functions/drawArrays.html"); }
-    public void test_conformance_more_functions_drawArraysOutOfBounds_html() throws Exception { doTest("tests/conformance/more/functions/drawArraysOutOfBounds.html"); }
-    public void test_conformance_more_functions_drawElements_html() throws Exception { doTest("tests/conformance/more/functions/drawElements.html"); }
-    public void test_conformance_more_functions_drawElementsBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/drawElementsBadArgs.html"); }
-    public void test_conformance_more_functions_isTests_html() throws Exception { doTest("tests/conformance/more/functions/isTests.html"); }
-    public void test_conformance_more_functions_readPixels_html() throws Exception { doTest("tests/conformance/more/functions/readPixels.html"); }
-    public void test_conformance_more_functions_readPixelsBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/readPixelsBadArgs.html"); }
-    public void test_conformance_more_functions_texImage2D_html() throws Exception { doTest("tests/conformance/more/functions/texImage2D.html"); }
-    public void test_conformance_more_functions_texImage2DBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/texImage2DBadArgs.html"); }
-    public void test_conformance_more_functions_texImage2DHTML_html() throws Exception { doTest("tests/conformance/more/functions/texImage2DHTML.html"); }
-    public void test_conformance_more_functions_texImage2DHTMLBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/texImage2DHTMLBadArgs.html"); }
-    public void test_conformance_more_functions_texSubImage2D_html() throws Exception { doTest("tests/conformance/more/functions/texSubImage2D.html"); }
-    public void test_conformance_more_functions_texSubImage2DBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/texSubImage2DBadArgs.html"); }
-    public void test_conformance_more_functions_texSubImage2DHTML_html() throws Exception { doTest("tests/conformance/more/functions/texSubImage2DHTML.html"); }
-    public void test_conformance_more_functions_texSubImage2DHTMLBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/texSubImage2DHTMLBadArgs.html"); }
-    public void test_conformance_more_functions_uniformMatrix_html() throws Exception { doTest("tests/conformance/more/functions/uniformMatrix.html"); }
-    public void test_conformance_more_functions_uniformMatrixBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/uniformMatrixBadArgs.html"); }
-    public void test_conformance_more_functions_uniformf_html() throws Exception { doTest("tests/conformance/more/functions/uniformf.html"); }
-    public void test_conformance_more_functions_uniformfArrayLen1_html() throws Exception { doTest("tests/conformance/more/functions/uniformfArrayLen1.html"); }
-    public void test_conformance_more_functions_uniformfBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/uniformfBadArgs.html"); }
-    public void test_conformance_more_functions_uniformi_html() throws Exception { doTest("tests/conformance/more/functions/uniformi.html"); }
-    public void test_conformance_more_functions_uniformiBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/uniformiBadArgs.html"); }
-    public void test_conformance_more_functions_vertexAttrib_html() throws Exception { doTest("tests/conformance/more/functions/vertexAttrib.html"); }
-    public void test_conformance_more_functions_vertexAttribBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/vertexAttribBadArgs.html"); }
-    public void test_conformance_more_functions_vertexAttribPointer_html() throws Exception { doTest("tests/conformance/more/functions/vertexAttribPointer.html"); }
-    public void test_conformance_more_functions_vertexAttribPointerBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/vertexAttribPointerBadArgs.html"); }
-    public void test_conformance_more_glsl_arrayOutOfBounds_html() throws Exception { doTest("tests/conformance/more/glsl/arrayOutOfBounds.html"); }
-    public void test_conformance_more_glsl_uniformOutOfBounds_html() throws Exception { doTest("tests/conformance/more/glsl/uniformOutOfBounds.html"); }
-    public void test_conformance_programs_get_active_test_html() throws Exception { doTest("tests/conformance/programs/get-active-test.html"); }
-    public void test_conformance_programs_gl_bind_attrib_location_test_html() throws Exception { doTest("tests/conformance/programs/gl-bind-attrib-location-test.html"); }
-    public void test_conformance_programs_gl_get_active_attribute_html() throws Exception { doTest("tests/conformance/programs/gl-get-active-attribute.html"); }
-    public void test_conformance_programs_gl_get_active_uniform_html() throws Exception { doTest("tests/conformance/programs/gl-get-active-uniform.html"); }
-    public void test_conformance_programs_gl_getshadersource_html() throws Exception { doTest("tests/conformance/programs/gl-getshadersource.html"); }
-    public void test_conformance_programs_gl_shader_test_html() throws Exception { doTest("tests/conformance/programs/gl-shader-test.html"); }
-    public void test_conformance_programs_invalid_UTF_16_html() throws Exception { doTest("tests/conformance/programs/invalid-UTF-16.html"); }
-    public void test_conformance_programs_program_test_html() throws Exception { doTest("tests/conformance/programs/program-test.html"); }
-    public void test_conformance_reading_read_pixels_pack_alignment_html() throws Exception { doTest("tests/conformance/reading/read-pixels-pack-alignment.html"); }
-    public void test_conformance_reading_read_pixels_test_html() throws Exception { doTest("tests/conformance/reading/read-pixels-test.html"); }
-    public void test_conformance_renderbuffers_framebuffer_object_attachment_html() throws Exception { doTest("tests/conformance/renderbuffers/framebuffer-object-attachment.html"); }
-    public void test_conformance_renderbuffers_framebuffer_test_html() throws Exception { doTest("tests/conformance/renderbuffers/framebuffer-test.html"); }
-    public void test_conformance_renderbuffers_renderbuffer_initialization_html() throws Exception { doTest("tests/conformance/renderbuffers/renderbuffer-initialization.html"); }
-    public void test_conformance_rendering_draw_arrays_out_of_bounds_html() throws Exception { doTest("tests/conformance/rendering/draw-arrays-out-of-bounds.html"); }
-    public void test_conformance_rendering_draw_elements_out_of_bounds_html() throws Exception { doTest("tests/conformance/rendering/draw-elements-out-of-bounds.html"); }
-    public void test_conformance_rendering_gl_clear_html() throws Exception { doTest("tests/conformance/rendering/gl-clear.html"); }
-    public void test_conformance_rendering_gl_drawelements_html() throws Exception { doTest("tests/conformance/rendering/gl-drawelements.html"); }
-    public void test_conformance_rendering_gl_scissor_test_html() throws Exception { doTest("tests/conformance/rendering/gl-scissor-test.html"); }
-    public void test_conformance_rendering_line_loop_tri_fan_html() throws Exception { doTest("tests/conformance/rendering/line-loop-tri-fan.html"); }
-    public void test_conformance_rendering_more_than_65536_indices_html() throws Exception { doTest("tests/conformance/rendering/more-than-65536-indices.html"); }
-    public void test_conformance_rendering_multisample_corruption_html() throws Exception { doTest("tests/conformance/rendering/multisample-corruption.html"); }
-    public void test_conformance_rendering_point_size_html() throws Exception { doTest("tests/conformance/rendering/point-size.html"); }
-    public void test_conformance_rendering_triangle_html() throws Exception { doTest("tests/conformance/rendering/triangle.html"); }
-    public void test_conformance_state_gl_enable_enum_test_html() throws Exception { doTest("tests/conformance/state/gl-enable-enum-test.html"); }
-    public void test_conformance_state_gl_enum_tests_html() throws Exception { doTest("tests/conformance/state/gl-enum-tests.html"); }
-    public void test_conformance_state_gl_get_calls_html() throws Exception { doTest("tests/conformance/state/gl-get-calls.html"); }
-    public void test_conformance_state_gl_geterror_html() throws Exception { doTest("tests/conformance/state/gl-geterror.html"); }
-    public void test_conformance_state_gl_getstring_html() throws Exception { doTest("tests/conformance/state/gl-getstring.html"); }
-    public void test_conformance_state_gl_object_get_calls_html() throws Exception { doTest("tests/conformance/state/gl-object-get-calls.html"); }
-    public void test_conformance_textures_compressed_tex_image_html() throws Exception { doTest("tests/conformance/textures/compressed-tex-image.html"); }
-    public void test_conformance_textures_copy_tex_image_and_sub_image_2d_html() throws Exception { doTest("tests/conformance/textures/copy-tex-image-and-sub-image-2d.html"); }
-    public void test_conformance_textures_gl_pixelstorei_html() throws Exception { doTest("tests/conformance/textures/gl-pixelstorei.html"); }
-    public void test_conformance_textures_gl_teximage_html() throws Exception { doTest("tests/conformance/textures/gl-teximage.html"); }
-    public void test_conformance_textures_origin_clean_conformance_html() throws Exception { doTest("tests/conformance/textures/origin-clean-conformance.html"); }
-    public void test_conformance_textures_tex_image_and_sub_image_2d_with_array_buffer_view_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-array-buffer-view.html"); }
-    public void test_conformance_textures_tex_image_and_sub_image_2d_with_canvas_rgb565_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-canvas-rgb565.html"); }
-    public void test_conformance_textures_tex_image_and_sub_image_2d_with_canvas_rgba4444_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-canvas-rgba4444.html"); }
-    public void test_conformance_textures_tex_image_and_sub_image_2d_with_canvas_rgba5551_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-canvas-rgba5551.html"); }
-    public void test_conformance_textures_tex_image_and_sub_image_2d_with_canvas_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-canvas.html"); }
-    public void test_conformance_textures_tex_image_and_sub_image_2d_with_image_data_rgb565_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-image-data-rgb565.html"); }
-    public void test_conformance_textures_tex_image_and_sub_image_2d_with_image_data_rgba4444_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-image-data-rgba4444.html"); }
-    public void test_conformance_textures_tex_image_and_sub_image_2d_with_image_data_rgba5551_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-image-data-rgba5551.html"); }
-    public void test_conformance_textures_tex_image_and_sub_image_2d_with_image_data_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-image-data.html"); }
-    public void test_conformance_textures_tex_image_and_sub_image_2d_with_image_rgb565_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-image-rgb565.html"); }
-    public void test_conformance_textures_tex_image_and_sub_image_2d_with_image_rgba4444_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-image-rgba4444.html"); }
-    public void test_conformance_textures_tex_image_and_sub_image_2d_with_image_rgba5551_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-image-rgba5551.html"); }
-    public void test_conformance_textures_tex_image_and_sub_image_2d_with_image_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-image.html"); }
-    public void test_conformance_textures_tex_image_and_sub_image_2d_with_video_rgb565_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-video-rgb565.html"); }
-    public void test_conformance_textures_tex_image_and_sub_image_2d_with_video_rgba4444_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-video-rgba4444.html"); }
-    public void test_conformance_textures_tex_image_and_sub_image_2d_with_video_rgba5551_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-video-rgba5551.html"); }
-    public void test_conformance_textures_tex_image_and_sub_image_2d_with_video_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-video.html"); }
-    public void test_conformance_textures_tex_image_and_uniform_binding_bugs_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-uniform-binding-bugs.html"); }
-    public void test_conformance_textures_tex_image_with_format_and_type_html() throws Exception { doTest("tests/conformance/textures/tex-image-with-format-and-type.html"); }
-    public void test_conformance_textures_tex_image_with_invalid_data_html() throws Exception { doTest("tests/conformance/textures/tex-image-with-invalid-data.html"); }
-    public void test_conformance_textures_tex_input_validation_html() throws Exception { doTest("tests/conformance/textures/tex-input-validation.html"); }
-    public void test_conformance_textures_tex_sub_image_2d_bad_args_html() throws Exception { doTest("tests/conformance/textures/tex-sub-image-2d-bad-args.html"); }
-    public void test_conformance_textures_tex_sub_image_2d_html() throws Exception { doTest("tests/conformance/textures/tex-sub-image-2d.html"); }
-    public void test_conformance_textures_texparameter_test_html() throws Exception { doTest("tests/conformance/textures/texparameter-test.html"); }
-    public void test_conformance_textures_texture_active_bind_2_html() throws Exception { doTest("tests/conformance/textures/texture-active-bind-2.html"); }
-    public void test_conformance_textures_texture_active_bind_html() throws Exception { doTest("tests/conformance/textures/texture-active-bind.html"); }
-    public void test_conformance_textures_texture_complete_html() throws Exception { doTest("tests/conformance/textures/texture-complete.html"); }
-    public void test_conformance_textures_texture_mips_html() throws Exception { doTest("tests/conformance/textures/texture-mips.html"); }
-    public void test_conformance_textures_texture_npot_video_html() throws Exception { doTest("tests/conformance/textures/texture-npot-video.html"); }
-    public void test_conformance_textures_texture_npot_html() throws Exception { doTest("tests/conformance/textures/texture-npot.html"); }
-    public void test_conformance_textures_texture_size_cube_maps_html() throws Exception { doTest("tests/conformance/textures/texture-size-cube-maps.html"); }
-    public void test_conformance_textures_texture_size_html() throws Exception { doTest("tests/conformance/textures/texture-size.html"); }
-    public void test_conformance_textures_texture_transparent_pixels_initialized_html() throws Exception { doTest("tests/conformance/textures/texture-transparent-pixels-initialized.html"); }
-    public void test_conformance_typedarrays_array_buffer_crash_html() throws Exception { doTest("tests/conformance/typedarrays/array-buffer-crash.html"); }
-    public void test_conformance_typedarrays_array_buffer_view_crash_html() throws Exception { doTest("tests/conformance/typedarrays/array-buffer-view-crash.html"); }
-    public void test_conformance_typedarrays_array_unit_tests_html() throws Exception { doTest("tests/conformance/typedarrays/array-unit-tests.html"); }
-    public void test_conformance_typedarrays_data_view_crash_html() throws Exception { doTest("tests/conformance/typedarrays/data-view-crash.html"); }
-    public void test_conformance_typedarrays_data_view_test_html() throws Exception { doTest("tests/conformance/typedarrays/data-view-test.html"); }
-    public void test_conformance_uniforms_gl_uniform_arrays_html() throws Exception { doTest("tests/conformance/uniforms/gl-uniform-arrays.html"); }
-    public void test_conformance_uniforms_gl_uniform_bool_html() throws Exception { doTest("tests/conformance/uniforms/gl-uniform-bool.html"); }
-    public void test_conformance_uniforms_gl_uniformmatrix4fv_html() throws Exception { doTest("tests/conformance/uniforms/gl-uniformmatrix4fv.html"); }
-    public void test_conformance_uniforms_gl_unknown_uniform_html() throws Exception { doTest("tests/conformance/uniforms/gl-unknown-uniform.html"); }
-    public void test_conformance_uniforms_null_uniform_location_html() throws Exception { doTest("tests/conformance/uniforms/null-uniform-location.html"); }
-    public void test_conformance_uniforms_uniform_location_html() throws Exception { doTest("tests/conformance/uniforms/uniform-location.html"); }
-    public void test_conformance_uniforms_uniform_samplers_test_html() throws Exception { doTest("tests/conformance/uniforms/uniform-samplers-test.html"); }
-}
diff --git a/tests/webgl/src/android/webgl/cts/ZipUtil.java b/tests/webgl/src/android/webgl/cts/ZipUtil.java
deleted file mode 100644
index 4b28e63..0000000
--- a/tests/webgl/src/android/webgl/cts/ZipUtil.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * 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.
- * 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.webgl.cts;
-
-import android.util.Log;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.lang.String;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-
-
-/**
- * Some boilerplate code to unzip files.
- */
-public class ZipUtil {
-    private final static String TAG = "ZipUtil";
-
-    /**
-     * Stream to a file.
-     */
-    public static void streamToPath(InputStream is,
-                                  File directory,
-                                  String name) throws Exception {
-        File file = new File(directory, name);
-        streamToPath(is, file);
-    }
-
-    public static void streamToPath(InputStream is,
-                                  File file) throws Exception {
-        Log.i(TAG, "Streaming to path " + file.getPath());
-        OutputStream os = null;
-        os = new FileOutputStream(file);
-        int count = -1;
-        byte[] buffer = new byte[10 * 1024];
-        while ((count = is.read(buffer)) != -1) {
-            os.write(buffer, 0, count);
-        }
-        os.close();
-    }
-
-    /**
-     * Unzip to a directory.
-     */
-    public static void unzipToPath(InputStream is,
-                                   File filePath) throws Exception {
-        ZipInputStream zis = new ZipInputStream(is);
-        unzipToPath(zis, filePath.getPath());
-    }
-
-    public static void unzipToPath(ZipInputStream zis,
-                                   String path) throws Exception {
-        Log.i(TAG, "Unzipping to path " + path);
-        byte[] buffer = new byte[10 * 1024];
-        ZipEntry entry;
-        while ((entry = zis.getNextEntry()) != null) {
-            File entryFile = new File(path, entry.getName());
-            if (entry.isDirectory()) {
-                if (!entryFile.exists()) {
-                   entryFile.mkdirs();
-                }
-                continue;
-            }
-            if (entryFile.getParentFile() != null &&
-                    !entryFile.getParentFile().exists()) {
-                entryFile.getParentFile().mkdirs();
-            }
-            if (!entryFile.exists()) {
-                entryFile.createNewFile();
-                entryFile.setReadable(true);
-                entryFile.setExecutable(true);
-            }
-            streamToPath(zis, entryFile);
-        }
-        zis.close();
-    }
-
-    /**
-     * Cleanup a directory.
-     */
-    static public boolean deleteDirectory(String directoryPath) {
-        File path = new File(directoryPath);
-        return deleteDirectory(path);
-    }
-
-    static public boolean deleteDirectory(File path) {
-        if (path.exists()) {
-            File[] files = path.listFiles();
-            for(int i = 0; i < files.length; i++) {
-                if(files[i].isDirectory()) {
-                    deleteDirectory(files[i]);
-                } else {
-                    files[i].delete();
-                }
-            }
-            return path.delete();
-        }
-        return false;
-    }
-}
diff --git a/tools/selinux/SELinuxNeverallowTestFrame.py b/tools/selinux/SELinuxNeverallowTestFrame.py
index 5eba5bb..45900de 100644
--- a/tools/selinux/SELinuxNeverallowTestFrame.py
+++ b/tools/selinux/SELinuxNeverallowTestFrame.py
@@ -72,8 +72,7 @@
         /* obtain sepolicy file from running device */
         devicePolicyFile = File.createTempFile("sepolicy", ".tmp");
         devicePolicyFile.deleteOnExit();
-        mDevice.executeAdbCommand("pull", "/sys/fs/selinux/policy",
-                devicePolicyFile.getAbsolutePath());
+        mDevice.pullFile("/sys/fs/selinux/policy", devicePolicyFile);
     }
 """
 src_body = ""
diff --git a/tools/tradefed-host/Android.mk b/tools/tradefed-host/Android.mk
index bd28575..1f73e95 100644
--- a/tools/tradefed-host/Android.mk
+++ b/tools/tradefed-host/Android.mk
@@ -27,6 +27,8 @@
 LOCAL_JAVA_LIBRARIES := tradefed-prebuilt hosttestlib
 LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceinfolib
 
+LOCAL_JAR_MANIFEST := MANIFEST.mf
+
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 
 include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/tools/tradefed-host/MANIFEST.mf b/tools/tradefed-host/MANIFEST.mf
new file mode 100644
index 0000000..5528c06
--- /dev/null
+++ b/tools/tradefed-host/MANIFEST.mf
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: com.android.cts.tradefed.testtype
+Implementation-Version: %BUILD_NUMBER%
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/command/CtsConsole.java b/tools/tradefed-host/src/com/android/cts/tradefed/command/CtsConsole.java
index ca4e050..250a121 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/command/CtsConsole.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/command/CtsConsole.java
@@ -56,7 +56,9 @@
 
     @Override
     public void run() {
-        printLine(String.format("Android CTS %s", CtsBuildProvider.CTS_BUILD_VERSION));
+        printLine(String.format("Android CTS %s build:%s",
+                CtsBuildProvider.CTS_BUILD_VERSION,
+                Package.getPackage("com.android.cts.tradefed.command").getImplementationVersion()));
         super.run();
     }
 
diff --git a/tools/utils/buildCts.py b/tools/utils/buildCts.py
index 79a3354..6b74608 100755
--- a/tools/utils/buildCts.py
+++ b/tools/utils/buildCts.py
@@ -295,7 +295,6 @@
 
     plan = tools.TestPlan(packages)
     plan.Exclude('.*')
-    plan.Include(r'android\.webgl')
     self.__WritePlan(plan, 'CTS-webview')
 
 
@@ -409,8 +408,7 @@
       'android.signature' : [],
       'android.tv' : [],
       'android.uiautomation' : [],
-      'android.uirendering' : [],
-      'android.webgl' : []}
+      'android.uirendering' : []}
 
 def BuildListForReleaseBuildTest():
   """ Construct a defaultdict that maps package name to a list of tests