Merge "Camera: Tonemap CTS update for HAL3.3" 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/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_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/CtsVerifier/Android.mk b/apps/CtsVerifier/Android.mk
index 37f1f90..2800fd1 100644
--- a/apps/CtsVerifier/Android.mk
+++ b/apps/CtsVerifier/Android.mk
@@ -26,8 +26,10 @@
 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 \
+                               cts-verifier-facilities \
                                ctstestrunner \
                                apache-commons-math \
                                androidplot \
@@ -113,3 +115,18 @@
 endif
 
 include $(call all-makefiles-under,$(LOCAL_PATH))
+
+# Build CTS verifier facilities as a libary.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE := cts-verifier-facilities
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-Iaidl-files-under, src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := compatibility-common-util-devicesidelib_v2
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
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 a9fd074..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">
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/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..24ba691 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
@@ -45,7 +45,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,14 +91,6 @@
         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 testCrossProfileIntentFilters() throws Exception {
         if (!mHasFeature) {
             return;
@@ -247,39 +239,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/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/CameraTestUtils.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
index f4eeba9..d39ff1f 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -560,8 +560,12 @@
             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 configureReprocessableCameraSession(CameraDevice camera,
@@ -571,8 +575,11 @@
         BlockingSessionCallback sessionListener = new BlockingSessionCallback(listener);
         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) {
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 db72e70..8ae01d0 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;
@@ -82,6 +83,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 +100,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 +120,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 +395,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;
             }
@@ -819,8 +846,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);
@@ -844,8 +877,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;
@@ -908,7 +947,7 @@
         } else {
             // TODO: need implement MediaCodec path.
         }
-        if (mRecordingSurface != null) {
+        if (mPersistentSurface == null && mRecordingSurface != null) {
             mRecordingSurface.release();
             mRecordingSurface = null;
         }
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/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/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/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/MediaPlayerTest.java b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
index 1fcb8b9..18cd353 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
@@ -26,11 +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;
@@ -69,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();
@@ -841,6 +845,10 @@
 
         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);
@@ -849,6 +857,10 @@
             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(
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 dbbda32..6f9e2a2 100644
--- a/tests/tests/media/src/android/media/cts/MediaSyncTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaSyncTest.java
@@ -32,6 +32,7 @@
 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;
@@ -61,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;
@@ -186,6 +188,8 @@
         final float rate = (float)TEST_MAX_SPEED;
         try {
             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");
         }
@@ -237,7 +241,7 @@
             }
         }, null);
 
-        mMediaSync.setPlaybackParams(PAUSED_RATE);
+        mMediaSync.setPlaybackParams(NORMAL_RATE);
 
         synchronized (condition) {
             mDecoderAudio.start();
@@ -442,6 +446,10 @@
             mHasAudio = true;
         }
 
+        SyncParams sync = new SyncParams().allowDefaults();
+        mMediaSync.setSyncParams(sync);
+        sync = mMediaSync.getSyncParams();
+
         mMediaSync.setPlaybackParams(new PlaybackParams().setSpeed(playbackRate));
 
         synchronized (conditionFirstAudioBuffer) {
@@ -492,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/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/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/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/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_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/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 8132b9e..10535b0 100644
--- a/tests/tests/tv/src/android/media/tv/cts/TvInputServiceTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/TvInputServiceTest.java
@@ -29,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;
 
@@ -67,7 +73,7 @@
         private int mTrackChangedCount;
         private int mContentAllowedCount;
         private int mContentBlockedCount;
-        private int mTimeShiftStatusChanged;
+        private int mTimeShiftStatusChangedCount;
 
         @Override
         public void onChannelRetuned(String inputId, Uri channelUri) {
@@ -106,7 +112,18 @@
 
         @Override
         public void onTimeShiftStatusChanged(String inputId, int status) {
-            mTimeShiftStatusChanged++;
+            mTimeShiftStatusChangedCount++;
+        }
+
+        public void resetCounts() {
+            mChannelRetunedCount = 0;
+            mVideoAvailableCount = 0;
+            mVideoUnavailableCount = 0;
+            mTrackSelectedCount = 0;
+            mTrackChangedCount = 0;
+            mContentAllowedCount = 0;
+            mContentBlockedCount = 0;
+            mTimeShiftStatusChangedCount = 0;
         }
     }
 
@@ -114,13 +131,20 @@
         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() {
@@ -157,12 +181,18 @@
         verifyCommandSetStreamVolume();
         verifyCommandSetCaptionEnabled();
         verifyCommandSelectTrack();
-        verifyCommandDispatchKeyEvent();
+        verifyCommandDispatchKeyDown();
+        verifyCommandDispatchKeyMultiple();
+        verifyCommandDispatchKeyUp();
+        verifyCommandDispatchTouchEvent();
+        verifyCommandDispatchTrackballEvent();
+        verifyCommandDispatchGenericMotionEvent();
         verifyCommandTimeShiftPause();
         verifyCommandTimeShiftResume();
         verifyCommandTimeShiftSeekTo();
         verifyCommandTimeShiftSetPlaybackParams();
         verifyCommandSetTimeShiftPositionCallback();
+        verifyCommandOverlayViewSizeChanged();
         verifyCallbackChannelRetuned();
         verifyCallbackVideoAvailable();
         verifyCallbackVideoUnavailable();
@@ -171,6 +201,7 @@
         verifyCallbackContentAllowed();
         verifyCallbackContentBlocked();
         verifyCallbackTimeShiftStatusChanged();
+        verifyCallbackLayoutSurface();
 
         runTestOnUiThread(new Runnable() {
             @Override
@@ -189,12 +220,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) {
@@ -207,6 +239,7 @@
     }
 
     public void verifyCommandSetCaptionEnabled() {
+        resetCounts();
         mTvView.setCaptionEnabled(true);
         mInstrumentation.waitForIdleSync();
         new PollingCheck(TIME_OUT) {
@@ -219,18 +252,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) {
@@ -242,43 +278,123 @@
         }.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.mTimeShiftPause > 0;
+                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.mTimeShiftResume > 0;
+                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.mTimeShiftSeekTo > 0;
+                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();
@@ -286,12 +402,13 @@
             @Override
             protected boolean check() {
                 CountingSession session = CountingTvInputService.sSession;
-                return session != null && session.mTimeShiftSetPlaybackParams > 0;
+                return session != null && session.mTimeShiftSetPlaybackParamsCount > 0;
             }
         }.run();
     }
 
     public void verifyCommandSetTimeShiftPositionCallback() {
+        resetCounts();
         mTvView.setTimeShiftPositionCallback(mTimeShiftPositionCallback);
         mInstrumentation.waitForIdleSync();
         new PollingCheck(TIME_OUT) {
@@ -303,7 +420,25 @@
         }.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);
@@ -317,6 +452,7 @@
     }
 
     public void verifyCallbackVideoAvailable() {
+        resetCounts();
         CountingSession session = CountingTvInputService.sSession;
         assertNotNull(session);
         session.notifyVideoAvailable();
@@ -329,6 +465,7 @@
     }
 
     public void verifyCallbackVideoUnavailable() {
+        resetCounts();
         CountingSession session = CountingTvInputService.sSession;
         assertNotNull(session);
         session.notifyVideoUnavailable(TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING);
@@ -341,6 +478,7 @@
     }
 
     public void verifyCallbackTracksChanged() {
+        resetCounts();
         CountingSession session = CountingTvInputService.sSession;
         assertNotNull(session);
         ArrayList<TvTrackInfo> tracks = new ArrayList<>();
@@ -355,6 +493,7 @@
     }
 
     public void verifyCallbackTrackSelected() {
+        resetCounts();
         CountingSession session = CountingTvInputService.sSession;
         assertNotNull(session);
         session.notifyTrackSelected(mDummyTrack.getType(), mDummyTrack.getId());
@@ -367,6 +506,7 @@
     }
 
     public void verifyCallbackContentAllowed() {
+        resetCounts();
         CountingSession session = CountingTvInputService.sSession;
         assertNotNull(session);
         session.notifyContentAllowed();
@@ -379,6 +519,7 @@
     }
 
     public void verifyCallbackContentBlocked() {
+        resetCounts();
         CountingSession session = CountingTvInputService.sSession;
         assertNotNull(session);
         TvContentRating rating = TvContentRating.createRating("android.media.tv", "US_TVPG",
@@ -393,24 +534,58 @@
     }
 
     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.mTimeShiftStatusChanged > 0;
+                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;
         }
 
@@ -419,18 +594,48 @@
             public volatile int mSetStreamVolumeCount;
             public volatile int mSetCaptionEnabledCount;
             public volatile int mSelectTrackCount;
+            public volatile int mCreateOverlayView;
             public volatile int mKeyDownCount;
-            public volatile int mTimeShiftPause;
-            public volatile int mTimeShiftResume;
-            public volatile int mTimeShiftSeekTo;
-            public volatile int mTimeShiftSetPlaybackParams;
-            public volatile long mTimeShiftGetCurrentPosition;
-            public volatile long mTimeShiftGetStartPosition;
+            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() {
             }
@@ -463,39 +668,86 @@
             }
 
             @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() {
-                mTimeShiftPause++;
+                mTimeShiftPauseCount++;
             }
 
             @Override
             public void onTimeShiftResume() {
-                mTimeShiftResume++;
+                mTimeShiftResumeCount++;
             }
 
             @Override
             public void onTimeShiftSeekTo(long timeMs) {
-                mTimeShiftSeekTo++;
+                mTimeShiftSeekToCount++;
             }
 
             @Override
             public void onTimeShiftSetPlaybackParams(PlaybackParams param) {
-                mTimeShiftSetPlaybackParams++;
+                mTimeShiftSetPlaybackParamsCount++;
             }
 
             @Override
             public long onTimeShiftGetCurrentPosition() {
-                return ++mTimeShiftGetCurrentPosition;
+                return ++mTimeShiftGetCurrentPositionCount;
             }
 
             @Override
             public long onTimeShiftGetStartPosition() {
-                return ++mTimeShiftGetStartPosition;
+                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..fca3d5b 100644
--- a/tests/tests/tv/src/android/media/tv/cts/TvViewTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/TvViewTest.java
@@ -258,6 +258,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 +269,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 +284,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,13 +296,16 @@
         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() {
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/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