Merge "Add Wifi status to help diagnose testClearKeyPlaybackCenc failures." into nyc-dev
diff --git a/OldCtsTestCaseList.mk b/OldCtsTestCaseList.mk
index 1c6bd7f..d2eb85b 100644
--- a/OldCtsTestCaseList.mk
+++ b/OldCtsTestCaseList.mk
@@ -155,12 +155,12 @@
     CtsAppTestCases \
     CtsAppWidgetTestCases \
     CtsAssistTestCases \
-    CtsAutomotiveTestCases \
     CtsBluetoothTestCases \
     CtsBrowserTestCases \
     CtsCalendarcommon2TestCases \
     CtsCallLogTestCases \
     CtsCameraTestCases \
+    CtsCarTestCases \
     CtsContentTestCases \
     CtsDatabaseTestCases \
     CtsDisplayTestCases \
@@ -196,6 +196,7 @@
     CtsNetTestCasesLegacyApi22 \
     CtsNetTestCasesLegacyPermission22 \
     CtsNetSecConfigAttributeTestCases \
+    CtsNetSecConfigCleartextTrafficTestCases \
     CtsNetSecConfigBasicDebugDisabledTestCases \
     CtsNetSecConfigBasicDebugEnabledTestCases \
     CtsNetSecConfigBasicDomainConfigTestCases \
diff --git a/apps/CameraITS/pymodules/its/device.py b/apps/CameraITS/pymodules/its/device.py
index 741baee..c669540 100644
--- a/apps/CameraITS/pymodules/its/device.py
+++ b/apps/CameraITS/pymodules/its/device.py
@@ -597,7 +597,12 @@
                        for c in cmd["outputSurfaces"]]
             formats = [s if s != "jpg" else "jpeg" for s in formats]
         else:
+            max_yuv_size = its.objects.get_available_output_sizes(
+                    "yuv", self.props)[0]
             formats = ['yuv']
+            cmd["outputSurfaces"] = [{"format": "yuv",
+                                      "width" : max_yuv_size[0],
+                                      "height": max_yuv_size[1]}]
         ncap = len(cmd["captureRequests"])
         nsurf = 1 if out_surfaces is None else len(cmd["outputSurfaces"])
         # Only allow yuv output to multiple targets
diff --git a/apps/CameraITS/tests/scene1/test_post_raw_sensitivity_boost.py b/apps/CameraITS/tests/scene1/test_post_raw_sensitivity_boost.py
index b0689c1..682c04a 100644
--- a/apps/CameraITS/tests/scene1/test_post_raw_sensitivity_boost.py
+++ b/apps/CameraITS/tests/scene1/test_post_raw_sensitivity_boost.py
@@ -14,8 +14,9 @@
 
 import its.device
 import its.caps
-import its.objects
 import its.image
+import its.objects
+import its.target
 import os.path
 import pylab
 import matplotlib
@@ -47,23 +48,24 @@
             raw_format = 'raw10'
         elif its.caps.raw12(props):
             raw_format = 'raw12'
-        else # should not reach here
+        else: # should not reach here
             raise its.error.Error('Cannot find available RAW output format')
 
         out_surfaces = [{"format": raw_format},
                         {"format": "yuv", "width": w, "height": h}]
 
         sens_min, sens_max = props['android.sensor.info.sensitivityRange']
-        sens_boost_min, sens_boost_max =
+        sens_boost_min, sens_boost_max = \
                 props['android.control.postRawSensitivityBoostRange']
 
-        e_targer, s_target =
+
+        e_target, s_target = \
                 its.target.get_target_exposure_combos(cam)["midSensitivity"]
 
         reqs = []
         settings = []
         s_boost = sens_boost_min
-        while s_boost <= sens_boost_min:
+        while s_boost <= sens_boost_max:
             s_raw = int(round(s_target * 100.0 / s_boost))
             if s_raw < sens_min or s_raw > sens_max:
                 continue
@@ -77,9 +79,15 @@
 
         raw_rgb_means = []
         yuv_rgb_means = []
-        for i,cap in enumerate(caps):
+        raw_caps, yuv_caps = caps
+        if not isinstance(raw_caps, list):
+            raw_caps = [raw_caps]
+        if not isinstance(yuv_caps, list):
+            yuv_caps = [yuv_caps]
+        for i in xrange(len(reqs)):
             (s, s_boost) = settings[i]
-            raw_cap, yuv_cap = cap
+            raw_cap = raw_caps[i]
+            yuv_cap = yuv_caps[i]
             raw_rgb = its.image.convert_capture_to_rgb_image(raw_cap, props=props)
             yuv_rgb = its.image.convert_capture_to_rgb_image(yuv_cap)
             raw_tile = its.image.get_image_patch(raw_rgb, 0.45,0.45,0.1,0.1)
@@ -90,7 +98,7 @@
                     "%s_raw_s=%04d_boost=%04d.jpg" % (NAME,s,s_boost))
             its.image.write_image(yuv_tile,
                     "%s_yuv_s=%04d_boost=%04d.jpg" % (NAME,s,s_boost))
-            print "s=%d, s_boost=%d: raw_means %s, yuv_means %d"%(
+            print "s=%d, s_boost=%d: raw_means %s, yuv_means %s"%(
                     s,s_boost,raw_rgb_means[-1], yuv_rgb_means[-1])
 
         xs = range(len(reqs))
@@ -125,7 +133,7 @@
         yuv_thres_max = 1 + RATIO_THRESHOLD
         for rgb in range(3):
             vals = [val[rgb] for val in yuv_rgb_means]
-            mean = sum(vals) / len(vales)
+            mean = sum(vals) / len(vals)
             print "%s channel vals %s mean %f"%(rgb_str[rgb], vals, mean)
             for step in range(len(reqs)):
                 ratio = vals[step] / mean
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 13bc98e..ee98618 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -460,8 +460,7 @@
         </activity>
 
         <activity android:name=".net.ConnectivityScreenOffTestActivity"
-                android:label="@string/network_screen_off_test"
-                android:screenOrientation="portrait">
+                android:label="@string/network_screen_off_test">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
@@ -1521,6 +1520,10 @@
             </intent-filter>
         </activity-alias>
 
+        <activity android:name=".managedprovisioning.OrganizationInfoTestActivity"
+                android:label="@string/provisioning_byod_organization_info">
+        </activity>
+
         <activity android:name=".managedprovisioning.PolicyTransparencyTestListActivity"
                 android:label="@string/device_profile_owner_policy_transparency_test">
             <intent-filter>
@@ -1625,6 +1628,7 @@
                 <action android:name="com.android.cts.verifier.managedprovisioning.CLEAR_NOTIFICATION" />
                 <action android:name="com.android.cts.verifier.managedprovisioning.TEST_SELECT_WORK_CHALLENGE" />
                 <action android:name="com.android.cts.verifier.managedprovisioning.TEST_CONFIRM_WORK_CREDENTIALS" />
+                <action android:name="com.android.cts.verifier.managedprovisioning.TEST_ORGANIZATION_INFO" />
                 <category android:name="android.intent.category.DEFAULT"></category>
             </intent-filter>
         </activity>
diff --git a/apps/CtsVerifier/jni/audio_loopback/Android.mk b/apps/CtsVerifier/jni/audio_loopback/Android.mk
index 3dfbc34..b302f44 100644
--- a/apps/CtsVerifier/jni/audio_loopback/Android.mk
+++ b/apps/CtsVerifier/jni/audio_loopback/Android.mk
@@ -23,6 +23,7 @@
 LOCAL_PRELINK_MODULE := false
 
 LOCAL_LDFLAGS := -Wl,--hash-style=sysv
-LOCAL_CFLAGS := -DSTDC_HEADERS
+LOCAL_CFLAGS := -DSTDC_HEADERS \
+    -Werror -Wall
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/apps/CtsVerifier/jni/audio_loopback/sles.cpp b/apps/CtsVerifier/jni/audio_loopback/sles.cpp
index 7859d35..b0b683b 100644
--- a/apps/CtsVerifier/jni/audio_loopback/sles.cpp
+++ b/apps/CtsVerifier/jni/audio_loopback/sles.cpp
@@ -40,14 +40,14 @@
     if (ppSles != NULL) {
         sles_data * pSles = (sles_data*) calloc(1, sizeof (sles_data));
 
-        SLES_PRINTF("malloc %d bytes at %p",sizeof(sles_data), pSles);
+        SLES_PRINTF("malloc %zu bytes at %p", sizeof(sles_data), pSles);
         *ppSles = pSles;
         if (pSles != NULL)
         {
             SLES_PRINTF("creating server. Sampling rate =%d, frame count = %d",samplingRate,
                     frameCount);
             status = slesCreateServer(pSles, samplingRate, frameCount, micSource);
-            SLES_PRINTF("slesCreateServer =%d",status);
+            SLES_PRINTF("slesCreateServer =%d", status);
         }
     }
     return status;
@@ -260,6 +260,7 @@
     //        char **freeBuffers;
 
     // Buffer indices
+/*
     pSles->rxFront;    // oldest recording
     pSles->rxRear;     // next to be recorded
     pSles->txFront;    // oldest playing
@@ -268,9 +269,8 @@
     pSles->freeRear;   // next to be freed
 
     pSles->fifo; //(*)
+*/
     pSles->fifo2Buffer = NULL;
-    pSles->recorderBufferQueue;
-    pSles->playerBufferQueue;
 
     // compute total free buffers as -r plus -t
     pSles->freeBufCount = pSles->rxBufCount + pSles->txBufCount;
@@ -325,7 +325,6 @@
     SLresult result;
 
     // create engine
-    pSles->engineObject;
     result = slCreateEngine(&(pSles->engineObject), 0, NULL, 0, NULL, NULL);
     ASSERT_EQ(SL_RESULT_SUCCESS, result);
     result = (*(pSles->engineObject))->Realize(pSles->engineObject, SL_BOOLEAN_FALSE);
@@ -336,7 +335,6 @@
     ASSERT_EQ(SL_RESULT_SUCCESS, result);
 
     // create output mix
-    pSles->outputmixObject;
     result = (*engineEngine)->CreateOutputMix(engineEngine, &(pSles->outputmixObject), 0, NULL,
             NULL);
     ASSERT_EQ(SL_RESULT_SUCCESS, result);
diff --git a/apps/CtsVerifier/res/layout/organization_info.xml b/apps/CtsVerifier/res/layout/organization_info.xml
new file mode 100644
index 0000000..320fb8c
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/organization_info.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/root_view"
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <TextView android:id="@+id/provisioning_byod_organization_info_instructions"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_weight="1"
+                android:text="@string/provisioning_byod_organization_info_instructions"/>
+
+        <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="horizontal">
+            <EditText android:id="@+id/organization_name_edit_text"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:hint="@string/provisioning_byod_organization_name_hint"
+                    android:gravity="top|start"
+                    android:windowSoftInputMode="adjustPan"
+                    android:padding="16dp"
+                    android:layout_weight="1"/>
+            <EditText android:id="@+id/organization_color_edit_text"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:hint="@string/provisioning_byod_organization_color_hint"
+                    android:gravity="top|start"
+                    android:digits="#0123456789abcdefABCDEF"
+                    android:inputType="textCapCharacters"
+                    android:windowSoftInputMode="adjustPan"
+                    android:padding="16dp"
+                    android:layout_weight="1" />
+        </LinearLayout>
+
+        <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="horizontal">
+            <Button android:id="@+id/organization_info_set_button"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:text="@string/provisioning_byod_set_organization_info_button_text"
+                    android:layout_weight="1"/>
+            <Button android:id="@+id/go_button"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:text="@string/go_button_text"
+                    android:layout_weight="1"/>
+        </LinearLayout>
+
+        <include layout="@layout/pass_fail_buttons" />
+
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index cbd7f6b..0dbb16f 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -1291,14 +1291,14 @@
     <string name="keychain_reset">Reset</string>
     <string name="keychain_skip">Skip</string>
     <string name="keychain_setup_desc">The first step sets up an internal KeyStore and generates credentials to use for the remainder of the test.\n\n
- Touch \'Next\' to begin.</string>
-    <string name="keychain_install_desc">Credentials generated. Touch \'Next\' to install them to the system keychain.\n\n
+ Tap \'Next\' to begin.</string>
+    <string name="keychain_install_desc">Credentials generated. Tap \'Next\' to install them to the system keychain.\n\n
 The container for the credentials will not be protected with a password; if prompted for one, leave that field blank.\n\n
 During installation you may be prompted for a name - accept the default suggestion.\n\n
 In the case that these credentials were already installed, you may skip this step.</string>
     <string name="keychain_https_desc">The last test involves setting up an HTTPS connection using credentials from the KeyChain.\n\n
 You should be prompted to select credentials; choose the ones you just installed in the previous step.</string>
-    <string name="keychain_reset_desc">Before marking this test as passed, touch \'Next\' to open security settings and reset the following items:\n
+    <string name="keychain_reset_desc">Before marking this test as passed, tap \'Next\' to open security settings and reset the following items:\n
  1. Clear device credentials.\n
  2. Change the lock screen type to \'None\'.</string>
 
@@ -1921,6 +1921,20 @@
         3. Check that the work notification has disappeared.\n
         4. Set work mode to on.\n
     </string>
+    <string name="provisioning_byod_organization_info">Organization Info</string>
+    <string name="provisioning_byod_organization_name_hint">Name</string>
+    <string name="provisioning_byod_organization_color_hint">#FF00FF</string>
+    <string name="provisioning_byod_set_organization_info_button_text">Set</string>
+    <string name="provisioning_byod_organization_info_instructions">
+    This test verifies that the Organization Info was set correctly.
+    You can only do this test after you have done "select work challenge" test.\n
+        1. Enter your organization name.\n
+        2. Enter a valid color code.\n
+        3. Press the Set button to set organization Info.\n
+        4. Press the Go button to open a dialog to confirm work credentials.\n
+        5. Verify that the background color of the resulting dialog is as set by you.\n
+        6. Verify that the header text has organization name as set by you.\n
+    </string>
 
     <!-- Strings for DeviceOwnerProvisioningTest -->
     <string name="provisioning_device_owner">Device Owner Provisioning</string>
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 e00d287..9b5df85 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
@@ -94,6 +94,7 @@
     private DialogTestListItem mConfirmWorkCredentials;
     private TestListItem mVpnTest;
     private TestListItem mDisallowAppsControlTest;
+    private TestListItem mOrganizationInfoTest;
     private TestListItem mPolicyTransparencyTest;
 
     public ByodFlowTestActivity() {
@@ -374,6 +375,12 @@
                 R.string.provisioning_byod_confirm_work_credentials_description,
                 new Intent(ByodHelperActivity.ACTION_TEST_CONFIRM_WORK_CREDENTIALS));
 
+        mOrganizationInfoTest = TestListItem.newTest(this,
+                R.string.provisioning_byod_organization_info,
+                OrganizationInfoTestActivity.class.getName(),
+                new Intent(this, OrganizationInfoTestActivity.class),
+                null);
+
         final Intent policyTransparencyTestIntent = new Intent(this,
                 PolicyTransparencyTestListActivity.class);
         policyTransparencyTestIntent.putExtra(
@@ -418,6 +425,7 @@
         adapter.add(mTurnOffWorkNotifications);
         adapter.add(mSelectWorkChallenge);
         adapter.add(mConfirmWorkCredentials);
+        adapter.add(mOrganizationInfoTest);
         adapter.add(mPolicyTransparencyTest);
 
         if (canResolveIntent(new Intent(Settings.ACTION_APPLICATION_SETTINGS))) {
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 cfb42fd..b9e6541 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
@@ -135,6 +135,9 @@
     public static final String ACTION_TEST_CONFIRM_WORK_CREDENTIALS =
             "com.android.cts.verifier.managedprovisioning.TEST_CONFIRM_WORK_CREDENTIALS";
 
+    public static final String ACTION_SET_ORGANIZATION_INFO =
+            "com.android.cts.verifier.managedprovisioning.TEST_ORGANIZATION_INFO";
+
     public static final int RESULT_FAILED = RESULT_FIRST_USER;
 
     private static final int REQUEST_INSTALL_PACKAGE = 2;
@@ -324,6 +327,16 @@
                     (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
             Intent launchIntent = keyguardManager.createConfirmDeviceCredentialIntent(null, null);
             startActivity(launchIntent);
+        } else if (ACTION_SET_ORGANIZATION_INFO.equals(action)) {
+            if(intent.hasExtra(OrganizationInfoTestActivity.EXTRA_ORGANIZATION_NAME)) {
+                final String organizationName = intent
+                        .getStringExtra(OrganizationInfoTestActivity.EXTRA_ORGANIZATION_NAME);
+                mDevicePolicyManager.setOrganizationName(mAdminReceiverComponent, organizationName);
+            }
+            final int organizationColor = intent.getIntExtra(
+                    OrganizationInfoTestActivity.EXTRA_ORGANIZATION_COLOR,
+                    mDevicePolicyManager.getOrganizationColor(mAdminReceiverComponent));
+            mDevicePolicyManager.setOrganizationColor(mAdminReceiverComponent, organizationColor);
         }
         // This activity has no UI and is only used to respond to CtsVerifier in the primary side.
         finish();
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 d7d9b71..e4250f0 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
@@ -102,6 +102,7 @@
             filter.addAction(VpnTestActivity.ACTION_VPN);
             filter.addAction(ByodHelperActivity.ACTION_TEST_SELECT_WORK_CHALLENGE);
             filter.addAction(ByodHelperActivity.ACTION_TEST_CONFIRM_WORK_CREDENTIALS);
+            filter.addAction(ByodHelperActivity.ACTION_SET_ORGANIZATION_INFO);
             filter.addAction(SetSupportMessageActivity.ACTION_SET_SUPPORT_MSG);
             filter.addAction(CommandReceiverActivity.ACTION_EXECUTE_COMMAND);
             dpm.addCrossProfileIntentFilter(getWho(context), filter,
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/OrganizationInfoTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/OrganizationInfoTestActivity.java
new file mode 100644
index 0000000..3fb7120
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/OrganizationInfoTestActivity.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.managedprovisioning;
+
+import android.content.Intent;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+/**
+ * Test class to verify Organization Info.
+ */
+public class OrganizationInfoTestActivity extends PassFailButtons.Activity
+        implements View.OnClickListener {
+
+    public static final String EXTRA_ORGANIZATION_NAME = "extra_organization_name";
+    public static final String EXTRA_ORGANIZATION_COLOR = "extra_organization_color";
+
+    private int mOrganizationColor;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.organization_info);
+        setPassFailButtonClickListeners();
+        setButtonClickListeners();
+    }
+
+    private void setButtonClickListeners() {
+        findViewById(R.id.organization_info_set_button).setOnClickListener(this);
+        findViewById(R.id.go_button).setOnClickListener(this);
+    }
+
+    @Override
+    public void onClick(View view) {
+        if (view.getId() == R.id.organization_info_set_button) {
+            EditText organizationNameEditText = (EditText) findViewById(
+                    R.id.organization_name_edit_text);
+            Intent intent = new Intent(ByodHelperActivity.ACTION_SET_ORGANIZATION_INFO);
+            intent.putExtra(EXTRA_ORGANIZATION_NAME, organizationNameEditText.getText().toString());
+            if (isOrganizationColorSet()) {
+                intent.putExtra(EXTRA_ORGANIZATION_COLOR, mOrganizationColor);
+            }
+            startActivity(intent);
+        } else if (view.getId() == R.id.go_button) {
+            Intent intent = new Intent(ByodHelperActivity.ACTION_TEST_CONFIRM_WORK_CREDENTIALS);
+            startActivity(intent);
+        }
+    }
+
+    private boolean isOrganizationColorSet() {
+        EditText organizationColorEditText = (EditText) findViewById(
+                R.id.organization_color_edit_text);
+        try {
+            mOrganizationColor = Color.parseColor(organizationColorEditText.getText().toString());
+        } catch (Exception e) {
+            Toast.makeText(this, "Not a valid Color value", Toast.LENGTH_SHORT).show();
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/net/ConnectivityScreenOffTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/net/ConnectivityScreenOffTestActivity.java
index e529b67..6109893 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/net/ConnectivityScreenOffTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/net/ConnectivityScreenOffTestActivity.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.graphics.Typeface;
 import android.net.ConnectivityManager;
 import android.net.ConnectivityManager.NetworkCallback;
@@ -89,7 +90,7 @@
 
     private final ScreenAndPlugStateReceiver mReceiver;
     private final IntentFilter mIntentFilter;
-    private boolean mHasBattery;
+    private boolean mWaitForPowerDisconnected;
 
     private PowerManager mPowerManager;
     private PowerManager.WakeLock mWakeLock;
@@ -159,10 +160,11 @@
                 null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
 
         // Whether or not this device (currently) has a battery.
-        mHasBattery = batteryInfo.getBooleanExtra(BatteryManager.EXTRA_PRESENT, true);
+        mWaitForPowerDisconnected =
+                batteryInfo.getBooleanExtra(BatteryManager.EXTRA_PRESENT, false) && !isLeanback();
 
         // Check if the device is already on battery power.
-        if (mHasBattery) {
+        if (mWaitForPowerDisconnected) {
             BatteryManager battMgr = (BatteryManager) getSystemService(Context.BATTERY_SERVICE);
             if (!battMgr.isCharging()) {
                 mState.setPowerDisconnected();
@@ -286,7 +288,8 @@
 
     /**
      * TODO(ek): Evaluate reworking the code roughly as follows:
-     *     - Move all the shared state here, including mHasBattery (and mTestingThread).
+     *     - Move all the shared state here, including mWaitForPowerDisconnected
+     *       (and mTestingThread).
      *     - Move from synchronizing on mLock to synchronizing on this since the
      *       AppState object is final, and delete mLock.
      *     - Synchronize the methods below, and add some required new methods.
@@ -311,7 +314,9 @@
 
         void setPowerConnected() { mPowerDisconnectTime = 0; }
         void setPowerDisconnected() { mPowerDisconnectTime = SystemClock.elapsedRealtime(); }
-        boolean validPowerStateForTesting() { return !mHasBattery || (mPowerDisconnectTime > 0); }
+        boolean validPowerStateForTesting() {
+            return !mWaitForPowerDisconnected || (mPowerDisconnectTime > 0);
+        }
     }
 
     class ScreenAndPlugStateReceiver extends BroadcastReceiver {
@@ -453,7 +458,7 @@
                     continue;
                 }
 
-                if (mHasBattery) {
+                if (mWaitForPowerDisconnected) {
                     final long delta = SystemClock.elapsedRealtime() - localState.mPowerDisconnectTime;
                     if (delta < MIN_POWER_DISCONNECT_MS) {
                         nextSleepDurationMs = (int) (MIN_POWER_DISCONNECT_MS - delta);
@@ -629,4 +634,9 @@
 
         return new HttpResult(rcode, msg);
     }
+
+    private boolean isLeanback() {
+        final PackageManager pm = this.getPackageManager();
+        return (pm != null && pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK));
+    }
 }
diff --git a/common/device-side/util/src/com/android/compatibility/common/util/DeviceInfoStore.java b/common/device-side/util/src/com/android/compatibility/common/util/DeviceInfoStore.java
index e0f3eab..9f1bda5 100644
--- a/common/device-side/util/src/com/android/compatibility/common/util/DeviceInfoStore.java
+++ b/common/device-side/util/src/com/android/compatibility/common/util/DeviceInfoStore.java
@@ -27,8 +27,12 @@
 
 public class DeviceInfoStore extends InfoStore {
 
-    private final File mJsonFile;
-    private JsonWriter mJsonWriter = null;
+    protected File mJsonFile;
+    protected JsonWriter mJsonWriter = null;
+
+    public DeviceInfoStore() {
+        mJsonFile = null;
+    }
 
     public DeviceInfoStore(File file) throws Exception {
         mJsonFile = file;
diff --git a/common/device-side/util/src/com/android/compatibility/common/util/DeviceReportLog.java b/common/device-side/util/src/com/android/compatibility/common/util/DeviceReportLog.java
index d87ebbc..57b9e3e 100644
--- a/common/device-side/util/src/com/android/compatibility/common/util/DeviceReportLog.java
+++ b/common/device-side/util/src/com/android/compatibility/common/util/DeviceReportLog.java
@@ -18,12 +18,14 @@
 
 import android.app.Instrumentation;
 import android.os.Bundle;
+import android.os.Environment;
 import android.util.Log;
 
 import com.android.compatibility.common.util.ReportLog;
 
 import org.xmlpull.v1.XmlPullParserException;
 
+import java.io.File;
 import java.io.IOException;
 
 /**
@@ -35,12 +37,87 @@
 public class DeviceReportLog extends ReportLog {
     private static final String TAG = DeviceReportLog.class.getSimpleName();
     private static final String RESULT = "COMPATIBILITY_TEST_RESULT";
+    private static final String DEFAULT_REPORT_LOG_NAME = "DefaultTestMetrics";
+    private static final String DEFAULT_STREAM_NAME = "DefaultStream";
     private static final int INST_STATUS_ERROR = -1;
     private static final int INST_STATUS_IN_PROGRESS = 2;
 
+    private ReportLogDeviceInfoStore store;
+
+    public DeviceReportLog() {
+        this(DEFAULT_REPORT_LOG_NAME, DEFAULT_STREAM_NAME);
+    }
+
+    public DeviceReportLog(String reportLogName) {
+        this(reportLogName, DEFAULT_STREAM_NAME);
+    }
+
+    public DeviceReportLog(String reportLogName, String streamName) {
+        super(reportLogName, streamName);
+        try {
+            final File dir = new File(Environment.getExternalStorageDirectory(), "report-log-files");
+            if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+                throw new IOException("External storage is not mounted");
+            } else if (!dir.mkdirs() && !dir.isDirectory()) {
+                throw new IOException("Cannot create directory for device info files");
+            } else {
+                File jsonFile = new File(dir, mReportLogName + ".reportlog.json");
+                store = new ReportLogDeviceInfoStore(jsonFile, mStreamName);
+                store.open();
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Could not create report log file.");
+        }
+    }
+
+    @Override
+    public void addValue(String source, String message, double value, ResultType type,
+             ResultUnit unit) {
+        super.addValue(source, message, value, type, unit);
+        try {
+            store.addResult(message, value);
+        } catch (IOException e) {
+            Log.e(TAG, "Could not log metric.", e);
+        }
+    }
+
+    @Override
+    public void addValue(String message, double value, ResultType type,
+                         ResultUnit unit) {
+        super.addValue(message, value, type, unit);
+        try {
+            store.addResult(message, value);
+        } catch (IOException e) {
+            Log.e(TAG, "Could not log metric.", e);
+        }
+    }
+
+    @Override
+    public void addValues(String source, String message, double[] values, ResultType type,
+                         ResultUnit unit) {
+        super.addValues(source, message, values, type, unit);
+        try {
+            store.addArrayResult(message, values);
+        } catch (IOException e) {
+            Log.e(TAG, "Could not log metric.", e);
+        }
+    }
+
+    @Override
+    public void addValues(String message, double[] values, ResultType type,
+                         ResultUnit unit) {
+        super.addValues(message, values, type, unit);
+        try {
+            store.addArrayResult(message, values);
+        } catch (IOException e) {
+            Log.e(TAG, "Could not log metric.", e);
+        }
+    }
+
     public void submit(Instrumentation instrumentation) {
         Log.i(TAG, "Submit");
         try {
+            store.close();
             Bundle output = new Bundle();
             output.putString(RESULT, serialize(this));
             instrumentation.sendStatus(INST_STATUS_IN_PROGRESS, output);
diff --git a/common/device-side/util/src/com/android/compatibility/common/util/ReportLogDeviceInfoStore.java b/common/device-side/util/src/com/android/compatibility/common/util/ReportLogDeviceInfoStore.java
new file mode 100644
index 0000000..67e6c39
--- /dev/null
+++ b/common/device-side/util/src/com/android/compatibility/common/util/ReportLogDeviceInfoStore.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.compatibility.common.util;
+
+import android.util.JsonWriter;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+
+public class ReportLogDeviceInfoStore extends DeviceInfoStore {
+
+    private final String mStreamName;
+
+    public ReportLogDeviceInfoStore(File jsonFile, String streamName) throws Exception {
+        mJsonFile = jsonFile;
+        mStreamName = streamName;
+    }
+
+    /**
+     * Creates the writer and starts the JSON Object for the metric stream.
+     */
+    @Override
+    public void open() throws IOException {
+        BufferedWriter formatWriter;
+        String oldMetrics;
+        if (mJsonFile.exists()) {
+            BufferedReader jsonReader = new BufferedReader(new FileReader(mJsonFile));
+            StringBuilder oldMetricsBuilder = new StringBuilder();
+            String line;
+            while ((line = jsonReader.readLine()) != null) {
+                oldMetricsBuilder.append(line);
+            }
+            oldMetrics = oldMetricsBuilder.toString().trim();
+            if (oldMetrics.charAt(oldMetrics.length() - 1) == '}') {
+                oldMetrics = oldMetrics.substring(0, oldMetrics.length() - 1);
+            }
+            oldMetrics = oldMetrics + ",";
+        } else {
+            oldMetrics = "{";
+        }
+        mJsonFile.createNewFile();
+        formatWriter = new BufferedWriter(new FileWriter(mJsonFile));
+        formatWriter.write(oldMetrics + "\"" + mStreamName + "\":", 0,
+            oldMetrics.length() + mStreamName.length() + 3);
+        formatWriter.flush();
+        formatWriter.close();
+        mJsonWriter = new JsonWriter(new FileWriter(mJsonFile, true));
+        mJsonWriter.beginObject();
+    }
+
+    /**
+     * Closes the writer.
+     */
+    @Override
+    public void close() throws IOException {
+        mJsonWriter.endObject();
+        mJsonWriter.close();
+        // Close the overall JSON object
+        BufferedWriter formatWriter = new BufferedWriter(new FileWriter(mJsonFile, true));
+        formatWriter.write("}", 0, 1);
+        formatWriter.flush();
+        formatWriter.close();
+    }
+}
diff --git a/common/device-side/util/tests/src/com/android/compatibility/common/util/DeviceReportTest.java b/common/device-side/util/tests/src/com/android/compatibility/common/util/DeviceReportTest.java
index 7dbece0..b8887cf 100644
--- a/common/device-side/util/tests/src/com/android/compatibility/common/util/DeviceReportTest.java
+++ b/common/device-side/util/tests/src/com/android/compatibility/common/util/DeviceReportTest.java
@@ -17,9 +17,17 @@
 
 import android.app.Instrumentation;
 import android.os.Bundle;
+import android.os.Environment;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.lang.StringBuilder;
 
 import junit.framework.TestCase;
 
+import org.json.JSONObject;
+
 /**
  * Tests for {@line DeviceReportLog}.
  */
@@ -50,6 +58,20 @@
     private static final double TEST_VALUE_2 = 5;
     private static final ResultType TEST_TYPE_2 = ResultType.LOWER_BETTER;
     private static final ResultUnit TEST_UNIT_2 = ResultUnit.COUNT;
+    private static final String TEST_MESSAGE_3 = "Sample";
+    private static final double TEST_VALUE_3 = 7;
+    private static final ResultType TEST_TYPE_3 = ResultType.LOWER_BETTER;
+    private static final ResultUnit TEST_UNIT_3 = ResultUnit.COUNT;
+    private static final String TEST_MESSAGE_4 = "Message";
+    private static final double TEST_VALUE_4 = 9;
+    private static final ResultType TEST_TYPE_4 = ResultType.LOWER_BETTER;
+    private static final ResultUnit TEST_UNIT_4 = ResultUnit.COUNT;
+    private static final String REPORT_NAME_1 = "TestReport1";
+    private static final String REPORT_NAME_2 = "TestReport2";
+    private static final String STREAM_NAME_1 = "SampleStream1";
+    private static final String STREAM_NAME_2 = "SampleStream2";
+    private static final String STREAM_NAME_3 = "SampleStream3";
+    private static final String STREAM_NAME_4 = "SampleStream4";
 
     public void testSubmit() throws Exception {
         DeviceReportLog log = new DeviceReportLog();
@@ -64,4 +86,69 @@
         ReportLog result = ReportLog.parse(metrics);
         assertNotNull("Metrics could not be decoded", result);
     }
+
+    public void testFile() throws Exception {
+        final File dir = new File(Environment.getExternalStorageDirectory(), "report-log-files");
+        assertTrue("External storage is not mounted",
+                Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED));
+        assertTrue("Report Log directory missing", dir.isDirectory());
+
+        // Remove files from earlier possible runs.
+        File[] files = dir.listFiles();
+        for (File file : files) {
+            file.delete();
+        }
+
+        TestInstrumentation inst = new TestInstrumentation();
+
+        DeviceReportLog log1 = new DeviceReportLog(REPORT_NAME_1, STREAM_NAME_1);
+        log1.addValue(TEST_MESSAGE_1, TEST_VALUE_1, TEST_TYPE_1, TEST_UNIT_1);
+        log1.setSummary(TEST_MESSAGE_1, TEST_VALUE_1, TEST_TYPE_1, TEST_UNIT_1);
+        log1.submit(inst);
+
+        DeviceReportLog log2 = new DeviceReportLog(REPORT_NAME_1, STREAM_NAME_2);
+        log2.addValue(TEST_MESSAGE_2, TEST_VALUE_2, TEST_TYPE_2, TEST_UNIT_2);
+        log2.setSummary(TEST_MESSAGE_2, TEST_VALUE_2, TEST_TYPE_2, TEST_UNIT_2);
+        log2.submit(inst);
+
+        DeviceReportLog log3 = new DeviceReportLog(REPORT_NAME_2, STREAM_NAME_3);
+        log3.addValue(TEST_MESSAGE_3, TEST_VALUE_3, TEST_TYPE_3, TEST_UNIT_3);
+        log3.setSummary(TEST_MESSAGE_3, TEST_VALUE_3, TEST_TYPE_3, TEST_UNIT_3);
+        log3.submit(inst);
+
+        DeviceReportLog log4 = new DeviceReportLog(REPORT_NAME_2, STREAM_NAME_4);
+        log4.addValue(TEST_MESSAGE_4, TEST_VALUE_4, TEST_TYPE_4, TEST_UNIT_4);
+        log4.setSummary(TEST_MESSAGE_4, TEST_VALUE_4, TEST_TYPE_4, TEST_UNIT_4);
+        log4.submit(inst);
+
+        File jsonFile1 = new File(dir, REPORT_NAME_1 + ".reportlog.json");
+        File jsonFile2 = new File(dir, REPORT_NAME_2 + ".reportlog.json");
+        assertTrue("Report Log missing", jsonFile1.exists());
+        assertTrue("Report Log missing", jsonFile2.exists());
+
+        BufferedReader jsonReader = new BufferedReader(new FileReader(jsonFile1));
+        StringBuilder metricsBuilder = new StringBuilder();
+        String line;
+        while ((line = jsonReader.readLine()) != null) {
+            metricsBuilder.append(line);
+        }
+        String metrics = metricsBuilder.toString().trim();
+        JSONObject jsonObject = new JSONObject(metrics);
+        assertTrue("Incorrect metrics",
+                jsonObject.getJSONObject(STREAM_NAME_1).getDouble(TEST_MESSAGE_1) == TEST_VALUE_1);
+        assertTrue("Incorrect metrics",
+                jsonObject.getJSONObject(STREAM_NAME_2).getDouble(TEST_MESSAGE_2) == TEST_VALUE_2);
+
+        jsonReader = new BufferedReader(new FileReader(jsonFile2));
+        metricsBuilder = new StringBuilder();
+        while ((line = jsonReader.readLine()) != null) {
+            metricsBuilder.append(line);
+        }
+        metrics = metricsBuilder.toString().trim();
+        jsonObject = new JSONObject(metrics);
+        assertTrue("Incorrect metrics",
+                jsonObject.getJSONObject(STREAM_NAME_3).getDouble(TEST_MESSAGE_3) == TEST_VALUE_3);
+        assertTrue("Incorrect metrics",
+                jsonObject.getJSONObject(STREAM_NAME_4).getDouble(TEST_MESSAGE_4) == TEST_VALUE_4);
+    }
 }
diff --git a/common/host-side/tradefed/res/config/common-compatibility-config.xml b/common/host-side/tradefed/res/config/common-compatibility-config.xml
index 7f3f76a..1b40f16 100644
--- a/common/host-side/tradefed/res/config/common-compatibility-config.xml
+++ b/common/host-side/tradefed/res/config/common-compatibility-config.xml
@@ -17,6 +17,8 @@
     <device_recovery class="com.android.tradefed.device.WaitDeviceRecovery" />
     <build_provider class="com.android.compatibility.common.tradefed.build.CompatibilityBuildProvider" />
     <test class="com.android.compatibility.common.tradefed.testtype.CompatibilityTest" />
-    <logger class="com.android.tradefed.log.FileLogger" />
+    <logger class="com.android.tradefed.log.FileLogger">
+        <option name="log-level-display" value="WARN" />
+    </logger>
     <result_reporter class="com.android.compatibility.common.tradefed.result.ResultReporter" />
 </configuration>
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java
index 28596d3..18695fe 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java
@@ -127,7 +127,7 @@
         long time = System.currentTimeMillis();
         String dirSuffix = getDirSuffix(time);
         if (mRetrySessionId != null) {
-            Log.d(mDeviceSerial, String.format("Retrying session %d", mRetrySessionId));
+            CLog.d("[%s] Retrying session %d", mDeviceSerial, mRetrySessionId);
             List<IInvocationResult> results = null;
             try {
                 results = ResultHandler.getResults(mBuildHelper.getResultsDir());
@@ -327,6 +327,7 @@
             File resultFile = ResultHandler.writeResults(mBuildHelper.getSuiteName(),
                     mBuildHelper.getSuiteVersion(), mBuildHelper.getSuitePlan(), mResult,
                     mResultDir, mStartTime, elapsedTime + mStartTime, mReferenceUrl);
+            logResult("Result saved at: %s", resultFile.getCanonicalPath());
             copyDynamicConfigFiles(mBuildHelper.getDynamicConfigFiles(), mResultDir);
             copyFormattingFiles(mResultDir);
             zipResults(mResultDir);
@@ -336,8 +337,8 @@
                     fis = new FileInputStream(resultFile);
                     mLogSaver.saveLogData("log-result", LogDataType.XML, fis);
                 } catch (IOException ioe) {
-                    Log.e(mDeviceSerial, "error saving XML with log saver");
-                    Log.e(mDeviceSerial, ioe);
+                    CLog.e("[%s] error saving XML with log saver", mDeviceSerial);
+                    CLog.e(ioe);
                 } finally {
                     StreamUtil.close(fis);
                 }
@@ -347,10 +348,12 @@
                     logResult("Result Server Response: %d",
                             mUploader.uploadResult(resultFile, mReferenceUrl));
                 } catch (IOException ioe) {
-                    Log.e(mDeviceSerial, ioe);
+                    CLog.e("[%s] IOException while uploading result.", mDeviceSerial);
+                    CLog.e(ioe);
                 }
             }
         } catch (IOException | XmlPullParserException e) {
+            CLog.e("[%s] Exception while saving result XML.", mDeviceSerial);
             CLog.e(e);
         }
     }
@@ -477,10 +480,11 @@
     }
 
     private void logResult(String format, Object... args) {
+        format = String.format("[%s] %s", mDeviceSerial, format);
         if (mQuietOutput) {
             CLog.i(format, args);
         } else {
-            Log.logAndDisplay(LogLevel.INFO, mDeviceSerial, String.format(format, args));
+            CLog.logAndDisplay(LogLevel.INFO, format, args);
         }
     }
 }
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ApkInstrumentationPreparer.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ApkInstrumentationPreparer.java
index 916e8ec..33ee5d8 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ApkInstrumentationPreparer.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ApkInstrumentationPreparer.java
@@ -26,7 +26,6 @@
 import com.android.tradefed.config.OptionClass;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.result.ITestInvocationListener;
 import com.android.tradefed.targetprep.BuildError;
 import com.android.tradefed.targetprep.ITargetCleaner;
@@ -83,7 +82,9 @@
             return;
         }
         try {
-            if (!instrument(device, buildInfo)) {
+            if (instrument(device, buildInfo)) {
+                logInfo("Target preparation successful");
+            } else {
                 throw new TargetSetupError("Not all target preparation steps completed");
             }
         } catch (FileNotFoundException e) {
@@ -106,8 +107,8 @@
         try {
             instrument(device, buildInfo);
         } catch (FileNotFoundException e1) {
-            CLog.e("Couldn't find apk to instrument");
-            CLog.e(e1);
+            logError("Couldn't find apk to instrument");
+            logError(e1);
         }
     }
 
@@ -122,6 +123,12 @@
             throw new FileNotFoundException(String.format("%s not found", mApkFileName));
         }
 
+        if (device.getAppPackageInfo(mPackageName) != null) {
+            logInfo("Package %s already present on the device, uninstalling ...", mPackageName);
+            device.uninstallPackage(mPackageName);
+        }
+
+        logInfo("Instrumenting package %s:", mPackageName);
         AndroidJUnitTest instrTest = new AndroidJUnitTest();
         instrTest.setDevice(device);
         instrTest.setInstallFile(apkFile);
@@ -134,7 +141,7 @@
             for (TestIdentifier test : testFailures.keySet()) {
                 success = false;
                 String trace = testFailures.get(test);
-                CLog.e("Target preparation step %s failed.\n%s", test.getTestName(), trace);
+                logError("Target preparation step %s failed.\n%s", test.getTestName(), trace);
             }
         }
         return success;
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java
index 0178bab..a0b8faf 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java
@@ -18,7 +18,6 @@
 
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.compatibility.common.tradefed.testtype.CompatibilityTest;
-import com.android.ddmlib.testrunner.TestIdentifier;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.config.Option;
 import com.android.tradefed.device.DeviceNotAvailableException;
@@ -63,8 +62,9 @@
         BUILD_KEYS.put("build_version_security_patch", "ro.build.version.security_patch");
     }
 
-    @Option(name = CompatibilityTest.SKIP_DEVICE_INFO_OPTION, description =
-            "Whether device info collection should be skipped")
+    @Option(name = CompatibilityTest.SKIP_DEVICE_INFO_OPTION,
+            shortName = 'd',
+            description = "Whether device info collection should be skipped")
     private boolean mSkipDeviceInfo = false;
 
     @Option(name= "src-dir", description = "The directory to copy to the results dir")
@@ -91,10 +91,6 @@
         getDeviceInfoFiles(device, buildInfo);
     }
 
-    private void addBuildInfo(ITestDevice device, IBuildInfo buildInfo, String key, String value)
-            throws DeviceNotAvailableException {
-    }
-
     private void getDeviceInfoFiles(ITestDevice device, IBuildInfo buildInfo) {
         CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(buildInfo);
         try {
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/LocationCheck.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/LocationCheck.java
index cea3136..94bc64f 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/LocationCheck.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/LocationCheck.java
@@ -51,6 +51,7 @@
             return; // skip this precondition if required location feature is not present
         }
 
+        logInfo("Verifying location setting");
         mSettingName = LOCATION_SETTING;
         mSettingType = SettingsPreparer.SettingType.SECURE;
         mExpectedSettingValues.add(NETWORK);
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PreconditionPreparer.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PreconditionPreparer.java
index 5c94c27..fc25e03 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PreconditionPreparer.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PreconditionPreparer.java
@@ -17,24 +17,29 @@
 package com.android.compatibility.common.tradefed.targetprep;
 
 import com.android.compatibility.common.tradefed.testtype.CompatibilityTest;
+import com.android.ddmlib.Log;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.config.Option;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil;
 import com.android.tradefed.targetprep.BuildError;
 import com.android.tradefed.targetprep.ITargetPreparer;
 import com.android.tradefed.targetprep.TargetSetupError;
 
 /**
- * An {@link ITargetPreparer} that performs checks and/or tasks to ensure the 
+ * An {@link ITargetPreparer} that performs checks and/or tasks to ensure the
  * the device is ready to run the test suite.
  */
 public abstract class PreconditionPreparer implements ITargetPreparer {
 
-    @Option(name = CompatibilityTest.SKIP_PRECONDITIONS_OPTION, description =
-            "Whether preconditions should be skipped")
+    @Option(name = CompatibilityTest.SKIP_PRECONDITIONS_OPTION,
+            shortName = 'o',
+            description = "Whether preconditions should be skipped")
     private boolean mSkipPreconditions = false;
 
+    protected final String LOG_TAG = getClass().getSimpleName();
+
     @Override
     public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
             BuildError, DeviceNotAvailableException {
@@ -45,4 +50,35 @@
 
     public abstract void run(ITestDevice device, IBuildInfo buildInfo)
             throws TargetSetupError, BuildError, DeviceNotAvailableException;
+
+    protected void logInfo(String info) {
+        LogUtil.printLog(Log.LogLevel.INFO, LOG_TAG, info);
+    }
+
+    protected void logInfo(String infoFormat, Object... args) {
+        LogUtil.printLog(Log.LogLevel.INFO, LOG_TAG, String.format(infoFormat, args));
+    }
+
+    protected void logWarning(String warning) {
+        LogUtil.printLog(Log.LogLevel.WARN, LOG_TAG, warning);
+    }
+
+    protected void logWarning(String warningFormat, Object... args) {
+        LogUtil.printLog(Log.LogLevel.WARN, LOG_TAG, String.format(warningFormat, args));
+    }
+
+    protected void logError(String error) {
+        LogUtil.printLog(Log.LogLevel.ERROR, LOG_TAG, error);
+    }
+
+    protected void logError(String errorFormat, Object... args) {
+        LogUtil.printLog(Log.LogLevel.ERROR, LOG_TAG, String.format(errorFormat, args));
+    }
+
+    protected void logError(Throwable t) {
+        if (t != null) {
+            Log.e(LOG_TAG, t);
+        }
+    }
+
 }
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PropertyCheck.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PropertyCheck.java
index 4d00ea5..79f19d0 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PropertyCheck.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PropertyCheck.java
@@ -15,13 +15,11 @@
  */
 package com.android.compatibility.common.tradefed.targetprep;
 
-import com.android.ddmlib.Log;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.config.Option;
 import com.android.tradefed.config.OptionClass;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil;
 import com.android.tradefed.targetprep.BuildError;
 import com.android.tradefed.targetprep.TargetSetupError;
 
@@ -48,11 +46,11 @@
     @Override
     public void run(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
             BuildError, DeviceNotAvailableException {
+
         String propertyValue = device.getProperty(mPropertyName);
         if (propertyValue == null) {
-            LogUtil.printLog(Log.LogLevel.WARN, LOG_TAG, String.format(
-                    "Property \"%s\" not found on device, cannot verify value \"%s\" ",
-                    mPropertyName, mExpectedPropertyValue));
+            logWarning("Property \"%s\" not found on device, cannot verify value \"%s\" ",
+                    mPropertyName, mExpectedPropertyValue);
             return;
         }
 
@@ -63,7 +61,7 @@
             if(mThrowError) {
                 throw new TargetSetupError(msg);
             } else {
-                LogUtil.printLog(Log.LogLevel.WARN, LOG_TAG, msg);
+                logWarning(msg);
             }
         }
     }
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ReportLogCollector.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ReportLogCollector.java
new file mode 100644
index 0000000..c786ef4
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ReportLogCollector.java
@@ -0,0 +1,101 @@
+/*
+ * 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.compatibility.common.tradefed.targetprep;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.targetprep.BuildError;
+import com.android.tradefed.targetprep.ITargetCleaner;
+import com.android.tradefed.targetprep.TargetSetupError;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+
+/**
+ * An {@link ITargetCleaner} that prepares and pulls report logs.
+ */
+public class ReportLogCollector implements ITargetCleaner {
+
+    @Option(name= "src-dir", description = "The directory to copy to the results dir")
+    private String mSrcDir;
+
+    @Option(name = "dest-dir", description = "The directory under the result to store the files")
+    private String mDestDir;
+
+    public ReportLogCollector() {
+    }
+
+    @Override
+    public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
+            BuildError, DeviceNotAvailableException {
+        prepareReportLogContainers(device, buildInfo);
+    }
+
+    private void addBuildInfo(ITestDevice device, IBuildInfo buildInfo, String key, String value)
+            throws DeviceNotAvailableException {
+    }
+
+    private void prepareReportLogContainers(ITestDevice device, IBuildInfo buildInfo) {
+        CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(buildInfo);
+        try {
+            File resultDir = buildHelper.getResultDir();
+            if (mDestDir != null) {
+                resultDir = new File(resultDir, mDestDir);
+            }
+            resultDir.mkdirs();
+            if (!resultDir.isDirectory()) {
+                CLog.e("%s is not a directory", resultDir.getAbsolutePath());
+                return;
+            }
+        } catch (FileNotFoundException fnfe) {
+            fnfe.printStackTrace();
+        }
+    }
+
+    @Override
+    public void tearDown(ITestDevice device, IBuildInfo buildInfo, Throwable e) {
+        // Pull report log files from device.
+        CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(buildInfo);
+        try {
+            File resultDir = buildHelper.getResultDir();
+            String resultPath = resultDir.getAbsolutePath();
+            pull(device, mSrcDir, resultPath);
+        } catch (FileNotFoundException fnfe) {
+            fnfe.printStackTrace();
+        }
+    }
+
+    private void pull(ITestDevice device, String src, String dest) {
+        String command = String.format("adb -s %s pull %s %s", device.getSerialNumber(), src, dest);
+        try {
+            Process p = Runtime.getRuntime().exec(new String[]{"/bin/bash", "-c", command});
+            if (p.waitFor() != 0) {
+                CLog.e("Failed to run %s", command);
+            }
+        } catch (Exception e) {
+            CLog.e("Caught exception during pull.");
+            CLog.e(e);
+        }
+    }
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/SettingsPreparer.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/SettingsPreparer.java
index f21ef39..d4c9d54 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/SettingsPreparer.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/SettingsPreparer.java
@@ -95,6 +95,8 @@
             String currentSettingValue = device.executeShellCommand(shellCmdGet).trim();
             // only change unexpected setting value
             if (!mExpectedSettingValues.contains(currentSettingValue)) {
+                logInfo("Changing value for %s from %s to %s",
+                        mSettingName, currentSettingValue, mSetValue);
                 device.executeShellCommand(shellCmdPut);
             }
             return;
@@ -102,6 +104,7 @@
 
         /* Case 2: Only set-value given */
         if (mSetValue != null) {
+            logInfo("Setting %s to value %s", mSettingName, mSetValue);
             device.executeShellCommand(shellCmdPut);
             return;
         }
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/WifiCheck.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/WifiCheck.java
index 0100969..5863bd8 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/WifiCheck.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/WifiCheck.java
@@ -15,13 +15,11 @@
  */
 package com.android.compatibility.common.tradefed.targetprep;
 
-import com.android.ddmlib.Log.LogLevel;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.config.Option;
 import com.android.tradefed.config.OptionClass;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.targetprep.BuildError;
 import com.android.tradefed.targetprep.TargetSetupError;
 
@@ -65,16 +63,15 @@
         if (mWifiSsid == null) { // no connection to create, check for existing connectivity
             if (!device.checkConnectivity()) {
                 throw new TargetSetupError("Device has no network connection, no ssid provided");
-            }  
+            }
         } else { // network provided in options, attempt to create new connection
-            CLog.logAndDisplay(LogLevel.INFO, "Attempting connection to \"%s\"", mWifiSsid);
-            if (device.connectToWifiNetwork(mWifiSsid, mWifiPsk)) { // attempt connection
-                CLog.logAndDisplay(LogLevel.INFO, "Connection successful");
-            } else {
+            logInfo("Attempting connection to \"%s\"", mWifiSsid);
+            if (!device.connectToWifiNetwork(mWifiSsid, mWifiPsk)) { // attempt connection
                 throw new TargetSetupError(String.format(
                         "Unable to connect to network \"%s\", some modules of CTS" +
                         "require an active network connection", mWifiSsid));
             }
         }
+        logInfo("Wifi is connected");
     }
 }
diff --git a/common/util/src/com/android/compatibility/common/util/ReportLog.java b/common/util/src/com/android/compatibility/common/util/ReportLog.java
index 445bbd4..37c39ef 100644
--- a/common/util/src/com/android/compatibility/common/util/ReportLog.java
+++ b/common/util/src/com/android/compatibility/common/util/ReportLog.java
@@ -46,19 +46,22 @@
     private static final String SOURCE_ATTR = "source";
     private static final String SUMMARY_TAG = "Summary";
     private static final String VALUE_TAG = "Value";
+    private static final String DEFAULT_NAME = "default";
 
-    private Metric mSummary;
-    private final List<Metric> mDetails = new ArrayList<>();
+    protected Metric mSummary;
+    protected String mReportLogName;
+    protected String mStreamName;
+    protected final List<Metric> mDetails = new ArrayList<>();
 
     public static class Metric implements Serializable {
         private static final int MAX_SOURCE_LENGTH = 200;
         private static final int MAX_MESSAGE_LENGTH = 200;
         private static final int MAX_NUM_VALUES = 1000;
-        private String mSource;
-        private String mMessage;
-        private double[] mValues;
-        private ResultType mType;
-        private ResultUnit mUnit;
+        String mSource;
+        String mMessage;
+        double[] mValues;
+        ResultType mType;
+        ResultUnit mUnit;
 
         Metric(String source, String message, double value, ResultType type, ResultUnit unit) {
             this(source, message, new double[] { value }, type, unit);
@@ -161,6 +164,15 @@
         }
     }
 
+    public ReportLog() {
+        mReportLogName = DEFAULT_NAME;
+    }
+
+    public ReportLog(String reportLogName, String streamName) {
+        mReportLogName = reportLogName;
+        mStreamName = streamName;
+    }
+
     /**
      * @param elem
      */
@@ -225,10 +237,12 @@
      * NOTE: messages over {@value Metric#MAX_MESSAGE_LENGTH} chars will be trimmed.
      */
     public void setSummary(String message, double value, ResultType type, ResultUnit unit) {
-        setSummary(new Metric(Stacktrace.getTestCallerClassMethodNameLineNumber(),
-                message, value, type, unit));
+        setSummary(new Metric(Stacktrace.getTestCallerClassMethodNameLineNumber(), message, value,
+                type, unit));
     }
 
+    // TODO(mishragaurav): Add support for values of other types.
+
     public Metric getSummary() {
         return mSummary;
     }
@@ -328,5 +342,4 @@
         }
         return report;
     }
-
 }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java
index 25ee645..d81abb6 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java
@@ -17,51 +17,23 @@
 package android.appsecurity.cts;
 
 import com.android.cts.migration.MigrationHelper;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.testtype.IAbi;
-import com.android.tradefed.testtype.IAbiReceiver;
-import com.android.tradefed.testtype.IBuildReceiver;
 
 /**
  * Set of tests that verify behavior of
  * {@link android.provider.DocumentsContract} and related intents.
  */
-public class DocumentsTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
+public class DocumentsTest extends DocumentsTestCase {
     private static final String PROVIDER_PKG = "com.android.cts.documentprovider";
     private static final String PROVIDER_APK = "CtsDocumentProvider.apk";
 
-    private static final String CLIENT_PKG = "com.android.cts.documentclient";
-    private static final String CLIENT_APK = "CtsDocumentClient.apk";
-
-    private IAbi mAbi;
-    private IBuildInfo mCtsBuild;
-
-    @Override
-    public void setAbi(IAbi abi) {
-        mAbi = abi;
-    }
-
-    @Override
-    public void setBuild(IBuildInfo buildInfo) {
-        mCtsBuild = buildInfo;
-    }
-
     @Override
     protected void setUp() throws Exception {
         super.setUp();
 
-        assertNotNull(mAbi);
-        assertNotNull(mCtsBuild);
-
         getDevice().uninstallPackage(PROVIDER_PKG);
-        getDevice().uninstallPackage(CLIENT_PKG);
 
         assertNull(getDevice().installPackage(
                 MigrationHelper.getTestFile(mCtsBuild, PROVIDER_APK), false));
-        assertNull(getDevice().installPackage(
-                MigrationHelper.getTestFile(mCtsBuild, CLIENT_APK), false));
     }
 
     @Override
@@ -69,7 +41,6 @@
         super.tearDown();
 
         getDevice().uninstallPackage(PROVIDER_PKG);
-        getDevice().uninstallPackage(CLIENT_PKG);
     }
 
     public void testOpenSimple() throws Exception {
@@ -92,33 +63,6 @@
         runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testTree");
     }
 
-    public void testOpenExternalDirectory_invalidPath() throws Exception {
-        runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testOpenExternalDirectory_invalidPath");
-    }
-
-    public void testOpenExternalDirectory_userRejects() throws Exception {
-        runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testOpenExternalDirectory_userRejects");
-    }
-
-    public void testOpenExternalDirectory_userAccepts() throws Exception {
-        runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testOpenExternalDirectory_userAccepts");
-    }
-
-    public void testOpenExternalDirectory_notAskedAgain() throws Exception {
-        runDeviceTests(CLIENT_PKG, ".DocumentsClientTest",
-                "testOpenExternalDirectory_notAskedAgain");
-    }
-
-    public void testOpenExternalDirectory_userAcceptsNewDirectory() throws Exception {
-        // TODO: figure out a better way to remove the directory.
-        final String command = "rm -rf /sdcard/Pictures";
-        final String output = getDevice().executeShellCommand(command);
-        if (!output.trim().isEmpty()) {
-            fail("Command '" + command + "' failed: '" + output + "'");
-        }
-        runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testOpenExternalDirectory_userAccepts");
-    }
-
     public void testGetContent() throws Exception {
         runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testGetContent");
     }
@@ -126,9 +70,4 @@
     public void testTransferDocument() throws Exception {
         runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testTransferDocument");
     }
-
-    public void runDeviceTests(String packageName, String testClassName, String testMethodName)
-            throws DeviceNotAvailableException {
-        Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
-    }
 }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java
new file mode 100644
index 0000000..7bd42b5
--- /dev/null
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.appsecurity.cts;
+
+import com.android.cts.migration.MigrationHelper;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+/**
+ * Base class for {@link android.provider.DocumentsContract} and related test cases.
+ */
+abstract  class DocumentsTestCase extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
+    protected static final String CLIENT_PKG = "com.android.cts.documentclient";
+    protected static final String CLIENT_APK = "CtsDocumentClient.apk";
+
+    protected IAbi mAbi;
+    protected IBuildInfo mCtsBuild;
+
+    @Override
+    public void setAbi(IAbi abi) {
+        mAbi = abi;
+    }
+
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mCtsBuild = buildInfo;
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        assertNotNull(mAbi);
+        assertNotNull(mCtsBuild);
+
+        getDevice().uninstallPackage(CLIENT_PKG);
+
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, CLIENT_APK), false));
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+
+        getDevice().uninstallPackage(CLIENT_PKG);
+    }
+
+    public void runDeviceTests(String packageName, String testClassName, String testMethodName)
+            throws DeviceNotAvailableException {
+        Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
+    }
+}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ScopedDirectoryAccessTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ScopedDirectoryAccessTest.java
new file mode 100644
index 0000000..ffc7597
--- /dev/null
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ScopedDirectoryAccessTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.appsecurity.cts;
+
+/**
+ * Set of tests that verify behavior of the Scoped Directory access API.
+ */
+public class ScopedDirectoryAccessTest extends DocumentsTestCase {
+
+    public void testInvalidPath() throws Exception {
+        runDeviceTests(CLIENT_PKG, ".ScopedDirectoryAccessClientTest", "testInvalidPath");
+    }
+
+    public void testUserRejects() throws Exception {
+        runDeviceTests(CLIENT_PKG, ".ScopedDirectoryAccessClientTest", "testUserRejects");
+    }
+
+    public void testUserAccepts() throws Exception {
+        runDeviceTests(CLIENT_PKG, ".ScopedDirectoryAccessClientTest", "testUserAccepts");
+    }
+
+    public void testUserAcceptsNewDirectory() throws Exception {
+        runDeviceTests(CLIENT_PKG, ".ScopedDirectoryAccessClientTest",
+                "testUserAcceptsNewDirectory");
+    }
+
+    public void testNotAskedAgain() throws Exception {
+        runDeviceTests(CLIENT_PKG, ".ScopedDirectoryAccessClientTest", "testNotAskedAgain");
+    }
+
+    public void testDeniesOnceButAllowsAskingAgain() throws Exception {
+        runDeviceTests(CLIENT_PKG, ".ScopedDirectoryAccessClientTest",
+                "testDeniesOnceButAllowsAskingAgain");
+    }
+
+    public void testDeniesOnceForAll() throws Exception {
+        runDeviceTests(CLIENT_PKG, ".ScopedDirectoryAccessClientTest", "testDeniesOnceForAll");
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/AppAccessData/src/com/android/cts/appaccessdata/AccessPrivateDataTest.java b/hostsidetests/appsecurity/test-apps/AppAccessData/src/com/android/cts/appaccessdata/AccessPrivateDataTest.java
index ba27114..e7565d4 100644
--- a/hostsidetests/appsecurity/test-apps/AppAccessData/src/com/android/cts/appaccessdata/AccessPrivateDataTest.java
+++ b/hostsidetests/appsecurity/test-apps/AppAccessData/src/com/android/cts/appaccessdata/AccessPrivateDataTest.java
@@ -17,7 +17,6 @@
 package com.android.cts.appaccessdata;
 
 import java.io.BufferedReader;
-import java.io.DataInputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -26,6 +25,7 @@
 
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.test.AndroidTestCase;
 
 /**
@@ -85,32 +85,27 @@
      */
     public void testAccessPublicData() throws IOException {
         try {
-            getOtherAppUid();
-        } catch (FileNotFoundException e) {
-            fail("Was not able to access another app's public file: " + e);
-        } catch (SecurityException e) {
-            fail("Was not able to access another app's public file: " + e);
+            // construct the absolute file path to the other app's public file
+            ApplicationInfo applicationInfo = getApplicationInfo(APP_WITH_DATA_PKG);
+            File publicFile = new File(applicationInfo.dataDir, "files/" + PUBLIC_FILE_NAME);
+            FileInputStream inputStream = new FileInputStream(publicFile);
+            inputStream.read();
+            inputStream.close();
+            fail("Was able to access another app's public file");
+        } catch (FileNotFoundException | SecurityException e) {
+            // expected
         }
     }
 
-    private int getOtherAppUid() throws IOException, FileNotFoundException, SecurityException {
-        // construct the absolute file path to the other app's public file
-        ApplicationInfo applicationInfo = getApplicationInfo(APP_WITH_DATA_PKG);
-        File publicFile = new File(applicationInfo.dataDir, "files/" + PUBLIC_FILE_NAME);
-        DataInputStream inputStream = new DataInputStream(new FileInputStream(publicFile));
-        int otherAppUid = inputStream.readInt();
-        inputStream.close();
-        return otherAppUid;
-    }
-
     private void accessPrivateTrafficStats() throws IOException {
         int otherAppUid = -1;
         try {
-            otherAppUid = getOtherAppUid();
-        } catch (FileNotFoundException | SecurityException e) {
-            fail("Was not able to access another app's public file: " + e);
+            otherAppUid = getContext()
+                    .createPackageContext(APP_WITH_DATA_PKG, 0 /*flags*/)
+                    .getApplicationInfo().uid;
+        } catch (NameNotFoundException e) {
+            fail("Was not able to find other app");
         }
-
         boolean foundOtherStats = false;
         try {
             BufferedReader qtaguidReader = new BufferedReader(new FileReader("/proc/net/xt_qtaguid/stats"));
diff --git a/hostsidetests/appsecurity/test-apps/AppWithData/src/com/android/cts/appwithdata/CreatePrivateDataTest.java b/hostsidetests/appsecurity/test-apps/AppWithData/src/com/android/cts/appwithdata/CreatePrivateDataTest.java
index 378ef42..f3787e8 100644
--- a/hostsidetests/appsecurity/test-apps/AppWithData/src/com/android/cts/appwithdata/CreatePrivateDataTest.java
+++ b/hostsidetests/appsecurity/test-apps/AppWithData/src/com/android/cts/appwithdata/CreatePrivateDataTest.java
@@ -79,8 +79,7 @@
         outputStream.close();
         assertTrue(getContext().getFileStreamPath(PRIVATE_FILE_NAME).exists());
 
-        outputStream = getContext().openFileOutput(PUBLIC_FILE_NAME,
-                Context.MODE_WORLD_READABLE);
+        outputStream = getContext().openFileOutput(PUBLIC_FILE_NAME, 0 /*mode*/);
         DataOutputStream dataOut = new DataOutputStream(outputStream);
         dataOut.writeInt(getContext().getApplicationInfo().uid);
         dataOut.close();
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java
index 69583a7..acba1f4 100644
--- a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java
+++ b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java
@@ -16,58 +16,20 @@
 
 package com.android.cts.documentclient;
 
-import static android.os.Environment.DIRECTORY_ALARMS;
-import static android.os.Environment.DIRECTORY_DCIM;
-import static android.os.Environment.DIRECTORY_DOCUMENTS;
-import static android.os.Environment.DIRECTORY_DOWNLOADS;
-import static android.os.Environment.DIRECTORY_MOVIES;
-import static android.os.Environment.DIRECTORY_MUSIC;
-import static android.os.Environment.DIRECTORY_NOTIFICATIONS;
-import static android.os.Environment.DIRECTORY_PICTURES;
-import static android.os.Environment.DIRECTORY_PODCASTS;
-import static android.os.Environment.DIRECTORY_RINGTONES;
-import static android.os.Environment.getExternalStorageDirectory;
-import static android.test.MoreAsserts.assertContainsRegex;
-import static android.test.MoreAsserts.assertNotEqual;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import android.app.Activity;
-import android.app.ActivityManager;
-import android.app.Instrumentation;
 import android.content.ContentResolver;
-import android.content.Context;
 import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.res.AssetFileDescriptor.AutoCloseInputStream;
-import android.content.res.AssetFileDescriptor;
 import android.database.Cursor;
 import android.net.Uri;
-import android.os.Environment;
 import android.os.SystemClock;
-import android.os.storage.StorageManager;
-import android.os.storage.StorageVolume;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Document;
 import android.provider.DocumentsProvider;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.Configurator;
-import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject;
 import android.support.test.uiautomator.UiObjectNotFoundException;
 import android.support.test.uiautomator.UiScrollable;
 import android.support.test.uiautomator.UiSelector;
-import android.support.test.uiautomator.Until;
-import android.test.InstrumentationTestCase;
 import android.test.MoreAsserts;
-import android.text.format.DateUtils;
 import android.util.Log;
-import android.view.MotionEvent;
 
 import com.android.cts.documentclient.MyActivity.Result;
 
@@ -75,47 +37,9 @@
  * Tests for {@link DocumentsProvider} and interaction with platform intents
  * like {@link Intent#ACTION_OPEN_DOCUMENT}.
  */
-public class DocumentsClientTest extends InstrumentationTestCase {
+public class DocumentsClientTest extends DocumentsClientTestCase {
     private static final String TAG = "DocumentsClientTest";
 
-    private UiDevice mDevice;
-    private MyActivity mActivity;
-
-    private static final long TIMEOUT = 30 * DateUtils.SECOND_IN_MILLIS;
-
-    private static final int REQUEST_CODE = 42;
-
-    private static final String[] STANDARD_DIRECTORIES = {
-        DIRECTORY_MUSIC,
-        DIRECTORY_PODCASTS,
-        DIRECTORY_RINGTONES,
-        DIRECTORY_ALARMS,
-        DIRECTORY_NOTIFICATIONS,
-        DIRECTORY_PICTURES,
-        DIRECTORY_MOVIES,
-        DIRECTORY_DOWNLOADS,
-        DIRECTORY_DCIM,
-        DIRECTORY_DOCUMENTS
-    };
-
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-
-        Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_FINGER);
-
-        mDevice = UiDevice.getInstance(getInstrumentation());
-        mActivity = launchActivity(getInstrumentation().getTargetContext().getPackageName(),
-                MyActivity.class, null);
-        mDevice.waitForIdle();
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        super.tearDown();
-        mActivity.finish();
-    }
-
     private UiObject findRoot(String label) throws UiObjectNotFoundException {
         final UiSelector rootsList = new UiSelector().resourceId(
                 "com.android.documentsui:id/container_roots").childSelector(
@@ -370,116 +294,6 @@
         }
     }
 
-    public void testOpenExternalDirectory_invalidPath() throws Exception {
-        if (!supportedHardware()) return;
-
-        for (StorageVolume volume : getVolumes()) {
-            openExternalDirectoryInvalidPath(volume, "");
-            openExternalDirectoryInvalidPath(volume, "/dev/null");
-            openExternalDirectoryInvalidPath(volume, "/../");
-            openExternalDirectoryInvalidPath(volume, "/HiddenStuff");
-        }
-    }
-
-    public void testOpenExternalDirectory_userRejects() throws Exception {
-        if (!supportedHardware()) return;
-
-        final String externalRoot = getExternalStorageDirectory().getPath();
-
-        final StorageVolume primaryVolume = getPrimaryVolume();
-
-        // Tests user clicking DENY button, for all valid directories.
-        for (String directory : STANDARD_DIRECTORIES) {
-            final Uri uri = Uri.fromFile(new File(externalRoot, directory));
-
-            final UiAlertDialog dialog = openExternalDirectoryValidPath(primaryVolume, directory);
-            dialog.noButton.click();
-            assertActivityFailed();
-        }
-
-        // Also test user clicking back button - one directory is enough.
-        openExternalDirectoryValidPath(primaryVolume, DIRECTORY_PICTURES);
-        mDevice.pressBack();
-        assertActivityFailed();
-    }
-
-    public void testOpenExternalDirectory_userAccepts() throws Exception {
-        if (!supportedHardware())
-            return;
-
-        for (StorageVolume volume : getVolumes()) {
-            userAcceptsOpenExternalDirectoryTest(volume, DIRECTORY_PICTURES);
-        }
-    }
-
-    public void testOpenExternalDirectory_notAskedAgain() throws Exception {
-        if (!supportedHardware())
-            return;
-
-        final StorageVolume volume = getPrimaryVolume();
-        final Uri grantedUri = userAcceptsOpenExternalDirectoryTest(volume, DIRECTORY_PICTURES);
-
-        // Calls it again - since the permission has been granted, it should return right away,
-        // without popping up the permissions dialog.
-        sendOpenExternalDirectoryIntent(volume, DIRECTORY_PICTURES);
-        final Intent newData = assertActivitySucceeded();
-        assertEquals(grantedUri, newData.getData());
-
-        // Make sure other directories still require user permission.
-        final Uri grantedUri2 = userAcceptsOpenExternalDirectoryTest(volume, DIRECTORY_ALARMS);
-        assertNotEqual(grantedUri, grantedUri2);
-    }
-
-    private Uri userAcceptsOpenExternalDirectoryTest(StorageVolume volume, String directoryName)
-            throws Exception {
-        // Asserts dialog contain the proper message.
-        final UiAlertDialog dialog = openExternalDirectoryValidPath(volume, directoryName);
-        final String message = dialog.messageText.getText();
-        Log.v(TAG, "request permission message: " + message);
-        final Context context = getInstrumentation().getTargetContext();
-        final String appLabel = context.getPackageManager().getApplicationLabel(
-                context.getApplicationInfo()).toString();
-        assertContainsRegex("missing app label", appLabel, message);
-        assertContainsRegex("missing folder", directoryName, message);
-        assertContainsRegex("missing root", volume.getDescription(context), message);
-
-        // Call API...
-        dialog.yesButton.click();
-
-        // ...and get its response.
-        final Intent data = assertActivitySucceeded();
-        final Uri grantedUri = data.getData();
-
-        // Test granted permission directly by persisting it...
-        final ContentResolver resolver = getInstrumentation().getContext().getContentResolver();
-        final int modeFlags = data.getFlags()
-                & (Intent.FLAG_GRANT_READ_URI_PERMISSION
-                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-        resolver.takePersistableUriPermission(grantedUri, modeFlags);
-
-        // ...and indirectly by creating some documents
-        final Uri doc = DocumentsContract.buildDocumentUriUsingTree(grantedUri,
-                DocumentsContract.getTreeDocumentId(grantedUri));
-        assertNotNull("could not get tree URI", doc);
-        final Uri pic = DocumentsContract.createDocument(resolver, doc, "image/png", "pic.png");
-        assertNotNull("could not create file (pic.png) on tree root", pic);
-        final Uri dir = DocumentsContract.createDocument(resolver, doc, Document.MIME_TYPE_DIR,
-                "my dir");
-        assertNotNull("could not create child dir (my dir)", pic);
-        final Uri dirPic = DocumentsContract.createDocument(resolver, dir, "image/png", "pic2.png");
-        assertNotNull("could not create file (pic.png) on child dir (my dir)", dirPic);
-
-        writeFully(pic, "pic".getBytes());
-        writeFully(dirPic, "dirPic".getBytes());
-
-        // Clean up created documents.
-        assertTrue("delete", DocumentsContract.deleteDocument(resolver, pic));
-        assertTrue("delete", DocumentsContract.deleteDocument(resolver, dirPic));
-        assertTrue("delete", DocumentsContract.deleteDocument(resolver, dir));
-
-        return grantedUri;
-    }
-
     public void testGetContent() throws Exception {
         if (!supportedHardware()) return;
 
@@ -614,126 +428,4 @@
             cursorDst.close();
         }
     }
-
-    private String getColumn(Uri uri, String column) {
-        final ContentResolver resolver = getInstrumentation().getContext().getContentResolver();
-        final Cursor cursor = resolver.query(uri, new String[] { column }, null, null, null);
-        try {
-            assertTrue(cursor.moveToFirst());
-            return cursor.getString(0);
-        } finally {
-            cursor.close();
-        }
-    }
-
-    private byte[] readFully(Uri uri) throws IOException {
-        final InputStream in = getInstrumentation().getContext().getContentResolver()
-                .openInputStream(uri);
-        return readFully(in);
-    }
-
-    private byte[] readTypedFully(Uri uri, String mimeType) throws IOException {
-        final AssetFileDescriptor descriptor =
-                getInstrumentation().getContext().getContentResolver()
-                        .openTypedAssetFileDescriptor(uri, mimeType, null, null);
-        try (AutoCloseInputStream in = new AutoCloseInputStream(descriptor)) {
-            return readFully(in);
-        }
-    }
-
-    private byte[] readFully(InputStream in) throws IOException {
-        try {
-            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
-            byte[] buffer = new byte[1024];
-            int count;
-            while ((count = in.read(buffer)) != -1) {
-                bytes.write(buffer, 0, count);
-            }
-            return bytes.toByteArray();
-        } finally {
-            in.close();
-        }
-    }
-
-    private void writeFully(Uri uri, byte[] data) throws IOException {
-        OutputStream out = getInstrumentation().getContext().getContentResolver()
-                .openOutputStream(uri);
-        try {
-            out.write(data);
-        } finally {
-            out.close();
-        }
-    }
-
-    private boolean supportedHardware() {
-        final PackageManager pm = getInstrumentation().getContext().getPackageManager();
-        if (pm.hasSystemFeature("android.hardware.type.television")
-                || pm.hasSystemFeature("android.hardware.type.watch")) {
-            return false;
-        }
-        return true;
-    }
-
-    private void assertActivityFailed() {
-        final Result result = mActivity.getResult();
-        assertEquals(REQUEST_CODE, result.requestCode);
-        assertEquals(Activity.RESULT_CANCELED, result.resultCode);
-        assertNull(result.data);
-    }
-
-    private Intent assertActivitySucceeded() {
-        final Result result = mActivity.getResult();
-        assertEquals(REQUEST_CODE, result.requestCode);
-        assertEquals(Activity.RESULT_OK, result.resultCode);
-        assertNotNull(result.data);
-        return result.data;
-    }
-
-    private void openExternalDirectoryInvalidPath(StorageVolume volume, String path) {
-        sendOpenExternalDirectoryIntent(volume, path);
-        assertActivityFailed();
-    }
-
-    private UiAlertDialog openExternalDirectoryValidPath(StorageVolume volume, String path)
-            throws UiObjectNotFoundException {
-        sendOpenExternalDirectoryIntent(volume, path);
-        return new UiAlertDialog();
-    }
-
-    private void sendOpenExternalDirectoryIntent(StorageVolume volume, String directoryName) {
-        final Intent intent = volume.createAccessIntent(directoryName);
-        mActivity.startActivityForResult(intent, REQUEST_CODE);
-        mDevice.waitForIdle();
-    }
-
-    private StorageVolume[] getVolumes() {
-        final StorageManager sm = (StorageManager)
-                getInstrumentation().getTargetContext().getSystemService(Context.STORAGE_SERVICE);
-        final StorageVolume[] volumes = sm.getVolumeList();
-        assertTrue("empty volumes", volumes.length > 0);
-        return volumes;
-    }
-
-    private StorageVolume getPrimaryVolume() {
-        final StorageManager sm = (StorageManager)
-                getInstrumentation().getTargetContext().getSystemService(Context.STORAGE_SERVICE);
-        return sm.getPrimaryVolume();
-    }
-
-    private final class UiAlertDialog {
-        final UiObject messageText;
-        final UiObject yesButton;
-        final UiObject noButton;
-
-        UiAlertDialog() throws UiObjectNotFoundException {
-            final String id = "android:id/parentPanel";
-            boolean gotIt = mDevice.wait(Until.hasObject(By.res(id)), TIMEOUT);
-            assertTrue("object with id '(" + id + "') not visible yet", gotIt);
-            final UiObject dialog = mDevice.findObject(new UiSelector().resourceId(id));
-            assertTrue("object with id '(" + id + "') doesn't exist", dialog.exists());
-            messageText = dialog.getChild(new UiSelector().resourceId("android:id/message"));
-            yesButton = dialog.getChild(new UiSelector().resourceId("android:id/button1"));
-            noButton  = dialog.getChild(new UiSelector().resourceId("android:id/button2"));
-        }
-    }
 }
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTestCase.java b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTestCase.java
new file mode 100644
index 0000000..cb7dc48
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTestCase.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.documentclient;
+
+import static android.cts.util.SystemUtil.runShellCommand;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import com.android.cts.documentclient.MyActivity.Result;
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.AssetFileDescriptor.AutoCloseInputStream;
+import android.database.Cursor;
+import android.net.Uri;
+import android.support.test.uiautomator.Configurator;
+import android.support.test.uiautomator.UiDevice;
+import android.test.InstrumentationTestCase;
+import android.text.format.DateUtils;
+import android.util.Log;
+import android.view.MotionEvent;
+
+/**
+ * Base class for DocumentsUI test cases.
+ */
+abstract class DocumentsClientTestCase extends InstrumentationTestCase {
+    private static final String TAG = "DocumentsClientTestCase";
+
+    protected UiDevice mDevice;
+    protected MyActivity mActivity;
+
+    protected static final long TIMEOUT = 30 * DateUtils.SECOND_IN_MILLIS;
+    protected static final int REQUEST_CODE = 42;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_FINGER);
+
+        mDevice = UiDevice.getInstance(getInstrumentation());
+        mActivity = launchActivity(getInstrumentation().getTargetContext().getPackageName(),
+                MyActivity.class, null);
+        mDevice.waitForIdle();
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        super.tearDown();
+        mActivity.finish();
+    }
+
+    protected String getColumn(Uri uri, String column) {
+        final ContentResolver resolver = getInstrumentation().getContext().getContentResolver();
+        final Cursor cursor = resolver.query(uri, new String[] { column }, null, null, null);
+        try {
+            assertTrue(cursor.moveToFirst());
+            return cursor.getString(0);
+        } finally {
+            cursor.close();
+        }
+    }
+
+    protected byte[] readFully(Uri uri) throws IOException {
+        final InputStream in = getInstrumentation().getContext().getContentResolver()
+                .openInputStream(uri);
+        return readFully(in);
+    }
+
+    protected byte[] readTypedFully(Uri uri, String mimeType) throws IOException {
+        final AssetFileDescriptor descriptor =
+                getInstrumentation().getContext().getContentResolver()
+                        .openTypedAssetFileDescriptor(uri, mimeType, null, null);
+        try (AutoCloseInputStream in = new AutoCloseInputStream(descriptor)) {
+            return readFully(in);
+        }
+    }
+
+    protected byte[] readFully(InputStream in) throws IOException {
+        try {
+            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+            byte[] buffer = new byte[1024];
+            int count;
+            while ((count = in.read(buffer)) != -1) {
+                bytes.write(buffer, 0, count);
+            }
+            return bytes.toByteArray();
+        } finally {
+            in.close();
+        }
+    }
+
+    protected void writeFully(Uri uri, byte[] data) throws IOException {
+        OutputStream out = getInstrumentation().getContext().getContentResolver()
+                .openOutputStream(uri);
+        try {
+            out.write(data);
+        } finally {
+            out.close();
+        }
+    }
+
+    protected boolean supportedHardware() {
+        final PackageManager pm = getInstrumentation().getContext().getPackageManager();
+        if (pm.hasSystemFeature("android.hardware.type.television")
+                || pm.hasSystemFeature("android.hardware.type.watch")) {
+            return false;
+        }
+        return true;
+    }
+
+    protected void assertActivityFailed() {
+        final Result result = mActivity.getResult();
+        assertEquals(REQUEST_CODE, result.requestCode);
+        assertEquals(Activity.RESULT_CANCELED, result.resultCode);
+        assertNull(result.data);
+    }
+
+    protected Intent assertActivitySucceeded() {
+        final Result result = mActivity.getResult();
+        assertEquals(REQUEST_CODE, result.requestCode);
+        assertEquals(Activity.RESULT_OK, result.resultCode);
+        assertNotNull(result.data);
+        return result.data;
+    }
+
+    protected String executeShellCommand(String command) throws Exception {
+        final String result = runShellCommand(getInstrumentation(), command).trim();
+        Log.d(TAG, "Command '" + command + "' returned '" + result + "'");
+        return result;
+    }
+
+    protected void clearDocumentsUi() throws Exception {
+        executeShellCommand("pm clear com.android.documentsui");
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/ScopedDirectoryAccessClientTest.java b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/ScopedDirectoryAccessClientTest.java
new file mode 100644
index 0000000..3553bbf
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/ScopedDirectoryAccessClientTest.java
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.documentclient;
+
+import static android.os.Environment.DIRECTORY_ALARMS;
+import static android.os.Environment.DIRECTORY_DCIM;
+import static android.os.Environment.DIRECTORY_DOCUMENTS;
+import static android.os.Environment.DIRECTORY_DOWNLOADS;
+import static android.os.Environment.DIRECTORY_MOVIES;
+import static android.os.Environment.DIRECTORY_MUSIC;
+import static android.os.Environment.DIRECTORY_NOTIFICATIONS;
+import static android.os.Environment.DIRECTORY_PICTURES;
+import static android.os.Environment.DIRECTORY_PODCASTS;
+import static android.os.Environment.DIRECTORY_RINGTONES;
+import static android.test.MoreAsserts.assertContainsRegex;
+import static android.test.MoreAsserts.assertNotEqual;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.storage.StorageManager;
+import android.os.storage.StorageVolume;
+import android.provider.DocumentsContract;
+import android.provider.DocumentsContract.Document;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiObjectNotFoundException;
+import android.support.test.uiautomator.UiSelector;
+import android.support.test.uiautomator.Until;
+import android.util.Log;
+
+/**
+ * Set of tests that verify behavior of the Scoped Directory Access API.
+ */
+public class ScopedDirectoryAccessClientTest extends DocumentsClientTestCase {
+    private static final String TAG = "ScopedDirectoryAccessClientTest";
+
+    private static final String[] STANDARD_DIRECTORIES = {
+        DIRECTORY_MUSIC,
+        DIRECTORY_PODCASTS,
+        DIRECTORY_RINGTONES,
+        DIRECTORY_ALARMS,
+        DIRECTORY_NOTIFICATIONS,
+        DIRECTORY_PICTURES,
+        DIRECTORY_MOVIES,
+        DIRECTORY_DOWNLOADS,
+        DIRECTORY_DCIM,
+        DIRECTORY_DOCUMENTS
+    };
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        // DocumentsUI caches some info like whether a user rejects a request, so we need to clear
+        // its data before each test.
+        clearDocumentsUi();
+    }
+
+    public void testInvalidPath() throws Exception {
+        if (!supportedHardware()) return;
+
+        for (StorageVolume volume : getVolumes()) {
+            openExternalDirectoryInvalidPath(volume, "");
+            openExternalDirectoryInvalidPath(volume, "/dev/null");
+            openExternalDirectoryInvalidPath(volume, "/../");
+            openExternalDirectoryInvalidPath(volume, "/HiddenStuff");
+        }
+    }
+
+    public void testUserRejects() throws Exception {
+        if (!supportedHardware()) return;
+
+        final StorageVolume primaryVolume = getPrimaryVolume();
+
+        // Tests user clicking DENY button, for all valid directories.
+        for (String directory : STANDARD_DIRECTORIES) {
+            final UiAlertDialog dialog = openExternalDirectoryValidPath(primaryVolume, directory);
+            dialog.noButton.click();
+            assertActivityFailed();
+        }
+
+        // Also test user clicking back button - one directory is enough.
+        openExternalDirectoryValidPath(primaryVolume, DIRECTORY_PICTURES);
+        mDevice.pressBack();
+        assertActivityFailed();
+    }
+
+    public void testUserAccepts() throws Exception {
+        if (!supportedHardware()) return;
+
+        for (StorageVolume volume : getVolumes()) {
+            userAcceptsOpenExternalDirectoryTest(volume, DIRECTORY_PICTURES);
+        }
+    }
+
+    public void testUserAcceptsNewDirectory() throws Exception {
+        if (!supportedHardware()) return;
+
+        // TODO: figure out a better way to remove the directory.
+        final String command = "rm -rf /sdcard/" + DIRECTORY_PICTURES;
+        final String output = executeShellCommand(command);
+        if (!output.isEmpty()) {
+            fail("Command '" + command + "' failed: '" + output + "'");
+        }
+        userAcceptsOpenExternalDirectoryTest(getPrimaryVolume(), DIRECTORY_PICTURES);
+    }
+
+    public void testNotAskedAgain() throws Exception {
+        if (!supportedHardware()) return;
+
+        final StorageVolume volume = getPrimaryVolume();
+        final Uri grantedUri = userAcceptsOpenExternalDirectoryTest(volume, DIRECTORY_PICTURES);
+
+        // Calls it again - since the permission has been granted, it should return right away,
+        // without popping up the permissions dialog.
+        sendOpenExternalDirectoryIntent(volume, DIRECTORY_PICTURES);
+        final Intent newData = assertActivitySucceeded();
+        assertEquals(grantedUri, newData.getData());
+
+        // Make sure other directories still require user permission.
+        final Uri grantedUri2 = userAcceptsOpenExternalDirectoryTest(volume, DIRECTORY_ALARMS);
+        assertNotEqual(grantedUri, grantedUri2);
+    }
+
+    public void testDeniesOnceButAllowsAskingAgain() throws Exception {
+        if (!supportedHardware())return;
+
+        for (StorageVolume volume : getVolumes()) {
+            // Rejects the first attempt...
+            UiAlertDialog dialog = openExternalDirectoryValidPath(volume, DIRECTORY_DCIM);
+            dialog.assertDoNotAskAgainVisibility(false);
+            dialog.noButton.click();
+            assertActivityFailed();
+
+            // ...and the second.
+            dialog = openExternalDirectoryValidPath(volume, DIRECTORY_DCIM);
+            dialog.assertDoNotAskAgainVisibility(true);
+            dialog.noButton.click();
+            assertActivityFailed();
+
+            // Third time is a charm...
+            userAcceptsOpenExternalDirectoryTest(volume, DIRECTORY_DCIM);
+        }
+    }
+
+    public void testDeniesOnceForAll() throws Exception {
+        if (!supportedHardware()) return;
+
+        for (StorageVolume volume : getVolumes()) {
+            // Rejects the first attempt...
+            UiAlertDialog dialog = openExternalDirectoryValidPath(volume, DIRECTORY_RINGTONES);
+            dialog.assertDoNotAskAgainVisibility(false);
+            dialog.noButton.click();
+            assertActivityFailed();
+
+            // ...and the second, checking the box
+            dialog = openExternalDirectoryValidPath(volume, DIRECTORY_RINGTONES);
+            UiObject checkbox = dialog.assertDoNotAskAgainVisibility(true);
+            assertTrue("checkbox should not be checkable", checkbox.isCheckable());
+            assertFalse("checkbox should not be checked", checkbox.isChecked());
+            checkbox.click();
+            assertTrue("checkbox should be checked", checkbox.isChecked()); // Sanity check
+            assertFalse("allow button should be disabled", dialog.yesButton.isEnabled());
+
+            dialog.noButton.click();
+            assertActivityFailed();
+
+            // Third strike out...
+            sendOpenExternalDirectoryIntent(volume, DIRECTORY_RINGTONES);
+            assertActivityFailed();
+        }
+    }
+
+    private Uri userAcceptsOpenExternalDirectoryTest(StorageVolume volume, String directoryName)
+            throws Exception {
+        // Asserts dialog contain the proper message.
+        final UiAlertDialog dialog = openExternalDirectoryValidPath(volume, directoryName);
+        final String message = dialog.messageText.getText();
+        Log.v(TAG, "request permission message: " + message);
+        final Context context = getInstrumentation().getTargetContext();
+        final String appLabel = context.getPackageManager().getApplicationLabel(
+                context.getApplicationInfo()).toString();
+        assertContainsRegex("missing app label", appLabel, message);
+        assertContainsRegex("missing folder", directoryName, message);
+        assertContainsRegex("missing root", volume.getDescription(context), message);
+
+        // Call API...
+        dialog.yesButton.click();
+
+        // ...and get its response.
+        final Intent data = assertActivitySucceeded();
+        final Uri grantedUri = data.getData();
+
+        // Test granted permission directly by persisting it...
+        final ContentResolver resolver = getInstrumentation().getContext().getContentResolver();
+        final int modeFlags = data.getFlags()
+                & (Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+        resolver.takePersistableUriPermission(grantedUri, modeFlags);
+
+        // ...and indirectly by creating some documents
+        final Uri doc = DocumentsContract.buildDocumentUriUsingTree(grantedUri,
+                DocumentsContract.getTreeDocumentId(grantedUri));
+        assertNotNull("could not get tree URI", doc);
+        final Uri pic = DocumentsContract.createDocument(resolver, doc, "image/png", "pic.png");
+        assertNotNull("could not create file (pic.png) on tree root", pic);
+        final Uri dir = DocumentsContract.createDocument(resolver, doc, Document.MIME_TYPE_DIR,
+                "my dir");
+        assertNotNull("could not create child dir (my dir)", pic);
+        final Uri dirPic = DocumentsContract.createDocument(resolver, dir, "image/png", "pic2.png");
+        assertNotNull("could not create file (pic.png) on child dir (my dir)", dirPic);
+
+        writeFully(pic, "pic".getBytes());
+        writeFully(dirPic, "dirPic".getBytes());
+
+        // Clean up created documents.
+        assertTrue("delete", DocumentsContract.deleteDocument(resolver, pic));
+        assertTrue("delete", DocumentsContract.deleteDocument(resolver, dirPic));
+        assertTrue("delete", DocumentsContract.deleteDocument(resolver, dir));
+
+        return grantedUri;
+    }
+
+    private void openExternalDirectoryInvalidPath(StorageVolume volume, String path) {
+        sendOpenExternalDirectoryIntent(volume, path);
+        assertActivityFailed();
+    }
+
+    private UiAlertDialog openExternalDirectoryValidPath(StorageVolume volume, String path)
+            throws UiObjectNotFoundException {
+        sendOpenExternalDirectoryIntent(volume, path);
+        return new UiAlertDialog();
+    }
+
+    private void sendOpenExternalDirectoryIntent(StorageVolume volume, String directoryName) {
+        final Intent intent = volume.createAccessIntent(directoryName);
+        mActivity.startActivityForResult(intent, REQUEST_CODE);
+        mDevice.waitForIdle();
+    }
+
+    private StorageVolume[] getVolumes() {
+        final StorageManager sm = (StorageManager)
+                getInstrumentation().getTargetContext().getSystemService(Context.STORAGE_SERVICE);
+        final StorageVolume[] volumes = sm.getVolumeList();
+        assertTrue("empty volumes", volumes.length > 0);
+        return volumes;
+    }
+
+    private StorageVolume getPrimaryVolume() {
+        final StorageManager sm = (StorageManager)
+                getInstrumentation().getTargetContext().getSystemService(Context.STORAGE_SERVICE);
+        return sm.getPrimaryVolume();
+    }
+
+    private final class UiAlertDialog {
+        final UiObject dialog;
+        final UiObject messageText;
+        final UiObject yesButton;
+        final UiObject noButton;
+
+        UiAlertDialog() throws UiObjectNotFoundException {
+            final String id = "android:id/parentPanel";
+            boolean gotIt = mDevice.wait(Until.hasObject(By.res(id)), TIMEOUT);
+            assertTrue("object with id '(" + id + "') not visible yet", gotIt);
+            dialog = mDevice.findObject(new UiSelector().resourceId(id));
+            assertTrue("object with id '(" + id + "') doesn't exist", dialog.exists());
+            messageText = dialog.getChild(
+                    new UiSelector().resourceId("com.android.documentsui:id/message"));
+            yesButton = dialog.getChild(new UiSelector().resourceId("android:id/button1"));
+            noButton  = dialog.getChild(new UiSelector().resourceId("android:id/button2"));
+        }
+
+        private UiObject getDoNotAskAgainCheckBox() throws UiObjectNotFoundException {
+            return dialog.getChild(
+                    new UiSelector().resourceId("com.android.documentsui:id/do_not_ask_checkbox"));
+        }
+
+        UiObject assertDoNotAskAgainVisibility(boolean expectVisible) {
+            UiObject checkbox = null;
+            try {
+                checkbox = getDoNotAskAgainCheckBox();
+                assertEquals("Wrong value for 'DoNotAskAgain.exists()",
+                        expectVisible, checkbox.exists());
+            } catch (UiObjectNotFoundException e) {
+                if (expectVisible) {
+                    fail("'Do Not Ask Again' not found");
+                }
+            }
+            return checkbox;
+        }
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/EncryptionApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/EncryptionApp/AndroidManifest.xml
index 824e285..b42414c 100644
--- a/hostsidetests/appsecurity/test-apps/EncryptionApp/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/EncryptionApp/AndroidManifest.xml
@@ -32,20 +32,20 @@
                 android:exported="true" />
 
         <activity android:name=".AwareActivity"
-                android:encryptionAware="true"
+                android:directBootAware="true"
                 android:exported="true" />
 
         <receiver android:name=".AwareReceiver"
-                android:encryptionAware="true"
+                android:directBootAware="true"
                 android:exported="true" />
 
         <service android:name=".AwareService"
-                android:encryptionAware="true"
+                android:directBootAware="true"
                 android:exported="true" />
 
         <provider android:name=".AwareProvider"
                 android:authorities="com.android.cts.encryptionapp.aware"
-                android:encryptionAware="true"
+                android:directBootAware="true"
                 android:exported="true" />
 
         <uses-library android:name="android.test.runner" />
diff --git a/hostsidetests/appsecurity/test-apps/TargetInstrumentationApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/TargetInstrumentationApp/AndroidManifest.xml
index c51444d..8b15f1f 100644
--- a/hostsidetests/appsecurity/test-apps/TargetInstrumentationApp/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/TargetInstrumentationApp/AndroidManifest.xml
@@ -20,5 +20,6 @@
     A simple app used to test that instrumentation cannot target an app signed with a different
     certificate.
     -->
+    <application />
 
 </manifest>
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ApplicationRestrictionsTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ApplicationRestrictionsTest.java
index 923fc44..9ecc339 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ApplicationRestrictionsTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ApplicationRestrictionsTest.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.os.UserManager;
@@ -183,13 +184,13 @@
         }
     }
 
-    public void testSetApplicationRestrictionsManagingPackage() {
+    public void testSetApplicationRestrictionsManagingPackage() throws NameNotFoundException {
         final String previousValue = mDevicePolicyManager.getApplicationRestrictionsManagingPackage(
                 ADMIN_RECEIVER_COMPONENT);
         try {
             mDevicePolicyManager.setApplicationRestrictionsManagingPackage(
-                    ADMIN_RECEIVER_COMPONENT, OTHER_PACKAGE);
-            assertEquals(OTHER_PACKAGE,
+                    ADMIN_RECEIVER_COMPONENT, APP_RESTRICTIONS_TARGET_PKG);
+            assertEquals(APP_RESTRICTIONS_TARGET_PKG,
                     mDevicePolicyManager.getApplicationRestrictionsManagingPackage(
                             ADMIN_RECEIVER_COMPONENT));
             mDevicePolicyManager.setApplicationRestrictionsManagingPackage(
@@ -205,6 +206,22 @@
         }
     }
 
+    public void testSetApplicationRestrictionsManagingPackageForNotInstalledPackage()
+            throws NameNotFoundException {
+        try {
+            mDevicePolicyManager.setApplicationRestrictionsManagingPackage(ADMIN_RECEIVER_COMPONENT,
+                    OTHER_PACKAGE);
+            fail("Not throwing exception for not installed package name");
+        } catch (NameNotFoundException expected) {
+            MoreAsserts.assertContainsRegex(OTHER_PACKAGE, expected.getMessage());
+        } finally {
+            mDevicePolicyManager.setApplicationRestrictionsManagingPackage(ADMIN_RECEIVER_COMPONENT,
+                    null);
+            assertNull(mDevicePolicyManager.getApplicationRestrictionsManagingPackage(
+                    ADMIN_RECEIVER_COMPONENT));
+        }
+    }
+
     // Should be consistent with assertBundle0
     private static Bundle createBundle0() {
         Bundle result = new Bundle();
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SetPolicyActivity.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SetPolicyActivity.java
index 890daa3..aaa017b 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SetPolicyActivity.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SetPolicyActivity.java
@@ -19,6 +19,7 @@
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.os.Bundle;
 import android.os.Process;
 import android.util.Log;
@@ -94,8 +95,12 @@
                     + " for user " + Process.myUserHandle());
         } else if (COMMAND_SET_APP_RESTRICTIONS_MANAGER.equals(command)) {
             String packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME);
-            dpm.setApplicationRestrictionsManagingPackage(
-                    BaseDeviceAdminTest.ADMIN_RECEIVER_COMPONENT, packageName);
+            try {
+                dpm.setApplicationRestrictionsManagingPackage(
+                        BaseDeviceAdminTest.ADMIN_RECEIVER_COMPONENT, packageName);
+            } catch (NameNotFoundException e) {
+                throw new IllegalArgumentException(e);
+            }
             Log.i(TAG, "Setting the application restrictions managing package to " + packageName);
         } else {
             Log.e(TAG, "Invalid command: " + command);
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CreateAndManageUserTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CreateAndManageUserTest.java
index 91663c7..391ef15 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CreateAndManageUserTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CreateAndManageUserTest.java
@@ -16,6 +16,7 @@
 
 package com.android.cts.deviceowner;
 
+import android.app.ActivityManager;
 import android.app.admin.DeviceAdminReceiver;
 import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
@@ -46,6 +47,7 @@
     private static final int BROADCAST_TIMEOUT = 15_000;
     private static final int USER_SWITCH_DELAY = 10_000;
     private PackageManager mPackageManager;
+    private ActivityManager mActivityManager;
     private volatile boolean mReceived;
     private volatile boolean mTestProfileOwnerWasUsed;
     private volatile boolean mSetupComplete;
@@ -55,6 +57,7 @@
     protected void setUp() throws Exception {
         super.setUp();
         mPackageManager = mContext.getPackageManager();
+        mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
     }
 
     @Override
@@ -241,7 +244,11 @@
     }
 
     public void testCreateAndManageUser_DontSkipSetupWizard() {
-        createAndManageUserTest(0);
+        if (!mActivityManager.isRunningInTestHarness()) {
+            // In test harness, the setup wizard will be disabled by default, so this test is always
+            // failing.
+            createAndManageUserTest(0);
+        }
     }
 
     // createAndManageUser should circumvent the DISALLOW_ADD_USER restriction
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DeviceLoggingTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DeviceLoggingTest.java
deleted file mode 100644
index 642915f..0000000
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DeviceLoggingTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.cts.deviceowner;
-
-import android.auditing.SecurityLog.SecurityEvent;
-import android.os.UserHandle;
-
-import java.util.List;
-
-public class DeviceLoggingTest extends BaseDeviceOwnerTest {
-
-    private static final String MESSAGE_ONLY_ONE_MANAGED_USER_ALLOWED =
-            "There should only be one user, managed by Device Owner";
-
-    /**
-     * Test: setting device logging can only be done if there's one user on the device.
-     */
-    public void testSetDeviceLoggingEnabledNotPossibleIfMoreThanOneUserPresent() {
-        try {
-            mDevicePolicyManager.setDeviceLoggingEnabled(getWho(), true);
-            fail("did not throw expected SecurityException");
-        } catch (SecurityException e) {
-            assertEquals(e.getMessage(), MESSAGE_ONLY_ONE_MANAGED_USER_ALLOWED);
-        }
-    }
-
-    /**
-     * Test: retrieving device logs can only be done if there's one user on the device.
-     */
-    public void testRetrievingDeviceLogsNotPossibleIfMoreThanOneUserPresent() {
-        try {
-            mDevicePolicyManager.retrieveDeviceLogs(getWho());
-            fail("did not throw expected SecurityException");
-        } catch (SecurityException e) {
-            assertEquals(e.getMessage(), MESSAGE_ONLY_ONE_MANAGED_USER_ALLOWED);
-        }
-    }
-
-    /**
-     * Test: retrieving previous device logs can only be done if there's one user on the device.
-     */
-    public void testRetrievingPreviousDeviceLogsNotPossibleIfMoreThanOneUserPresent() {
-        try {
-            mDevicePolicyManager.retrievePreviousDeviceLogs(getWho());
-            fail("did not throw expected SecurityException");
-        } catch (SecurityException e) {
-            assertEquals(e.getMessage(), MESSAGE_ONLY_ONE_MANAGED_USER_ALLOWED);
-        }
-    }
-
-    /**
-     * Test: retrieving device logs should be rate limited - subsequent attempts should return null.
-     * TODO(mkarpinski): consider how we can test that the rate limiting is set to 2 hours.
-     */
-    public void testRetrievingDeviceLogsNotPossibleImmediatelyAfterPreviousSuccessfulRetrieval() {
-        List<SecurityEvent> logs = mDevicePolicyManager.retrieveDeviceLogs(getWho());
-        // if logs is null it means that that attempt was rate limited => test PASS
-        if (logs != null) {
-            assertNull(mDevicePolicyManager.retrieveDeviceLogs(getWho()));
-            assertNull(mDevicePolicyManager.retrieveDeviceLogs(getWho()));
-        }
-    }
-}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/HardwarePropertiesManagerTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/HardwarePropertiesManagerTest.java
new file mode 100644
index 0000000..f61c796
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/HardwarePropertiesManagerTest.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.deviceowner;
+
+import android.content.Context;
+import android.os.CpuUsageInfo;
+import android.os.HardwarePropertiesManager;
+import android.os.SystemClock;
+
+import java.lang.Math;
+
+/**
+ * Test {@link HardwarePropertiesManager}
+ */
+public class HardwarePropertiesManagerTest extends BaseDeviceOwnerTest {
+    public static final int MAX_FAN_SPEED = 20000;
+    public static final int MAX_DEVICE_TEMPERATURE = 200;
+    public static final int MONITORING_ITERATION_NUMBER = 10;
+
+    // Time between checks in milliseconds.
+    public static final long SLEEP_TIME = 10;
+
+    private void checkFanSpeed(float speed) {
+        assertTrue(speed >= 0 && speed < MAX_FAN_SPEED);
+    }
+
+    private void checkDeviceTemp(float temp, float throttlingTemp, float shutdownTemp) {
+        // Check validity of current temperature.
+        assertTrue(Math.abs(temp) < MAX_DEVICE_TEMPERATURE
+                || temp == HardwarePropertiesManager.UNDEFINED_TEMPERATURE);
+
+        // Compare current temperature and shutdown threshold.
+        assertTrue(temp < shutdownTemp
+                || shutdownTemp == HardwarePropertiesManager.UNDEFINED_TEMPERATURE);
+        // Compare throttling and shutdown thresholds.
+        assertTrue(throttlingTemp < shutdownTemp
+                || throttlingTemp == HardwarePropertiesManager.UNDEFINED_TEMPERATURE
+                || shutdownTemp == HardwarePropertiesManager.UNDEFINED_TEMPERATURE);
+    }
+
+    private void checkCpuUsageInfo(CpuUsageInfo info) {
+        assertTrue(info == null || (info.getActive() >= 0 && info.getTotal() >= 0
+                && info.getTotal() >= info.getActive()));
+    }
+
+    private void checkFanSpeeds(float[] fanSpeeds) {
+        for (float speed : fanSpeeds) {
+            checkFanSpeed(speed);
+        }
+    }
+
+    private void checkTemps(float[] temps, float[] throttlingThresholds,
+            float[] shutdownThresholds) {
+        assertEquals(temps.length, throttlingThresholds.length);
+        assertEquals(temps.length, shutdownThresholds.length);
+        for (int i = 0; i < temps.length; ++i) {
+            checkDeviceTemp(temps[i], throttlingThresholds[i], shutdownThresholds[i]);
+        }
+    }
+
+    private void checkCpuUsages(CpuUsageInfo[] cpuUsages) {
+        for (CpuUsageInfo info : cpuUsages) {
+            checkCpuUsageInfo(info);
+        }
+    }
+
+    // Check validity of new array of fan speeds:
+    // the number of fans should be the same.
+    private void checkFanSpeeds(float[] speeds, float[] oldSpeeds) {
+        assertEquals(speeds.length, oldSpeeds.length);
+    }
+
+    // Check validity of new array of cpu usages:
+    // The number of CPUs should be the same and total/active time should not decrease.
+    private void checkCpuUsages(CpuUsageInfo[] infos,
+            CpuUsageInfo[] oldInfos) {
+        assertEquals(infos.length, oldInfos.length);
+        for (int i = 0; i < infos.length; ++i) {
+            assertTrue(oldInfos[i] == null || infos[i] == null
+                    || (oldInfos[i].getActive() <= infos[i].getActive()
+                        && oldInfos[i].getTotal() <= infos[i].getTotal()));
+        }
+    }
+
+    /**
+     * test points:
+     * 1. Get fan speeds, device temperatures and CPU usage information.
+     * 2. Check for validity.
+     * 3. Sleep.
+     * 4. Do it 10 times and compare with old ones.
+     */
+    public void testHardwarePropertiesManager() throws InterruptedException,
+            SecurityException {
+        HardwarePropertiesManager hm = (HardwarePropertiesManager) getContext().getSystemService(
+                Context.HARDWARE_PROPERTIES_SERVICE);
+
+        float[] oldFanSpeeds = hm.getFanSpeeds();
+
+        float[] cpuTemps = hm.getDeviceTemperatures(
+                HardwarePropertiesManager.DEVICE_TEMPERATURE_CPU,
+                HardwarePropertiesManager.TEMPERATURE_CURRENT);
+        float[] cpuThrottlingThresholds = hm.getDeviceTemperatures(
+                HardwarePropertiesManager.DEVICE_TEMPERATURE_CPU,
+                HardwarePropertiesManager.TEMPERATURE_THROTTLING);
+        float[] cpuShutdownThresholds = hm.getDeviceTemperatures(
+                HardwarePropertiesManager.DEVICE_TEMPERATURE_CPU,
+                HardwarePropertiesManager.TEMPERATURE_SHUTDOWN);
+
+        float[] gpuTemps = hm.getDeviceTemperatures(
+                HardwarePropertiesManager.DEVICE_TEMPERATURE_GPU,
+                HardwarePropertiesManager.TEMPERATURE_CURRENT);
+        float[] gpuThrottlingThresholds = hm.getDeviceTemperatures(
+                HardwarePropertiesManager.DEVICE_TEMPERATURE_GPU,
+                HardwarePropertiesManager.TEMPERATURE_THROTTLING);
+        float[] gpuShutdownThresholds = hm.getDeviceTemperatures(
+                HardwarePropertiesManager.DEVICE_TEMPERATURE_GPU,
+                HardwarePropertiesManager.TEMPERATURE_SHUTDOWN);
+
+        float[] batteryTemps = hm.getDeviceTemperatures(
+                HardwarePropertiesManager.DEVICE_TEMPERATURE_BATTERY,
+                HardwarePropertiesManager.TEMPERATURE_CURRENT);
+        float[] batteryThrottlingThresholds = hm.getDeviceTemperatures(
+                HardwarePropertiesManager.DEVICE_TEMPERATURE_BATTERY,
+                HardwarePropertiesManager.TEMPERATURE_THROTTLING);
+        float[] batteryShutdownThresholds = hm.getDeviceTemperatures(
+                HardwarePropertiesManager.DEVICE_TEMPERATURE_BATTERY,
+                HardwarePropertiesManager.TEMPERATURE_SHUTDOWN);
+
+        float[] skinTemps = hm.getDeviceTemperatures(
+                HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN,
+                HardwarePropertiesManager.TEMPERATURE_CURRENT);
+        float[] skinThrottlingThresholds = hm.getDeviceTemperatures(
+                HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN,
+                HardwarePropertiesManager.TEMPERATURE_THROTTLING);
+        float[] skinShutdownThresholds = hm.getDeviceTemperatures(
+                HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN,
+                HardwarePropertiesManager.TEMPERATURE_SHUTDOWN);
+
+        CpuUsageInfo[] oldCpuUsages = hm.getCpuUsages();
+
+        checkFanSpeeds(oldFanSpeeds);
+        checkTemps(cpuTemps, cpuThrottlingThresholds, cpuShutdownThresholds);
+        checkTemps(gpuTemps, gpuThrottlingThresholds, gpuShutdownThresholds);
+        checkTemps(batteryTemps, batteryThrottlingThresholds, batteryShutdownThresholds);
+        checkTemps(skinTemps, skinThrottlingThresholds, skinShutdownThresholds);
+        checkCpuUsages(oldCpuUsages);
+
+        for (int i = 0; i < MONITORING_ITERATION_NUMBER; i++) {
+            Thread.sleep(SLEEP_TIME);
+
+            float[] fanSpeeds = hm.getFanSpeeds();
+            cpuTemps = hm.getDeviceTemperatures(
+                    HardwarePropertiesManager.DEVICE_TEMPERATURE_CPU,
+                    HardwarePropertiesManager.TEMPERATURE_CURRENT);
+            gpuTemps = hm.getDeviceTemperatures(
+                    HardwarePropertiesManager.DEVICE_TEMPERATURE_GPU,
+                    HardwarePropertiesManager.TEMPERATURE_CURRENT);
+            batteryTemps = hm.getDeviceTemperatures(
+                    HardwarePropertiesManager.DEVICE_TEMPERATURE_BATTERY,
+                    HardwarePropertiesManager.TEMPERATURE_CURRENT);
+            skinTemps = hm.getDeviceTemperatures(
+                    HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN,
+                    HardwarePropertiesManager.TEMPERATURE_CURRENT);
+            CpuUsageInfo[] cpuUsages = hm.getCpuUsages();
+
+            checkFanSpeeds(fanSpeeds);
+            checkTemps(cpuTemps, cpuThrottlingThresholds, cpuShutdownThresholds);
+            checkTemps(gpuTemps, gpuThrottlingThresholds, gpuShutdownThresholds);
+            checkTemps(batteryTemps, batteryThrottlingThresholds, batteryShutdownThresholds);
+            checkTemps(skinTemps, skinThrottlingThresholds, skinShutdownThresholds);
+            checkCpuUsages(cpuUsages);
+
+            // No need to compare length of old and new temperature arrays:
+            // they are compared through throttling and shutdown threshold arrays lengths.
+            checkFanSpeeds(fanSpeeds, oldFanSpeeds);
+            checkCpuUsages(cpuUsages, oldCpuUsages);
+
+            oldFanSpeeds = fanSpeeds;
+            oldCpuUsages = cpuUsages;
+        }
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/PreDeviceOwnerTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/PreDeviceOwnerTest.java
new file mode 100644
index 0000000..c70ed16
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/PreDeviceOwnerTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.deviceowner;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.test.AndroidTestCase;
+
+/**
+ * The following test can run in DeviceOwner mode or non-DeviceOwner mode.
+ * Don't inherit {@link BaseDeviceOwnerTest}
+ */
+public class PreDeviceOwnerTest extends AndroidTestCase {
+
+    protected DevicePolicyManager mDevicePolicyManager;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mDevicePolicyManager = (DevicePolicyManager)
+                mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+    }
+
+    public void testIsProvisioningAllowedFalse() {
+        assertFalse(mDevicePolicyManager.isProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE));
+    }
+
+    public void testIsProvisioningAllowedFalseForManagedProfileAction() {
+        assertFalse(mDevicePolicyManager
+                .isProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE));
+    }
+
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SecurityLoggingTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SecurityLoggingTest.java
new file mode 100644
index 0000000..0c1f421
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SecurityLoggingTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.deviceowner;
+
+import android.app.admin.SecurityLog.SecurityEvent;
+import android.os.UserHandle;
+
+import java.util.List;
+
+public class SecurityLoggingTest extends BaseDeviceOwnerTest {
+
+    private static final String MESSAGE_ONLY_ONE_MANAGED_USER_ALLOWED =
+            "There should only be one user, managed by Device Owner";
+
+    /**
+     * Test: setting security logging can only be done if there's one user on the device.
+     */
+    public void testSetSecurityLoggingEnabledNotPossibleIfMoreThanOneUserPresent() {
+        try {
+            mDevicePolicyManager.setSecurityLoggingEnabled(getWho(), true);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertEquals(e.getMessage(), MESSAGE_ONLY_ONE_MANAGED_USER_ALLOWED);
+        }
+    }
+
+    /**
+     * Test: retrieving security logs can only be done if there's one user on the device.
+     */
+    public void testRetrievingSecurityLogsNotPossibleIfMoreThanOneUserPresent() {
+        try {
+            mDevicePolicyManager.retrieveSecurityLogs(getWho());
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertEquals(e.getMessage(), MESSAGE_ONLY_ONE_MANAGED_USER_ALLOWED);
+        }
+    }
+
+    /**
+     * Test: retrieving previous security logs can only be done if there's one user on the device.
+     */
+    public void testRetrievingPreviousSecurityLogsNotPossibleIfMoreThanOneUserPresent() {
+        try {
+            mDevicePolicyManager.retrievePreRebootSecurityLogs(getWho());
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertEquals(e.getMessage(), MESSAGE_ONLY_ONE_MANAGED_USER_ALLOWED);
+        }
+    }
+
+    /**
+     * Test: retrieving security logs should be rate limited - subsequent attempts should return
+     * null.
+     */
+    public void testRetrievingSecurityLogsNotPossibleImmediatelyAfterPreviousSuccessfulRetrieval() {
+        List<SecurityEvent> logs = mDevicePolicyManager.retrieveSecurityLogs(getWho());
+        // if logs is null it means that that attempt was rate limited => test PASS
+        if (logs != null) {
+            assertNull(mDevicePolicyManager.retrieveSecurityLogs(getWho()));
+            assertNull(mDevicePolicyManager.retrieveSecurityLogs(getWho()));
+        }
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PreManagedProfileTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PreManagedProfileTest.java
new file mode 100644
index 0000000..99fd50d
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PreManagedProfileTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.managedprofile;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.test.AndroidTestCase;
+
+public class PreManagedProfileTest extends AndroidTestCase {
+
+    protected DevicePolicyManager mDevicePolicyManager;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mDevicePolicyManager = (DevicePolicyManager) mContext
+                .getSystemService(Context.DEVICE_POLICY_SERVICE);
+    }
+
+    public void testIsProvisioningAllowedTrue() {
+        assertTrue(mDevicePolicyManager
+                .isProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE));
+    }
+
+    public void testIsProvisioningAllowedFalse() {
+        assertFalse(mDevicePolicyManager
+                .isProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE));
+    }
+
+}
diff --git a/hostsidetests/devicepolicy/app/PackageInstaller/src/com/android/cts/packageinstaller/ManualPackageInstallTest.java b/hostsidetests/devicepolicy/app/PackageInstaller/src/com/android/cts/packageinstaller/ManualPackageInstallTest.java
index 96affae..1bb797f 100644
--- a/hostsidetests/devicepolicy/app/PackageInstaller/src/com/android/cts/packageinstaller/ManualPackageInstallTest.java
+++ b/hostsidetests/devicepolicy/app/PackageInstaller/src/com/android/cts/packageinstaller/ManualPackageInstallTest.java
@@ -33,11 +33,11 @@
     private static final BySelector POPUP_BUTTON_SELECTOR = By
             .clazz(android.widget.Button.class.getName())
             .res("android:id/button1")
-            .pkg("com.google.android.packageinstaller");
-    private static final BySelector POPUP_TEXT_SELECTOR = By
-            .clazz(android.widget.TextView.class.getName())
-            .res("android:id/alertTitle")
-            .pkg("com.google.android.packageinstaller");
+            .pkg("com.android.settings");
+    private static final BySelector POPUP_IMAGE_SELECTOR = By
+            .clazz(android.widget.ImageView.class.getName())
+            .res("com.android.settings:id/admin_support_icon")
+            .pkg("com.android.settings");
     private static final BySelector INSTALL_BUTTON_SELECTOR = By
             .clazz(android.widget.Button.class.getName())
             .res("com.android.packageinstaller:id/ok_button")
@@ -106,9 +106,9 @@
     }
 
     private void automateDismissInstallBlockedDialog() {
-        mDevice.wait(Until.hasObject(POPUP_TEXT_SELECTOR), AUTOMATOR_WAIT_TIMEOUT);
-        UiObject2 text = mDevice.findObject(POPUP_TEXT_SELECTOR);
-        assertNotNull("Alert dialog not found", text);
+        mDevice.wait(Until.hasObject(POPUP_IMAGE_SELECTOR), AUTOMATOR_WAIT_TIMEOUT);
+        UiObject2 icon = mDevice.findObject(POPUP_IMAGE_SELECTOR);
+        assertNotNull("Policy transparency dialog icon not found", icon);
         // "OK" button only present in the dialog if it is blocked by policy.
         UiObject2 button = mDevice.findObject(POPUP_BUTTON_SELECTOR);
         assertNotNull("OK button not found", button);
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index 60bbc55..3919dc3 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -61,6 +61,13 @@
     protected static final int FLAG_GUEST = 0x00000004;
     protected static final int FLAG_EPHEMERAL = 0x00000100;
 
+    protected static interface Settings {
+        public static final String GLOBAL_NAMESPACE = "global";
+        public static interface Global {
+            public static final String DEVICE_PROVISIONED = "device_provisioned";
+        }
+    }
+
     protected IBuildInfo mCtsBuild;
 
     private String mPackageVerifier;
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomDeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomDeviceOwnerTest.java
index 61ae4f3..23cdb5a 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomDeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomDeviceOwnerTest.java
@@ -16,6 +16,7 @@
 
 package com.android.cts.devicepolicy;
 
+import com.android.cts.devicepolicy.BaseDevicePolicyTest.Settings;
 import com.android.cts.migration.MigrationHelper;
 
 import java.io.File;
@@ -149,4 +150,18 @@
             getDevice().uninstallPackage(PACKAGE_INSTALLER_PKG);
         }
     }
+
+    public void testIsProvisioningAllowed() throws Exception {
+        // Must install the apk since the test runs in the DO apk.
+        installAppAsUser(DEVICE_OWNER_APK, mPrimaryUserId);
+        try {
+            // When CTS runs, setupwizard is complete. Expects it has to return false as DO can
+            // only be provisioned before setupwizard is completed.
+
+            assertTrue(runDeviceTestsAsUser(DEVICE_OWNER_PKG, ".PreDeviceOwnerTest",
+                    "testIsProvisioningAllowedFalse", /* deviceOwnerUserId */ 0));
+        } finally {
+            getDevice().uninstallPackage(DEVICE_OWNER_PKG);
+        }
+    }
 }
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomManagedProfileTest.java
new file mode 100644
index 0000000..53e9138
--- /dev/null
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomManagedProfileTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.devicepolicy;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+
+public class CustomManagedProfileTest extends BaseDevicePolicyTest {
+
+    private static final String MANAGED_PROFILE_PKG = "com.android.cts.managedprofile";
+    private static final String MANAGED_PROFILE_APK = "CtsManagedProfileApp.apk";
+
+    @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 && hasDeviceFeature("android.software.managed_users");
+    }
+
+    public void testIsProvisioningAllowed() throws Exception {
+        final int primaryUserId = getPrimaryUser();
+        // Must install the apk since the test runs in the ManagedProfile apk.
+        installAppAsUser(MANAGED_PROFILE_APK, mPrimaryUserId);
+        try {
+            if (mHasFeature) {
+                // Since we assume, in ManagedProfileTest, provisioning has to be successful,
+                // DevicePolicyManager.isProvisioningAllowed must return true
+                assertIsProvisioningAllowed(true, primaryUserId);
+            } else {
+                // Test the case when feature flag is off
+                assertIsProvisioningAllowed(false, primaryUserId);
+            }
+        } finally {
+            getDevice().uninstallPackage(MANAGED_PROFILE_PKG);
+        }
+    }
+
+    private void assertIsProvisioningAllowed(boolean expected, int userId)
+            throws DeviceNotAvailableException {
+        final String testName = expected ? "testIsProvisioningAllowedTrue"
+                : "testIsProvisioningAllowedFalse";
+        assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".PreManagedProfileTest", testName,
+                userId));
+    }
+}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index 6a22a5c..18ed0a6 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -291,27 +291,27 @@
         }
     }
 
-    public void testDeviceLoggingWithTwoUsers() throws Exception {
+    public void testSecurityLoggingWithTwoUsers() throws Exception {
         if (!mHasFeature || getMaxNumberOfUsersSupported() < 2) {
             return;
         }
         int userId = -1;
         try {
             userId = createUser();
-            executeDeviceTestMethod(".DeviceLoggingTest",
-                    "testSetDeviceLoggingEnabledNotPossibleIfMoreThanOneUserPresent");
-            executeDeviceTestMethod(".DeviceLoggingTest",
-                    "testRetrievingDeviceLogsNotPossibleIfMoreThanOneUserPresent");
-            executeDeviceTestMethod(".DeviceLoggingTest",
-                    "testRetrievingPreviousDeviceLogsNotPossibleIfMoreThanOneUserPresent");
+            executeDeviceTestMethod(".SecurityLoggingTest",
+                    "testSetSecurityLoggingEnabledNotPossibleIfMoreThanOneUserPresent");
+            executeDeviceTestMethod(".SecurityLoggingTest",
+                    "testRetrievingSecurityLogsNotPossibleIfMoreThanOneUserPresent");
+            executeDeviceTestMethod(".SecurityLoggingTest",
+                    "testRetrievingPreviousSecurityLogsNotPossibleIfMoreThanOneUserPresent");
         } finally {
             removeUser(userId);
         }
     }
 
-    public void testDeviceLoggingWithSingleUser() throws Exception {
-        executeDeviceTestMethod(".DeviceLoggingTest",
-                "testRetrievingDeviceLogsNotPossibleImmediatelyAfterPreviousSuccessfulRetrieval");
+    public void testSecurityLoggingWithSingleUser() throws Exception {
+        executeDeviceTestMethod(".SecurityLoggingTest",
+                "testRetrievingSecurityLogsNotPossibleImmediatelyAfterPreviousSuccessfulRetrieval");
     }
 
     public void testLockTask() throws Exception {
@@ -357,6 +357,26 @@
         }
     }
 
+    // Execute HardwarePropertiesManagerTest as a device owner.
+    public void testHardwarePropertiesManagerAsDeviceOwner() throws Exception {
+        if (!mHasFeature)
+            return;
+
+        executeDeviceTestMethod(".HardwarePropertiesManagerTest", "testHardwarePropertiesManager");
+    }
+
+    public void testIsManagedDeviceProvisioningAllowed() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        // This case runs when DO is provisioned
+        // mHasFeature == true and provisioned, can't provision DO again.
+        executeDeviceTestMethod(".PreDeviceOwnerTest", "testIsProvisioningAllowedFalse");
+        // Can't provision Managed Profile when DO is on
+        executeDeviceTestMethod(".PreDeviceOwnerTest",
+                "testIsProvisioningAllowedFalseForManagedProfileAction");
+    }
+
     private void executeDeviceOwnerTest(String testClassName) throws Exception {
         if (!mHasFeature) {
             return;
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
index 13fd921..8eaa606 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
@@ -591,6 +591,20 @@
         }
     }
 
+    public void testIsProvisioningAllowed() throws DeviceNotAvailableException {
+        if (!mHasFeature) {
+            return;
+        }
+        // In Managed profile user when managed profile is provisioned
+        assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".PreManagedProfileTest",
+                "testIsProvisioningAllowedFalse", mProfileUserId));
+
+        // In parent user when managed profile is provisioned
+        // It's allowed to provision again by removing the previous profile
+        assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".PreManagedProfileTest",
+                "testIsProvisioningAllowedTrue", mParentUserId));
+    }
+
     private void setDirectoryPrefix(String directoryName, int userId)
             throws DeviceNotAvailableException {
         String command = "content call --uri " + DIRECTORY_PRIVOIDER_URI
diff --git a/hostsidetests/net/AndroidTest.xml b/hostsidetests/net/AndroidTest.xml
index 4b6994a..9945805 100644
--- a/hostsidetests/net/AndroidTest.xml
+++ b/hostsidetests/net/AndroidTest.xml
@@ -16,5 +16,6 @@
 <configuration description="Config for CTS net host test cases">
     <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
         <option name="jar" value="CtsHostsideNetworkTests.jar" />
+        <option name="runtime-hint" value="3m56s" />
     </test>
 </configuration>
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
index def3439..adaaf84 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
@@ -221,7 +221,7 @@
             if (result.equals(expectedResult))
                 return;
             Log.v(TAG, "Command '" + command + "' returned '" + result + " instead of '"
-                    + expectedResult + "' on attempt #; sleeping 1s before polling again");
+                    + expectedResult + "' on attempt #" + i + "; sleeping 1s before trying again");
             Thread.sleep(SECOND_IN_MS);
         }
         fail("Command '" + command + "' did not return '" + expectedResult + "' after " + maxTries
@@ -253,13 +253,12 @@
 
         Log.i(TAG, "Setting wi-fi network " + netId + " metered status to " + metered);
         final String setCommand = "cmd netpolicy set metered-network " + netId + " " + metered;
-        final String result = executeShellCommand(setCommand);
-        assertTrue("Command '" + setCommand + "' failed: " + result, result.isEmpty());
+        assertDelayedShellCommand(setCommand, "");
 
         // Sanity check.
-        final String newStatus = executeShellCommand("cmd netpolicy get metered-network " + netId);
-        assertEquals("Metered status of wi-fi network " + netId + " not set properly",
-                newStatus.trim(), Boolean.toString(metered));
+        final  String getCommand = "cmd netpolicy get metered-network " + netId;
+        assertDelayedShellCommand(getCommand, Boolean.toString(metered));
+
         return netId;
     }
 
diff --git a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
index 59b73f4..a18b82d 100644
--- a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
+++ b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
@@ -602,11 +602,6 @@
         assertDomainZeroOrOne("u:r:drmserver:s0", "/system/bin/drmserver");
     }
 
-    /* Media server is always running */
-    public void testMediaserverDomain() throws DeviceNotAvailableException {
-        assertDomainN("u:r:mediaserver:s0", "media.log", "/system/bin/mediaserver");
-    }
-
     /* Installd is always running */
     public void testInstalldDomain() throws DeviceNotAvailableException {
         assertDomainOne("u:r:installd:s0", "/system/bin/installd");
diff --git a/hostsidetests/services/activitymanager/AndroidTest.xml b/hostsidetests/services/activitymanager/AndroidTest.xml
index ce407a3..641fa09 100644
--- a/hostsidetests/services/activitymanager/AndroidTest.xml
+++ b/hostsidetests/services/activitymanager/AndroidTest.xml
@@ -20,5 +20,6 @@
     </target_preparer>
     <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
         <option name="jar" value="CtsServicesHostTestCases.jar" />
+        <option name="runtime-hint" value="4m7s" />
     </test>
 </configuration>
diff --git a/hostsidetests/services/activitymanager/app/AndroidManifest.xml b/hostsidetests/services/activitymanager/app/AndroidManifest.xml
index 8a2a448..39fb19f 100755
--- a/hostsidetests/services/activitymanager/app/AndroidManifest.xml
+++ b/hostsidetests/services/activitymanager/app/AndroidManifest.xml
@@ -24,6 +24,10 @@
                 android:resizeableActivity="true"
                 android:exported="true"
         />
+        <activity android:name=".NonResizeableActivity"
+                android:resizeableActivity="false"
+                android:exported="true"
+        />
         <activity android:name=".DockedActivity"
                 android:resizeableActivity="true"
                 android:exported="true"
diff --git a/hostsidetests/services/activitymanager/app/src/android/server/app/NonResizeableActivity.java b/hostsidetests/services/activitymanager/app/src/android/server/app/NonResizeableActivity.java
new file mode 100644
index 0000000..6312b47
--- /dev/null
+++ b/hostsidetests/services/activitymanager/app/src/android/server/app/NonResizeableActivity.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.app;
+
+public class NonResizeableActivity extends AbstractLifecycleLogActivity {
+
+     private static final String TAG = NonResizeableActivity.class.getSimpleName();
+
+    @Override
+    protected String getTag() {
+        return TAG;
+    }
+}
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityAndWindowManagersState.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityAndWindowManagersState.java
index e74ecdf..63e1dbe 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityAndWindowManagersState.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityAndWindowManagersState.java
@@ -61,6 +61,9 @@
                 retry = false;
             }
         } while (retry && retriesLeft-- > 0);
+
+        assertSanity();
+        assertValidBounds();
     }
 
     private boolean shouldRetry(String[] waitForActivitiesVisible) {
@@ -114,7 +117,7 @@
         assertTrue(msg, mWmState.containsStack(stackId));
     }
 
-    void assertDoesNotContainsStack(String msg, int stackId) throws Exception {
+    void assertDoesNotContainStack(String msg, int stackId) throws Exception {
         assertFalse(msg, mAmState.containsStack(stackId));
         assertFalse(msg, mWmState.containsStack(stackId));
     }
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerActivityVisiblityTests.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerActivityVisiblityTests.java
index e077f7e..877e53b 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerActivityVisiblityTests.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerActivityVisiblityTests.java
@@ -32,7 +32,6 @@
         mDevice.executeShellCommand(AM_START_HOME_ACTIVITY_COMMAND);
 
         mAmWmState.computeState(mDevice, new String[] {VISIBLE_BEHIND_ACTIVITY});
-        mAmWmState.assertSanity();
         mAmWmState.assertContainsStack(
                 "Must contain fullscreen stack.", FULLSCREEN_WORKSPACE_STACK_ID);
         mAmWmState.assertFrontStack("Home stack must be the front stack.", HOME_STACK_ID);
@@ -46,7 +45,6 @@
 
         mAmWmState.computeState(mDevice,
                 new String[] {VISIBLE_BEHIND_ACTIVITY, TRANSLUCENT_ACTIVITY});
-        mAmWmState.assertSanity();
         mAmWmState.assertVisibility(VISIBLE_BEHIND_ACTIVITY, true);
         mAmWmState.assertVisibility(TRANSLUCENT_ACTIVITY, true);
     }
@@ -57,7 +55,6 @@
 
         mAmWmState.computeState(mDevice,
                 new String[] {VISIBLE_BEHIND_ACTIVITY, TRANSLUCENT_ACTIVITY});
-        mAmWmState.assertSanity();
         mAmWmState.assertVisibility(VISIBLE_BEHIND_ACTIVITY, true);
         mAmWmState.assertVisibility(TRANSLUCENT_ACTIVITY, true);
     }
@@ -73,7 +70,6 @@
         mDevice.executeShellCommand(AM_MOVE_TOP_ACTIVITY_TO_PINNED_STACK_COMMAND);
 
         mAmWmState.computeState(mDevice, new String[] {PIP_ON_PIP_ACTIVITY, TRANSLUCENT_ACTIVITY});
-        mAmWmState.assertSanity();
         mAmWmState.assertFrontStack("Pinned stack must be the front stack.", PINNED_STACK_ID);
         mAmWmState.assertVisibility(PIP_ON_PIP_ACTIVITY, true);
         mAmWmState.assertVisibility(TRANSLUCENT_ACTIVITY, true);
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
index 840fb7f..58a7ae6 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
@@ -17,12 +17,14 @@
 package android.server.cts;
 
 import java.awt.Rectangle;
+import java.util.ArrayList;
 
 import static com.android.ddmlib.Log.LogLevel.*;
 
 public class ActivityManagerDockedStackTests extends ActivityManagerTestBase {
 
     private static final String TEST_ACTIVITY_NAME = "TestActivity";
+    private static final String NON_RESIZEABLE_ACTIVITY_NAME = "NonResizeableActivity";
     private static final String DOCKED_ACTIVITY_NAME = "DockedActivity";
     private static final String LAUNCH_TO_SIDE_ACTIVITY_NAME = "LaunchToSideActivity";
     private static final String NO_RELAUNCH_ACTIVITY_NAME = "NoRelaunchActivity";
@@ -30,31 +32,38 @@
     private static final int TASK_SIZE = 600;
     private static final int STACK_SIZE = 300;
 
-    // TODO: Add test for non-resizeable activity.
-
     public void testStackList() throws Exception {
         mDevice.executeShellCommand(getAmStartCmd(TEST_ACTIVITY_NAME));
         mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
-        mAmWmState.assertSanity();
         mAmWmState.assertContainsStack("Must contain home stack.", HOME_STACK_ID);
         mAmWmState.assertContainsStack(
                 "Must contain fullscreen stack.", FULLSCREEN_WORKSPACE_STACK_ID);
+        mAmWmState.assertDoesNotContainStack("Must not contain docked stack.", DOCKED_STACK_ID);
     }
 
     public void testDockActivity() throws Exception {
         launchActivityInDockStack(TEST_ACTIVITY_NAME);
         mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
-        mAmWmState.assertSanity();
         mAmWmState.assertContainsStack("Must contain home stack.", HOME_STACK_ID);
         mAmWmState.assertContainsStack("Must contain docked stack.", DOCKED_STACK_ID);
     }
 
+    public void testNonResizeableNotDocked() throws Exception {
+        launchActivityInDockStack(NON_RESIZEABLE_ACTIVITY_NAME);
+        mAmWmState.computeState(mDevice, new String[] {NON_RESIZEABLE_ACTIVITY_NAME});
+
+        mAmWmState.assertContainsStack("Must contain home stack.", HOME_STACK_ID);
+        mAmWmState.assertDoesNotContainStack("Must not contain docked stack.", DOCKED_STACK_ID);
+        mAmWmState.assertFrontStack(
+                "Fullscreen stack must be front stack.", FULLSCREEN_WORKSPACE_STACK_ID);
+    }
+
     public void testLaunchToSide() throws Exception {
         launchActivityInDockStack(LAUNCH_TO_SIDE_ACTIVITY_NAME);
         printStacksAndTasks();
         launchActivityToSide(LAUNCH_TO_SIDE_ACTIVITY_NAME);
         mAmWmState.computeState(mDevice, new String[] {LAUNCH_TO_SIDE_ACTIVITY_NAME});
-        mAmWmState.assertSanity();
+
         mAmWmState.assertContainsStack(
                 "Must contain fullscreen stack.", FULLSCREEN_WORKSPACE_STACK_ID);
         mAmWmState.assertContainsStack("Must contain docked stack.", DOCKED_STACK_ID);
@@ -65,41 +74,32 @@
         launchActivityToSide(LAUNCH_TO_SIDE_ACTIVITY_NAME);
         final String[] waitForActivitiesVisible = new String[] {LAUNCH_TO_SIDE_ACTIVITY_NAME};
         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
-        mAmWmState.assertSanity();
         mAmWmState.assertContainsStack(
                 "Must contain fullscreen stack.", FULLSCREEN_WORKSPACE_STACK_ID);
         mAmWmState.assertContainsStack("Must contain docked stack.", DOCKED_STACK_ID);
 
-        // Rotate device single steps (90°) 0-1-2-3
+        // Rotate device single steps (90°) 0-1-2-3.
+        // Each time we compute the state we implicitly assert valid bounds.
         setDeviceRotation(0);
         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
-        mAmWmState.assertValidBounds();
         setDeviceRotation(1);
         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
-        mAmWmState.assertValidBounds();
         setDeviceRotation(2);
         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
-        mAmWmState.assertValidBounds();
         setDeviceRotation(3);
         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
-        mAmWmState.assertValidBounds();
         // Double steps (180°) We ended the single step at 3. So, we jump directly to 1 for double
         // step. So, we are testing 3-1-3 for one side and 0-2-0 for the other side.
         setDeviceRotation(1);
         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
-        mAmWmState.assertValidBounds();
         setDeviceRotation(3);
         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
-        mAmWmState.assertValidBounds();
         setDeviceRotation(0);
         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
-        mAmWmState.assertValidBounds();
         setDeviceRotation(2);
         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
-        mAmWmState.assertValidBounds();
         setDeviceRotation(0);
         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
-        mAmWmState.assertValidBounds();
     }
 
     public void testRotationWhenDockedWhileLocked() throws Exception {
@@ -116,25 +116,21 @@
         setDeviceRotation(0);
         unlockDevice();
         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
-        mAmWmState.assertValidBounds();
 
         lockDevice();
         setDeviceRotation(1);
         unlockDevice();
         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
-        mAmWmState.assertValidBounds();
 
         lockDevice();
         setDeviceRotation(2);
         unlockDevice();
         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
-        mAmWmState.assertValidBounds();
 
         lockDevice();
         setDeviceRotation(3);
         unlockDevice();
         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
-        mAmWmState.assertValidBounds();
     }
 
     public void testResizeDockedStack() throws Exception {
@@ -142,7 +138,6 @@
         launchActivityInDockStack(DOCKED_ACTIVITY_NAME);
         resizeDockedStack(STACK_SIZE, STACK_SIZE, TASK_SIZE, TASK_SIZE);
         mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME, DOCKED_ACTIVITY_NAME});
-        mAmWmState.assertSanity();
         mAmWmState.assertContainsStack("Must contain docked stack", DOCKED_STACK_ID);
         mAmWmState.assertContainsStack("Must contain fullscreen stack",
                 FULLSCREEN_WORKSPACE_STACK_ID);
@@ -164,7 +159,6 @@
 
         mAmWmState.computeState(mDevice,
                 new String[]{TEST_ACTIVITY_NAME, NO_RELAUNCH_ACTIVITY_NAME});
-        mAmWmState.assertSanity();
         final Rectangle initialDockBounds =
                 mAmWmState.getWmState().getStack(DOCKED_STACK_ID).getBounds();
 
@@ -180,7 +174,6 @@
 
         mAmWmState.computeState(mDevice,
                 new String[]{TEST_ACTIVITY_NAME, NO_RELAUNCH_ACTIVITY_NAME});
-        mAmWmState.assertSanity();
 
         assertActivityLifecycle(TEST_ACTIVITY_NAME, true);
         assertActivityLifecycle(NO_RELAUNCH_ACTIVITY_NAME, false);
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerFreeformStackTests.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerFreeformStackTests.java
index 786e8e1..f86d9ec 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerFreeformStackTests.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerFreeformStackTests.java
@@ -17,6 +17,7 @@
 package android.server.cts;
 
 import java.awt.Rectangle;
+import java.util.ArrayList;
 
 public class ActivityManagerFreeformStackTests extends ActivityManagerTestBase {
 
@@ -28,6 +29,7 @@
     // NOTE: Launching the FreeformActivity will automatically launch the TestActivity
     // with bounds (0, 0, 500, 500)
     private static final String FREEFORM_ACTIVITY = "FreeformActivity";
+    private static final String NON_RESIZEABLE_ACTIVITY = "NonResizeableActivity";
     private static final String NO_RELAUNCH_ACTIVITY = "NoRelaunchActivity";
 
     public void testFreeformWindowManagementSupport() throws Exception {
@@ -35,11 +37,9 @@
         launchActivityInStack(FREEFORM_ACTIVITY, FREEFORM_WORKSPACE_STACK_ID);
 
         mAmWmState.computeState(mDevice, new String[] {FREEFORM_ACTIVITY});
-        mAmWmState.assertSanity();
-        mAmWmState.assertValidBounds();
 
         if (!supportsFreeform()) {
-            mAmWmState.assertDoesNotContainsStack(
+            mAmWmState.assertDoesNotContainStack(
                     "Must not contain freeform stack.", FREEFORM_WORKSPACE_STACK_ID);
             return;
         }
@@ -54,15 +54,25 @@
                 mAmWmState.getAmState().getTaskByActivityName(TEST_ACTIVITY).getBounds());
     }
 
+    public void testNonResizeableActivityNotLaunchedToFreeform() throws Exception {
+        launchActivityInStack(NON_RESIZEABLE_ACTIVITY, FREEFORM_WORKSPACE_STACK_ID);
+
+        mAmWmState.computeState(mDevice, new String[] {NON_RESIZEABLE_ACTIVITY});
+
+        mAmWmState.assertFrontStack(
+                "Fullscreen stack must be the front stack.", FULLSCREEN_WORKSPACE_STACK_ID);
+        mAmWmState.assertDoesNotContainStack(
+                "Must not contain freeform stack.", FREEFORM_WORKSPACE_STACK_ID);
+    }
+
     public void testActivityLifeCycleOnResizeFreeformTask() throws Exception {
         launchActivityInStack(TEST_ACTIVITY, FREEFORM_WORKSPACE_STACK_ID);
         launchActivityInStack(NO_RELAUNCH_ACTIVITY, FREEFORM_WORKSPACE_STACK_ID);
 
         mAmWmState.computeState(mDevice, new String[]{TEST_ACTIVITY, NO_RELAUNCH_ACTIVITY});
-        mAmWmState.assertSanity();
 
         if (!supportsFreeform()) {
-            mAmWmState.assertDoesNotContainsStack(
+            mAmWmState.assertDoesNotContainStack(
                     "Must not contain freeform stack.", FREEFORM_WORKSPACE_STACK_ID);
             return;
         }
@@ -73,7 +83,6 @@
                 TEST_TASK_OFFSET_2, TEST_TASK_OFFSET_2, TEST_TASK_SIZE_1, TEST_TASK_SIZE_2);
 
         mAmWmState.computeState(mDevice, new String[]{TEST_ACTIVITY, NO_RELAUNCH_ACTIVITY});
-        mAmWmState.assertSanity();
 
         clearLogcat();
         resizeActivityTask(TEST_ACTIVITY,
@@ -81,7 +90,6 @@
         resizeActivityTask(NO_RELAUNCH_ACTIVITY,
                 TEST_TASK_OFFSET_2, TEST_TASK_OFFSET_2, TEST_TASK_SIZE_2, TEST_TASK_SIZE_1);
         mAmWmState.computeState(mDevice, new String[]{TEST_ACTIVITY, NO_RELAUNCH_ACTIVITY});
-        mAmWmState.assertSanity();
 
         assertActivityLifecycle(TEST_ACTIVITY, true);
         assertActivityLifecycle(NO_RELAUNCH_ACTIVITY, false);
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerManifestLayoutTests.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerManifestLayoutTests.java
index bae3c6e..f0008eb 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerManifestLayoutTests.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerManifestLayoutTests.java
@@ -146,8 +146,6 @@
 
         mAmWmState.computeState(mDevice, true /* visibleOnly */, new String[] {activityName});
 
-        mAmWmState.assertSanity();
-
         mAmWmState.assertFocusedWindow("Test window must be the front window.", windowName);
 
         mAmWmState.getWmState().getMatchingWindowState(windowName, mTempWindowList);
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
index 4250404..c57b648 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
@@ -52,8 +52,6 @@
         }
 
         mAmWmState.computeState(mDevice, new String[] {topActiviyName});
-        mAmWmState.assertSanity();
-        mAmWmState.assertValidBounds();
 
         if (supportsPip()) {
             final String windowName = getWindowName(topActiviyName);
@@ -81,7 +79,7 @@
                         "Pinned window can't be focused window.", windowName);
             }
         } else {
-            mAmWmState.assertDoesNotContainsStack(
+            mAmWmState.assertDoesNotContainStack(
                     "Must not contain pinned stack.", PINNED_STACK_ID);
         }
     }
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerReplaceWindowTests.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerReplaceWindowTests.java
index 298a759..624128b 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerReplaceWindowTests.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerReplaceWindowTests.java
@@ -86,8 +86,6 @@
             throws Exception {
         mAmWmState.computeState(mDevice, visibleOnly, new String[] {activityName});
 
-        mAmWmState.assertSanity();
-
         mAmWmState.assertFocusedWindow("Test window must be the front window.",
                 windowName);
 
diff --git a/hostsidetests/systemui/Android.mk b/hostsidetests/systemui/Android.mk
index 1c0dd06..41f05ef 100644
--- a/hostsidetests/systemui/Android.mk
+++ b/hostsidetests/systemui/Android.mk
@@ -28,6 +28,8 @@
 
 LOCAL_CTS_TEST_PACKAGE := android.host.systemui
 
+LOCAL_CTS_MODULE_CONFIG := $(LOCAL_PATH)/Old$(CTS_MODULE_TEST_CONFIG)
+
 LOCAL_SDK_VERSION := current
 
 # Tag this module as a cts test artifact
diff --git a/hostsidetests/systemui/OldAndroidTest.xml b/hostsidetests/systemui/OldAndroidTest.xml
new file mode 100644
index 0000000..2efcb94
--- /dev/null
+++ b/hostsidetests/systemui/OldAndroidTest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for CTS System UI host test cases">
+
+    <include name="common-config" />
+    <!-- This will tell tradefed to install the test apk. -->
+    <option name="cts-apk-installer:test-file-name" value="CtsSystemUiDeviceApp.apk" />
+</configuration>
diff --git a/hostsidetests/theme/AndroidTest.xml b/hostsidetests/theme/AndroidTest.xml
index 516df3d..50418ec 100644
--- a/hostsidetests/theme/AndroidTest.xml
+++ b/hostsidetests/theme/AndroidTest.xml
@@ -20,5 +20,6 @@
     </target_preparer>
     <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
         <option name="jar" value="CtsThemeHostTestCases.jar" />
+        <option name="runtime-hint" value="5h2m34s" />
     </test>
 </configuration>
diff --git a/suite/audio_quality/lib/src/audio/AudioLocal.cpp b/suite/audio_quality/lib/src/audio/AudioLocal.cpp
index 71b7afb..2a65689 100644
--- a/suite/audio_quality/lib/src/audio/AudioLocal.cpp
+++ b/suite/audio_quality/lib/src/audio/AudioLocal.cpp
@@ -23,7 +23,7 @@
     // gain control not necessary in MobilePre as there is no control.
     // This means audio source itself should be adjusted to control volume
     if (mState == EStNone) {
-        if (run() != android::NO_ERROR) {
+        if (run("AudioLocal") != android::NO_ERROR) {
             LOGE("AudioLocal cannot run");
             // cannot run thread
             return false;
diff --git a/suite/audio_quality/lib/src/audio/RemoteAudio.cpp b/suite/audio_quality/lib/src/audio/RemoteAudio.cpp
index d9b7c51..ead04b91 100644
--- a/suite/audio_quality/lib/src/audio/RemoteAudio.cpp
+++ b/suite/audio_quality/lib/src/audio/RemoteAudio.cpp
@@ -59,7 +59,7 @@
 bool RemoteAudio::init(int port)
 {
     mPort = port;
-    if (run() != android::NO_ERROR) {
+    if (run("RemoteAudio") != android::NO_ERROR) {
         LOGE("RemoteAudio cannot run");
         // cannot run thread
         return false;
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/TimingConstraintsTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/TimingConstraintsTest.java
index 40b67c8..62c7124 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/TimingConstraintsTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/TimingConstraintsTest.java
@@ -41,18 +41,6 @@
         assertTrue("Timed out waiting for override deadline.", executed);
     }
 
-    public void testSchedulePeriodic() throws Exception {
-        JobInfo periodicJob =
-                new JobInfo.Builder(TIMING_JOB_ID, kJobServiceComponent)
-                        .setPeriodic(5000L)  // 5 second period.
-                        .build();
-
-        kTestEnvironment.setExpectedExecutions(3);
-        mJobScheduler.schedule(periodicJob);
-        final boolean countedDown = kTestEnvironment.awaitExecution();
-        assertTrue("Timed out waiting for periodic jobs to execute", countedDown);
-    }
-
     public void testCancel() throws Exception {
         JobInfo cancelJob = new JobInfo.Builder(CANCEL_JOB_ID, kJobServiceComponent)
                 .setMinimumLatency(5000L) // make sure it doesn't actually run immediately
@@ -106,4 +94,4 @@
                         " JobParameters#isOverrideDeadlineExpired=false",
                 kTestEnvironment.getLastJobParameters().isOverrideDeadlineExpired());
     }
-}
\ No newline at end of file
+}
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
index bc88085..bb199b4 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
@@ -24,6 +24,7 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
+import android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener;
 
 import java.util.List;
 
@@ -63,6 +64,19 @@
         };
         assertTrue(mAccessibilityManager.addAccessibilityStateChangeListener(listener));
         assertTrue(mAccessibilityManager.removeAccessibilityStateChangeListener(listener));
+        assertFalse(mAccessibilityManager.removeAccessibilityStateChangeListener(listener));
+    }
+
+    public void testAddAndRemoveTouchExplorationStateChangeListener() throws Exception {
+        TouchExplorationStateChangeListener listener = new TouchExplorationStateChangeListener() {
+            @Override
+            public void onTouchExplorationStateChanged(boolean enabled) {
+                // Do nothing.
+            }
+        };
+        assertTrue(mAccessibilityManager.addTouchExplorationStateChangeListener(listener));
+        assertTrue(mAccessibilityManager.removeTouchExplorationStateChangeListener(listener));
+        assertFalse(mAccessibilityManager.removeTouchExplorationStateChangeListener(listener));
     }
 
     public void testIsTouchExplorationEnabled() throws Exception {
@@ -173,6 +187,10 @@
                 AccessibilityEvent.TYPE_VIEW_CLICKED));
     }
 
+    public void testTouchExplorationStateChanged() throws Exception {
+        waitForTouchExplorationEnabled();
+    }
+
     private void waitForAccessibilityEnabled() throws InterruptedException {
         final Object waitObject = new Object();
 
@@ -192,6 +210,29 @@
             }
         }
         mAccessibilityManager.removeAccessibilityStateChangeListener(listener);
-        assertTrue("Time out enabling accessibility", mAccessibilityManager.isEnabled());
+        assertTrue("Timed out enabling accessibility", mAccessibilityManager.isEnabled());
+    }
+
+    private void waitForTouchExplorationEnabled() throws InterruptedException {
+        final Object waitObject = new Object();
+
+        TouchExplorationStateChangeListener listener = new TouchExplorationStateChangeListener() {
+            @Override
+            public void onTouchExplorationStateChanged(boolean b) {
+                synchronized (waitObject) {
+                    waitObject.notifyAll();
+                }
+            }
+        };
+        mAccessibilityManager.addTouchExplorationStateChangeListener(listener);
+        long timeoutTime = System.currentTimeMillis() + WAIT_FOR_ACCESSIBILITY_ENABLED_TIMEOUT;
+        synchronized (waitObject) {
+            if (!mAccessibilityManager.isEnabled() && (System.currentTimeMillis() < timeoutTime)) {
+                waitObject.wait(timeoutTime - System.currentTimeMillis());
+            }
+        }
+        mAccessibilityManager.removeTouchExplorationStateChangeListener(listener);
+        assertTrue("Timed out enabling touch exploration",
+                mAccessibilityManager.isTouchExplorationEnabled());
     }
 }
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfo_CollectionInfoTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfo_CollectionInfoTest.java
new file mode 100644
index 0000000..d64bd94
--- /dev/null
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfo_CollectionInfoTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.accessibility.cts;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.accessibility.AccessibilityNodeInfo.CollectionInfo;
+
+/**
+ * Class for testing {@link CollectionInfo}.
+ */
+public class AccessibilityNodeInfo_CollectionInfoTest extends AndroidTestCase {
+
+    @SmallTest
+    public void testObtain() {
+        CollectionInfo c;
+
+        c = CollectionInfo.obtain(0, 1, true);
+        assertNotNull(c);
+        assertEquals(0, c.getRowCount());
+        assertEquals(1, c.getColumnCount());
+        assertTrue(c.isHierarchical());
+        assertEquals(CollectionInfo.SELECTION_MODE_NONE, c.getSelectionMode());
+
+        c = CollectionInfo.obtain(1, 2, true, CollectionInfo.SELECTION_MODE_MULTIPLE);
+        assertNotNull(c);
+        assertEquals(1, c.getRowCount());
+        assertEquals(2, c.getColumnCount());
+        assertTrue(c.isHierarchical());
+        assertEquals(CollectionInfo.SELECTION_MODE_MULTIPLE, c.getSelectionMode());
+    }
+}
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfo_RangeInfoTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfo_RangeInfoTest.java
new file mode 100644
index 0000000..954d762
--- /dev/null
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfo_RangeInfoTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.accessibility.cts;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.RangeInfo;
+
+/**
+ * Class for testing {@link AccessibilityNodeInfo.RangeInfo}.
+ */
+public class AccessibilityNodeInfo_RangeInfoTest extends AndroidTestCase {
+
+    /** Allowed tolerance for floating point equality comparisons. */
+    public static final float FLOAT_TOLERANCE = 0.001f;
+
+    @SmallTest
+    public void testObtain() {
+        RangeInfo r;
+
+        r = RangeInfo.obtain(RangeInfo.RANGE_TYPE_INT, -100, 0, -50);
+        assertEquals(RangeInfo.RANGE_TYPE_INT, r.getType());
+        assertEquals(-100, r.getMin(), FLOAT_TOLERANCE);
+        assertEquals(0, r.getMax(), FLOAT_TOLERANCE);
+        assertEquals(-50, r.getCurrent(), FLOAT_TOLERANCE);
+
+        r = RangeInfo.obtain(RangeInfo.RANGE_TYPE_FLOAT, -1.5f, 1.5f, 0.0f);
+        assertEquals(RangeInfo.RANGE_TYPE_FLOAT, r.getType());
+        assertEquals(-1.5f, r.getMin(), FLOAT_TOLERANCE);
+        assertEquals(1.5f, r.getMax(), FLOAT_TOLERANCE);
+        assertEquals(0.0f, r.getCurrent(), FLOAT_TOLERANCE);
+
+        r = RangeInfo.obtain(RangeInfo.RANGE_TYPE_PERCENT, 0.0f, 100.0f, 50.0f);
+        assertEquals(RangeInfo.RANGE_TYPE_PERCENT, r.getType());
+        assertEquals(0.0f, r.getMin(), FLOAT_TOLERANCE);
+        assertEquals(100.0f, r.getMax(), FLOAT_TOLERANCE);
+        assertEquals(50.0f, r.getCurrent(), FLOAT_TOLERANCE);
+    }
+}
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeProviderTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeProviderTest.java
new file mode 100644
index 0000000..eeee235
--- /dev/null
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeProviderTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.accessibility.cts;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.accessibility.AccessibilityNodeProvider;
+
+/**
+ * Class for testing {@link AccessibilityNodeProvider}.
+ */
+public class AccessibilityNodeProviderTest extends AndroidTestCase {
+    @SmallTest
+    public void testDefaultBehavior() {
+        AccessibilityNodeProvider p = new AccessibilityNodeProvider() {
+            // Class is abstract, but has no abstract methods.
+        };
+
+        assertNull(p.createAccessibilityNodeInfo(0));
+        assertNull(p.findAccessibilityNodeInfosByText(null, 0));
+        assertNull(p.findFocus(0));
+        assertFalse(p.performAction(0, 0, null));
+    }
+}
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityWindowInfoTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityWindowInfoTest.java
new file mode 100644
index 0000000..293feec
--- /dev/null
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityWindowInfoTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.accessibility.cts;
+
+import android.graphics.Rect;
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.accessibility.AccessibilityWindowInfo;
+
+/**
+ * Class for testing {@link AccessibilityWindowInfo}.
+ */
+public class AccessibilityWindowInfoTest extends AndroidTestCase {
+
+    @SmallTest
+    public void testObtain() {
+        AccessibilityWindowInfo w1 = AccessibilityWindowInfo.obtain();
+        assertNotNull(w1);
+
+        AccessibilityWindowInfo w2 = AccessibilityWindowInfo.obtain(w1);
+        assertNotSame(w1, w2);
+        assertEquals(w1, w2);
+    }
+
+    @SmallTest
+    public void testParceling() {
+        Parcel parcel = Parcel.obtain();
+        AccessibilityWindowInfo w1 = AccessibilityWindowInfo.obtain();
+        w1.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+        AccessibilityWindowInfo w2 = AccessibilityWindowInfo.CREATOR.createFromParcel(parcel);
+        assertNotSame(w1, w2);
+        assertEquals(w1, w2);
+
+    }
+
+    @SmallTest
+    public void testDefaultValues() {
+        AccessibilityWindowInfo w = AccessibilityWindowInfo.obtain();
+        assertEquals(0, w.getChildCount());
+        assertEquals(-1, w.getType());
+        assertEquals(-1, w.getLayer());
+        assertEquals(-1, w.getId());
+        assertEquals(0, w.describeContents());
+        assertNull(w.getParent());
+        assertNull(w.getRoot());
+        assertFalse(w.isAccessibilityFocused());
+        assertFalse(w.isActive());
+        assertFalse(w.isFocused());
+
+        Rect rect = new Rect();
+        w.getBoundsInScreen(rect);
+        assertTrue(rect.isEmpty());
+
+        try {
+            w.getChild(0);
+            fail("Expected IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // Expected.
+        }
+    }
+
+    @SmallTest
+    public void testRecycle() {
+        AccessibilityWindowInfo w = AccessibilityWindowInfo.obtain();
+        w.recycle();
+
+        try {
+            w.recycle();
+            fail("Expected IllegalStateException");
+        } catch (IllegalStateException e) {
+            // Expected.
+        }
+    }
+}
diff --git a/tests/accessibility/src/android/view/accessibility/cts/CaptioningManagerTest.java b/tests/accessibility/src/android/view/accessibility/cts/CaptioningManagerTest.java
index 34beb59..997ee61 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/CaptioningManagerTest.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/CaptioningManagerTest.java
@@ -67,7 +67,9 @@
         putSecureSetting("accessibility_captioning_enabled", "1");
         assertTrue("Observed enabled change", listener.wasEnabledChangedCalled);
 
+        // Style change gets posted in a Runnable, so we need to wait for idle.
         putSecureSetting("accessibility_captioning_preset", "-1");
+        getInstrumentation().waitForIdleSync();
         assertTrue("Observed user style change", listener.wasUserStyleChangedCalled);
 
         putSecureSetting("accessibility_captioning_locale", "ja_JP");
diff --git a/tests/accessibility/src/android/view/accessibility/cts/SpeakingAccessibilityService.java b/tests/accessibility/src/android/view/accessibility/cts/SpeakingAccessibilityService.java
index afa08cd..219a2ff 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/SpeakingAccessibilityService.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/SpeakingAccessibilityService.java
@@ -17,6 +17,7 @@
 package android.view.accessibility.cts;
 
 import android.accessibilityservice.AccessibilityService;
+import android.accessibilityservice.AccessibilityServiceInfo;
 import android.view.accessibility.AccessibilityEvent;
 
 /**
@@ -34,6 +35,10 @@
 
     @Override
     protected void onServiceConnected() {
+        final AccessibilityServiceInfo info = getServiceInfo();
+        info.flags |= AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE;
+        setServiceInfo(info);
+
         synchronized (sWaitObjectForConnecting) {
             sConnectedInstance = this;
             sWaitObjectForConnecting.notifyAll();
diff --git a/tests/accessibility/src/android/view/accessibility/cts/VibratingAccessibilityService.java b/tests/accessibility/src/android/view/accessibility/cts/VibratingAccessibilityService.java
index 6bf522e..41edf9f 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/VibratingAccessibilityService.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/VibratingAccessibilityService.java
@@ -17,6 +17,7 @@
 package android.view.accessibility.cts;
 
 import android.accessibilityservice.AccessibilityService;
+import android.accessibilityservice.AccessibilityServiceInfo;
 import android.view.accessibility.AccessibilityEvent;
 
 /**
@@ -34,6 +35,10 @@
 
     @Override
     protected void onServiceConnected() {
+        final AccessibilityServiceInfo info = getServiceInfo();
+        info.flags |= AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE;
+        setServiceInfo(info);
+
         synchronized (sWaitObjectForConnecting) {
             sConnectedInstance = this;
             sWaitObjectForConnecting.notifyAll();
diff --git a/tests/accessibilityservice/AndroidTest.xml b/tests/accessibilityservice/AndroidTest.xml
index 1287524..fe261dc 100644
--- a/tests/accessibilityservice/AndroidTest.xml
+++ b/tests/accessibilityservice/AndroidTest.xml
@@ -20,5 +20,6 @@
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.accessibilityservice.cts" />
+        <option name="runtime-hint" value="2m12s" />
     </test>
 </configuration>
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java
index 2a17486..52af854 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java
@@ -17,16 +17,19 @@
 import android.accessibilityservice.AccessibilityService;
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.accessibilityservice.GestureDescription;
+import android.accessibilityservice.GestureDescription.Builder;
+import android.accessibilityservice.GestureDescription.StrokeDescription;
 import android.app.UiAutomation;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.graphics.Matrix;
+import android.graphics.Path;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
 import android.os.SystemClock;
 import android.provider.Settings;
 import android.test.ActivityInstrumentationTestCase2;
-import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewConfiguration;
@@ -96,7 +99,7 @@
         final int clickYInsideView = 20;
         int clickX = clickXInsideView + mViewBounds.left;
         int clickY = clickYInsideView + mViewBounds.top;
-        GestureDescription click = GestureDescription.createClick(clickX, clickY);
+        GestureDescription click = createClick(clickX, clickY);
         assertTrue(StubGestureAccessibilityService.sConnectedInstance
                 .doDispatchGesture(click, mCallback, null));
         mCallback.assertGestureCompletes(GESTURE_COMPLETION_TIMEOUT);
@@ -144,7 +147,7 @@
         final int clickYInsideView = 20;
         int clickX = clickXInsideView + mViewBounds.left;
         int clickY = clickYInsideView + mViewBounds.top;
-        GestureDescription longClick = GestureDescription.createLongClick(clickX, clickY);
+        GestureDescription longClick = createLongClick(clickX, clickY);
         assertTrue(StubGestureAccessibilityService.sConnectedInstance
                 .doDispatchGesture(longClick, mCallback, null));
         mCallback.assertGestureCompletes(
@@ -186,8 +189,7 @@
         int gestureTime = 500;
         float swipeTolerance = 2.0f;
 
-        GestureDescription swipe = GestureDescription
-                .createSwipe(startX, startY, endX, endY, gestureTime);
+        GestureDescription swipe = createSwipe(startX, startY, endX, endY, gestureTime);
         assertTrue(StubGestureAccessibilityService.sConnectedInstance
                 .doDispatchGesture(swipe, mCallback, null));
         mCallback.assertGestureCompletes(gestureTime + GESTURE_COMPLETION_TIMEOUT);
@@ -231,8 +233,7 @@
         int endY = endYInsideView + mViewBounds.top;
         int gestureTime = 1000;
 
-        GestureDescription swipe = GestureDescription
-                .createSwipe(startX, startY, endX, endY, gestureTime);
+        GestureDescription swipe = createSwipe(startX, startY, endX, endY, gestureTime);
         assertTrue(StubGestureAccessibilityService.sConnectedInstance
                 .doDispatchGesture(swipe, mCallback, null));
         mCallback.assertGestureCompletes(gestureTime + GESTURE_COMPLETION_TIMEOUT);
@@ -269,7 +270,7 @@
         int gestureTime = 500;
         float pinchTolerance = 2.0f;
 
-        GestureDescription pinch = GestureDescription.createPinch(centerX, centerY, startSpacing,
+        GestureDescription pinch = createPinch(centerX, centerY, startSpacing,
                 endSpacing, 45.0F, gestureTime);
         assertTrue(StubGestureAccessibilityService.sConnectedInstance
                 .doDispatchGesture(pinch, mCallback, null));
@@ -481,4 +482,84 @@
             }
         }
     }
+
+    private GestureDescription createClick(int x, int y) {
+        Path clickPath = new Path();
+        clickPath.moveTo(x, y);
+        clickPath.lineTo(x + 1, y);
+        GestureDescription.StrokeDescription clickStroke =
+                new GestureDescription.StrokeDescription(clickPath, 0, ViewConfiguration.getTapTimeout());
+        GestureDescription.Builder clickBuilder = new GestureDescription.Builder();
+        clickBuilder.addStroke(clickStroke);
+        return clickBuilder.build();
+    }
+
+    private GestureDescription createLongClick(int x, int y) {
+        Path clickPath = new Path();
+        clickPath.moveTo(x, y);
+        clickPath.lineTo(x + 1, y);
+        int longPressTime = ViewConfiguration.getLongPressTimeout();
+
+        GestureDescription.StrokeDescription longClickStroke =
+                new GestureDescription.StrokeDescription(clickPath, 0, longPressTime + (longPressTime / 2));
+        GestureDescription.Builder longClickBuilder = new GestureDescription.Builder();
+        longClickBuilder.addStroke(longClickStroke);
+        return longClickBuilder.build();
+    }
+
+    private GestureDescription createSwipe(
+            int startX, int startY, int endX, int endY, long duration) {
+        Path swipePath = new Path();
+        swipePath.moveTo(startX, startY);
+        swipePath.lineTo(endX, endY);
+
+        GestureDescription.StrokeDescription swipeStroke = new GestureDescription.StrokeDescription(swipePath, 0, duration);
+        GestureDescription.Builder swipeBuilder = new GestureDescription.Builder();
+        swipeBuilder.addStroke(swipeStroke);
+        return swipeBuilder.build();
+    }
+
+    private GestureDescription createPinch(int centerX, int centerY, int startSpacing,
+            int endSpacing, float orientation, long duration) {
+        if ((startSpacing < 0) || (endSpacing < 0)) {
+            throw new IllegalArgumentException("Pinch spacing cannot be negative");
+        }
+        float[] startPoint1 = new float[2];
+        float[] endPoint1 = new float[2];
+        float[] startPoint2 = new float[2];
+        float[] endPoint2 = new float[2];
+
+        /* Build points for a horizontal gesture centered at the origin */
+        startPoint1[0] = startSpacing / 2;
+        startPoint1[1] = 0;
+        endPoint1[0] = endSpacing / 2;
+        endPoint1[1] = 0;
+        startPoint2[0] = -startSpacing / 2;
+        startPoint2[1] = 0;
+        endPoint2[0] = -endSpacing / 2;
+        endPoint2[1] = 0;
+
+        /* Rotate and translate the points */
+        Matrix matrix = new Matrix();
+        matrix.setRotate(orientation);
+        matrix.postTranslate(centerX, centerY);
+        matrix.mapPoints(startPoint1);
+        matrix.mapPoints(endPoint1);
+        matrix.mapPoints(startPoint2);
+        matrix.mapPoints(endPoint2);
+
+        Path path1 = new Path();
+        path1.moveTo(startPoint1[0], startPoint1[1]);
+        path1.lineTo(endPoint1[0], endPoint1[1]);
+        Path path2 = new Path();
+        path2.moveTo(startPoint2[0], startPoint2[1]);
+        path2.lineTo(endPoint2[0], endPoint2[1]);
+
+        GestureDescription.StrokeDescription path1Stroke = new GestureDescription.StrokeDescription(path1, 0, duration);
+        GestureDescription.StrokeDescription path2Stroke = new GestureDescription.StrokeDescription(path2, 0, duration);
+        GestureDescription.Builder swipeBuilder = new GestureDescription.Builder();
+        swipeBuilder.addStroke(path1Stroke);
+        swipeBuilder.addStroke(path2Stroke);
+        return swipeBuilder.build();
+    }
 }
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/GestureDescriptionTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/GestureDescriptionTest.java
index b696cba..b3fa9d2 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/GestureDescriptionTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/GestureDescriptionTest.java
@@ -119,7 +119,7 @@
 
     public void testAddStroke_allowUpToMaxPaths() {
         GestureDescription.Builder gestureBuilder = new GestureDescription.Builder();
-        for (int i = 0; i < GestureDescription.MAX_STROKE_COUNT; i++) {
+        for (int i = 0; i < GestureDescription.getMaxStrokeCount(); i++) {
             Path path = new Path();
             path.moveTo(i, i);
             path.lineTo(10 + i, 10 + i);
@@ -144,7 +144,7 @@
         GestureDescription.Builder gestureBuilder = new GestureDescription.Builder();
         try {
             gestureBuilder.addStroke(new GestureDescription.StrokeDescription(
-                    path, 0, GestureDescription.MAX_GESTURE_DURATION_MS + 1));
+                    path, 0, GestureDescription.getMaxGestureDuration() + 1));
             fail("Missing exception for adding stroke with duration too long.");
         } catch (RuntimeException e) {
         }
@@ -159,151 +159,6 @@
         }
     }
 
-
-    public void testClickAt_negativeX_shouldThrow() {
-        try {
-            GestureDescription.createClick(-1, 0);
-            fail("Missing exception for clicking at negative x coordinate.");
-        } catch (IllegalArgumentException e) {
-        }
-    }
-
-    public void testClickAt_negativeY_shouldThrow() {
-        try {
-            GestureDescription.createClick(0, -1);
-            fail("Missing exception for clicking at negative y coordinate.");
-        } catch (IllegalArgumentException e) {
-        }
-    }
-
-    public void testLongClickAt_negativeX_shouldThrow() {
-        try {
-            GestureDescription.createLongClick(-1, 0);
-            fail("Missing exception for long clicking at negative x coordinate.");
-        } catch (IllegalArgumentException e) {
-        }
-    }
-
-    public void testLongClickAt_negativeY_shouldThrow() {
-        try {
-            GestureDescription.createLongClick(0, -1);
-            fail("Missing exception for long clicking at negative y coordinate.");
-        } catch (IllegalArgumentException e) {
-        }
-    }
-
-    public void testZeroDurationSwipe_shouldThrow() {
-        try {
-            GestureDescription.createSwipe(0, 0, 100, 100, 0);
-            fail("Missing exception for creating zero duration swipe.");
-        } catch (IllegalArgumentException e) {
-        }
-    }
-
-    public void testNegativeDurationSwipe_shouldThrow() {
-        try {
-            GestureDescription.createSwipe(0, 0, 100, 100, -1);
-            fail("Missing exception for creating negative duration swipe.");
-        } catch (IllegalArgumentException e) {
-        }
-    }
-
-    public void testZeroLengthSwipe_shouldThrow() {
-        try {
-            GestureDescription.createSwipe(0, 0, 0, 0, 10);
-            fail("Missing exception for creating zero-length swipe.");
-        } catch (IllegalArgumentException e) {
-        }
-    }
-
-    public void testSwipe_negativeStartX_shouldThrow() {
-        try {
-            GestureDescription.createSwipe(-1, 0, 0, 0, 10);
-            fail("Missing exception for creating swipe with negative starting x.");
-        } catch (IllegalArgumentException e) {
-        }
-    }
-
-    public void testSwipe_negativeStartY_shouldThrow() {
-        try {
-            GestureDescription.createSwipe(0, -1, 0, 0, 10);
-            fail("Missing exception for creating swipe with negative starting y.");
-        } catch (IllegalArgumentException e) {
-        }
-    }
-
-    public void testSwipe_negativeEndX_shouldThrow() {
-        try {
-            GestureDescription.createSwipe(0, 0, -1, 0, 10);
-            fail("Missing exception for creating swipe with negative ending x.");
-        } catch (IllegalArgumentException e) {
-        }
-    }
-
-    public void testSwipe_negativeEndY_shouldThrow() {
-        try {
-            GestureDescription.createSwipe(0, 0, 0, -1, 10);
-            fail("Missing exception for creating swipe with negative ending y.");
-        } catch (IllegalArgumentException e) {
-        }
-    }
-
-    public void testZeroDurationPinch_shouldBeNull() {
-        try {
-            GestureDescription.createPinch(100, 100, 50, 75, 0, 0);
-            fail("Missing exception for creating pinch with zero duration.");
-        } catch (IllegalArgumentException e) {
-        }
-    }
-
-    public void testNegativeDurationPinch_shouldBeNull() {
-        try {
-            GestureDescription.createPinch(100, 100, 50, 75, 0, -1);
-            fail("Missing exception for creating pinch with negative duration.");
-        } catch (IllegalArgumentException e) {
-        }
-    }
-
-    public void testZeroLengthPinch_shouldThrow() {
-        try {
-            GestureDescription.createPinch(100, 100, 50, 50, 0, 100);
-            fail("Missing exception for creating pinch with zero length.");
-        } catch (IllegalArgumentException e) {
-        }
-    }
-
-    public void testPinch_negativeCenterX_shouldThrow() {
-        try {
-            GestureDescription.createPinch(-100, 100, 50, 75, 0, 100);
-            fail("Missing exception for creating pinch with negative center x.");
-        } catch (IllegalArgumentException e) {
-        }
-    }
-
-    public void testPinch_negativeCenterY_shouldThrow() {
-        try {
-            GestureDescription.createPinch(100, -100, 50, 75, 0, 100);
-            fail("Missing exception for creating pinch with negative center y.");
-        } catch (IllegalArgumentException e) {
-        }
-    }
-
-    public void testPinch_negativeStartSpacing_shouldThrow() {
-        try {
-            GestureDescription.createPinch(100, 100, -50, 75, 0, 100);
-            fail("Missing exception for creating pinch with negative start spacing.");
-        } catch (IllegalArgumentException e) {
-        }
-    }
-
-    public void testPinch_negativeEndSpacing_shouldThrow() {
-        try {
-            GestureDescription.createPinch(100, 100, 50, -75, 0, 100);
-            fail("Missing exception for creating pinch with negative end spacing.");
-        } catch (IllegalArgumentException e) {
-        }
-    }
-
     public void testStrokeDescriptionGetters_workAsExpected() {
         int x = 100;
         int startY = 100;
diff --git a/tests/admin/Android.mk b/tests/admin/Android.mk
index 7933004..e12cc94 100644
--- a/tests/admin/Android.mk
+++ b/tests/admin/Android.mk
@@ -20,7 +20,8 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner mockito-target
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    ctstestrunner mockito-target platform-test-annotations
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
@@ -37,4 +38,4 @@
 
 include $(BUILD_CTS_PACKAGE)
 
-include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/admin/src/android/admin/cts/DeviceAdminReceiverTest.java b/tests/admin/src/android/admin/cts/DeviceAdminReceiverTest.java
index 9b80b33..81ea503 100644
--- a/tests/admin/src/android/admin/cts/DeviceAdminReceiverTest.java
+++ b/tests/admin/src/android/admin/cts/DeviceAdminReceiverTest.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.platform.test.annotations.Presubmit;
 import android.test.AndroidTestCase;
 import android.util.Log;
 
@@ -62,6 +63,7 @@
                 mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN);
     }
 
+    @Presubmit
     public void testOnReceive() {
         if (!mDeviceAdmin) {
             Log.w(TAG, "Skipping testOnReceive");
diff --git a/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java b/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
index 57d22dd..543a385 100644
--- a/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
+++ b/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
@@ -122,52 +122,52 @@
         }
     }
 
-    public void testSetDeviceLoggingEnabled_failIfNotDeviceOwner() {
+    public void testSetSecurityLoggingEnabled_failIfNotDeviceOwner() {
         if (!mDeviceAdmin) {
-            Log.w(TAG, "Skipping testSetDeviceLoggingEnabled_failIfNotDeviceOwner");
+            Log.w(TAG, "Skipping testSetSecurityLoggingEnabled_failIfNotDeviceOwner");
             return;
         }
         try {
-            mDevicePolicyManager.setDeviceLoggingEnabled(mComponent, true);
+            mDevicePolicyManager.setSecurityLoggingEnabled(mComponent, true);
             fail("did not throw expected SecurityException");
         } catch (SecurityException e) {
             assertDeviceOwnerMessage(e.getMessage());
         }
     }
 
-    public void testGetDeviceLoggingEnabled_failIfNotDeviceOwner() {
+    public void testIsSecurityLoggingEnabled_failIfNotDeviceOwner() {
         if (!mDeviceAdmin) {
-            Log.w(TAG, "Skipping testGetDeviceLoggingEnabled_failIfNotDeviceOwner");
+            Log.w(TAG, "Skipping testIsSecurityLoggingEnabled_failIfNotDeviceOwner");
             return;
         }
         try {
-            mDevicePolicyManager.getDeviceLoggingEnabled(mComponent);
+            mDevicePolicyManager.isSecurityLoggingEnabled(mComponent);
             fail("did not throw expected SecurityException");
         } catch (SecurityException e) {
             assertDeviceOwnerMessage(e.getMessage());
         }
     }
 
-    public void testRetrieveDeviceLogs_failIfNotDeviceOwner() {
+    public void testRetrieveSecurityLogs_failIfNotDeviceOwner() {
         if (!mDeviceAdmin) {
-            Log.w(TAG, "Skipping testRetrieveDeviceLogs_failIfNotDeviceOwner");
+            Log.w(TAG, "Skipping testRetrieveSecurityLogs_failIfNotDeviceOwner");
             return;
         }
         try {
-            mDevicePolicyManager.retrieveDeviceLogs(mComponent);
+            mDevicePolicyManager.retrieveSecurityLogs(mComponent);
             fail("did not throw expected SecurityException");
         } catch (SecurityException e) {
             assertDeviceOwnerMessage(e.getMessage());
         }
     }
 
-    public void testRetrievePreviousDeviceLogs_failIfNotDeviceOwner() {
+    public void testRetrievePreRebootSecurityLogs_failIfNotDeviceOwner() {
         if (!mDeviceAdmin) {
-            Log.w(TAG, "Skipping testRetrievePreviousDeviceLogs_failIfNotDeviceOwner");
+            Log.w(TAG, "Skipping testRetrievePreRebootSecurityLogs_failIfNotDeviceOwner");
             return;
         }
         try {
-            mDevicePolicyManager.retrievePreviousDeviceLogs(mComponent);
+            mDevicePolicyManager.retrievePreRebootSecurityLogs(mComponent);
             fail("did not throw expected SecurityException");
         } catch (SecurityException e) {
             assertDeviceOwnerMessage(e.getMessage());
diff --git a/tests/app/AndroidTest.xml b/tests/app/AndroidTest.xml
index acbc9e7..6487bd7 100644
--- a/tests/app/AndroidTest.xml
+++ b/tests/app/AndroidTest.xml
@@ -23,7 +23,7 @@
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.app.cts" />
-        <option name="runtime-hint" value="3m8s" />
+        <option name="runtime-hint" value="6m38s" />
     </test>
 
 </configuration>
diff --git a/tests/app/src/android/app/cts/AlertDialog_BuilderCursorTest.java b/tests/app/src/android/app/cts/AlertDialog_BuilderCursorTest.java
new file mode 100644
index 0000000..6305adb
--- /dev/null
+++ b/tests/app/src/android/app/cts/AlertDialog_BuilderCursorTest.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.cts;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.AlertDialog.Builder;
+import android.app.Instrumentation;
+import android.app.stubs.DialogStubActivity;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.content.DialogInterface.OnMultiChoiceClickListener;
+import android.cts.util.PollingCheck;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteCursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.support.test.InstrumentationRegistry;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.ListView;
+
+import java.io.File;
+
+import static org.mockito.Mockito.*;
+
+@MediumTest
+public class AlertDialog_BuilderCursorTest
+        extends ActivityInstrumentationTestCase2<DialogStubActivity> {
+    private Builder mBuilder;
+    private Context mContext;
+    private Instrumentation mInstrumentation;
+    private AlertDialog mDialog;
+    private ListView mListView;
+
+    private static final String TEXT_COLUMN_NAME = "text";
+    private static final String CHECKED_COLUMN_NAME = "checked";
+
+    private String[] mTextContent;
+    private boolean[] mCheckedContent;
+
+    private String[] mProjectionWithChecked;
+    private String[] mProjectionWithoutChecked;
+
+    private SQLiteDatabase mDatabase;
+    private File mDatabaseFile;
+    private Cursor mCursor;
+
+    private OnClickListener mOnClickListener = mock(OnClickListener.class);
+
+    /**
+     * Multi-choice click listener that is registered on our {@link AlertDialog} when it's in
+     * multi-choide mode. Note that this needs to be a separate class that is also protected (not
+     * private) so that Mockito can "spy" on it.
+     */
+    protected class MultiChoiceClickListener implements OnMultiChoiceClickListener {
+        private boolean[] mCheckedTracker;
+
+        public MultiChoiceClickListener(boolean[] checkedTracker) {
+            mCheckedTracker = checkedTracker;
+        }
+
+        @Override
+        public void onClick(DialogInterface dialog, int which,
+                boolean isChecked) {
+            // Update the underlying database with the new checked
+            // state for the specific row
+            mCursor.moveToPosition(which);
+            ContentValues valuesToUpdate = new ContentValues();
+            valuesToUpdate.put(CHECKED_COLUMN_NAME, isChecked ? 1 : 0);
+            mDatabase.update("test", valuesToUpdate,
+                    TEXT_COLUMN_NAME + " = ?",
+                    new String[] { mCursor.getString(1) } );
+            mCursor.requery();
+            mCheckedTracker[which] = isChecked;
+        }
+    }
+
+    public AlertDialog_BuilderCursorTest() {
+        super("android.app.stubs", DialogStubActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mBuilder = null;
+        mInstrumentation = getInstrumentation();
+        mContext = getActivity();
+        final Activity activity = getActivity();
+        new PollingCheck() {
+            @Override
+            protected boolean check() {
+                return activity.hasWindowFocus();
+            }
+        }.run();
+        mListView = null;
+        mDialog = null;
+
+        // Local test data for the tests
+        mTextContent = new String[] { "Adele", "Beyonce", "Ciara", "Dido" };
+        mCheckedContent = new boolean[] { false, false, true, false };
+
+        // Two projections - one with "checked" column and one without
+        mProjectionWithChecked = new String[] {
+                "_id",                       // 0
+                TEXT_COLUMN_NAME,            // 1
+                CHECKED_COLUMN_NAME          // 2
+        };
+        mProjectionWithoutChecked = new String[] {
+                "_id",                       // 0
+                TEXT_COLUMN_NAME             // 1
+        };
+
+        File dbDir = mContext.getDir("tests", Context.MODE_PRIVATE);
+        mDatabaseFile = new File(dbDir, "database_alert_dialog_test.db");
+        if (mDatabaseFile.exists()) {
+            mDatabaseFile.delete();
+        }
+        mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null);
+        assertNotNull(mDatabase);
+        // Create and populate a test table
+        mDatabase.execSQL(
+                "CREATE TABLE test (_id INTEGER PRIMARY KEY, " + TEXT_COLUMN_NAME +
+                        " TEXT, " + CHECKED_COLUMN_NAME + " INTEGER);");
+        for (int i = 0; i < mTextContent.length; i++) {
+            mDatabase.execSQL("INSERT INTO test (" + TEXT_COLUMN_NAME + ", " +
+                    CHECKED_COLUMN_NAME + ") VALUES ('" + mTextContent[i] + "', " +
+                    (mCheckedContent[i] ? "1" : "0") + ");");
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mCursor != null) {
+            // Close the cursor on the UI thread as the list view in the alert dialog
+            // will get notified of any change to the underlying cursor.
+            InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+                @Override
+                public void run() {
+                    mCursor.close();
+                    mCursor = null;
+                }
+            });
+        }
+        if (mDatabase != null) {
+            mDatabase.close();
+        }
+        if (mDatabaseFile != null) {
+            mDatabaseFile.delete();
+        }
+
+        super.tearDown();
+    }
+
+    public void testSetCursor() throws Throwable {
+        // Use a projection without "checked" column
+        mCursor = mDatabase.query("test", mProjectionWithoutChecked,
+                null, null, null, null, null);
+        assertNotNull(mCursor);
+
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                mBuilder = new Builder(mContext);
+                mBuilder.setCursor(mCursor, mOnClickListener, TEXT_COLUMN_NAME);
+                mDialog = mBuilder.show();
+                mListView = mDialog.getListView();
+                mListView.performItemClick(null, 0, 0);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+        final SQLiteCursor selected = (SQLiteCursor) mListView.getSelectedItem();
+        assertEquals(mCursor.getString(1), selected.getString(1));
+        verify(mOnClickListener, times(1)).onClick(mDialog, 0);
+        verifyNoMoreInteractions(mOnClickListener);
+    }
+
+    public void testSetSingleChoiceItemsWithParamCursor() throws Throwable {
+        // Use a projection without "checked" column
+        mCursor = mDatabase.query("test", mProjectionWithoutChecked,
+                null, null, null, null, null);
+        assertNotNull(mCursor);
+
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                mBuilder = new Builder(mContext);
+                mBuilder.setSingleChoiceItems(mCursor, 0, TEXT_COLUMN_NAME, mOnClickListener);
+                mDialog = mBuilder.show();
+                mListView = mDialog.getListView();
+                mListView.performItemClick(null, 0, 0);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+        final SQLiteCursor selected = (SQLiteCursor) mListView.getSelectedItem();
+        assertEquals(mCursor.getString(1), selected.getString(1));
+        verify(mOnClickListener, times(1)).onClick(mDialog, 0);
+        verifyNoMoreInteractions(mOnClickListener);
+    }
+
+    public void testSetMultiChoiceItemsWithParamCursor() throws Throwable {
+        mCursor = mDatabase.query("test", mProjectionWithChecked,
+                null, null, null, null, null);
+        assertNotNull(mCursor);
+
+        final boolean[] checkedTracker = mCheckedContent.clone();
+        final OnMultiChoiceClickListener mockMultiChoiceClickListener =
+                spy(new MultiChoiceClickListener(checkedTracker));
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                mBuilder = new Builder(mContext);
+                mBuilder.setMultiChoiceItems(mCursor, CHECKED_COLUMN_NAME, TEXT_COLUMN_NAME,
+                        mockMultiChoiceClickListener);
+                mDialog = mBuilder.show();
+                mListView = mDialog.getListView();
+                mListView.performItemClick(null, 0, 0);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+
+        SQLiteCursor selected = (SQLiteCursor) mListView.getSelectedItem();
+        assertEquals(mCursor.getString(0), selected.getString(0));
+        verify(mockMultiChoiceClickListener, times(1)).onClick(mDialog, 0, true);
+        // Verify that our multi-choice listener was invoked to update our tracker array
+        assertTrue(checkedTracker[0]);
+        assertFalse(checkedTracker[1]);
+        assertTrue(checkedTracker[2]);
+        assertFalse(checkedTracker[3]);
+
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                mListView.performItemClick(null, 1, 1);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+
+        selected = (SQLiteCursor) mListView.getSelectedItem();
+        assertEquals(mCursor.getString(1), selected.getString(1));
+        verify(mockMultiChoiceClickListener, times(1)).onClick(mDialog, 1, true);
+        // Verify that our multi-choice listener was invoked to update our tracker array
+        assertTrue(checkedTracker[0]);
+        assertTrue(checkedTracker[1]);
+        assertTrue(checkedTracker[2]);
+        assertFalse(checkedTracker[3]);
+
+        verifyNoMoreInteractions(mockMultiChoiceClickListener);
+    }
+}
diff --git a/tests/app/src/android/app/cts/AlertDialog_BuilderTest.java b/tests/app/src/android/app/cts/AlertDialog_BuilderTest.java
index ff9d772..d13585a 100644
--- a/tests/app/src/android/app/cts/AlertDialog_BuilderTest.java
+++ b/tests/app/src/android/app/cts/AlertDialog_BuilderTest.java
@@ -22,8 +22,6 @@
 import android.app.Instrumentation;
 import android.app.stubs.DialogStubActivity;
 import android.app.stubs.R;
-import android.content.ContentResolver;
-import android.content.ContentValues;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnCancelListener;
@@ -33,10 +31,7 @@
 import android.content.DialogInterface.OnMultiChoiceClickListener;
 import android.content.res.TypedArray;
 import android.cts.util.PollingCheck;
-import android.database.Cursor;
-import android.database.CursorWrapper;
 import android.graphics.drawable.Drawable;
-import android.provider.Contacts.People;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.view.KeyEvent;
@@ -61,9 +56,6 @@
     private AlertDialog mDialog;
     private Button mButton;
     private CharSequence mSelectedItem;
-    private final String[] mPROJECTION = new String[] {
-            People._ID, People.NAME
-    };
 
     private View mView;
     private ListView mListView;
@@ -419,27 +411,6 @@
         assertEquals(adapter, mListView.getAdapter());
     }
 
-    public void testSetCursor() throws Throwable {
-        preparePeople();
-        final Cursor c = mContext.getContentResolver().query(People.CONTENT_URI, mPROJECTION, null,
-                null, null);
-
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                mBuilder = new AlertDialog.Builder(mContext);
-                mBuilder.setCursor(c, mOnClickListener, People.NAME);
-                mDialog = mBuilder.show();
-                mListView = mDialog.getListView();
-                mListView.performItemClick(null, 0, 0);
-            }
-        });
-        mInstrumentation.waitForIdleSync();
-        final CursorWrapper selected = (CursorWrapper)mListView.getSelectedItem();
-        assertEquals(c.getString(1), selected.getString(1));
-        verify(mOnClickListener, times(1)).onClick(mDialog, 0);
-        verifyNoMoreInteractions(mOnClickListener);
-    }
-
     public void testSetMultiChoiceItemsWithParamInt() throws Throwable {
 
         final CharSequence[] items = mContext.getResources().getTextArray(
@@ -488,30 +459,6 @@
         assertEquals(items[0], mListView.getItemAtPosition(0));
     }
 
-    public void testSetMultiChoiceItemsWithParamCursor() throws Throwable {
-        preparePeople();
-        final Cursor c = mContext.getContentResolver().query(People.CONTENT_URI, mPROJECTION, null,
-                null, null);
-
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                mBuilder = new AlertDialog.Builder(mContext);
-                mBuilder.setMultiChoiceItems(c, People.NAME, People.NAME,
-                        mOnMultiChoiceClickListener);
-                mDialog = mBuilder.show();
-                mListView = mDialog.getListView();
-                mListView.performItemClick(null, 0, 0);
-                mListView.performItemClick(null, 1, 0);
-            }
-        });
-        mInstrumentation.waitForIdleSync();
-        final CursorWrapper selected = (CursorWrapper)mListView.getSelectedItem();
-        assertEquals(c.getString(1), selected.getString(1));
-        verify(mOnMultiChoiceClickListener, times(1)).onClick(mDialog, 0, true);
-        verify(mOnMultiChoiceClickListener, times(1)).onClick(mDialog, 1, true);
-        verifyNoMoreInteractions(mOnMultiChoiceClickListener);
-    }
-
     public void testSetSingleChoiceItemsWithParamInt() throws Throwable {
         final CharSequence[] items = mContext.getResources().getTextArray(
                 R.array.difficultyLevel);
@@ -534,39 +481,6 @@
         verifyNoMoreInteractions(mOnClickListener);
     }
 
-    private void preparePeople() {
-        final ContentResolver mResolver = mContext.getContentResolver();
-        mResolver.delete(People.CONTENT_URI, null, null);
-        final ContentValues values = new ContentValues();
-        values.put(People._ID, "1");
-        values.put(People.NAME, "name");
-        mResolver.insert(People.CONTENT_URI, values);
-    }
-
-    public void testSetSingleChoiceItemsWithParamCursor() throws Throwable {
-        final String[] PROJECTION = new String[] {
-                People._ID, People.NAME
-        };
-        preparePeople();
-        final Cursor c = mContext.getContentResolver().query(People.CONTENT_URI, PROJECTION, null,
-                null, null);
-
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                mBuilder = new AlertDialog.Builder(mContext);
-                mBuilder.setSingleChoiceItems(c, 0, People.NAME, mOnClickListener);
-                mDialog = mBuilder.show();
-                mListView = mDialog.getListView();
-                mListView.performItemClick(null, 0, 0);
-            }
-        });
-        mInstrumentation.waitForIdleSync();
-        final CursorWrapper selected = (CursorWrapper)mListView.getSelectedItem();
-        assertEquals(c.getString(1), selected.getString(1));
-        verify(mOnClickListener, times(1)).onClick(mDialog, 0);
-        verifyNoMoreInteractions(mOnClickListener);
-    }
-
     public void testSetSingleChoiceItemsWithParamCharSequence() throws Throwable {
         final CharSequence[] items = mContext.getResources().getTextArray(
                 R.array.difficultyLevel);
diff --git a/tests/camera/AndroidManifest.xml b/tests/camera/AndroidManifest.xml
index 2b39fca..f8c4a8e 100644
--- a/tests/camera/AndroidManifest.xml
+++ b/tests/camera/AndroidManifest.xml
@@ -68,6 +68,13 @@
             android:process=":camera2ActivityProcess">
         </activity>
 
+        <activity android:name="android.hardware.multiprocess.camera.cts.MediaRecorderCameraActivity"
+            android:label="RemoteMediaRecorderCameraActivity"
+            android:screenOrientation="landscape"
+            android:configChanges="keyboardHidden|orientation|screenSize"
+            android:process=":mediaRecorderCameraActivityProcess">
+        </activity>
+
     </application>
 
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/tests/camera/AndroidTest.xml b/tests/camera/AndroidTest.xml
index df15689..b54e1a22 100644
--- a/tests/camera/AndroidTest.xml
+++ b/tests/camera/AndroidTest.xml
@@ -21,5 +21,7 @@
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.camera.cts" />
         <option name="runtime-hint" value="12m7s" />
+        <!-- test-timeout unit is ms, value = 30 min -->
+        <option name="test-timeout" value="1800000" />
     </test>
 </configuration>
diff --git a/tests/camera/src/android/hardware/camera2/cts/AllocationTest.java b/tests/camera/src/android/hardware/camera2/cts/AllocationTest.java
index e6a13ff..2969753 100644
--- a/tests/camera/src/android/hardware/camera2/cts/AllocationTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/AllocationTest.java
@@ -95,8 +95,6 @@
         super.setContext(context);
         mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
         assertNotNull("Can't connect to camera manager!", mCameraManager);
-
-        RenderScriptSingleton.setContext(context);
     }
 
     @Override
@@ -111,6 +109,8 @@
         mCameraIterable = new CameraIterable();
         mSizeIterable = new SizeIterable();
         mResultIterable = new ResultIterable();
+
+        RenderScriptSingleton.setContext(getContext());
     }
 
     @Override
@@ -470,15 +470,14 @@
                     @Override
                     public void run(final Size size) throws CameraAccessException {
                         // Create a script graph that converts YUV to RGB
-                        final ScriptGraph scriptGraph = ScriptGraph.create()
+                        try (ScriptGraph scriptGraph = ScriptGraph.create()
                                 .configureInputWithSurface(size, YUV_420_888)
                                 .chainScript(ScriptYuvToRgb.class)
-                                .buildGraph();
+                                .buildGraph()) {
 
-                        if (VERBOSE) Log.v(TAG, "Prepared ScriptYuvToRgb for size " + size);
+                            if (VERBOSE) Log.v(TAG, "Prepared ScriptYuvToRgb for size " + size);
 
-                        // Run the graph against camera input and validate we get some input
-                        try {
+                            // Run the graph against camera input and validate we get some input
                             CaptureRequest request =
                                     configureAndCreateRequestForSurface(scriptGraph.getInputSurface()).build();
 
@@ -495,8 +494,6 @@
                             });
 
                             stopCapture();
-                        } finally {
-                            scriptGraph.close();
                         }
                     }
                 });
@@ -536,36 +533,37 @@
                 final Size maxSize = getMaxSize(
                         getSupportedSizeForFormat(YUV_420_888, camera.getId(), mCameraManager));
 
-                ScriptGraph scriptGraph = createGraphForYuvCroppedMeans(maxSize);
+                try (ScriptGraph scriptGraph = createGraphForYuvCroppedMeans(maxSize)) {
 
-                CaptureRequest.Builder req =
-                        configureAndCreateRequestForSurface(scriptGraph.getInputSurface());
+                    CaptureRequest.Builder req =
+                            configureAndCreateRequestForSurface(scriptGraph.getInputSurface());
 
-                // Take a shot with very low ISO and exposure time. Expect it to be black.
-                int minimumSensitivity = staticInfo.getSensitivityMinimumOrDefault();
-                long minimumExposure = staticInfo.getExposureMinimumOrDefault();
-                setManualCaptureRequest(req, minimumSensitivity, minimumExposure);
+                    // Take a shot with very low ISO and exposure time. Expect it to be black.
+                    int minimumSensitivity = staticInfo.getSensitivityMinimumOrDefault();
+                    long minimumExposure = staticInfo.getExposureMinimumOrDefault();
+                    setManualCaptureRequest(req, minimumSensitivity, minimumExposure);
 
-                CaptureRequest lowIsoExposureShot = req.build();
-                captureSingleShotAndExecute(lowIsoExposureShot, scriptGraph);
+                    CaptureRequest lowIsoExposureShot = req.build();
+                    captureSingleShotAndExecute(lowIsoExposureShot, scriptGraph);
 
-                float[] blackMeans = convertPixelYuvToRgb(scriptGraph.getOutputData());
+                    float[] blackMeans = convertPixelYuvToRgb(scriptGraph.getOutputData());
 
-                // Take a shot with very high ISO and exposure time. Expect it to be white.
-                int maximumSensitivity = staticInfo.getSensitivityMaximumOrDefault();
-                long maximumExposure = staticInfo.getExposureMaximumOrDefault();
-                setManualCaptureRequest(req, maximumSensitivity, maximumExposure);
+                    // Take a shot with very high ISO and exposure time. Expect it to be white.
+                    int maximumSensitivity = staticInfo.getSensitivityMaximumOrDefault();
+                    long maximumExposure = staticInfo.getExposureMaximumOrDefault();
+                    setManualCaptureRequest(req, maximumSensitivity, maximumExposure);
 
-                CaptureRequest highIsoExposureShot = req.build();
-                captureSingleShotAndExecute(highIsoExposureShot, scriptGraph);
+                    CaptureRequest highIsoExposureShot = req.build();
+                    captureSingleShotAndExecute(highIsoExposureShot, scriptGraph);
 
-                float[] whiteMeans = convertPixelYuvToRgb(scriptGraph.getOutputData());
+                    float[] whiteMeans = convertPixelYuvToRgb(scriptGraph.getOutputData());
 
-                // low iso + low exposure (first shot)
-                assertArrayWithinUpperBound("Black means too high", blackMeans, THRESHOLD_LOW);
+                    // low iso + low exposure (first shot)
+                    assertArrayWithinUpperBound("Black means too high", blackMeans, THRESHOLD_LOW);
 
-                // high iso + high exposure (second shot)
-                assertArrayWithinLowerBound("White means too low", whiteMeans, THRESHOLD_HIGH);
+                    // high iso + high exposure (second shot)
+                    assertArrayWithinLowerBound("White means too low", whiteMeans, THRESHOLD_HIGH);
+                }
             }
         });
     }
@@ -608,48 +606,49 @@
                     sensitivities[i] = sensitivityMin + delta * i;
                 }
 
-                ScriptGraph scriptGraph = createGraphForYuvCroppedMeans(maxSize);
+                try (ScriptGraph scriptGraph = createGraphForYuvCroppedMeans(maxSize)) {
 
-                CaptureRequest.Builder req =
-                        configureAndCreateRequestForSurface(scriptGraph.getInputSurface());
+                    CaptureRequest.Builder req =
+                            configureAndCreateRequestForSurface(scriptGraph.getInputSurface());
 
-                // Take burst shots with increasing sensitivity one after other.
-                for (int i = 0; i < NUM_STEPS; ++i) {
-                    setManualCaptureRequest(req, sensitivities[i], EXPOSURE_TIME_NS);
-                    captureSingleShotAndExecute(req.build(), scriptGraph);
-                    float[] means = convertPixelYuvToRgb(scriptGraph.getOutputData());
-                    rgbMeans.add(means);
+                    // Take burst shots with increasing sensitivity one after other.
+                    for (int i = 0; i < NUM_STEPS; ++i) {
+                        setManualCaptureRequest(req, sensitivities[i], EXPOSURE_TIME_NS);
+                        captureSingleShotAndExecute(req.build(), scriptGraph);
+                        float[] means = convertPixelYuvToRgb(scriptGraph.getOutputData());
+                        rgbMeans.add(means);
 
-                    if (VERBOSE) {
-                        Log.v(TAG, "testParamSensitivity - captured image " + i +
-                                " with RGB means: " + Arrays.toString(means));
+                        if (VERBOSE) {
+                            Log.v(TAG, "testParamSensitivity - captured image " + i +
+                                    " with RGB means: " + Arrays.toString(means));
+                        }
                     }
-                }
 
-                // Test that every consecutive image gets brighter.
-                for (int i = 0; i < rgbMeans.size() - 1; ++i) {
-                    float[] curMeans = rgbMeans.get(i);
-                    float[] nextMeans = rgbMeans.get(i+1);
+                    // Test that every consecutive image gets brighter.
+                    for (int i = 0; i < rgbMeans.size() - 1; ++i) {
+                        float[] curMeans = rgbMeans.get(i);
+                        float[] nextMeans = rgbMeans.get(i+1);
 
-                    assertArrayNotGreater(
-                            String.format("Shot with sensitivity %d should not have higher " +
-                                    "average means than shot with sensitivity %d",
-                                    sensitivities[i], sensitivities[i+1]),
-                            curMeans, nextMeans);
-                }
+                        assertArrayNotGreater(
+                                String.format("Shot with sensitivity %d should not have higher " +
+                                        "average means than shot with sensitivity %d",
+                                        sensitivities[i], sensitivities[i+1]),
+                                curMeans, nextMeans);
+                    }
 
-                // Test the min-max diff and ratios are within expected thresholds
-                float[] lastMeans = rgbMeans.get(NUM_STEPS - 1);
-                float[] firstMeans = rgbMeans.get(/*location*/0);
-                for (int i = 0; i < RGB_CHANNELS; ++i) {
-                    assertTrue(
-                            String.format("Sensitivity max-min diff too small (max=%f, min=%f)",
-                                    lastMeans[i], firstMeans[i]),
-                            lastMeans[i] - firstMeans[i] > THRESHOLD_MAX_MIN_DIFF);
-                    assertTrue(
-                            String.format("Sensitivity max-min ratio too small (max=%f, min=%f)",
-                                    lastMeans[i], firstMeans[i]),
-                            lastMeans[i] / firstMeans[i] > THRESHOLD_MAX_MIN_RATIO);
+                    // Test the min-max diff and ratios are within expected thresholds
+                    float[] lastMeans = rgbMeans.get(NUM_STEPS - 1);
+                    float[] firstMeans = rgbMeans.get(/*location*/0);
+                    for (int i = 0; i < RGB_CHANNELS; ++i) {
+                        assertTrue(
+                                String.format("Sensitivity max-min diff too small (max=%f, min=%f)",
+                                        lastMeans[i], firstMeans[i]),
+                                lastMeans[i] - firstMeans[i] > THRESHOLD_MAX_MIN_DIFF);
+                        assertTrue(
+                                String.format("Sensitivity max-min ratio too small (max=%f, min=%f)",
+                                        lastMeans[i], firstMeans[i]),
+                                lastMeans[i] / firstMeans[i] > THRESHOLD_MAX_MIN_RATIO);
+                    }
                 }
             }
         });
diff --git a/tests/camera/src/android/hardware/camera2/cts/CameraTestUtils.java b/tests/camera/src/android/hardware/camera2/cts/CameraTestUtils.java
index 8324490..35e792b 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -2079,7 +2079,8 @@
                 exifFocalLength, EXIF_FOCAL_LENGTH_ERROR_MARGIN);
         // More checks for focal length.
         collector.expectEquals("Exif focal length should match capture result",
-                validateFocalLength(result, staticInfo, collector), exifFocalLength);
+                validateFocalLength(result, staticInfo, collector),
+                exifFocalLength, EXIF_FOCAL_LENGTH_ERROR_MARGIN);
 
         // TAG_EXPOSURE_TIME
         // ExifInterface API gives exposure time value in the form of float instead of rational
@@ -2110,7 +2111,8 @@
                         apertureValue, EXIF_APERTURE_ERROR_MARGIN);
                 // More checks for aperture.
                 collector.expectEquals("Exif aperture length should match capture result",
-                        validateAperture(result, staticInfo, collector), apertureValue);
+                        validateAperture(result, staticInfo, collector),
+                        apertureValue, EXIF_APERTURE_ERROR_MARGIN);
             }
         }
 
diff --git a/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java b/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java
index a9f0008..02bb348 100644
--- a/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java
@@ -97,6 +97,8 @@
 
     @Override
     protected void setUp() throws Exception {
+        RenderScriptSingleton.setContext(getContext());
+
         super.setUp();
     }
 
@@ -110,8 +112,6 @@
     @Override
     public synchronized void setContext(Context context) {
         super.setContext(context);
-
-        RenderScriptSingleton.setContext(context);
     }
 
     /**
diff --git a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
index 81767a6..4d9a145 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
@@ -539,11 +539,22 @@
                 (maxJpegSize.getWidth() <= maxYuvSize.getWidth() &&
                         maxJpegSize.getHeight() <= maxYuvSize.getHeight()) : false;
 
+            float croppedWidth = (float)sensorSize.getWidth();
+            float croppedHeight = (float)sensorSize.getHeight();
+            float sensorAspectRatio = (float)sensorSize.getWidth() / (float)sensorSize.getHeight();
+            float maxYuvAspectRatio = (float)maxYuvSize.getWidth() / (float)maxYuvSize.getHeight();
+            if (sensorAspectRatio < maxYuvAspectRatio) {
+                croppedHeight = (float)sensorSize.getWidth() / maxYuvAspectRatio;
+            } else if (sensorAspectRatio > maxYuvAspectRatio) {
+                croppedWidth = (float)sensorSize.getHeight() * maxYuvAspectRatio;
+            }
+            Size croppedSensorSize = new Size((int)croppedWidth, (int)croppedHeight);
+
             boolean maxYuvMatchSensor =
-                    (maxYuvSize.getWidth() <= sensorSize.getWidth() * (1.0 + SIZE_ERROR_MARGIN) &&
-                     maxYuvSize.getWidth() >= sensorSize.getWidth() * (1.0 - SIZE_ERROR_MARGIN) &&
-                     maxYuvSize.getHeight() <= sensorSize.getHeight() * (1.0 + SIZE_ERROR_MARGIN) &&
-                     maxYuvSize.getHeight() >= sensorSize.getHeight() * (1.0 - SIZE_ERROR_MARGIN));
+                    (maxYuvSize.getWidth() <= croppedSensorSize.getWidth() * (1.0 + SIZE_ERROR_MARGIN) &&
+                     maxYuvSize.getWidth() >= croppedSensorSize.getWidth() * (1.0 - SIZE_ERROR_MARGIN) &&
+                     maxYuvSize.getHeight() <= croppedSensorSize.getHeight() * (1.0 + SIZE_ERROR_MARGIN) &&
+                     maxYuvSize.getHeight() >= croppedSensorSize.getHeight() * (1.0 - SIZE_ERROR_MARGIN));
 
             // No need to do null check since framework will generate the key if HAL don't supply
             boolean haveAeLock = CameraTestUtils.getValueNotNull(
@@ -627,8 +638,9 @@
                         haveFastSyncLatency);
                 assertTrue(
                         String.format("BURST-capable camera device %s max YUV size %s should be" +
-                                "close to active array size %s",
-                                mIds[counter], maxYuvSize.toString(), sensorSize.toString()),
+                                "close to active array size %s or cropped active array size %s",
+                                mIds[counter], maxYuvSize.toString(), sensorSize.toString(),
+                                croppedSensorSize.toString()),
                         maxYuvMatchSensor);
                 assertTrue(
                         String.format("BURST-capable camera device %s does not support AE lock",
diff --git a/tests/camera/src/android/hardware/camera2/cts/StaticMetadataTest.java b/tests/camera/src/android/hardware/camera2/cts/StaticMetadataTest.java
index 3f2d886..8ee0a41 100644
--- a/tests/camera/src/android/hardware/camera2/cts/StaticMetadataTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/StaticMetadataTest.java
@@ -116,9 +116,19 @@
                 // Max jpeg resolution must be very close to  sensor resolution
                 Size[] jpegSizes = mStaticInfo.getJpegOutputSizesChecked();
                 Size maxJpegSize = CameraTestUtils.getMaxSize(jpegSizes);
+                float croppedWidth = (float)sensorSize.getWidth();
+                float croppedHeight = (float)sensorSize.getHeight();
+                float sensorAspectRatio = (float)sensorSize.getWidth() / (float)sensorSize.getHeight();
+                float maxJpegAspectRatio = (float)maxJpegSize.getWidth() / (float)maxJpegSize.getHeight();
+                if (sensorAspectRatio < maxJpegAspectRatio) {
+                    croppedHeight = (float)sensorSize.getWidth() / maxJpegAspectRatio;
+                } else if (sensorAspectRatio > maxJpegAspectRatio) {
+                    croppedWidth = (float)sensorSize.getHeight() * maxJpegAspectRatio;
+                }
+                Size croppedSensorSize = new Size((int)croppedWidth, (int)croppedHeight);
                 mCollector.expectSizesAreSimilar(
-                    "Active array size and max JPEG size should be similar",
-                    sensorSize, maxJpegSize, SIZE_ERROR_MARGIN);
+                    "Active array size or cropped active array size and max JPEG size should be similar",
+                    croppedSensorSize, maxJpegSize, SIZE_ERROR_MARGIN);
             }
 
             // TODO: test all the keys mandatory for all capability devices.
diff --git a/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java b/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
index ce229b1..a9b4ad2 100644
--- a/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
@@ -402,7 +402,7 @@
                     continue;
                 }
                 takePictureTestByCamera(/*aeRegions*/null, /*awbRegions*/null, /*afRegions*/null,
-                        /*addAeTriggerCancel*/true, /*allocateBitmap*/true);
+                        /*addAeTriggerCancel*/false, /*allocateBitmap*/true);
             } finally {
                 closeDevice();
                 closeImageReader();
diff --git a/tests/camera/src/android/hardware/multiprocess/camera/cts/CameraEvictionTest.java b/tests/camera/src/android/hardware/multiprocess/camera/cts/CameraEvictionTest.java
index 9f1ae03..834d37cf 100644
--- a/tests/camera/src/android/hardware/multiprocess/camera/cts/CameraEvictionTest.java
+++ b/tests/camera/src/android/hardware/multiprocess/camera/cts/CameraEvictionTest.java
@@ -147,93 +147,7 @@
      * Test basic eviction scenarios for the Camera1 API.
      */
     public void testCamera1ActivityEviction() throws Throwable {
-
-        // Open a camera1 client in the main CTS process's activity
-        final Camera.ErrorCallback mockErrorCb1 = mock(Camera.ErrorCallback.class);
-        final boolean[] skip = {false};
-        runTestOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                // Open camera
-                mCamera = Camera.open();
-                if (mCamera == null) {
-                    skip[0] = true;
-                } else {
-                    mCamera.setErrorCallback(mockErrorCb1);
-                }
-                notifyFromUI();
-            }
-        });
-        waitForUI();
-
-        if (skip[0]) {
-            Log.i(TAG, "Skipping testCamera1ActivityEviction, device has no cameras.");
-            return;
-        }
-
-        verifyZeroInteractions(mockErrorCb1);
-
-        startRemoteProcess(Camera1Activity.class, "camera1ActivityProcess");
-
-        // Make sure camera was setup correctly in remote activity
-        List<ErrorLoggingService.LogEvent> events = null;
-        try {
-            events = mErrorServiceConnection.getLog(SETUP_TIMEOUT,
-                    TestConstants.EVENT_CAMERA_CONNECT);
-        } finally {
-            if (events != null) assertOnly(TestConstants.EVENT_CAMERA_CONNECT, events);
-        }
-
-        Thread.sleep(WAIT_TIME);
-
-        // Ensure UI thread has a chance to process callbacks.
-        runTestOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                Log.i("CTS", "Did something on UI thread.");
-                notifyFromUI();
-            }
-        });
-        waitForUI();
-
-        // Make sure we received correct callback in error listener, and nothing else
-        verify(mockErrorCb1, only()).onError(eq(Camera.CAMERA_ERROR_EVICTED), isA(Camera.class));
-        mCamera = null;
-
-        // Try to open the camera again (even though other TOP process holds the camera).
-        final boolean[] pass = {false};
-        runTestOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                // Open camera
-                try {
-                    mCamera = Camera.open();
-                } catch (RuntimeException e) {
-                    pass[0] = true;
-                }
-                notifyFromUI();
-            }
-        });
-        waitForUI();
-
-        assertTrue("Did not receive exception when opening camera while camera is held by a" +
-                " higher priority client process.", pass[0]);
-
-        // Verify that attempting to open the camera didn't cause anything weird to happen in the
-        // other process.
-        List<ErrorLoggingService.LogEvent> eventList2 = null;
-        boolean timeoutExceptionHit = false;
-        try {
-            eventList2 = mErrorServiceConnection.getLog(EVICTION_TIMEOUT);
-        } catch (TimeoutException e) {
-            timeoutExceptionHit = true;
-        }
-
-        assertNone("Remote camera service received invalid events: ", eventList2);
-        assertTrue("Remote camera service exited early", timeoutExceptionHit);
-        android.os.Process.killProcess(mProcessPid);
-        mProcessPid = -1;
-        forceCtsActivityToTop();
+        testAPI1ActivityEviction(Camera1Activity.class, "camera1ActivityProcess");
     }
 
     /**
@@ -342,6 +256,114 @@
         forceCtsActivityToTop();
     }
 
+
+    /**
+     * Test basic eviction scenarios for camera used in MediaRecoder
+     */
+    public void testMediaRecorderCameraActivityEviction() throws Throwable {
+        testAPI1ActivityEviction(MediaRecorderCameraActivity.class,
+                "mediaRecorderCameraActivityProcess");
+    }
+
+    /**
+     * Test basic eviction scenarios for Camera1 API.
+     *
+     * This test will open camera, create a higher priority process to run the specified activity,
+     * open camera again, and verify the right clients are evicted.
+     *
+     * @param activityKlass An activity to run in a higher priority process.
+     * @param processName The process name.
+     */
+    private void testAPI1ActivityEviction (java.lang.Class<?> activityKlass, String processName)
+            throws Throwable {
+        // Open a camera1 client in the main CTS process's activity
+        final Camera.ErrorCallback mockErrorCb1 = mock(Camera.ErrorCallback.class);
+        final boolean[] skip = {false};
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                // Open camera
+                mCamera = Camera.open();
+                if (mCamera == null) {
+                    skip[0] = true;
+                } else {
+                    mCamera.setErrorCallback(mockErrorCb1);
+                }
+                notifyFromUI();
+            }
+        });
+        waitForUI();
+
+        if (skip[0]) {
+            Log.i(TAG, "Skipping testCamera1ActivityEviction, device has no cameras.");
+            return;
+        }
+
+        verifyZeroInteractions(mockErrorCb1);
+
+        startRemoteProcess(activityKlass, processName);
+
+        // Make sure camera was setup correctly in remote activity
+        List<ErrorLoggingService.LogEvent> events = null;
+        try {
+            events = mErrorServiceConnection.getLog(SETUP_TIMEOUT,
+                    TestConstants.EVENT_CAMERA_CONNECT);
+        } finally {
+            if (events != null) assertOnly(TestConstants.EVENT_CAMERA_CONNECT, events);
+        }
+
+        Thread.sleep(WAIT_TIME);
+
+        // Ensure UI thread has a chance to process callbacks.
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                Log.i("CTS", "Did something on UI thread.");
+                notifyFromUI();
+            }
+        });
+        waitForUI();
+
+        // Make sure we received correct callback in error listener, and nothing else
+        verify(mockErrorCb1, only()).onError(eq(Camera.CAMERA_ERROR_EVICTED), isA(Camera.class));
+        mCamera = null;
+
+        // Try to open the camera again (even though other TOP process holds the camera).
+        final boolean[] pass = {false};
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                // Open camera
+                try {
+                    mCamera = Camera.open();
+                } catch (RuntimeException e) {
+                    pass[0] = true;
+                }
+                notifyFromUI();
+            }
+        });
+        waitForUI();
+
+        assertTrue("Did not receive exception when opening camera while camera is held by a" +
+                " higher priority client process.", pass[0]);
+
+        // Verify that attempting to open the camera didn't cause anything weird to happen in the
+        // other process.
+        List<ErrorLoggingService.LogEvent> eventList2 = null;
+        boolean timeoutExceptionHit = false;
+        try {
+            eventList2 = mErrorServiceConnection.getLog(EVICTION_TIMEOUT);
+        } catch (TimeoutException e) {
+            timeoutExceptionHit = true;
+        }
+
+        assertNone("Remote camera service received invalid events: ", eventList2);
+        assertTrue("Remote camera service exited early", timeoutExceptionHit);
+        android.os.Process.killProcess(mProcessPid);
+        mProcessPid = -1;
+        forceCtsActivityToTop();
+    }
+
     /**
      * Ensure the CTS activity becomes foreground again instead of launcher.
      */
diff --git a/tests/camera/src/android/hardware/multiprocess/camera/cts/MediaRecorderCameraActivity.java b/tests/camera/src/android/hardware/multiprocess/camera/cts/MediaRecorderCameraActivity.java
new file mode 100644
index 0000000..0558800
--- /dev/null
+++ b/tests/camera/src/android/hardware/multiprocess/camera/cts/MediaRecorderCameraActivity.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.multiprocess.camera.cts;
+
+import android.app.Activity;
+import android.camera.cts.R;
+import android.media.MediaRecorder;
+import android.os.Bundle;
+import android.os.Environment;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.ViewGroup;
+
+import java.io.File;
+
+/**
+ * Activity implementing basic access of camera using MediaRecorder API.
+ *
+ * <p />
+ * This will log all errors to {@link android.hardware.multiprocess.camera.cts.ErrorLoggingService}.
+ */
+public class MediaRecorderCameraActivity extends Activity implements SurfaceHolder.Callback {
+    private static final String TAG = "MediaRecorderCameraActivity";
+
+    private static final int VIDEO_WIDTH = 640;
+    private static final int VIDEO_HEIGHT = 480;
+    private static final int LAYOUT_WIDTH = VIDEO_WIDTH;
+    private static final int LAYOUT_HEIGHT = VIDEO_HEIGHT;
+
+    private final String OUTPUT_PATH = new File(Environment.getExternalStorageDirectory(),
+                "record.out").getAbsolutePath();
+
+    private File mOutFile;
+    private SurfaceView mSurfaceView;
+    private ErrorLoggingService.ErrorServiceConnection mErrorServiceConnection;
+    private MediaRecorder mMediaRecorder;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        Log.i(TAG, "onCreate called.");
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.surface_view);
+
+        mErrorServiceConnection = new ErrorLoggingService.ErrorServiceConnection(this);
+        mErrorServiceConnection.start();
+
+        mMediaRecorder = new MediaRecorder();
+    }
+
+    @Override
+    protected void onResume() {
+        Log.i(TAG, "onResume called.");
+        super.onResume();
+        try {
+
+            mSurfaceView = (SurfaceView)this.findViewById(R.id.surface_view);
+            ViewGroup.LayoutParams lp = mSurfaceView.getLayoutParams();
+            lp.width = LAYOUT_WIDTH;
+            lp.height = LAYOUT_HEIGHT;
+            mSurfaceView.setLayoutParams(lp);
+
+            SurfaceHolder holder = mSurfaceView.getHolder();
+            holder.setFixedSize(LAYOUT_WIDTH, LAYOUT_HEIGHT);
+            holder.addCallback(this);
+
+        } catch (Throwable e) {
+            mErrorServiceConnection.logAsync(TestConstants.EVENT_CAMERA_ERROR, TAG +
+                    " camera exception during connection: " + e);
+            Log.e(TAG, "Runtime error: " + e);
+        }
+    }
+
+    @Override
+    protected void onPause() {
+        Log.i(TAG, "onPause called.");
+        super.onPause();
+    }
+
+    @Override
+    protected void onDestroy() {
+        Log.i(TAG, "onDestroy called.");
+        super.onDestroy();
+        if (mErrorServiceConnection != null) {
+            mErrorServiceConnection.stop();
+            mErrorServiceConnection = null;
+        }
+
+        if (mOutFile != null && mOutFile.exists()) {
+            mOutFile.delete();
+        }
+
+        if (mMediaRecorder != null) {
+            mMediaRecorder.stop();
+            mMediaRecorder.release();
+        }
+    }
+
+    @Override
+    public void surfaceCreated(SurfaceHolder holder) {
+    }
+
+    @Override
+    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+        try {
+            mOutFile = new File(OUTPUT_PATH);
+            mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
+            mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
+            mMediaRecorder.setPreviewDisplay(mSurfaceView.getHolder().getSurface());
+            mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
+            mMediaRecorder.setVideoSize(VIDEO_WIDTH, VIDEO_HEIGHT);
+            mMediaRecorder.setOutputFile(OUTPUT_PATH);
+            mMediaRecorder.prepare();
+            mMediaRecorder.start();
+
+            mErrorServiceConnection.logAsync(TestConstants.EVENT_CAMERA_CONNECT,
+                    TAG + " camera connected");
+        } catch (Throwable e) {
+            mErrorServiceConnection.logAsync(TestConstants.EVENT_CAMERA_ERROR, TAG +
+                    " camera exception during connection: " + e);
+            Log.e(TAG, "Runtime error: " + e);
+        }
+    }
+
+    @Override
+    public void surfaceDestroyed(SurfaceHolder holder) {
+    }
+}
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index 185fc56..56475fd 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -31,13 +31,6 @@
   bug: 17595050
 },
 {
-  description: "test fails on devices with no telephony",
-  names: [
-    "android.calllog.cts.CallLogBackupTest#testSingleCallBackup"
-  ],
-  bug: 23776099
-},
-{
   description: "test fails on some devices",
   names: [
     "android.dumpsys.cts.DumpsysHostTest#testBatterystatsOutput",
@@ -342,5 +335,22 @@
       "android.security.cts.MediaCryptoTest#testMediaCryptoWidevine"
   ],
   bug: 27218502
+},
+{
+  description: "Still investigating this, root cause unknown yet",
+  bug: 27578806,
+  names: ["com.android.cts.cpptools.RunAsHostTest#testRunAs"]
+},
+{
+  description: "Some SensorBatchingTest cases fails due to test imperection",
+  names: [
+      "android.hardware.cts.SensorBatchingTests#testGyroscope_fastest_batching",
+      "android.hardware.cts.SensorBatchingTests#testGravity_50hz_batching",
+      "android.hardware.cts.SensorBatchingTests#testGravity_fastest_batching",
+      "android.hardware.cts.SensorBatchingTests#testLinearAcceleration_50hz_batching",
+      "android.hardware.cts.SensorBatchingTests#testLinearAcceleration_fastest_batching",
+      "android.hardware.cts.SensorBatchingTests#testRotationVector_50hz_batching"
+      ],
+  bug: 27534791
 }
 ]
diff --git a/tests/filesystem/AndroidTest.xml b/tests/filesystem/AndroidTest.xml
index 1962357..d05134d 100644
--- a/tests/filesystem/AndroidTest.xml
+++ b/tests/filesystem/AndroidTest.xml
@@ -20,6 +20,6 @@
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.filesystem.cts" />
-        <option name="runtime-hint" value="9m" />
+        <option name="runtime-hint" value="22m48s" />
     </test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/tests/tests/automotive/Android.mk b/tests/fragment/Android.mk
similarity index 71%
copy from tests/tests/automotive/Android.mk
copy to tests/fragment/Android.mk
index abef2ac..2352564 100644
--- a/tests/tests/automotive/Android.mk
+++ b/tests/fragment/Android.mk
@@ -16,17 +16,19 @@
 
 include $(CLEAR_VARS)
 
-LOCAL_PACKAGE_NAME := CtsAutomotiveTestCases
+LOCAL_PACKAGE_NAME := CtsFragmentTestCases
 
-# Don't include this package in any target.
-LOCAL_MODULE_TAGS := optional
+# don't include this package in any target
+LOCAL_MODULE_TAGS := tests
 
-# When built, explicitly put it in the data partition.
+# and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_DEX_PREOPT := false
 
-LOCAL_JAVA_LIBRARIES := android.car
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util android-support-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
@@ -35,4 +37,4 @@
 
 LOCAL_SDK_VERSION := current
 
-include $(BUILD_CTS_PACKAGE)
+include $(BUILD_PACKAGE)
diff --git a/tests/fragment/AndroidManifest.xml b/tests/fragment/AndroidManifest.xml
new file mode 100644
index 0000000..05027b5
--- /dev/null
+++ b/tests/fragment/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.fragment.cts">
+
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+
+        <activity android:name=".FragmentTestActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="android.fragment.cts"
+                     android:label="CTS tests of android.app Fragments" />
+
+</manifest>
+
diff --git a/tests/tests/automotive/AndroidTest.xml b/tests/fragment/AndroidTest.xml
similarity index 81%
copy from tests/tests/automotive/AndroidTest.xml
copy to tests/fragment/AndroidTest.xml
index b4af1f5..f3e302a 100644
--- a/tests/tests/automotive/AndroidTest.xml
+++ b/tests/fragment/AndroidTest.xml
@@ -13,12 +13,12 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<configuration description="Config for CTS Automotive test cases">
+<configuration description="Configuration for app.usage Tests">
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
         <option name="cleanup-apks" value="true" />
-        <option name="test-file-name" value="CtsAutomotiveTestCases.apk" />
+        <option name="test-file-name" value="CtsFragmentTestCases.apk" />
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="android.support.car.cts" />
+        <option name="package" value="android.fragment.cts" />
     </test>
-</configuration>
+</configuration>
\ No newline at end of file
diff --git a/tests/fragment/res/layout/strict_view_fragment.xml b/tests/fragment/res/layout/strict_view_fragment.xml
new file mode 100644
index 0000000..324f8d0
--- /dev/null
+++ b/tests/fragment/res/layout/strict_view_fragment.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright 2016, The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+-->
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:id="@+id/text1" />
diff --git a/tests/fragment/src/android/fragment/cts/FragmentLifecycleTest.java b/tests/fragment/src/android/fragment/cts/FragmentLifecycleTest.java
new file mode 100644
index 0000000..01c4e70
--- /dev/null
+++ b/tests/fragment/src/android/fragment/cts/FragmentLifecycleTest.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package android.fragment.cts;
+
+import android.app.FragmentManager;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.View;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.TestCase.*;
+
+@RunWith(AndroidJUnit4.class)
+public class FragmentLifecycleTest {
+
+    @Rule
+    public ActivityTestRule<FragmentTestActivity> mActivityRule =
+            new ActivityTestRule<FragmentTestActivity>(FragmentTestActivity.class);
+
+    @Test
+    @MediumTest
+    public void basicLifecycle() throws Throwable {
+        final FragmentManager fm = mActivityRule.getActivity().getFragmentManager();
+        final StrictFragment strictFragment = new StrictFragment();
+
+        // Add fragment; StrictFragment will throw if it detects any violation
+        // in standard lifecycle method ordering or expected preconditions.
+        fm.beginTransaction().add(strictFragment, "EmptyHeadless").commit();
+        executePendingTransactions(fm);
+
+        assertTrue("fragment is not added", strictFragment.isAdded());
+        assertFalse("fragment is detached", strictFragment.isDetached());
+        assertTrue("fragment is not resumed", strictFragment.isResumed());
+
+        // Test removal as well; StrictFragment will throw here too.
+        fm.beginTransaction().remove(strictFragment).commit();
+        executePendingTransactions(fm);
+
+        assertFalse("fragment is added", strictFragment.isAdded());
+        assertFalse("fragment is resumed", strictFragment.isResumed());
+
+        // This one is perhaps counterintuitive; "detached" means specifically detached
+        // but still managed by a FragmentManager. The .remove call above
+        // should not enter this state.
+        assertFalse("fragment is detached", strictFragment.isDetached());
+    }
+
+    @Test
+    @MediumTest
+    public void detachment() throws Throwable {
+        final FragmentManager fm = mActivityRule.getActivity().getFragmentManager();
+        final StrictFragment f1 = new StrictFragment();
+        final StrictFragment f2 = new StrictFragment();
+
+        fm.beginTransaction().add(f1, "1").add(f2, "2").commit();
+        executePendingTransactions(fm);
+
+        assertTrue("fragment 1 is not added", f1.isAdded());
+        assertTrue("fragment 2 is not added", f2.isAdded());
+
+        // Test detaching fragments using StrictFragment to throw on errors.
+        fm.beginTransaction().detach(f1).detach(f2).commit();
+        executePendingTransactions(fm);
+
+        assertTrue("fragment 1 is not detached", f1.isDetached());
+        assertTrue("fragment 2 is not detached", f2.isDetached());
+        assertFalse("fragment 1 is added", f1.isAdded());
+        assertFalse("fragment 2 is added", f2.isAdded());
+
+        // Only reattach f1; leave v2 detached.
+        fm.beginTransaction().attach(f1).commit();
+        executePendingTransactions(fm);
+
+        assertTrue("fragment 1 is not added", f1.isAdded());
+        assertFalse("fragment 1 is detached", f1.isDetached());
+        assertTrue("fragment 2 is not detached", f2.isDetached());
+
+        // Remove both from the FragmentManager.
+        fm.beginTransaction().remove(f1).remove(f2).commit();
+        executePendingTransactions(fm);
+
+        assertFalse("fragment 1 is added", f1.isAdded());
+        assertFalse("fragment 2 is added", f2.isAdded());
+        assertFalse("fragment 1 is detached", f1.isDetached());
+        assertFalse("fragment 2 is detached", f2.isDetached());
+    }
+
+    @Test
+    @MediumTest
+    public void basicBackStack() throws Throwable {
+        final FragmentManager fm = mActivityRule.getActivity().getFragmentManager();
+        final StrictFragment f1 = new StrictFragment();
+        final StrictFragment f2 = new StrictFragment();
+
+        // Add a fragment normally to set up
+        fm.beginTransaction().add(f1, "1").commit();
+        executePendingTransactions(fm);
+
+        assertTrue("fragment 1 is not added", f1.isAdded());
+
+        // Remove the first one and add a second. We're not using replace() here since
+        // these fragments are headless and as of this test writing, replace() only works
+        // for fragments with views and a container view id.
+        // Add it to the back stack so we can pop it afterwards.
+        fm.beginTransaction().remove(f1).add(f2, "2").addToBackStack("stack1").commit();
+        executePendingTransactions(fm);
+
+        assertFalse("fragment 1 is added", f1.isAdded());
+        assertTrue("fragment 2 is not added", f2.isAdded());
+
+        // Test popping the stack
+        fm.popBackStack();
+        executePendingTransactions(fm);
+
+        assertFalse("fragment 2 is added", f2.isAdded());
+        assertTrue("fragment 1 is not added", f1.isAdded());
+    }
+
+    @Test
+    @MediumTest
+    public void attachBackStack() throws Throwable {
+        final FragmentManager fm = mActivityRule.getActivity().getFragmentManager();
+        final StrictFragment f1 = new StrictFragment();
+        final StrictFragment f2 = new StrictFragment();
+
+        // Add a fragment normally to set up
+        fm.beginTransaction().add(f1, "1").commit();
+        executePendingTransactions(fm);
+
+        assertTrue("fragment 1 is not added", f1.isAdded());
+
+        fm.beginTransaction().detach(f1).add(f2, "2").addToBackStack("stack1").commit();
+        executePendingTransactions(fm);
+
+        assertTrue("fragment 1 is not detached", f1.isDetached());
+        assertFalse("fragment 2 is detached", f2.isDetached());
+        assertFalse("fragment 1 is added", f1.isAdded());
+        assertTrue("fragment 2 is not added", f2.isAdded());
+    }
+
+    @Test
+    @MediumTest
+    public void viewLifecycle() throws Throwable {
+        // Test basic lifecycle when the fragment creates a view
+
+        final FragmentManager fm = mActivityRule.getActivity().getFragmentManager();
+        final StrictViewFragment f1 = new StrictViewFragment();
+
+        fm.beginTransaction().add(android.R.id.content, f1).commit();
+        executePendingTransactions(fm);
+
+        assertTrue("fragment 1 is not added", f1.isAdded());
+        final View view = f1.getView();
+        assertNotNull("fragment 1 returned null from getView", view);
+        assertTrue("fragment 1's view is not attached to a window", view.isAttachedToWindow());
+
+        fm.beginTransaction().remove(f1).commit();
+        executePendingTransactions(fm);
+
+        assertFalse("fragment 1 is added", f1.isAdded());
+        assertNull("fragment 1 returned non-null from getView after removal", f1.getView());
+        assertFalse("fragment 1's previous view is still attached to a window",
+                view.isAttachedToWindow());
+    }
+
+    @Test
+    @MediumTest
+    public void viewReplace() throws Throwable {
+        // Replace one view with another, then reverse it with the back stack
+
+        final FragmentManager fm = mActivityRule.getActivity().getFragmentManager();
+        final StrictViewFragment f1 = new StrictViewFragment();
+        final StrictViewFragment f2 = new StrictViewFragment();
+
+        fm.beginTransaction().add(android.R.id.content, f1).commit();
+        executePendingTransactions(fm);
+
+        assertTrue("fragment 1 is not added", f1.isAdded());
+
+        View origView1 = f1.getView();
+        assertNotNull("fragment 1 returned null view", origView1);
+        assertTrue("fragment 1's view not attached", origView1.isAttachedToWindow());
+
+        fm.beginTransaction().replace(android.R.id.content, f2).addToBackStack("stack1").commit();
+        executePendingTransactions(fm);
+
+        assertFalse("fragment 1 is added", f1.isAdded());
+        assertTrue("fragment 2 is added", f2.isAdded());
+        assertNull("fragment 1 returned non-null view", f1.getView());
+        assertFalse("fragment 1's old view still attached", origView1.isAttachedToWindow());
+        View origView2 = f2.getView();
+        assertNotNull("fragment 2 returned null view", origView2);
+        assertTrue("fragment 2's view not attached", origView2.isAttachedToWindow());
+
+        fm.popBackStack();
+        executePendingTransactions(fm);
+
+        assertTrue("fragment 1 is not added", f1.isAdded());
+        assertFalse("fragment 2 is added", f2.isAdded());
+        assertNull("fragment 2 returned non-null view", f2.getView());
+        assertFalse("fragment 2's view still attached", origView2.isAttachedToWindow());
+        View newView1 = f1.getView();
+        assertNotSame("fragment 1 had same view from last attachment", origView1, newView1);
+        assertTrue("fragment 1's view not attached", newView1.isAttachedToWindow());
+    }
+
+    private void executePendingTransactions(final FragmentManager fm) throws Throwable {
+        mActivityRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                fm.executePendingTransactions();
+            }
+        });
+    }
+}
diff --git a/tests/fragment/src/android/fragment/cts/FragmentTestActivity.java b/tests/fragment/src/android/fragment/cts/FragmentTestActivity.java
new file mode 100644
index 0000000..fd26d0a
--- /dev/null
+++ b/tests/fragment/src/android/fragment/cts/FragmentTestActivity.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package android.fragment.cts;
+
+import android.app.Activity;
+
+public class FragmentTestActivity extends Activity {
+}
diff --git a/tests/fragment/src/android/fragment/cts/StrictFragment.java b/tests/fragment/src/android/fragment/cts/StrictFragment.java
new file mode 100644
index 0000000..f0c4a8a
--- /dev/null
+++ b/tests/fragment/src/android/fragment/cts/StrictFragment.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package android.fragment.cts;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.os.Bundle;
+
+/**
+ * This fragment watches its primary lifecycle events and throws IllegalStateException
+ * if any of them are called out of order or from a bad/unexpected state.
+ */
+public class StrictFragment extends Fragment {
+    public static final int DETACHED = 0;
+    public static final int ATTACHED = 1;
+    public static final int CREATED = 2;
+    public static final int ACTIVITY_CREATED = 3;
+    public static final int STARTED = 4;
+    public static final int RESUMED = 5;
+
+    int mState;
+
+    boolean mCalledOnAttach, mCalledOnCreate, mCalledOnActivityCreated,
+            mCalledOnStart, mCalledOnResume, mCalledOnSaveInstanceState,
+            mCalledOnPause, mCalledOnStop, mCalledOnDestroy, mCalledOnDetach;
+
+    static String stateToString(int state) {
+        switch (state) {
+            case DETACHED: return "DETACHED";
+            case ATTACHED: return "ATTACHED";
+            case CREATED: return "CREATED";
+            case ACTIVITY_CREATED: return "ACTIVITY_CREATED";
+            case STARTED: return "STARTED";
+            case RESUMED: return "RESUMED";
+        }
+        return "(unknown " + state + ")";
+    }
+
+    public void checkGetActivity() {
+        if (getActivity() == null) {
+            throw new IllegalStateException("getActivity() returned null at unexpected time");
+        }
+    }
+
+    public void checkState(String caller, int... expected) {
+        if (expected == null || expected.length == 0) {
+            throw new IllegalArgumentException("must supply at least one expected state");
+        }
+        for (int expect : expected) {
+            if (mState == expect) {
+                return;
+            }
+        }
+        final StringBuilder expectString = new StringBuilder(stateToString(expected[0]));
+        for (int i = 1; i < expected.length; i++) {
+            expectString.append(" or ").append(stateToString(expected[i]));
+        }
+        throw new IllegalStateException(caller + " called while fragment was "
+                + stateToString(mState) + "; expected " + expectString.toString());
+    }
+
+    public void checkStateAtLeast(String caller, int minState) {
+        if (mState < minState) {
+            throw new IllegalStateException(caller + " called while fragment was "
+                    + stateToString(mState) + "; expected at least " + stateToString(minState));
+        }
+    }
+
+    @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        mCalledOnAttach = true;
+        checkState("onAttach", DETACHED);
+        mState = ATTACHED;
+        checkGetActivity();
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        if (mCalledOnCreate) {
+            throw new IllegalStateException("onCreate called more than once");
+        }
+        mCalledOnCreate = true;
+        checkState("onCreate", ATTACHED);
+        mState = CREATED;
+        checkGetActivity();
+    }
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        mCalledOnActivityCreated = true;
+        checkState("onActivityCreated", ATTACHED, CREATED);
+        mState = ACTIVITY_CREATED;
+        checkGetActivity();
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        mCalledOnStart = true;
+        checkState("onStart", ACTIVITY_CREATED);
+        mState = STARTED;
+        checkGetActivity();
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        mCalledOnResume = true;
+        checkState("onResume", STARTED);
+        mState = RESUMED;
+        checkGetActivity();
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        mCalledOnSaveInstanceState = true;
+        checkGetActivity();
+        checkStateAtLeast("onSaveInstanceState", STARTED);
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        mCalledOnPause = true;
+        checkState("onPause", RESUMED);
+        mState = STARTED;
+        checkGetActivity();
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+        mCalledOnStop = true;
+        checkState("onStop", STARTED);
+        mState = CREATED;
+        checkGetActivity();
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        mCalledOnDestroy = true;
+        checkState("onDestroy", CREATED);
+        mState = ATTACHED;
+        checkGetActivity();
+    }
+
+    @Override
+    public void onDetach() {
+        super.onDetach();
+        mCalledOnDetach = true;
+        checkState("onDestroy", CREATED, ATTACHED);
+        mState = DETACHED;
+        checkGetActivity();
+    }
+}
diff --git a/tests/fragment/src/android/fragment/cts/StrictViewFragment.java b/tests/fragment/src/android/fragment/cts/StrictViewFragment.java
new file mode 100644
index 0000000..8c0ab51
--- /dev/null
+++ b/tests/fragment/src/android/fragment/cts/StrictViewFragment.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package android.fragment.cts;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class StrictViewFragment extends StrictFragment {
+    boolean mOnCreateViewCalled, mOnViewCreatedCalled, mOnDestroyViewCalled;
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        checkGetActivity();
+        checkState("onCreateView", CREATED);
+        final View result = inflater.inflate(R.layout.strict_view_fragment, container, false);
+        mOnCreateViewCalled = true;
+        return result;
+    }
+
+    @Override
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+        if (view == null) {
+            throw new IllegalArgumentException("onViewCreated view argument should not be null");
+        }
+        checkGetActivity();
+        checkState("onViewCreated", CREATED);
+        mOnViewCreatedCalled = true;
+    }
+
+    @Override
+    public void onDestroyView() {
+        super.onDestroyView();
+        if (getView() == null) {
+            throw new IllegalStateException("getView returned null in onDestroyView");
+        }
+        checkGetActivity();
+        checkState("onDestroyView", CREATED);
+        mOnDestroyViewCalled = true;
+    }
+}
diff --git a/tests/sample/AndroidManifest.xml b/tests/sample/AndroidManifest.xml
index 2f32e86..b27e0d3 100755
--- a/tests/sample/AndroidManifest.xml
+++ b/tests/sample/AndroidManifest.xml
@@ -19,6 +19,7 @@
     package="android.sample.cts">
 
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <application>
         <uses-library android:name="android.test.runner" />
         <activity android:name="android.sample.SampleDeviceActivity" >
diff --git a/tests/sample/AndroidTest.xml b/tests/sample/AndroidTest.xml
index ae790fb..86bc616 100644
--- a/tests/sample/AndroidTest.xml
+++ b/tests/sample/AndroidTest.xml
@@ -14,6 +14,12 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Sample test cases">
+    <target_preparer class=
+        "com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="device" />
+        <option name="config-filename" value="CtsSampleDeviceTestCases" />
+        <option name="version" value="1.0" />
+    </target_preparer>
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsSampleDeviceTestCases.apk" />
diff --git a/tests/sample/DynamicConfig.xml b/tests/sample/DynamicConfig.xml
new file mode 100644
index 0000000..515dc01
--- /dev/null
+++ b/tests/sample/DynamicConfig.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<dynamicConfig>
+    <entry key="report-log-name">
+        <value>SampleTestMetrics</value>
+    </entry>
+    <entry key="testMultiplication-stream-name">
+        <value>testMultiplicationMetrics</value>
+    </entry>
+    <entry key="testCountUp-stream-name">
+        <value>testCountUpMetrics</value>
+    </entry>
+    <entry key="testCountDown-stream-name">
+        <value>testCountDownMetrics</value>
+    </entry>
+    <entry key="testSort-stream-name">
+        <value>testSortMetrics</value>
+    </entry>
+</dynamicConfig>
\ No newline at end of file
diff --git a/tests/sample/src/android/sample/cts/SampleDeviceReportLogTest.java b/tests/sample/src/android/sample/cts/SampleDeviceReportLogTest.java
new file mode 100644
index 0000000..8985bd6
--- /dev/null
+++ b/tests/sample/src/android/sample/cts/SampleDeviceReportLogTest.java
@@ -0,0 +1,166 @@
+/*
+ * 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.sample.cts;
+
+import android.sample.SampleDeviceActivity;
+import android.test.ActivityInstrumentationTestCase2;
+
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.DynamicConfigDeviceSide;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+
+/**
+ * A simple compatibility test which includes results in the report.
+ *
+ * This class has 3 dummy tests that create report logs and log dummy metrics.
+ */
+public class SampleDeviceReportLogTest
+        extends ActivityInstrumentationTestCase2<SampleDeviceActivity> {
+
+    /**
+     * The default name for metrics report log file.
+     */
+    private String DEFAULT_REPORT_LOG_NAME = "DefaultMetrics";
+
+    /**
+     * The default name for a metrics stream.
+     */
+    private String DEFAULT_STREAM_NAME = "DefaultStream";
+
+    /**
+     * Sample numbers used by the sample tests.
+     */
+    private static final int MULTIPLICATION_NUMBER_1 = 23;
+    private static final int MULTIPLICATION_NUMBER_2 = 97;
+    private static final int MULTIPLICATION_RESULT = 2231;
+    private static final int COUNT_START = 1;
+    private static final int COUNT_END = 1000;
+
+    private static final String EXPECTED_PRODUCT_TAG = "Expected Product";
+    private static final String ACTUAL_PRODUCT_TAG = "Actual Product";
+    private static final String START_TAG = "Count Start";
+    private static final String END_TAG = "Actual End";
+
+    /**
+     * Constructor which passes the class of the activity to be instrumented.
+     */
+    public SampleDeviceReportLogTest() {
+        super(SampleDeviceActivity.class);
+    }
+
+    /**
+     * Sample test that creates and logs test metrics into a report log.
+     */
+    public void testMultiplication() {
+        // Perform test.
+        int product = MULTIPLICATION_NUMBER_1 * MULTIPLICATION_NUMBER_2;
+        assertTrue("Multiplication result do not match", product == MULTIPLICATION_RESULT);
+
+        // Log metrics from the test.
+        String reportLogName = getReportLogName();
+        String streamName = getStreamName("testMultiplication-stream-name");
+        DeviceReportLog reportLog = new DeviceReportLog(reportLogName, streamName);
+        reportLog.addValue(EXPECTED_PRODUCT_TAG, 1.0 * MULTIPLICATION_RESULT, ResultType.NEUTRAL,
+                ResultUnit.NONE);
+        reportLog.addValue(ACTUAL_PRODUCT_TAG, 1.0 * product, ResultType.NEUTRAL, ResultUnit.NONE);
+        reportLog.setSummary(ACTUAL_PRODUCT_TAG, 1.0 * product, ResultType.NEUTRAL, ResultUnit.NONE);
+        reportLog.submit(getInstrumentation());
+    }
+
+    /**
+     * Sample test to check counting up.
+     */
+    public void testCountUp() {
+        String streamName = getStreamName("testCountUp-stream-name");
+        countHelper(1, streamName);
+    }
+
+    /**
+     * Sample test to check counting down.
+     */
+    public void testCountDown() {
+        String streamName = getStreamName("testCountDown-stream-name");
+        countHelper(2, streamName);
+    }
+
+    /**
+     * Sample test function that counts up or down based on test parameter. It creates and logs test
+     * metrics into a report log.
+     * @param testParameter {@link String} parameter passed by caller test function.
+     * @param streamName {@link String} name of the report log stream retrieved from dynamic config.
+     */
+    private void countHelper(int testParameter, String streamName) {
+        // Perform test.
+        int start;
+        int end;
+        if (testParameter == 1) {
+            start = COUNT_START;
+            end = COUNT_END;
+            for (int i = start; i <= end;) {
+                i++;
+            }
+        } else {
+            start = COUNT_END;
+            end = COUNT_START;
+            for (int i = start; i >= end;) {
+                i--;
+            }
+        }
+
+        // Log metrics.
+        String reportLogName = getReportLogName();
+        DeviceReportLog reportLog = new DeviceReportLog(reportLogName, streamName);
+        reportLog.addValue(streamName + START_TAG, 1.0 * start, ResultType.NEUTRAL, ResultUnit.NONE);
+        reportLog.addValue(streamName + END_TAG, 1.0 * end, ResultType.NEUTRAL, ResultUnit.NONE);
+        reportLog.setSummary(streamName + END_TAG, 1.0 * end, ResultType.NEUTRAL, ResultUnit.NONE);
+        reportLog.submit(getInstrumentation());
+    }
+
+    /**
+     * Retreives name of report log from dynamic config.
+     *
+     * @return {@link String} name of the report log.
+     */
+    private String getReportLogName() {
+        try {
+            DynamicConfigDeviceSide dynamicConfig = new DynamicConfigDeviceSide(
+                    "CtsSampleDeviceTestCases");
+            return dynamicConfig.getValues("report-log-name").get(0);
+        } catch (Exception e) {
+            // Do nothing.
+        }
+        return DEFAULT_REPORT_LOG_NAME ;
+    }
+
+
+    /**
+     * Retreives name of metrics stream from dynamic config.
+     *
+     * @param key The key in dynamic config containing stream name.
+     * @return {@link String} name of the stream.
+     */
+    private String getStreamName(String key) {
+        try {
+            DynamicConfigDeviceSide dynamicConfig = new DynamicConfigDeviceSide(
+                    "CtsSampleDeviceTestCases");
+            return dynamicConfig.getValues(key).get(0);
+        } catch (Exception e) {
+            // Do nothing.
+        }
+        return DEFAULT_STREAM_NAME ;
+    }
+}
diff --git a/tests/sample/src/android/sample/cts/SampleDeviceResultTest.java b/tests/sample/src/android/sample/cts/SampleDeviceResultTest.java
index 7bd434e..2f6ce78 100644
--- a/tests/sample/src/android/sample/cts/SampleDeviceResultTest.java
+++ b/tests/sample/src/android/sample/cts/SampleDeviceResultTest.java
@@ -19,6 +19,7 @@
 import android.test.ActivityInstrumentationTestCase2;
 
 import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.DynamicConfigDeviceSide;
 import com.android.compatibility.common.util.MeasureRun;
 import com.android.compatibility.common.util.MeasureTime;
 import com.android.compatibility.common.util.ResultType;
@@ -36,6 +37,16 @@
 public class SampleDeviceResultTest extends ActivityInstrumentationTestCase2<SampleDeviceActivity> {
 
     /**
+     * The default name for metrics report log file.
+     */
+    private String DEFAULT_REPORT_LOG_NAME = "DefaultMetrics";
+
+    /**
+     * The default name for a metrics stream.
+     */
+    private String DEFAULT_STREAM_NAME = "DefaultStream";
+
+    /**
      * The number of times to repeat the test.
      */
     private static final int REPEAT = 5;
@@ -53,6 +64,43 @@
     }
 
     /**
+     * Measures the time taken to sort an array.
+     */
+    public void testSort() throws Exception {
+        // MeasureTime runs the workload N times and records the time taken by each run.
+        double[] result = MeasureTime.measure(REPEAT, new MeasureRun() {
+            /**
+             * The size of the array to sort.
+             */
+            private static final int ARRAY_SIZE = 100000;
+            private int[] array;
+            @Override
+            public void prepare(int i) throws Exception {
+                array = createArray(ARRAY_SIZE);
+            }
+            @Override
+            public void run(int i) throws Exception {
+                Arrays.sort(array);
+                assertTrue("Array not sorted", isSorted(array));
+            }
+        });
+        // Compute the stats.
+        Stat.StatResult stat = Stat.getStat(result);
+        // Create a new report to hold the metrics.
+        String reportLogName = getReportLogName();
+        String streamName = getStreamName("testSort-stream-name");
+        DeviceReportLog reportLog = new DeviceReportLog(reportLogName, streamName);
+        // Add the results to the report.
+        reportLog.addValues("Times", result, ResultType.LOWER_BETTER, ResultUnit.MS);
+        reportLog.addValue("Min", stat.mMin, ResultType.LOWER_BETTER, ResultUnit.MS);
+        reportLog.addValue("Max", stat.mMax, ResultType.LOWER_BETTER, ResultUnit.MS);
+        // Every report must have a summary,
+        reportLog.setSummary("Average", stat.mAverage, ResultType.LOWER_BETTER, ResultUnit.MS);
+        // Submit the report to the given instrumentation.
+        reportLog.submit(getInstrumentation());
+    }
+
+    /**
      * Creates an array filled with random numbers of the given size.
      */
     private static int[] createArray(int size) {
@@ -77,38 +125,37 @@
     }
 
     /**
-     * Measures the time taken to sort an array.
+     * Retreives name of report log from dynamic config.
+     *
+     * @return {@link String} name of the report log.
      */
-    public void testSort() throws Exception {
-        // MeasureTime runs the workload N times and records the time taken by each run.
-        double[] result = MeasureTime.measure(REPEAT, new MeasureRun() {
-            /**
-             * The size of the array to sort.
-             */
-            private static final int ARRAY_SIZE = 100000;
-            private int[] array;
-            @Override
-            public void prepare(int i) throws Exception {
-                array = createArray(ARRAY_SIZE);
-            }
-            @Override
-            public void run(int i) throws Exception {
-                Arrays.sort(array);
-                assertTrue("Array not sorted", isSorted(array));
-            }
-        });
-        // Compute the stats.
-        Stat.StatResult stat = Stat.getStat(result);
-        // Create a new report to hold the metrics.
-        DeviceReportLog reportLog = new DeviceReportLog();
-        // Add the results to the report.
-        reportLog.addValues("Times", result, ResultType.LOWER_BETTER, ResultUnit.MS);
-        reportLog.addValue("Min", stat.mMin, ResultType.LOWER_BETTER, ResultUnit.MS);
-        reportLog.addValue("Max", stat.mMax, ResultType.LOWER_BETTER, ResultUnit.MS);
-        // Every report must have a summary,
-        reportLog.setSummary("Average", stat.mAverage, ResultType.LOWER_BETTER, ResultUnit.MS);
-        // Submit the report to the given instrumentation.
-        reportLog.submit(getInstrumentation());
+    private String getReportLogName() {
+        try {
+            DynamicConfigDeviceSide dynamicConfig = new DynamicConfigDeviceSide(
+                    "CtsSampleDeviceTestCases");
+            return dynamicConfig.getValues("report-log-name").get(0);
+        } catch (Exception e) {
+            // Do nothing.
+        }
+        return DEFAULT_REPORT_LOG_NAME;
     }
 
+    /**
+     * Retreives name of metrics stream from dynamic config.
+     *
+     * @param key The key in dynamic config containing stream name.
+     * @return {@link String} name of the stream.
+     */
+    private String getStreamName(String key) {
+        try {
+            DynamicConfigDeviceSide dynamicConfig = new DynamicConfigDeviceSide(
+                    "CtsSampleDeviceTestCases");
+            return dynamicConfig.getValues(key).get(0);
+        } catch (Exception e) {
+            // Do nothing.
+        }
+        return DEFAULT_STREAM_NAME ;
+    }
+
+
 }
diff --git a/tests/signature/src/android/signature/cts/JDiffClassDescription.java b/tests/signature/src/android/signature/cts/JDiffClassDescription.java
index e39e18a..2e13650 100644
--- a/tests/signature/src/android/signature/cts/JDiffClassDescription.java
+++ b/tests/signature/src/android/signature/cts/JDiffClassDescription.java
@@ -462,7 +462,7 @@
      * @param apiMethod the method read from the api file.
      * @param reflectedMethod the method found via reflections.
      */
-    private boolean areMethodModifiedCompatibile(JDiffMethod apiMethod ,
+    private boolean areMethodsModifiedCompatible(JDiffMethod apiMethod ,
             Method reflectedMethod) {
 
         // If the apiMethod isn't synchronized
@@ -479,7 +479,7 @@
         int mod1 = reflectedMethod.getModifiers() & ~ignoredMods;
         int mod2 = apiMethod.mModifier & ~ignoredMods;
 
-        // We can ignore FINAL for final classes
+        // We can ignore FINAL for classes
         if ((mModifier & Modifier.FINAL) != 0) {
             mod1 &= ~Modifier.FINAL;
             mod2 &= ~Modifier.FINAL;
@@ -495,10 +495,6 @@
     private void checkMethodCompliance() {
         for (JDiffMethod method : jDiffMethods) {
             try {
-                // this is because jdiff think a method in an interface is not abstract
-                if (JDiffType.INTERFACE.equals(mClassType)) {
-                    method.mModifier |= Modifier.ABSTRACT;
-                }
 
                 Method m = findMatchingMethod(method);
                 if (m == null) {
@@ -522,7 +518,7 @@
                         return;
                     }
 
-                    if (!areMethodModifiedCompatibile(method, m)) {
+                    if (!areMethodsModifiedCompatible(method, m)) {
                         mResultObserver.notifyFailure(FailureType.MISMATCH_METHOD,
                                 method.toReadableString(mAbsoluteClassName),
                                 "Non-compatible method found when looking for " +
@@ -545,35 +541,62 @@
      * @param method the reflected method to compare
      * @return true, if both methods are the same
      */
-    private boolean matches(JDiffMethod jDiffMethod, Method method) {
+    private boolean matches(JDiffMethod jDiffMethod, Method reflectedMethod) {
         // If the method names aren't equal, the methods can't match.
-        if (jDiffMethod.mName.equals(method.getName())) {
-            String jdiffReturnType = jDiffMethod.mReturnType;
-            String reflectionReturnType = typeToString(method.getGenericReturnType());
-            List<String> jdiffParamList = jDiffMethod.mParamList;
-
-            // Next, compare the return types of the two methods.  If
-            // they aren't equal, the methods can't match.
-            if (jdiffReturnType.equals(reflectionReturnType)) {
-                Type[] params = method.getGenericParameterTypes();
-                // Next, check the method parameters.  If they have
-                // different number of parameters, the two methods
-                // can't match.
-                if (jdiffParamList.size() == params.length) {
-                    // If any of the parameters don't match, the
-                    // methods can't match.
-                    for (int i = 0; i < jdiffParamList.size(); i++) {
-                        if (!compareParam(jdiffParamList.get(i), params[i])) {
-                            return false;
-                        }
-                    }
-                    // We've passed all the tests, the methods do
-                    // match.
-                    return true;
-                }
-            }
+        if (!jDiffMethod.mName.equals(reflectedMethod.getName())) {
+            return false;
         }
-        return false;
+        String jdiffReturnType = jDiffMethod.mReturnType;
+        String reflectionReturnType = typeToString(reflectedMethod.getGenericReturnType());
+        List<String> jdiffParamList = jDiffMethod.mParamList;
+
+        // Next, compare the return types of the two methods.  If
+        // they aren't equal, the methods can't match.
+        if (!jdiffReturnType.equals(reflectionReturnType)) {
+            return false;
+        }
+
+        Type[] params = reflectedMethod.getGenericParameterTypes();
+
+        // Next, check the method parameters.  If they have different
+        // parameter lengths, the two methods can't match.
+        if (jdiffParamList.size() != params.length) {
+            return false;
+        }
+
+        boolean piecewiseParamsMatch = true;
+
+        // Compare method parameters piecewise and return true if they all match.
+        for (int i = 0; i < jdiffParamList.size(); i++) {
+            piecewiseParamsMatch &= compareParam(jdiffParamList.get(i), params[i]);
+        }
+        if (piecewiseParamsMatch) {
+            return true;
+        }
+
+        /** NOTE: There are cases where piecewise method parameter checking
+         * fails even though the strings are equal, so compare entire strings
+         * against each other. This is not done by default to avoid a
+         * TransactionTooLargeException.
+         * Additionally, this can fail anyway due to extra
+         * information dug up by reflection.
+         *
+         * TODO: fix parameter equality checking and reflection matching
+         * See https://b.corp.google.com/issues/27726349
+         */
+
+        StringBuilder reflectedMethodParams = new StringBuilder("");
+        StringBuilder jdiffMethodParams = new StringBuilder("");
+
+        for (int i = 0; i < jdiffParamList.size(); i++) {
+            jdiffMethodParams.append(jdiffParamList.get(i));
+            reflectedMethodParams.append(params[i]);
+        }
+
+        String jDiffFName = jdiffMethodParams.toString();
+        String refName = reflectedMethodParams.toString();
+
+        return jDiffFName.equals(refName);
     }
 
     /**
diff --git a/tests/tests/accounts/Android.mk b/tests/tests/accounts/Android.mk
index fccdb86..dc17e0e 100644
--- a/tests/tests/accounts/Android.mk
+++ b/tests/tests/accounts/Android.mk
@@ -21,7 +21,8 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_STATIC_JAVA_LIBRARIES := CtsAccountTestsCommon ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    CtsAccountTestsCommon ctstestrunner platform-test-annotations
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/accounts/src/android/accounts/cts/AccountManagerTest.java b/tests/tests/accounts/src/android/accounts/cts/AccountManagerTest.java
index dd1f51a..3520d9c 100644
--- a/tests/tests/accounts/src/android/accounts/cts/AccountManagerTest.java
+++ b/tests/tests/accounts/src/android/accounts/cts/AccountManagerTest.java
@@ -32,6 +32,7 @@
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.StrictMode;
+import android.platform.test.annotations.Presubmit;
 import android.test.ActivityInstrumentationTestCase2;
 
 import java.io.IOException;
@@ -1440,6 +1441,7 @@
     /**
      * Test confirmCredentials()
      */
+    @Presubmit
     public void testConfirmCredentials() throws IOException, AuthenticatorException,
             OperationCanceledException {
 
diff --git a/tests/tests/animation/src/android/animation/cts/AnimatorSetTest.java b/tests/tests/animation/src/android/animation/cts/AnimatorSetTest.java
index 0163a58..b57299f 100644
--- a/tests/tests/animation/src/android/animation/cts/AnimatorSetTest.java
+++ b/tests/tests/animation/src/android/animation/cts/AnimatorSetTest.java
@@ -15,9 +15,14 @@
  */
 package android.animation.cts;
 
+import java.lang.Override;
+import java.lang.Runnable;
+import java.lang.Thread;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -55,15 +60,81 @@
     }
 
      public void testPlaySequentially() throws Throwable {
+         xAnimator.setRepeatCount(0);
+         yAnimator.setRepeatCount(0);
+         xAnimator.setDuration(50);
+         yAnimator.setDuration(50);
          Animator[] animatorArray = {xAnimator, yAnimator};
-
          mAnimatorSet = new AnimatorSet();
          mAnimatorSet.playSequentially(animatorArray);
+         verifySequentialPlayOrder(mAnimatorSet, animatorArray);
 
-         assertFalse(mAnimatorSet.isRunning());
-         startAnimation(mAnimatorSet);
-         Thread.sleep(100);
-         assertTrue(mAnimatorSet.isRunning());
+         ValueAnimator anim1 = ValueAnimator.ofFloat(0f, 1f);
+         ValueAnimator anim2 = ValueAnimator.ofInt(0, 100);
+         anim1.setDuration(50);
+         anim2.setDuration(50);
+         AnimatorSet set = new AnimatorSet();
+         set.playSequentially(anim1, anim2);
+         verifySequentialPlayOrder(set, new Animator[] {anim1, anim2});
+    }
+
+    /**
+     * Start the animator, and verify the animators are played sequentially in the order that is
+     * defined in the array.
+     *
+     * @param set AnimatorSet to be started and verified
+     * @param animators animators that we put in the AnimatorSet, in the order that they'll play
+     */
+    private void verifySequentialPlayOrder(final AnimatorSet set, Animator[] animators)
+            throws Throwable {
+
+        final MyListener[] listeners = new MyListener[animators.length];
+        for (int i = 0; i < animators.length; i++) {
+            if (i == 0) {
+                listeners[i] = new MyListener();
+            } else {
+                final int current = i;
+                listeners[i] = new MyListener() {
+                    @Override
+                    public void onAnimationStart(Animator anim) {
+                        super.onAnimationStart(anim);
+                        // Check that the previous animator has finished.
+                        assertTrue(listeners[current - 1].mEndIsCalled);
+                    }
+                };
+            }
+            animators[i].addListener(listeners[i]);
+        }
+
+        final CountDownLatch startLatch = new CountDownLatch(1);
+        final CountDownLatch endLatch = new CountDownLatch(1);
+
+        set.addListener(new MyListener() {
+            @Override
+            public void onAnimationEnd(Animator anim) {
+                endLatch.countDown();
+            }
+        });
+
+        long totalDuration = set.getTotalDuration();
+        assertFalse(set.isRunning());
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                set.start();
+                startLatch.countDown();
+            }
+        });
+
+        // Set timeout to 100ms, if current count reaches 0 before the timeout, startLatch.await(...)
+        // will return immediately.
+        assertTrue(startLatch.await(100, TimeUnit.MILLISECONDS));
+        assertTrue(set.isRunning());
+        assertTrue(endLatch.await(totalDuration * 2, TimeUnit.MILLISECONDS));
+        // Check that all the animators have finished.
+        for (int i = 0; i < listeners.length; i++) {
+            assertTrue(listeners[i].mEndIsCalled);
+        }
     }
 
     public void testPlayTogether() throws Throwable {
@@ -74,10 +145,44 @@
         mAnimatorSet.playTogether(animatorArray);
 
         assertFalse(mAnimatorSet.isRunning());
+        assertFalse(xAnimator.isRunning());
+        assertFalse(yAnimator.isRunning());
         startAnimation(mAnimatorSet);
         Thread.sleep(100);
         assertTrue(mAnimatorSet.isRunning());
-   }
+        assertTrue(xAnimator.isRunning());
+        assertTrue(yAnimator.isRunning());
+
+        // Now assemble another animator set
+        ValueAnimator anim1 = ValueAnimator.ofFloat(0f, 100f);
+        ValueAnimator anim2 = ValueAnimator.ofFloat(10f, 100f);
+        AnimatorSet set = new AnimatorSet();
+        set.playTogether(anim1, anim2);
+
+        assertFalse(set.isRunning());
+        assertFalse(anim1.isRunning());
+        assertFalse(anim2.isRunning());
+        startAnimation(set);
+        Thread.sleep(100);
+        assertTrue(set.isRunning());
+        assertTrue(anim1.isRunning());
+        assertTrue(anim2.isRunning());
+    }
+
+    public void testPlayBeforeAfter() throws Throwable {
+        xAnimator.setRepeatCount(0);
+        yAnimator.setRepeatCount(0);
+        final ValueAnimator zAnimator = ValueAnimator.ofFloat(0f, 100f);
+
+        xAnimator.setDuration(50);
+        yAnimator.setDuration(50);
+        zAnimator.setDuration(50);
+
+        AnimatorSet set = new AnimatorSet();
+        set.play(yAnimator).before(zAnimator).after(xAnimator);
+
+        verifySequentialPlayOrder(set, new Animator[] {xAnimator, yAnimator, zAnimator});
+    }
 
     public void testDuration() throws Throwable {
         xAnimator.setRepeatCount(ValueAnimator.INFINITE);
@@ -243,4 +348,17 @@
         int x = 1;
         int y = 2;
     }
+
+    class MyListener extends AnimatorListenerAdapter {
+        boolean mStartIsCalled = false;
+        boolean mEndIsCalled = false;
+
+        public void onAnimationStart(Animator animation) {
+            mStartIsCalled = true;
+        }
+
+        public void onAnimationEnd(Animator animation) {
+            mEndIsCalled = true;
+        }
+    }
 }
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/ActivityTransitionActivity.java b/tests/tests/app.usage/src/android/app/usage/cts/ActivityTransitionActivity.java
index 8947de0..0e413c9 100644
--- a/tests/tests/app.usage/src/android/app/usage/cts/ActivityTransitionActivity.java
+++ b/tests/tests/app.usage/src/android/app/usage/cts/ActivityTransitionActivity.java
@@ -18,7 +18,6 @@
 
 import android.app.Activity;
 import android.app.SharedElementCallback;
-import android.app.usage.cts.R;
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.ResultReceiver;
@@ -59,6 +58,9 @@
     public static final String ARRIVE_RETURN_TIME_READY = "arriveReturnTimeReady";
     public static final String ARRIVE_RETURN_TIME = "arriveReturnTime";
 
+    public static final String ENTER_VISIBILITY = "enterVisibility";
+    public static final String RETURN_VISIBILITY = "returnVisibility";
+
     private int mLayoutId;
     private int mTest;
     private ResultReceiver mResultReceiver;
@@ -67,6 +69,8 @@
 
     public int resultCode = 0;
     public Bundle result = new Bundle();
+    public final OptionalVisibility exitVisibility = new OptionalVisibility();
+    public final OptionalVisibility reenterVisibility = new OptionalVisibility();
 
     public boolean mPauseOnRestart;
     public boolean mQuickFinish;
@@ -76,12 +80,6 @@
     public CountDownLatch returnLatch = new CountDownLatch(1);
     public CountDownLatch reenterLatch = new CountDownLatch(1);
 
-    public static final int EXIT_TRANSITION_INDEX = 0;
-    public static final int ENTER_TRANSITION_INDEX = 1;
-    public static final int RETURN_TRANSITION_INDEX = 2;
-    public static final int REENTER_TRANSITION_INDEX = 3;
-    public static final int sVisibility[] = new int[4];
-
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
@@ -109,11 +107,10 @@
 
         getWindow().setSharedElementEnterTransition(new ChangeBounds().setDuration(DURATION));
         getWindow().setSharedElementReturnTransition(new ChangeBounds().setDuration(DURATION));
-        getWindow().setEnterTransition(createVisibilityTransition(true, ENTER_TRANSITION_INDEX));
-        getWindow().setReturnTransition(createVisibilityTransition(true, RETURN_TRANSITION_INDEX));
-        getWindow().setExitTransition(createVisibilityTransition(false, EXIT_TRANSITION_INDEX));
-        getWindow().setReenterTransition(createVisibilityTransition(false,
-                REENTER_TRANSITION_INDEX));
+        getWindow().setEnterTransition(createVisibilityTransition(true, ENTER_VISIBILITY));
+        getWindow().setReturnTransition(createVisibilityTransition(true, RETURN_VISIBILITY));
+        getWindow().setExitTransition(createVisibilityTransition(false, exitVisibility));
+        getWindow().setReenterTransition(createVisibilityTransition(false, reenterVisibility));
         getWindow().getReenterTransition().addListener(new TransitionListenerAdapter() {
             @Override
             public void onTransitionEnd(Transition transition) {
@@ -131,10 +128,17 @@
         startTest();
     }
 
-    private Transition createVisibilityTransition(boolean isExplode, int startIndex) {
+    private Transition createVisibilityTransition(boolean isExplode, OptionalVisibility visibility) {
         final Transition transition = isExplode ? new Explode() : new Fade();
         transition.setDuration(DURATION);
-        transition.addListener(new VisibilityCheck(R.id.redSquare, startIndex));
+        transition.addListener(new VisibilityCheck(R.id.redSquare, visibility));
+        return transition;
+    }
+
+    private Transition createVisibilityTransition(boolean isExplode, String propertyName) {
+        final Transition transition = isExplode ? new Explode() : new Fade();
+        transition.setDuration(DURATION);
+        transition.addListener(new VisibilityCheck(R.id.redSquare, propertyName));
         return transition;
     }
 
@@ -237,17 +241,49 @@
 
     private class VisibilityCheck extends TransitionListenerAdapter {
         private final int mViewId;
-        private final int mStartIndex;
+        private final OptionalVisibility mVisibility;
+        private final String mPropertyName;
 
-        public VisibilityCheck(int viewId, int startIndex) {
+        public VisibilityCheck(int viewId, OptionalVisibility visibility) {
             mViewId = viewId;
-            this.mStartIndex = startIndex;
+            mVisibility = visibility;
+            mPropertyName = null;
+        }
+
+        public VisibilityCheck(int viewId, String propertyName) {
+            mViewId = viewId;
+            mVisibility = null;
+            mPropertyName = propertyName;
         }
 
         @Override
         public void onTransitionEnd(Transition transition) {
             final View view = findViewById(mViewId);
-            sVisibility[mStartIndex ] = view.getVisibility();
+            if (mPropertyName != null) {
+                if (mResultReceiver != null) {
+                    Bundle data = new Bundle();
+                    data.putInt(mPropertyName, view.getVisibility());
+                    mResultReceiver.send(RESULT_OK, data);
+                }
+            } else {
+                mVisibility.set(view.getVisibility());
+            }
+        }
+    }
+
+    public static class OptionalVisibility {
+        private int mVisibility = -1;
+
+        public void set(int visibility) {
+            mVisibility = visibility;
+        }
+
+        public int get() {
+            return mVisibility;
+        }
+
+        public boolean isSet() {
+            return mVisibility != -1;
         }
     }
 }
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/ActivityTransitionTest.java b/tests/tests/app.usage/src/android/app/usage/cts/ActivityTransitionTest.java
index b23edb7..25d885a 100644
--- a/tests/tests/app.usage/src/android/app/usage/cts/ActivityTransitionTest.java
+++ b/tests/tests/app.usage/src/android/app/usage/cts/ActivityTransitionTest.java
@@ -17,7 +17,6 @@
 
 import android.app.ActivityOptions;
 import android.app.SharedElementCallback;
-import android.app.usage.cts.R;
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.Handler;
@@ -28,7 +27,6 @@
 import android.transition.Transition.TransitionListener;
 import android.view.View;
 
-import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -51,7 +49,6 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        Arrays.fill(ActivityTransitionActivity.sVisibility, -1);
         setActivityInitialTouchMode(false);
         mActivity = getActivity();
         mNumArrivedCalls = 0;
@@ -135,12 +132,14 @@
         runTestOnUiThread(new Runnable() {
             @Override
             public void run() {
+                mReceiver = new PassInfo(new Handler());
                 mActivity.mPauseOnRestart = true;
                 Bundle options = ActivityOptions.makeSceneTransitionAnimation(mActivity,
                         mActivity.findViewById(R.id.hello), "target").toBundle();
                 Intent intent = new Intent(mActivity, ActivityTransitionActivity.class);
                 intent.putExtra(ActivityTransitionActivity.LAYOUT_ID, R.layout.end);
                 intent.putExtra(ActivityTransitionActivity.QUICK_FINISH, true);
+                intent.putExtra(ActivityTransitionActivity.RESULT_RECEIVER, mReceiver);
                 mActivity.startActivityForResult(intent, 0, options);
             }
         });
@@ -151,7 +150,7 @@
         assertTrue("Reenter transition didn't finish", latch.await(1000, TimeUnit.MILLISECONDS));
         assertTrue(mActivity.reenterLatch.await(300, TimeUnit.MILLISECONDS));
         getInstrumentation().waitForIdleSync();
-        checkNormalTransitionVisibility();
+        checkNoReturnTransitionVisibility();
         runTestOnUiThread(new Runnable() {
             @Override
             public void run() {
@@ -168,12 +167,14 @@
         runTestOnUiThread(new Runnable() {
             @Override
             public void run() {
+                mReceiver = new PassInfo(new Handler());
                 Bundle options = ActivityOptions.makeSceneTransitionAnimation(mActivity,
                         mActivity.findViewById(R.id.hello), "target").toBundle();
                 Intent intent = new Intent(mActivity, ActivityTransitionActivity.class);
                 intent.putExtra(ActivityTransitionActivity.LAYOUT_ID, R.layout.end);
                 intent.putExtra(ActivityTransitionActivity.QUICK_FINISH, true);
                 intent.putExtra(ActivityTransitionActivity.ALLOW_OVERLAP, false);
+                intent.putExtra(ActivityTransitionActivity.RESULT_RECEIVER, mReceiver);
                 mActivity.startActivityForResult(intent, 0, options);
             }
         });
@@ -182,7 +183,7 @@
                 mActivity.returnLatch.await(1500, TimeUnit.MILLISECONDS));
         assertTrue(mActivity.reenterLatch.await(300, TimeUnit.MILLISECONDS));
         getInstrumentation().waitForIdleSync();
-        checkNormalTransitionVisibility();
+        checkNoReturnTransitionVisibility();
         runTestOnUiThread(new Runnable() {
             @Override
             public void run() {
@@ -200,12 +201,14 @@
         runTestOnUiThread(new Runnable() {
             @Override
             public void run() {
+                mReceiver = new PassInfo(new Handler());
                 Bundle options = ActivityOptions.makeSceneTransitionAnimation(mActivity,
                         mActivity.findViewById(R.id.hello), "target").toBundle();
                 Intent intent = new Intent(mActivity, ActivityTransitionActivity.class);
                 intent.putExtra(ActivityTransitionActivity.LAYOUT_ID, R.layout.end);
                 intent.putExtra(ActivityTransitionActivity.QUICK_FINISH, true);
                 intent.putExtra(ActivityTransitionActivity.ALLOW_OVERLAP, true);
+                intent.putExtra(ActivityTransitionActivity.RESULT_RECEIVER, mReceiver);
                 mActivity.startActivityForResult(intent, 0, options);
             }
         });
@@ -215,7 +218,7 @@
         assertTrue("Reenter transition didn't finish", latch.await(1000, TimeUnit.MILLISECONDS));
         assertTrue(mActivity.reenterLatch.await(300, TimeUnit.MILLISECONDS));
         getInstrumentation().waitForIdleSync();
-        checkNormalTransitionVisibility();
+        checkNoReturnTransitionVisibility();
         runTestOnUiThread(new Runnable() {
             @Override
             public void run() {
@@ -232,6 +235,7 @@
         runTestOnUiThread(new Runnable() {
             @Override
             public void run() {
+                mReceiver = new PassInfo(new Handler());
                 Bundle options = ActivityOptions.makeSceneTransitionAnimation(mActivity,
                         mActivity.findViewById(R.id.hello), "target").toBundle();
                 Intent intent = new Intent(mActivity, ActivityTransitionActivity.class);
@@ -239,6 +243,7 @@
                 intent.putExtra(ActivityTransitionActivity.QUICK_FINISH, true);
                 intent.putExtra(ActivityTransitionActivity.ALLOW_OVERLAP, true);
                 intent.putExtra(ActivityTransitionActivity.NO_RETURN_TRANSITION, true);
+                intent.putExtra(ActivityTransitionActivity.RESULT_RECEIVER, mReceiver);
                 mActivity.startActivityForResult(intent, 0, options);
             }
         });
@@ -261,19 +266,18 @@
 
     private void checkNormalTransitionVisibility() {
         checkNoReturnTransitionVisibility();
-        final int[]  visibilities = ActivityTransitionActivity.sVisibility;
         assertEquals(View.INVISIBLE,
-                visibilities[ActivityTransitionActivity.RETURN_TRANSITION_INDEX]);
+                mReceiver.resultData.getInt(ActivityTransitionActivity.RETURN_VISIBILITY, -1));
     }
 
     private void checkNoReturnTransitionVisibility() {
-        final int[]  visibilities = ActivityTransitionActivity.sVisibility;
+        assertTrue(mActivity.exitVisibility.isSet());
+        assertTrue(mActivity.reenterVisibility.isSet());
+
         assertEquals(View.VISIBLE,
-                visibilities[ActivityTransitionActivity.ENTER_TRANSITION_INDEX]);
-        assertEquals(View.INVISIBLE,
-                visibilities[ActivityTransitionActivity.EXIT_TRANSITION_INDEX]);
-        assertEquals(View.VISIBLE,
-                visibilities[ActivityTransitionActivity.REENTER_TRANSITION_INDEX]);
+                mReceiver.resultData.getInt(ActivityTransitionActivity.ENTER_VISIBILITY, -1));
+        assertEquals(View.INVISIBLE, mActivity.exitVisibility.get());
+        assertEquals(View.VISIBLE, mActivity.reenterVisibility.get());
     }
 
     private CountDownLatch setReenterLatch() {
@@ -303,9 +307,10 @@
         mActivity.getWindow().getReenterTransition().addListener(listener);
         return latch;
     }
+
     public static class PassInfo extends ResultReceiver {
         public int resultCode;
-        public Bundle resultData;
+        public Bundle resultData = new Bundle();
 
         public PassInfo(Handler handler) {
             super(handler);
@@ -314,7 +319,9 @@
         @Override
         protected void onReceiveResult(int resultCode, Bundle resultData) {
             this.resultCode = resultCode;
-            this.resultData = resultData;
+            if (resultData != null) {
+                this.resultData.putAll(resultData);
+            }
         }
     }
 }
diff --git a/tests/tests/calllog/src/android/calllog/cts/CallLogBackupTest.java b/tests/tests/calllog/src/android/calllog/cts/CallLogBackupTest.java
index 5b0e0c7..695a138 100644
--- a/tests/tests/calllog/src/android/calllog/cts/CallLogBackupTest.java
+++ b/tests/tests/calllog/src/android/calllog/cts/CallLogBackupTest.java
@@ -19,9 +19,11 @@
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.database.Cursor;
 import android.provider.CallLog;
 import android.provider.CallLog.Calls;
+import android.provider.Settings;
 import android.test.InstrumentationTestCase;
 import android.util.Log;
 
@@ -53,6 +55,7 @@
     private static final String LOCAL_BACKUP_COMPONENT =
             "android/com.android.internal.backup.LocalTransport";
     private static final String CALLLOG_BACKUP_PACKAGE = "com.android.providers.calllogbackup";
+    private static final String ALT_CALLLOG_BACKUP_PACKAGE = "com.android.calllogbackup";
 
     private static final String TEST_NUMBER = "555-1234";
     private static final int CALL_START_TIME = 0;
@@ -88,9 +91,18 @@
         int presentation;
     }
 
+    private String mCallLogBackupPackageName;
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+        PackageManager pm = getContext().getPackageManager();
+        try {
+            pm.getPackageInfo(CALLLOG_BACKUP_PACKAGE, 0);
+            mCallLogBackupPackageName = CALLLOG_BACKUP_PACKAGE;
+        } catch (PackageManager.NameNotFoundException e) {
+            mCallLogBackupPackageName = ALT_CALLLOG_BACKUP_PACKAGE;
+        }
     }
 
     /**
@@ -103,16 +115,23 @@
      *   6) Verify that we the call from step (2)
      */
     public void testSingleCallBackup() throws Exception {
+        if (!getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+            Log.i(TAG, "Skipping calllog tests: no telephony feature");
+            return;
+        }
         // This CTS test depends on the local transport and so if it is not present,
         // skip the test with success.
         if (!hasBackupTransport(LOCAL_BACKUP_COMPONENT)) {
-            Log.i(TAG, "skipping calllog tests");
+            Log.i(TAG, "skipping calllog tests: no local transport");
             return;
         }
 
         // Turn on backup and set to the local backup agent.
         boolean previouslyEnabled = enableBackup(true /* enable */);
         String oldTransport = setBackupTransport(LOCAL_BACKUP_COMPONENT);
+        int previousFullDataBackupAware = Settings.Secure.getInt(getContext().getContentResolver(),
+                "user_full_data_backup_aware", 0);
+        enableFullDataBackupAware(1);
 
         // Clear the call log
         Log.i(TAG, "Clearing the call log");
@@ -125,7 +144,7 @@
 
         // Run backup for the call log (saves the single call).
         Log.i(TAG, "Running backup");
-        runBackupFor(CALLLOG_BACKUP_PACKAGE);
+        runBackupFor(mCallLogBackupPackageName);
         Thread.sleep(TIMEOUT_BACKUP); // time for backup
 
         // Clear the call log and verify that it is empty
@@ -135,7 +154,7 @@
 
         // Restore from the previous backup and verify we have the new call again.
         Log.i(TAG, "Restoring the single call");
-        runRestoreFor(CALLLOG_BACKUP_PACKAGE);
+        runRestoreFor(mCallLogBackupPackageName);
         Thread.sleep(TIMEOUT_BACKUP); // time for restore
 
         verifyCall();
@@ -144,6 +163,7 @@
         Log.i(TAG, "Reseting backup");
         setBackupTransport(oldTransport);
         enableBackup(previouslyEnabled);
+        enableFullDataBackupAware(previousFullDataBackupAware);
     }
 
     private Call verifyCall() {
@@ -183,6 +203,10 @@
         exec("bmgr restore " + packageName);
     }
 
+    private void enableFullDataBackupAware(int status) throws Exception {
+        exec("settings put secure user_full_data_backup_aware " + status);
+    }
+
     private String setBackupTransport(String transport) throws Exception {
         String output = exec("bmgr transport " + transport);
         Pattern pattern = Pattern.compile("\\(formerly (.*)\\)$");
diff --git a/tests/tests/automotive/Android.mk b/tests/tests/car/Android.mk
similarity index 95%
rename from tests/tests/automotive/Android.mk
rename to tests/tests/car/Android.mk
index abef2ac..0138317 100644
--- a/tests/tests/automotive/Android.mk
+++ b/tests/tests/car/Android.mk
@@ -16,7 +16,7 @@
 
 include $(CLEAR_VARS)
 
-LOCAL_PACKAGE_NAME := CtsAutomotiveTestCases
+LOCAL_PACKAGE_NAME := CtsCarTestCases
 
 # Don't include this package in any target.
 LOCAL_MODULE_TAGS := optional
diff --git a/tests/tests/automotive/AndroidManifest.xml b/tests/tests/car/AndroidManifest.xml
similarity index 100%
rename from tests/tests/automotive/AndroidManifest.xml
rename to tests/tests/car/AndroidManifest.xml
diff --git a/tests/tests/automotive/AndroidTest.xml b/tests/tests/car/AndroidTest.xml
similarity index 87%
rename from tests/tests/automotive/AndroidTest.xml
rename to tests/tests/car/AndroidTest.xml
index b4af1f5..d82c101 100644
--- a/tests/tests/automotive/AndroidTest.xml
+++ b/tests/tests/car/AndroidTest.xml
@@ -16,9 +16,9 @@
 <configuration description="Config for CTS Automotive test cases">
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
         <option name="cleanup-apks" value="true" />
-        <option name="test-file-name" value="CtsAutomotiveTestCases.apk" />
+        <option name="test-file-name" value="CtsCarTestCases.apk" />
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="android.support.car.cts" />
+        <option name="package" value="android.car.cts" />
     </test>
 </configuration>
diff --git a/tests/tests/automotive/src/android/car/cts/CarApiTestBase.java b/tests/tests/car/src/android/car/cts/CarApiTestBase.java
similarity index 100%
rename from tests/tests/automotive/src/android/car/cts/CarApiTestBase.java
rename to tests/tests/car/src/android/car/cts/CarApiTestBase.java
diff --git a/tests/tests/automotive/src/android/car/cts/CarAppContextManagerTest.java b/tests/tests/car/src/android/car/cts/CarAppContextManagerTest.java
similarity index 100%
rename from tests/tests/automotive/src/android/car/cts/CarAppContextManagerTest.java
rename to tests/tests/car/src/android/car/cts/CarAppContextManagerTest.java
diff --git a/tests/tests/car/src/android/car/cts/CarAudioManagerTest.java b/tests/tests/car/src/android/car/cts/CarAudioManagerTest.java
new file mode 100644
index 0000000..cec1db6
--- /dev/null
+++ b/tests/tests/car/src/android/car/cts/CarAudioManagerTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.car.cts;
+
+import android.car.Car;
+import android.car.media.CarAudioManager;
+import android.media.AudioAttributes;
+
+/** Unit tests for {@link CarAudioManager}. */
+public class CarAudioManagerTest extends CarApiTestBase {
+    private static final String TAG = CarAudioManagerTest.class.getSimpleName();
+    private CarAudioManager mManager;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mManager = (CarAudioManager) getCar().getCarManager(Car.AUDIO_SERVICE);
+        assertNotNull(mManager);
+    }
+
+    public void testGetAudioAttributesForCarUsageForMusic() throws Exception {
+        AudioAttributes.Builder musicBuilder = new AudioAttributes.Builder();
+        musicBuilder.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
+                .setUsage(AudioAttributes.USAGE_MEDIA);
+
+        assertEquals(musicBuilder.build(), mManager.getAudioAttributesForCarUsage(
+                             CarAudioManager.CAR_AUDIO_USAGE_MUSIC));
+    }
+
+    public void testGetAudioAttributesForCarUsageForUnknown() throws Exception {
+        AudioAttributes.Builder unknownBuilder = new AudioAttributes.Builder();
+        unknownBuilder.setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
+                .setUsage(AudioAttributes.USAGE_UNKNOWN);
+
+        assertEquals(unknownBuilder.build(), mManager.getAudioAttributesForCarUsage(10007));
+    }
+}
diff --git a/tests/tests/automotive/src/android/car/cts/CarInfoManagerTest.java b/tests/tests/car/src/android/car/cts/CarInfoManagerTest.java
similarity index 100%
rename from tests/tests/automotive/src/android/car/cts/CarInfoManagerTest.java
rename to tests/tests/car/src/android/car/cts/CarInfoManagerTest.java
diff --git a/tests/tests/automotive/src/android/car/cts/CarPackageManagerTest.java b/tests/tests/car/src/android/car/cts/CarPackageManagerTest.java
similarity index 60%
rename from tests/tests/automotive/src/android/car/cts/CarPackageManagerTest.java
rename to tests/tests/car/src/android/car/cts/CarPackageManagerTest.java
index 2865710..dc5fe0a 100644
--- a/tests/tests/automotive/src/android/car/cts/CarPackageManagerTest.java
+++ b/tests/tests/car/src/android/car/cts/CarPackageManagerTest.java
@@ -18,16 +18,21 @@
 import android.car.Car;
 import android.car.CarNotConnectedException;
 import android.car.content.pm.CarPackageManager;
-import android.telecom.TelecomManager;
-import android.util.Log;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
 
-import java.util.ArrayList;
 import java.util.List;
-import java.util.concurrent.ExecutionException;
 
 public class CarPackageManagerTest extends CarApiTestBase {
 
     private CarPackageManager mCarPm;
+    private static String TAG = CarPackageManagerTest.class.getSimpleName();
+
+    /** Name of the meta-data attribute for the automotive application XML resource */
+    private static final String METADATA_ATTRIBUTE = "android.car.application";
+
 
     @Override
     protected void setUp() throws Exception {
@@ -39,8 +44,6 @@
        assertFalse(mCarPm.isActivityAllowedWhileDriving("com.basic.package", "DummyActivity"));
        // Real system activity is not allowed as well.
        assertFalse(mCarPm.isActivityAllowedWhileDriving("com.android.phone", "CallActivity"));
-       assertTrue(mCarPm.isActivityAllowedWhileDriving(
-               "com.google.android.car.media", "com.google.android.car.media.MediaProxyActivity"));
 
        try {
            mCarPm.isActivityAllowedWhileDriving("com.android.settings", null);
@@ -62,6 +65,32 @@
        }
    }
 
+    public void testSystemActivitiesAllowed() throws CarNotConnectedException {
+        List<PackageInfo> packages = getContext().getPackageManager().getInstalledPackages(
+                PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA);
+
+        for (PackageInfo info : packages) {
+            if (info.applicationInfo == null) {
+                continue;
+            }
+            if ((info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 ||
+                    ((info.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)) {
+
+                Bundle metaData = info.applicationInfo.metaData;
+                if (metaData == null || metaData.getInt(METADATA_ATTRIBUTE, 0) == 0) {
+                    continue;  // No car metadata, ignoring this app.
+                }
+
+                if (info.activities != null && info.activities.length > 0) {
+                    String activity = info.activities[0].name;
+                    String packageName = info.packageName;
+                    assertTrue("Failed for package: " + packageName + ", activity: " + activity,
+                            mCarPm.isActivityAllowedWhileDriving(packageName, activity));
+                }
+            }
+        }
+    }
+
     public void testServiceAllowedWhileDriving() throws Exception {
         assertFalse(mCarPm.isServiceAllowedWhileDriving("com.basic.package", ""));
         assertTrue(mCarPm.isServiceAllowedWhileDriving("com.android.settings", "Any"));
@@ -75,4 +104,5 @@
             // Expected.
         }
     }
+
 }
diff --git a/tests/tests/automotive/src/android/car/cts/CarSensorManagerTest.java b/tests/tests/car/src/android/car/cts/CarSensorManagerTest.java
similarity index 100%
rename from tests/tests/automotive/src/android/car/cts/CarSensorManagerTest.java
rename to tests/tests/car/src/android/car/cts/CarSensorManagerTest.java
diff --git a/tests/tests/automotive/src/android/car/cts/CarTest.java b/tests/tests/car/src/android/car/cts/CarTest.java
similarity index 100%
rename from tests/tests/automotive/src/android/car/cts/CarTest.java
rename to tests/tests/car/src/android/car/cts/CarTest.java
diff --git a/tests/tests/automotive/src/android/car/cts/CarUiProviderTest.java b/tests/tests/car/src/android/car/cts/CarUiProviderTest.java
similarity index 100%
rename from tests/tests/automotive/src/android/car/cts/CarUiProviderTest.java
rename to tests/tests/car/src/android/car/cts/CarUiProviderTest.java
diff --git a/tests/tests/automotive/src/android/car/cts/ExceptionsTest.java b/tests/tests/car/src/android/car/cts/ExceptionsTest.java
similarity index 100%
rename from tests/tests/automotive/src/android/car/cts/ExceptionsTest.java
rename to tests/tests/car/src/android/car/cts/ExceptionsTest.java
diff --git a/tests/tests/content/AndroidManifest.xml b/tests/tests/content/AndroidManifest.xml
index d88fdad..d4f203e 100644
--- a/tests/tests/content/AndroidManifest.xml
+++ b/tests/tests/content/AndroidManifest.xml
@@ -21,7 +21,6 @@
     <!-- content sync tests -->
     <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
     <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
-    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
     <uses-permission android:name="android.permission.USE_CREDENTIALS" />
     <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
     <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
diff --git a/tests/tests/content/res/color-land/testcolor_orientation.xml b/tests/tests/content/res/color-land/testcolor_orientation.xml
new file mode 100644
index 0000000..f9e285b
--- /dev/null
+++ b/tests/tests/content/res/color-land/testcolor_orientation.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="@android:color/white" />
+</selector>
diff --git a/tests/tests/content/res/drawable/testcolor.xml b/tests/tests/content/res/color/testcolor.xml
similarity index 100%
rename from tests/tests/content/res/drawable/testcolor.xml
rename to tests/tests/content/res/color/testcolor.xml
diff --git a/tests/tests/content/res/color/testcolor_orientation.xml b/tests/tests/content/res/color/testcolor_orientation.xml
new file mode 100644
index 0000000..bef1ef6
--- /dev/null
+++ b/tests/tests/content/res/color/testcolor_orientation.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="@android:color/black" />
+</selector>
diff --git a/tests/tests/content/res/color/testcolor_themed.xml b/tests/tests/content/res/color/testcolor_themed.xml
new file mode 100644
index 0000000..eee0526
--- /dev/null
+++ b/tests/tests/content/res/color/testcolor_themed.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="?attr/themeColor" />
+</selector>
diff --git a/tests/tests/content/res/drawable/colordrawable_themed.xml b/tests/tests/content/res/drawable/colordrawable_themed.xml
new file mode 100644
index 0000000..eacbe65
--- /dev/null
+++ b/tests/tests/content/res/drawable/colordrawable_themed.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<color xmlns:android="http://schemas.android.com/apk/res/android"
+       android:color="?attr/themeColor" />
diff --git a/tests/tests/content/res/values/attrs.xml b/tests/tests/content/res/values/attrs.xml
index ac88ef6..12b731b 100644
--- a/tests/tests/content/res/values/attrs.xml
+++ b/tests/tests/content/res/values/attrs.xml
@@ -48,6 +48,9 @@
     <attr name="type14" format="string"/>
     <attr name="type15" format="reference"/>
     <attr name="type16" format="string"/>
+    <attr name="type17" format="reference|color"/>
+    <attr name="typeEmpty" format="reference"/>
+    <attr name="typeUndefined" format="reference"/>
     <declare-styleable name="style1">
         <attr name="type1"/>
         <attr name="type2"/>
@@ -65,6 +68,9 @@
         <attr name="type14"/>
         <attr name="type15"/>
         <attr name="type16"/>
+        <attr name="type17"/>
+        <attr name="typeEmpty"/>
+        <attr name="typeUndefined"/>
     </declare-styleable>
     <attr name="testEnum">
         <enum name="val1" value="1" />
diff --git a/tests/tests/content/res/values/styles.xml b/tests/tests/content/res/values/styles.xml
index b27968d..c6e4b1d 100644
--- a/tests/tests/content/res/values/styles.xml
+++ b/tests/tests/content/res/values/styles.xml
@@ -33,6 +33,9 @@
         <item name="type14">TypedArray Test!</item>
         <item name="type15">@array/difficultyLevel</item>
         <item name="type16">Typed Value!</item>
+        <item name="type17">@color/testcolor_orientation</item>
+        <item name="typeEmpty">@empty</item>
+        <item name="typeUndefined">@null</item>
     </style>
 
     <style name="TextViewWithoutColorAndAppearance">
diff --git a/tests/tests/content/src/android/content/cts/ContextTest.java b/tests/tests/content/src/android/content/cts/ContextTest.java
index c988f77..4cb85cc 100644
--- a/tests/tests/content/src/android/content/cts/ContextTest.java
+++ b/tests/tests/content/src/android/content/cts/ContextTest.java
@@ -16,10 +16,6 @@
 
 package android.content.cts;
 
-import android.content.cts.R;
-
-import org.xmlpull.v1.XmlPullParserException;
-
 import android.content.Context;
 import android.content.cts.util.XmlUtils;
 import android.content.res.ColorStateList;
@@ -34,6 +30,8 @@
 import android.util.Xml;
 import android.view.WindowManager;
 
+import org.xmlpull.v1.XmlPullParserException;
+
 import java.io.File;
 import java.io.IOException;
 
@@ -90,11 +88,11 @@
      * they don't have file-based encryption, so that apps can go through a
      * backup/restore cycle between FBE and non-FBE devices.
      */
-    public void testCreateDeviceEncryptedStorageContext() throws Exception {
-        final Context deviceContext = mContext.createDeviceEncryptedStorageContext();
+    public void testCreateDeviceProtectedStorageContext() throws Exception {
+        final Context deviceContext = mContext.createDeviceProtectedStorageContext();
 
-        assertFalse(mContext.isDeviceEncryptedStorage());
-        assertTrue(deviceContext.isDeviceEncryptedStorage());
+        assertFalse(mContext.isDeviceProtectedStorage());
+        assertTrue(deviceContext.isDeviceProtectedStorage());
 
         final File defaultFile = new File(mContext.getFilesDir(), "test");
         final File deviceFile = new File(deviceContext.getFilesDir(), "test");
@@ -108,21 +106,21 @@
         assertTrue(deviceFile.exists());
     }
 
-    public void testMigrateSharedPreferencesFrom() throws Exception {
-        final Context deviceContext = mContext.createDeviceEncryptedStorageContext();
+    public void testMoveSharedPreferencesFrom() throws Exception {
+        final Context deviceContext = mContext.createDeviceProtectedStorageContext();
 
         mContext.getSharedPreferences("test", Context.MODE_PRIVATE).edit().putInt("answer", 42)
                 .commit();
 
         // Verify that we can migrate
-        assertTrue(deviceContext.migrateSharedPreferencesFrom(mContext, "test"));
+        assertTrue(deviceContext.moveSharedPreferencesFrom(mContext, "test"));
         assertEquals(0, mContext.getSharedPreferences("test", Context.MODE_PRIVATE)
                 .getInt("answer", 0));
         assertEquals(42, deviceContext.getSharedPreferences("test", Context.MODE_PRIVATE)
                 .getInt("answer", 0));
 
         // Trying to migrate again when already done is a no-op
-        assertTrue(deviceContext.migrateSharedPreferencesFrom(mContext, "test"));
+        assertTrue(deviceContext.moveSharedPreferencesFrom(mContext, "test"));
         assertEquals(0, mContext.getSharedPreferences("test", Context.MODE_PRIVATE)
                 .getInt("answer", 0));
         assertEquals(42, deviceContext.getSharedPreferences("test", Context.MODE_PRIVATE)
@@ -132,7 +130,7 @@
         deviceContext.getSharedPreferences("test", Context.MODE_PRIVATE).edit()
                 .putInt("question", 24).commit();
 
-        assertTrue(mContext.migrateSharedPreferencesFrom(deviceContext, "test"));
+        assertTrue(mContext.moveSharedPreferencesFrom(deviceContext, "test"));
         assertEquals(42, mContext.getSharedPreferences("test", Context.MODE_PRIVATE)
                 .getInt("answer", 0));
         assertEquals(24, mContext.getSharedPreferences("test", Context.MODE_PRIVATE)
@@ -143,8 +141,8 @@
                 .getInt("question", 0));
     }
 
-    public void testMigrateDatabaseFrom() throws Exception {
-        final Context deviceContext = mContext.createDeviceEncryptedStorageContext();
+    public void testMoveDatabaseFrom() throws Exception {
+        final Context deviceContext = mContext.createDeviceProtectedStorageContext();
 
         SQLiteDatabase db = mContext.openOrCreateDatabase("test.db",
                 Context.MODE_PRIVATE | Context.MODE_ENABLE_WRITE_AHEAD_LOGGING, null);
@@ -154,7 +152,7 @@
         db.close();
 
         // Verify that we can migrate
-        assertTrue(deviceContext.migrateDatabaseFrom(mContext, "test.db"));
+        assertTrue(deviceContext.moveDatabaseFrom(mContext, "test.db"));
         db = deviceContext.openOrCreateDatabase("test.db",
                 Context.MODE_PRIVATE | Context.MODE_ENABLE_WRITE_AHEAD_LOGGING, null);
         Cursor c = db.query("list", null, null, null, null, null, null);
@@ -168,10 +166,10 @@
         db.close();
 
         // Trying to migrate again when already done is a no-op
-        assertTrue(deviceContext.migrateDatabaseFrom(mContext, "test.db"));
+        assertTrue(deviceContext.moveDatabaseFrom(mContext, "test.db"));
 
         // Verify that we can migrate back
-        assertTrue(mContext.migrateDatabaseFrom(deviceContext, "test.db"));
+        assertTrue(mContext.moveDatabaseFrom(deviceContext, "test.db"));
         db = mContext.openOrCreateDatabase("test.db",
                 Context.MODE_PRIVATE | Context.MODE_ENABLE_WRITE_AHEAD_LOGGING, null);
         c = db.query("list", null, null, null, null, null, null);
diff --git a/tests/tests/content/src/android/content/res/cts/AssetFileDescriptorTest.java b/tests/tests/content/src/android/content/res/cts/AssetFileDescriptorTest.java
index e4a9500..f5dc5ca 100644
--- a/tests/tests/content/src/android/content/res/cts/AssetFileDescriptorTest.java
+++ b/tests/tests/content/src/android/content/res/cts/AssetFileDescriptorTest.java
@@ -24,9 +24,11 @@
 import java.util.Arrays;
 
 import android.content.res.AssetFileDescriptor;
+import android.os.Bundle;
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
 
 public class AssetFileDescriptorTest extends AndroidTestCase {
     private static final long START_OFFSET = 0;
@@ -66,6 +68,31 @@
         getContext().deleteFile(FILE_NAME);
     }
 
+    @SmallTest
+    public void testConstructor() throws IOException {
+        ParcelFileDescriptor fd = ParcelFileDescriptor.open(
+                mFile, ParcelFileDescriptor.MODE_READ_WRITE);
+        AssetFileDescriptor assetFileDes;
+        Bundle extras;
+
+        assetFileDes = new AssetFileDescriptor(fd, START_OFFSET, LENGTH);
+        assertNotNull(assetFileDes);
+        assetFileDes.close();
+
+        extras = null;
+        assetFileDes = new AssetFileDescriptor(fd, START_OFFSET, LENGTH, extras);
+        assertEquals(extras, assetFileDes.getExtras());
+        assertNotNull(assetFileDes);
+        assetFileDes.close();
+
+        extras = new Bundle();
+        assetFileDes = new AssetFileDescriptor(fd, START_OFFSET, LENGTH, extras);
+        assertEquals(extras, assetFileDes.getExtras());
+        assertNotNull(assetFileDes);
+        assetFileDes.close();
+    }
+
+    @SmallTest
     public void testInputOutputStream() throws IOException {
         /*
          * test createOutputStream() and createInputStrean()
@@ -150,6 +177,7 @@
         }
     }
 
+    @SmallTest
     public void testMiscMethod() {
         // test getLength()
         assertEquals(LENGTH, mAssetFileDes.getLength());
diff --git a/tests/tests/content/src/android/content/res/cts/AssetManagerTest.java b/tests/tests/content/src/android/content/res/cts/AssetManagerTest.java
index b861264..4893ec1 100644
--- a/tests/tests/content/src/android/content/res/cts/AssetManagerTest.java
+++ b/tests/tests/content/src/android/content/res/cts/AssetManagerTest.java
@@ -26,6 +26,7 @@
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.util.TypedValue;
 
 import java.io.BufferedReader;
@@ -45,6 +46,7 @@
         mAssets = mContext.getAssets();
     }
 
+    @SmallTest
     public void testAssetOperations() throws IOException, XmlPullParserException {
         final Resources res = getContext().getResources();
         final TypedValue value = new TypedValue();
@@ -117,7 +119,23 @@
 
     }
 
+    @SmallTest
+    public void testClose() throws IOException, XmlPullParserException {
+        final AssetManager assets = new AssetManager();
+        assets.close();
 
+        // Should no-op.
+        assets.close();
+
+        try {
+            assets.openXmlResourceParser("AndroidManifest.xml");
+            fail("Expected RuntimeException");
+        } catch (RuntimeException e) {
+            // Expected.
+        }
+    }
+
+    @SmallTest
     public void testGetNonSystemLocales() {
         // This is the list of locales built into this test package. It is basically the locales
         // specified in the Android.mk files (assuming they have corresponding resources), plus the
diff --git a/tests/tests/content/src/android/content/res/cts/ColorStateListTest.java b/tests/tests/content/src/android/content/res/cts/ColorStateListTest.java
index 2222ce4..2029b95 100644
--- a/tests/tests/content/src/android/content/res/cts/ColorStateListTest.java
+++ b/tests/tests/content/src/android/content/res/cts/ColorStateListTest.java
@@ -20,51 +20,110 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
+import android.content.pm.ActivityInfo;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
+import android.content.res.Resources.Theme;
 import android.graphics.Color;
 import android.os.Parcel;
 import android.test.AndroidTestCase;
 
 import android.content.cts.R;
-
+import android.test.suitebuilder.annotation.SmallTest;
 
 public class ColorStateListTest extends AndroidTestCase {
-    public void testColorStateList() throws NotFoundException, XmlPullParserException, IOException {
-        final int[][] state = new int[][] { { 0 }, { 0 } };
-        final int[] colors = new int[] { Color.RED, Color.BLUE };
-        ColorStateList c = new ColorStateList(state, colors);
+
+    @SmallTest
+    public void testConstructor() {
+        final int[][] state = new int[][]{{0}, {0}};
+        final int[] colors = new int[]{Color.RED, Color.BLUE};
+        final ColorStateList c = new ColorStateList(state, colors);
         assertTrue(c.isStateful());
         assertEquals(Color.RED, c.getDefaultColor());
+    }
 
-        final int alpha = 36;
-        final ColorStateList c1 = c.withAlpha(alpha);
-        assertNotSame(Color.RED, c1.getDefaultColor());
-        // check alpha
-        assertEquals(alpha, c1.getDefaultColor() >>> 24);
-        assertEquals(Color.RED & 0x00FF0000, c1.getDefaultColor() & 0x00FF0000);
-
-        final int xmlId = R.drawable.testcolor;
-        final int colorInXml = 0xFFA6C839;// this color value is define in testcolor.xml file.
+    @SmallTest
+    public void testCreateFromXml() throws Exception {
+        final int xmlId = R.color.testcolor;
+        final int colorInXml = 0xFFA6C839; // this color value is defined in testcolor.xml file.
         final Resources res = getContext().getResources();
-        c = ColorStateList.createFromXml(res, res.getXml(xmlId));
+        final ColorStateList c = ColorStateList.createFromXml(res, res.getXml(xmlId));
         assertEquals(colorInXml, c.getDefaultColor());
         assertEquals(0, c.describeContents());
         assertFalse(c.isStateful());
         assertNotNull(c.toString());
         assertEquals(colorInXml, c.getColorForState(new int[]{0}, 0));
+    }
 
-        c = ColorStateList.valueOf(Color.GRAY);
+    @SmallTest
+    public void testCreateFromXmlThemed() throws Exception {
+        final int xmlId = R.color.testcolor_themed;
+        final int colorInXml = Color.BLACK; // this color value is defined in styles.xml file.
+        final Resources res = getContext().getResources();
+        final Theme theme = res.newTheme();
+        theme.applyStyle(R.style.Theme_ThemedDrawableTest, true);
+        final ColorStateList c = ColorStateList.createFromXml(res, res.getXml(xmlId), theme);
+        assertEquals(colorInXml, c.getDefaultColor());
+        assertEquals(0, c.describeContents());
+        assertFalse(c.isStateful());
+        assertNotNull(c.toString());
+        assertEquals(colorInXml, c.getColorForState(new int[]{0}, 0));
+    }
+
+    @SmallTest
+    public void testGetChangingConfigurations() {
+        final Resources res = getContext().getResources();
+        ColorStateList c;
+
+        c = res.getColorStateList(R.color.testcolor, null);
+        assertEquals(c.getChangingConfigurations(), 0);
+
+        c = res.getColorStateList(R.color.testcolor_orientation, null);
+        assertEquals(ActivityInfo.CONFIG_ORIENTATION, c.getChangingConfigurations());
+    }
+
+    @SmallTest
+    public void testWithAlpha() {
+        final int[][] state = new int[][]{{0}, {0}};
+        final int[] colors = new int[]{Color.RED, Color.BLUE};
+        final ColorStateList c = new ColorStateList(state, colors);
+        final int alpha = 36;
+        final ColorStateList c1 = c.withAlpha(alpha);
+        assertNotSame(Color.RED, c1.getDefaultColor());
+        assertEquals(alpha, c1.getDefaultColor() >>> 24);
+        assertEquals(Color.RED & 0x00FF0000, c1.getDefaultColor() & 0x00FF0000);
+    }
+
+    @SmallTest
+    public void testValueOf() {
+        final ColorStateList c = ColorStateList.valueOf(Color.GRAY);
         assertEquals(Color.GRAY, c.getDefaultColor());
+    }
 
+    @SmallTest
+    public void testParcelable() {
+        final ColorStateList c = ColorStateList.valueOf(Color.GRAY);
         final Parcel parcel = Parcel.obtain();
         c.writeToParcel(parcel, 0);
         parcel.setDataPosition(0);
-        ColorStateList actual = ColorStateList.CREATOR.createFromParcel(parcel);
-        // can only compare the state and the default color. because no API to
-        // get every color of ColorStateList
+
+        final ColorStateList actual = ColorStateList.CREATOR.createFromParcel(parcel);
         assertEquals(c.isStateful(), actual.isStateful());
         assertEquals(c.getDefaultColor(), actual.getDefaultColor());
     }
+
+    @SmallTest
+    public void testIsOpaque() {
+        ColorStateList c;
+
+        c = ColorStateList.valueOf(Color.GRAY);
+        assertTrue(c.isOpaque());
+
+        c = ColorStateList.valueOf(0x80FFFFFF);
+        assertFalse(c.isOpaque());
+
+        c = ColorStateList.valueOf(Color.TRANSPARENT);
+        assertFalse(c.isOpaque());
+    }
 }
diff --git a/tests/tests/content/src/android/content/res/cts/ConfigurationTest.java b/tests/tests/content/src/android/content/res/cts/ConfigurationTest.java
index c1ee6c4..bc0f42e 100644
--- a/tests/tests/content/src/android/content/res/cts/ConfigurationTest.java
+++ b/tests/tests/content/src/android/content/res/cts/ConfigurationTest.java
@@ -403,6 +403,14 @@
         assertEquals(View.LAYOUT_DIRECTION_RTL, config.getLayoutDirection());
     }
 
+    public void testIsScreenRound() {
+        Configuration config = new Configuration();
+        assertFalse(config.isScreenRound());
+
+        config.screenLayout |= Configuration.SCREENLAYOUT_ROUND_YES;
+        assertTrue(config.isScreenRound());
+    }
+
     public void testFixUpLocaleList() {
         Configuration config = new Configuration();
 
diff --git a/tests/tests/content/src/android/content/res/cts/Resources_NotFoundExceptionTest.java b/tests/tests/content/src/android/content/res/cts/Resources_NotFoundExceptionTest.java
index 8fa8d7b..d75fcdd 100644
--- a/tests/tests/content/src/android/content/res/cts/Resources_NotFoundExceptionTest.java
+++ b/tests/tests/content/src/android/content/res/cts/Resources_NotFoundExceptionTest.java
@@ -23,41 +23,57 @@
 public class Resources_NotFoundExceptionTest extends TestCase {
 
     public void testNotFoundException() {
-        NotFoundException ne = null;
-        boolean isThrowed = false;
-        boolean isFinnalyRun = false;
+        NotFoundException ne;
+        boolean wasThrown;
+
+        wasThrown = false;
+        ne = new NotFoundException();
+
         try {
-            ne = new NotFoundException();
             throw ne;
         } catch (NotFoundException e) {
             // expected
             assertSame(ne, e);
-            isThrowed = true;
+            wasThrown = true;
         } finally {
-            if (!isThrowed) {
+            if (!wasThrown) {
                 fail("should throw out NotFoundException");
             }
-            isFinnalyRun = true;
         }
-        assertTrue(isFinnalyRun);
 
-        isThrowed = false;
-        isFinnalyRun = false;
         final String MESSAGE = "test";
+        wasThrown = false;
+        ne = new NotFoundException(MESSAGE);
+
         try {
-            ne = new NotFoundException(MESSAGE);
             throw ne;
         } catch (NotFoundException e) {
             // expected
             assertSame(ne, e);
             assertEquals(MESSAGE, e.getMessage());
-            isThrowed = true;
+            wasThrown = true;
         } finally {
-            if (!isThrowed) {
+            if (!wasThrown) {
                 fail("should throw out NotFoundException");
             }
-            isFinnalyRun = true;
         }
-        assertTrue(isFinnalyRun);
+
+        final Exception CAUSE = new NullPointerException();
+        wasThrown = false;
+        ne = new NotFoundException(MESSAGE, CAUSE);
+
+        try {
+            throw ne;
+        } catch (NotFoundException e) {
+            // expected
+            assertSame(ne, e);
+            assertEquals(MESSAGE, e.getMessage());
+            assertEquals(CAUSE, e.getCause());
+            wasThrown = true;
+        } finally {
+            if (!wasThrown) {
+                fail("should throw out NotFoundException");
+            }
+        }
     }
 }
diff --git a/tests/tests/content/src/android/content/res/cts/Resources_ThemeTest.java b/tests/tests/content/src/android/content/res/cts/Resources_ThemeTest.java
index 533b186..b7a621f 100644
--- a/tests/tests/content/src/android/content/res/cts/Resources_ThemeTest.java
+++ b/tests/tests/content/src/android/content/res/cts/Resources_ThemeTest.java
@@ -23,7 +23,10 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.content.res.Resources.Theme;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
 import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.util.AttributeSet;
 import android.util.TypedValue;
 import android.util.Xml;
@@ -44,6 +47,7 @@
         mResTheme = getContext().getResources().newTheme();
     }
 
+    @SmallTest
     public void testSetMethods() {
         // call a native method, and have no way to get the style
         mResTheme.applyStyle(R.raw.testmp3, false);
@@ -54,6 +58,7 @@
         mResTheme.setTo(other);
     }
 
+    @SmallTest
     public void testObtainStyledAttributes() {
         final int[] attrs = new int[1];
         attrs[0] = R.raw.testmp3;
@@ -77,12 +82,14 @@
         testTypedArray.recycle();
     }
 
+    @SmallTest
     public void testResolveAttribute() {
         final TypedValue value = new TypedValue();
         getContext().getResources().getValue(R.raw.testmp3, value, true);
         assertFalse(mResTheme.resolveAttribute(R.raw.testmp3, value, false));
     }
 
+    @SmallTest
     public void testGetChangingConfigurations() {
         Resources.Theme theme = getContext().getResources().newTheme();
         assertEquals("Initial changing configuration mask is empty",
@@ -104,6 +111,7 @@
                 theme.getChangingConfigurations());
     }
 
+    @SmallTest
     public void testRebase() {
         Resources res = getContext().getResources();
         Configuration config = res.getConfiguration();
@@ -132,4 +140,21 @@
         assertEquals("Theme was rebased in RTL config", true, t.getBoolean(0, false));
         t.recycle();
     }
+
+    @SmallTest
+    public void testGetDrawable() {
+        final Resources res = getContext().getResources();
+        final Theme theme = res.newTheme();
+        theme.applyStyle(R.style.Theme_ThemedDrawableTest, true);
+
+        final ColorDrawable dr = (ColorDrawable) theme.getDrawable(R.drawable.colordrawable_themed);
+        assertEquals(Color.BLACK, dr.getColor());
+    }
+
+    @SmallTest
+    public void testGetResources() {
+        final Resources res = getContext().getResources();
+        final Theme theme = res.newTheme();
+        assertSame(res, theme.getResources());
+    }
 }
diff --git a/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java b/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java
index 2eb82a8..ee7449c 100644
--- a/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java
+++ b/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java
@@ -16,11 +16,11 @@
 
 package android.content.res.cts;
 
-import android.content.cts.R;
-
 import org.xmlpull.v1.XmlPullParserException;
 
+import android.content.cts.R;
 import android.content.cts.util.XmlUtils;
+import android.content.pm.ActivityInfo;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.test.AndroidTestCase;
@@ -30,12 +30,10 @@
 
 import java.io.IOException;
 
-
-public class TypedArrayTest extends AndroidTestCase{
-    private TypedArray mTypedArray;
+public class TypedArrayTest extends AndroidTestCase {
     private static final int DEFINT = -1;
     private static final float DEFFLOAT = -1.0f;
-    private static final int EXPECTEDCLOLOR = 0xff0000ff;
+    private static final int EXPECTED_COLOR = 0xff0000ff;
     private static final int EXPECTED_COLOR_STATE = 0xff00ff00;
     private static final float EXPECTED_DIMENSION = 0.75f;
     private static final int EXPECTED_PIXEL_OFFSET = 10;
@@ -47,20 +45,23 @@
     private static final String EXPECTED_STRING = "Hello, Android!";
     private static final String EXPECTED_TEXT = "TypedArray Test!";
     private static final String[] EXPECTED_TEXT_ARRAY = {"Easy", "Medium", "Hard"};
-    private static final int EXPETED_INDEX = 15;
+    private static final int EXPECTED_INDEX = 15;
     private static final TypedValue DEF_VALUE = new TypedValue();
-    private static final int EXPECTED_INDEX_COUNT = 16;
+    private static final int EXPECTED_INDEX_COUNT = 17;
     private static final String EXPTECTED_POS_DESCRIP = "<internal>";
-    private static final int EXPECTED_LENGTH = 16;
+    private static final int EXPECTED_LENGTH = 19;
     private static final String EXPECTED_NON_RESOURCE_STRING = "testNonResourcesString";
     private static final String XML_BEGIN = "resources";
     private static final int EXPECTED_INT_ATT = 86400;
+    private static final int EXPECTED_CHANGING_CONFIG =
+            ActivityInfo.CONFIG_ORIENTATION | ActivityInfo.CONFIG_LOCALE;
+
+    private TypedArray mTypedArray;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        final int[] attrs = R.styleable.style1;
-        mTypedArray = getContext().getTheme().obtainStyledAttributes(R.style.Whatever, attrs);
+        mTypedArray = getContext().getTheme().obtainStyledAttributes(R.style.Whatever, R.styleable.style1);
     }
 
     @Override
@@ -69,85 +70,126 @@
         mTypedArray.recycle();
     }
 
-    /*
-     * Test all get attrs methods, all test value are in styles.xml and attrs.xml.
-     */
-    public void testAttrsMethod() {
-        // getBoolean test
-        assertTrue(mTypedArray.getBoolean(R.styleable.style1_type1, false));
-        assertFalse(mTypedArray.getBoolean(R.styleable.style1_type2, true));
+    public void testGetType() {
+        final TypedArray t = getContext().getTheme().obtainStyledAttributes(
+                R.style.Whatever, R.styleable.style1);
 
-        assertEquals(EXPECTEDCLOLOR, mTypedArray.getColor(R.styleable.style1_type3, DEFINT));
+        assertEquals(TypedValue.TYPE_INT_BOOLEAN, t.getType(R.styleable.style1_type1));
+        assertEquals(TypedValue.TYPE_INT_BOOLEAN, t.getType(R.styleable.style1_type2));
+        assertEquals(TypedValue.TYPE_INT_COLOR_ARGB8, t.getType(R.styleable.style1_type3));
+        assertEquals(TypedValue.TYPE_INT_COLOR_ARGB8, t.getType(R.styleable.style1_type4));
+        assertEquals(TypedValue.TYPE_DIMENSION, t.getType(R.styleable.style1_type5));
+        assertEquals(TypedValue.TYPE_DIMENSION, t.getType(R.styleable.style1_type6));
+        assertEquals(TypedValue.TYPE_DIMENSION, t.getType(R.styleable.style1_type7));
+        assertEquals(TypedValue.TYPE_STRING, t.getType(R.styleable.style1_type8));
+        assertEquals(TypedValue.TYPE_FLOAT, t.getType(R.styleable.style1_type9));
+        assertEquals(TypedValue.TYPE_FRACTION, t.getType(R.styleable.style1_type10));
+        assertEquals(TypedValue.TYPE_INT_DEC, t.getType(R.styleable.style1_type11));
+        assertEquals(TypedValue.TYPE_INT_DEC, t.getType(R.styleable.style1_type12));
+        assertEquals(TypedValue.TYPE_STRING, t.getType(R.styleable.style1_type13));
+        assertEquals(TypedValue.TYPE_STRING, t.getType(R.styleable.style1_type14));
+        assertEquals(TypedValue.TYPE_REFERENCE, t.getType(R.styleable.style1_type15));
+        assertEquals(TypedValue.TYPE_STRING, t.getType(R.styleable.style1_type16));
+        assertEquals(TypedValue.TYPE_NULL, t.getType(R.styleable.style1_typeEmpty));
+        assertEquals(TypedValue.TYPE_NULL, t.getType(R.styleable.style1_typeUndefined));
 
-        // getColorStateList test
-        final int[] set = new int[1];
-        set[0] = 0;
+        t.recycle();
+    }
+
+    public void testBasics() {
+        final TypedArray t = getContext().getTheme().obtainStyledAttributes(
+                R.style.Whatever, R.styleable.style1);
+
+        assertEquals(EXPECTED_CHANGING_CONFIG, t.getChangingConfigurations());
+        assertEquals(EXPECTED_INDEX_COUNT, t.getIndexCount());
+        assertEquals(EXPTECTED_POS_DESCRIP, t.getPositionDescription());
+        assertEquals(EXPECTED_LENGTH, t.length());
+        assertEquals(getContext().getResources(), t.getResources());
+        assertNotNull(t.toString());
+
+        t.recycle();
+    }
+
+    public void testGetAttributes() {
+        final TypedArray t = getContext().getTheme().obtainStyledAttributes(
+                R.style.Whatever, R.styleable.style1);
+
+        assertTrue(t.getBoolean(R.styleable.style1_type1, false));
+        assertFalse(t.getBoolean(R.styleable.style1_type2, true));
+
+        assertEquals(EXPECTED_COLOR,
+                t.getColor(R.styleable.style1_type3, DEFINT));
         assertEquals(EXPECTED_COLOR_STATE,
-                mTypedArray.getColorStateList(R.styleable.style1_type4).
-                getColorForState(set, DEFINT));
+                t.getColorStateList(R.styleable.style1_type4).getDefaultColor());
 
         // This get values equals attribute dimension value set in styles.xml
         // multiplied by the appropriate metric, the metric is unknown.
         assertEquals(EXPECTED_DIMENSION,
-                mTypedArray.getDimension(R.styleable.style1_type5, DEFFLOAT));
+                t.getDimension(R.styleable.style1_type5, DEFFLOAT));
+
         assertEquals(EXPECTED_PIXEL_OFFSET,
-                mTypedArray.getDimensionPixelOffset(R.styleable.style1_type6, DEFINT));
+                t.getDimensionPixelOffset(R.styleable.style1_type6, DEFINT));
         assertEquals(EXPECTED_LAYOUT_DIMENSION,
-                mTypedArray.getLayoutDimension(R.styleable.style1_type6, "type6"));
+                t.getLayoutDimension(R.styleable.style1_type6, "type6"));
         assertEquals(EXPECTED_LAYOUT_DIMENSION,
-                mTypedArray.getLayoutDimension(R.styleable.style1_type6, 0));
+                t.getLayoutDimension(R.styleable.style1_type6, 0));
+
         assertEquals(EXPECTED_PIXEL_SIZE,
-                mTypedArray.getDimensionPixelSize(R.styleable.style1_type7, DEFINT));
+                t.getDimensionPixelSize(R.styleable.style1_type7, DEFINT));
 
-        // getDrawable test
-        assertNotNull(mTypedArray.getDrawable(R.styleable.style1_type8));
-        // getResourceId test
-        assertEquals(R.drawable.pass,
-                mTypedArray.getResourceId(R.styleable.style1_type8, DEFINT));
+        assertNotNull(t.getDrawable(R.styleable.style1_type8));
+        assertEquals(R.drawable.pass, t.getResourceId(R.styleable.style1_type8, DEFINT));
 
-        assertEquals(EXPECTED_FLOAT, mTypedArray.getFloat(R.styleable.style1_type9, DEFFLOAT));
-
+        assertEquals(EXPECTED_FLOAT,
+                t.getFloat(R.styleable.style1_type9, DEFFLOAT));
         assertEquals(EXPECTED_FRACTION,
-                mTypedArray.getFraction(R.styleable.style1_type10, 10, 10, DEFFLOAT));
+                t.getFraction(R.styleable.style1_type10, 10, 10, DEFFLOAT));
+        assertEquals(EXPECTED_INT,
+                t.getInt(R.styleable.style1_type11, DEFINT));
+        assertEquals(EXPECTED_INT_ATT,
+                t.getInteger(R.styleable.style1_type12, DEFINT));
 
-        assertEquals(EXPECTED_INT, mTypedArray.getInt(R.styleable.style1_type11, DEFINT));
+        assertEquals(EXPECTED_STRING, t.getString(R.styleable.style1_type13));
+        assertNull(t.getNonResourceString(R.styleable.style1_type14));
+        assertEquals(EXPECTED_TEXT, t.getText(R.styleable.style1_type14));
 
-        assertEquals(EXPECTED_INT_ATT, mTypedArray.getInteger(R.styleable.style1_type12, DEFINT));
-
-        assertEquals(EXPECTED_STRING, mTypedArray.getString(R.styleable.style1_type13));
-
-        // getNonResourceString test
-        assertNull(mTypedArray.getNonResourceString(R.styleable.style1_type14));
-
-        assertEquals(EXPECTED_TEXT, mTypedArray.getText(R.styleable.style1_type14));
-
-        CharSequence[] textArray = mTypedArray.getTextArray(R.styleable.style1_type15);
+        final CharSequence[] textArray = t.getTextArray(R.styleable.style1_type15);
         assertEquals(EXPECTED_TEXT_ARRAY[0], textArray[0]);
         assertEquals(EXPECTED_TEXT_ARRAY[1], textArray[1]);
         assertEquals(EXPECTED_TEXT_ARRAY[2], textArray[2]);
 
-        // getIndex test
-        int index = mTypedArray.getIndex(R.styleable.style1_type16);
-        assertEquals(EXPETED_INDEX, index);
-        assertTrue(mTypedArray.getValue(index, DEF_VALUE));
-        // hasValue test
-        assertTrue(mTypedArray.hasValue(R.styleable.style1_type16));
+        final int index = t.getIndex(R.styleable.style1_type16);
+        assertEquals(EXPECTED_INDEX, index);
+        assertTrue(t.getValue(index, DEF_VALUE));
+    }
 
-        // peekValue test
-        assertNotNull(mTypedArray.peekValue(R.styleable.style1_type16));
+    public void testPeekValue() {
+        final TypedArray t = getContext().getTheme().obtainStyledAttributes(
+                R.style.Whatever, R.styleable.style1);
 
-        assertEquals(EXPECTED_INDEX_COUNT, mTypedArray.getIndexCount());
+        final TypedValue v = t.peekValue(R.styleable.style1_type11);
+        assertNotNull(v);
+        assertEquals(TypedValue.TYPE_INT_DEC, v.type);
+        assertEquals(EXPECTED_INT, v.data);
 
-        assertEquals(EXPTECTED_POS_DESCRIP,
-                mTypedArray.getPositionDescription());
+        t.recycle();
+    }
 
-        // getResources test
-        assertEquals(getContext().getResources(), mTypedArray.getResources());
+    public void testHasValue() {
+        final TypedArray t = getContext().getTheme().obtainStyledAttributes(
+                R.style.Whatever, R.styleable.style1);
 
-        assertEquals(EXPECTED_LENGTH, mTypedArray.length());
+        // hasValue()
+        assertTrue(t.hasValue(R.styleable.style1_type16));
+        assertFalse(t.hasValue(R.styleable.style1_typeEmpty));
+        assertFalse(t.hasValue(R.styleable.style1_typeUndefined));
 
-        // toString test
-        assertNotNull(mTypedArray.toString());
+        // hasValueOrEmpty()
+        assertTrue(t.hasValueOrEmpty(R.styleable.style1_type16));
+        assertTrue(t.hasValueOrEmpty(R.styleable.style1_typeEmpty));
+        assertFalse(t.hasValueOrEmpty(R.styleable.style1_typeUndefined));
+
+        t.recycle();
     }
 
     public void testRecycle() {
diff --git a/tests/tests/display/Android.mk b/tests/tests/display/Android.mk
index 2b81ec1..5de5610 100644
--- a/tests/tests/display/Android.mk
+++ b/tests/tests/display/Android.mk
@@ -27,7 +27,7 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test platform-test-annotations
 
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
diff --git a/tests/tests/display/src/android/display/cts/DisplayTest.java b/tests/tests/display/src/android/display/cts/DisplayTest.java
index 1f9f8d1..1d1db2b 100644
--- a/tests/tests/display/src/android/display/cts/DisplayTest.java
+++ b/tests/tests/display/src/android/display/cts/DisplayTest.java
@@ -28,6 +28,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.ParcelFileDescriptor;
+import android.platform.test.annotations.Presubmit;
 import android.test.InstrumentationTestCase;
 import android.util.DisplayMetrics;
 import android.view.Display;
@@ -139,6 +140,7 @@
     /**
      * Verify that the WindowManager returns the default display.
      */
+    @Presubmit
     public void testDefaultDisplay() {
         assertEquals(Display.DEFAULT_DISPLAY, mWindowManager.getDefaultDisplay().getDisplayId());
     }
diff --git a/tests/tests/dpi/Android.mk b/tests/tests/dpi/Android.mk
index 0c158121..3f4cde5 100644
--- a/tests/tests/dpi/Android.mk
+++ b/tests/tests/dpi/Android.mk
@@ -17,7 +17,7 @@
 
 include $(CLEAR_VARS)
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner platform-test-annotations
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java b/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java
index e722646..fc38fdd 100644
--- a/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java
+++ b/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.platform.test.annotations.Presubmit;
 import android.test.AndroidTestCase;
 import android.util.DisplayMetrics;
 import android.view.Display;
@@ -31,6 +32,7 @@
  */
 public class ConfigurationTest extends AndroidTestCase {
 
+    @Presubmit
     public void testScreenConfiguration() {
         WindowManager windowManager =
                 (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
diff --git a/tests/tests/externalservice/Android.mk b/tests/tests/externalservice/Android.mk
index 3adfc34..c438dd6 100644
--- a/tests/tests/externalservice/Android.mk
+++ b/tests/tests/externalservice/Android.mk
@@ -36,7 +36,7 @@
 
 LOCAL_PACKAGE_NAME := CtsExternalServiceTestCases
 
-LOCAL_SDK_VERSION := system_current
+LOCAL_SDK_VERSION := current
 
 include $(BUILD_CTS_PACKAGE)
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/externalservice/service/Android.mk b/tests/tests/externalservice/service/Android.mk
index 68e9d1a..9541b0e 100644
--- a/tests/tests/externalservice/service/Android.mk
+++ b/tests/tests/externalservice/service/Android.mk
@@ -30,6 +30,6 @@
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
 
-LOCAL_SDK_VERSION := system_current
+LOCAL_SDK_VERSION := current
 
 include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/tests/externalservice/src/android/externalservice/cts/ExternalServiceTest.java b/tests/tests/externalservice/src/android/externalservice/cts/ExternalServiceTest.java
index b80b2ff..37c8613 100644
--- a/tests/tests/externalservice/src/android/externalservice/cts/ExternalServiceTest.java
+++ b/tests/tests/externalservice/src/android/externalservice/cts/ExternalServiceTest.java
@@ -31,7 +31,6 @@
 import android.os.RemoteException;
 import android.test.AndroidTestCase;
 import android.util.Log;
-import android.util.MutableInt;
 
 import android.externalservice.common.ServiceMessages;
 
@@ -140,15 +139,13 @@
 
         // Check the identity of the service.
         Messenger remote = new Messenger(mConnection.service);
-        MutableInt uid = new MutableInt(0);
-        MutableInt pid = new MutableInt(0);
-        StringBuilder pkg = new StringBuilder();
-        assertTrue(identifyService(remote, uid, pid, pkg));
+        ServiceIdentity id = identifyService(remote);
+        assertNotNull(id);
 
-        assertFalse(uid.value == 0 || pid.value == 0);
-        assertNotEquals(Process.myUid(), uid.value);
-        assertNotEquals(Process.myPid(), pid.value);
-        assertEquals(getContext().getPackageName(), pkg.toString());
+        assertFalse(id.uid == 0 || id.pid == 0);
+        assertNotEquals(Process.myUid(), id.uid);
+        assertNotEquals(Process.myPid(), id.pid);
+        assertEquals(getContext().getPackageName(), id.packageName);
     }
 
     /** Tests that the APK providing the externalService can bind the service itself, and that
@@ -165,11 +162,9 @@
 
         // Get the identity of the creator.
         Messenger remoteCreator = new Messenger(creatorConnection.service);
-        MutableInt creatorUid = new MutableInt(0);
-        MutableInt creatorPid = new MutableInt(0);
-        StringBuilder creatorPkg = new StringBuilder();
-        assertTrue(identifyService(remoteCreator, creatorUid, creatorPid, creatorPkg));
-        assertFalse(creatorUid.value == 0 || creatorPid.value == 0);
+        ServiceIdentity creatorId = identifyService(remoteCreator);
+        assertNotNull(creatorId);
+        assertFalse(creatorId.uid == 0 || creatorId.pid == 0);
 
         // Have the creator actually start its service.
         final Message creatorMsg =
@@ -201,12 +196,9 @@
         // Get the connection to the creator's service.
         assertNotNull(creatorMsg.obj);
         Messenger remoteCreatorService = (Messenger) creatorMsg.obj;
-        MutableInt creatorServiceUid = new MutableInt(0);
-        MutableInt creatorServicePid = new MutableInt(0);
-        StringBuilder creatorServicePkg = new StringBuilder();
-        assertTrue(identifyService(remoteCreatorService, creatorServiceUid, creatorServicePid,
-                creatorServicePkg));
-        assertFalse(creatorServiceUid.value == 0 || creatorPid.value == 0);
+        ServiceIdentity creatorServiceId = identifyService(remoteCreatorService);
+        assertNotNull(creatorServiceId);
+        assertFalse(creatorServiceId.uid == 0 || creatorId.pid == 0);
 
         // Create an external service from this (the test) process.
         intent = new Intent();
@@ -216,37 +208,34 @@
         assertTrue(getContext().bindService(intent, mConnection,
                     Context.BIND_AUTO_CREATE | Context.BIND_EXTERNAL_SERVICE));
         assertTrue(mCondition.block(CONDITION_TIMEOUT));
-        MutableInt serviceUid = new MutableInt(0);
-        MutableInt servicePid = new MutableInt(0);
-        StringBuilder servicePkg = new StringBuilder();
-        assertTrue(identifyService(new Messenger(mConnection.service), serviceUid, servicePid,
-                servicePkg));
-        assertFalse(serviceUid.value == 0 || servicePid.value == 0);
+        ServiceIdentity serviceId = identifyService(new Messenger(mConnection.service));
+        assertNotNull(serviceId);
+        assertFalse(serviceId.uid == 0 || serviceId.pid == 0);
 
         // Make sure that all the processes are unique.
         int myUid = Process.myUid();
         int myPid = Process.myPid();
         String myPkg = getContext().getPackageName();
 
-        assertNotEquals(myUid, creatorUid.value);
-        assertNotEquals(myUid, creatorServiceUid.value);
-        assertNotEquals(myUid, serviceUid.value);
-        assertNotEquals(myPid, creatorPid.value);
-        assertNotEquals(myPid, creatorServicePid.value);
-        assertNotEquals(myPid, servicePid.value);
+        assertNotEquals(myUid, creatorId.uid);
+        assertNotEquals(myUid, creatorServiceId.uid);
+        assertNotEquals(myUid, serviceId.uid);
+        assertNotEquals(myPid, creatorId.pid);
+        assertNotEquals(myPid, creatorServiceId.pid);
+        assertNotEquals(myPid, serviceId.pid);
 
-        assertNotEquals(creatorUid.value, creatorServiceUid.value);
-        assertNotEquals(creatorUid.value, serviceUid.value);
-        assertNotEquals(creatorPid.value, creatorServicePid.value);
-        assertNotEquals(creatorPid.value, servicePid.value);
+        assertNotEquals(creatorId.uid, creatorServiceId.uid);
+        assertNotEquals(creatorId.uid, serviceId.uid);
+        assertNotEquals(creatorId.pid, creatorServiceId.pid);
+        assertNotEquals(creatorId.pid, serviceId.pid);
 
-        assertNotEquals(creatorServiceUid.value, serviceUid.value);
-        assertNotEquals(creatorServicePid.value, servicePid.value);
+        assertNotEquals(creatorServiceId.uid, serviceId.uid);
+        assertNotEquals(creatorServiceId.pid, serviceId.pid);
 
-        assertNotEquals(myPkg, creatorPkg.toString());
-        assertNotEquals(myPkg, creatorServicePkg.toString());
-        assertEquals(creatorPkg.toString(), creatorServicePkg.toString());
-        assertEquals(myPkg, servicePkg.toString());
+        assertNotEquals(myPkg, creatorId.packageName);
+        assertNotEquals(myPkg, creatorServiceId.packageName);
+        assertEquals(creatorId.packageName, creatorServiceId.packageName);
+        assertEquals(myPkg, serviceId.packageName);
 
         getContext().unbindService(creatorConnection);
     }
@@ -264,11 +253,9 @@
 
         assertTrue(mCondition.block(CONDITION_TIMEOUT));
 
-        MutableInt uidOne = new MutableInt(0);
-        MutableInt pidOne = new MutableInt(0);
-        StringBuilder pkgOne = new StringBuilder();
-        assertTrue(identifyService(new Messenger(initialConn.service), uidOne, pidOne, pkgOne));
-        assertFalse(uidOne.value == 0 || pidOne.value == 0);
+        ServiceIdentity idOne = identifyService(new Messenger(initialConn.service));
+        assertNotNull(idOne);
+        assertFalse(idOne.uid == 0 || idOne.pid == 0);
 
         // Bind the service with a different priority.
         mCondition.close();
@@ -279,38 +266,41 @@
 
         assertTrue(mCondition.block(CONDITION_TIMEOUT));
 
-        MutableInt uidTwo = new MutableInt(0);
-        MutableInt pidTwo = new MutableInt(0);
-        StringBuilder pkgTwo = new StringBuilder();
-        Messenger prioMessenger = new Messenger(prioConn.service);
-        assertTrue(identifyService(prioMessenger, uidTwo, pidTwo, pkgTwo));
-        assertFalse(uidTwo.value == 0 || pidTwo.value == 0);
+        ServiceIdentity idTwo = identifyService(new Messenger(prioConn.service));
+        assertNotNull(idTwo);
+        assertFalse(idTwo.uid == 0 || idTwo.pid == 0);
 
-        assertEquals(uidOne.value, uidTwo.value);
-        assertEquals(pidOne.value, pidTwo.value);
-        assertEquals(pkgOne.toString(), pkgTwo.toString());
-        assertNotEquals(Process.myUid(), uidOne.value);
-        assertNotEquals(Process.myPid(), pidOne.value);
-        assertEquals(getContext().getPackageName(), pkgOne.toString());
+        assertEquals(idOne.uid, idTwo.uid);
+        assertEquals(idOne.pid, idTwo.pid);
+        assertEquals(idOne.packageName, idTwo.packageName);
+        assertNotEquals(Process.myUid(), idOne.uid);
+        assertNotEquals(Process.myPid(), idOne.pid);
+        assertEquals(getContext().getPackageName(), idOne.packageName);
 
         getContext().unbindService(prioConn);
         getContext().unbindService(initialConn);
     }
 
-    /** Given a Messenger, this will message the service to retrieve its UID, PID, and package name,
-     * storing the results in the mutable parameters. */
-    private boolean identifyService(Messenger service, final MutableInt uid, final MutableInt pid,
-            final StringBuilder packageName) {
+    /** Contains information about the security principal of a Service. */
+    private static class ServiceIdentity {
+        int uid;
+        int pid;
+        String packageName;
+    }
+
+    /** Given a Messenger, this will message the service to retrieve its UID, PID, and package name.
+     * On success, returns a ServiceIdentity. On failure, returns null. */
+    private ServiceIdentity identifyService(Messenger service) {
+        final ServiceIdentity id = new ServiceIdentity();
         Handler handler = new Handler(Looper.getMainLooper()) {
             @Override
             public void handleMessage(Message msg) {
                 Log.d(TAG, "Received message: " + msg);
                 switch (msg.what) {
                     case ServiceMessages.MSG_IDENTIFY_RESPONSE:
-                        uid.value = msg.arg1;
-                        pid.value = msg.arg2;
-                        packageName.append(
-                                msg.getData().getString(ServiceMessages.IDENTIFY_PACKAGE));
+                        id.uid = msg.arg1;
+                        id.pid = msg.arg2;
+                        id.packageName = msg.getData().getString(ServiceMessages.IDENTIFY_PACKAGE);
                         mCondition.open();
                         break;
                 }
@@ -326,10 +316,12 @@
             service.send(msg);
         } catch (RemoteException e) {
             fail("Unexpected remote exception: " + e);
-            return false;
+            return null;
         }
 
-        return mCondition.block(CONDITION_TIMEOUT);
+        if (!mCondition.block(CONDITION_TIMEOUT))
+            return null;
+        return id;
     }
 
     private class Connection implements ServiceConnection {
diff --git a/tests/tests/graphics/res/color/fill_gradient_linear.xml b/tests/tests/graphics/res/color/fill_gradient_linear.xml
index e0e3f03..d9b7497 100644
--- a/tests/tests/graphics/res/color/fill_gradient_linear.xml
+++ b/tests/tests/graphics/res/color/fill_gradient_linear.xml
@@ -18,8 +18,8 @@
 -->
 <gradient xmlns:android="http://schemas.android.com/apk/res/android"
           android:angle="90"
-          android:startColor="?android:attr/colorPrimary"
-          android:endColor="?android:attr/colorControlActivated"
+          android:startColor="?attr/themeColor"
+          android:endColor="#0f0"
           android:centerColor="#00ff0000"
           android:startX="0"
           android:startY="0"
diff --git a/tests/tests/graphics/res/color/fill_gradient_linear_clamp.xml b/tests/tests/graphics/res/color/fill_gradient_linear_clamp.xml
new file mode 100644
index 0000000..56d9fc8
--- /dev/null
+++ b/tests/tests/graphics/res/color/fill_gradient_linear_clamp.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:angle="90"
+          android:startColor="?attr/themeColor"
+          android:endColor="#0f0"
+          android:centerColor="#00ff0000"
+          android:startX="0"
+          android:startY="0"
+          android:endX="50"
+          android:endY="50"
+          android:type="linear"
+          android:tileMode="clamp">
+</gradient>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/color/fill_gradient_linear_item.xml b/tests/tests/graphics/res/color/fill_gradient_linear_item.xml
index cfb1236..c1fb560 100644
--- a/tests/tests/graphics/res/color/fill_gradient_linear_item.xml
+++ b/tests/tests/graphics/res/color/fill_gradient_linear_item.xml
@@ -18,15 +18,15 @@
 -->
 <gradient xmlns:android="http://schemas.android.com/apk/res/android"
           android:angle="90"
-          android:startColor="?android:attr/colorPrimary"
-          android:endColor="?android:attr/colorControlActivated"
+          android:startColor="?attr/themeColor"
+          android:endColor="#0f0"
           android:centerColor="#f00"
           android:startX="0"
           android:startY="0"
           android:endX="100"
           android:endY="100"
           android:type="linear">
-    <item android:offset="0.1" android:color="?android:attr/colorPrimary"/>
+    <item android:offset="0.1" android:color="?attr/themeColor"/>
     <item android:offset="0.4" android:color="#fff"/>
-    <item android:offset="0.9" android:color="?android:attr/colorControlActivated"/>
+    <item android:offset="0.9" android:color="#0f0"/>
 </gradient>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/color/fill_gradient_linear_item_overlap.xml b/tests/tests/graphics/res/color/fill_gradient_linear_item_overlap.xml
index 18274b9..a5b261a 100644
--- a/tests/tests/graphics/res/color/fill_gradient_linear_item_overlap.xml
+++ b/tests/tests/graphics/res/color/fill_gradient_linear_item_overlap.xml
@@ -18,16 +18,16 @@
 -->
 <gradient xmlns:android="http://schemas.android.com/apk/res/android"
           android:angle="90"
-          android:startColor="?android:attr/colorPrimary"
-          android:endColor="?android:attr/colorControlActivated"
+          android:startColor="?attr/themeColor"
+          android:endColor="#0f0"
           android:centerColor="#f00"
           android:startX="0"
           android:startY="0"
           android:endX="100"
           android:endY="100"
           android:type="linear">
-    <item android:offset="0.1" android:color="?android:attr/colorPrimary"/>
+    <item android:offset="0.1" android:color="?attr/themeColor"/>
     <item android:offset="0.4" android:color="#f00"/>
     <item android:offset="0.4" android:color="#fff"/>
-    <item android:offset="0.9" android:color="?android:attr/colorControlActivated"/>
+    <item android:offset="0.9" android:color="#0f0"/>
 </gradient>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/color/fill_gradient_linear_item_overlap_mirror.xml b/tests/tests/graphics/res/color/fill_gradient_linear_item_overlap_mirror.xml
new file mode 100644
index 0000000..009eb52
--- /dev/null
+++ b/tests/tests/graphics/res/color/fill_gradient_linear_item_overlap_mirror.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:angle="90"
+          android:startColor="?attr/themeColor"
+          android:endColor="#0f0"
+          android:centerColor="#f00"
+          android:startX="0"
+          android:startY="0"
+          android:endX="50"
+          android:endY="50"
+          android:type="linear"
+          android:tileMode="mirror">
+    <item android:offset="0.1" android:color="?attr/themeColor"/>
+    <item android:offset="0.4" android:color="#f00"/>
+    <item android:offset="0.4" android:color="#fff"/>
+    <item android:offset="0.9" android:color="#0f0"/>
+</gradient>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/color/fill_gradient_linear_item_repeat.xml b/tests/tests/graphics/res/color/fill_gradient_linear_item_repeat.xml
new file mode 100644
index 0000000..c89e981
--- /dev/null
+++ b/tests/tests/graphics/res/color/fill_gradient_linear_item_repeat.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:angle="90"
+          android:startColor="?attr/themeColor"
+          android:endColor="#0f0"
+          android:centerColor="#f00"
+          android:startX="0"
+          android:startY="0"
+          android:endX="50"
+          android:endY="50"
+          android:type="linear"
+          android:tileMode="repeat">
+    <item android:offset="0.1" android:color="?attr/themeColor"/>
+    <item android:offset="0.4" android:color="#fff"/>
+    <item android:offset="0.9" android:color="#0f0"/>
+</gradient>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/color/fill_gradient_radial.xml b/tests/tests/graphics/res/color/fill_gradient_radial.xml
index ef6fd70..389a0fc 100644
--- a/tests/tests/graphics/res/color/fill_gradient_radial.xml
+++ b/tests/tests/graphics/res/color/fill_gradient_radial.xml
@@ -18,10 +18,10 @@
 -->
 <gradient xmlns:android="http://schemas.android.com/apk/res/android"
           android:centerColor="#ff0000"
-          android:endColor="?android:attr/colorControlActivated"
+          android:endColor="#0f0"
           android:centerX="300"
           android:centerY="300"
           android:gradientRadius="100"
-          android:startColor="?android:attr/colorPrimary"
+          android:startColor="?attr/themeColor"
           android:type="radial">
 </gradient>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/color/fill_gradient_radial_clamp.xml b/tests/tests/graphics/res/color/fill_gradient_radial_clamp.xml
new file mode 100644
index 0000000..ff29134
--- /dev/null
+++ b/tests/tests/graphics/res/color/fill_gradient_radial_clamp.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:centerColor="#ff0000"
+          android:endColor="#0f0"
+          android:centerX="300"
+          android:centerY="300"
+          android:gradientRadius="50"
+          android:startColor="?attr/themeColor"
+          android:type="radial"
+          android:tileMode="clamp">
+</gradient>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/color/fill_gradient_radial_item.xml b/tests/tests/graphics/res/color/fill_gradient_radial_item.xml
index c6cea7c..2f116c9 100644
--- a/tests/tests/graphics/res/color/fill_gradient_radial_item.xml
+++ b/tests/tests/graphics/res/color/fill_gradient_radial_item.xml
@@ -24,7 +24,7 @@
           android:gradientRadius="100"
           android:startColor="#ffffffff"
           android:type="radial">
-    <item android:offset="0.1" android:color="?android:attr/colorPrimary"/>
+    <item android:offset="0.1" android:color="?attr/themeColor"/>
     <item android:offset="0.4" android:color="#fff"/>
-    <item android:offset="0.9" android:color="?android:attr/colorControlActivated"/>
+    <item android:offset="0.9" android:color="#0f0"/>
 </gradient>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/color/fill_gradient_radial_item_repeat.xml b/tests/tests/graphics/res/color/fill_gradient_radial_item_repeat.xml
new file mode 100644
index 0000000..d17fc48
--- /dev/null
+++ b/tests/tests/graphics/res/color/fill_gradient_radial_item_repeat.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:centerColor="#ff0000"
+          android:endColor="#ff0000ff"
+          android:centerX="300"
+          android:centerY="300"
+          android:gradientRadius="50"
+          android:startColor="#ffffffff"
+          android:type="radial"
+          android:tileMode="repeat">
+    <item android:offset="0.1" android:color="?attr/themeColor"/>
+    <item android:offset="0.4" android:color="#fff"/>
+    <item android:offset="0.9" android:color="#0f0"/>
+</gradient>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/color/fill_gradient_radial_item_short.xml b/tests/tests/graphics/res/color/fill_gradient_radial_item_short.xml
index fefbe9f..111d023 100644
--- a/tests/tests/graphics/res/color/fill_gradient_radial_item_short.xml
+++ b/tests/tests/graphics/res/color/fill_gradient_radial_item_short.xml
@@ -21,6 +21,6 @@
           android:centerY="300"
           android:gradientRadius="100"
           android:type="radial">
-    <item android:offset="0.1" android:color="?android:attr/colorPrimary"/>
-    <item android:offset="0.9" android:color="?android:attr/colorControlActivated"/>
+    <item android:offset="0.1" android:color="?attr/themeColor"/>
+    <item android:offset="0.9" android:color="#0f0"/>
 </gradient>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/color/fill_gradient_radial_item_short_mirror.xml b/tests/tests/graphics/res/color/fill_gradient_radial_item_short_mirror.xml
new file mode 100644
index 0000000..1aa110c
--- /dev/null
+++ b/tests/tests/graphics/res/color/fill_gradient_radial_item_short_mirror.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:centerX="300"
+          android:centerY="300"
+          android:gradientRadius="50"
+          android:type="radial"
+          android:tileMode="mirror">
+    <item android:offset="0.1" android:color="?attr/themeColor"/>
+    <item android:offset="0.9" android:color="#0f0"/>
+</gradient>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/color/fill_gradient_sweep_clamp.xml b/tests/tests/graphics/res/color/fill_gradient_sweep_clamp.xml
new file mode 100644
index 0000000..80f39f3
--- /dev/null
+++ b/tests/tests/graphics/res/color/fill_gradient_sweep_clamp.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:centerColor="#ff0000"
+          android:endColor="#ff0000ff"
+          android:centerX="500"
+          android:centerY="500"
+          android:gradientRadius="10"
+          android:startColor="#ffffffff"
+          android:type="sweep"
+          android:tileMode="clamp">
+</gradient>
diff --git a/tests/tests/graphics/res/color/fill_gradient_sweep_item.xml b/tests/tests/graphics/res/color/fill_gradient_sweep_item.xml
index 332b9389..2a010c0 100644
--- a/tests/tests/graphics/res/color/fill_gradient_sweep_item.xml
+++ b/tests/tests/graphics/res/color/fill_gradient_sweep_item.xml
@@ -24,7 +24,7 @@
           android:gradientRadius="10"
           android:startColor="#ffffffff"
           android:type="sweep">
-    <item android:offset="0.1" android:color="?android:attr/colorPrimary"/>
+    <item android:offset="0.1" android:color="?attr/themeColor"/>
     <item android:offset="0.4" android:color="#fff"/>
-    <item android:offset="0.9" android:color="?android:attr/colorControlActivated"/>
+    <item android:offset="0.9" android:color="#0f0"/>
 </gradient>
diff --git a/tests/tests/graphics/res/color/fill_gradient_sweep_item_long.xml b/tests/tests/graphics/res/color/fill_gradient_sweep_item_long.xml
index 3931288..7b0bbef 100644
--- a/tests/tests/graphics/res/color/fill_gradient_sweep_item_long.xml
+++ b/tests/tests/graphics/res/color/fill_gradient_sweep_item_long.xml
@@ -22,9 +22,9 @@
           android:gradientRadius="10"
           android:type="sweep">
     <item android:offset="-0.3" android:color="#f00"/>
-    <item android:offset="0.1" android:color="?android:attr/colorPrimary"/>
+    <item android:offset="0.1" android:color="?attr/themeColor"/>
     <item android:offset="0.4" android:color="#0f0"/>
     <item android:offset="0.6" android:color="#00f"/>
-    <item android:offset="0.7" android:color="?android:attr/colorControlActivated"/>
+    <item android:offset="0.7" android:color="#0f0"/>
     <item android:offset="1.5" android:color="#00f"/>
 </gradient>
diff --git a/tests/tests/graphics/res/color/fill_gradient_sweep_item_long_mirror.xml b/tests/tests/graphics/res/color/fill_gradient_sweep_item_long_mirror.xml
new file mode 100644
index 0000000..2a73a4f
--- /dev/null
+++ b/tests/tests/graphics/res/color/fill_gradient_sweep_item_long_mirror.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:centerX="500"
+          android:centerY="500"
+          android:gradientRadius="10"
+          android:type="sweep"
+          android:tileMode="mirror">
+    <item android:offset="-0.3" android:color="#f00"/>
+    <item android:offset="0.1" android:color="?attr/themeColor"/>
+    <item android:offset="0.4" android:color="#0f0"/>
+    <item android:offset="0.6" android:color="#00f"/>
+    <item android:offset="0.7" android:color="#0f0"/>
+    <item android:offset="1.5" android:color="#00f"/>
+</gradient>
diff --git a/tests/tests/graphics/res/color/fill_gradient_sweep_item_repeat.xml b/tests/tests/graphics/res/color/fill_gradient_sweep_item_repeat.xml
new file mode 100644
index 0000000..62e6f66
--- /dev/null
+++ b/tests/tests/graphics/res/color/fill_gradient_sweep_item_repeat.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:centerColor="#ff0000"
+          android:endColor="#ff0000ff"
+          android:centerX="500"
+          android:centerY="500"
+          android:gradientRadius="10"
+          android:startColor="#ffffffff"
+          android:type="sweep"
+          android:tileMode="repeat">
+    <item android:offset="0.1" android:color="?attr/themeColor"/>
+    <item android:offset="0.4" android:color="#fff"/>
+    <item android:offset="0.9" android:color="#0f0"/>
+</gradient>
diff --git a/tests/tests/graphics/res/color/stroke_gradient_clamp.xml b/tests/tests/graphics/res/color/stroke_gradient_clamp.xml
new file mode 100644
index 0000000..3d746e7
--- /dev/null
+++ b/tests/tests/graphics/res/color/stroke_gradient_clamp.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:angle="90"
+          android:centerColor="#7f7f7f"
+          android:endColor="#ffffff"
+          android:startColor="#000000"
+          android:startX="0"
+          android:endX="50"
+          android:startY="0"
+          android:endY="0"
+          android:type="linear"
+          android:tileMode="clamp">
+</gradient>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/color/stroke_gradient_item_alpha_mirror.xml b/tests/tests/graphics/res/color/stroke_gradient_item_alpha_mirror.xml
new file mode 100644
index 0000000..352a2fd
--- /dev/null
+++ b/tests/tests/graphics/res/color/stroke_gradient_item_alpha_mirror.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:startX="0"
+          android:endX="50"
+          android:startY="0"
+          android:endY="0"
+          android:type="linear"
+          android:tileMode="mirror">
+    <item android:offset="0.1" android:color="#f00"/>
+    <item android:offset="0.2" android:color="#2f0f"/>
+    <item android:offset="0.9" android:color="#f00f"/>
+</gradient>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/color/stroke_gradient_item_repeat.xml b/tests/tests/graphics/res/color/stroke_gradient_item_repeat.xml
new file mode 100644
index 0000000..42281d1
--- /dev/null
+++ b/tests/tests/graphics/res/color/stroke_gradient_item_repeat.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:angle="90"
+          android:centerColor="#7f7f7f"
+          android:endColor="#ffffff"
+          android:startColor="#000000"
+          android:startX="0"
+          android:endX="50"
+          android:startY="0"
+          android:endY="0"
+          android:type="linear"
+          android:tileMode="repeat">
+    <item android:offset="0.1" android:color="#f00"/>
+    <item android:offset="0.2" android:color="#f0f"/>
+    <item android:offset="0.9" android:color="#f00f"/>
+</gradient>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_filltype_evenodd_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_filltype_evenodd_golden.png
new file mode 100644
index 0000000..bef75d4
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_filltype_evenodd_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_filltype_nonzero_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_filltype_nonzero_golden.png
new file mode 100644
index 0000000..85cf20b
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_filltype_nonzero_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_1_clamp_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_1_clamp_golden.png
new file mode 100644
index 0000000..a137784
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_1_clamp_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_1_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_1_golden.png
index 638802f..d5288d1 100644
--- a/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_1_golden.png
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_1_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_2_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_2_golden.png
index 1f248e3..54fbca7 100644
--- a/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_2_golden.png
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_2_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_2_repeat_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_2_repeat_golden.png
new file mode 100644
index 0000000..40432cd
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_2_repeat_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_3_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_3_golden.png
index 085e72a..09fd92f 100644
--- a/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_3_golden.png
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_3_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_3_mirror_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_3_mirror_golden.png
new file mode 100644
index 0000000..9f1b257
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_3_mirror_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable/vector_icon_filltype_evenodd.xml b/tests/tests/graphics/res/drawable/vector_icon_filltype_evenodd.xml
new file mode 100644
index 0000000..d5d86d8
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_filltype_evenodd.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<vector android:height="24dp" android:viewportHeight="400.0"
+        android:viewportWidth="1200.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillType="evenOdd"
+          android:fillColor="#f00"
+          android:pathData="M250,75L323,301 131,161 369,161 177,301z"
+          android:strokeColor="#000" android:strokeWidth="3"/>
+    <path android:fillType="evenOdd"
+          android:fillColor="#f00"
+          android:pathData="M600,81A107,107 0,0 1,600 295A107,107 0,0 1,600 81zM600,139A49,49 0,0 1,600 237A49,49 0,0 1,600 139z"
+          android:strokeColor="#000" android:strokeWidth="3"/>
+    <path android:fillType="evenOdd"
+          android:fillColor="#f00"
+          android:pathData="M950,81A107,107 0,0 1,950 295A107,107 0,0 1,950 81zM950,139A49,49 0,0 0,950 237A49,49 0,0 0,950 139z"
+          android:strokeColor="#000" android:strokeWidth="3"/>
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_filltype_nonzero.xml b/tests/tests/graphics/res/drawable/vector_icon_filltype_nonzero.xml
new file mode 100644
index 0000000..9754e4b
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_filltype_nonzero.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<vector android:height="24dp" android:viewportHeight="400.0"
+        android:viewportWidth="1200.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillType="nonZero"
+          android:fillColor="#f00"
+          android:pathData="M250,75L323,301 131,161 369,161 177,301z"
+          android:strokeColor="#000" android:strokeWidth="3"/>
+    <path android:fillType="nonZero"
+          android:fillColor="#f00"
+          android:pathData="M600,81A107,107 0,0 1,600 295A107,107 0,0 1,600 81zM600,139A49,49 0,0 1,600 237A49,49 0,0 1,600 139z"
+          android:strokeColor="#000" android:strokeWidth="3"/>
+    <path android:fillType="nonZero"
+          android:fillColor="#f00"
+          android:pathData="M950,81A107,107 0,0 1,950 295A107,107 0,0 1,950 81zM950,139A49,49 0,0 0,950 237A49,49 0,0 0,950 139z"
+          android:strokeColor="#000" android:strokeWidth="3"/>
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_gradient_1_clamp.xml b/tests/tests/graphics/res/drawable/vector_icon_gradient_1_clamp.xml
new file mode 100644
index 0000000..2fa440a
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_gradient_1_clamp.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="400"
+        android:viewportWidth="400" >
+
+<group android:name="backgroundGroup"
+       android:scaleX="0.5"
+       android:scaleY="0.5">
+    <path
+            android:name="background1"
+            android:fillColor="@color/fill_gradient_linear_clamp"
+            android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+    <path
+            android:name="background2"
+            android:fillColor="@color/fill_gradient_radial_clamp"
+            android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+    <path
+            android:name="background3"
+            android:fillColor="@color/fill_gradient_sweep_clamp"
+            android:pathData="M 400,400 l 200,0 l 0, 200 l -200, 0 z" />
+</group>
+<group
+        android:name="translateToCenterGroup"
+        android:translateX="50.0"
+        android:translateY="90.0" >
+    <path
+            android:name="twoLines"
+            android:pathData="@string/twoLinePathData"
+            android:strokeColor="@color/stroke_gradient_clamp"
+            android:strokeWidth="20" />
+
+    <group
+            android:name="rotationGroup"
+            android:pivotX="0.0"
+            android:pivotY="0.0"
+            android:rotation="-45.0">
+        <path
+                android:name="twoLines1"
+                android:pathData="@string/twoLinePathData"
+                android:strokeColor="@color/stroke_gradient_clamp"
+                android:strokeWidth="20" />
+
+        <group
+                android:name="translateGroup"
+                android:translateX="130.0"
+                android:translateY="160.0">
+            <group android:name="scaleGroup" >
+                <path
+                        android:name="twoLines3"
+                        android:pathData="@string/twoLinePathData"
+                        android:strokeColor="@color/stroke_gradient_clamp"
+                        android:strokeWidth="20" />
+            </group>
+        </group>
+
+        <group
+                android:name="translateGroupHalf"
+                android:translateX="65.0"
+                android:translateY="80.0">
+            <group android:name="scaleGroup" >
+                <path
+                        android:name="twoLines2"
+                        android:pathData="@string/twoLinePathData"
+                        android:fillColor="@color/fill_gradient_linear_clamp"
+                        android:strokeColor="@color/stroke_gradient_clamp"
+                        android:strokeWidth="20" />
+            </group>
+        </group>
+    </group>
+</group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_gradient_2_repeat.xml b/tests/tests/graphics/res/drawable/vector_icon_gradient_2_repeat.xml
new file mode 100644
index 0000000..5a43f80
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_gradient_2_repeat.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="400"
+        android:viewportWidth="400" >
+
+<group android:name="backgroundGroup"
+       android:scaleX="0.5"
+       android:scaleY="0.5">
+    <path
+            android:name="background1"
+            android:fillColor="@color/fill_gradient_linear_item_repeat"
+            android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+    <path
+            android:name="background2"
+            android:fillColor="@color/fill_gradient_radial_item_repeat"
+            android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+    <path
+            android:name="background3"
+            android:fillColor="@color/fill_gradient_sweep_item_repeat"
+            android:pathData="M 400,400 l 200,0 l 0, 200 l -200, 0 z" />
+</group>
+<group
+        android:name="translateToCenterGroup"
+        android:translateX="50.0"
+        android:translateY="90.0" >
+    <path
+            android:name="twoLines"
+            android:pathData="@string/twoLinePathData"
+            android:strokeColor="@color/stroke_gradient_item_repeat"
+            android:strokeWidth="20" />
+
+    <group
+            android:name="rotationGroup"
+            android:pivotX="0.0"
+            android:pivotY="0.0"
+            android:rotation="-45.0">
+        <path
+                android:name="twoLines1"
+                android:pathData="@string/twoLinePathData"
+                android:strokeColor="@color/stroke_gradient_item_repeat"
+                android:strokeWidth="20" />
+
+        <group
+                android:name="translateGroup"
+                android:translateX="130.0"
+                android:translateY="160.0">
+            <group android:name="scaleGroup" >
+                <path
+                        android:name="twoLines3"
+                        android:pathData="@string/twoLinePathData"
+                        android:strokeColor="@color/stroke_gradient_item_repeat"
+                        android:strokeWidth="20" />
+            </group>
+        </group>
+
+        <group
+                android:name="translateGroupHalf"
+                android:translateX="65.0"
+                android:translateY="80.0">
+            <group android:name="scaleGroup" >
+                <path
+                        android:name="twoLines2"
+                        android:pathData="@string/twoLinePathData"
+                        android:strokeColor="@color/stroke_gradient_item_repeat"
+                        android:strokeWidth="20" />
+            </group>
+        </group>
+    </group>
+</group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_gradient_3_mirror.xml b/tests/tests/graphics/res/drawable/vector_icon_gradient_3_mirror.xml
new file mode 100644
index 0000000..e8de7c2
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_gradient_3_mirror.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="400"
+        android:viewportWidth="400" >
+
+<group android:name="backgroundGroup"
+       android:scaleX="0.5"
+       android:scaleY="0.5">
+    <path
+            android:name="background1"
+            android:fillColor="@color/fill_gradient_linear_item_overlap_mirror"
+            android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+    <path
+            android:name="background2"
+            android:fillColor="@color/fill_gradient_radial_item_short_mirror"
+            android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+    <path
+            android:name="background3"
+            android:fillColor="@color/fill_gradient_sweep_item_long_mirror"
+            android:pathData="M 400,400 l 200,0 l 0, 200 l -200, 0 z" />
+</group>
+<group
+        android:name="translateToCenterGroup"
+        android:translateX="50.0"
+        android:translateY="90.0" >
+    <path
+            android:name="twoLines"
+            android:pathData="@string/twoLinePathData"
+            android:strokeColor="@color/stroke_gradient_item_alpha_mirror"
+            android:strokeWidth="20" />
+
+    <group
+            android:name="rotationGroup"
+            android:pivotX="0.0"
+            android:pivotY="0.0"
+            android:rotation="-45.0">
+        <path
+                android:name="twoLines1"
+                android:pathData="@string/twoLinePathData"
+                android:strokeColor="@color/stroke_gradient_item_alpha_mirror"
+                android:strokeWidth="20" />
+
+        <group
+                android:name="translateGroup"
+                android:translateX="130.0"
+                android:translateY="160.0">
+            <group android:name="scaleGroup" >
+                <path
+                        android:name="twoLines3"
+                        android:pathData="@string/twoLinePathData"
+                        android:strokeColor="@color/stroke_gradient_item_alpha_mirror"
+                        android:strokeWidth="20" />
+            </group>
+        </group>
+
+        <group
+                android:name="translateGroupHalf"
+                android:translateX="65.0"
+                android:translateY="80.0">
+            <group android:name="scaleGroup" >
+                <path
+                        android:name="twoLines2"
+                        android:pathData="@string/twoLinePathData"
+                        android:strokeColor="@color/stroke_gradient_item_alpha"
+                        android:strokeWidth="20" />
+            </group>
+        </group>
+    </group>
+</group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/layout/animated_vector_drawable_source.xml b/tests/tests/graphics/res/layout/animated_vector_drawable_source.xml
new file mode 100644
index 0000000..57f268f
--- /dev/null
+++ b/tests/tests/graphics/res/layout/animated_vector_drawable_source.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Demonstrates a simple layout with AnimatedVectorDrawable in an ImageView. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+
+    <ImageView
+        android:id = "@+id/avd_view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:src="@drawable/animation_vector_drawable_grouping_1"/>
+
+</LinearLayout>
diff --git a/tests/tests/graphics/src/android/graphics/cts/AvoidXfermodeTest.java b/tests/tests/graphics/src/android/graphics/cts/AvoidXfermodeTest.java
deleted file mode 100644
index beb3621..0000000
--- a/tests/tests/graphics/src/android/graphics/cts/AvoidXfermodeTest.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.graphics.cts;
-
-import android.graphics.AvoidXfermode;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Bitmap.Config;
-
-import junit.framework.TestCase;
-
-public class AvoidXfermodeTest extends TestCase {
-    /*
-     * ToBeFixed: This test ought to work with a TOLERANCE of 0. See bug 2034547.
-     */
-    private static final int TOLERANCE = 255;
-    private static final int BASE_SIZE = 50;
-    private static final int BITMAP_HEIGHT = BASE_SIZE * 2;
-    private static final int BITMAP_WIDTH = BASE_SIZE * 2;
-
-    public void testAvoidXfermode() {
-        Paint greenPaint;
-        Paint redAvoidingGreenPaint;
-        Paint blueTargetingGreenPaint;
-        greenPaint = new Paint();
-        greenPaint.setColor(Color.GREEN);
-        AvoidXfermode avoidMode =
-            new AvoidXfermode(greenPaint.getColor(), TOLERANCE, AvoidXfermode.Mode.AVOID);
-        redAvoidingGreenPaint = new Paint();
-        redAvoidingGreenPaint.setColor(Color.RED);
-        redAvoidingGreenPaint.setXfermode(avoidMode);
-        AvoidXfermode targetMode =
-            new AvoidXfermode(greenPaint.getColor(), TOLERANCE, AvoidXfermode.Mode.TARGET);
-        blueTargetingGreenPaint = new Paint();
-        blueTargetingGreenPaint.setColor(Color.BLUE);
-        blueTargetingGreenPaint.setXfermode(targetMode);
-
-        Bitmap b = Bitmap.createBitmap(BITMAP_WIDTH, BITMAP_HEIGHT, Config.ARGB_8888);
-        b.eraseColor(Color.BLACK);
-        Canvas canvas = new Canvas(b);
-        // vertical bar on the left
-        canvas.drawRect(0f, 0f, BASE_SIZE, 2 * BASE_SIZE, greenPaint);
-        // horizontal bar on top
-        canvas.drawRect(0f, 0f, 2 * BASE_SIZE, BASE_SIZE, redAvoidingGreenPaint);
-        // horizontal bar at bottom
-        canvas.drawRect(0f, BASE_SIZE, 2 * BASE_SIZE, 2 * BASE_SIZE, blueTargetingGreenPaint);
-
-        assertEquals(Color.GREEN, b.getPixel(BASE_SIZE / 2, BASE_SIZE / 2));
-        assertEquals(Color.RED, b.getPixel(BASE_SIZE + BASE_SIZE / 2, BASE_SIZE / 2));
-        assertEquals(Color.BLUE, b.getPixel(BASE_SIZE / 2, BASE_SIZE + BASE_SIZE / 2));
-        assertEquals(Color.BLACK, b.getPixel(BASE_SIZE + BASE_SIZE / 2, BASE_SIZE + BASE_SIZE / 2));
-    }
-}
diff --git a/tests/tests/graphics/src/android/graphics/cts/AvoidXfermode_ModeTest.java b/tests/tests/graphics/src/android/graphics/cts/AvoidXfermode_ModeTest.java
deleted file mode 100644
index 8704e6f..0000000
--- a/tests/tests/graphics/src/android/graphics/cts/AvoidXfermode_ModeTest.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.graphics.cts;
-
-import android.graphics.AvoidXfermode;
-import android.graphics.AvoidXfermode.Mode;
-import android.test.AndroidTestCase;
-
-public class AvoidXfermode_ModeTest extends AndroidTestCase{
-
-    public void testValueOf(){
-        assertEquals(Mode.AVOID, Mode.valueOf("AVOID"));
-        assertEquals(Mode.TARGET, Mode.valueOf("TARGET"));
-    }
-
-    public void testValues(){
-        Mode[] mode = Mode.values();
-
-        assertEquals(2, mode.length);
-        assertEquals(Mode.AVOID, mode[0]);
-        assertEquals(Mode.TARGET, mode[1]);
-
-        //Mode is used as a argument here for all the methods that use it
-        assertNotNull(new AvoidXfermode(10, 24, Mode.AVOID));
-        assertNotNull(new AvoidXfermode(10, 24, Mode.TARGET));
-    }
-}
diff --git a/tests/tests/graphics/src/android/graphics/cts/ComposeShaderTest.java b/tests/tests/graphics/src/android/graphics/cts/ComposeShaderTest.java
index 1a2164a..b44faff 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ComposeShaderTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ComposeShaderTest.java
@@ -23,8 +23,8 @@
 import android.graphics.ComposeShader;
 import android.graphics.LinearGradient;
 import android.graphics.Paint;
-import android.graphics.PixelXorXfermode;
 import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
 import android.graphics.Shader;
 import android.graphics.Xfermode;
 import android.graphics.Bitmap.Config;
@@ -71,17 +71,17 @@
     }
 
     public void testXfermode() {
-        Bitmap greenBitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
-        greenBitmap.eraseColor(Color.GREEN);
+        Bitmap redBitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
+        redBitmap.eraseColor(Color.RED);
         Bitmap cyanBitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
         cyanBitmap.eraseColor(Color.CYAN);
 
-        BitmapShader blueShader = new BitmapShader(greenBitmap, TileMode.CLAMP, TileMode.CLAMP);
-        BitmapShader redShader = new BitmapShader(cyanBitmap, TileMode.CLAMP, TileMode.CLAMP);
+        BitmapShader redShader = new BitmapShader(redBitmap, TileMode.CLAMP, TileMode.CLAMP);
+        BitmapShader cyanShader = new BitmapShader(cyanBitmap, TileMode.CLAMP, TileMode.CLAMP);
 
-        PixelXorXfermode xferMode = new PixelXorXfermode(Color.WHITE);
+        PorterDuffXfermode xferMode = new PorterDuffXfermode(PorterDuff.Mode.ADD);
 
-        ComposeShader shader = new ComposeShader(blueShader, redShader, xferMode);
+        ComposeShader shader = new ComposeShader(redShader, cyanShader, xferMode);
 
         Bitmap bitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
         Canvas canvas = new Canvas(bitmap);
@@ -89,7 +89,7 @@
         paint.setShader(shader);
         canvas.drawPaint(paint);
 
-        // white ^ green ^ cyan = yellow
-        assertEquals(Color.YELLOW, bitmap.getPixel(0, 0));
+        // green + cyan = white
+        assertEquals(Color.WHITE, bitmap.getPixel(0, 0));
     }
 }
diff --git a/tests/tests/graphics/src/android/graphics/cts/OutlineTest.java b/tests/tests/graphics/src/android/graphics/cts/OutlineTest.java
new file mode 100644
index 0000000..4b01916
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/cts/OutlineTest.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.cts;
+
+import android.graphics.Outline;
+import android.graphics.Path;
+import android.graphics.Rect;
+import android.test.suitebuilder.annotation.SmallTest;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+@SmallTest
+public class OutlineTest {
+    @Test
+    public void testDefaults() {
+        Outline outline = new Outline();
+
+        assertEquals(0.0f, outline.getAlpha(), 0.0f);
+        assertTrue(outline.isEmpty());
+        Rect outRect = new Rect();
+        assertFalse(outline.getRect(outRect));
+        assertTrue(outline.getRadius() < 0);
+    }
+
+    @Test
+    public void testGetSetAlpha() {
+        Outline outline = new Outline();
+
+        outline.setAlpha(1.0f);
+        assertEquals(1.0f, outline.getAlpha(), 0.0f);
+
+        outline.setAlpha(0.0f);
+        assertEquals(0.0f, outline.getAlpha(), 0.0f);
+
+        outline.setAlpha(0.45f);
+        assertEquals(0.45f, outline.getAlpha(), 0.0f);
+
+        // define out of range getter/setter behavior: (note will be clamped in native when consumed)
+        outline.setAlpha(4f);
+        assertEquals(4f, outline.getAlpha(), 0.0f);
+        outline.setAlpha(-30f);
+        assertEquals(-30f, outline.getAlpha(), 0.0f);
+    }
+
+    @Test
+    public void testSetRect() {
+        Outline outline = new Outline();
+        Rect outRect = new Rect();
+
+        outline.setRect(0, 0, 0, 0);
+        assertTrue(outline.isEmpty());
+
+        outline.setRect(10, 5, 4, 5);
+        assertTrue(outline.isEmpty());
+
+        outline.setRect(new Rect());
+        assertTrue(outline.isEmpty());
+
+        outline.setRect(10, 10, 20, 20);
+        assertFalse(outline.isEmpty());
+        assertTrue(outline.getRect(outRect));
+        assertEquals(new Rect(10, 10, 20, 20), outRect);
+        assertTrue(outline.canClip());
+
+        outline.setRect(new Rect(10, 10, 20, 20));
+        assertFalse(outline.isEmpty());
+        assertTrue(outline.getRect(outRect));
+        assertEquals(new Rect(10, 10, 20, 20), outRect);
+        assertTrue(outline.canClip());
+    }
+
+    @Test
+    public void testSetRoundRect() {
+        Outline outline = new Outline();
+        Rect outRect = new Rect();
+
+        outline.setRoundRect(0, 0, 0, 0, 1f);
+        assertTrue(outline.isEmpty());
+
+        outline.setRoundRect(10, 5, 4, 5, 1f);
+        assertTrue(outline.isEmpty());
+
+        outline.setRoundRect(new Rect(), 1f);
+        assertTrue(outline.isEmpty());
+
+        outline.setRoundRect(10, 10, 20, 20, 5f);
+        assertFalse(outline.isEmpty());
+        assertTrue(outline.getRect(outRect));
+        assertEquals(new Rect(10, 10, 20, 20), outRect);
+        assertEquals(5f, outline.getRadius(), 0.0f);
+        assertTrue(outline.canClip());
+
+        outline.setRoundRect(new Rect(10, 10, 20, 20), 4f);
+        assertFalse(outline.isEmpty());
+        assertTrue(outline.getRect(outRect));
+        assertEquals(new Rect(10, 10, 20, 20), outRect);
+        assertEquals(4f, outline.getRadius(), 0.0f);
+        assertTrue(outline.canClip());
+    }
+
+    @Test
+    public void testSetOval() {
+        Outline outline = new Outline();
+
+        outline.setOval(0, 0, 0, 0);
+        assertTrue(outline.isEmpty());
+
+        outline.setOval(10, 5, 4, 5);
+        assertTrue(outline.isEmpty());
+
+        Rect outRect = new Rect();
+        outline.setOval(0, 0, 50, 51); // different x & y radii, so not round rect
+        assertFalse(outline.getRect(outRect)); // not round rect, doesn't work
+        assertFalse(outline.canClip()); // not round rect, doesn't work
+        assertFalse(outline.isEmpty());
+
+        outline.setOval(0, 0, 50, 50); // same x & y radii, so round rect
+        assertTrue(outline.getRect(outRect)); // is round rect, so works
+        assertTrue(outline.canClip()); // is round rect, so works
+        assertFalse(outline.isEmpty());
+    }
+
+    @Test
+    public void testSetConvexPath() {
+        Outline outline = new Outline();
+        Path path = new Path();
+
+        assertTrue(path.isEmpty());
+        outline.setConvexPath(path);
+        assertTrue(outline.isEmpty());
+
+        path.addCircle(50, 50, 50, Path.Direction.CW);
+        outline.setConvexPath(path);
+        assertFalse(outline.isEmpty());
+    }
+
+    @Test
+    public void testGetRectRadius() {
+        Outline outline = new Outline();
+
+        Rect outRect = new Rect();
+        outline.setRoundRect(15, 10, 45, 40, 30.0f);
+        assertEquals(30.0f, outline.getRadius(), 0.0f);
+        assertTrue(outline.getRect(outRect));
+        assertEquals(new Rect(15, 10, 45, 40), outRect);
+
+        outline.setRect(5, 10, 15, 20);
+        assertEquals(0.0f, outline.getRadius(), 0.0f);
+        assertTrue(outline.getRect(outRect));
+        assertEquals(new Rect(5, 10, 15, 20), outRect);
+
+        outline.setOval(0, 0, 50, 60);
+        assertTrue(outline.getRadius() < 0);
+        assertFalse(outline.getRect(outRect));
+    }
+
+    @Test
+    public void testOffset() {
+        Outline outline = new Outline();
+
+        Rect outRect = new Rect();
+        outline.setRoundRect(15, 10, 45, 40, 30.0f);
+        outline.offset(-15, -10);
+        assertTrue(outline.getRect(outRect));
+        assertEquals(new Rect(0, 0, 30, 30), outRect);
+
+        outline.setRect(5, 10, 15, 20);
+        outline.offset(-5, -10);
+        assertTrue(outline.getRect(outRect));
+        assertEquals(new Rect(0, 0, 10, 10), outRect);
+    }
+}
diff --git a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
index c813bdb..92f31b0a 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
@@ -28,6 +28,7 @@
 import android.graphics.Path;
 import android.graphics.PathEffect;
 import android.graphics.Rasterizer;
+import android.graphics.Rect;
 import android.graphics.Shader;
 import android.graphics.Bitmap;
 import android.graphics.BitmapShader;
@@ -852,6 +853,57 @@
         assertEquals(10.0f, p.getStrokeWidth());
     }
 
+    public void testSetFontFeatureSettings() {
+        Paint p = new Paint();
+        // Roboto font (system default) has "fi" ligature
+        String text = "fi";
+        float[] widths = new float[text.length()];
+        p.getTextWidths(text, widths);
+        assertTrue(widths[0] > 0.0f);
+        assertEquals(0.0f, widths[1]);
+
+        // Disable ligature using OpenType feature
+        p.setFontFeatureSettings("'liga' off");
+        p.getTextWidths(text, widths);
+        assertTrue(widths[0] > 0.0f);
+        assertTrue(widths[1] > 0.0f);
+
+        // Re-enable ligature
+        p.setFontFeatureSettings("'liga' on");
+        p.getTextWidths(text, widths);
+        assertTrue(widths[0] > 0.0f);
+        assertEquals(0.0f, widths[1]);
+    }
+
+    public void testGetTextBounds() {
+        Paint p = new Paint();
+        p.setTextSize(10);
+        String text1 = "hello";
+        Rect bounds1 = new Rect();
+        Rect bounds2 = new Rect();
+        p.getTextBounds(text1, 0, text1.length(), bounds1);
+        char[] textChars1 = text1.toCharArray();
+        p.getTextBounds(textChars1, 0, textChars1.length, bounds2);
+        // verify that string and char array methods produce consistent results
+        assertEquals(bounds1, bounds2);
+        String text2 = "hello world";
+
+        // verify substring produces consistent results
+        p.getTextBounds(text2, 0, text1.length(), bounds2);
+        assertEquals(bounds1, bounds2);
+
+        // longer string is expected to have same left edge but be wider
+        p.getTextBounds(text2, 0, text2.length(), bounds2);
+        assertEquals(bounds1.left, bounds2.left);
+        assertTrue(bounds2.right > bounds1.right);
+
+        // bigger size implies bigger bounding rect
+        p.setTextSize(20);
+        p.getTextBounds(text1, 0, text1.length(), bounds2);
+        assertTrue(bounds2.right > bounds1.right);
+        assertTrue(bounds2.bottom - bounds2.top > bounds1.bottom - bounds1.top);
+    }
+
     public void testReset() {
         Paint p  = new Paint();
         ColorFilter c = new ColorFilter();
diff --git a/tests/tests/graphics/src/android/graphics/cts/PixelXorXfermodeTest.java b/tests/tests/graphics/src/android/graphics/cts/PixelXorXfermodeTest.java
deleted file mode 100644
index e2d68da..0000000
--- a/tests/tests/graphics/src/android/graphics/cts/PixelXorXfermodeTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics.cts;
-
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.PixelXorXfermode;
-import android.graphics.Bitmap.Config;
-import android.test.AndroidTestCase;
-
-public class PixelXorXfermodeTest extends AndroidTestCase {
-
-    public void testPixelXorXfermode() {
-        int width = 100;
-        int height = 100;
-        Bitmap b1 = Bitmap.createBitmap(width / 2, height, Config.ARGB_8888);
-        b1.eraseColor(Color.WHITE);
-        Bitmap b2 = Bitmap.createBitmap(width, height / 2, Config.ARGB_8888);
-        b2.eraseColor(Color.CYAN);
-
-        Bitmap target = Bitmap.createBitmap(width, height, Config.ARGB_8888);
-        target.eraseColor(Color.BLACK);
-        Canvas canvas = new Canvas(target);
-        Paint p = new Paint();
-        canvas.drawBitmap(b1, 0, 0, p);
-        p.setXfermode(new PixelXorXfermode(Color.GREEN));
-        canvas.drawBitmap(b2, 0, height / 2, p);
-        assertEquals(Color.WHITE, target.getPixel(width / 4, height / 4));
-        // white ^ green ^ cyan = yellow
-        assertEquals(Color.YELLOW, target.getPixel(width / 4, height * 3 / 4));
-        // black ^ green ^ cyan = blue
-        assertEquals(Color.BLUE, target.getPixel(width * 3 / 4, height * 3 / 4));
-
-        // XOR transfer always results in an opaque image
-        p.setXfermode(new PixelXorXfermode(alphaColor(Color.GREEN, 25)));
-        target.eraseColor(alphaColor(Color.BLACK, 42));
-        p.setColor(alphaColor(Color.CYAN, 5));
-        canvas.drawPaint(p);
-        // result is always opaque, even though all inputs have alpha
-        assertEquals(255, Color.alpha(target.getPixel(0, 0)));
-    }
-
-    private int alphaColor(int color, int alpha) {
-        int red = Color.red(color);
-        int green = Color.green(color);
-        int blue = Color.blue(color);
-        return Color.argb(alpha, red, green, blue);
-    }
-}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
index 8081ebb..92f3125 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
@@ -23,6 +23,7 @@
 import android.graphics.PixelFormat;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
+import android.graphics.cts.R;
 import android.graphics.drawable.Animatable2;
 import android.graphics.drawable.AnimatedVectorDrawable;
 import android.graphics.drawable.Drawable;
@@ -33,8 +34,7 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Xml;
-
-import android.graphics.cts.R;
+import android.widget.ImageView;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -43,6 +43,8 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 
+import static java.lang.Thread.sleep;
+
 public class AnimatedVectorDrawableTest extends ActivityInstrumentationTestCase2<DrawableStubActivity> {
     private static final String LOGTAG = AnimatedVectorDrawableTest.class.getSimpleName();
 
@@ -55,7 +57,10 @@
     private Bitmap mBitmap;
     private Canvas mCanvas;
     private static final boolean DBG_DUMP_PNG = false;
-    private int mResId = R.drawable.animation_vector_drawable_grouping_1;
+    private final int mResId = R.drawable.animation_vector_drawable_grouping_1;
+    private final int mLayoutId = R.layout.animated_vector_drawable_source;
+    private final int mImageViewId = R.id.avd_view;
+
 
     public AnimatedVectorDrawableTest() {
         super(DrawableStubActivity.class);
@@ -250,36 +255,81 @@
     }
 
     @MediumTest
-    public void testAddCallback()  {
-        MyCallback callback = new MyCallback();
-        final AnimatedVectorDrawable d1 = (AnimatedVectorDrawable) mResources.getDrawable(mResId);
-
-        d1.registerAnimationCallback(callback);
+    public void testAddCallbackBeforeStart() throws InterruptedException {
+        final MyCallback callback = new MyCallback();
         // The AVD has a duration as 100ms.
         mActivity.runOnUiThread(new Runnable() {
             @Override
             public void run() {
+                mActivity.setContentView(mLayoutId);
+                ImageView imageView = (ImageView) mActivity.findViewById(mImageViewId);
+                AnimatedVectorDrawable d1 = (AnimatedVectorDrawable) imageView.getDrawable();
+                d1.registerAnimationCallback(callback);
                 d1.start();
             }
         });
-
         getInstrumentation().waitForIdleSync();
-
+        sleep(200);
         assertTrue(callback.mStart);
         assertTrue(callback.mEnd);
     }
 
     @MediumTest
-    public void testRemoveCallback() {
-        MyCallback callback = new MyCallback();
-        final AnimatedVectorDrawable d1 = (AnimatedVectorDrawable) mResources.getDrawable(mResId);
-
-        d1.registerAnimationCallback(callback);
-        assertTrue(d1.unregisterAnimationCallback(callback));
+    public void testAddCallbackAfterTrigger() throws InterruptedException {
+        final MyCallback callback = new MyCallback();
         // The AVD has a duration as 100ms.
         mActivity.runOnUiThread(new Runnable() {
             @Override
             public void run() {
+                mActivity.setContentView(mLayoutId);
+                ImageView imageView = (ImageView) mActivity.findViewById(mImageViewId);
+                AnimatedVectorDrawable d1 = (AnimatedVectorDrawable) imageView.getDrawable();
+                // This reset call can enforce the AnimatorSet is setup properly in AVD, when
+                // running on UI thread.
+                d1.reset();
+                d1.registerAnimationCallback(callback);
+                d1.start();
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+        sleep(200);
+        assertTrue(callback.mStart);
+        assertTrue(callback.mEnd);
+    }
+
+    @MediumTest
+    public void testAddCallbackAfterStart() throws InterruptedException {
+        final MyCallback callback = new MyCallback();
+        // The AVD has a duration as 100ms.
+        mActivity.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mActivity.setContentView(mLayoutId);
+                ImageView imageView = (ImageView) mActivity.findViewById(mImageViewId);
+                AnimatedVectorDrawable d1 = (AnimatedVectorDrawable) imageView.getDrawable();
+                d1.start();
+                d1.registerAnimationCallback(callback);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+        sleep(200);
+        // Whether or not the callback.start is true could vary when running on Render Thread.
+        // Therefore, we don't make assertion here. The most useful flag is the callback.mEnd.
+        assertTrue(callback.mEnd);
+    }
+
+    @MediumTest
+    public void testRemoveCallback() {
+        final MyCallback callback = new MyCallback();
+        // The AVD has a duration as 100ms.
+        mActivity.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mActivity.setContentView(mLayoutId);
+                ImageView imageView = (ImageView) mActivity.findViewById(mImageViewId);
+                AnimatedVectorDrawable d1 = (AnimatedVectorDrawable) imageView.getDrawable();
+                d1.registerAnimationCallback(callback);
+                assertTrue(d1.unregisterAnimationCallback(callback));
                 d1.start();
             }
         });
@@ -291,15 +341,17 @@
 
     @MediumTest
     public void testClearCallback() {
-        MyCallback callback = new MyCallback();
-        final AnimatedVectorDrawable d1 = (AnimatedVectorDrawable) mResources.getDrawable(mResId);
+        final MyCallback callback = new MyCallback();
 
-        d1.registerAnimationCallback(callback);
-        d1.clearAnimationCallbacks();
         // The AVD has a duration as 100ms.
         mActivity.runOnUiThread(new Runnable() {
             @Override
             public void run() {
+                mActivity.setContentView(mLayoutId);
+                ImageView imageView = (ImageView) mActivity.findViewById(mImageViewId);
+                AnimatedVectorDrawable d1 = (AnimatedVectorDrawable) imageView.getDrawable();
+                d1.registerAnimationCallback(callback);
+                d1.clearAnimationCallbacks();
                 d1.start();
             }
         });
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerTest.java
index e2c0e0a..e78b04c 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerTest.java
@@ -78,7 +78,7 @@
     }
 
     private void helpTestSetEnterFadeDuration(int enterFadeDuration) {
-        DrawableContainer container = new MockDrawableContainer();
+        DrawableContainer container = new LevelListDrawable();
         DrawableContainerState cs = ((DrawableContainerState) container.getConstantState());
         container.setEnterFadeDuration(enterFadeDuration);
         assertEquals(enterFadeDuration, cs.getEnterFadeDuration());
@@ -90,7 +90,7 @@
     }
 
     private void helpTestSetExitFadeDuration(int exitFadeDuration) {
-        DrawableContainer container = new MockDrawableContainer();
+        DrawableContainer container = new LevelListDrawable();
         DrawableContainerState cs = ((DrawableContainerState) container.getConstantState());
         container.setExitFadeDuration(exitFadeDuration);
         assertEquals(exitFadeDuration, cs.getExitFadeDuration());
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java
index f174f01..a39c18f 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java
@@ -46,7 +46,10 @@
 public class VectorDrawableTest extends AndroidTestCase {
     private static final String LOGTAG = "VectorDrawableTest";
 
-    private static final int[] ICON_RES_IDS = new int[] {
+    // Separate the test assets into different groups such that we could isolate the issue faster.
+    // Some new APIs or bug fixes only exist in particular os version, such that we name the tests
+    // and associated assets with OS code name L, M, N etc...
+    private static final int[] BASIC_ICON_RES_IDS = new int[]{
             R.drawable.vector_icon_create,
             R.drawable.vector_icon_delete,
             R.drawable.vector_icon_heart,
@@ -59,6 +62,24 @@
             R.drawable.vector_icon_repeated_a_1,
             R.drawable.vector_icon_repeated_a_2,
             R.drawable.vector_icon_clip_path_1,
+    };
+
+    private static final int[] BASIC_GOLDEN_IMAGES = new int[] {
+            R.drawable.vector_icon_create_golden,
+            R.drawable.vector_icon_delete_golden,
+            R.drawable.vector_icon_heart_golden,
+            R.drawable.vector_icon_schedule_golden,
+            R.drawable.vector_icon_settings_golden,
+            R.drawable.vector_icon_random_path_1_golden,
+            R.drawable.vector_icon_random_path_2_golden,
+            R.drawable.vector_icon_repeated_cq_golden,
+            R.drawable.vector_icon_repeated_st_golden,
+            R.drawable.vector_icon_repeated_a_1_golden,
+            R.drawable.vector_icon_repeated_a_2_golden,
+            R.drawable.vector_icon_clip_path_1_golden,
+    };
+
+    private static final int[] L_M_ICON_RES_IDS = new int[] {
             R.drawable.vector_icon_transformation_1,
             R.drawable.vector_icon_transformation_2,
             R.drawable.vector_icon_transformation_3,
@@ -72,23 +93,9 @@
             R.drawable.vector_icon_stroke_3,
             R.drawable.vector_icon_scale_1,
             R.drawable.vector_icon_scale_2,
-            R.drawable.vector_icon_implicit_lineto,
-            R.drawable.vector_icon_arcto,
     };
 
-    private static final int[] GOLDEN_IMAGES = new int[] {
-            R.drawable.vector_icon_create_golden,
-            R.drawable.vector_icon_delete_golden,
-            R.drawable.vector_icon_heart_golden,
-            R.drawable.vector_icon_schedule_golden,
-            R.drawable.vector_icon_settings_golden,
-            R.drawable.vector_icon_random_path_1_golden,
-            R.drawable.vector_icon_random_path_2_golden,
-            R.drawable.vector_icon_repeated_cq_golden,
-            R.drawable.vector_icon_repeated_st_golden,
-            R.drawable.vector_icon_repeated_a_1_golden,
-            R.drawable.vector_icon_repeated_a_2_golden,
-            R.drawable.vector_icon_clip_path_1_golden,
+    private static final int[] L_M_GOLDEN_IMAGES = new int[] {
             R.drawable.vector_icon_transformation_1_golden,
             R.drawable.vector_icon_transformation_2_golden,
             R.drawable.vector_icon_transformation_3_golden,
@@ -102,20 +109,38 @@
             R.drawable.vector_icon_stroke_3_golden,
             R.drawable.vector_icon_scale_1_golden,
             R.drawable.vector_icon_scale_2_golden,
+    };
+
+    private static final int[] N_ICON_RES_IDS = new int[] {
+            R.drawable.vector_icon_implicit_lineto,
+            R.drawable.vector_icon_arcto,
+            R.drawable.vector_icon_filltype_nonzero,
+            R.drawable.vector_icon_filltype_evenodd,
+    };
+
+    private static final int[] N_GOLDEN_IMAGES = new int[] {
             R.drawable.vector_icon_implicit_lineto_golden,
             R.drawable.vector_icon_arcto_golden,
+            R.drawable.vector_icon_filltype_nonzero_golden,
+            R.drawable.vector_icon_filltype_evenodd_golden,
     };
 
     private static final int[] GRADIENT_ICON_RES_IDS = new int[] {
             R.drawable.vector_icon_gradient_1,
             R.drawable.vector_icon_gradient_2,
             R.drawable.vector_icon_gradient_3,
+            R.drawable.vector_icon_gradient_1_clamp,
+            R.drawable.vector_icon_gradient_2_repeat,
+            R.drawable.vector_icon_gradient_3_mirror,
     };
 
     private static final int[] GRADIENT_GOLDEN_IMAGES = new int[] {
             R.drawable.vector_icon_gradient_1_golden,
             R.drawable.vector_icon_gradient_2_golden,
             R.drawable.vector_icon_gradient_3_golden,
+            R.drawable.vector_icon_gradient_1_clamp_golden,
+            R.drawable.vector_icon_gradient_2_repeat_golden,
+            R.drawable.vector_icon_gradient_3_mirror_golden,
     };
 
     private static final int[] STATEFUL_RES_IDS = new int[] {
@@ -163,8 +188,18 @@
     }
 
     @MediumTest
-    public void testSimpleVectorDrawables() throws XmlPullParserException, IOException {
-        verifyVectorDrawables(ICON_RES_IDS, GOLDEN_IMAGES, null);
+    public void testBasicVectorDrawables() throws XmlPullParserException, IOException {
+        verifyVectorDrawables(BASIC_ICON_RES_IDS, BASIC_GOLDEN_IMAGES, null);
+    }
+
+    @MediumTest
+    public void testLMVectorDrawables() throws XmlPullParserException, IOException {
+        verifyVectorDrawables(L_M_ICON_RES_IDS, L_M_GOLDEN_IMAGES, null);
+    }
+
+    @MediumTest
+    public void testNVectorDrawables() throws XmlPullParserException, IOException {
+        verifyVectorDrawables(N_ICON_RES_IDS, N_GOLDEN_IMAGES, null);
     }
 
     @MediumTest
@@ -197,7 +232,9 @@
                 throw new XmlPullParserException("No start tag found");
             }
 
-            mVectorDrawable.inflate(mResources, parser, attrs, mContext.getTheme());
+            Theme theme = mResources.newTheme();
+            theme.applyStyle(R.style.Theme_ThemedDrawableTest, true);
+            mVectorDrawable.inflate(mResources, parser, attrs, theme);
 
             if (stateSet != null) {
                 mVectorDrawable.setState(stateSet);
diff --git a/tests/tests/hardware/Android.mk b/tests/tests/hardware/Android.mk
index 45aef43..a59c5f4 100644
--- a/tests/tests/hardware/Android.mk
+++ b/tests/tests/hardware/Android.mk
@@ -24,7 +24,8 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil compatibility-device-util
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    ctsdeviceutil compatibility-device-util platform-test-annotations
 
 LOCAL_SDK_VERSION := current
 
@@ -52,7 +53,13 @@
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil compatibility-device-util ctstestrunner mockito-target android-ex-camera2
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    ctsdeviceutil \
+    compatibility-device-util \
+    ctstestrunner \
+    mockito-target \
+    android-ex-camera2 \
+    platform-test-annotations
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/tests/hardware/AndroidTest.xml b/tests/tests/hardware/AndroidTest.xml
index 14027dd..68131d1 100644
--- a/tests/tests/hardware/AndroidTest.xml
+++ b/tests/tests/hardware/AndroidTest.xml
@@ -26,6 +26,7 @@
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.hardware.cts" />
+        <option name="runtime-hint" value="47m28s" />
     </test>
 
 </configuration>
diff --git a/tests/tests/hardware/src/android/hardware/cts/GeomagneticFieldTest.java b/tests/tests/hardware/src/android/hardware/cts/GeomagneticFieldTest.java
index dc927b6..75d7b7c 100644
--- a/tests/tests/hardware/src/android/hardware/cts/GeomagneticFieldTest.java
+++ b/tests/tests/hardware/src/android/hardware/cts/GeomagneticFieldTest.java
@@ -16,8 +16,8 @@
 
 package android.hardware.cts;
 
-
 import android.hardware.GeomagneticField;
+import android.platform.test.annotations.Presubmit;
 import android.test.AndroidTestCase;
 
 import java.util.GregorianCalendar;
@@ -29,6 +29,7 @@
     private static final float ALTITUDE_OF_CHENGDU = 500f;
     private static final long TEST_TIME = new GregorianCalendar(2010, 5, 1).getTimeInMillis();
 
+    @Presubmit
     public void testGeomagneticField() {
         GeomagneticField geomagneticField = new GeomagneticField(LATITUDE_OF_CHENGDU,
                 LONGITUDE_OF_CHENGDU, ALTITUDE_OF_CHENGDU, TEST_TIME);
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorBatchingFifoTest.java b/tests/tests/hardware/src/android/hardware/cts/SensorBatchingFifoTest.java
index 2443004..1db2d51 100644
--- a/tests/tests/hardware/src/android/hardware/cts/SensorBatchingFifoTest.java
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorBatchingFifoTest.java
@@ -24,6 +24,7 @@
 import android.hardware.cts.helpers.TestSensorEnvironment;
 import android.hardware.cts.helpers.sensoroperations.TestSensorOperation;
 import android.hardware.cts.helpers.sensorverification.FifoLengthVerification;
+import android.platform.test.annotations.Presubmit;
 
 import java.util.concurrent.TimeUnit;
 
@@ -46,6 +47,7 @@
                 PackageManager.FEATURE_HIFI_SENSORS);
     }
 
+    @Presubmit
     public void testAccelerometerFifoLength() throws Throwable {
         if (!mHasHifiSensors) return;
         runBatchingSensorFifoTest(
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java b/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java
index 302ce72..bcd1734 100644
--- a/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java
@@ -90,6 +90,7 @@
                     context,
                     sensorType,
                     shouldEmulateSensorUnderLoad(),
+                    true, /* isIntegrationTest */
                     sensor.getMinDelay(),
                     MAX_REPORTING_LATENCY_US);
             TestSensorOperation batchingOperation =
@@ -143,6 +144,7 @@
                             context,
                             sensorType,
                             shouldEmulateSensorUnderLoad(),
+                            true, /* isIntegrationTest */
                             generateSamplingRateInUs(sensorType),
                             generateReportLatencyInUs());
                     TestSensorOperation sensorOperation =
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorTest.java b/tests/tests/hardware/src/android/hardware/cts/SensorTest.java
index 2bbf053..95a76b8 100644
--- a/tests/tests/hardware/src/android/hardware/cts/SensorTest.java
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorTest.java
@@ -44,6 +44,7 @@
 import android.os.HandlerThread;
 import android.os.PowerManager;
 import android.os.SystemClock;
+import android.platform.test.annotations.Presubmit;
 import android.util.Log;
 
 import java.util.ArrayList;
@@ -200,6 +201,7 @@
 
     // Some sensors like proximity, significant motion etc. are defined as wake-up sensors by
     // default. Check if the wake-up flag is set correctly.
+    @Presubmit
     public void testWakeUpFlags() {
         final int TYPE_WAKE_GESTURE = 23;
         final int TYPE_GLANCE_GESTURE = 24;
@@ -241,6 +243,7 @@
         }
     }
 
+    @Presubmit
     public void testSensorStringTypes() {
         for (Sensor sensor : mSensorList) {
             if (sensor.getType() < MAX_OFFICIAL_ANDROID_SENSOR_TYPE &&
@@ -314,10 +317,14 @@
     // TODO: remove when parameterized tests are supported (see SensorBatchingTests.java)
     @TimeoutReq(minutes=20)
     public void testBatchAndFlush() throws Exception {
+        // TODO - replace this constant once method to do so is made available
+        final int SENSOR_TYPE_DEVICE_PRIVATE_BASE = 0x10000;
         SensorCtsHelper.sleep(3, TimeUnit.SECONDS);
         ArrayList<Throwable> errorsFound = new ArrayList<>();
         for (Sensor sensor : mSensorList) {
-            verifyRegisterListenerCallFlush(sensor, null /* handler */, errorsFound);
+            if (sensor.getType() < SENSOR_TYPE_DEVICE_PRIVATE_BASE) {
+                verifyRegisterListenerCallFlush(sensor, null /* handler */, errorsFound);
+            }
         }
         assertOnErrors(errorsFound);
     }
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEnvironment.java b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEnvironment.java
index 47c8313..6ef7938 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEnvironment.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEnvironment.java
@@ -23,6 +23,8 @@
 
 import java.util.concurrent.TimeUnit;
 
+/* TODO: Refactor constructors into a builder */
+
 /**
  * A class that encapsulates base environment information for the {@link SensorOperation}.
  * The environment is self contained and carries its state around all the sensor test framework.
@@ -41,6 +43,7 @@
     private final int mSamplingPeriodUs;
     private final int mMaxReportLatencyUs;
     private final boolean mIsDeviceSuspendTest;
+    private final boolean mIsIntegrationTest;
 
     /**
      * Constructs an environment for sensor testing.
@@ -131,6 +134,34 @@
      * Constructs an environment for sensor testing.
      *
      * @param context The context for the test
+     * @param sensorType The type of the sensor under test
+     * @param sensorMightHaveMoreListeners Whether the sensor under test is acting under load
+     * @param isIntegrationTest Whether this is an integration test (more than one sensor actived)
+     * @param samplingPeriodUs The requested collection period for the sensor under test
+     * @param maxReportLatencyUs The requested collection report latency for the sensor under test
+     *
+     * @deprecated Use variants with {@link Sensor} objects.
+     */
+    @Deprecated
+    public TestSensorEnvironment(
+            Context context,
+            int sensorType,
+            boolean sensorMightHaveMoreListeners,
+            boolean isIntegrationTest,
+            int samplingPeriodUs,
+            int maxReportLatencyUs) {
+        this(context,
+                getSensor(context, sensorType),
+                sensorMightHaveMoreListeners,
+                isIntegrationTest,
+                samplingPeriodUs,
+                maxReportLatencyUs);
+    }
+
+    /**
+     * Constructs an environment for sensor testing.
+     *
+     * @param context The context for the test
      * @param sensor The sensor under test
      * @param samplingPeriodUs The requested collection period for the sensor under test
      * @param maxReportLatencyUs The requested collection report latency for the sensor under test
@@ -176,15 +207,46 @@
             Context context,
             Sensor sensor,
             boolean sensorMightHaveMoreListeners,
+            boolean isIntegrationTest,
+            int samplingPeriodUs,
+            int maxReportLatencyUs) {
+        this(context,
+                sensor,
+                sensorMightHaveMoreListeners,
+                samplingPeriodUs,
+                maxReportLatencyUs,
+                false /* isDeviceSuspendTest */,
+                isIntegrationTest);
+    }
+
+    public TestSensorEnvironment(
+            Context context,
+            Sensor sensor,
+            boolean sensorMightHaveMoreListeners,
             int samplingPeriodUs,
             int maxReportLatencyUs,
             boolean isDeviceSuspendTest) {
+        this(context, sensor, sensorMightHaveMoreListeners,
+                samplingPeriodUs, maxReportLatencyUs,
+                false /* isDeviceSuspendTest */,
+                false /* isIntegrationTest */);
+    }
+
+    public TestSensorEnvironment(
+            Context context,
+            Sensor sensor,
+            boolean sensorMightHaveMoreListeners,
+            int samplingPeriodUs,
+            int maxReportLatencyUs,
+            boolean isDeviceSuspendTest,
+            boolean isIntegrationTest) {
         mContext = context;
         mSensor = sensor;
         mSensorMightHaveMoreListeners = sensorMightHaveMoreListeners;
         mSamplingPeriodUs = samplingPeriodUs;
         mMaxReportLatencyUs = maxReportLatencyUs;
         mIsDeviceSuspendTest = isDeviceSuspendTest;
+        mIsIntegrationTest = isIntegrationTest;
     }
 
     /**
@@ -265,6 +327,7 @@
     }
 
     /**
+     * Calculate the maximum expected sampling period in us.
      * @return The maximum acceptable actual sampling period of this sensor.
      *         For continuous sensors, this is higher than {@link #getExpectedSamplingPeriodUs()}
      *         because sensors are allowed to run up to 10% slower than requested.
@@ -282,6 +345,20 @@
         return (int) (expectedSamplingPeriodUs / MAXIMUM_EXPECTED_SAMPLING_FREQUENCY_MULTIPLIER);
     }
 
+
+    /**
+     * Calculate the allowed sensor start delay.
+     *
+     * CDD Section 7.3:
+     * MUST report the first sensor sample within 400 milliseconds + 2 * sample_time of the
+     * sensor being activated. It is acceptable for this sample to have an accuracy of 0.
+     *
+     * [CDD] Keep this updated with CDD.
+     */
+    public long getAllowedSensorStartDelay() {
+        return TimeUnit.MILLISECONDS.toMicros(400) + 2 * getMaximumExpectedSamplingPeriodUs();
+    }
+
     /**
      * @return The number of axes in the coordinate system of the sensor under test.
      */
@@ -378,5 +455,9 @@
     public boolean isDeviceSuspendTest() {
         return mIsDeviceSuspendTest;
     }
+
+    public boolean isIntegrationTest() {
+        return mIsIntegrationTest;
+    }
 }
 
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEventListener.java b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEventListener.java
index dbe7c15..2da6a3b 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEventListener.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEventListener.java
@@ -194,7 +194,8 @@
      * It will overwrite the file if it already exists, the file is created in a relative directory
      * named 'events' under the sensor test directory (part of external storage).
      */
-    public void logCollectedEventsToFile(String fileName, long deviceWakeUpTimeMs)
+    public void logCollectedEventsToFile(String fileName, long deviceWakeUpTimeMs,
+            long testStartTimeMs, long testStopTimeMs)
         throws IOException {
         StringBuilder builder = new StringBuilder();
         builder.append("Sensor='").append(mEnvironment.getSensor()).append("', ");
@@ -203,7 +204,11 @@
         builder.append("RequestedSamplingPeriod=")
                 .append(mEnvironment.getRequestedSamplingPeriodUs()).append("us, ");
         builder.append("MaxReportLatency=")
-                .append(mEnvironment.getMaxReportLatencyUs()).append("us");
+                .append(mEnvironment.getMaxReportLatencyUs()).append("us, ");
+        builder.append("StartedTimestamp=")
+                .append(testStartTimeMs).append("ms, ");
+        builder.append("StoppedTimestamp=")
+                .append(testStopTimeMs).append("ms");
         synchronized (mCollectedEvents) {
             int i = 0, j = 0;
             while (i < mCollectedEvents.size() && j < mTimeStampFlushCompleteEvents.size()) {
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorOperation.java
index 779bb49..5ef2d3c 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorOperation.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorOperation.java
@@ -66,6 +66,8 @@
     private final Executor mExecutor;
     private final Handler mHandler;
     private long mDeviceWakeUpTimeMs = -1;
+    private long mStartTimeMs = -1;
+    private long mStopTimeMs = -1;
 
     /**
      * An interface that defines an abstraction for operations to be performed by the
@@ -124,20 +126,21 @@
         getStats().addValue("sensor_name", mEnvironment.getSensor().getName());
         TestSensorEventListener listener = new TestSensorEventListener(mEnvironment, mHandler);
 
+        mStartTimeMs = SystemClock.elapsedRealtime();
         if (mEnvironment.isDeviceSuspendTest()) {
             SuspendStateMonitor suspendStateMonitor = new SuspendStateMonitor();
-            long startTimeMs = SystemClock.elapsedRealtime();
             // Device should go into suspend here.
             mExecutor.execute(mSensorManager, listener);
-            long endTimeMs = SystemClock.elapsedRealtime();
+            mStopTimeMs = SystemClock.elapsedRealtime();
             // Check if the device has gone into suspend during test execution.
             mDeviceWakeUpTimeMs = suspendStateMonitor.getLastWakeUpTime();
             suspendStateMonitor.cancel();
             Assert.assertTrue("Device did not go into suspend during test execution",
-                                       startTimeMs < mDeviceWakeUpTimeMs &&
-                                       mDeviceWakeUpTimeMs < endTimeMs);
+                                       mStartTimeMs < mDeviceWakeUpTimeMs &&
+                                       mDeviceWakeUpTimeMs < mStopTimeMs);
         } else {
             mExecutor.execute(mSensorManager, listener);
+            mStopTimeMs = SystemClock.elapsedRealtime();
         }
 
         boolean failed = false;
@@ -147,8 +150,8 @@
             failed |= evaluateResults(collectedEvents, verification, sb);
         }
 
+        trySaveCollectedEvents(parent, listener);
         if (failed) {
-            trySaveCollectedEvents(parent, listener);
             String msg = SensorCtsHelper
                     .formatAssertionMessage("VerifySensorOperation", mEnvironment, sb.toString());
             getStats().addValue(SensorStats.ERROR, msg);
@@ -213,7 +216,8 @@
         }
 
         try {
-            listener.logCollectedEventsToFile(sanitizedFileName, mDeviceWakeUpTimeMs);
+            listener.logCollectedEventsToFile(sanitizedFileName, mDeviceWakeUpTimeMs,
+                    mStartTimeMs, mStopTimeMs);
         } catch (IOException e) {
             Log.w(TAG, "Unable to save collected events to file: " + sanitizedFileName, e);
         }
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventBasicVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventBasicVerification.java
index 1e82b78..670c065 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventBasicVerification.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventBasicVerification.java
@@ -18,6 +18,7 @@
 
 import junit.framework.Assert;
 
+import android.os.Build;
 import android.hardware.Sensor;
 import android.hardware.SensorEvent;
 import android.hardware.cts.helpers.SensorStats;
@@ -28,15 +29,23 @@
 import java.util.concurrent.TimeUnit;
 
 /**
- * A {@link ISensorVerification} which verifies if the collected sensor events have any obvious 
+ * A {@link ISensorVerification} which verifies if the collected sensor events have any obvious
  * problems, such as no sample, wrong sensor type, etc.
  */
 public class EventBasicVerification extends AbstractSensorVerification {
 
     public static final String PASSED_KEY = "event_basic_passed";
-    private static final long ALLOWED_SENSOR_DELIVERING_DELAY_US =
+    // allowed time from registration to sensor start sampling
+    private static final long ALLOWED_SENSOR_START_DELAY_US =
             TimeUnit.MILLISECONDS.toMicros(1000);
 
+    // allowed time for entire sensor system to send sample to test app
+    private static final long ALLOWED_SENSOR_EVENT_LATENCY_US =
+            TimeUnit.MILLISECONDS.toMicros(1000);
+
+    // mercy added for recently added test. remove this mercy factor for next letter release.
+    private final float NUM_EVENT_MERCY_FACTOR; // 0~1, 0 means most strict
+
     private final long mExpectedMinNumEvent;
     private final Object mSensor;
     private long  mNumEvent;
@@ -56,6 +65,12 @@
 
         mNumEvent = 0;
         mWrongSensorObserved = false;
+
+        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
+            NUM_EVENT_MERCY_FACTOR = 0;
+        } else {
+            NUM_EVENT_MERCY_FACTOR = 0.3f;
+        }
     }
 
     /**
@@ -69,25 +84,79 @@
             TestSensorEnvironment environment,
             long testDurationUs) {
 
-        long minTestDurationUs;
-        long batchUs = environment.getMaxReportLatencyUs();
+        // The calculation is still OK if sampleUs is not the actual sensor hardware
+        // sample period since the actual sample period by definition only goes smaller, which
+        // result in more samples.
         long sampleUs = environment.getExpectedSamplingPeriodUs();
-        if (batchUs > 0) {
-            // test duration deduct allowed delivering latency and portion of time to deliver batch
-            // (which will be 10% of the batching time)
-            long effectiveTime = testDurationUs - ALLOWED_SENSOR_DELIVERING_DELAY_US - batchUs/10;
 
-            // allow part of last batch to be partially delivered (>80%)
-            minTestDurationUs = Math.max(
-                    effectiveTime/batchUs * batchUs - batchUs/5,
-                    environment.getExpectedSamplingPeriodUs());
+        long askedBatchUs = environment.getMaxReportLatencyUs();
+
+        long reservedFifoUs = sampleUs * environment.getSensor().getFifoReservedEventCount(); //>=0
+
+        // max() prevent loop-hole if HAL specify smaller max fifo than reserved fifo.
+        long maximumFifoUs = Math.max(
+                sampleUs * environment.getSensor().getFifoMaxEventCount(), reservedFifoUs); //>=0
+
+        long effectiveDurationUs = Math.max(testDurationUs -
+                Math.max(ALLOWED_SENSOR_START_DELAY_US, environment.getAllowedSensorStartDelay()) -
+                ALLOWED_SENSOR_EVENT_LATENCY_US, 0);
+
+        boolean isSingleSensorTest = !environment.isIntegrationTest();
+
+        long expectedMinUs;
+        if (isSingleSensorTest) {
+            // When the sensor under test is the only one active, max fifo size is assumed to be
+            // available.
+            long expectedBatchUs = Math.min(maximumFifoUs, askedBatchUs);
+            if (expectedBatchUs > 0) {
+                // This sensor should be running in batching mode.
+                expectedMinUs =
+                        effectiveDurationUs / expectedBatchUs * expectedBatchUs
+                        - expectedBatchUs / 5;
+            } else {
+                // streaming, allow actual rate to be as slow as 80% of the asked rate.
+                expectedMinUs = effectiveDurationUs * 4 / 5;
+            }
         } else {
-            minTestDurationUs =
-                    Math.max(testDurationUs - ALLOWED_SENSOR_DELIVERING_DELAY_US,
-                             environment.getExpectedSamplingPeriodUs());
-        }
+            // More convoluted case. Batch size can vary from reserved fifo length to max fifo size.
+            long minBatchUs = Math.min(reservedFifoUs, askedBatchUs);
+            long maxBatchUs = Math.min(maximumFifoUs, askedBatchUs);
 
-        long expectedMinNumEvent = minTestDurationUs / environment.getExpectedSamplingPeriodUs();
+            // The worst scenario happens when the sensor batch time being just above half of the
+            // test time, then the test can only receive one batch which halves the expected number
+            // of samples. The expected number of samples received have a lower bound like the
+            // figure below.
+            //
+            // expected samples
+            //  ^
+            //  |                          ______
+            //  |\                        /
+            //  |  \                    /
+            //  |    \                /
+            //  |      \            /
+            //  |        \        /
+            //  |          \    /
+            //  |            \/
+            //  |
+            //  |
+            //  |
+            //  |
+            //  +------------+-----------+------->  actual batch size in time
+            //  0   1/2*testDuration   testDuration
+            //
+            long worstBatchUs = effectiveDurationUs / 2 + 1;
+            if ((minBatchUs > worstBatchUs) ==  (maxBatchUs > worstBatchUs)) {
+                // same side
+                double ratio = Math.min(Math.abs(worstBatchUs - minBatchUs),
+                        Math.abs(worstBatchUs - maxBatchUs)) / (double)worstBatchUs;
+                expectedMinUs = (long)((ratio + 1) / 2 * testDurationUs) * 4 / 5;
+            } else {
+                // the worst case is possible
+                expectedMinUs = worstBatchUs * 4 / 5;
+            }
+        }
+        long expectedMinNumEvent = expectedMinUs/sampleUs;
+
         return new EventBasicVerification(expectedMinNumEvent, environment.getSensor());
     }
 
@@ -103,7 +172,7 @@
         stats.addValue(SensorStats.EVENT_COUNT_EXPECTED_KEY, mExpectedMinNumEvent);
         stats.addValue(SensorStats.WRONG_SENSOR_KEY, mWrongSensorObserved);
 
-        boolean enoughSample = mNumEvent >= mExpectedMinNumEvent;
+        boolean enoughSample = mNumEvent >= mExpectedMinNumEvent * ( 1 - NUM_EVENT_MERCY_FACTOR );
         boolean noWrongSensor = !mWrongSensorObserved;
 
         boolean success = enoughSample && noWrongSensor;
@@ -111,7 +180,8 @@
 
         if (!success) {
             Assert.fail(String.format("Failed due to (%s%s)",
-                        enoughSample?"":"insufficient events, ",
+                        enoughSample?"":"insufficient events " + mNumEvent + "/" +
+                                mExpectedMinNumEvent + ", ",
                         noWrongSensor?"":"wrong sensor observed, "));
         }
     }
diff --git a/tests/tests/hardware/src/android/hardware/fingerprint/cts/FingerprintManagerTest.java b/tests/tests/hardware/src/android/hardware/fingerprint/cts/FingerprintManagerTest.java
index 95704b9..f11b6bc 100644
--- a/tests/tests/hardware/src/android/hardware/fingerprint/cts/FingerprintManagerTest.java
+++ b/tests/tests/hardware/src/android/hardware/fingerprint/cts/FingerprintManagerTest.java
@@ -21,6 +21,7 @@
 import android.hardware.fingerprint.FingerprintManager;
 import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
 import android.os.CancellationSignal;
+import android.platform.test.annotations.Presubmit;
 import android.test.AndroidTestCase;
 
 /**
@@ -65,6 +66,7 @@
         }
     }
 
+    @Presubmit
     public void test_hasFingerprintHardware() {
         if (!mHasFingerprintManager) {
             return; // skip test if no fingerprint feature
diff --git a/tests/tests/icu/AndroidTest.xml b/tests/tests/icu/AndroidTest.xml
index 299956d..18c95cd 100644
--- a/tests/tests/icu/AndroidTest.xml
+++ b/tests/tests/icu/AndroidTest.xml
@@ -20,5 +20,6 @@
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="runner" value="android.icu.cts.IcuTestRunner" /><!-- override AJUR -->
         <option name="package" value="android.icu.cts" />
+        <option name="runtime-hint" value="30m19s" />
     </test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/tests/tests/icu/resources/android/icu/cts/expectations/icu-known-failures.txt b/tests/tests/icu/resources/android/icu/cts/expectations/icu-known-failures.txt
index e667c08..9ca52c5 100644
--- a/tests/tests/icu/resources/android/icu/cts/expectations/icu-known-failures.txt
+++ b/tests/tests/icu/resources/android/icu/cts/expectations/icu-known-failures.txt
@@ -16,9 +16,9 @@
   bug: "27310873"
 },
 {
-  description: "Cannot find any classes to test because APK doesn't have entries for directories, android/icu/",
+  description: "Cannot find any classes to test because .class files are not treated as resources in APK",
   name: "android.icu.dev.test.serializable.CoverageTest",
-  bug: "27310873"
+  bug: "27666677"
 },
 {
   description: "Serialized forms have not been converted to use repackaged classes",
@@ -34,42 +34,28 @@
   description: "A completely empty test case",
   name: "android.icu.dev.test.duration.PeriodBuilderTest"
 },
-// The following are known to be broken but the reason is not yet known. They are expected to
-// succeed and so will be run and will fail but that is intentional so that they do not get
-// forgotten and are investigated to determine whether it is correct behavior on Android or a bug
-// that needs fixing.
 {
-  description: "Broken and not yet triaged",
-  names: [
-    "android.icu.dev.test.bidi.TestCompatibility#testCompatibility",
-    "android.icu.dev.test.calendar.ChineseTest#TestCoverage",
-    "android.icu.dev.test.calendar.ChineseTest#TestInitWithCurrentTime",
-    "android.icu.dev.test.calendar.IBMCalendarTest#TestAddRollEra0AndEraBounds",
-    "android.icu.dev.test.duration.ICUDurationTest#TestBasics",
-    "android.icu.dev.test.format.DataDrivenFormatTest#TestConsistentPivot",
-    "android.icu.dev.test.format.DataDrivenFormatTest#TestDateFormatBasic",
-    "android.icu.dev.test.format.DateFormatRegressionTest#Test4073003",
-    "android.icu.dev.test.format.DateFormatRegressionTest#Test4151706",
-    "android.icu.dev.test.format.DateFormatRegressionTest#Test4182066",
-    "android.icu.dev.test.format.DateFormatTest#TestBadInput135",
-    "android.icu.dev.test.format.DateFormatTest#TestDotAndAtLeniency",
-    "android.icu.dev.test.format.DateFormatTest#TestGenericTime",
-    "android.icu.dev.test.format.DateFormatTest#TestPartialParse994",
-    "android.icu.dev.test.format.DateFormatTest#TestQuarters",
-    "android.icu.dev.test.format.DateFormatTest#TestSpaceParsing",
-    "android.icu.dev.test.format.DateFormatTest#TestTwoDigitYear",
-    "android.icu.dev.test.format.DateFormatTest#TestWhiteSpaceParsing",
-    "android.icu.dev.test.format.NumberFormatTest#TestDataDrivenJDK",
-    "android.icu.dev.test.format.NumberFormatTest#TestNonpositiveMultiplier",
-    "android.icu.dev.test.format.PluralRulesTest#testOverUnderflow",
-    "android.icu.dev.test.timezone.TimeZoneBoundaryTest#TestStepwise",
-    "android.icu.dev.test.timezone.TimeZoneTest#TestObservesDaylightTime",
-    "android.icu.dev.test.util.CurrencyTest#TestGetKeywordValues"
-  ],
-  result: "SUCCESS"
+  description: "Fails on host and on device in same way before and after packaging",
+  name: "android.icu.dev.test.bidi.TestCompatibility#testCompatibility",
+  bug: "23995372"
 },
 {
-  description: "Broken due to warnings, not yet triaged",
+  description: "Problem with negative multiplier, not a regression",
+  name: "android.icu.dev.test.format.NumberFormatTest#TestNonpositiveMultiplier",
+  bug: "19185440"
+},
+{
+  description: "Wrong case for exponent separator",
+  name: "android.icu.dev.test.format.PluralRulesTest#testOverUnderflow",
+  bug: "27566754"
+},
+{
+  description: "Checks differences in DecimalFormat classes from ICU4J and JDK but on Android java.text.DecimalFormat is implemented in terms of ICU4J",
+  name: "android.icu.dev.test.format.NumberFormatTest#TestDataDrivenJDK",
+  bug: "27711713"
+},
+{
+  description: "Collation rules data has been removed from ICU4J data on Android",
   names: [
     "android.icu.dev.test.collator.CollationCreationMethodTest#TestRuleVsLocaleCreationMonkey",
     "android.icu.dev.test.collator.CollationMiscTest#TestImport",
@@ -78,6 +64,6 @@
     "android.icu.dev.test.collator.CollationTest#TestDataDriven",
     "android.icu.dev.test.collator.G7CollationTest#TestG7Data"
   ],
-  result: "SUCCESS"
+  bug: "27552651"
 }
 ]
diff --git a/tests/tests/icu/src/android/icu/cts/IcuRunListener.java b/tests/tests/icu/src/android/icu/cts/IcuRunListener.java
index 5e1e003..0a6f355 100644
--- a/tests/tests/icu/src/android/icu/cts/IcuRunListener.java
+++ b/tests/tests/icu/src/android/icu/cts/IcuRunListener.java
@@ -17,12 +17,12 @@
 package android.icu.cts;
 
 import android.app.Instrumentation;
-import android.icu.cts.junit.ICUTestFailedException;
-import android.icu.cts.junit.IcuRunnerParams;
 import android.os.Bundle;
+import android.support.test.internal.util.AndroidRunnerParams;
 import android.util.Log;
 import java.util.ArrayList;
 import java.util.List;
+import junit.framework.AssertionFailedError;
 import org.junit.runner.Description;
 import org.junit.runner.Result;
 import org.junit.runner.notification.Failure;
@@ -54,7 +54,7 @@
      */
     private final Instrumentation instrumentation;
 
-    private final IcuRunnerParams icuRunnerParams;
+    private final AndroidRunnerParams runnerParams;
 
     private final int totalTestCount;
 
@@ -77,10 +77,10 @@
 
     private long testStartTime;
 
-    public IcuRunListener(Instrumentation instrumentation, IcuRunnerParams icuRunnerParams,
+    public IcuRunListener(Instrumentation instrumentation, AndroidRunnerParams runnerParams,
             int totalTestCount) {
         this.instrumentation = instrumentation;
-        this.icuRunnerParams = icuRunnerParams;
+        this.runnerParams = runnerParams;
         this.totalTestCount = totalTestCount;
         failedTests = new ArrayList<>();
     }
@@ -130,28 +130,15 @@
 
         @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
         Throwable exception = failure.getException();
-        if (exception instanceof ICUTestFailedException) {
-            ICUTestFailedException icuTestFailedException =
-                    (ICUTestFailedException) exception;
-
-            String information = icuTestFailedException.getInformation();
-            int errorCount = icuTestFailedException.getErrorCount();
-
-            // Include the detailed logs from ICU as the stack trace.
-            currentTestResult.putString(REPORT_KEY_STACK, information);
-
-            // Also append the logs to the console output.
-            String output = "Failure: " + description + ", due to " + errorCount + " error(s)\n"
-                    + information;
-            currentTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, output);
+        if (exception instanceof AssertionFailedError) {
             resultStatus = REPORT_VALUE_RESULT_FAILURE;
         } else {
-            String information = failure.getTrace();
-            currentTestResult.putString(REPORT_KEY_STACK, information);
-            String output = "Error: " + description + "\n" + information;
-            currentTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, output);
             resultStatus = REPORT_VALUE_RESULT_ERROR;
         }
+        String information = failure.getTrace();
+        currentTestResult.putString(REPORT_KEY_STACK, information);
+        String output = "Error: " + description + "\n" + information;
+        currentTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, output);
     }
 
     @Override
@@ -178,7 +165,7 @@
 
     public Bundle getFinalResults() {
         int totalTests = totalFailures + totalSuccess;
-        Log.d(IcuTestRunner.TAG, (icuRunnerParams.getSkipExecution() ? "Skipped " : "Ran ")
+        Log.d(IcuTestRunner.TAG, (runnerParams.isSkipExecution() ? "Skipped " : "Ran ")
                 + totalTests + " tests, " + totalSuccess + " passed, " + totalFailures + " failed");
         Bundle results = new Bundle();
         results.putString(REPORT_KEY_IDENTIFIER, REPORT_VALUE_ID);
diff --git a/tests/tests/icu/src/android/icu/cts/IcuTestFilter.java b/tests/tests/icu/src/android/icu/cts/IcuTestFilter.java
index 2ee1fcd..3da2976 100644
--- a/tests/tests/icu/src/android/icu/cts/IcuTestFilter.java
+++ b/tests/tests/icu/src/android/icu/cts/IcuTestFilter.java
@@ -15,12 +15,13 @@
  */
 package android.icu.cts;
 
-import android.icu.cts.junit.IcuTestFmwkRunner;
-import android.icu.cts.junit.IcuTestGroupRunner;
 import android.util.Log;
+import java.util.List;
 import javax.annotation.Nullable;
 import org.junit.runner.Description;
 import org.junit.runner.manipulation.Filter;
+import org.junit.runners.ParentRunner;
+import org.junit.runners.Suite;
 import vogar.Expectation;
 import vogar.ExpectationStore;
 import vogar.Result;
@@ -28,36 +29,36 @@
 /**
  * Filter out tests/classes that are not requested or which are expected to fail.
  *
- * <p>This filter has to handle a hierarchy of {@code Description descriptions} that looks
- * something like this (in CTSv2):
+ * <p>This filter has to handle both a hierarchy of {@code Description descriptions} that looks
+ * something like this:
  * <pre>
- * IcuTestGroupRunner
- *     IcuTestGroupRunner
- *         IcuTestGroupRunner
- *             IcuTestFmwkRunner
- *                 IcuFrameworkTest
+ * Suite
+ *     Suite
+ *         Suite
+ *             ParentRunner
+ *                 Test
  *                 ...
  *             ...
- *         IcuTestFmwkRunner
- *             IcuFrameworkTest
+ *         ParentRunner
+ *             Test
  *             ...
  *         ...
- *     IcuTestGroupRunner
- *         IcuTestFmwkRunner
- *             IcuFrameworkTest
+ *     Suite
+ *         ParentRunner
+ *             Test
  *             ...
  *         ...
  *     ...
  * </pre>
  *
  * <p>And also a flatter hierarchy that looks like this (in CTSv1):
- * IcuTestFmwkRunner
- *     IcuFrameworkTest
- *     ...
+ * Runner
+ * Test
+ * ...
  * ...
  *
- * <p>It cannot filter out the non-leaf nodes in the hierarchy, i.e. {@link IcuTestGroupRunner} and
- * {@link IcuTestFmwkRunner}, as that would prevent it from traversing the hierarchy and finding
+ * <p>It cannot filter out the non-leaf nodes in the hierarchy, i.e. {@link Suite} and
+ * {@link ParentRunner}, as that would prevent it from traversing the hierarchy and finding
  * the leaf nodes.
  */
 class IcuTestFilter extends Filter {
@@ -73,12 +74,13 @@
 
     @Override
     public boolean shouldRun(Description description) {
-        // The description will only have a method name if it is a leaf node in the hierarchy, see
-        // class JavaDoc, otherwise it will be a non-leaf node. Non-leaf nodes must not be filtered
-        // out as that would prevent leaf nodes from being visited.
-        String methodName = description.getMethodName();
-        if (methodName != null) {
-            String className = description.getClassName();
+        // Only filter leaf nodes. The description is for a test if and only if it is a leaf node.
+        // Non-leaf nodes must not be filtered out as that would prevent leaf nodes from being
+        // visited in the case when we are traversing the hierarchy of classes.
+        Description testDescription = getTestDescription(description);
+        if (testDescription != null) {
+            String className = testDescription.getClassName();
+            String methodName = testDescription.getMethodName();
             String testName = className + "#" + methodName;
 
             // If the test isn't in the list of tests to run then do not run it.
@@ -99,6 +101,29 @@
         return true;
     }
 
+    private Description getTestDescription(Description description) {
+        List<Description> children = description.getChildren();
+        // An empty description is by definition a test.
+        if (children.isEmpty()) {
+            return description;
+        }
+
+        // Handle initialization errors that were wrapped in an ErrorReportingRunner as a special
+        // case. This is needed because ErrorReportingRunner is treated as a suite of Throwables,
+        // (where each Throwable corresponds to a test called initializationError) and so its
+        // description contains children, one for each Throwable, and so is not treated as a test
+        // to filter. Unfortunately, it does not support Filterable so this filter is never applied
+        // to its children.
+        // See https://github.com/junit-team/junit/issues/1253
+        Description child = children.get(0);
+        String methodName = child.getMethodName();
+        if ("initializationError".equals(methodName)) {
+            return child;
+        }
+
+        return null;
+    }
+
     @Override
     public String describe() {
         return "IcuTestFilter";
diff --git a/tests/tests/icu/src/android/icu/cts/IcuTestList.java b/tests/tests/icu/src/android/icu/cts/IcuTestList.java
index c06b571..a9c3c5f 100644
--- a/tests/tests/icu/src/android/icu/cts/IcuTestList.java
+++ b/tests/tests/icu/src/android/icu/cts/IcuTestList.java
@@ -15,7 +15,6 @@
  */
 package android.icu.cts;
 
-import android.icu.cts.junit.TestFmwkUtils;
 import android.util.Log;
 import java.util.ArrayList;
 import java.util.LinkedHashSet;
@@ -34,49 +33,59 @@
     @Nullable
     private final Set<String> testsToRun;
 
-    private final List<Class> classesToRun;
+    private final List<Class<?>> classesToRun;
 
-    /**
-     * @param testNameList
-     *         The list of test names (i.e. {@code <class>#<method>}). If null then all
-     *         tests should be run.
-     */
-    public IcuTestList(@Nullable List<String> testNameList) {
+    public static IcuTestList exclusiveList(List<String> testNameList) {
+        Set<String> classNamesToRun = new LinkedHashSet<>();
+        Set<String> testsToRun = new LinkedHashSet<>(testNameList);
 
-        // Populate a set with the unique class names of all the tests.
-        Set<String> classNamesToRun;
-        if (testNameList == null) {
-            // Run from the root test class.
-            classNamesToRun = TestFmwkUtils.getRootClassNames();
-            Log.d(IcuTestRunner.TAG, "Running all tests rooted at " + classNamesToRun);
-            testsToRun = null;
-        } else {
-            classNamesToRun = new LinkedHashSet<>();
-            testsToRun = new LinkedHashSet<>(testNameList);
-
-            for (String testName : testNameList) {
-                int index = testName.indexOf('#');
-                String className;
-                if (index == -1) {
-                    className = testName;
-                } else {
-                    className = testName.substring(0, index);
-                }
-                classNamesToRun.add(className);
+        for (String testName : testNameList) {
+            int index = testName.indexOf('#');
+            String className;
+            if (index == -1) {
+                className = testName;
+            } else {
+                className = testName.substring(0, index);
             }
-
-            Log.d(IcuTestRunner.TAG, "Running only the following tests: " + testsToRun);
+            classNamesToRun.add(className);
         }
 
+        Log.d(IcuTestRunner.TAG, "Running only the following tests: " + testsToRun);
+        return new IcuTestList(getClasses(classNamesToRun), testsToRun);
+    }
+
+    public static IcuTestList rootList(List<String> rootList) {
+
+        // Run from the root test class.
+        Set<String> classNamesToRun = new LinkedHashSet<>(rootList);
+        Log.d(IcuTestRunner.TAG, "Running all tests rooted at " + classNamesToRun);
+
+        List<Class<?>> classesToRun1 = getClasses(classNamesToRun);
+
+        return new IcuTestList(classesToRun1, null);
+    }
+
+    private static List<Class<?>> getClasses(Set<String> classNames) {
         // Populate the list of classes to run.
-        classesToRun = new ArrayList<>();
-        for (String className : classNamesToRun) {
+        List<Class<?>> classesToRun = new ArrayList<>();
+        for (String className : classNames) {
             try {
                 classesToRun.add(Class.forName(className));
             } catch (ClassNotFoundException e) {
                 throw new IllegalStateException("Could not load class '" + className, e);
             }
         }
+        return classesToRun;
+    }
+
+    /**
+     * @param classes The list of classes to run.
+     * @param testsToRun The exclusive set of tests to run or null if all tests reachable from the
+     * classes are to be run.
+     */
+    private IcuTestList(List<Class<?>> classes, Set<String> testsToRun) {
+        this.testsToRun = testsToRun;
+        this.classesToRun = classes;
     }
 
     /**
diff --git a/tests/tests/icu/src/android/icu/cts/IcuTestRunner.java b/tests/tests/icu/src/android/icu/cts/IcuTestRunner.java
index 48a4cc1..51c4999 100644
--- a/tests/tests/icu/src/android/icu/cts/IcuTestRunner.java
+++ b/tests/tests/icu/src/android/icu/cts/IcuTestRunner.java
@@ -18,10 +18,10 @@
 
 import android.app.Activity;
 import android.app.Instrumentation;
-import android.icu.cts.junit.IcuRunnerParams;
-import android.icu.cts.junit.IcuTestRunnerBuilder;
+import android.icu.junit.IcuTestRunnerBuilder;
 import android.os.Bundle;
 import android.os.Debug;
+import android.support.test.internal.util.AndroidRunnerParams;
 import android.util.Log;
 import java.io.BufferedReader;
 import java.io.FileReader;
@@ -62,6 +62,9 @@
     private static final List<String> EXPECTATIONS_PATHS =
             Collections.singletonList("expectations/icu-known-failures.txt");
 
+    /** The args for the runner. */
+    private Bundle args;
+
     /** Only count the number of tests, and not run them. */
     private boolean testCountOnly;
 
@@ -82,8 +85,9 @@
     @Override
     public void onCreate(Bundle args) {
         super.onCreate(args);
+        this.args = args;
 
-        boolean debug = args.getBoolean(ARGUMENT_DEBUG);
+        boolean debug = "true".equalsIgnoreCase(args.getString(ARGUMENT_DEBUG));
         if (debug) {
             Log.i(TAG, "Waiting for debugger to connect...");
             Debug.waitForDebugger();
@@ -126,28 +130,34 @@
             testNameList = null;
         }
 
-        icuTestList = new IcuTestList(testNameList);
+        if (testNameList == null) {
+            icuTestList = IcuTestList.rootList(Arrays.asList(
+                    "android.icu.cts.coverage.TestAll",
+                    "android.icu.dev.test.TestAll"));
+        } else {
+            icuTestList = IcuTestList.exclusiveList(testNameList);
+        }
 
         start();
     }
 
     @Override
     public void onStart() {
-
         if (logOnly || testCountOnly) {
             Log.d(TAG, "Counting/logging tests only");
         } else {
             Log.d(TAG, "Running tests");
         }
 
-        IcuRunnerParams icuRunnerParams = new IcuRunnerParams(logOnly || testCountOnly);
+        AndroidRunnerParams runnerParams = new AndroidRunnerParams(this, args,
+                logOnly || testCountOnly, -1, false);
 
         JUnitCore core = new JUnitCore();
 
         Request request;
         int totalTestCount;
         try {
-            RunnerBuilder runnerBuilder = new IcuTestRunnerBuilder(icuRunnerParams);
+            RunnerBuilder runnerBuilder = new IcuTestRunnerBuilder(runnerParams);
             Class[] classes = icuTestList.getClassesToRun();
             Runner suite = new Computer().getSuite(runnerBuilder, classes);
 
@@ -173,7 +183,7 @@
             throw new RuntimeException("Could not create a suite", e);
         }
 
-        IcuRunListener icuRunListener = new IcuRunListener(this, icuRunnerParams, totalTestCount);
+        IcuRunListener icuRunListener = new IcuRunListener(this, runnerParams, totalTestCount);
         core.addListener(icuRunListener);
         core.run(request);
 
diff --git a/tests/tests/icu/src/android/icu/cts/junit/ErrorReportingRunner.java b/tests/tests/icu/src/android/icu/cts/junit/ErrorReportingRunner.java
deleted file mode 100644
index bbd0651..0000000
--- a/tests/tests/icu/src/android/icu/cts/junit/ErrorReportingRunner.java
+++ /dev/null
@@ -1,122 +0,0 @@
-package android.icu.cts.junit;
-
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.junit.runner.Description;
-import org.junit.runner.Runner;
-import org.junit.runner.manipulation.Filter;
-import org.junit.runner.manipulation.Filterable;
-import org.junit.runner.manipulation.NoTestsRemainException;
-import org.junit.runner.notification.Failure;
-import org.junit.runner.notification.RunNotifier;
-import org.junit.runners.model.InitializationError;
-
-/**
- * A copy of the JUnit 4.10 {@link org.junit.internal.runners.ErrorReportingRunner} class.
- *
- * <p>Modified as follows:</p>
- *
- * <ul>
- * <li>allows the class in error to be specified by name rather than {@link Class} object so that it
- * can be used for when the class could not be found. See
- * {@link #ErrorReportingRunner(String, Throwable)} and
- * {@link #fTestClassName}.
- * <li>supports filtering of the individual causes. See {@link #filter(Filter)}.
- * <li>uses the cause to construct the description allowing filtering on specific error messages.
- * See {@link #describeCause(Throwable)}.
- * </ul>
- */
-// android-changed - implements Filterable
-class ErrorReportingRunner extends Runner implements Filterable {
-    private final List<Throwable> fCauses;
-
-    // android-changed - changed type from Class<?> and renamed from fTestClass.
-    private final String fTestClassName;
-
-    public ErrorReportingRunner(String testClassName, Throwable cause) {
-        fTestClassName = testClassName;
-        // Take a copy so that they can be modified during filtering if necessary.
-        fCauses = new ArrayList<>(getCauses(cause));
-    }
-    // end android-changed
-
-    @Override
-    public Description getDescription() {
-        // android-changed - renamed from fTestClass.
-        Description description= Description.createSuiteDescription(fTestClassName);
-        // end android-changed
-        for (Throwable each : fCauses)
-            description.addChild(describeCause(each));
-        return description;
-    }
-
-    @Override
-    public void run(RunNotifier notifier) {
-        for (Throwable each : fCauses)
-            runCause(each, notifier);
-    }
-
-    // android-changed - added filtering support
-    @Override
-    public void filter(Filter filter) throws NoTestsRemainException {
-        Iterator<Throwable> iterator = fCauses.iterator();
-        while (iterator.hasNext()) {
-            Throwable cause = iterator.next();
-            Description description = describeCause(cause);
-            if (!filter.shouldRun(description)) {
-                iterator.remove();
-            }
-        }
-
-        // If there are no causes left then throw an exception to cause the parent runner, if any,
-        // to remove this runner from its list.
-        if (fCauses.isEmpty()) {
-            throw new NoTestsRemainException();
-        }
-    }
-    // end android-changed
-
-    @SuppressWarnings("deprecation")
-    private List<Throwable> getCauses(Throwable cause) {
-        if (cause instanceof InvocationTargetException)
-            return getCauses(cause.getCause());
-        if (cause instanceof InitializationError)
-            return ((InitializationError) cause).getCauses();
-        if (cause instanceof org.junit.internal.runners.InitializationError)
-            return ((org.junit.internal.runners.InitializationError) cause)
-                    .getCauses();
-        return Arrays.asList(cause);
-    }
-
-    private Description describeCause(Throwable child) {
-        // android-changed - create a description that incorporates the cause
-        // Extract the first line of the message, exclude any special characters that could
-        // cause problems with later parsing of the description.
-        String message = child.getMessage();
-        Matcher matcher = Pattern.compile("^([^()\n]*).*").matcher(message);
-        if (matcher.matches()) {
-            message = matcher.group(1);
-        }
-
-        // Create a suite description (need to use that method because the createTestDescription
-        // methods use a class rather than a class name).
-        String causeClassName = child.getClass().getName();
-        return Description.createSuiteDescription(
-                String.format("initializationError[%s: %s](%s)",
-                        causeClassName, message, fTestClassName));
-        // end android-changed
-    }
-
-    private void runCause(Throwable child, RunNotifier notifier) {
-        Description description= describeCause(child);
-        notifier.fireTestStarted(description);
-        notifier.fireTestFailure(new Failure(description, child));
-        notifier.fireTestFinished(description);
-    }
-}
\ No newline at end of file
diff --git a/tests/tests/icu/src/android/icu/cts/junit/ICUTestFailedException.java b/tests/tests/icu/src/android/icu/cts/junit/ICUTestFailedException.java
deleted file mode 100644
index 0e9f045..0000000
--- a/tests/tests/icu/src/android/icu/cts/junit/ICUTestFailedException.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.icu.cts.junit;
-
-/**
- * An exception used to tunnel extra failure information from a failing test to
- * {@link android.icu.cts.IcuRunListener}
- */
-public class ICUTestFailedException extends Exception {
-
-    /**
-     * The number of errors found within the test.
-     *
-     * <p>The ICU test framework differs from JUnit as an individual test can continue after an
-     * error is encountered, this field keeps track of the number of errors encountered.
-     */
-    private final int errorCount;
-
-    /**
-     * The output from the test itself.
-     */
-    private final String information;
-
-    public ICUTestFailedException(String message, int errorCount, String information) {
-        super(message);
-        this.errorCount = errorCount;
-        this.information = information;
-    }
-
-    public int getErrorCount() {
-        return errorCount;
-    }
-
-    public String getInformation() {
-        return information;
-    }
-}
diff --git a/tests/tests/icu/src/android/icu/cts/junit/IcuFrameworkTest.java b/tests/tests/icu/src/android/icu/cts/junit/IcuFrameworkTest.java
deleted file mode 100644
index 7e85497..0000000
--- a/tests/tests/icu/src/android/icu/cts/junit/IcuFrameworkTest.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.icu.cts.junit;
-
-import android.icu.dev.test.TestFmwk;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import org.junit.runner.Description;
-
-/**
- * Represents a test within a {@link TestFmwk} class.
- */
-final class IcuFrameworkTest implements Comparable<IcuFrameworkTest> {
-
-    private static final String[] EMPTY_ARGS = new String[0];
-
-    private static final Pattern EXTRACT_ERROR_INFO = Pattern.compile(
-            "^[A-Za-z0-9_]+ \\{(\n.*)\n\\}.*", Pattern.DOTALL);
-
-    /**
-     * The {@link TestFmwk} instance on which the tests will be run.
-     */
-    private final TestFmwk testFmwk;
-
-    private final TestFmwk.Target target;
-
-    /**
-     * The name of the individual target to run.
-     */
-    private final String methodName;
-
-    IcuFrameworkTest(TestFmwk testFmwk, TestFmwk.Target target, String methodName) {
-        this.testFmwk = testFmwk;
-        this.target = target;
-        this.methodName = methodName;
-    }
-
-    public String getMethodName() {
-        return methodName;
-    }
-
-    /**
-     * Runs the target.
-     */
-    public void run() throws ICUTestFailedException {
-        test_for_TestFmwk_Run();
-    }
-
-    /**
-     * A special method to avoid the TestFmwk from throwing an InternalError when an error occurs
-     * during execution of the test but outside the actual test method, e.g. in a
-     * {@link TestFmwk#validate()} method. See http://bugs.icu-project.org/trac/ticket/12183
-     *
-     * <p>DO NOT CHANGE THE NAME
-     */
-    private void test_for_TestFmwk_Run() throws ICUTestFailedException {
-        StringWriter stringWriter = new StringWriter();
-        PrintWriter log = new PrintWriter(stringWriter);
-
-        TestFmwk.TestParams localParams = TestFmwk.TestParams.create(EMPTY_ARGS, log);
-        if (localParams == null) {
-            throw new IllegalStateException("Could not create params");
-        }
-
-        // We don't want an error summary as we are only running one test.
-        localParams.errorSummary = null;
-
-        try {
-            // Make sure that the TestFmwk is initialized with the correct parameters. This method
-            // is being called solely for its side effect of updating the TestFmwk.params field.
-            testFmwk.resolveTarget(localParams);
-
-            // Run the target.
-            target.run();
-        } catch (Exception e) {
-            // Output the exception to the log and make sure it is treated as an error.
-            e.printStackTrace(log);
-            localParams.errorCount++;
-        }
-
-        // Treat warnings as errors.
-        int errorCount = localParams.errorCount + localParams.warnCount;
-
-        // Ensure that all data is written to the StringWriter.
-        log.flush();
-
-        // Treat warnings as errors.
-        String information = stringWriter.toString();
-        if (errorCount != 0) {
-            // Remove unnecessary formatting.
-            Matcher matcher = EXTRACT_ERROR_INFO.matcher(information);
-            if (matcher.matches()) {
-                information = matcher.group(1)/*.replace("\n    ", "\n")*/;
-            }
-            throw new ICUTestFailedException("ICU test failed: " + getDescription(),
-                    errorCount, information);
-        }
-    }
-
-    /**
-     * Get the JUnit {@link Description}
-     */
-    public Description getDescription() {
-        // Get a description for the specific method within the class.
-        return Description.createTestDescription(testFmwk.getClass(), methodName);
-    }
-
-    @Override
-    public int compareTo(IcuFrameworkTest o) {
-        return methodName.compareTo(o.methodName);
-    }
-}
diff --git a/tests/tests/icu/src/android/icu/cts/junit/IcuRunnerParams.java b/tests/tests/icu/src/android/icu/cts/junit/IcuRunnerParams.java
deleted file mode 100644
index 369b672..0000000
--- a/tests/tests/icu/src/android/icu/cts/junit/IcuRunnerParams.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.icu.cts.junit;
-
-/**
- * Encapsulates options passed to {@link IcuTestFmwkRunner}.
- */
-public class IcuRunnerParams {
-
-    /**
-     * True if the tests should not actually be executed, false otherwise.
-     */
-    private final boolean skipExecution;
-
-    public static IcuRunnerParams getDefaultParams() {
-        return new IcuRunnerParams(false);
-    }
-
-    public IcuRunnerParams(boolean skipExecution) {
-        this.skipExecution = skipExecution;
-    }
-
-    public boolean getSkipExecution() {
-        return skipExecution;
-    }
-}
diff --git a/tests/tests/icu/src/android/icu/cts/junit/IcuTestFmwkRunner.java b/tests/tests/icu/src/android/icu/cts/junit/IcuTestFmwkRunner.java
deleted file mode 100644
index a290ae6..0000000
--- a/tests/tests/icu/src/android/icu/cts/junit/IcuTestFmwkRunner.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.icu.cts.junit;
-
-import android.icu.dev.test.TestFmwk;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import org.junit.runner.Description;
-import org.junit.runner.notification.RunNotifier;
-import org.junit.runners.model.Statement;
-
-/**
- * A {@link org.junit.runner.Runner} that can be used to run a class that is a {@link TestFmwk}
- * but not a {@link android.icu.dev.test.TestFmwk.TestGroup}
- */
-public class IcuTestFmwkRunner extends IcuTestParentRunner<IcuFrameworkTest> {
-
-    /**
-     * A {@link Statement} that does nothing, used when skipping execution.
-     */
-    private static final Statement EMPTY_STATEMENT = new Statement() {
-        @Override
-        public void evaluate() throws Throwable {
-        }
-    };
-
-    private final IcuRunnerParams icuRunnerParams;
-
-    private final List<IcuFrameworkTest> tests;
-
-    /**
-     * The constructor used when this class is used with {@code @RunWith(...)}.
-     */
-    public IcuTestFmwkRunner(Class<?> testClass)
-            throws Exception {
-        this(checkClass(testClass), IcuRunnerParams.getDefaultParams());
-    }
-
-    /**
-     * Make sure that the supplied test class is supported by this.
-     */
-    private static Class<? extends TestFmwk> checkClass(Class<?> testClass) {
-        if (!TestFmwk.class.isAssignableFrom(testClass)) {
-            throw new IllegalStateException(
-                    "Cannot use " + IcuTestFmwkRunner.class + " for running "
-                            + testClass + " as it is not a " + TestFmwk.class);
-        }
-        if (TestFmwk.TestGroup.class.isAssignableFrom(testClass)) {
-            throw new IllegalStateException(
-                    "Cannot use " + IcuTestFmwkRunner.class + " for running "
-                            + testClass + " as it is a " + TestFmwk.TestGroup.class
-                            + ": Use @RunWith(" + IcuTestGroupRunner.class.getSimpleName()
-                            + ".class) instead");
-        }
-
-        return testClass.asSubclass(TestFmwk.class);
-    }
-
-    IcuTestFmwkRunner(Class<? extends TestFmwk> testFmwkClass, IcuRunnerParams icuRunnerParams)
-            throws Exception {
-        super(testFmwkClass);
-
-        this.icuRunnerParams = icuRunnerParams;
-
-        // Create a TestFmwk and make sure that it's initialized properly.
-        TestFmwk testFmwk = TestFmwkUtils.newTestFmwkInstance(testFmwkClass);
-
-        tests = new ArrayList<>();
-
-        TestFmwk.Target target = TestFmwkUtils.getTargets(testFmwk);
-        while (target != null) {
-            String name = target.name;
-            // Just ignore targets that do not have a name, they are do nothing place holders.
-            if (name != null) {
-                tests.add(new IcuFrameworkTest(testFmwk, target, name));
-            }
-            target = target.getNext();
-        }
-
-        // If the class has no tests then fail.
-        if (tests.isEmpty()) {
-            throw new IllegalStateException("Cannot find any tests for " + testFmwkClass);
-        }
-
-        // Sort the methods to ensure consistent ordering.
-        Collections.sort(tests);
-    }
-
-    @Override
-    protected List<IcuFrameworkTest> getChildren() {
-        return tests;
-    }
-
-    @Override
-    protected Description describeChild(IcuFrameworkTest child) {
-        return child.getDescription();
-    }
-
-    @Override
-    protected void runChild(final IcuFrameworkTest child, RunNotifier notifier) {
-        Description description = describeChild(child);
-        Statement statement;
-        if (icuRunnerParams.getSkipExecution()) {
-            statement = EMPTY_STATEMENT;
-        } else {
-            statement = new Statement() {
-                @Override
-                public void evaluate() throws Throwable {
-                    child.run();
-                }
-            };
-        }
-        runLeaf(statement, description, notifier);
-    }
-}
diff --git a/tests/tests/icu/src/android/icu/cts/junit/IcuTestGroupRunner.java b/tests/tests/icu/src/android/icu/cts/junit/IcuTestGroupRunner.java
deleted file mode 100644
index b09de71..0000000
--- a/tests/tests/icu/src/android/icu/cts/junit/IcuTestGroupRunner.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.icu.cts.junit;
-
-import android.icu.dev.test.TestFmwk;
-import java.util.ArrayList;
-import java.util.List;
-import org.junit.runner.Description;
-import org.junit.runner.Runner;
-import org.junit.runner.notification.RunNotifier;
-import org.junit.runners.model.RunnerBuilder;
-
-/**
- * A {@link org.junit.runner.Runner} that can be used to run a class that is a
- * {@link TestFmwk.TestGroup} but not a {@link TestFmwk}
- */
-public class IcuTestGroupRunner extends IcuTestParentRunner<Runner> {
-
-    private final List<Runner> runners;
-
-    /**
-     * The constructor used when this class is used with {@code @RunWith(...)}.
-     */
-    public IcuTestGroupRunner(Class<?> testClass, RunnerBuilder runnerBuilder)
-            throws Exception {
-        super(testClass);
-
-        Class<? extends TestFmwk.TestGroup> testGroupClass = checkClass(testClass);
-
-        // Create a TestGroup and make sure that it's initialized properly.
-        TestFmwk.TestGroup testGroup = TestFmwkUtils.newTestFmwkInstance(testGroupClass);
-
-        runners = new ArrayList<>();
-        List<String> classNames = TestFmwkUtils.getClassNames(testGroup);
-        ClassLoader classLoader = testGroupClass.getClassLoader();
-        for (String className : classNames) {
-            Runner runner;
-
-            try {
-                Class<?> childTestClass = Class.forName(className, false, classLoader);
-                runner = runnerBuilder.safeRunnerForClass(childTestClass);
-            } catch (ClassNotFoundException e) {
-                runner = new ErrorReportingRunner(className, e);
-            }
-
-            runners.add(runner);
-        }
-    }
-
-    /**
-     * Make sure that the supplied test class is supported by this.
-     */
-    private static Class<? extends TestFmwk.TestGroup> checkClass(Class<?> testClass) {
-        if (!TestFmwk.TestGroup.class.isAssignableFrom(testClass)) {
-            if (TestFmwk.class.isAssignableFrom(testClass)) {
-                throw new IllegalStateException(
-                        "Cannot use " + IcuTestGroupRunner.class + " for running "
-                                + testClass + " as it is a " + TestFmwk.class
-                                + ": Use @RunWith(" + IcuTestFmwkRunner.class.getSimpleName()
-                                + ".class) instead");
-            }
-            throw new IllegalStateException(
-                    "Cannot use " + IcuTestGroupRunner.class + " for running "
-                            + testClass + " as it is not a " + TestFmwk.TestGroup.class);
-        }
-
-        return testClass.asSubclass(TestFmwk.TestGroup.class);
-    }
-
-    @Override
-    protected List<Runner> getChildren() {
-        return runners;
-    }
-
-    @Override
-    protected Description describeChild(Runner child) {
-        return child.getDescription();
-    }
-
-    @Override
-    protected void runChild(Runner child, RunNotifier notifier) {
-        child.run(notifier);
-    }
-}
diff --git a/tests/tests/icu/src/android/icu/cts/junit/IcuTestParentRunner.java b/tests/tests/icu/src/android/icu/cts/junit/IcuTestParentRunner.java
deleted file mode 100644
index 8bf05b9..0000000
--- a/tests/tests/icu/src/android/icu/cts/junit/IcuTestParentRunner.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.icu.cts.junit;
-
-import org.junit.runners.ParentRunner;
-import org.junit.runners.model.InitializationError;
-
-/**
- * Extends {@link ParentRunner} to prevent it from trying to create an instance of
- * {@link org.junit.runners.model.TestClass} for the supplied {@code testClass} because that
- * requires that the {@code testClass} has only a single constructor and at least one ICU test
- * ({@code android.icu.dev.test.serializable.CoverageTest}) has more than one constructor.
- *
- * <p>This provides a dummy class and overrides the {@link #getName()} method to return the
- * correct name. The consequence of this is that it is not possible to use JUnit 4 annotations
- * related to the class, like {@link org.junit.BeforeClass}, {@link org.junit.ClassRule}, etc.
- */
-abstract class IcuTestParentRunner<T> extends ParentRunner<T> {
-
-    private final Class<?> testClass;
-
-    IcuTestParentRunner(Class<?> testClass) throws InitializationError {
-        super(DummyTestClass.class);
-        this.testClass = testClass;
-    }
-
-    @Override
-    protected String getName() {
-        return testClass.getName();
-    }
-
-    /**
-     * A dummy test class to pass to {@link ParentRunner} for it to validate and check for
-     * annotations.
-     *
-     * <p>Must be public.
-     */
-    public static class DummyTestClass {
-
-    }
-}
diff --git a/tests/tests/icu/src/android/icu/cts/junit/IcuTestRunnerBuilder.java b/tests/tests/icu/src/android/icu/cts/junit/IcuTestRunnerBuilder.java
deleted file mode 100644
index 16b915c..0000000
--- a/tests/tests/icu/src/android/icu/cts/junit/IcuTestRunnerBuilder.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.icu.cts.junit;
-
-import android.icu.dev.test.TestFmwk;
-import org.junit.runner.Runner;
-import org.junit.runners.model.RunnerBuilder;
-
-/**
- * A {@link RunnerBuilder} used for running ICU test classes derived from {@link TestFmwk}.
- */
-public class IcuTestRunnerBuilder extends RunnerBuilder {
-
-    private final IcuRunnerParams icuRunnerParams;
-
-    public IcuTestRunnerBuilder(IcuRunnerParams icuRunnerParams) {
-        this.icuRunnerParams = icuRunnerParams;
-    }
-
-    @Override
-    public Runner runnerForClass(Class<?> testClass) throws Throwable {
-        try {
-            // Check for a TestGroup before a TestFmwk class as TestGroup is a subclass of TestFmwk
-            if (TestFmwk.TestGroup.class.isAssignableFrom(testClass)) {
-                return new IcuTestGroupRunner(testClass.asSubclass(TestFmwk.TestGroup.class), this);
-            }
-
-            if (TestFmwk.class.isAssignableFrom(testClass)) {
-                // Make sure that in the event of an error the resulting Runner an be filtered out.
-                return new IcuTestFmwkRunner(testClass.asSubclass(TestFmwk.class), icuRunnerParams);
-            }
-        } catch (Exception e) {
-            return new ErrorReportingRunner(testClass.getName(), e);
-        }
-
-        return null;
-    }
-}
diff --git a/tests/tests/icu/src/android/icu/cts/junit/TestFmwkUtils.java b/tests/tests/icu/src/android/icu/cts/junit/TestFmwkUtils.java
deleted file mode 100644
index 1ddf86d..0000000
--- a/tests/tests/icu/src/android/icu/cts/junit/TestFmwkUtils.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.icu.cts.junit;
-
-import android.icu.dev.test.TestFmwk;
-import com.google.common.collect.ImmutableSet;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Abstracts away reflection code that accesses various hidden fields and methods in the ICU test
- * framework.
- *
- * <p>Assuming that this is integrated into ICU test framework itself then ideally the test
- * framework will itself be modified to remove the need for this reflection at which point this
- * class can be removed.
- */
-public class TestFmwkUtils {
-
-    /**
-     * The field on TestGroup which has the list of classes in it.
-     */
-    private static final Field classesToTestField = getField(TestFmwk.TestGroup.class, "names");
-
-    /**
-     * The field on TestGroup which has the default package in it.
-     */
-    private static final Field defaultPackageField =
-            getField(TestFmwk.TestGroup.class, "defaultPackage");
-
-    /**
-     * The field on TestFmwk which has the {@link android.icu.dev.test.TestFmwk.TestParams} in it.
-     */
-    private static final Field paramsField = getField(TestFmwk.class, "params");
-
-    private static final Method getTargetsMethod = getTargetsMethod();
-
-    private static final String REPACKAGED_ROOT_TEST_GROUP_NAME = "android.icu.dev.test.TestAll";
-
-    private static Field getField(Class<?> theClass, String name) {
-        // Find the field, and complain if it is not where it's expected to be.
-        try {
-            Field field = theClass.getDeclaredField(name);
-            field.setAccessible(true);  // It's private by default.
-            return field;
-        } catch (NoSuchFieldException e) {
-            throw new RuntimeException("Class structure of ICU tests have changed.", e);
-        }
-    }
-
-    private static Method getTargetsMethod() {
-        try {
-            Method method = TestFmwk.class.getDeclaredMethod("getTargets", String.class);
-            method.setAccessible(true);
-            return method;
-        } catch (NoSuchMethodException e) {
-            throw new RuntimeException("Class structure of ICU tests have changed.", e);
-        }
-    }
-
-    public static TestFmwk.Target getTargets(TestFmwk testFmwk) {
-        return test_for_TestFmwk_GetTargets(testFmwk);
-    }
-
-    /**
-     * A special method to avoid the TestFmwk from throwing an InternalError when an error occurs
-     * during execution of the test but outside the actual test method, e.g. in a
-     * {@link TestFmwk#validate()} method. See http://bugs.icu-project.org/trac/ticket/12183
-     *
-     * <p>DO NOT CHANGE THE NAME
-     */
-    private static TestFmwk.Target test_for_TestFmwk_GetTargets(TestFmwk testFmwk) {
-        try {
-            return (TestFmwk.Target) getTargetsMethod.invoke(testFmwk, new Object[] {null});
-        } catch (InvocationTargetException | IllegalAccessException e) {
-            throw new IllegalStateException(
-                    "Problem calling getTargets(null) on " + testFmwk, e);
-        }
-    }
-
-    public static <T extends TestFmwk> T newTestFmwkInstance(Class<? extends T> testFmwkClass)
-            throws IllegalAccessException, InstantiationException {
-        // Create a TestFmwk and make sure that it's params field is initialized.
-        T testFmwk = testFmwkClass.newInstance();
-        TestFmwk.TestParams testParams = TestFmwk.TestParams.create(new String[0], null);
-        paramsField.set(testFmwk, testParams);
-        return testFmwk;
-    }
-
-    private static boolean hasGetTargetsMethod(Class<?> clazz) {
-        try {
-            clazz.getDeclaredMethod("getTargets", String.class);
-            return true;
-        } catch (NoSuchMethodException e) {
-            return false;
-        }
-    }
-
-    public static boolean overridesGetTargetsMethod(Class<?> testFmwkClass) {
-        while (testFmwkClass != TestFmwk.class && testFmwkClass != Object.class) {
-            if (hasGetTargetsMethod(testFmwkClass)) {
-                return true;
-            }
-
-            testFmwkClass = testFmwkClass.getSuperclass();
-        }
-
-        return false;
-    }
-
-    public static List<String> getClassNames(TestFmwk.TestGroup testGroup) {
-        try {
-            String[] classNames = (String[]) classesToTestField.get(testGroup);
-            String defaultPackage = (String) defaultPackageField.get(testGroup);
-
-            List<String> list = new ArrayList<>(classNames.length);
-            for (String basicName : classNames) {
-                // Handle relative class names.
-                String fullyQualifiedName;
-                if (basicName.contains(".")) {
-                    fullyQualifiedName = basicName;
-                } else {
-                    fullyQualifiedName = defaultPackage + basicName;
-                }
-
-                list.add(fullyQualifiedName);
-            }
-
-            // Sort to ensure consistent ordering.
-            Collections.sort(list);
-
-            return list;
-        } catch (IllegalAccessException e) {
-            throw new IllegalStateException("Problem getting class names from " + testGroup, e);
-        }
-    }
-
-    public static Set<String> getRootClassNames() {
-        return ImmutableSet.of(REPACKAGED_ROOT_TEST_GROUP_NAME);
-    }
-}
diff --git a/tests/tests/icu/src/android/icu/cts/junit/package-info.java b/tests/tests/icu/src/android/icu/cts/junit/package-info.java
deleted file mode 100644
index 2da0748..0000000
--- a/tests/tests/icu/src/android/icu/cts/junit/package-info.java
+++ /dev/null
@@ -1,10 +0,0 @@
-/**
- * Contains classes used to make ICU tests runnable by JUnit.
- *
- * <p>Ideally, this will be integrated into ICU itself and cleaned up so that ICU tests can be
- * simply run using standard JUnit. e.g. ICU test classes will be annotated with
- * {@code RunWith(IcuTestGroupRunner.class)} or {@code RunWith(IcuTestFmwkRunner.class)} depending
- * on whether they extend {@link android.icu.dev.test.TestFmwk.TestGroup} or
- * {@link android.icu.dev.test.TestFmwk}.
- */
-package android.icu.cts.junit;
diff --git a/tests/tests/icu/test-list.txt b/tests/tests/icu/test-list.txt
index 93b9f89..84da3c4 100644
--- a/tests/tests/icu/test-list.txt
+++ b/tests/tests/icu/test-list.txt
@@ -3,7 +3,6 @@
 android.icu.dev.test.bidi.TestBidi#testBidi
 android.icu.dev.test.bidi.TestCharFromDirProp#testCharFromDirProp
 android.icu.dev.test.bidi.TestClassOverride#testClassOverride
-android.icu.dev.test.bidi.TestCompatibility#testCompatibility
 android.icu.dev.test.bidi.TestContext#testContext
 android.icu.dev.test.bidi.TestFailureRecovery#testFailureRecovery
 android.icu.dev.test.bidi.TestInverse#testInverse
@@ -267,7 +266,6 @@
 android.icu.dev.test.collator.CollationAPITest#TestSubClass
 android.icu.dev.test.collator.CollationAPITest#TestVariableTopSetting
 android.icu.dev.test.collator.CollationChineseTest#TestPinYin
-android.icu.dev.test.collator.CollationCreationMethodTest#TestRuleVsLocaleCreationMonkey
 android.icu.dev.test.collator.CollationCurrencyTest#TestCurrency
 android.icu.dev.test.collator.CollationDummyTest#TestExtra
 android.icu.dev.test.collator.CollationDummyTest#TestIdentical
@@ -341,8 +339,6 @@
 android.icu.dev.test.collator.CollationMiscTest#TestHungarianTailoring
 android.icu.dev.test.collator.CollationMiscTest#TestIdenticalCompare
 android.icu.dev.test.collator.CollationMiscTest#TestImplicitTailoring
-android.icu.dev.test.collator.CollationMiscTest#TestImport
-android.icu.dev.test.collator.CollationMiscTest#TestImportWithType
 android.icu.dev.test.collator.CollationMiscTest#TestIncompleteCnt
 android.icu.dev.test.collator.CollationMiscTest#TestIncrementalNormalize
 android.icu.dev.test.collator.CollationMiscTest#TestInvalidListsAndRanges
@@ -384,7 +380,6 @@
 android.icu.dev.test.collator.CollationMiscTest#TestSurrogates
 android.icu.dev.test.collator.CollationMiscTest#TestTibetanConformance
 android.icu.dev.test.collator.CollationMiscTest#TestUCAPrecontext
-android.icu.dev.test.collator.CollationMiscTest#TestUCARules
 android.icu.dev.test.collator.CollationMiscTest#TestUnknownCollationKeyword
 android.icu.dev.test.collator.CollationMiscTest#TestUpperFirstQuaternary
 android.icu.dev.test.collator.CollationMiscTest#TestVariableTop
@@ -442,7 +437,6 @@
 android.icu.dev.test.collator.CollationSpanishTest#TestPrimary
 android.icu.dev.test.collator.CollationSpanishTest#TestTertiary
 android.icu.dev.test.collator.CollationTest#TestCollationWeights
-android.icu.dev.test.collator.CollationTest#TestDataDriven
 android.icu.dev.test.collator.CollationTest#TestFCD
 android.icu.dev.test.collator.CollationTest#TestImplicits
 android.icu.dev.test.collator.CollationTest#TestMinMax
@@ -462,7 +456,6 @@
 android.icu.dev.test.collator.G7CollationTest#TestDemo2
 android.icu.dev.test.collator.G7CollationTest#TestDemo3
 android.icu.dev.test.collator.G7CollationTest#TestDemo4
-android.icu.dev.test.collator.G7CollationTest#TestG7Data
 android.icu.dev.test.collator.LotusCollationKoreanTest#TestTertiary
 android.icu.dev.test.collator.UCAConformanceTest#TestRulesNonIgnorable
 android.icu.dev.test.collator.UCAConformanceTest#TestRulesShifted
@@ -965,7 +958,6 @@
 android.icu.dev.test.format.NumberFormatTest#TestCurrFmtNegSameAsPositive
 android.icu.dev.test.format.NumberFormatTest#TestCustomCurrencySignAndSeparator
 android.icu.dev.test.format.NumberFormatTest#TestDataDrivenICU
-android.icu.dev.test.format.NumberFormatTest#TestDataDrivenJDK
 android.icu.dev.test.format.NumberFormatTest#TestDecimalFormatCurrencyParse
 android.icu.dev.test.format.NumberFormatTest#TestExplicitParents
 android.icu.dev.test.format.NumberFormatTest#TestExponent
@@ -989,7 +981,6 @@
 android.icu.dev.test.format.NumberFormatTest#TestMiscCurrencyParsing
 android.icu.dev.test.format.NumberFormatTest#TestMultiCurrencySign
 android.icu.dev.test.format.NumberFormatTest#TestNegZeroRounding
-android.icu.dev.test.format.NumberFormatTest#TestNonpositiveMultiplier
 android.icu.dev.test.format.NumberFormatTest#TestNumberFormatFactory
 android.icu.dev.test.format.NumberFormatTest#TestNumberFormatTestTupleToString
 android.icu.dev.test.format.NumberFormatTest#TestNumberingSystems
@@ -1140,7 +1131,6 @@
 android.icu.dev.test.format.PluralRulesTest#TestLocales
 android.icu.dev.test.format.PluralRulesTest#testOperands
 android.icu.dev.test.format.PluralRulesTest#TestOrdinal
-android.icu.dev.test.format.PluralRulesTest#testOverUnderflow
 android.icu.dev.test.format.PluralRulesTest#TestParseDescription
 android.icu.dev.test.format.PluralRulesTest#testParseEmpty
 android.icu.dev.test.format.PluralRulesTest#testParsing
diff --git a/tests/tests/keystore/Android.mk b/tests/tests/keystore/Android.mk
index 7ba87e3..8e86c0e 100644
--- a/tests/tests/keystore/Android.mk
+++ b/tests/tests/keystore/Android.mk
@@ -23,7 +23,8 @@
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner core-tests-support
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    ctstestrunner core-tests-support platform-test-annotations
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/keystore/src/android/keystore/cts/CipherTest.java b/tests/tests/keystore/src/android/keystore/cts/CipherTest.java
index 60a48e0..57a7648 100644
--- a/tests/tests/keystore/src/android/keystore/cts/CipherTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/CipherTest.java
@@ -16,6 +16,7 @@
 
 package android.keystore.cts;
 
+import android.platform.test.annotations.Presubmit;
 import android.security.keystore.KeyProperties;
 import android.security.keystore.KeyProtection;
 import android.test.AndroidTestCase;
@@ -221,6 +222,7 @@
     private static final byte[] AES256_KAT_KEY_BYTES =
             HexEncoding.decode("cf601cc10aaf434d1f01747136aff222af7fb426d101901712214c3fea18125f");
 
+    @Presubmit
     public void testAlgorithmList() {
         // Assert that Android Keystore Provider exposes exactly the expected Cipher
         // transformations. We don't care whether the transformations are exposed via aliases, as
diff --git a/tests/tests/location/AndroidTest.xml b/tests/tests/location/AndroidTest.xml
index 178e8d1..4ac850e 100644
--- a/tests/tests/location/AndroidTest.xml
+++ b/tests/tests/location/AndroidTest.xml
@@ -21,7 +21,7 @@
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.location.cts" />
-        <option name="runtime-hint" value="1m26s" />
+        <option name="runtime-hint" value="18m8s" />
     </test>
 
 </configuration>
diff --git a/tests/tests/location/src/android/location/cts/GnssMeasurementTest.java b/tests/tests/location/src/android/location/cts/GnssMeasurementTest.java
index ce81402..3ae7b3c 100644
--- a/tests/tests/location/src/android/location/cts/GnssMeasurementTest.java
+++ b/tests/tests/location/src/android/location/cts/GnssMeasurementTest.java
@@ -51,7 +51,6 @@
         measurement.setState(14);
         measurement.setSvid(15);
         measurement.setTimeOffsetNanos(16.0);
-        measurement.setPseudorangeRateCorrected(true);
     }
 
     private static void verifyTestValues(GnssMeasurement measurement) {
@@ -74,7 +73,6 @@
         assertEquals(14, measurement.getState());
         assertEquals(15, measurement.getSvid());
         assertEquals(16.0, measurement.getTimeOffsetNanos());
-        assertTrue(measurement.isPseudorangeRateCorrected());
     }
 
     public void testWriteToParcel() {
@@ -95,11 +93,6 @@
         verifyTestValues(newMeasurement);
     }
 
-    public void testPseudorangeRateCorrected() {
-        GnssMeasurement measurement = new GnssMeasurement();
-        measurement.isPseudorangeRateCorrected();
-    }
-
     public void testSetReset() {
         GnssMeasurement measurement = new GnssMeasurement();
         setTestValues(measurement);
diff --git a/tests/tests/location/src/android/location/cts/GnssMeasurementsEventCallbackTest.java b/tests/tests/location/src/android/location/cts/GnssMeasurementsEventCallbackTest.java
index 930c344..72addce 100644
--- a/tests/tests/location/src/android/location/cts/GnssMeasurementsEventCallbackTest.java
+++ b/tests/tests/location/src/android/location/cts/GnssMeasurementsEventCallbackTest.java
@@ -16,6 +16,8 @@
 
 package android.location.cts;
 
+import android.location.GnssClock;
+import android.location.GnssMeasurement;
 import android.location.GnssMeasurementsEvent;
 import android.test.AndroidTestCase;
 
@@ -25,7 +27,11 @@
 
     public void testAllMethodsExist() {
         GnssMeasurementsEvent.Callback callback = new MockCallback();
-        GnssMeasurementsEvent event = new GnssMeasurementsEvent(null, null);
+        GnssClock clock = new GnssClock();
+        GnssMeasurement m1 = new GnssMeasurement();
+        GnssMeasurement m2 = new GnssMeasurement();
+        GnssMeasurementsEvent event = new GnssMeasurementsEvent(
+                clock, new GnssMeasurement[] {m1, m2});
         callback.onGnssMeasurementsReceived(event);
         callback.onStatusChanged(GnssMeasurementsEvent.STATUS_READY);
     }
diff --git a/tests/tests/location/src/android/location/cts/GnssMeasurementsEventTest.java b/tests/tests/location/src/android/location/cts/GnssMeasurementsEventTest.java
index 33cf924..51af03d 100644
--- a/tests/tests/location/src/android/location/cts/GnssMeasurementsEventTest.java
+++ b/tests/tests/location/src/android/location/cts/GnssMeasurementsEventTest.java
@@ -28,7 +28,11 @@
 
 public class GnssMeasurementsEventTest extends AndroidTestCase {
     public void testDescribeContents() {
-        GnssMeasurementsEvent event = new GnssMeasurementsEvent(null, null);
+        GnssClock clock = new GnssClock();
+        GnssMeasurement m1 = new GnssMeasurement();
+        GnssMeasurement m2 = new GnssMeasurement();
+        GnssMeasurementsEvent event = new GnssMeasurementsEvent(
+                clock, new GnssMeasurement[] {m1, m2});
         event.describeContents();
     }
 
diff --git a/tests/tests/location/src/android/location/cts/GnssNavigationMessageEventCallbackTest.java b/tests/tests/location/src/android/location/cts/GnssNavigationMessageEventCallbackTest.java
index a548122..0589c57 100644
--- a/tests/tests/location/src/android/location/cts/GnssNavigationMessageEventCallbackTest.java
+++ b/tests/tests/location/src/android/location/cts/GnssNavigationMessageEventCallbackTest.java
@@ -16,6 +16,7 @@
 
 package android.location.cts;
 
+import android.location.GnssNavigationMessage;
 import android.location.GnssNavigationMessageEvent;
 import android.test.AndroidTestCase;
 
@@ -25,7 +26,8 @@
 
     public void testAllMethodsExist() {
         GnssNavigationMessageEvent.Callback callback = new MockCallback();
-        GnssNavigationMessageEvent event = new GnssNavigationMessageEvent(null);
+        GnssNavigationMessage message = new GnssNavigationMessage();
+        GnssNavigationMessageEvent event = new GnssNavigationMessageEvent(message);
         callback.onGnssNavigationMessageReceived(event);
         callback.onStatusChanged(GnssNavigationMessageEvent.STATUS_READY);
     }
diff --git a/tests/tests/location/src/android/location/cts/GnssNavigationMessageEventTest.java b/tests/tests/location/src/android/location/cts/GnssNavigationMessageEventTest.java
index 730bd525..0772092 100644
--- a/tests/tests/location/src/android/location/cts/GnssNavigationMessageEventTest.java
+++ b/tests/tests/location/src/android/location/cts/GnssNavigationMessageEventTest.java
@@ -23,7 +23,8 @@
 
 public class GnssNavigationMessageEventTest extends AndroidTestCase {
     public void testDescribeContents() {
-        GnssNavigationMessageEvent event = new GnssNavigationMessageEvent(null);
+        GnssNavigationMessage message = new GnssNavigationMessage();
+        GnssNavigationMessageEvent event = new GnssNavigationMessageEvent(message);
         event.describeContents();
     }
 
diff --git a/tests/tests/location/src/android/location/cts/GnssNavigationMessageTest.java b/tests/tests/location/src/android/location/cts/GnssNavigationMessageTest.java
index 87814c5..a4e18e6 100644
--- a/tests/tests/location/src/android/location/cts/GnssNavigationMessageTest.java
+++ b/tests/tests/location/src/android/location/cts/GnssNavigationMessageTest.java
@@ -93,7 +93,7 @@
     private static void setTestValues(GnssNavigationMessage message) {
         message.setData(new byte[] {1, 2, 3, 4});
         message.setMessageId(5);
-        message.setStatus(GnssNavigationMessage.PARCELABLE_WRITE_RETURN_VALUE);
+        message.setStatus(GnssNavigationMessage.STATUS_PARITY_REBUILT);
         message.setSubmessageId(6);
         message.setSvid(7);
         message.setType(GnssNavigationMessage.TYPE_GPS_L2CNAV);
@@ -101,12 +101,13 @@
 
     private static void verifyTestValues(GnssNavigationMessage message) {
         byte[] data = message.getData();
+        assertEquals(4, data.length);
         assertEquals(1, data[0]);
         assertEquals(2, data[1]);
         assertEquals(3, data[2]);
         assertEquals(4, data[3]);
         assertEquals(5, message.getMessageId());
-        assertEquals(GnssNavigationMessage.PARCELABLE_WRITE_RETURN_VALUE, message.getStatus());
+        assertEquals(GnssNavigationMessage.STATUS_PARITY_REBUILT, message.getStatus());
         assertEquals(6, message.getSubmessageId());
         assertEquals(7, message.getSvid());
         assertEquals(GnssNavigationMessage.TYPE_GPS_L2CNAV, message.getType());
diff --git a/tests/tests/location/src/android/location/cts/LocationManagerTest.java b/tests/tests/location/src/android/location/cts/LocationManagerTest.java
index 85de83d..36358ab 100644
--- a/tests/tests/location/src/android/location/cts/LocationManagerTest.java
+++ b/tests/tests/location/src/android/location/cts/LocationManagerTest.java
@@ -477,7 +477,7 @@
         }
 
         try {
-            mManager.removeUpdates( (LocationListener) null );
+            mManager.removeUpdates((LocationListener) null );
             fail("Should throw IllegalArgumentException if listener is null!");
         } catch (IllegalArgumentException e) {
             // expected
@@ -566,7 +566,12 @@
         updateLocation(latitude3, longitude3);
         assertFalse(listener.hasCalledOnLocationChanged(TEST_TIME_OUT));
 
-        mManager.requestSingleUpdate(LocationManager.GPS_PROVIDER, mPendingIntent);
+        try {
+            mManager.requestSingleUpdate(LocationManager.GPS_PROVIDER, mPendingIntent);
+            fail("Should throw IllegalArgumentException if PendingIntent is null!");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
 
         try {
             mManager.requestSingleUpdate(LocationManager.GPS_PROVIDER, (LocationListener) null,
@@ -584,7 +589,7 @@
         }
 
         try {
-            mManager.removeUpdates( (LocationListener) null );
+            mManager.removeUpdates((LocationListener) null );
             fail("Should throw IllegalArgumentException if listener is null!");
         } catch (IllegalArgumentException e) {
             // expected
diff --git a/tests/tests/media/Android.mk b/tests/tests/media/Android.mk
index 7a92a2c..879c72b 100644
--- a/tests/tests/media/Android.mk
+++ b/tests/tests/media/Android.mk
@@ -44,9 +44,9 @@
 # include both the 32 and 64 bit versions
 LOCAL_MULTILIB := both
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctsmediautil ctsdeviceutil compatibility-device-util ctstestserver ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctsmediautil ctsdeviceutil compatibility-device-util ctstestserver ctstestrunner ndkaudio
 
-LOCAL_JNI_SHARED_LIBRARIES := libctsmediacodec_jni libaudio_jni libnativehelper_compat_libc++
+LOCAL_JNI_SHARED_LIBRARIES := libctsmediacodec_jni libaudio_jni libnativehelper_compat_libc++ libndkaudioLib
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/media/libaudiojni/Android.mk b/tests/tests/media/libaudiojni/Android.mk
index 27b42c1..d1b1ced 100644
--- a/tests/tests/media/libaudiojni/Android.mk
+++ b/tests/tests/media/libaudiojni/Android.mk
@@ -37,4 +37,6 @@
 LOCAL_SHARED_LIBRARIES := libandroid liblog libnativehelper_compat_libc++ libOpenSLES
 LOCAL_CXX_STL := libc++_static
 
+LOCAL_CFLAGS := -Werror -Wall
+
 include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/media/libaudiojni/appendix-b-1-2-recording.cpp b/tests/tests/media/libaudiojni/appendix-b-1-2-recording.cpp
index 5f6f3aa..e628c6f 100644
--- a/tests/tests/media/libaudiojni/appendix-b-1-2-recording.cpp
+++ b/tests/tests/media/libaudiojni/appendix-b-1-2-recording.cpp
@@ -56,8 +56,6 @@
     SLDataLocator_IODevice locator_mic;
     SLDeviceVolumeItf devicevolumeItf;
     SLDataSink audioSink;
-    SLDataLocator_URI uri;
-    SLDataFormat_MIME mime;
 
     int i;
     SLboolean required[MAX_NUMBER_INTERFACES];
diff --git a/tests/tests/media/libaudiojni/audio-record-native.cpp b/tests/tests/media/libaudiojni/audio-record-native.cpp
index 5f72ab3..f771d9b 100644
--- a/tests/tests/media/libaudiojni/audio-record-native.cpp
+++ b/tests/tests/media/libaudiojni/audio-record-native.cpp
@@ -405,7 +405,6 @@
     }
 
     static void BufferQueueCallback(SLBufferQueueItf queueItf, void *pContext) {
-        SLresult res;
         // naked native record
         AudioRecordNative *record = (AudioRecordNative *)pContext;
         record->bufferQueueCallback(queueItf);
diff --git a/tests/tests/media/libaudiojni/audio-track-native.cpp b/tests/tests/media/libaudiojni/audio-track-native.cpp
index 23e6a0f..ce8bf91 100644
--- a/tests/tests/media/libaudiojni/audio-track-native.cpp
+++ b/tests/tests/media/libaudiojni/audio-track-native.cpp
@@ -345,7 +345,6 @@
     }
 
     static void BufferQueueCallback(SLBufferQueueItf queueItf, void *pContext) {
-        SLresult res;
         // naked native track
         AudioTrackNative *track = (AudioTrackNative *)pContext;
         track->bufferQueueCallback(queueItf);
diff --git a/tests/tests/media/libmediandkjni/Android.mk b/tests/tests/media/libmediandkjni/Android.mk
index b59d1fb..259c95e 100644
--- a/tests/tests/media/libmediandkjni/Android.mk
+++ b/tests/tests/media/libmediandkjni/Android.mk
@@ -35,4 +35,6 @@
 
 LOCAL_SDK_VERSION := 23
 
+LOCAL_CFLAGS := -Werror -Wall
+
 include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/media/libmediandkjni/native-media-jni.cpp b/tests/tests/media/libmediandkjni/native-media-jni.cpp
index f15a196..546ef2b 100644
--- a/tests/tests/media/libmediandkjni/native-media-jni.cpp
+++ b/tests/tests/media/libmediandkjni/native-media-jni.cpp
@@ -263,7 +263,7 @@
         int t = AMediaExtractor_getSampleTrackIndex(ex);
         if (t >=0) {
             ssize_t bufidx = AMediaCodec_dequeueInputBuffer(codec[t], 5000);
-            ALOGV("track %d, input buffer %d", t, bufidx);
+            ALOGV("track %d, input buffer %zd", t, bufidx);
             if (bufidx >= 0) {
                 size_t bufsize;
                 uint8_t *buf = AMediaCodec_getInputBuffer(codec[t], bufidx, &bufsize);
@@ -408,7 +408,7 @@
 
     while (!sawOutputEOS) {
         ssize_t bufidx = AMediaCodec_dequeueInputBuffer(codec, 5000);
-        ALOGV("input buffer %d", bufidx);
+        ALOGV("input buffer %zd", bufidx);
         if (bufidx >= 0) {
             size_t bufsize;
             uint8_t *buf = AMediaCodec_getInputBuffer(codec, bufidx, &bufsize);
@@ -481,7 +481,7 @@
             return false;
         } else if (!strncmp(mime, "audio/", 6) || !strncmp(mime, "video/", 6)) {
             ssize_t tidx = AMediaMuxer_addTrack(muxer, format);
-            ALOGI("track %d -> %d format %s", i, tidx, s);
+            ALOGI("track %d -> %zd format %s", i, tidx, s);
             AMediaExtractor_selectTrack(ex, i);
         } else {
             ALOGE("expected audio or video mime type, got %s", mime);
@@ -536,7 +536,7 @@
     int64_t duration = 0;
     if (!AMediaFormat_getInt64(format, AMEDIAFORMAT_KEY_DURATION, &duration)
             || duration != 123456789123456789ll) {
-        ALOGE("AMediaFormat_getInt64 fail: %lld", duration);
+        ALOGE("AMediaFormat_getInt64 fail: %lld", (long long) duration);
         return false;
     }
 
diff --git a/tests/tests/media/libndkaudio/Android.mk b/tests/tests/media/libndkaudio/Android.mk
new file mode 100644
index 0000000..29e2118
--- /dev/null
+++ b/tests/tests/media/libndkaudio/Android.mk
@@ -0,0 +1,59 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE    := libndkaudioLib
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_C_INCLUDES := \
+  frameworks/wilhelm/include \
+  frameworks/wilhelm/src/android \
+  $(call include-path-for, wilhelm)
+
+LOCAL_SRC_FILES := \
+  OpenSLESUtils.cpp \
+  AudioPlayer.cpp \
+  AudioSource.cpp \
+  PeriodicAudioSource.cpp \
+  SystemParams.cpp \
+  WaveTableGenerator.cpp \
+  WaveTableOscillator.cpp \
+  com_android_ndkaudio_AudioPlayer.cpp \
+  AudioRecorder.cpp \
+  com_android_ndkaudio_AudioRecorder.cpp
+
+LOCAL_CXX_STL := libc++_static
+
+LOCAL_SHARED_LIBRARIES := liblog libOpenSLES
+
+LOCAL_CFLAGS := -Werror -Wall
+
+include $(BUILD_SHARED_LIBRARY)
+
+#
+# ndkaudio - java
+#
+include $(CLEAR_VARS)
+
+LOCAL_MODULE  := ndkaudio
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tests/tests/media/libndkaudio/AndroidManifest.xml b/tests/tests/media/libndkaudio/AndroidManifest.xml
new file mode 100644
index 0000000..3fbb9ad
--- /dev/null
+++ b/tests/tests/media/libndkaudio/AndroidManifest.xml
@@ -0,0 +1,10 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.ndkaudio"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="23"
+        android:targetSdkVersion="23" />
+
+</manifest>
diff --git a/tests/tests/media/libndkaudio/AudioPlayer.cpp b/tests/tests/media/libndkaudio/AudioPlayer.cpp
new file mode 100644
index 0000000..af7d24a
--- /dev/null
+++ b/tests/tests/media/libndkaudio/AudioPlayer.cpp
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <assert.h>
+
+#include <android/log.h>
+
+#include <SLES/OpenSLES.h>
+#include <SLES/OpenSLES_Android.h>
+
+#include "AudioPlayer.h"
+
+#include "AudioSource.h"
+#include "SystemParams.h"
+#include "OpenSLESUtils.h"
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/*
+ * OpenSL ES Stuff
+ */
+static const char* TAG = "AudioPlayer";
+
+// engine interfaces
+static SLObjectItf engineObject = 0;
+static SLEngineItf engineItf;
+
+// output mix interfaces
+static SLObjectItf outputMixObject = 0;
+
+// this callback handler is called every time a buffer finishes playing
+static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf /*bq*/, void *context)
+{
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "bqPlayerCallback()");
+    ((ndkaudio::AudioPlayer*)context)->enqueBuffer();
+}
+
+static void OpenSLEngine() {
+    SLresult result;
+
+    // create engine
+    result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
+    assert(SL_RESULT_SUCCESS == result);
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "OpenSLEngine() - engineObject:%p", engineObject);
+
+    // realize the engine
+    result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "Realize() engine result:%s", getSLErrStr(result));
+   assert(SL_RESULT_SUCCESS == result);
+
+    // get the engine interface, which is needed in order to create other objects
+    result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineItf);
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "GetInterface() engine:%p result:%s", engineItf, getSLErrStr(result));
+    assert(SL_RESULT_SUCCESS == result);
+
+    // get the output mixer
+    result = (*engineItf)->CreateOutputMix(engineItf, &outputMixObject, 0, 0, 0);
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "CreateOutputMix() mix:%p result:%s", outputMixObject, getSLErrStr(result));
+    assert(SL_RESULT_SUCCESS == result);
+
+    // realize the output mix
+    result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "Realize() result:%s", getSLErrStr(result));
+    assert(SL_RESULT_SUCCESS == result);
+}
+
+static void CloseSLEngine() {
+    __android_log_print(ANDROID_LOG_INFO, TAG, "CloseSLEngine()");
+
+    // destroy output mix object, and invalidate all associated interfaces
+    if (outputMixObject != NULL) {
+        (*outputMixObject)->Destroy(outputMixObject);
+        outputMixObject = NULL;
+    }
+
+    if (engineObject != NULL) {
+        (*engineObject)->Destroy(engineObject);
+        engineObject = NULL;
+        engineItf = NULL;
+    }
+}
+
+/*
+ * AudioPlayer
+ */
+namespace ndkaudio {
+
+AudioPlayer::AudioPlayer() {
+    source_ = NULL;
+
+    sampleRate_ = SystemParams::getSampleRate();
+    numChannels_ = 1;
+
+    numPlayBuffFrames_ = SystemParams::getNumBufferFrames();
+
+    playing_ = false;
+
+    time_ = 0;
+
+    bqPlayerObject_ = NULL;
+    bq_ = NULL;
+    bqPlayerPlay_ = NULL;
+    configItf_ = NULL;
+
+    OpenSLEngine();
+}
+
+AudioPlayer::~AudioPlayer() {
+    CloseSLEngine();
+
+    delete[] playBuff_;
+    playBuff_ = 0;
+}
+
+SLresult AudioPlayer::Open(int numChannels, AudioSource* source) {
+    source_ = source;
+
+    SLresult result;
+
+    numChannels_ = numChannels;
+
+    int internalBuffFactor = 1;
+
+    playBuff_ =
+            new float[numPlayBuffFrames_ * numChannels_ * internalBuffFactor];
+    playBuffSizeInBytes_ = numPlayBuffFrames_ * numChannels_ * sizeof(float)
+            * internalBuffFactor;
+
+    sampleRate_ = SystemParams::getSampleRate();
+
+//    __android_log_print(ANDROID_LOG_INFO, TAG,
+//                        "AudioPlayer::Open(chans:%d, rate:%d)", numChannels,
+//                        sampleRate_);
+
+    // configure audio source
+    SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {
+            SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,    // locatorType
+            1}; // numBuffers
+
+    // SLuint32 chanMask = SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT;
+    SLAndroidDataFormat_PCM_EX format_pcm = {SL_ANDROID_DATAFORMAT_PCM_EX,	// formatType
+            (SLuint32) numChannels_,			// numChannels
+            (SLuint32)(sampleRate_ * 1000),			// milliSamplesPerSec
+            32,								// bitsPerSample
+            32,								// containerSize;
+            (SLuint32) chanCountToChanMask(numChannels_),  // channelMask
+            SL_BYTEORDER_LITTLEENDIAN,  // endianness
+            SL_ANDROID_PCM_REPRESENTATION_FLOAT};  // representation
+    SLDataSource audioSrc = {&loc_bufq, &format_pcm};
+
+    // configure audio sink
+    SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX,
+            outputMixObject};
+    SLDataSink audioSnk = {&loc_outmix, NULL};
+
+    const SLInterfaceID ids[] =
+            {SL_IID_BUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION};
+    const SLboolean req[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
+
+    // The Player
+    result = (*engineItf)->CreateAudioPlayer(engineItf, &bqPlayerObject_,
+                                             &audioSrc, &audioSnk,
+                                             sizeof(ids) / sizeof(ids[0]), ids,
+                                             req);
+//    __android_log_print(ANDROID_LOG_INFO, TAG,
+//                        "CreateAudioPlayer() result:%s, bqPlayerObject_:%p",
+//                        getSLErrStr(result), bqPlayerObject_);
+    assert(SL_RESULT_SUCCESS == result);
+
+    return result;
+}
+
+void AudioPlayer::Close() {
+    __android_log_write(ANDROID_LOG_INFO, TAG, "CloseSLPlayer()");
+
+    if (bqPlayerObject_ != NULL) {
+        (*bqPlayerObject_)->Destroy(bqPlayerObject_);
+        bqPlayerObject_ = NULL;
+
+        // invalidate any interfaces
+        bqPlayerPlay_ = NULL;
+        bq_ = NULL;
+    }
+}
+
+SLresult AudioPlayer::RealizePlayer() {
+    SLresult result;
+
+    result = (*bqPlayerObject_)->Realize(bqPlayerObject_, SL_BOOLEAN_FALSE);
+//    __android_log_print(ANDROID_LOG_INFO, TAG,
+//                        "Realize player object result:%s", getSLErrStr(result));
+    assert(SL_RESULT_SUCCESS == result);
+
+    result = (*bqPlayerObject_)->GetInterface(bqPlayerObject_, SL_IID_PLAY,
+                                              &bqPlayerPlay_);
+//    __android_log_print(ANDROID_LOG_INFO, TAG,
+//                        "get player interface result:%s, bqPlayerPlay_:%p",
+//                        getSLErrStr(result), bqPlayerPlay_);
+    assert(SL_RESULT_SUCCESS == result);
+
+    // The BufferQueue
+    result = (*bqPlayerObject_)->GetInterface(bqPlayerObject_,
+                                              SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
+                                              &bq_);
+//    __android_log_print(ANDROID_LOG_INFO, TAG,
+//                        "get bufferqueue interface:%p result:%s", bq_,
+//                        getSLErrStr(result));
+    assert(SL_RESULT_SUCCESS == result);
+
+    // The register BufferQueue callback
+    result = (*bq_)->RegisterCallback(bq_, bqPlayerCallback, this);
+//    __android_log_print(ANDROID_LOG_INFO, TAG, "register callback result:%s",
+//                        getSLErrStr(result));
+    assert(SL_RESULT_SUCCESS == result);
+
+    return result;
+}
+
+SLresult AudioPlayer::RealizeRoutingProxy() {
+    SLresult result;
+
+    // The Config interface (for routing)
+    result = (*bqPlayerObject_)->GetInterface(bqPlayerObject_,
+                                              SL_IID_ANDROIDCONFIGURATION,
+                                              (void*) &configItf_);
+//    __android_log_print(ANDROID_LOG_INFO, TAG, "get Config result:%s",
+//                        getSLErrStr(result));
+    assert(SL_RESULT_SUCCESS == result);
+
+    return result;
+}
+
+SLresult AudioPlayer::Start() {
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "Start()");
+    playing_ = true;
+
+    // set the player's state to playing
+    SLresult result = (*bqPlayerPlay_)->SetPlayState(bqPlayerPlay_,
+                                                     SL_PLAYSTATE_PLAYING);
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "SetPlayState() result:%s", getSLErrStr(result));
+    assert(SL_RESULT_SUCCESS == result);
+
+    enqueBuffer();
+
+    return result;
+}
+
+void AudioPlayer::Stop() {
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "Stop()");
+    playing_ = false;
+}
+
+SLresult AudioPlayer::enqueBuffer() {
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "AudioPlayer::enqueBuffer()");
+    if (playing_) {
+        //long dataSizeInSamples = source_->getData(time_++, playBuff_,
+        //                                          numPlayBuffFrames_,
+        //                                          source_->getNumChannels());
+        return (*bq_)->Enqueue(bq_, playBuff_, playBuffSizeInBytes_);
+    } else {
+        (*bqPlayerPlay_)->SetPlayState(bqPlayerPlay_, SL_PLAYSTATE_STOPPED);
+        return 0;
+    }
+}
+
+} // namespace ndkaudio
+
diff --git a/tests/tests/media/libndkaudio/AudioPlayer.h b/tests/tests/media/libndkaudio/AudioPlayer.h
new file mode 100644
index 0000000..57d48c7
--- /dev/null
+++ b/tests/tests/media/libndkaudio/AudioPlayer.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AUDIOPLAYER_H_
+#define AUDIOPLAYER_H_
+
+#include <SLES/OpenSLES.h>
+#include <SLES/OpenSLES_Android.h>
+
+namespace ndkaudio {
+
+class AudioSource;
+
+class AudioPlayer {
+ public:
+    AudioPlayer();
+    ~AudioPlayer();
+
+    SLresult Open(int numChannels, AudioSource* filler);
+    void Close();
+
+    SLresult RealizePlayer();
+    SLresult RealizeRoutingProxy();
+
+    SLresult Start();
+    void Stop();
+
+    inline bool isPlaying() {
+        return playing_;
+    }
+    inline AudioSource* getSource() {
+        return source_;
+    }
+
+    // This is public because it needs to be called by the OpenSL ES callback, but it should not
+    // be called by anyone else.
+    SLresult enqueBuffer();
+
+    SLPlayItf getPlayerObject() {
+        return bqPlayerPlay_;
+    }
+
+    SLAndroidConfigurationItf getConfigItf() {
+        return configItf_;
+    }
+
+ private:
+    // void fill();
+
+    AudioSource* source_;
+    int sampleRate_;
+    int numChannels_;
+
+    float* playBuff_;
+    long numPlayBuffFrames_;
+    long playBuffSizeInBytes_;
+
+    bool playing_;
+
+    long time_;
+
+    // OpenSLES stuff
+    SLObjectItf bqPlayerObject_;
+    SLPlayItf bqPlayerPlay_;
+    SLAndroidSimpleBufferQueueItf bq_;
+    SLAndroidConfigurationItf configItf_;
+};
+
+} // namespace ndkaudio
+
+#endif /* AUDIOPLAYER_H_ */
diff --git a/tests/tests/media/libndkaudio/AudioRecorder.cpp b/tests/tests/media/libndkaudio/AudioRecorder.cpp
new file mode 100644
index 0000000..050c29d
--- /dev/null
+++ b/tests/tests/media/libndkaudio/AudioRecorder.cpp
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <assert.h>
+
+#include <android/log.h>
+
+#include <SLES/OpenSLES.h>
+#include <SLES/OpenSLES_Android.h>
+
+#include "AudioRecorder.h"
+
+#include "AudioSink.h"
+#include "SystemParams.h"
+#include "OpenSLESUtils.h"
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#define ARRAYSIZE(a) sizeof((a))/sizeof((a)[0])
+
+using namespace ndkaudio;
+
+//static const char* const TAG = "AudioRecorder";
+
+#define NB_BUFFERS_IN_QUEUE 1
+
+static void RecCallback(SLRecordItf /*recorderItf_*/, void * /*context*/, SLuint32 event)
+{
+    if (SL_RECORDEVENT_HEADATNEWPOS & event) {
+        // __android_log_print(ANDROID_LOG_INFO, TAG, "SL_RECORDEVENT_HEADATNEWPOS");
+    }
+
+    if (SL_RECORDEVENT_HEADATMARKER & event) {
+        // __android_log_print(ANDROID_LOG_INFO, TAG, "SL_RECORDEVENT_HEADATMARKER");
+    }
+
+    if (SL_RECORDEVENT_BUFFER_FULL & event) {
+        // __android_log_print(ANDROID_LOG_INFO, TAG, "SL_RECORDEVENT_BUFFER_FULL");
+    }
+}
+
+#define BUFFER_SIZE_IN_FRAMES	8192
+
+static float* recBuffer = NULL;
+
+static void RecBufferQueueCallback(SLAndroidSimpleBufferQueueItf /*queueItf*/, void * context)
+{
+    AudioRecorder* recorder = (AudioRecorder*)context;
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "RecBufferQueueCallback()");
+    recorder->enqueBuffer();
+}
+
+/*
+ * The OpenSL ES code was derived from:
+ *   frameworks/wilhelm/tests/examples/slesTestRecBuffQueue.cpp
+ */
+AudioRecorder::AudioRecorder()
+ : sink_(NULL),
+   recording_(false),
+   sampleRate_(48000),
+   numChannels_(0),
+   numBufferSamples_(0),
+   engineObj_(NULL),
+   engineItf_(NULL),
+   recorderObj_(NULL),
+   recorderItf_(NULL),
+   recBuffQueueItf_(NULL),
+   configItf_(NULL)
+{}
+
+AudioRecorder::~AudioRecorder() {}
+
+void AudioRecorder::Open(int numChannels, AudioSink* sink) {
+    sink_ = sink;
+    numChannels_ = numChannels;
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "AudioRecorder::Open() - numChannels:%d", numChannels);
+
+    SLresult result;
+
+    numBufferSamples_ = BUFFER_SIZE_IN_FRAMES * numChannels_;
+    recBuffer = new float[numBufferSamples_];
+
+    SLEngineOption EngineOption[] = {
+            {(SLuint32) SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE}
+    };
+
+    /* Create the OpenSL ES Engine object */
+    result = slCreateEngine(&engineObj_, 1, EngineOption, 0, NULL, NULL);
+    assert(SL_RESULT_SUCCESS == result);
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "slCreateEngine() - engineObj_:%p", engineObj_);
+
+    /* Realizing the SL Engine in synchronous mode. */
+    result = (*engineObj_)->Realize(engineObj_, SL_BOOLEAN_FALSE);
+    assert(SL_RESULT_SUCCESS == result);
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "(*engineObj_)->Realize()");
+
+    result = (*engineObj_)->GetInterface(engineObj_, SL_IID_ENGINE, (void*)&engineItf_);
+    assert(SL_RESULT_SUCCESS == result);
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "GetInterface() - engineItf_:%p", engineItf_);
+
+    // Configuration of the recorder
+    SLboolean required[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
+    SLInterfaceID iidArray[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION};
+
+    SLDataLocator_IODevice ioDevice;
+    ioDevice.locatorType = SL_DATALOCATOR_IODEVICE;
+    ioDevice.deviceType = SL_IODEVICE_AUDIOINPUT;
+    ioDevice.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT;
+    ioDevice.device = NULL;
+
+    SLDataSource recSource;
+    recSource.pLocator = (void *) &ioDevice;
+    recSource.pFormat = NULL;
+
+    /* Setup the (OpenSL ES) data sink */
+    SLDataLocator_AndroidSimpleBufferQueue recBuffQueue;
+    recBuffQueue.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
+    recBuffQueue.numBuffers = NB_BUFFERS_IN_QUEUE;
+
+    SLAndroidDataFormat_PCM_EX pcm;
+    pcm.formatType = SL_ANDROID_DATAFORMAT_PCM_EX;
+    pcm.numChannels = numChannels_;
+    pcm.sampleRate = sampleRate_ * 1000; // milliHz
+    pcm.bitsPerSample = 32;
+    pcm.containerSize = 32;
+    pcm.channelMask = chanCountToChanMask(numChannels_);
+    pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
+    pcm.representation = SL_ANDROID_PCM_REPRESENTATION_FLOAT;
+
+    SLDataSink recDest;
+    recDest.pLocator = (void *) &recBuffQueue;
+    recDest.pFormat = (void * ) &pcm;
+
+    /* Create the audio recorder */
+    result = (*engineItf_)->CreateAudioRecorder(engineItf_, &recorderObj_, &recSource, &recDest,
+            ARRAYSIZE(iidArray), iidArray, required);
+    assert(SL_RESULT_SUCCESS == result);
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "CreateAudioRecorder() - recorderObj_:%p", recorderObj_);
+}
+
+void AudioRecorder::Close() {
+    /* Shutdown OpenSL ES */
+    (*engineObj_)->Destroy(engineObj_);
+    engineObj_ = 0;
+}
+
+void AudioRecorder::RealizeRecorder() {
+    SLresult result;
+
+    /* Realize the recorder in synchronous mode. */
+    result = (*recorderObj_)->Realize(recorderObj_, SL_BOOLEAN_FALSE);
+    assert(SL_RESULT_SUCCESS == result);
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "Recorder realized");
+
+    /* Get the record interface which is implicit */
+    result = (*recorderObj_)->GetInterface(recorderObj_, SL_IID_RECORD, (void*)&recorderItf_);
+    assert(SL_RESULT_SUCCESS == result);
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "GetInterface() recorderItf_:%p", recorderItf_);
+
+    /* Set up the recorder callback to get events during the recording */
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "SetMarkerPosition()");
+    result = (*recorderItf_)->SetMarkerPosition(recorderItf_, 2000);
+    assert(SL_RESULT_SUCCESS == result);
+
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "SetPositionUpdatePeriod()");
+    result = (*recorderItf_)->SetPositionUpdatePeriod(recorderItf_, 500);
+    assert(SL_RESULT_SUCCESS == result);
+
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "SetCallbackEventsMask()");
+    result = (*recorderItf_)->SetCallbackEventsMask(recorderItf_, SL_RECORDEVENT_HEADATMARKER | SL_RECORDEVENT_HEADATNEWPOS);
+    assert(SL_RESULT_SUCCESS == result);
+
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "RegisterCallback() - Events");
+    result = (*recorderItf_)->RegisterCallback(recorderItf_, RecCallback, NULL);
+    assert(SL_RESULT_SUCCESS == result);
+
+    /* Get the buffer queue interface which was explicitly requested */
+    result = (*recorderObj_)->GetInterface(recorderObj_, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, (void*)&recBuffQueueItf_);
+    assert(SL_RESULT_SUCCESS == result);
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "GetInterface() recBuffQueueItf_:%p", recBuffQueueItf_);
+
+    result = (*recBuffQueueItf_)->RegisterCallback(recBuffQueueItf_, RecBufferQueueCallback, (void*)this);
+    assert(SL_RESULT_SUCCESS == result);
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "RegisterCallback() - Buffers");
+}
+
+void AudioRecorder::RealizeRoutingProxy() {
+    SLresult result;
+    // The Config interface (for routing)
+    result = (*recorderObj_)->GetInterface(recorderObj_, SL_IID_ANDROIDCONFIGURATION, (void*)&configItf_);
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "get Config result:%s", getSLErrStr(result));
+    assert(SL_RESULT_SUCCESS == result);
+}
+
+void AudioRecorder::Start() {
+    SLresult result;
+
+    /* Enqueue buffers to map the region of memory allocated to store the recorded data */
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "Enqueueing buffer");
+    //int bufferSizeInBytes = BUFFER_SIZE_IN_FRAMES * numChannels_ * sizeof(float);
+
+    enqueBuffer();
+
+    /* ------------------------------------------------------ */
+    /* Start recording */
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "Start Recording");
+    recording_ = true;
+    result = (*recorderItf_)->SetRecordState(recorderItf_, SL_RECORDSTATE_RECORDING);
+    assert(SL_RESULT_SUCCESS == result);
+}
+
+void AudioRecorder::Stop() {
+    recording_ = false;
+
+    SLresult result;
+    result = (*recorderItf_)->SetRecordState(recorderItf_, SL_RECORDSTATE_STOPPED);
+}
+
+SLresult AudioRecorder::enqueBuffer() {
+    SLresult result;
+    int bufferSizeInBytes = numBufferSamples_ * sizeof(float);
+    // __android_log_print(ANDROID_LOG_INFO, TAG, "Enque %d bytes", bufferSizeInBytes);
+    result = (*recBuffQueueItf_)->Enqueue(recBuffQueueItf_, recBuffer, bufferSizeInBytes);
+    assert(SL_RESULT_SUCCESS == result);
+
+    return result;
+}
+
+float* AudioRecorder::GetRecordBuffer() {
+    return recBuffer;
+}
diff --git a/tests/tests/media/libndkaudio/AudioRecorder.h b/tests/tests/media/libndkaudio/AudioRecorder.h
new file mode 100644
index 0000000..93a03c3
--- /dev/null
+++ b/tests/tests/media/libndkaudio/AudioRecorder.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _AUDIORECORDER_H_
+#define _AUDIORECORDER_H_
+
+#include <SLES/OpenSLES.h>
+#include <SLES/OpenSLES_Android.h>
+
+namespace ndkaudio {
+
+class AudioSink;
+
+class AudioRecorder {
+ public:
+    AudioRecorder();
+    ~AudioRecorder();
+
+    void Open(int numChannels, AudioSink* sink);
+    void Close();
+
+    void RealizeRecorder();
+    void RealizeRoutingProxy();
+
+    void Start();
+    void Stop();
+
+    inline bool isRecording() {
+        return recording_;
+    }
+    inline AudioSink* getSink() {
+        return sink_;
+    }
+
+    SLAndroidConfigurationItf getConfigItf() {
+        return configItf_;
+    }
+
+    // public, but don't call directly (called by the OSLES callback)
+    SLresult enqueBuffer();
+
+    int GetNumBufferSamples() {
+        return numBufferSamples_;
+    }
+    float* GetRecordBuffer();
+
+ private:
+    AudioSink* sink_;
+    bool recording_;
+
+    int sampleRate_;
+    int numChannels_;
+
+    int numBufferSamples_;
+
+    // OpenSL ES stuff
+    // - Engine
+    SLObjectItf engineObj_;
+    SLEngineItf engineItf_;
+
+    // - Recorder
+    SLObjectItf recorderObj_;
+    SLRecordItf recorderItf_;
+    SLAndroidSimpleBufferQueueItf recBuffQueueItf_;
+    SLAndroidConfigurationItf configItf_;
+};
+
+} // namespace ndkaudio
+
+#endif // _AUDIORECORDER_H_
diff --git a/tests/tests/media/libndkaudio/AudioSink.h b/tests/tests/media/libndkaudio/AudioSink.h
new file mode 100644
index 0000000..933abc9
--- /dev/null
+++ b/tests/tests/media/libndkaudio/AudioSink.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _AUDIOSINK_H_
+#define _AUDIOSINK_H_
+
+namespace ndkaudio {
+
+class AudioSink {
+ public:
+    AudioSink();
+    virtual ~AudioSink();
+
+    virtual bool put(float * buff, int numFrames, int numChannels) =0;
+};
+
+}  // namespace ndkaudio
+
+#endif // _AUDIOSINK_H_
+
diff --git a/tests/tests/media/libndkaudio/AudioSource.cpp b/tests/tests/media/libndkaudio/AudioSource.cpp
new file mode 100644
index 0000000..6e4fbbc
--- /dev/null
+++ b/tests/tests/media/libndkaudio/AudioSource.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AudioSource.h"
+
+#include "SystemParams.h"
+
+namespace ndkaudio {
+
+//static const char* const TAG = "AudioSource";
+
+AudioSource::AudioSource(int numChannels)
+ : numChannels_(numChannels),
+   lastReadSize_(0),
+   numBuffFrames_(SystemParams::getNumBufferFrames())
+{}
+
+AudioSource::~AudioSource()
+{}
+
+} // namespace ndkaudio
diff --git a/tests/tests/media/libndkaudio/AudioSource.h b/tests/tests/media/libndkaudio/AudioSource.h
new file mode 100644
index 0000000..1d192b4
--- /dev/null
+++ b/tests/tests/media/libndkaudio/AudioSource.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AUDIOSOURCE_H_
+#define AUDIOSOURCE_H_
+
+namespace ndkaudio {
+
+class AudioSource {
+ public:
+    AudioSource(int numChannels);
+    virtual ~AudioSource();
+
+    int getLastReadSize() {
+        return lastReadSize_;
+    }
+    int getNumChannels() {
+        return numChannels_;
+    }
+    int getNumBufferFrames() {
+        return numBuffFrames_;
+    }
+
+    virtual int getData(long time, float * buff, int numFrames,
+                        int numChannels) =0;
+
+ protected:
+    int numChannels_;
+    int lastReadSize_;
+    int numBuffFrames_;
+};
+
+} //namespace ndkaudio
+
+#endif /* AUDIOSOURCE_H_ */
diff --git a/tests/tests/media/libndkaudio/OpenSLESUtils.cpp b/tests/tests/media/libndkaudio/OpenSLESUtils.cpp
new file mode 100644
index 0000000..7302ef5
--- /dev/null
+++ b/tests/tests/media/libndkaudio/OpenSLESUtils.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "OpenSLESUtils.h"
+
+#include <SLES/OpenSLES.h>
+#include <SLES/OpenSLES_Android.h>
+
+/*
+ * OSLES Helpers
+ */
+static const char* errStrings[] = {
+        "SL_RESULT_SUCCESS",	// 0)
+        "SL_RESULT_PRECONDITIONS_VIOLATE",  // 1
+        "SL_RESULT_PARAMETER_INVALID",      // 2
+        "SL_RESULT_MEMORY_FAILURE",         // 3
+        "SL_RESULT_RESOURCE_ERROR",         // 4
+        "SL_RESULT_RESOURCE_LOST",          // 5
+        "SL_RESULT_IO_ERROR",               // 6
+        "SL_RESULT_BUFFER_INSUFFICIENT",    // 7
+        "SL_RESULT_CONTENT_CORRUPTED",      // 8
+        "SL_RESULT_CONTENT_UNSUPPORTED",    // 9
+        "SL_RESULT_CONTENT_NOT_FOUND",      // 10
+        "SL_RESULT_PERMISSION_DENIED",      // 11
+        "SL_RESULT_FEATURE_UNSUPPORTED",    // 12
+        "SL_RESULT_INTERNAL_ERROR",         // 13
+        "SL_RESULT_UNKNOWN_ERROR",          // 14
+        "SL_RESULT_OPERATION_ABORTED",      // 15
+        "SL_RESULT_CONTROL_LOST"            // 16
+};
+
+const char * getSLErrStr(int code) {
+    return errStrings[code];
+}
+
+// These will wind up in <SLES/OpenSLES_Android.h>
+#define SL_ANDROID_SPEAKER_QUAD (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT \
+ | SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT)
+
+#define SL_ANDROID_SPEAKER_5DOT1 (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT \
+ | SL_SPEAKER_FRONT_CENTER  | SL_SPEAKER_LOW_FREQUENCY| SL_SPEAKER_BACK_LEFT \
+ | SL_SPEAKER_BACK_RIGHT)
+
+#define SL_ANDROID_SPEAKER_7DOT1 (SL_ANDROID_SPEAKER_5DOT1 | SL_SPEAKER_SIDE_LEFT \
+ |SL_SPEAKER_SIDE_RIGHT)
+
+int chanCountToChanMask(int chanCount) {
+    int channelMask = 0;
+
+    switch (chanCount) {
+        case 1:
+            channelMask = SL_SPEAKER_FRONT_CENTER;
+            break;
+
+        case 2:
+            channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
+            break;
+
+        case 4:  // Quad
+            channelMask = SL_ANDROID_SPEAKER_QUAD;
+            break;
+
+        case 6:  // 5.1
+            channelMask = SL_ANDROID_SPEAKER_5DOT1;
+            break;
+
+        case 8:  // 7.1
+            channelMask = SL_ANDROID_SPEAKER_7DOT1;
+            break;
+    }
+    return channelMask;
+}
diff --git a/tests/tests/media/libndkaudio/OpenSLESUtils.h b/tests/tests/media/libndkaudio/OpenSLESUtils.h
new file mode 100644
index 0000000..89dde3d
--- /dev/null
+++ b/tests/tests/media/libndkaudio/OpenSLESUtils.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _OPENSLESUTILS_H_
+#define _OPENSLESUTILS_H_
+
+const char * getSLErrStr(int code);
+int chanCountToChanMask(int chanCount);
+
+#endif // _OPENSLESUTILS_H_
diff --git a/tests/tests/media/libndkaudio/PeriodicAudioSource.cpp b/tests/tests/media/libndkaudio/PeriodicAudioSource.cpp
new file mode 100644
index 0000000..a861bb8
--- /dev/null
+++ b/tests/tests/media/libndkaudio/PeriodicAudioSource.cpp
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PeriodicAudioSource.h"
+
+namespace ndkaudio {
+
+PeriodicAudioSource::PeriodicAudioSource(int numChannels)
+ : AudioSource(numChannels), targetFreq_(1000.0f) {
+}
+
+} // namespace ndkaudio
diff --git a/tests/tests/media/libndkaudio/PeriodicAudioSource.h b/tests/tests/media/libndkaudio/PeriodicAudioSource.h
new file mode 100644
index 0000000..ebb4a02
--- /dev/null
+++ b/tests/tests/media/libndkaudio/PeriodicAudioSource.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PERIODICAUDIOSOURCE_H_
+#define PERIODICAUDIOSOURCE_H_
+
+#include "AudioSource.h"
+
+namespace ndkaudio {
+
+class PeriodicAudioSource : public AudioSource {
+ public:
+    PeriodicAudioSource(int numChannels);
+
+    void setAudioFrequency(float freq) {
+        targetFreq_ = freq;
+    }
+
+    float calcCurrentFreq(long time);
+
+ protected:
+    float targetFreq_;
+};
+
+} // namespace ndkaudio
+
+#endif /* PERIODICAUDIOSOURCE_H_ */
diff --git a/tests/tests/media/libndkaudio/SystemParams.cpp b/tests/tests/media/libndkaudio/SystemParams.cpp
new file mode 100644
index 0000000..c7f58f4
--- /dev/null
+++ b/tests/tests/media/libndkaudio/SystemParams.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SystemParams.h"
+
+namespace ndkaudio {
+
+int SystemParams::sysSampleRate_ = 48000;
+int SystemParams::sysBuffFrames_ = 480;
+
+void SystemParams::init(int sysSampleRate, int sysBuffFrames) {
+    sysSampleRate_ = sysSampleRate;
+    sysBuffFrames_ = sysBuffFrames;
+}
+
+} // namespace ndkaudio
diff --git a/tests/tests/media/libndkaudio/SystemParams.h b/tests/tests/media/libndkaudio/SystemParams.h
new file mode 100644
index 0000000..96e9af0
--- /dev/null
+++ b/tests/tests/media/libndkaudio/SystemParams.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEMPARAMS_H_
+#define SYSTEMPARAMS_H_
+
+namespace ndkaudio {
+
+class SystemParams {
+ public:
+    static void init(int sysSampleRate, int sysBuffFrames);
+
+    static int getSampleRate() {
+        return sysSampleRate_;
+    }
+    static int getNumBufferFrames() {
+        return sysBuffFrames_;
+    }
+
+ private:
+    static int sysSampleRate_;
+    static int sysBuffFrames_;
+};
+
+} // namespace ndkaudio
+
+#endif /* SYSTEMPARAMS_H_ */
diff --git a/tests/tests/media/libndkaudio/WaveTableGenerator.cpp b/tests/tests/media/libndkaudio/WaveTableGenerator.cpp
new file mode 100644
index 0000000..5df87e7
--- /dev/null
+++ b/tests/tests/media/libndkaudio/WaveTableGenerator.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <math.h>
+
+#include <android/log.h>
+
+#include "WaveTableGenerator.h"
+
+static const float kPI = 3.14159265359;	// close enough
+
+//static const char* const TAG = "WaveTableGenerator";
+
+namespace ndkaudio {
+
+float* WaveTableGenerator::genSinWave(int size, float maxValue) {
+    return genSinWave(size, maxValue, new float[size]);
+}
+
+float* WaveTableGenerator::genSinWave(int size, float maxValue, float* tbl) {
+    float incr = (kPI * 2.0f) / (float) size;
+    float val = 0.0f;
+    for (int index = 0; index < size; index++) {
+        tbl[index] = (float) sin(val) * maxValue;
+        val += incr;
+    }
+
+    return tbl;
+}
+
+} // namespace ndkaudio
diff --git a/tests/tests/media/libndkaudio/WaveTableGenerator.h b/tests/tests/media/libndkaudio/WaveTableGenerator.h
new file mode 100644
index 0000000..fbe188a
--- /dev/null
+++ b/tests/tests/media/libndkaudio/WaveTableGenerator.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WAVETABLEGENERATOR_H_
+#define WAVETABLEGENERATOR_H_
+
+namespace ndkaudio {
+
+class WaveTableGenerator {
+ public:
+    // SINE
+    static float* genSinWave(int size, float maxValue);
+    static float* genSinWave(int size, float maxValue, float* tbl);
+};
+
+}  // namespace ndkaudio
+
+#endif /* WAVETABLEGENERATOR_H_ */
diff --git a/tests/tests/media/libndkaudio/WaveTableOscillator.cpp b/tests/tests/media/libndkaudio/WaveTableOscillator.cpp
new file mode 100644
index 0000000..2b7f850
--- /dev/null
+++ b/tests/tests/media/libndkaudio/WaveTableOscillator.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/log.h>
+
+//static const char * const TAG = "WaveTableOscillator";
+
+#include "WaveTableOscillator.h"
+#include "SystemParams.h"
+
+namespace ndkaudio {
+
+WaveTableOscillator::WaveTableOscillator(int numChannels, float* waveTable,
+                                         int waveTableSize)
+ : PeriodicAudioSource(numChannels),
+   waveTable_(waveTable),
+   waveTableSize_(waveTableSize),
+   fN_(0.0f),
+   srcPhase_(0.0f),
+   prevFillTime_(0)
+{
+    setWaveTable(waveTable, waveTableSize);
+}
+
+void WaveTableOscillator::setWaveTable(float* waveTable, int waveTableSize) {
+    waveTable_ = waveTable;
+    waveTableSize_ = waveTableSize - 1;
+
+    // The frequency that would be played if we took every sample from the table and
+    // played it at the system sample-rate. The "Nominal" frequency
+    fN_ = SystemParams::getSampleRate() / (float) waveTableSize_;
+}
+
+int WaveTableOscillator::getData(long time, float* outBuff, int numFrames,
+                                 int /*outChans*/) {
+    prevFillTime_ = time;
+
+    // Frequency - main
+    float currentFreq = targetFreq_;
+
+    float phaseIncr = currentFreq / fN_;
+
+//	__android_log_print(ANDROID_LOG_INFO, TAG, "getData() freq:%f, fN_:%f, phs:%f incr:%f", currentFreq, fN_, srcPhase_, phaseIncr);
+
+    if (numChannels_ == 1) {
+        // calculate wave values
+        for (int dstIndex = 0; dstIndex < numFrames; ++dstIndex) {
+            // 'mod' back into the waveTable
+            if (srcPhase_ >= (float) waveTableSize_) {
+                srcPhase_ -= (float) waveTableSize_;
+            }
+
+            // linear-interpolate
+            int srcIndex = (int) srcPhase_;
+            float delta0 = srcPhase_ - srcIndex;
+            float delta1 = 1.0f - delta0;
+            outBuff[dstIndex] = ((waveTable_[srcIndex] * delta1)
+                    + (waveTable_[srcIndex + 1] * delta0)) / 2.0f;
+
+            srcPhase_ += phaseIncr;
+        }
+    } else if (numChannels_ == 2) {
+        // calculate wave values
+        int dstIndex = 0;
+        for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
+            // 'mod' back into the waveTable
+            if (srcPhase_ >= (float) waveTableSize_) {
+                srcPhase_ -= (float) waveTableSize_;
+            }
+
+            // linear-interpolate
+            int srcIndex = (int) srcPhase_;
+            float delta0 = srcPhase_ - srcIndex;
+            float delta1 = 1.0f - delta0;
+            float out = ((waveTable_[srcIndex] * delta1)
+                    + (waveTable_[srcIndex + 1] * delta0)) / 2.0f;
+
+            outBuff[dstIndex++] = out;
+            outBuff[dstIndex++] = out;
+
+            srcPhase_ += phaseIncr;
+        }
+    }
+
+//	__android_log_print(ANDROID_LOG_INFO, TAG, "    %d samples", numSamples);
+    return numFrames;
+}
+
+} // namespace ndkaudio
diff --git a/tests/tests/media/libndkaudio/WaveTableOscillator.h b/tests/tests/media/libndkaudio/WaveTableOscillator.h
new file mode 100644
index 0000000..aaccaf3
--- /dev/null
+++ b/tests/tests/media/libndkaudio/WaveTableOscillator.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WAVETABLEOSCILLATOR_H_
+#define WAVETABLEOSCILLATOR_H_
+
+#include "PeriodicAudioSource.h"
+
+namespace ndkaudio {
+
+/*
+ * The assumption here is that the provided wave table contains 1 cycle of the wave
+ * and that the first and last samples are the same.
+ */
+class WaveTableOscillator : public PeriodicAudioSource {
+ public:
+    WaveTableOscillator(int numChannels, float* waveTable, int waveTableSize);
+
+    void setWaveTable(float* waveTable, int waveTableSize);
+
+    int getData(long time, float* outBuff, int numFrames, int outChans);
+
+ private:
+    float* waveTable_;
+    int waveTableSize_;
+
+    // 'nominal' frequency (i.e. how many times we step through the
+    // 1-cycle wave table in a second
+    float fN_;
+
+    // current pointer into the wave table
+    float srcPhase_;
+
+    // profiling
+    long prevFillTime_;
+};
+
+} // namespace ndkaudio
+
+#endif /* WAVETABLEOSCILLATOR_H_ */
diff --git a/tests/tests/media/libndkaudio/com_android_ndkaudio_AudioPlayer.cpp b/tests/tests/media/libndkaudio/com_android_ndkaudio_AudioPlayer.cpp
new file mode 100644
index 0000000..a5b480e
--- /dev/null
+++ b/tests/tests/media/libndkaudio/com_android_ndkaudio_AudioPlayer.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <android/log.h>
+
+#include "com_android_ndkaudio_AudioPlayer.h"
+
+#include "AudioPlayer.h"
+#include "WaveTableGenerator.h"
+#include "WaveTableOscillator.h"
+#include "SystemParams.h"
+
+static const char* TAG = "_com_android_ndkaudio_AudioPlayer_";
+
+using namespace ndkaudio;
+
+static int numChannels = 2;
+static int waveTableSize = 0;
+static float * waveTable = 0;
+
+static WaveTableOscillator* waveTableSource;
+static AudioPlayer* nativePlayer;
+
+static SLresult lastSLResult = 0;
+
+extern "C" {
+
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioPlayer_Create(JNIEnv*, jobject) {
+  __android_log_print(ANDROID_LOG_INFO, TAG, "AudioPlayer_Create() ...");
+
+  if (nativePlayer == 0) {
+      waveTableSize = SystemParams::getNumBufferFrames();
+      waveTable = WaveTableGenerator::genSinWave(waveTableSize, 1.0f);
+      waveTableSource = new WaveTableOscillator(numChannels, waveTable, waveTableSize);
+
+      nativePlayer = new AudioPlayer();
+      nativePlayer->Open(numChannels, waveTableSource);
+  }
+}
+
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioPlayer_Destroy(JNIEnv*, jobject) {
+  __android_log_print(ANDROID_LOG_INFO, TAG, "AudioPlayer_Destroy() ...");
+  nativePlayer->Close();
+}
+
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioPlayer_RealizePlayer(JNIEnv*, jobject) {
+    __android_log_print(ANDROID_LOG_INFO, TAG, "AudioPlayer_RealizePlayer() ...");
+    nativePlayer->RealizePlayer();
+  }
+
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioPlayer_RealizeRoutingProxy(JNIEnv*, jobject) {
+    __android_log_print(ANDROID_LOG_INFO, TAG, "AudioPlayer_RealizeRoutingProxy() ...");
+    nativePlayer->RealizeRoutingProxy();
+  }
+
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioPlayer_Start(JNIEnv*, jobject) {
+  __android_log_print(ANDROID_LOG_INFO, TAG, "AudioPlayer_Start() ...");
+  nativePlayer->Start();
+}
+
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioPlayer_Stop(JNIEnv*, jobject) {
+  __android_log_print(ANDROID_LOG_INFO, TAG, "AudioPlayer_Stop() ...");
+  nativePlayer->Stop();
+}
+
+JNIEXPORT jobject JNICALL Java_com_android_ndkaudio_AudioPlayer_GetRoutingInterface(JNIEnv*, jobject) {
+  __android_log_print(ANDROID_LOG_INFO, TAG, "AudioPlayer_GetRoutingInterface() ...");
+
+  SLAndroidConfigurationItf configItf = nativePlayer->getConfigItf();
+  __android_log_print(ANDROID_LOG_INFO, TAG, "  configItf:%p", configItf);
+  jobject routingObj = 0;
+  lastSLResult = (*configItf)->AcquireJavaProxy(configItf, SL_ANDROID_JAVA_PROXY_ROUTING, &routingObj);
+  __android_log_print(ANDROID_LOG_INFO, TAG, "  routingObj:%p", routingObj);
+  return routingObj;
+}
+
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioPlayer_ReleaseRoutingInterface(JNIEnv*, jobject, jobject /*proxyObj*/) {
+  __android_log_print(ANDROID_LOG_INFO, TAG, "AudioPlayer_ReleaseRoutingInterface() ...");
+
+  SLAndroidConfigurationItf configItf = nativePlayer->getConfigItf();
+  lastSLResult = (*configItf)->ReleaseJavaProxy(configItf, SL_ANDROID_JAVA_PROXY_ROUTING/*, proxyObj*/);
+}
+
+JNIEXPORT long JNICALL Java_com_android_ndkaudio_AudioPlayer_GetLastSLResult(JNIEnv*, jobject) {
+    return lastSLResult;
+}
+
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioPlayer_ClearLastSLResult(JNIEnv*, jobject) {
+    lastSLResult = 0;
+}
+
+} // extern "C"
diff --git a/tests/tests/media/libndkaudio/com_android_ndkaudio_AudioPlayer.h b/tests/tests/media/libndkaudio/com_android_ndkaudio_AudioPlayer.h
new file mode 100644
index 0000000..e01d3ac
--- /dev/null
+++ b/tests/tests/media/libndkaudio/com_android_ndkaudio_AudioPlayer.h
@@ -0,0 +1,99 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_android_ndkaudio_AudioPlayer */
+
+#ifndef _Included_com_android_ndkaudio_AudioPlayer
+#define _Included_com_android_ndkaudio_AudioPlayer
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     com_android_ndkaudio_AudioPlayer
+ * Method:    InitN
+ * Signature: ()V
+ */
+
+/*
+ * Class:     com_android_ndkaudio_AudioPlayer
+ * Method:    Create
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioPlayer_Create
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     com_android_ndkaudio_AudioPlayer
+ * Method:    Destroy
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioPlayer_Destroy
+  (JNIEnv*, jobject);
+
+/*
+ * Class:     com_android_ndkaudio_AudioPlayer
+ * Method:    RealizePlayer
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioPlayer_RealizePlayer
+  (JNIEnv*, jobject);
+
+/*
+ * Class:     com_android_ndkaudio_AudioPlayer
+ * Method:    RealizeRoutingProxy
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioPlayer_RealizeRoutingProxy
+  (JNIEnv*, jobject);
+
+/*
+ * Class:     com_android_ndkaudio_AudioPlayer
+ * Method:    Start
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioPlayer_Start
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     com_android_ndkaudio_AudioPlayer
+ * Method:    Stop
+ * Signature: ()android/
+ */
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioPlayer_Stop
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     com_android_ndkaudio_AudioPlayer
+ * Method:    GetRoutingInterface
+ * Signature: ()Landroid/media/AudioRouting;
+ */
+JNIEXPORT jobject JNICALL Java_com_android_ndkaudio_AudioPlayer_GetRoutingInterface
+  (JNIEnv*, jobject);
+
+/*
+ * Class:     com_android_ndkaudio_AudioPlayer
+ * Method:    GetRoutingInterface
+ * Signature: (Landroid/media/AudioRouting;)V
+ */
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioPlayer_ReleaseRoutingInterface
+  (JNIEnv*, jobject, jobject);
+
+/*
+ * Class:     com_android_ndkaudio_AudioPlayer
+ * Method:    GetLastSLResult
+ * Signature: ()J
+ */
+JNIEXPORT long JNICALL Java_com_android_ndkaudio_AudioPlayer_GetLastSLResult
+  (JNIEnv*, jobject);
+
+/*
+ * Class:     com_android_ndkaudio_AudioPlayer
+ * Method:    ClearLastSLResult
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioPlayer_ClearLastSLResult
+  (JNIEnv*, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/tests/tests/media/libndkaudio/com_android_ndkaudio_AudioRecorder.cpp b/tests/tests/media/libndkaudio/com_android_ndkaudio_AudioRecorder.cpp
new file mode 100644
index 0000000..e7b6abd
--- /dev/null
+++ b/tests/tests/media/libndkaudio/com_android_ndkaudio_AudioRecorder.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <android/log.h>
+
+#include "com_android_ndkaudio_AudioRecorder.h"
+
+#include "AudioRecorder.h"
+
+using namespace ndkaudio;
+
+static const char* TAG = "_com_android_ndkaudio_AudioRecorder_";
+
+static int numChannels = 2;
+
+static AudioRecorder* nativeRecorder;
+
+static SLresult lastSLResult = 0;
+extern "C" {
+
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioRecorder_Create(JNIEnv*, jobject) {
+  __android_log_print(ANDROID_LOG_INFO, TAG, "AudioRecorder_Create() ...");
+  if (nativeRecorder == 0) {
+      nativeRecorder = new AudioRecorder();
+  }
+  nativeRecorder->Open(numChannels, 0);
+}
+
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioRecorder_Destroy(JNIEnv*, jobject) {
+  __android_log_print(ANDROID_LOG_INFO, TAG, "AudioRecorder_Destroy() ...");
+  nativeRecorder->Close();
+  delete nativeRecorder;
+  nativeRecorder = 0;
+}
+
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioRecorder_RealizeRecorder(JNIEnv*, jobject) {
+    __android_log_print(ANDROID_LOG_INFO, TAG, "AudioRecorder_RealizePlayer() ...");
+    nativeRecorder->RealizeRecorder();
+  }
+
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioRecorder_RealizeRoutingProxy(JNIEnv*, jobject) {
+    __android_log_print(ANDROID_LOG_INFO, TAG, "RealizeRoutingProxy ...");
+    nativeRecorder->RealizeRoutingProxy();
+  }
+
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioRecorder_Start(JNIEnv *, jobject) {
+  __android_log_print(ANDROID_LOG_INFO, TAG, "AudioRecorder_Start() ...");
+  nativeRecorder->Start();
+}
+
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioRecorder_Stop(JNIEnv *, jobject) {
+  __android_log_print(ANDROID_LOG_INFO, TAG, "AudioRecorder_Stop() ...");
+  nativeRecorder->Stop();
+}
+
+JNIEXPORT jobject JNICALL Java_com_android_ndkaudio_AudioRecorder_GetRoutingInterface(JNIEnv*, jobject) {
+  __android_log_print(ANDROID_LOG_INFO, TAG, "AudioPlayer_GetRoutingObj() ...");
+
+  SLAndroidConfigurationItf configItf = nativeRecorder->getConfigItf();
+  jobject routingObj = 0;
+  lastSLResult = (*configItf)->AcquireJavaProxy(configItf, SL_ANDROID_JAVA_PROXY_ROUTING, &routingObj);
+  __android_log_print(ANDROID_LOG_INFO, TAG, "  routingObj:%p", routingObj);
+  return routingObj;
+}
+
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioRecorder_ReleaseRoutingInterface(JNIEnv*, jobject, jobject /*proxyObj*/) {
+  __android_log_print(ANDROID_LOG_INFO, TAG, "AudioPlayer_GetRoutingObj() ...");
+
+  SLAndroidConfigurationItf configItf = nativeRecorder->getConfigItf();
+  lastSLResult = (*configItf)->ReleaseJavaProxy(configItf, SL_ANDROID_JAVA_PROXY_ROUTING/*, proxyObj*/);
+}
+
+JNIEXPORT jint JNICALL Java_com_android_ndkaudio_AudioRecorder_GetNumBufferSamples(JNIEnv*, jobject) {
+    return nativeRecorder->GetNumBufferSamples();
+}
+
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioRecorder_GetBufferData(JNIEnv* jEnv, jobject, jfloatArray j_data) {
+    float* dataBuffer = nativeRecorder->GetRecordBuffer();
+    if (dataBuffer != 0) {
+        jEnv->SetFloatArrayRegion(j_data, 0, nativeRecorder->GetNumBufferSamples(), dataBuffer);
+    }
+}
+
+JNIEXPORT long JNICALL Java_com_android_ndkaudio_AudioRecorder_GetLastSLResult(JNIEnv*, jobject) {
+    return lastSLResult;
+}
+
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioRecorder_ClearLastSLResult(JNIEnv*, jobject) {
+    lastSLResult = 0;
+}
+
+} // extern "C"
diff --git a/tests/tests/media/libndkaudio/com_android_ndkaudio_AudioRecorder.h b/tests/tests/media/libndkaudio/com_android_ndkaudio_AudioRecorder.h
new file mode 100644
index 0000000..d35d4b0
--- /dev/null
+++ b/tests/tests/media/libndkaudio/com_android_ndkaudio_AudioRecorder.h
@@ -0,0 +1,109 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_android_ndkaudio_AudioRecorder */
+
+#ifndef _Included_com_android_ndkaudio_AudioRecorder
+#define _Included_com_android_ndkaudio_AudioRecorder
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     com_android_ndkaudio_AudioRecorder
+ * Method:    Create
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioRecorder_Create
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     com_android_ndkaudio_AudioRecorder
+ * Method:    Destroy
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioRecorder_Destroy
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     com_android_ndkaudio_AudioRecorder
+ * Method:    RealizeRecorder
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioRecorder_RealizeRecorder
+  (JNIEnv*, jobject);
+
+/*
+ * Class:     com_android_ndkaudio_AudioRecorder
+ * Method:    RealizeRoutingProxy
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioRecorder_RealizeRoutingProxy
+  (JNIEnv*, jobject);
+
+/*
+ * Class:     com_android_ndkaudio_AudioRecorder
+ * Method:    Start
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioRecorder_Start
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     com_android_ndkaudio_AudioRecorder
+ * Method:    Stop
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioRecorder_Stop
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     com_android_ndkaudio_AudioRecorder
+ * Method:    GetRoutingInterface
+ * Signature: ()Landroid/media/AudioRouting;
+ */
+JNIEXPORT jobject JNICALL Java_com_android_ndkaudio_AudioRecorder_GetRoutingInterface
+  (JNIEnv*, jobject);
+
+/*
+ * Class:     com_android_ndkaudio_AudioRecorder
+ * Method:    ReleaseRoutingInterface
+ * Signature: (Landroid/media/AudioRouting;)V
+ */
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioRecorder_ReleaseRoutingInterface
+  (JNIEnv*, jobject, jobject);
+
+/*
+ * Class:     com_android_ndkaudio_AudioRecorder
+ * Method:    GetNumBufferFrames
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_android_ndkaudio_AudioRecorder_GetNumBufferFrames
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     com_android_ndkaudio_AudioRecorder
+ * Method:    GetBufferData
+ * Signature: ([F)V
+ */
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioRecorder_GetBufferData
+  (JNIEnv *, jobject, jfloatArray);
+
+/*
+ * Class:     com_android_ndkaudio_AudioRecorder
+ * Method:    GetLastSLResult
+ * Signature: ()J
+ */
+JNIEXPORT long JNICALL Java_com_android_ndkaudio_AudioRecorder_GetLastSLResult
+  (JNIEnv*, jobject);
+
+/*
+ * Class:     com_android_ndkaudio_AudioRecorder
+ * Method:    ClearLastSLResult
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_android_ndkaudio_AudioRecorder_ClearLastSLResult
+  (JNIEnv*, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/tests/tests/media/libndkaudio/src/com/android/ndkaudio/AudioPlayer.java b/tests/tests/media/libndkaudio/src/com/android/ndkaudio/AudioPlayer.java
new file mode 100644
index 0000000..f9cd109
--- /dev/null
+++ b/tests/tests/media/libndkaudio/src/com/android/ndkaudio/AudioPlayer.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.ndkaudio;
+
+import android.media.AudioRouting;
+
+public class AudioPlayer {
+    public AudioPlayer() {
+        Create();
+    }
+
+    public native void Create();
+    public native void Destroy();
+
+    public native void RealizePlayer();
+    public native void RealizeRoutingProxy();
+
+    public native void Start();
+    public native void Stop();
+
+    public native AudioRouting GetRoutingInterface();
+
+    public native void ReleaseRoutingInterface(AudioRouting proxyObj);
+
+    public native long GetLastSLResult();
+    public native void ClearLastSLResult();
+}
diff --git a/tests/tests/media/libndkaudio/src/com/android/ndkaudio/AudioRecorder.java b/tests/tests/media/libndkaudio/src/com/android/ndkaudio/AudioRecorder.java
new file mode 100644
index 0000000..52d20c4
--- /dev/null
+++ b/tests/tests/media/libndkaudio/src/com/android/ndkaudio/AudioRecorder.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.ndkaudio;
+
+import android.media.AudioRouting;
+
+public class AudioRecorder {
+    public AudioRecorder() {
+        Create();
+    }
+
+    public native void Create();
+    public native void Destroy();
+
+    public native void RealizeRecorder();
+    public native void RealizeRoutingProxy();
+
+    public native void Start();
+    public native void Stop();
+
+    public native AudioRouting GetRoutingInterface();
+    public native void ReleaseRoutingInterface(AudioRouting proxyObj);
+
+    public native int GetNumBufferSamples();
+    public native void GetBufferData(float[] dstBuff);
+
+    public native long GetLastSLResult();
+    public native void ClearLastSLResult();
+}
diff --git a/tests/tests/media/res/raw/sine1khzm40db.wav b/tests/tests/media/res/raw/sine1khzm40db.wav
index ba541c4..b653a77 100644
--- a/tests/tests/media/res/raw/sine1khzm40db.wav
+++ b/tests/tests/media/res/raw/sine1khzm40db.wav
Binary files differ
diff --git a/tests/tests/media/src/android/media/cts/AudioManagerTest.java b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
index 16b1cf3..c78f82a 100644
--- a/tests/tests/media/src/android/media/cts/AudioManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
@@ -35,8 +35,6 @@
 import static android.media.AudioManager.VIBRATE_TYPE_RINGER;
 import static android.provider.Settings.System.SOUND_EFFECTS_ENABLED;
 
-import android.media.cts.R;
-
 import android.content.Context;
 import android.content.res.Resources;
 import android.media.AudioManager;
@@ -48,8 +46,6 @@
 import android.test.InstrumentationTestCase;
 import android.view.SoundEffectConstants;
 
-import java.util.TreeMap;
-
 public class AudioManagerTest extends InstrumentationTestCase {
 
     private final static int MP3_TO_PLAY = R.raw.testmp3;
@@ -184,294 +180,417 @@
         if (mUseFixedVolume || !mHasVibrator) {
             return;
         }
-        // VIBRATE_SETTING_ON
-        mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ON);
-        assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
-                mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
-        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
-        assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+        try {
+            Utils.toggleNotificationPolicyAccess(
+                    mContext.getPackageName(), getInstrumentation(), true);
+            // VIBRATE_SETTING_ON
+            mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ON);
+            assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
+                    mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
+            mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+            assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
 
-        mAudioManager.setRingerMode(RINGER_MODE_SILENT);
-        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+            mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+            assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
 
-        mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
-        assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
-                mAudioManager.getRingerMode());
-        assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+            mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+            assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
+                    mAudioManager.getRingerMode());
+            assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
 
-        // VIBRATE_SETTING_OFF
-        mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_OFF);
-        assertEquals(VIBRATE_SETTING_OFF,
-                mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
-        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
-        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+            // VIBRATE_SETTING_OFF
+            mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_OFF);
+            assertEquals(VIBRATE_SETTING_OFF,
+                    mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
+            mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+            assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
 
-        mAudioManager.setRingerMode(RINGER_MODE_SILENT);
-        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+            mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+            assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
 
-        mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
-        assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
-                mAudioManager.getRingerMode());
-        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+            mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+            assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
+                    mAudioManager.getRingerMode());
+            assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
 
-        // VIBRATE_SETTING_ONLY_SILENT
-        mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ONLY_SILENT);
-        assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
-                mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
-        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
-        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+            // VIBRATE_SETTING_ONLY_SILENT
+            mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ONLY_SILENT);
+            assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
+                    mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
+            mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+            assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
 
-        mAudioManager.setRingerMode(RINGER_MODE_SILENT);
-        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+            mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+            assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
 
-        mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
-        assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
-                mAudioManager.getRingerMode());
-        assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+            mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+            assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
+                    mAudioManager.getRingerMode());
+            assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
 
-        // VIBRATE_TYPE_NOTIFICATION
-        mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ON);
-        assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
-                mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
-        mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_OFF);
-        assertEquals(VIBRATE_SETTING_OFF, mAudioManager
-                .getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
-        mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ONLY_SILENT);
-        assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
-                mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
+            // VIBRATE_TYPE_NOTIFICATION
+            mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ON);
+            assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
+                    mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
+            mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_OFF);
+            assertEquals(VIBRATE_SETTING_OFF, mAudioManager
+                    .getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
+            mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ONLY_SILENT);
+            assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
+                    mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
+        } finally {
+            Utils.toggleNotificationPolicyAccess(
+                    mContext.getPackageName(), getInstrumentation(), false);
+        }
     }
 
     public void testVibrateRinger() throws Exception {
         if (mUseFixedVolume || !mHasVibrator) {
             return;
         }
-        // VIBRATE_TYPE_RINGER
-        mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ON);
-        assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
-                mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
-        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
-        assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+        try {
+            Utils.toggleNotificationPolicyAccess(
+                    mContext.getPackageName(), getInstrumentation(), true);
+            // VIBRATE_TYPE_RINGER
+            mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ON);
+            assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
+                    mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
+            mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+            assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
 
-        mAudioManager.setRingerMode(RINGER_MODE_SILENT);
-        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+            mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+            assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
 
-        mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
-        assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
-                mAudioManager.getRingerMode());
-        assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+            mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+            assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
+                    mAudioManager.getRingerMode());
+            assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
 
-        // VIBRATE_SETTING_OFF
-        mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_OFF);
-        assertEquals(VIBRATE_SETTING_OFF, mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
-        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
-        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+            // VIBRATE_SETTING_OFF
+            mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_OFF);
+            assertEquals(VIBRATE_SETTING_OFF, mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
+            mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+            assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
 
-        mAudioManager.setRingerMode(RINGER_MODE_SILENT);
-        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+            mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+            assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
 
-        mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
-        assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
-                mAudioManager.getRingerMode());
-        // Note: as of Froyo, if VIBRATE_TYPE_RINGER is set to OFF, it will
-        // not vibrate, even in RINGER_MODE_VIBRATE. This allows users to
-        // disable the vibration for incoming calls only.
-        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+            mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+            assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
+                    mAudioManager.getRingerMode());
+            // Note: as of Froyo, if VIBRATE_TYPE_RINGER is set to OFF, it will
+            // not vibrate, even in RINGER_MODE_VIBRATE. This allows users to
+            // disable the vibration for incoming calls only.
+            assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
 
-        // VIBRATE_SETTING_ONLY_SILENT
-        mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ONLY_SILENT);
-        assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
-                mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
-        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
-        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+            // VIBRATE_SETTING_ONLY_SILENT
+            mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ONLY_SILENT);
+            assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
+                    mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
+            mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+            assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
 
-        mAudioManager.setRingerMode(RINGER_MODE_SILENT);
-        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+            mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+            assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
 
-        mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
-        assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
-                mAudioManager.getRingerMode());
-        assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+            mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+            assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
+                    mAudioManager.getRingerMode());
+            assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
 
-        // VIBRATE_TYPE_NOTIFICATION
-        mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ON);
-        assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
-                mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
-        mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_OFF);
-        assertEquals(VIBRATE_SETTING_OFF, mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
-        mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ONLY_SILENT);
-        assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
-                mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
+            // VIBRATE_TYPE_NOTIFICATION
+            mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ON);
+            assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
+                    mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
+            mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_OFF);
+            assertEquals(VIBRATE_SETTING_OFF, mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
+            mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ONLY_SILENT);
+            assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
+                    mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
+        } finally {
+            Utils.toggleNotificationPolicyAccess(
+                    mContext.getPackageName(), getInstrumentation(), false);
+        }
     }
 
     public void testAccessRingMode() throws Exception {
-        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
-        assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
-
-        mAudioManager.setRingerMode(RINGER_MODE_SILENT);
-        // AudioService#setRingerMode() has:
-        // if (isTelevision) return;
-        if (mUseFixedVolume || mIsTelevision) {
+        try {
+            Utils.toggleNotificationPolicyAccess(
+                    mContext.getPackageName(), getInstrumentation(), true);
+            mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
             assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
-        } else {
+
+            mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+            // AudioService#setRingerMode() has:
+            // if (isTelevision) return;
+            if (mUseFixedVolume || mIsTelevision) {
+                assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
+            } else {
+                assertEquals(RINGER_MODE_SILENT, mAudioManager.getRingerMode());
+            }
+
+            mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+            if (mUseFixedVolume || mIsTelevision) {
+                assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
+            } else {
+                assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
+                        mAudioManager.getRingerMode());
+            }
+        } finally {
+            Utils.toggleNotificationPolicyAccess(
+                    mContext.getPackageName(), getInstrumentation(), false);
+        }
+    }
+
+    public void testSetRingerModePolicyAccess() throws Exception {
+        try {
+            // Apps without policy access cannot change silent -> normal or silent -> vibrate.
+            Utils.toggleNotificationPolicyAccess(
+                    mContext.getPackageName(), getInstrumentation(), true);
+            mAudioManager.setRingerMode(RINGER_MODE_SILENT);
             assertEquals(RINGER_MODE_SILENT, mAudioManager.getRingerMode());
-        }
+            Utils.toggleNotificationPolicyAccess(
+                    mContext.getPackageName(), getInstrumentation(), false);
 
-        mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
-        if (mUseFixedVolume || mIsTelevision) {
+            try {
+                mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+                fail("Apps without notification policy access cannot change ringer mode");
+            } catch (SecurityException e) {
+            }
+
+            try {
+                mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+                fail("Apps without notification policy access cannot change ringer mode");
+            } catch (SecurityException e) {
+            }
+
+            // Apps without policy access cannot change normal -> silent.
+            Utils.toggleNotificationPolicyAccess(
+                    mContext.getPackageName(), getInstrumentation(), true);
+            mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
             assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
-        } else {
-            assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
-                    mAudioManager.getRingerMode());
+            Utils.toggleNotificationPolicyAccess(
+                    mContext.getPackageName(), getInstrumentation(), false);
+
+            try {
+                mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+                fail("Apps without notification policy access cannot change ringer mode");
+            } catch (SecurityException e) {
+            }
+            assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
+
+            // Apps without policy access cannot change vibrate -> silent.
+            Utils.toggleNotificationPolicyAccess(
+                    mContext.getPackageName(), getInstrumentation(), true);
+            mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+            assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode());
+            Utils.toggleNotificationPolicyAccess(
+                    mContext.getPackageName(), getInstrumentation(), false);
+
+            try {
+                mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+                fail("Apps without notification policy access cannot change ringer mode");
+            } catch (SecurityException e) {
+            }
+
+            // Apps without policy access can change vibrate -> normal and vice versa.
+            assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode());
+            mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+            assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
+            mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+            assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode());
+        } finally {
+            Utils.toggleNotificationPolicyAccess(
+                    mContext.getPackageName(), getInstrumentation(), false);
         }
     }
 
+    public void testVolumeDndAffectedStream() throws Exception {
+        if (mUseFixedVolume || mHasVibrator) {
+            return;
+        }
+        Utils.toggleNotificationPolicyAccess(
+                mContext.getPackageName(), getInstrumentation(), true);
+        mAudioManager.setStreamVolume(
+                AudioManager.STREAM_SYSTEM, 7, AudioManager.FLAG_ALLOW_RINGER_MODES);
+        mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
+        Utils.toggleNotificationPolicyAccess(
+                mContext.getPackageName(), getInstrumentation(), false);
+        // 7 to 0, fail.
+        try {
+            mAudioManager.setStreamVolume(
+                    AudioManager.STREAM_SYSTEM, 0, AudioManager.FLAG_ALLOW_RINGER_MODES);
+            fail("Apps without notification policy access cannot change ringer mode");
+        } catch (SecurityException e) {}
+
+        // 7 to 1: success
+        mAudioManager.setStreamVolume(
+                AudioManager.STREAM_SYSTEM, 1, AudioManager.FLAG_ALLOW_RINGER_MODES);
+        assertEquals("setStreamVolume did not change volume",
+                1, mAudioManager.getStreamVolume(AudioManager.STREAM_SYSTEM));
+
+        // 0 to non-zero: fail.
+        Utils.toggleNotificationPolicyAccess(
+                mContext.getPackageName(), getInstrumentation(), true);
+        mAudioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
+        mAudioManager.setStreamVolume(
+                AudioManager.STREAM_SYSTEM, 0, AudioManager.FLAG_ALLOW_RINGER_MODES);
+        Utils.toggleNotificationPolicyAccess(
+                mContext.getPackageName(), getInstrumentation(), false);
+
+        try {
+            mAudioManager.setStreamVolume(
+                    AudioManager.STREAM_SYSTEM, 6, AudioManager.FLAG_ALLOW_RINGER_MODES);
+            fail("Apps without notification policy access cannot change ringer mode");
+        } catch (SecurityException e) {}
+    }
+
     public void testVolume() throws Exception {
-        int volume, volumeDelta;
-        int[] streams = { AudioManager.STREAM_ALARM,
-                          AudioManager.STREAM_MUSIC,
-                          AudioManager.STREAM_VOICE_CALL,
-                          AudioManager.STREAM_RING };
+        try {
+            Utils.toggleNotificationPolicyAccess(
+                    mContext.getPackageName(), getInstrumentation(), true);
+            int volume, volumeDelta;
+            int[] streams = {AudioManager.STREAM_ALARM,
+                    AudioManager.STREAM_MUSIC,
+                    AudioManager.STREAM_VOICE_CALL,
+                    AudioManager.STREAM_RING};
 
-        mAudioManager.adjustVolume(ADJUST_RAISE, 0);
-        mAudioManager.adjustSuggestedStreamVolume(
-                ADJUST_LOWER, USE_DEFAULT_STREAM_TYPE, 0);
-        int maxMusicVolume = mAudioManager.getStreamMaxVolume(STREAM_MUSIC);
+            mAudioManager.adjustVolume(ADJUST_RAISE, 0);
+            mAudioManager.adjustSuggestedStreamVolume(
+                    ADJUST_LOWER, USE_DEFAULT_STREAM_TYPE, 0);
+            int maxMusicVolume = mAudioManager.getStreamMaxVolume(STREAM_MUSIC);
 
-        for (int i = 0; i < streams.length; i++) {
-            // set ringer mode to back normal to not interfere with volume tests
-            mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+            for (int i = 0; i < streams.length; i++) {
+                // set ringer mode to back normal to not interfere with volume tests
+                mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
 
-            int maxVolume = mAudioManager.getStreamMaxVolume(streams[i]);
-            int minVolume = mAudioManager.getStreamMinVolume(streams[i]);
+                int maxVolume = mAudioManager.getStreamMaxVolume(streams[i]);
+                int minVolume = mAudioManager.getStreamMinVolume(streams[i]);
 
-            // validate min
-            assertTrue(String.format("minVolume(%d) must be >= 0", minVolume), minVolume >= 0);
-            assertTrue(String.format("minVolume(%d) must be < maxVolume(%d)", minVolume, maxVolume),
-                    minVolume < maxVolume);
+                // validate min
+                assertTrue(String.format("minVolume(%d) must be >= 0", minVolume), minVolume >= 0);
+                assertTrue(String.format("minVolume(%d) must be < maxVolume(%d)", minVolume,
+                        maxVolume),
+                        minVolume < maxVolume);
 
-            mAudioManager.setStreamVolume(streams[i], 1, 0);
-            if (mUseFixedVolume) {
-                assertEquals(maxVolume, mAudioManager.getStreamVolume(streams[i]));
-                continue;
-            }
-            assertEquals(1, mAudioManager.getStreamVolume(streams[i]));
+                mAudioManager.setStreamVolume(streams[i], 1, 0);
+                if (mUseFixedVolume) {
+                    assertEquals(maxVolume, mAudioManager.getStreamVolume(streams[i]));
+                    continue;
+                }
+                assertEquals(1, mAudioManager.getStreamVolume(streams[i]));
 
-            if (streams[i] == AudioManager.STREAM_MUSIC && mAudioManager.isWiredHeadsetOn()) {
-                // due to new regulations, music sent over a wired headset may be volume limited
-                // until the user explicitly increases the limit, so we can't rely on being able
-                // to set the volume to getStreamMaxVolume(). Instead, determine the current limit
-                // by increasing the volume until it won't go any higher, then use that volume as
-                // the maximum for the purposes of this test
-                int curvol = 0;
-                int prevvol = 0;
-                do {
-                    prevvol = curvol;
-                    mAudioManager.adjustStreamVolume(streams[i], ADJUST_RAISE, 0);
-                    curvol = mAudioManager.getStreamVolume(streams[i]);
-                } while (curvol != prevvol);
-                maxVolume = maxMusicVolume = curvol;
-            }
-            mAudioManager.setStreamVolume(streams[i], maxVolume, 0);
-            mAudioManager.adjustStreamVolume(streams[i], ADJUST_RAISE, 0);
-            assertEquals(maxVolume, mAudioManager.getStreamVolume(streams[i]));
-
-            volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(streams[i]));
-            mAudioManager.adjustSuggestedStreamVolume(ADJUST_LOWER, streams[i], 0);
-            assertEquals(maxVolume - volumeDelta, mAudioManager.getStreamVolume(streams[i]));
-
-            // volume lower
-            mAudioManager.setStreamVolume(streams[i], maxVolume, 0);
-            volume = mAudioManager.getStreamVolume(streams[i]);
-            while (volume > minVolume) {
-                volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(streams[i]));
-                mAudioManager.adjustStreamVolume(streams[i], ADJUST_LOWER, 0);
-                assertEquals(Math.max(0, volume - volumeDelta),
-                             mAudioManager.getStreamVolume(streams[i]));
-                volume = mAudioManager.getStreamVolume(streams[i]);
-            }
-
-            mAudioManager.adjustStreamVolume(streams[i], ADJUST_SAME, 0);
-
-            // volume raise
-            mAudioManager.setStreamVolume(streams[i], 1, 0);
-            volume = mAudioManager.getStreamVolume(streams[i]);
-            while (volume < maxVolume) {
-                volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(streams[i]));
+                if (streams[i] == AudioManager.STREAM_MUSIC && mAudioManager.isWiredHeadsetOn()) {
+                    // due to new regulations, music sent over a wired headset may be volume limited
+                    // until the user explicitly increases the limit, so we can't rely on being able
+                    // to set the volume to getStreamMaxVolume(). Instead, determine the current limit
+                    // by increasing the volume until it won't go any higher, then use that volume as
+                    // the maximum for the purposes of this test
+                    int curvol = 0;
+                    int prevvol = 0;
+                    do {
+                        prevvol = curvol;
+                        mAudioManager.adjustStreamVolume(streams[i], ADJUST_RAISE, 0);
+                        curvol = mAudioManager.getStreamVolume(streams[i]);
+                    } while (curvol != prevvol);
+                    maxVolume = maxMusicVolume = curvol;
+                }
+                mAudioManager.setStreamVolume(streams[i], maxVolume, 0);
                 mAudioManager.adjustStreamVolume(streams[i], ADJUST_RAISE, 0);
-                assertEquals(Math.min(volume + volumeDelta, maxVolume),
-                             mAudioManager.getStreamVolume(streams[i]));
-                volume = mAudioManager.getStreamVolume(streams[i]);
-            }
-
-            // volume same
-            mAudioManager.setStreamVolume(streams[i], maxVolume, 0);
-            for (int k = 0; k < maxVolume; k++) {
-                mAudioManager.adjustStreamVolume(streams[i], ADJUST_SAME, 0);
                 assertEquals(maxVolume, mAudioManager.getStreamVolume(streams[i]));
+
+                volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(streams[i]));
+                mAudioManager.adjustSuggestedStreamVolume(ADJUST_LOWER, streams[i], 0);
+                assertEquals(maxVolume - volumeDelta, mAudioManager.getStreamVolume(streams[i]));
+
+                // volume lower
+                mAudioManager.setStreamVolume(streams[i], maxVolume, 0);
+                volume = mAudioManager.getStreamVolume(streams[i]);
+                while (volume > minVolume) {
+                    volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(streams[i]));
+                    mAudioManager.adjustStreamVolume(streams[i], ADJUST_LOWER, 0);
+                    assertEquals(Math.max(0, volume - volumeDelta),
+                            mAudioManager.getStreamVolume(streams[i]));
+                    volume = mAudioManager.getStreamVolume(streams[i]);
+                }
+
+                mAudioManager.adjustStreamVolume(streams[i], ADJUST_SAME, 0);
+
+                // volume raise
+                mAudioManager.setStreamVolume(streams[i], 1, 0);
+                volume = mAudioManager.getStreamVolume(streams[i]);
+                while (volume < maxVolume) {
+                    volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(streams[i]));
+                    mAudioManager.adjustStreamVolume(streams[i], ADJUST_RAISE, 0);
+                    assertEquals(Math.min(volume + volumeDelta, maxVolume),
+                            mAudioManager.getStreamVolume(streams[i]));
+                    volume = mAudioManager.getStreamVolume(streams[i]);
+                }
+
+                // volume same
+                mAudioManager.setStreamVolume(streams[i], maxVolume, 0);
+                for (int k = 0; k < maxVolume; k++) {
+                    mAudioManager.adjustStreamVolume(streams[i], ADJUST_SAME, 0);
+                    assertEquals(maxVolume, mAudioManager.getStreamVolume(streams[i]));
+                }
+
+                mAudioManager.setStreamVolume(streams[i], maxVolume, 0);
             }
 
-            mAudioManager.setStreamVolume(streams[i], maxVolume, 0);
+            if (mUseFixedVolume) {
+                return;
+            }
+
+            // adjust volume
+            mAudioManager.adjustVolume(ADJUST_RAISE, 0);
+
+            MediaPlayer mp = MediaPlayer.create(mContext, MP3_TO_PLAY);
+            assertNotNull(mp);
+            mp.setAudioStreamType(STREAM_MUSIC);
+            mp.setLooping(true);
+            mp.start();
+            Thread.sleep(TIME_TO_PLAY);
+            assertTrue(mAudioManager.isMusicActive());
+
+            // adjust volume as ADJUST_SAME
+            for (int k = 0; k < maxMusicVolume; k++) {
+                mAudioManager.adjustVolume(ADJUST_SAME, 0);
+                assertEquals(maxMusicVolume, mAudioManager.getStreamVolume(STREAM_MUSIC));
+            }
+
+            // adjust volume as ADJUST_RAISE
+            mAudioManager.setStreamVolume(STREAM_MUSIC, 0, 0);
+            volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(STREAM_MUSIC));
+            mAudioManager.adjustVolume(ADJUST_RAISE, 0);
+            assertEquals(Math.min(volumeDelta, maxMusicVolume),
+                    mAudioManager.getStreamVolume(STREAM_MUSIC));
+
+            // adjust volume as ADJUST_LOWER
+            mAudioManager.setStreamVolume(STREAM_MUSIC, maxMusicVolume, 0);
+            maxMusicVolume = mAudioManager.getStreamVolume(STREAM_MUSIC);
+            volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(STREAM_MUSIC));
+            mAudioManager.adjustVolume(ADJUST_LOWER, 0);
+            assertEquals(Math.max(0, maxMusicVolume - volumeDelta),
+                    mAudioManager.getStreamVolume(STREAM_MUSIC));
+
+            mp.stop();
+            mp.release();
+            Thread.sleep(TIME_TO_PLAY);
+            assertFalse(mAudioManager.isMusicActive());
+        } finally {
+            Utils.toggleNotificationPolicyAccess(
+                    mContext.getPackageName(), getInstrumentation(), false);
         }
-
-        if (mUseFixedVolume) {
-            return;
-        }
-
-        // adjust volume
-        mAudioManager.adjustVolume(ADJUST_RAISE, 0);
-
-        MediaPlayer mp = MediaPlayer.create(mContext, MP3_TO_PLAY);
-        assertNotNull(mp);
-        mp.setAudioStreamType(STREAM_MUSIC);
-        mp.setLooping(true);
-        mp.start();
-        Thread.sleep(TIME_TO_PLAY);
-        assertTrue(mAudioManager.isMusicActive());
-
-        // adjust volume as ADJUST_SAME
-        for (int k = 0; k < maxMusicVolume; k++) {
-            mAudioManager.adjustVolume(ADJUST_SAME, 0);
-            assertEquals(maxMusicVolume, mAudioManager.getStreamVolume(STREAM_MUSIC));
-        }
-
-        // adjust volume as ADJUST_RAISE
-        mAudioManager.setStreamVolume(STREAM_MUSIC, 0, 0);
-        volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(STREAM_MUSIC));
-        mAudioManager.adjustVolume(ADJUST_RAISE, 0);
-        assertEquals(Math.min(volumeDelta, maxMusicVolume),
-                     mAudioManager.getStreamVolume(STREAM_MUSIC));
-
-        // adjust volume as ADJUST_LOWER
-        mAudioManager.setStreamVolume(STREAM_MUSIC, maxMusicVolume, 0);
-        maxMusicVolume = mAudioManager.getStreamVolume(STREAM_MUSIC);
-        volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(STREAM_MUSIC));
-        mAudioManager.adjustVolume(ADJUST_LOWER, 0);
-        assertEquals(Math.max(0, maxMusicVolume - volumeDelta),
-                     mAudioManager.getStreamVolume(STREAM_MUSIC));
-
-        mp.stop();
-        mp.release();
-        Thread.sleep(TIME_TO_PLAY);
-        assertFalse(mAudioManager.isMusicActive());
     }
 
-    public void testMute() {
+    public void testMuteFixedVolume() throws Exception {
         int[] streams = {
                 AudioManager.STREAM_VOICE_CALL,
                 AudioManager.STREAM_MUSIC,
                 AudioManager.STREAM_RING,
                 AudioManager.STREAM_ALARM,
                 AudioManager.STREAM_NOTIFICATION,
-                AudioManager.STREAM_SYSTEM };
-
-        int muteAffectedStreams = System.getInt(mContext.getContentResolver(),
-                System.MUTE_STREAMS_AFFECTED,
-                        // Same defaults as in AudioService. Should be kept in
-                        // sync.
-                        ((1 << AudioManager.STREAM_MUSIC) |
-                                (1 << AudioManager.STREAM_RING) |
-                                (1 << AudioManager.STREAM_NOTIFICATION) |
-                                (1 << AudioManager.STREAM_SYSTEM)));
+                AudioManager.STREAM_SYSTEM};
         if (mUseFixedVolume) {
             for (int i = 0; i < streams.length; i++) {
                 mAudioManager.adjustStreamVolume(streams[i], AudioManager.ADJUST_MUTE, 0);
@@ -486,54 +605,87 @@
                 assertFalse("Muting should not affect a fixed volume device.",
                         mAudioManager.isStreamMute(streams[i]));
             }
+        }
+    }
+
+    public void testMute() throws Exception {
+        if (mUseFixedVolume) {
             return;
         }
-        // This ensures we're out of vibrate or silent modes.
-        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
-        for (int i = 0; i < streams.length; i++) {
-            // ensure each stream is on and turned up.
-            mAudioManager.setStreamVolume(streams[i], mAudioManager.getStreamMaxVolume(streams[i]),
-                    0);
-            if (((1 << streams[i]) & muteAffectedStreams) == 0) {
+
+        int[] streams = {
+                AudioManager.STREAM_VOICE_CALL,
+                AudioManager.STREAM_MUSIC,
+                AudioManager.STREAM_RING,
+                AudioManager.STREAM_ALARM,
+                AudioManager.STREAM_NOTIFICATION,
+                AudioManager.STREAM_SYSTEM };
+
+        try {
+            int muteAffectedStreams = System.getInt(mContext.getContentResolver(),
+                    System.MUTE_STREAMS_AFFECTED,
+                    // Same defaults as in AudioService. Should be kept in
+                    // sync.
+                    ((1 << AudioManager.STREAM_MUSIC) |
+                            (1 << AudioManager.STREAM_RING) |
+                            (1 << AudioManager.STREAM_NOTIFICATION) |
+                            (1 << AudioManager.STREAM_SYSTEM)));
+            Utils.toggleNotificationPolicyAccess(
+                    mContext.getPackageName(), getInstrumentation(), true);
+            // This ensures we're out of vibrate or silent modes.
+            mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+            Utils.toggleNotificationPolicyAccess(
+                    mContext.getPackageName(), getInstrumentation(), false);
+            for (int i = 0; i < streams.length; i++) {
+                // ensure each stream is on and turned up.
+                mAudioManager.setStreamVolume(streams[i],
+                        mAudioManager.getStreamMaxVolume(streams[i]),
+                        0);
+                if (((1 << streams[i]) & muteAffectedStreams) == 0) {
+                    mAudioManager.adjustStreamVolume(streams[i], AudioManager.ADJUST_MUTE, 0);
+                    assertFalse("Stream " + streams[i] + " should not be affected by mute.",
+                            mAudioManager.isStreamMute(streams[i]));
+                    mAudioManager.setStreamMute(streams[i], true);
+                    assertFalse("Stream " + streams[i] + " should not be affected by mute.",
+                            mAudioManager.isStreamMute(streams[i]));
+                    mAudioManager.adjustStreamVolume(streams[i], AudioManager.ADJUST_TOGGLE_MUTE,
+                            0);
+                    assertFalse("Stream " + streams[i] + " should not be affected by mute.",
+                            mAudioManager.isStreamMute(streams[i]));
+                    continue;
+                }
                 mAudioManager.adjustStreamVolume(streams[i], AudioManager.ADJUST_MUTE, 0);
-                assertFalse("Stream " + streams[i] + " should not be affected by mute.",
+                assertTrue("Muting stream " + streams[i] + " failed.",
                         mAudioManager.isStreamMute(streams[i]));
-                mAudioManager.setStreamMute(streams[i], true);
-                assertFalse("Stream " + streams[i] + " should not be affected by mute.",
+
+                mAudioManager.adjustStreamVolume(streams[i], AudioManager.ADJUST_UNMUTE, 0);
+                assertFalse("Unmuting stream " + streams[i] + " failed.",
                         mAudioManager.isStreamMute(streams[i]));
+
                 mAudioManager.adjustStreamVolume(streams[i], AudioManager.ADJUST_TOGGLE_MUTE, 0);
-                assertFalse("Stream " + streams[i] + " should not be affected by mute.",
+                assertTrue("Toggling mute on stream " + streams[i] + " failed.",
                         mAudioManager.isStreamMute(streams[i]));
-                continue;
+
+                mAudioManager.adjustStreamVolume(streams[i], AudioManager.ADJUST_TOGGLE_MUTE, 0);
+                assertFalse("Toggling mute on stream " + streams[i] + " failed.",
+                        mAudioManager.isStreamMute(streams[i]));
+
+                mAudioManager.setStreamMute(streams[i], true);
+                assertTrue("Muting stream " + streams[i] + " using setStreamMute failed",
+                        mAudioManager.isStreamMute(streams[i]));
+
+                // mute it three more times to verify the ref counting is gone.
+                mAudioManager.setStreamMute(streams[i], true);
+                mAudioManager.setStreamMute(streams[i], true);
+                mAudioManager.setStreamMute(streams[i], true);
+
+                mAudioManager.setStreamMute(streams[i], false);
+                assertFalse("Unmuting stream " + streams[i] + " using setStreamMute failed.",
+                        mAudioManager.isStreamMute(streams[i]));
             }
-            mAudioManager.adjustStreamVolume(streams[i], AudioManager.ADJUST_MUTE, 0);
-            assertTrue("Muting stream " + streams[i] + " failed.",
-                    mAudioManager.isStreamMute(streams[i]));
-
-            mAudioManager.adjustStreamVolume(streams[i], AudioManager.ADJUST_UNMUTE, 0);
-            assertFalse("Unmuting stream " + streams[i] + " failed.",
-                    mAudioManager.isStreamMute(streams[i]));
-
-            mAudioManager.adjustStreamVolume(streams[i], AudioManager.ADJUST_TOGGLE_MUTE, 0);
-            assertTrue("Toggling mute on stream " + streams[i] + " failed.",
-                    mAudioManager.isStreamMute(streams[i]));
-
-            mAudioManager.adjustStreamVolume(streams[i], AudioManager.ADJUST_TOGGLE_MUTE, 0);
-            assertFalse("Toggling mute on stream " + streams[i] + " failed.",
-                    mAudioManager.isStreamMute(streams[i]));
-
-            mAudioManager.setStreamMute(streams[i], true);
-            assertTrue("Muting stream " + streams[i] + " using setStreamMute failed",
-                    mAudioManager.isStreamMute(streams[i]));
-
-            // mute it three more times to verify the ref counting is gone.
-            mAudioManager.setStreamMute(streams[i], true);
-            mAudioManager.setStreamMute(streams[i], true);
-            mAudioManager.setStreamMute(streams[i], true);
-
-            mAudioManager.setStreamMute(streams[i], false);
-            assertFalse("Unmuting stream " + streams[i] + " using setStreamMute failed.",
-                    mAudioManager.isStreamMute(streams[i]));
+        } finally {
+            Utils.toggleNotificationPolicyAccess(
+                    mContext.getPackageName(), getInstrumentation(), false);
         }
     }
 
@@ -549,4 +701,5 @@
     private int getVolumeDelta(int volume) {
         return 1;
     }
+
 }
diff --git a/tests/tests/media/src/android/media/cts/AudioPlayRoutingNative.java b/tests/tests/media/src/android/media/cts/AudioPlayRoutingNative.java
new file mode 100644
index 0000000..6156095
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/AudioPlayRoutingNative.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.cts;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.content.Context;
+import android.cts.util.CtsAndroidTestCase;
+import android.media.AudioDeviceInfo;
+import android.media.AudioManager;
+import android.media.AudioRouting;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import com.android.ndkaudio.AudioPlayer;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+public class AudioPlayRoutingNative extends AndroidTestCase {
+    private static final String TAG = "AudioPlayRoutingNative";
+
+    private AudioManager mAudioManager;
+
+    static {
+        System.loadLibrary("ndkaudioLib");
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        // get the AudioManager
+        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+        assertNotNull(mAudioManager);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    //
+    // Tests
+    //
+
+    // Test a basic Aquire/Release cycle on the default player.
+    public void testAquireDefaultProxy() throws Exception {
+        AudioPlayer player = new AudioPlayer();
+        player.ClearLastSLResult();
+        player.RealizePlayer();
+        player.RealizeRoutingProxy();
+
+        AudioRouting routingObj = player.GetRoutingInterface();
+        assertNotNull(routingObj);
+
+        // Not allowed to acquire twice
+        routingObj = player.GetRoutingInterface();
+        assertNull(routingObj);
+        assertTrue(player.GetLastSLResult() != 0);
+
+        player.ReleaseRoutingInterface(routingObj);
+        assertTrue(player.GetLastSLResult() == 0);
+    }
+
+    // Test an Aquire before the OpenSL ES player is Realized.
+    public void testAquirePreRealizeDefaultProxy() throws Exception {
+        AudioPlayer player = new AudioPlayer();
+        player.ClearLastSLResult();
+        player.RealizeRoutingProxy();
+        assertTrue(player.GetLastSLResult() == 0);
+
+        AudioRouting routingObj = player.GetRoutingInterface();
+        assertTrue(player.GetLastSLResult() == 0);
+        assertNotNull(routingObj);
+
+        player.RealizePlayer();
+        assertTrue(player.GetLastSLResult() == 0);
+
+        player.ReleaseRoutingInterface(routingObj);
+        assertTrue(player.GetLastSLResult() == 0);
+    }
+
+    // Test actually setting the routing through the enumerated devices.
+    public void testRouting() {
+        AudioPlayer player = new AudioPlayer();
+        player.ClearLastSLResult();
+        player.RealizePlayer();
+        player.RealizeRoutingProxy();
+
+        AudioRouting routingObj = player.GetRoutingInterface();
+        assertNotNull(routingObj);
+
+        AudioDeviceInfo[] deviceList;
+        deviceList = mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
+        assertTrue(deviceList != null);
+        for (AudioDeviceInfo devInfo : deviceList) {
+            assertTrue(routingObj.setPreferredDevice(devInfo));
+        }
+
+        player.ReleaseRoutingInterface(routingObj);
+        assertTrue(player.GetLastSLResult() == 0);
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/AudioRecordRoutingNative.java b/tests/tests/media/src/android/media/cts/AudioRecordRoutingNative.java
new file mode 100644
index 0000000..c965e14
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/AudioRecordRoutingNative.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.cts;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.content.Context;
+import android.media.AudioDeviceInfo;
+import android.media.AudioManager;
+import android.media.AudioRouting;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import com.android.ndkaudio.AudioRecorder;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+public class AudioRecordRoutingNative extends AndroidTestCase {
+    private static final String TAG = "AudioRecordRoutingNative";
+
+    private AudioManager mAudioManager;
+
+    static {
+        System.loadLibrary("ndkaudioLib");
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        // get the AudioManager
+        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+        assertNotNull(mAudioManager);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    //
+    // Tests
+    //
+
+    // Test a basic Aquire/Release cycle on the default recorder.
+    public void testAquireDefaultProxy() throws Exception {
+        AudioRecorder recorder = new AudioRecorder();
+        recorder.ClearLastSLResult();
+        recorder.RealizeRecorder();
+        recorder.RealizeRoutingProxy();
+
+        AudioRouting routingObj = recorder.GetRoutingInterface();
+        assertNotNull(routingObj);
+
+        // Not allowed to acquire twice
+        routingObj = recorder.GetRoutingInterface();
+        assertNull(routingObj);
+        assertTrue(recorder.GetLastSLResult() != 0);
+
+        recorder.ReleaseRoutingInterface(routingObj);
+        assertTrue(recorder.GetLastSLResult() == 0);
+    }
+
+    // Test an Aquire before the OpenSL ES recorder is Realized.
+    public void testAquirePreRealizeDefaultProxy() throws Exception {
+        AudioRecorder recorder = new AudioRecorder();
+        recorder.ClearLastSLResult();
+        recorder.RealizeRecorder();
+        recorder.RealizeRoutingProxy();
+        assertTrue(recorder.GetLastSLResult() == 0);
+
+        AudioRouting routingObj = recorder.GetRoutingInterface();
+        assertTrue(recorder.GetLastSLResult() == 0);
+        assertNotNull(routingObj);
+
+        recorder.RealizeRecorder();
+        assertTrue(recorder.GetLastSLResult() == 0);
+
+        recorder.ReleaseRoutingInterface(routingObj);
+        assertTrue(recorder.GetLastSLResult() == 0);
+    }
+
+    // Test actually setting the routing through the enumerated devices.
+    public void testRouting() {
+        AudioRecorder recorder = new AudioRecorder();
+        recorder.ClearLastSLResult();
+        recorder.RealizeRecorder();
+        recorder.RealizeRoutingProxy();
+
+        AudioRouting routingObj = recorder.GetRoutingInterface();
+        assertNotNull(routingObj);
+
+        AudioDeviceInfo[] deviceList;
+        deviceList = mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS);
+        assertTrue(deviceList != null);
+        for (AudioDeviceInfo devInfo : deviceList) {
+            assertTrue(routingObj.setPreferredDevice(devInfo));
+        }
+
+        recorder.ReleaseRoutingInterface(routingObj);
+        assertTrue(recorder.GetLastSLResult() == 0);
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/AudioRecordTest.java b/tests/tests/media/src/android/media/cts/AudioRecordTest.java
index c2c729b..afd6997 100644
--- a/tests/tests/media/src/android/media/cts/AudioRecordTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioRecordTest.java
@@ -749,7 +749,7 @@
             return;
         }
         // audit recording plays back recorded audio, so use longer test timing
-        final int TEST_TIME_MS = auditRecording ? 10000 : 2000;
+        final int TEST_TIME_MS = auditRecording ? 60000 : 2000;
         final int TEST_SOURCE = MediaRecorder.AudioSource.DEFAULT;
         mIsHandleMessageCalled = false;
 
@@ -1252,7 +1252,8 @@
         final double ratio = (double)timeDiff / timeByFrames;
 
         // Usually the ratio is accurate to one part per thousand or better.
-        // Log.d(TAG, "ratio " + ratio);
+        // Log.d(TAG, "ratio=" + ratio + ", timeDiff=" + timeDiff + ", frameDiff=" + frameDiff +
+        //        ", timeByFrames=" + timeByFrames + ", sampleRate=" + sampleRate);
         assertEquals(1.0 /* expected */, ratio, 0.01 /* delta */);
     }
 
diff --git a/tests/tests/media/src/android/media/cts/AudioTrackLatencyTest.java b/tests/tests/media/src/android/media/cts/AudioTrackLatencyTest.java
index 505c4dc..0851a0a 100644
--- a/tests/tests/media/src/android/media/cts/AudioTrackLatencyTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioTrackLatencyTest.java
@@ -54,7 +54,8 @@
 public class AudioTrackLatencyTest extends CtsAndroidTestCase {
     private String TAG = "AudioTrackLatencyTest";
     private final static long NANOS_PER_MILLISECOND = 1000000L;
-    private final static long NANOS_PER_SECOND = NANOS_PER_MILLISECOND * 1000L;
+    private final static int MILLIS_PER_SECOND = 1000;
+    private final static long NANOS_PER_SECOND = NANOS_PER_MILLISECOND * MILLIS_PER_SECOND;
 
     private void log(String testName, String message) {
         Log.i(TAG, "[" + testName + "] " + message);
@@ -97,8 +98,9 @@
                 initialBufferSize, track.getBufferSizeInFrames());
 
         int resultZero = track.setBufferSizeInFrames(0);
-        assertTrue(TEST_NAME + ": zero size OK", resultZero > 0);
-        assertTrue(TEST_NAME + ": zero size < original", resultZero < initialBufferSize);
+        assertTrue(TEST_NAME + ": should be >0, but got " + resultZero, resultZero > 0);
+        assertTrue(TEST_NAME + ": zero size < original, but got " + resultZero,
+                resultZero < initialBufferSize);
         assertEquals(TEST_NAME + ": should match resultZero",
                 resultZero, track.getBufferSizeInFrames());
 
@@ -118,6 +120,148 @@
         track.release();
     }
 
+    // Helper class for tests
+    private static class TestSetup {
+        public int sampleRate = 48000;
+        public int samplesPerFrame = 2;
+        public int bytesPerSample = 2;
+        public int config = AudioFormat.CHANNEL_OUT_STEREO;
+        public int format = AudioFormat.ENCODING_PCM_16BIT;
+        public int mode = AudioTrack.MODE_STREAM;
+        public int streamType = AudioManager.STREAM_MUSIC;
+        public int framesPerBuffer = 256;
+        public double amplitude = 0.5;
+
+        private AudioTrack mTrack;
+        private short[] mData;
+        private int mActualSizeInFrames;
+
+        AudioTrack createTrack() {
+            mData = AudioHelper.createSineWavesShort(framesPerBuffer,
+                    samplesPerFrame, 1, amplitude);
+            int minBufferSize = AudioTrack.getMinBufferSize(sampleRate, config, format);
+            // Create a buffer that is 3/2 times bigger than the minimum.
+            // This gives me room to cut it in half and play without glitching.
+            // This is an arbitrary scaling factor.
+            int bufferSize = (minBufferSize * 3) / 2;
+            mTrack = new AudioTrack(streamType, sampleRate, config, format,
+                    bufferSize, mode);
+
+            // Calculate and use a smaller buffer size
+            int smallBufferSize = bufferSize / 2; // arbitrary, smaller might underflow
+            int smallBuffSizeInFrames = smallBufferSize / (samplesPerFrame * bytesPerSample);
+            mActualSizeInFrames = mTrack.setBufferSizeInFrames(smallBuffSizeInFrames);
+            return mTrack;
+
+        }
+
+        int primeAudioTrack(String testName) {
+            // Prime the buffer.
+            int samplesWrittenTotal = 0;
+            int samplesWritten;
+            do{
+                samplesWritten = mTrack.write(mData, 0, mData.length);
+                if (samplesWritten > 0) {
+                    samplesWrittenTotal += samplesWritten;
+                }
+            } while (samplesWritten == mData.length);
+            int framesWrittenTotal = samplesWrittenTotal / samplesPerFrame;
+            assertTrue(testName + ": framesWrittenTotal = " + framesWrittenTotal
+                    + ", size = " + mActualSizeInFrames,
+                    framesWrittenTotal >= mActualSizeInFrames);
+            return framesWrittenTotal;
+        }
+
+        /**
+         * @param seconds
+         */
+        public void writeSeconds(double seconds) throws InterruptedException {
+            long msecEnd = System.currentTimeMillis() + (long)(seconds * 1000);
+            while (System.currentTimeMillis() < msecEnd) {
+                // Use non-blocking mode in case the track is hung.
+                int samplesWritten = mTrack.write(mData, 0, mData.length, AudioTrack.WRITE_NON_BLOCKING);
+                if (samplesWritten < mData.length) {
+                    int samplesRemaining = mData.length - samplesWritten;
+                    int framesRemaining = samplesRemaining / samplesPerFrame;
+                    int millis = (framesRemaining * 1000) / sampleRate;
+                    Thread.sleep(millis);
+                }
+            }
+        }
+    }
+
+    // Try to play an AudioTrack when the initial size is less than capacity.
+    // We want to make sure the track starts properly and is not stuck.
+    public void testPlaySmallBuffer() throws Exception {
+        final String TEST_NAME = "testPlaySmallBuffer";
+        TestSetup setup = new TestSetup();
+        AudioTrack track = setup.createTrack();
+
+        // Prime the buffer.
+        int framesWrittenTotal = setup.primeAudioTrack(TEST_NAME);
+
+        // Start playing and let it drain.
+        int position1 = track.getPlaybackHeadPosition();
+        assertEquals(TEST_NAME + ": initial position", 0, position1);
+        track.play();
+
+        // Make sure it starts within a reasonably short time.
+        final long MAX_TIME_TO_START_MSEC =  500; // arbitrary
+        long giveUpAt = System.currentTimeMillis() + MAX_TIME_TO_START_MSEC;
+        int position2 = track.getPlaybackHeadPosition();
+        while ((position1 == position2)
+                && (System.currentTimeMillis() < giveUpAt)) {
+            Thread.sleep(20); // arbitrary interval
+            position2 = track.getPlaybackHeadPosition();
+        }
+        assertTrue(TEST_NAME + ": did it start?, position after start = " + position2,
+                position2 > position1);
+
+        // Make sure it finishes playing the data.
+        // Wait several times longer than it should take to play the data.
+        final int several = 3; // arbitrary
+        Thread.sleep(several * framesWrittenTotal * MILLIS_PER_SECOND / setup.sampleRate);
+        position2 = track.getPlaybackHeadPosition();
+        assertEquals(TEST_NAME + ": did it play all the data?",
+                framesWrittenTotal, position2);
+
+        track.release();
+    }
+
+    // Try to play and pause an AudioTrack when the initial size is less than capacity.
+    // We want to make sure the track starts properly and is not stuck.
+    public void testPlayPauseSmallBuffer() throws Exception {
+        final String TEST_NAME = "testPlayPauseSmallBuffer";
+        TestSetup setup = new TestSetup();
+        AudioTrack track = setup.createTrack();
+
+        // Prime the buffer.
+        setup.primeAudioTrack(TEST_NAME);
+
+        // Start playing then pause and play in a loop.
+        int position1 = track.getPlaybackHeadPosition();
+        assertEquals(TEST_NAME + ": initial position", 0, position1);
+        track.play();
+        // try pausing several times to see it if it fails
+        final int several = 4; // arbitrary
+        for (int i = 0; i < several; i++) {
+            // write data in non-blocking mode for a few seconds
+            setup.writeSeconds(2.0); // arbitrary, long enough for audio to get to the device
+            // Did position advance as we were playing? Or was the track stuck?
+            int position2 = track.getPlaybackHeadPosition();
+            int delta = position2 - position1; // safe from wrapping
+            assertTrue(TEST_NAME + ": [" + i + "] did it advance? p1 = " + position1
+                    + ", p2 = " + position2, delta > 0);
+            position1 = position2;
+            // pause for a second
+            track.pause();
+            Thread.sleep(MILLIS_PER_SECOND);
+            track.play();
+        }
+
+        track.release();
+    }
+
     // Create a track with or without FLAG_LOW_LATENCY
     private AudioTrack createCustomAudioTrack(boolean lowLatency) {
         final String TEST_NAME = "createCustomAudioTrack";
@@ -303,7 +447,7 @@
         // Play with ridiculously small size. We want to get underruns so we know that an app
         // can get to the edge of underrunning.
         int resultZero = track.setBufferSizeInFrames(0);
-        assertTrue(TEST_NAME + ": zero size OK", resultZero > 0);
+        assertTrue(TEST_NAME + ": should return > 0, got " + resultZero, resultZero > 0);
         assertTrue(TEST_NAME + ": zero size < original", resultZero < initialBufferSize);
         numSeconds = TEST_NUM_SECONDS / 2; // cuz test takes longer when underflowing
         numBuffers = numSeconds * TEST_SR / TEST_FRAMES_PER_BUFFER;
diff --git a/tests/tests/media/src/android/media/cts/MediaRouterTest.java b/tests/tests/media/src/android/media/cts/MediaRouterTest.java
new file mode 100644
index 0000000..33544b9
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaRouterTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media.cts;
+
+import android.content.Context;
+import android.media.MediaRouter;
+import android.media.MediaRouter.RouteCategory;
+import android.media.MediaRouter.RouteInfo;
+import android.media.MediaRouter.UserRouteInfo;
+import android.test.InstrumentationTestCase;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Test {@link android.media.MediaRouter}.
+ */
+public class MediaRouterTest extends InstrumentationTestCase {
+
+    private MediaRouter mMediaRouter;
+    private RouteCategory mTestCategory;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        final Context context = getInstrumentation().getContext();
+        mMediaRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
+        mTestCategory = mMediaRouter.createRouteCategory("testCategory", false);
+    }
+
+    protected void tearDown() throws Exception {
+        mMediaRouter.clearUserRoutes();
+        super.tearDown();
+    }
+
+    public void testSelectRoute() throws Exception {
+        RouteInfo prevSelectedRoute = mMediaRouter.getSelectedRoute(
+                MediaRouter.ROUTE_TYPE_LIVE_AUDIO | MediaRouter.ROUTE_TYPE_LIVE_VIDEO
+                | MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY);
+
+        final String newRouteName = "User route's name";
+        UserRouteInfo newRoute = mMediaRouter.createUserRoute(mTestCategory);
+        newRoute.setName(newRouteName);
+        mMediaRouter.addUserRoute(newRoute);
+        mMediaRouter.selectRoute(newRoute.getSupportedTypes(), newRoute);
+
+        RouteInfo nowSelectedRoute = mMediaRouter.getSelectedRoute(MediaRouter.ROUTE_TYPE_USER);
+        assertEquals(newRoute, nowSelectedRoute);
+        assertEquals(mTestCategory, nowSelectedRoute.getCategory());
+
+        mMediaRouter.selectRoute(prevSelectedRoute.getSupportedTypes(), prevSelectedRoute);
+    }
+
+    public void testGetRouteCount() throws Exception {
+        final int count = mMediaRouter.getRouteCount();
+        assertTrue("By default, a media router has at least one route.", count > 0);
+
+        UserRouteInfo userRoute1 = mMediaRouter.createUserRoute(mTestCategory);
+        mMediaRouter.addUserRoute(userRoute1);
+        assertEquals(count + 1, mMediaRouter.getRouteCount());
+
+        mMediaRouter.removeUserRoute(userRoute1);
+        assertEquals(count, mMediaRouter.getRouteCount());
+
+        UserRouteInfo userRoute2 = mMediaRouter.createUserRoute(mTestCategory);
+        mMediaRouter.addUserRoute(userRoute1);
+        mMediaRouter.addUserRoute(userRoute2);
+        assertEquals(count + 2, mMediaRouter.getRouteCount());
+
+        mMediaRouter.clearUserRoutes();
+        assertEquals(count, mMediaRouter.getRouteCount());
+    }
+
+    public void testRouteCategory() throws Exception {
+        final int count = mMediaRouter.getCategoryCount();
+        assertTrue("By default, a media router has at least one route category.", count > 0);
+
+        UserRouteInfo newRoute = mMediaRouter.createUserRoute(mTestCategory);
+        mMediaRouter.addUserRoute(newRoute);
+        assertEquals(count + 1, mMediaRouter.getCategoryCount());
+
+        for (int i = 0; i < mMediaRouter.getCategoryCount(); i++) {
+            if (mMediaRouter.getCategoryAt(i) == mTestCategory) {
+                List<RouteInfo> routesInCategory = new ArrayList<RouteInfo>();
+                mTestCategory.getRoutes(routesInCategory);
+                assertEquals(1, routesInCategory.size());
+
+                RouteInfo route = routesInCategory.get(0);
+                assertEquals(newRoute, route);
+                return;
+            }
+        }
+        assertTrue(false);
+    }
+
+    public void testRouteInfo_getDeviceType() throws Exception {
+        final RouteInfo defaultRoute = mMediaRouter.getDefaultRoute();
+        assertTrue(defaultRoute != null);
+
+        final int deviceType = defaultRoute.getDeviceType();
+        assertEquals(RouteInfo.DEVICE_TYPE_UNKNOWN, deviceType);
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/Utils.java b/tests/tests/media/src/android/media/cts/Utils.java
index bb9cf78..914a0518 100644
--- a/tests/tests/media/src/android/media/cts/Utils.java
+++ b/tests/tests/media/src/android/media/cts/Utils.java
@@ -18,9 +18,13 @@
 
 import android.app.Instrumentation;
 import android.app.UiAutomation;
+import android.content.ContentResolver;
+import android.content.Context;
 import android.os.ParcelFileDescriptor;
+import android.provider.Settings;
 
 import java.io.FileInputStream;
+import java.io.IOException;
 import java.io.InputStream;
 import java.util.Scanner;
 
@@ -67,4 +71,39 @@
             result = convertStreamToString(inputStream);
         }
     }
+
+    protected static void toggleNotificationPolicyAccess(String packageName,
+            Instrumentation instrumentation, boolean on) throws IOException {
+        Context context = instrumentation.getContext();
+
+        // Get permission to enable accessibility
+        UiAutomation uiAutomation = instrumentation.getUiAutomation();
+
+        ContentResolver cr = context.getContentResolver();
+        String alreadyEnabledServices = Settings.Secure.getString(
+                cr, Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES);
+        ParcelFileDescriptor fd = null;
+        if (on) {
+            // Change the settings to enable the media cts package
+            fd = uiAutomation.executeShellCommand(
+                    "settings --user cur put secure "
+                            + Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES + " "
+                            + alreadyEnabledServices + ":"
+                            + packageName);
+        } else {
+            int index =  alreadyEnabledServices.indexOf(":" + packageName);
+            if (index >= 0) {
+                fd = uiAutomation.executeShellCommand(
+                        "settings --user cur put secure "
+                                + Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES + " "
+                                + alreadyEnabledServices.substring(0, index));
+            }
+        }
+        if (fd != null) {
+            InputStream in = new FileInputStream(fd.getFileDescriptor());
+            byte[] buffer = new byte[4096];
+            while (in.read(buffer) > 0) ;
+        }
+        uiAutomation.destroy();
+    }
 }
diff --git a/tests/tests/media/src/android/media/cts/VideoEncoderTest.java b/tests/tests/media/src/android/media/cts/VideoEncoderTest.java
index 79b7543..5edee65 100644
--- a/tests/tests/media/src/android/media/cts/VideoEncoderTest.java
+++ b/tests/tests/media/src/android/media/cts/VideoEncoderTest.java
@@ -32,6 +32,7 @@
 import android.media.MediaCodecList;
 import android.media.MediaExtractor;
 import android.media.MediaFormat;
+import android.media.MediaMuxer;
 import android.net.Uri;
 import android.util.Log;
 import android.util.Pair;
@@ -39,9 +40,12 @@
 import android.util.Size;
 import android.view.Surface;
 
+import java.io.File;
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
+import java.util.function.Consumer;
+import java.util.function.Function;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -168,9 +172,20 @@
     abstract class VideoProcessorBase extends MediaCodec.Callback {
         private static final String TAG = "VideoProcessorBase";
 
+        /*
+         * Set this to true to save the encoding results to /data/local/tmp
+         * You will need to make /data/local/tmp writeable, run "setenforce 0",
+         * and remove files left from a previous run.
+         */
+        private boolean mSaveResults = false;
+        private static final String FILE_DIR = "/data/local/tmp";
+        protected int mMuxIndex = -1;
+
+        protected String mProcessorName = "VideoProcessor";
         private MediaExtractor mExtractor;
+        protected MediaMuxer mMuxer;
         private ByteBuffer mBuffer = ByteBuffer.allocate(MAX_SAMPLE_SIZE);
-        private int mTrackIndex = -1;
+        protected int mTrackIndex = -1;
         private boolean mSignaledDecoderEOS;
 
         protected boolean mCompleted;
@@ -185,6 +200,21 @@
         protected int mFrameRate = 0;
         protected int mBitRate = 0;
 
+        protected Function<MediaFormat, Boolean> mUpdateConfigFormatHook;
+        protected Function<MediaFormat, Boolean> mCheckOutputFormatHook;
+
+        public void setProcessorName(String name) {
+            mProcessorName = name;
+        }
+
+        public void setUpdateConfigHook(Function<MediaFormat, Boolean> hook) {
+            mUpdateConfigFormatHook = hook;
+        }
+
+        public void setCheckOutputFormatHook(Function<MediaFormat, Boolean> hook) {
+            mCheckOutputFormatHook = hook;
+        }
+
         protected void open(String path) throws IOException {
             mExtractor = new MediaExtractor();
             if (path.startsWith("android.resource://")) {
@@ -209,8 +239,8 @@
 
         // returns true if encoder supports the size
         protected boolean initCodecsAndConfigureEncoder(
-                String videoEncName, String outMime, int width, int height, int colorFormat)
-                        throws IOException {
+                String videoEncName, String outMime, int width, int height,
+                int colorFormat) throws IOException {
             mDecFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat);
 
             MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
@@ -230,7 +260,7 @@
             }
 
             MediaFormat outFmt = MediaFormat.createVideoFormat(outMime, width, height);
-
+            int bitRate = 0;
             {
                 int maxWidth = encCaps.getSupportedWidths().getUpper();
                 int maxHeight = encCaps.getSupportedHeightsFor(maxWidth).getUpper();
@@ -243,7 +273,7 @@
                 }
                 outFmt.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
 
-                int bitRate = mBitRate;
+                bitRate = mBitRate;
                 if (bitRate <= 0) {
                     bitRate = encCaps.getBitrateRange().clamp(
                         (int)(encCaps.getBitrateRange().getUpper() /
@@ -255,8 +285,31 @@
             }
             outFmt.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
             outFmt.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat);
+            // Some extra configure before starting the encoder.
+            if (mUpdateConfigFormatHook != null) {
+                if (!mUpdateConfigFormatHook.apply(outFmt)) {
+                    return false;
+                }
+            }
             mEncoder.configure(outFmt, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
             Log.i(TAG, "encoder input format " + mEncoder.getInputFormat() + " from " + outFmt);
+            if (mSaveResults) {
+                try {
+                    String outFileName =
+                            FILE_DIR + mProcessorName + "_" + bitRate + "bps";
+                    if (outMime.equals(MediaFormat.MIMETYPE_VIDEO_VP8) ||
+                            outMime.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
+                        mMuxer = new MediaMuxer(
+                                outFileName + ".webm", MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM);
+                    } else {
+                        mMuxer = new MediaMuxer(
+                                outFileName + ".mp4", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
+                    }
+                    // The track can't be added until we have the codec specific data
+                } catch (Exception e) {
+                    Log.i(TAG, "couldn't create muxer: " + e);
+                }
+            }
             return true;
         }
 
@@ -273,6 +326,11 @@
                 mExtractor.release();
                 mExtractor = null;
             }
+            if (mMuxer != null) {
+                mMuxer.stop();
+                mMuxer.release();
+                mMuxer = null;
+            }
         }
 
         // returns true if filled buffer
@@ -314,7 +372,16 @@
             if (DEBUG) Log.v(TAG, "encoder received output #" + ix
                      + " (sz=" + info.size + ", f=" + info.flags
                      + ", ts=" + info.presentationTimeUs + ")");
-            mEncodedStream.addBuffer(mEncoder.getOutputBuffer(ix), info);
+            ByteBuffer outputBuffer = mEncoder.getOutputBuffer(ix);
+            mEncodedStream.addBuffer(outputBuffer, info);
+
+            if (mMuxer != null) {
+                // reset position as addBuffer() modifies it
+                outputBuffer.position(info.offset);
+                outputBuffer.limit(info.offset + info.size);
+                mMuxer.writeSampleData(mMuxIndex, outputBuffer, info);
+            }
+
             if (!mCompleted) {
                 mEncoder.releaseOutputBuffer(ix, false);
                 if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
@@ -333,6 +400,15 @@
 
         protected void saveEncoderFormat(MediaFormat format) {
             mEncodedStream.setFormat(format);
+            if (mCheckOutputFormatHook != null) {
+                mCheckOutputFormatHook.apply(format);
+            }
+            if (mMuxer != null) {
+                if (mMuxIndex < 0) {
+                    mMuxIndex = mMuxer.addTrack(format);
+                    mMuxer.start();
+                }
+            }
         }
 
         public void playBack(Surface surface) {
@@ -770,7 +846,8 @@
     class Encoder {
         final private String mName;
         final private String mMime;
-        final private VideoCapabilities mCaps;
+        final private CodecCapabilities mCaps;
+        final private VideoCapabilities mVideoCaps;
 
         final private Map<Size, Set<Size>> mMinMax;     // extreme sizes
         final private Map<Size, Set<Size>> mNearMinMax; // sizes near extreme
@@ -784,7 +861,8 @@
         Encoder(String name, String mime, CodecCapabilities caps) {
             mName = name;
             mMime = mime;
-            mCaps = caps.getVideoCapabilities();
+            mCaps = caps;
+            mVideoCaps = caps.getVideoCapabilities();
 
             /* calculate min/max sizes */
             mMinMax = new HashMap<Size, Set<Size>>();
@@ -793,8 +871,8 @@
             mArbitraryH = new HashSet<Size>();
             mSizes = new HashSet<Size>();
 
-            xAlign = mCaps.getWidthAlignment();
-            yAlign = mCaps.getHeightAlignment();
+            xAlign = mVideoCaps.getWidthAlignment();
+            yAlign = mVideoCaps.getHeightAlignment();
 
             initializeSizes();
         }
@@ -811,16 +889,16 @@
                 int j = ((7 * i) % 11) + 1;
                 int width, height;
                 try {
-                    width = alignedPointInRange(i * 0.125, xAlign, mCaps.getSupportedWidths());
+                    width = alignedPointInRange(i * 0.125, xAlign, mVideoCaps.getSupportedWidths());
                     height = alignedPointInRange(
-                            j * 0.077, yAlign, mCaps.getSupportedHeightsFor(width));
+                            j * 0.077, yAlign, mVideoCaps.getSupportedHeightsFor(width));
                     mArbitraryW.add(new Size(width, height));
                 } catch (IllegalArgumentException e) {
                 }
 
                 try {
-                    height = alignedPointInRange(i * 0.125, yAlign, mCaps.getSupportedHeights());
-                    width = alignedPointInRange(j * 0.077, xAlign, mCaps.getSupportedWidthsFor(height));
+                    height = alignedPointInRange(i * 0.125, yAlign, mVideoCaps.getSupportedHeights());
+                    width = alignedPointInRange(j * 0.077, xAlign, mVideoCaps.getSupportedWidthsFor(height));
                     mArbitraryH.add(new Size(width, height));
                 } catch (IllegalArgumentException e) {
                 }
@@ -841,34 +919,34 @@
                 for (int dy = 0; dy <= yAlign; dy += yAlign) {
                     Set<Size> bucket = (dx + dy == 0) ? minMax : nearMinMax;
                     try {
-                        int width = getExtreme(mCaps.getSupportedWidths(), x, dx);
-                        int height = getExtreme(mCaps.getSupportedHeightsFor(width), y, dy);
+                        int width = getExtreme(mVideoCaps.getSupportedWidths(), x, dx);
+                        int height = getExtreme(mVideoCaps.getSupportedHeightsFor(width), y, dy);
                         bucket.add(new Size(width, height));
 
                         // try max max with more reasonable ratio if too skewed
                         if (x + y == 2 && width >= 4 * height) {
                             Size wideScreen = getLargestSizeForRatio(16, 9);
                             width = getExtreme(
-                                    mCaps.getSupportedWidths()
+                                    mVideoCaps.getSupportedWidths()
                                             .intersect(0, wideScreen.getWidth()), x, dx);
-                            height = getExtreme(mCaps.getSupportedHeightsFor(width), y, 0);
+                            height = getExtreme(mVideoCaps.getSupportedHeightsFor(width), y, 0);
                             bucket.add(new Size(width, height));
                         }
                     } catch (IllegalArgumentException e) {
                     }
 
                     try {
-                        int height = getExtreme(mCaps.getSupportedHeights(), y, dy);
-                        int width = getExtreme(mCaps.getSupportedWidthsFor(height), x, dx);
+                        int height = getExtreme(mVideoCaps.getSupportedHeights(), y, dy);
+                        int width = getExtreme(mVideoCaps.getSupportedWidthsFor(height), x, dx);
                         bucket.add(new Size(width, height));
 
                         // try max max with more reasonable ratio if too skewed
                         if (x + y == 2 && height >= 4 * width) {
                             Size wideScreen = getLargestSizeForRatio(9, 16);
                             height = getExtreme(
-                                    mCaps.getSupportedHeights()
+                                    mVideoCaps.getSupportedHeights()
                                             .intersect(0, wideScreen.getHeight()), y, dy);
-                            width = getExtreme(mCaps.getSupportedWidthsFor(height), x, dx);
+                            width = getExtreme(mVideoCaps.getSupportedWidthsFor(height), x, dx);
                             bucket.add(new Size(width, height));
                         }
                     } catch (IllegalArgumentException e) {
@@ -907,17 +985,17 @@
         }
 
         private Size getLargestSizeForRatio(int x, int y) {
-            Range<Integer> widthRange = mCaps.getSupportedWidths();
-            Range<Integer> heightRange = mCaps.getSupportedHeightsFor(widthRange.getUpper());
-            final int xAlign = mCaps.getWidthAlignment();
-            final int yAlign = mCaps.getHeightAlignment();
+            Range<Integer> widthRange = mVideoCaps.getSupportedWidths();
+            Range<Integer> heightRange = mVideoCaps.getSupportedHeightsFor(widthRange.getUpper());
+            final int xAlign = mVideoCaps.getWidthAlignment();
+            final int yAlign = mVideoCaps.getHeightAlignment();
 
             // scale by alignment
             int width = alignInRange(
                     Math.sqrt(widthRange.getUpper() * heightRange.getUpper() * (double)x / y),
                     xAlign, widthRange);
             int height = alignInRange(
-                    width * (double)y / x, yAlign, mCaps.getSupportedHeightsFor(width));
+                    width * (double)y / x, yAlign, mVideoCaps.getSupportedHeightsFor(width));
             return new Size(width, height);
         }
 
@@ -950,22 +1028,87 @@
             return test(width, height, true /* optional */, flexYUV);
         }
 
+        public boolean testIntraRefresh(int width, int height) {
+            final int refreshPeriod = 10;
+            if (!mCaps.isFeatureSupported(CodecCapabilities.FEATURE_IntraRefresh)) {
+                return false;
+            }
+
+            Function<MediaFormat, Boolean> updateConfigFormatHook =
+                    new Function<MediaFormat, Boolean>() {
+                public Boolean apply(MediaFormat fmt) {
+                    // set i-frame-interval to 10000 so encoded video only has 1 i-frame.
+                    fmt.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10000);
+                    fmt.setInteger(MediaFormat.KEY_INTRA_REFRESH_PERIOD, refreshPeriod);
+                    return true;
+                }
+            };
+
+            Function<MediaFormat, Boolean> checkOutputFormatHook =
+                    new Function<MediaFormat, Boolean>() {
+                public Boolean apply(MediaFormat fmt) {
+                    int intraPeriod = fmt.getInteger(MediaFormat.KEY_INTRA_REFRESH_PERIOD);
+                    // Make sure intra period is correct and carried in the output format.
+                    // intraPeriod must be larger than 0 and not larger than what has been set.
+                    if (intraPeriod > refreshPeriod) {
+                        throw new RuntimeException("Intra period mismatch");
+                    }
+                    return true;
+                }
+            };
+
+            String testName =
+                    mName + '_' + width + "x" + height + '_' + "flexYUV_intraRefresh";
+
+            Consumer<VideoProcessorBase> configureVideoProcessor =
+                    new Consumer<VideoProcessorBase>() {
+                public void accept(VideoProcessorBase processor) {
+                    processor.setProcessorName(testName);
+                    processor.setUpdateConfigHook(updateConfigFormatHook);
+                    processor.setCheckOutputFormatHook(checkOutputFormatHook);
+                }
+            };
+
+            return test(width, height, 0 /* frameRate */, 0 /* bitRate */, true /* optional */,
+                    true /* flex */, configureVideoProcessor);
+        }
+
         public boolean testDetailed(
                 int width, int height, int frameRate, int bitRate, boolean flexYUV) {
-            return test(width, height, frameRate, bitRate, true /* optional */, flexYUV);
+            String testName =
+                    mName + '_' + width + "x" + height + '_' + (flexYUV ? "flexYUV" : " surface");
+            Consumer<VideoProcessorBase> configureVideoProcessor =
+                    new Consumer<VideoProcessorBase>() {
+                public void accept(VideoProcessorBase processor) {
+                    processor.setProcessorName(testName);
+                }
+            };
+            return test(width, height, frameRate, bitRate, true /* optional */, flexYUV,
+                    configureVideoProcessor);
         }
 
         public boolean testSupport(int width, int height, int frameRate, int bitRate) {
-            return mCaps.areSizeAndRateSupported(width, height, frameRate) &&
-                    mCaps.getBitrateRange().contains(bitRate);
+            return mVideoCaps.areSizeAndRateSupported(width, height, frameRate) &&
+                    mVideoCaps.getBitrateRange().contains(bitRate);
         }
 
-        private boolean test(int width, int height, boolean optional, boolean flexYUV) {
-            return test(width, height, 0 /* frameRate */, 0 /* bitRate */, optional, flexYUV);
+        private boolean test(
+                int width, int height, boolean optional, boolean flexYUV) {
+            String testName =
+                    mName + '_' + width + "x" + height + '_' + (flexYUV ? "flexYUV" : " surface");
+            Consumer<VideoProcessorBase> configureVideoProcessor =
+                    new Consumer<VideoProcessorBase>() {
+                public void accept(VideoProcessorBase processor) {
+                    processor.setProcessorName(testName);
+                }
+            };
+            return test(width, height, 0 /* frameRate */, 0 /* bitRate */,
+                    optional, flexYUV, configureVideoProcessor);
         }
 
-        private boolean test(int width, int height, int frameRate, int bitRate,
-                boolean optional, boolean flexYUV) {
+        private boolean test(
+                int width, int height, int frameRate, int bitRate, boolean optional,
+                boolean flexYUV, Consumer<VideoProcessorBase> configureVideoProcessor) {
             Log.i(TAG, "testing " + mMime + " on " + mName + " for " + width + "x" + height
                     + (flexYUV ? " flexYUV" : " surface"));
 
@@ -973,6 +1116,7 @@
                 flexYUV ? new VideoProcessor() : new SurfaceVideoProcessor();
 
             processor.setFrameAndBitRates(frameRate, bitRate);
+            configureVideoProcessor.accept(processor);
 
             // We are using a resource URL as an example
             boolean success = processor.processLoop(
@@ -1409,6 +1553,46 @@
     public void testOtherVP9Flex1080p()   { specific(otherVP9(),   1920, 1080, true /* flex */); }
     public void testOtherVP9Surf1080p()   { specific(otherVP9(),   1920, 1080, false /* flex */); }
 
+    public void testGoogH265Flex360pWithIntraRefresh() {
+        intraRefresh(googH265(), 480, 360);
+    }
+
+    public void testGoogH264Flex360pWithIntraRefresh() {
+        intraRefresh(googH264(), 480, 360);
+    }
+
+    public void testGoogH263Flex360pWithIntraRefresh() {
+        intraRefresh(googH263(), 480, 360);
+    }
+
+    public void testGoogMpeg4Flex360pWithIntraRefresh() {
+        intraRefresh(googMpeg4(), 480, 360);
+    }
+
+    public void testGoogVP8Flex360pWithIntraRefresh() {
+        intraRefresh(googVP8(), 480, 360);
+    }
+
+    public void testOtherH265Flex360pWithIntraRefresh() {
+        intraRefresh(otherH265(), 480, 360);
+    }
+
+    public void testOtherH264Flex360pWithIntraRefresh() {
+        intraRefresh(otherH264(), 480, 360);
+    }
+
+    public void testOtherH263FlexQCIFWithIntraRefresh() {
+        intraRefresh(otherH263(), 176, 120);
+    }
+
+    public void testOtherMpeg4Flex360pWithIntraRefresh() {
+        intraRefresh(otherMpeg4(), 480, 360);
+    }
+
+    public void testOtherVP8Flex360pWithIntraRefresh() {
+        intraRefresh(otherVP8(), 480, 360);
+    }
+
     // Tests encoder profiles required by CDD.
     // H264
     public void testH264LowQualitySDSupport()   {
@@ -1581,6 +1765,23 @@
         }
     }
 
+    /* test intra refresh with flexYUV */
+    private void intraRefresh(Encoder[] encoders, int width, int height) {
+        boolean skipped = true;
+        if (encoders.length == 0) {
+            MediaUtils.skipTest("no such encoder present");
+            return;
+        }
+        for (Encoder encoder : encoders) {
+            if (encoder.testIntraRefresh(width, height)) {
+                skipped = false;
+            }
+        }
+        if (skipped) {
+            MediaUtils.skipTest("intra-refresh unsupported");
+        }
+    }
+
     /* test size, frame rate and bit rate */
     private void detailed(
             Encoder[] encoders, int width, int height, int frameRate, int bitRate,
diff --git a/tests/tests/mediastress/preconditions/src/android/mediastress/cts/preconditions/MediaPreparer.java b/tests/tests/mediastress/preconditions/src/android/mediastress/cts/preconditions/MediaPreparer.java
index 35d4bbd..7254045 100644
--- a/tests/tests/mediastress/preconditions/src/android/mediastress/cts/preconditions/MediaPreparer.java
+++ b/tests/tests/mediastress/preconditions/src/android/mediastress/cts/preconditions/MediaPreparer.java
@@ -18,14 +18,11 @@
 import com.android.compatibility.common.tradefed.targetprep.PreconditionPreparer;
 import com.android.compatibility.common.util.DynamicConfigHostSide;
 import com.android.ddmlib.IDevice;
-import com.android.ddmlib.Log;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.config.Option;
 import com.android.tradefed.config.OptionClass;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil;
-import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.targetprep.BuildError;
 import com.android.tradefed.targetprep.TargetSetupError;
 import com.android.tradefed.util.FileUtil;
@@ -150,7 +147,7 @@
         if(!matcher.find()) {
             // could not find resolution in dumpsysOutput, return largest max playback resolution
             // so that preparer copies all media files
-            CLog.e(MAX_PLAYBACK_RES_FAILURE_MSG);
+            logError(MAX_PLAYBACK_RES_FAILURE_MSG);
             return resolutions[RES_1920_1080];
         }
 
@@ -160,7 +157,7 @@
             first = Integer.parseInt(matcher.group(1));
             second = Integer.parseInt(matcher.group(2));
         } catch (NumberFormatException e) {
-            CLog.e(MAX_PLAYBACK_RES_FAILURE_MSG);
+            logError(MAX_PLAYBACK_RES_FAILURE_MSG);
             return resolutions[RES_1920_1080];
         }
         // dimensions in dumpsys output seem consistently reversed
@@ -195,11 +192,6 @@
         return true;
     }
 
-    /* A simple helper to print messages to the tradefed console */
-    private static void printInfo(String info) {
-        LogUtil.printLog(Log.LogLevel.INFO, LOG_TAG, info);
-    }
-
     /*
      * After downloading and unzipping the media files, mLocalMediaPath must be the path to the
      * directory containing 'bbb_short' and 'bbb_full' directories, as it is defined in its
@@ -249,7 +241,7 @@
                     new BufferedOutputStream(new FileOutputStream(mediaFolderZip));
             byte[] buffer = new byte[1024];
             int count;
-            printInfo("Downloading media files to host");
+            logInfo("Downloading media files to host");
             while ((count = in.read(buffer)) >= 0) {
                 out.write(buffer, 0, count);
             }
@@ -257,7 +249,7 @@
             out.close();
             in.close();
 
-            printInfo("Unzipping media files");
+            logInfo("Unzipping media files");
             ZipUtil.extractZip(new ZipFile(mediaFolderZip), mediaFolder);
 
         } catch (IOException e) {
@@ -283,16 +275,15 @@
             Dimension copiedResolution = resolutions[resIndex];
             String resString = resolutionString(copiedResolution);
             if (copiedResolution.width > mvpr.width || copiedResolution.height > mvpr.height) {
-                printInfo(String.format(
-                        "Device cannot support resolutions %s and larger, media copying complete",
-                        resString));
+                logInfo("Device cannot support resolutions %s and larger, media copying complete",
+                        resString);
                 return;
             }
             String deviceShortFilePath = baseDeviceShortDir + resString;
             String deviceFullFilePath = baseDeviceFullDir + resString;
             if (!device.doesFileExist(deviceShortFilePath) ||
                     !device.doesFileExist(deviceFullFilePath)) {
-                printInfo(String.format("Copying files of resolution %s to device", resString));
+                logInfo("Copying files of resolution %s to device", resString);
                 String localShortDirName = "bbb_short/" + resString;
                 String localFullDirName = "bbb_full/" + resString;
                 File localShortDir = new File(mLocalMediaPath, localShortDirName);
@@ -330,7 +321,7 @@
         Dimension mvpr = getMaxVideoPlaybackResolution(device);
         if (mediaFilesExistOnDevice(device, mvpr)) {
             // if files already on device, do nothing
-            printInfo("Media files found on the device");
+            logInfo("Media files found on the device");
             return;
         }
 
@@ -356,7 +347,7 @@
             updateLocalMediaPath(mediaFolder);
         }
 
-        printInfo(String.format("Media files located on host at: %s", mLocalMediaPath));
+        logInfo("Media files located on host at: %s", mLocalMediaPath);
         copyMediaFiles(device, mvpr);
     }
 
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/MediaPlayerStressTest.java b/tests/tests/mediastress/src/android/mediastress/cts/MediaPlayerStressTest.java
index 6f4ebdd..b33451b 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/MediaPlayerStressTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/MediaPlayerStressTest.java
@@ -19,7 +19,6 @@
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.content.Intent;
-import android.media.CamcorderProfile;
 import android.cts.util.MediaUtils;
 import android.media.MediaRecorder.AudioEncoder;
 import android.media.MediaRecorder.VideoEncoder;
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/NativeMediaActivity.java b/tests/tests/mediastress/src/android/mediastress/cts/NativeMediaActivity.java
index a37d4c2..ca935c4 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/NativeMediaActivity.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/NativeMediaActivity.java
@@ -20,7 +20,6 @@
 import android.app.Activity;
 import android.content.res.Configuration;
 import android.graphics.SurfaceTexture;
-import android.media.CamcorderProfile;
 import android.os.Bundle;
 import android.util.Log;
 import android.view.Surface;
@@ -34,7 +33,7 @@
 import junit.framework.Assert;
 
 public class NativeMediaActivity extends Activity implements OnSurfaceChangedListener {
-    public static final String EXTRA_VIDEO_QUALITY = "videoQuality";
+    public static final String EXTRA_VIDEO_HEIGHT = "videoHeight";
     // should be long enough. time-out can be treated as error
     public static final long NATIVE_MEDIA_LIFECYCLE_TIMEOUT_MS = 10000;
     static final String TAG = "NativeMedia";
@@ -51,8 +50,7 @@
 
     private SurfaceTextureGLSurfaceView mGLView;
     private volatile boolean mNativeCreated = false;
-    /** 0 for default (480x360), other value can be CamcorderProfile.QUALITY_480P / 720P / 1080P */
-    private int mVideoQuality = 0;
+    private int mVideoHeight = 360;
     // native media status queued whenever there is a change in life.
     private final BlockingQueue<Boolean> mNativeWaitQ = new LinkedBlockingQueue<Boolean>();
 
@@ -61,7 +59,7 @@
         super.onCreate(icicle);
         getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
                 WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
-        mVideoQuality = getIntent().getIntExtra(EXTRA_VIDEO_QUALITY, mVideoQuality);
+        mVideoHeight = getIntent().getIntExtra(EXTRA_VIDEO_HEIGHT, mVideoHeight);
         mGLView = new SurfaceTextureGLSurfaceView(this, this);
         setContentView(mGLView);
     }
@@ -159,14 +157,14 @@
 
     private String getMediaString() {
         int mediaIndex = 0; // default: 480x360
-        switch(mVideoQuality) {
-        case CamcorderProfile.QUALITY_1080P:
+        switch(mVideoHeight) {
+        case 1080:
             mediaIndex = 3;
             break;
-        case CamcorderProfile.QUALITY_720P:
+        case 720:
             mediaIndex = 2;
             break;
-        case CamcorderProfile.QUALITY_480P:
+        case 480:
             mediaIndex = 1;
             break;
         }
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/NativeMediaTest.java b/tests/tests/mediastress/src/android/mediastress/cts/NativeMediaTest.java
index 05145f5..40284a6 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/NativeMediaTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/NativeMediaTest.java
@@ -18,7 +18,6 @@
 import android.app.Instrumentation;
 import android.content.Intent;
 import android.cts.util.MediaUtils;
-import android.media.CamcorderProfile;
 import android.media.MediaFormat;
 import android.media.MediaRecorder.AudioEncoder;
 import android.media.MediaRecorder.VideoEncoder;
@@ -40,37 +39,30 @@
     }
 
     public void test1080pPlay() throws InterruptedException {
-        runPlayTest(CamcorderProfile.QUALITY_1080P);
+        runPlayTest(1920, 1080);
     }
 
     public void test720pPlay() throws InterruptedException {
-        runPlayTest(CamcorderProfile.QUALITY_720P);
+        runPlayTest(1280, 720);
     }
 
     public void test480pPlay() throws InterruptedException {
-        runPlayTest(CamcorderProfile.QUALITY_480P);
+        runPlayTest(720, 480);
     }
 
     public void testDefaultPlay() throws InterruptedException {
-        runPlayTest(0);
+        runPlayTest(480, 360);
     }
 
-    private void runPlayTest(int quality) throws InterruptedException {
+    private void runPlayTest(int width, int height) throws InterruptedException {
+        MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, width, height);
         // Don't run the test if the codec isn't supported.
-        if (!MediaUtils.checkDecoder(MIME_TYPE)) {
+        if (!MediaUtils.canDecode(format)) {
             return; // skip
         }
-        // Don't run the test if the quality level isn't supported.
-        if (quality != 0) {
-            if (!isResolutionSupported(quality)) {
-                Log.w(TAG, "Quality level " + quality + " not supported.");
-                return;
-            }
-        }
 
         Intent intent = new Intent();
-        intent.putExtra(NativeMediaActivity.EXTRA_VIDEO_QUALITY,
-                quality);
+        intent.putExtra(NativeMediaActivity.EXTRA_VIDEO_HEIGHT, height);
         setActivityIntent(intent);
         final NativeMediaActivity activity = getActivity();
         final Instrumentation instrumentation = getInstrumentation();
@@ -98,17 +90,4 @@
         Assert.assertNotNull(status); // null means time-out
         Assert.assertEquals(expectAlive, status.booleanValue());
     }
-
-    private boolean isResolutionSupported(int quality) {
-        Assert.assertEquals(Environment.getExternalStorageState(), Environment.MEDIA_MOUNTED);
-        if (!CamcorderProfile.hasProfile(quality)) {
-            return false;
-        }
-        CamcorderProfile profile = CamcorderProfile.get(quality);
-        if ((profile != null) && (profile.videoCodec == VIDEO_CODEC) &&
-                (profile.audioCodec == AudioEncoder.AAC)) {
-            return true;
-        }
-        return false;
-    }
 }
diff --git a/tests/tests/nativemedia/sl/Android.mk b/tests/tests/nativemedia/sl/Android.mk
index 8019823..e782994 100644
--- a/tests/tests/nativemedia/sl/Android.mk
+++ b/tests/tests/nativemedia/sl/Android.mk
@@ -51,6 +51,8 @@
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
 
+LOCAL_CFLAGS := -Werror -Wall
+
 include $(BUILD_CTS_EXECUTABLE)
 
 include $(CLEAR_VARS)
@@ -64,6 +66,7 @@
 
 LOCAL_CFLAGS := \
     -DBUILD_ONLY \
+    -Werror -Wall
 
 LOCAL_SHARED_LIBRARIES := \
     liblog \
diff --git a/tests/tests/net/AndroidManifest.xml b/tests/tests/net/AndroidManifest.xml
index 2bc8216..f8daabf 100644
--- a/tests/tests/net/AndroidManifest.xml
+++ b/tests/tests/net/AndroidManifest.xml
@@ -28,6 +28,7 @@
     <uses-permission android:name="android.permission.RECORD_AUDIO" />
     <uses-permission android:name="android.permission.WAKE_LOCK" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
 
     <application>
         <uses-library android:name="android.test.runner" />
diff --git a/tests/tests/net/src/android/net/cts/AirplaneModeTest.java b/tests/tests/net/src/android/net/cts/AirplaneModeTest.java
new file mode 100644
index 0000000..0a3146c
--- /dev/null
+++ b/tests/tests/net/src/android/net/cts/AirplaneModeTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.cts;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.provider.Settings;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import java.lang.Thread;
+
+public class AirplaneModeTest extends AndroidTestCase {
+    private static final String TAG = "AirplaneModeTest";
+    private static final String FEATURE_BLUETOOTH = "android.hardware.bluetooth";
+    private static final String FEATURE_WIFI = "android.hardware.wifi";
+    private static final int TIMEOUT_MS = 10 * 1000;
+    private boolean mHasFeature;
+    private Context mContext;
+    private ContentResolver resolver;
+
+    public void setup() {
+        mContext= getContext();
+        resolver = mContext.getContentResolver();
+        mHasFeature = (mContext.getPackageManager().hasSystemFeature(FEATURE_BLUETOOTH)
+                       || mContext.getPackageManager().hasSystemFeature(FEATURE_WIFI));
+    }
+
+    public void testAirplaneMode() {
+        setup();
+        if (!mHasFeature) {
+            Log.i(TAG, "The device doesn't support network bluetooth or wifi feature");
+            return;
+        }
+
+        for (int testCount = 0; testCount < 2; testCount++) {
+            if (!doOneTest()) {
+                fail("Airplane mode failed to change in " + TIMEOUT_MS + "msec");
+                return;
+            }
+        }
+    }
+
+    private boolean doOneTest() {
+        boolean airplaneModeOn = isAirplaneModeOn();
+        setAirplaneModeOn(!airplaneModeOn);
+
+        try {
+            Thread.sleep(TIMEOUT_MS);
+        } catch (InterruptedException e) {
+            Log.e(TAG, "Sleep time interrupted.", e);
+        }
+
+        if (airplaneModeOn == isAirplaneModeOn()) {
+            return false;
+        }
+        return true;
+    }
+
+    private void setAirplaneModeOn(boolean enabling) {
+        // Change the system setting for airplane mode
+        Settings.Global.putInt(resolver, Settings.Global.AIRPLANE_MODE_ON, enabling ? 1 : 0);
+    }
+
+    private boolean isAirplaneModeOn() {
+        // Read the system setting for airplane mode
+        return Settings.Global.getInt(mContext.getContentResolver(),
+                                      Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
+    }
+}
diff --git a/tests/tests/net/src/android/net/cts/TheaterModeTest.java b/tests/tests/net/src/android/net/cts/TheaterModeTest.java
new file mode 100644
index 0000000..10fca6f
--- /dev/null
+++ b/tests/tests/net/src/android/net/cts/TheaterModeTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.cts;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.provider.Settings;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import java.lang.Thread;
+
+public class TheaterModeTest extends AndroidTestCase {
+    private static final String TAG = "TheaterModeTest";
+    private static final String FEATURE_BLUETOOTH = "android.hardware.bluetooth";
+    private static final String FEATURE_WIFI = "android.hardware.wifi";
+    private static final int TIMEOUT_MS = 10 * 1000;
+    private boolean mHasFeature;
+    private Context mContext;
+    private ContentResolver resolver;
+
+    public void setup() {
+        mContext= getContext();
+        resolver = mContext.getContentResolver();
+        mHasFeature = (mContext.getPackageManager().hasSystemFeature(FEATURE_BLUETOOTH)
+                       || mContext.getPackageManager().hasSystemFeature(FEATURE_WIFI));
+    }
+
+    public void testTheaterMode() {
+        setup();
+        if (!mHasFeature) {
+            Log.i(TAG, "The device doesn't support network bluetooth or wifi feature");
+            return;
+        }
+
+        for (int testCount = 0; testCount < 2; testCount++) {
+            if (!doOneTest()) {
+                fail("Theater mode failed to change in " + TIMEOUT_MS + "msec");
+                return;
+            }
+        }
+    }
+
+    private boolean doOneTest() {
+        boolean theaterModeOn = isTheaterModeOn();
+
+        setTheaterModeOn(!theaterModeOn);
+        try {
+            Thread.sleep(TIMEOUT_MS);
+        } catch (InterruptedException e) {
+            Log.e(TAG, "Sleep time interrupted.", e);
+        }
+
+        if (theaterModeOn == isTheaterModeOn()) {
+            return false;
+        }
+        return true;
+    }
+
+    private void setTheaterModeOn(boolean enabling) {
+        // Change the system setting for theater mode
+        Settings.Global.putInt(resolver, Settings.Global.THEATER_MODE_ON, enabling ? 1 : 0);
+    }
+
+    private boolean isTheaterModeOn() {
+        // Read the system setting for theater mode
+        return Settings.Global.getInt(mContext.getContentResolver(),
+                                      Settings.Global.THEATER_MODE_ON, 0) != 0;
+    }
+}
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java b/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
index 4478bd4..897e5cf 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
@@ -296,6 +296,8 @@
         for (int i = 0; i < WIFI_SCAN_TEST_ITERATIONS; ++i) {
             startScan();
             // Make sure at least one AP is found.
+            assertTrue("mScanResult should not be null. This may be due to a scan timeout",
+                       mScanResults != null);
             assertFalse("empty scan results!", mScanResults.isEmpty());
             long nowMillis = SystemClock.elapsedRealtime();
             // Keep track of how many APs are fresh in one scan.
@@ -373,7 +375,7 @@
             assertTrue(notExist != pos);
 
             // Enable & disable network
-            boolean disableOthers = false;
+            boolean disableOthers = true;
             assertTrue(mWifiManager.enableNetwork(netId, disableOthers));
             wifiConfiguration = mWifiManager.getConfiguredNetworks().get(pos);
             assertDisableOthers(wifiConfiguration, disableOthers);
@@ -484,6 +486,9 @@
         }
         assertTrue(mWifiManager.isWifiEnabled());
 
+        // This will generate a distinct stack trace if the initial connection fails.
+        connectWifi();
+
         int i = 0;
         for (; i < 15; i++) {
             // Wait for a WiFi connection
diff --git a/tests/tests/automotive/Android.mk b/tests/tests/networksecurityconfig/networksecurityconfig-cleartext/Android.mk
similarity index 73%
copy from tests/tests/automotive/Android.mk
copy to tests/tests/networksecurityconfig/networksecurityconfig-cleartext/Android.mk
index abef2ac..df29b5f 100644
--- a/tests/tests/automotive/Android.mk
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-cleartext/Android.mk
@@ -11,28 +11,24 @@
 # 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)
+#
+LOCAL_PATH := $(call my-dir)
 
 include $(CLEAR_VARS)
+LOCAL_PACKAGE_NAME := CtsNetSecConfigCleartextTrafficTestCases
 
-LOCAL_PACKAGE_NAME := CtsAutomotiveTestCases
-
-# Don't include this package in any target.
-LOCAL_MODULE_TAGS := optional
-
-# When built, explicitly put it in the data partition.
+LOCAL_MODULE_TAGS := tests
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
-
-LOCAL_JAVA_LIBRARIES := android.car
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner org.apache.http.legacy android-support-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES += $(call all-java-files-under, ../src)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res/
 
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
 
 LOCAL_SDK_VERSION := current
-
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/networksecurityconfig/networksecurityconfig-cleartext/AndroidManifest.xml b/tests/tests/networksecurityconfig/networksecurityconfig-cleartext/AndroidManifest.xml
new file mode 100644
index 0000000..dbb4770
--- /dev/null
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-cleartext/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="android.security.net.config.cts.CtsNetSecConfigCleartextTrafficTestCases">
+  <application>
+      <uses-library android:name="android.test.runner"/>
+      <meta-data android:name="android.security.net.config"
+                 android:resource="@xml/network_security_config" />
+  </application>
+
+  <uses-permission android:name="android.permission.INTERNET" />
+  <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                   android:targetPackage="android.security.net.config.cts.CtsNetSecConfigCleartextTrafficTestCases"
+                   android:label="">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
+</manifest>
diff --git a/tests/tests/automotive/AndroidTest.xml b/tests/tests/networksecurityconfig/networksecurityconfig-cleartext/AndroidTest.xml
similarity index 75%
copy from tests/tests/automotive/AndroidTest.xml
copy to tests/tests/networksecurityconfig/networksecurityconfig-cleartext/AndroidTest.xml
index b4af1f5..9957342 100644
--- a/tests/tests/automotive/AndroidTest.xml
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-cleartext/AndroidTest.xml
@@ -13,12 +13,12 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<configuration description="Config for CTS Automotive test cases">
+<configuration description="Config for CTS CtsNetSecConfigCleartextTraffic test cases">
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
         <option name="cleanup-apks" value="true" />
-        <option name="test-file-name" value="CtsAutomotiveTestCases.apk" />
+        <option name="test-file-name" value="CtsNetSecConfigCleartextTrafficTestCases.apk" />
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="android.support.car.cts" />
+        <option name="package" value="android.security.net.config.cts.CtsNetSecConfigCleartextTrafficTestCases" />
     </test>
 </configuration>
diff --git a/tests/tests/networksecurityconfig/networksecurityconfig-cleartext/res/xml/network_security_config.xml b/tests/tests/networksecurityconfig/networksecurityconfig-cleartext/res/xml/network_security_config.xml
new file mode 100644
index 0000000..987b178
--- /dev/null
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-cleartext/res/xml/network_security_config.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+  <domain-config cleartextTrafficPermitted="false">
+    <domain includeSubdomains="true">android.com</domain>
+    <domain-config cleartextTrafficPermitted="true">
+      <domain>developer.android.com</domain>
+    </domain-config>
+  </domain-config>
+</network-security-config>
diff --git a/tests/tests/networksecurityconfig/networksecurityconfig-cleartext/src/android/security/net/config/cts/CleartextPermittedTest.java b/tests/tests/networksecurityconfig/networksecurityconfig-cleartext/src/android/security/net/config/cts/CleartextPermittedTest.java
new file mode 100644
index 0000000..401b5ac
--- /dev/null
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-cleartext/src/android/security/net/config/cts/CleartextPermittedTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.net.config.cts;
+
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import javax.net.ssl.X509TrustManager;
+import junit.framework.TestCase;
+
+public class CleartextPermittedTest extends TestCase {
+    public void testDefaultAllowed() throws Exception {
+        TestUtils.assertCleartextConnectionSucceeds("google.com", 80);
+        TestUtils.assertTlsConnectionSucceeds("google.com", 443);
+    }
+
+    public void testCleartextBlocked() throws Exception {
+        TestUtils.assertCleartextConnectionFails("android.com", 80);
+        TestUtils.assertTlsConnectionSucceeds("android.com", 443);
+        // subdomains of android.com are also disallowed.
+        TestUtils.assertCleartextConnectionFails("www.android.com", 80);
+        TestUtils.assertTlsConnectionSucceeds("www.android.com", 443);
+    }
+
+    public void testNestedCleartextPermitted() throws Exception {
+        // developer.android.com is explicitly permitted.
+        TestUtils.assertCleartextConnectionSucceeds("developer.android.com", 80);
+        TestUtils.assertTlsConnectionSucceeds("developer.android.com", 443);
+    }
+}
diff --git a/tests/tests/networksecurityconfig/src/android/security/net/config/cts/TestUtils.java b/tests/tests/networksecurityconfig/src/android/security/net/config/cts/TestUtils.java
index 0952cd3..d114ab5 100644
--- a/tests/tests/networksecurityconfig/src/android/security/net/config/cts/TestUtils.java
+++ b/tests/tests/networksecurityconfig/src/android/security/net/config/cts/TestUtils.java
@@ -20,6 +20,7 @@
 
 import java.io.InputStream;
 import java.io.IOException;
+import java.net.HttpURLConnection;
 import java.net.Socket;
 import java.net.URL;
 import java.security.KeyStore;
@@ -28,7 +29,6 @@
 import java.security.cert.X509Certificate;
 import java.util.List;
 import java.util.ArrayList;
-import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLHandshakeException;
 import javax.net.ssl.TrustManager;
@@ -45,17 +45,26 @@
     private TestUtils() {
     }
 
-
     public static void assertTlsConnectionSucceeds(String host, int port) throws Exception {
         assertSslSocketSucceeds(host, port);
-        assertHttpClientHttpsSucceeds(host, port);
-        assertUrlConnectionHttpsSucceeds(host, port);
+        assertHttpClientSucceeds(host, port, true /* https */);
+        assertUrlConnectionSucceeds(host, port, true /* https */);
     }
 
     public static void assertTlsConnectionFails(String host, int port) throws Exception {
         assertSslSocketFails(host, port);
-        assertHttpClientHttpsFails(host, port);
-        assertUrlConnectionHttpsFails(host, port);
+        assertHttpClientFails(host, port, true /* https */);
+        assertUrlConnectionFails(host, port, true /* https */);
+    }
+
+    public static void assertCleartextConnectionSucceeds(String host, int port) throws Exception {
+        assertHttpClientSucceeds(host, port, false /* http */);
+        assertUrlConnectionSucceeds(host, port, false /* http */);
+    }
+
+    public static void assertCleartextConnectionFails(String host, int port) throws Exception {
+        assertHttpClientFails(host, port, false /* http */);
+        assertUrlConnectionFails(host, port, false /* http */);
     }
 
     public static X509TrustManager getDefaultTrustManager() throws Exception {
@@ -95,26 +104,27 @@
         s.getInputStream();
     }
 
-    private static void assertUrlConnectionHttpsFails(String host, int port)
+    private static void assertUrlConnectionFails(String host, int port, boolean https)
             throws Exception {
-        URL url = new URL("https://" + host + ":" + port);
-        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
+        URL url = new URL((https ? "https://" : "http://") + host + ":" + port);
+        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
         try {
             connection.getInputStream();
             fail("Connection to " + host + ":" + port + " succeeded");
-        } catch (SSLHandshakeException expected) {
+        } catch (IOException expected) {
         }
     }
 
-    private static void assertUrlConnectionHttpsSucceeds(String host, int port)
+    private static void assertUrlConnectionSucceeds(String host, int port, boolean https)
             throws Exception {
-        URL url = new URL("https://" + host + ":" + port);
-        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
+        URL url = new URL((https ? "https://" : "http://") + host + ":" + port);
+        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
         connection.getInputStream();
     }
 
-    private static void assertHttpClientHttpsSucceeds(String host, int port) throws Exception {
-        URL url = new URL("https://" + host + ":" + port);
+    private static void assertHttpClientSucceeds(String host, int port, boolean https)
+            throws Exception {
+        URL url = new URL((https ? "https://" : "http://") + host + ":" + port);
         AndroidHttpClient httpClient = AndroidHttpClient.newInstance(null);
         try {
             HttpResponse response = httpClient.execute(new HttpGet(url.toString()));
@@ -123,8 +133,9 @@
         }
     }
 
-    private static void assertHttpClientHttpsFails(String host, int port) throws Exception {
-        URL url = new URL("https://" + host + ":" + port);
+    private static void assertHttpClientFails(String host, int port, boolean https)
+            throws Exception {
+        URL url = new URL((https ? "https://" : "http://") + host + ":" + port);
         AndroidHttpClient httpClient = AndroidHttpClient.newInstance(null);
         try {
             HttpResponse response = httpClient.execute(new HttpGet(url.toString()));
diff --git a/tests/tests/os/Android.mk b/tests/tests/os/Android.mk
index c837ce3..bbee284 100644
--- a/tests/tests/os/Android.mk
+++ b/tests/tests/os/Android.mk
@@ -24,15 +24,17 @@
 # Include both the 32 and 64 bit versions
 LOCAL_MULTILIB := both
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner guava
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    ctsdeviceutil ctstestrunner guava platform-test-annotations
 
 LOCAL_JNI_SHARED_LIBRARIES := libcts_jni libctsos_jni libnativehelper_compat_libc++
 
-LOCAL_SRC_FILES := $(call all-java-files-under, src) \
-        src/android/os/cts/IParcelFileDescriptorPeer.aidl \
-        src/android/os/cts/IEmptyService.aidl \
-        src/android/os/cts/ISeccompIsolatedService.aidl \
-        src/android/os/cts/ISecondary.aidl
+LOCAL_SRC_FILES := \
+    $(call all-java-files-under, src) \
+    src/android/os/cts/IParcelFileDescriptorPeer.aidl \
+    src/android/os/cts/IEmptyService.aidl \
+    src/android/os/cts/ISeccompIsolatedService.aidl \
+    src/android/os/cts/ISecondary.aidl
 
 LOCAL_PACKAGE_NAME := CtsOsTestCases
 
diff --git a/tests/tests/os/src/android/os/cts/CustomClassLoaderTest.java b/tests/tests/os/src/android/os/cts/CustomClassLoaderTest.java
index bd88073..4c4804e 100644
--- a/tests/tests/os/src/android/os/cts/CustomClassLoaderTest.java
+++ b/tests/tests/os/src/android/os/cts/CustomClassLoaderTest.java
@@ -19,6 +19,7 @@
 import java.io.*;
 import java.lang.reflect.*;
 
+import android.platform.test.annotations.Presubmit;
 import android.test.AndroidTestCase;
 
 public class CustomClassLoaderTest extends AndroidTestCase {
@@ -76,6 +77,7 @@
 
     /* Test a custom class loader based on the PathClassLoader.
      */
+    @Presubmit
     public void testCustomPathClassLoader() throws Exception {
         // Try to load the TestClass class by the CustomPathClassLoader.
         try {
diff --git a/tests/tests/os/src/android/os/cts/HardwarePropertiesManagerTest.java b/tests/tests/os/src/android/os/cts/HardwarePropertiesManagerTest.java
deleted file mode 100644
index 4239fa2..0000000
--- a/tests/tests/os/src/android/os/cts/HardwarePropertiesManagerTest.java
+++ /dev/null
@@ -1,145 +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.os.cts;
-
-import android.content.Context;
-import android.os.CpuUsageInfo;
-import android.os.HardwarePropertiesManager;
-import android.os.SystemClock;
-import android.test.AndroidTestCase;
-
-import java.lang.Math;
-
-public class HardwarePropertiesManagerTest extends AndroidTestCase {
-    public static final int MAX_FAN_SPEED = 20000;
-    public static final int MAX_DEVICE_TEMP = 200;
-    public static final int MONITORING_ITERATION_NUMBER = 10;
-
-    // Time between checks in milliseconds.
-    public static final long SLEEP_TIME = 10;
-
-    private void checkFanSpeed(float speed) {
-        assertTrue(speed >= 0 && speed < MAX_FAN_SPEED);
-    }
-
-    private void checkDeviceTemp(float temp) {
-        assertTrue(Math.abs(temp) < MAX_DEVICE_TEMP);
-    }
-
-    private void checkCpuUsageInfo(CpuUsageInfo info) {
-        assertTrue(info.getActive() >= 0 && info.getTotal() >= 0 && info.getTotal() >= info.getActive());
-    }
-
-    private void checkFanSpeeds(float[] fanSpeeds) {
-        for (float speed : fanSpeeds) {
-            checkFanSpeed(speed);
-        }
-    }
-
-    private void checkTemps(float[] temps) {
-        for (float temp : temps) {
-            checkDeviceTemp(temp);
-        }
-    }
-
-    private void checkCpuUsages(CpuUsageInfo[] cpuUsages) {
-        for (CpuUsageInfo info : cpuUsages) {
-            checkCpuUsageInfo(info);
-        }
-    }
-
-    // Check validity of new array of fan speeds:
-    // the number of fans should be the same.
-    private void checkFanSpeeds(float[] speeds, float[] oldSpeeds) {
-        assertEquals(speeds.length, oldSpeeds.length);
-    }
-
-    // Check validity of new array of device temperatures:
-    // the number of entries should be the same.
-    private void checkDeviceTemps(float[] temps, float[] oldTemps) {
-        assertEquals(temps.length, oldTemps.length);
-    }
-
-    // Check validity of new array of cpu usages:
-    // The number of CPUs should be the same and total/active time should not decrease.
-    private void checkCpuUsages(CpuUsageInfo[] infos,
-                                CpuUsageInfo[] oldInfos) {
-        assertEquals(infos.length, oldInfos.length);
-        for (int i = 0; i < infos.length; ++i) {
-            assertTrue(oldInfos[i].getActive() <= infos[i].getActive() &&
-                    oldInfos[i].getTotal() <= infos[i].getTotal());
-        }
-    }
-
-    /**
-     * test points:
-     * 1. Get fan speeds, device temperatures and CPU usage information.
-     * 2. Check for validity.
-     * 3. Sleep.
-     * 4. Do it 10 times and compare with old ones.
-     */
-    public void testHardwarePropertiesManager() throws InterruptedException {
-        HardwarePropertiesManager hm = (HardwarePropertiesManager) getContext().getSystemService(
-            Context.HARDWARE_PROPERTIES_SERVICE);
-
-        float[] oldFanSpeeds = hm.getFanSpeeds();
-        float[] oldCpuTemps = hm.getDeviceTemperatures(
-            HardwarePropertiesManager.DEVICE_TEMPERATURE_CPU);
-        float[] oldGpuTemps = hm.getDeviceTemperatures(
-            HardwarePropertiesManager.DEVICE_TEMPERATURE_GPU);
-        float[] oldBatteryTemps = hm.getDeviceTemperatures(
-            HardwarePropertiesManager.DEVICE_TEMPERATURE_BATTERY);
-        CpuUsageInfo[] oldCpuUsages = hm.getCpuUsages();
-
-        checkFanSpeeds(oldFanSpeeds);
-        checkTemps(oldCpuTemps);
-        checkTemps(oldGpuTemps);
-        checkTemps(oldBatteryTemps);
-        checkCpuUsages(oldCpuUsages);
-
-        for (int i = 0; i < MONITORING_ITERATION_NUMBER; i++) {
-            Thread.sleep(SLEEP_TIME);
-
-            float[] fanSpeeds = hm.getFanSpeeds();
-            float[] cpuTemps = hm.getDeviceTemperatures(
-                HardwarePropertiesManager.DEVICE_TEMPERATURE_CPU);
-            float[] gpuTemps = hm.getDeviceTemperatures(
-                HardwarePropertiesManager.DEVICE_TEMPERATURE_GPU);
-            float[] batteryTemps = hm.getDeviceTemperatures(
-                HardwarePropertiesManager.DEVICE_TEMPERATURE_BATTERY);
-            CpuUsageInfo[] cpuUsages = hm.getCpuUsages();
-
-            checkFanSpeeds(fanSpeeds);
-            checkTemps(cpuTemps);
-            checkTemps(gpuTemps);
-            checkTemps(batteryTemps);
-            checkCpuUsages(cpuUsages);
-
-            checkFanSpeeds(fanSpeeds, oldFanSpeeds);
-            checkDeviceTemps(cpuTemps, oldCpuTemps);
-            checkDeviceTemps(gpuTemps, oldGpuTemps);
-            checkDeviceTemps(batteryTemps, oldBatteryTemps);
-            checkCpuUsages(cpuUsages, oldCpuUsages);
-
-            oldFanSpeeds = fanSpeeds;
-            oldCpuTemps = cpuTemps;
-            oldGpuTemps = gpuTemps;
-            oldBatteryTemps = batteryTemps;
-            oldCpuUsages = cpuUsages;
-        }
-    }
-}
diff --git a/tests/tests/os/src/android/os/cts/SecurityPatchTest.java b/tests/tests/os/src/android/os/cts/SecurityPatchTest.java
index 5516a19..f35af2e 100644
--- a/tests/tests/os/src/android/os/cts/SecurityPatchTest.java
+++ b/tests/tests/os/src/android/os/cts/SecurityPatchTest.java
@@ -32,7 +32,7 @@
     private static final String SECURITY_PATCH_DATE_ERROR =
             "ro.build.version.security_patch should be \"%d-%02d\" or later. Found \"%s\"";
     private static final int SECURITY_PATCH_YEAR = 2016;
-    private static final int SECURITY_PATCH_MONTH = 04;
+    private static final int SECURITY_PATCH_MONTH = 05;
 
     private boolean mSkipTests = false;
 
diff --git a/tests/tests/permission/Android.mk b/tests/tests/permission/Android.mk
index 2de9d9c..c37ddfc 100644
--- a/tests/tests/permission/Android.mk
+++ b/tests/tests/permission/Android.mk
@@ -29,7 +29,8 @@
 
 LOCAL_JAVA_LIBRARIES := telephony-common
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner guava android-ex-camera2
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    ctstestrunner guava android-ex-camera2 platform-test-annotations
 
 LOCAL_JNI_SHARED_LIBRARIES := libctspermission_jni libnativehelper_compat_libc++
 
diff --git a/tests/tests/permission/src/android/permission/cts/Camera2PermissionTest.java b/tests/tests/permission/src/android/permission/cts/Camera2PermissionTest.java
index 021a501..e40d7cb 100644
--- a/tests/tests/permission/src/android/permission/cts/Camera2PermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/Camera2PermissionTest.java
@@ -23,6 +23,7 @@
 import android.hardware.camera2.CameraManager;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.platform.test.annotations.Presubmit;
 import android.test.AndroidTestCase;
 import android.util.Log;
 
@@ -96,6 +97,7 @@
     /**
      * Add and remove availability listeners should work without permission.
      */
+    @Presubmit
     public void testAvailabilityCallback() throws Exception {
         DummyCameraListener availabilityListener = new DummyCameraListener();
         // Remove a not-registered listener is a no-op.
diff --git a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
index 00c655e..617f0ab 100644
--- a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
@@ -107,7 +107,7 @@
                 .getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);
         String myAppDirectory = getContext().getApplicationInfo().dataDir;
         for (ApplicationInfo app : apps) {
-            if (!myAppDirectory.equals(app.dataDir)) {
+            if (app.dataDir != null && !myAppDirectory.equals(app.dataDir)) {
                 writableDirs.addAll(getWritableDirectoriesAndSubdirectoriesOf(new File(app.dataDir)));
             }
         }
@@ -624,7 +624,6 @@
                     "/mnt_ext/badablk3",
                     "/mnt_ext/cache",
                     "/mnt_ext/data",
-                    "/system/etc/dhcpcd/dhcpcd-run-hooks",
                     "/system/etc/security/drm",
                     "/synthesis/hades",
                     "/synthesis/chimaira",
diff --git a/tests/tests/print/AndroidTest.xml b/tests/tests/print/AndroidTest.xml
index 21d8f03..68aa157 100644
--- a/tests/tests/print/AndroidTest.xml
+++ b/tests/tests/print/AndroidTest.xml
@@ -20,5 +20,6 @@
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.print.cts" />
+        <option name="runtime-hint" value="12m35s" />
     </test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/tests/tests/provider/Android.mk b/tests/tests/provider/Android.mk
index b92a924..59fb9f6 100644
--- a/tests/tests/provider/Android.mk
+++ b/tests/tests/provider/Android.mk
@@ -32,7 +32,8 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    ctsdeviceutil ctstestrunner platform-test-annotations
 
 LOCAL_JNI_SHARED_LIBRARIES := libcts_jni libnativehelper_compat_libc++
 
diff --git a/tests/tests/provider/AndroidManifest.xml b/tests/tests/provider/AndroidManifest.xml
index b4836d0..e56ac1d 100644
--- a/tests/tests/provider/AndroidManifest.xml
+++ b/tests/tests/provider/AndroidManifest.xml
@@ -23,7 +23,6 @@
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
     <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
     <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
-    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
     <uses-permission android:name="android.permission.USE_CREDENTIALS" />
     <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
     <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
diff --git a/tests/tests/provider/src/android/provider/cts/BlockedNumberBackupRestoreTest.java b/tests/tests/provider/src/android/provider/cts/BlockedNumberBackupRestoreTest.java
new file mode 100644
index 0000000..fc0333c
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/BlockedNumberBackupRestoreTest.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.provider.cts;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.provider.BlockedNumberContract;
+import android.telecom.Log;
+
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * CTS tests for backup and restore of blocked numbers using local transport.
+ */
+// To run the tests in this file w/o running all the cts tests:
+// make cts
+// cts-tradefed
+// run cts -m CtsProviderTestCases --test android.provider.cts.BlockedNumberBackupRestoreTest
+public class BlockedNumberBackupRestoreTest extends TestCaseThatRunsIfTelephonyIsEnabled {
+    private static final String TAG = "BlockedNumberBackupRestoreTest";
+    private static final String LOCAL_BACKUP_COMPONENT =
+            "android/com.android.internal.backup.LocalTransport";
+    private static final String BLOCKED_NUMBERS_PROVIDER_PACKAGE =
+            "com.android.providers.blockednumber";
+    private static final int BACKUP_TIMEOUT_MILLIS = 4000;
+    private static final Pattern BMGR_ENABLED_PATTERN = Pattern.compile(
+            "^Backup Manager currently (enabled|disabled)$");
+
+    private ContentResolver mContentResolver;
+    private Context mContext;
+    private String mOldTransport;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mContext = getInstrumentation().getContext();
+        mContentResolver = mContext.getContentResolver();
+
+        BlockedNumberTestUtils.setDefaultSmsApp(
+                true, mContext.getPackageName(), getInstrumentation().getUiAutomation());
+
+        mOldTransport = setBackupTransport(LOCAL_BACKUP_COMPONENT);
+        clearBlockedNumbers();
+        wipeBackup();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        wipeBackup();
+        clearBlockedNumbers();
+        setBackupTransport(mOldTransport);
+
+        BlockedNumberTestUtils.setDefaultSmsApp(
+                false, mContext.getPackageName(), getInstrumentation().getUiAutomation());
+
+        super.tearDown();
+    }
+
+    public void testBackupAndRestoreForSingleNumber() throws Exception {
+        if (!hasBackupTransport(LOCAL_BACKUP_COMPONENT)) {
+            Log.i(TAG, "skipping BlockedNumberBackupRestoreTest");
+        }
+
+        Log.i(TAG, "Adding blocked numbers.");
+        insertBlockedNumber("123456789");
+
+        Log.i(TAG, "Running backup.");
+        runBackup();
+        Thread.sleep(BACKUP_TIMEOUT_MILLIS);
+
+        Log.i(TAG, "Clearing blocked numbers.");
+        clearBlockedNumbers();
+        verifyBlockedNumbers();
+
+        Log.i(TAG, "Restoring blocked numbers.");
+        runRestore();
+        Thread.sleep(BACKUP_TIMEOUT_MILLIS);
+        verifyBlockedNumbers("123456789");
+    }
+
+    public void testBackupAndRestoreWithDeletion() throws Exception {
+        if (!hasBackupTransport(LOCAL_BACKUP_COMPONENT)) {
+            Log.i(TAG, "skipping BlockedNumberBackupRestoreTest");
+        }
+
+        Log.i(TAG, "Adding blocked numbers.");
+        insertBlockedNumber("123456789");
+        insertBlockedNumber("223456789");
+        insertBlockedNumber("323456789");
+
+        Log.i(TAG, "Running backup.");
+        runBackup();
+        Thread.sleep(BACKUP_TIMEOUT_MILLIS);
+
+        Log.i(TAG, "Deleting blocked number.");
+        deleteNumber("123456789");
+        verifyBlockedNumbers("223456789", "323456789");
+
+        Log.i(TAG, "Running backup.");
+        runBackup();
+        Thread.sleep(BACKUP_TIMEOUT_MILLIS);
+
+        Log.i(TAG, "Clearing blocked numbers.");
+        clearBlockedNumbers();
+        verifyBlockedNumbers();
+
+        Log.i(TAG, "Restoring blocked numbers.");
+        runRestore();
+        Thread.sleep(BACKUP_TIMEOUT_MILLIS);
+        verifyBlockedNumbers("223456789", "323456789");
+    }
+
+    private void insertBlockedNumber(String number) {
+        ContentValues cv = new ContentValues();
+        cv.put(BlockedNumberContract.BlockedNumbers.COLUMN_ORIGINAL_NUMBER, number);
+        mContentResolver.insert(BlockedNumberContract.BlockedNumbers.CONTENT_URI, cv);
+    }
+
+    private void deleteNumber(String number) {
+        assertEquals(1,
+                mContentResolver.delete(
+                        BlockedNumberContract.BlockedNumbers.CONTENT_URI,
+                        BlockedNumberContract.BlockedNumbers.COLUMN_ORIGINAL_NUMBER + "= ?",
+                        new String[] {number}));
+    }
+
+    private void verifyBlockedNumbers(String ... blockedNumbers) {
+        assertEquals(blockedNumbers.length,
+                mContentResolver.query(
+                        BlockedNumberContract.BlockedNumbers.CONTENT_URI, null, null, null, null)
+                        .getCount());
+        for (String blockedNumber : blockedNumbers) {
+            assertTrue(BlockedNumberContract.isBlocked(mContext, blockedNumber));
+        }
+    }
+
+    private void clearBlockedNumbers() {
+        mContentResolver.delete(BlockedNumberContract.BlockedNumbers.CONTENT_URI, null, null);
+    }
+
+    private boolean hasBackupTransport(String transport) throws Exception {
+        String output = BlockedNumberTestUtils.executeShellCommand(
+                getInstrumentation().getUiAutomation(), "bmgr list transports");
+        for (String t : output.split(" ")) {
+            if ("*".equals(t)) {
+                // skip the current selection marker.
+                continue;
+            } else if (Objects.equals(transport, t)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private String setBackupTransport(String transport) throws Exception {
+        String output = exec("bmgr transport " + transport);
+        Pattern pattern = Pattern.compile("\\(formerly (.*)\\)$");
+        Matcher matcher = pattern.matcher(output);
+        if (matcher.find()) {
+            return matcher.group(1);
+        } else {
+            throw new Exception("non-parsable output setting bmgr transport: " + output);
+        }
+    }
+
+    private void runBackup() throws Exception {
+        exec("bmgr backupnow " + BLOCKED_NUMBERS_PROVIDER_PACKAGE);
+    }
+
+    private void runRestore() throws Exception {
+        exec("bmgr restore " + BLOCKED_NUMBERS_PROVIDER_PACKAGE);
+    }
+
+    private void wipeBackup() throws Exception {
+        exec("bmgr wipe " + LOCAL_BACKUP_COMPONENT + " " + BLOCKED_NUMBERS_PROVIDER_PACKAGE);
+    }
+
+    private String exec(String command) throws Exception {
+        return BlockedNumberTestUtils.executeShellCommand(
+                getInstrumentation().getUiAutomation(), command);
+    }
+}
diff --git a/tests/tests/provider/src/android/provider/cts/BlockedNumberContractTest.java b/tests/tests/provider/src/android/provider/cts/BlockedNumberContractTest.java
index 7ea63f3..9509d00 100644
--- a/tests/tests/provider/src/android/provider/cts/BlockedNumberContractTest.java
+++ b/tests/tests/provider/src/android/provider/cts/BlockedNumberContractTest.java
@@ -43,7 +43,7 @@
 // To run the tests in this file w/o running all the cts tests:
 // make cts
 // cts-tradefed
-// run cts -c android.provider.cts.BlockedNumberContractTest
+// run cts -m CtsProviderTestCases --test android.provider.cts.BlockedNumberContractTest
 public class BlockedNumberContractTest extends TestCaseThatRunsIfTelephonyIsEnabled {
     private ContentResolver mContentResolver;
     private Context mContext;
@@ -105,11 +105,7 @@
         } catch (SecurityException expected) {
         }
 
-        try {
-            BlockedNumberContract.canCurrentUserBlockNumbers(mContext);
-            fail("Should throw SecurityException");
-        } catch (SecurityException expected) {
-        }
+        assertTrue(BlockedNumberContract.canCurrentUserBlockNumbers(mContext));
     }
 
     public void testGetType() throws Exception {
@@ -344,17 +340,7 @@
     }
 
     private void setDefaultSmsApp(boolean setToSmsApp) throws Exception {
-        StringBuilder command = new StringBuilder();
-        command.append("appops set ");
-        command.append(mContext.getPackageName());
-        command.append(" WRITE_SMS ");
-        command.append(setToSmsApp ? "allow" : "default");
-
-        ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation()
-                .executeShellCommand(command.toString());
-
-        InputStream is = new FileInputStream(pfd.getFileDescriptor());
-        final byte[] buffer = new byte[8192];
-        while ((is.read(buffer)) != -1);
+        BlockedNumberTestUtils.setDefaultSmsApp(
+                setToSmsApp, mContext.getPackageName(), getInstrumentation().getUiAutomation());
     }
 }
diff --git a/tests/tests/provider/src/android/provider/cts/BlockedNumberTestUtils.java b/tests/tests/provider/src/android/provider/cts/BlockedNumberTestUtils.java
new file mode 100644
index 0000000..b520542
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/BlockedNumberTestUtils.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.provider.cts;
+
+import android.app.UiAutomation;
+import android.os.ParcelFileDescriptor;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Utility methods for blocked number cts tests.
+ */
+public class BlockedNumberTestUtils {
+    static void setDefaultSmsApp(boolean setToSmsApp, String packageName, UiAutomation uiAutomation)
+            throws Exception {
+        String command = String.format(
+                "appops set %s WRITE_SMS %s", packageName, setToSmsApp ? "allow" : "default");
+        executeShellCommand(uiAutomation, command);
+    }
+
+    static String executeShellCommand(UiAutomation uiAutomation, String command)
+            throws IOException {
+        ParcelFileDescriptor pfd = uiAutomation.executeShellCommand(command.toString());
+        BufferedReader br = null;
+        try (InputStream in = new FileInputStream(pfd.getFileDescriptor());) {
+            br = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
+            String str = null;
+            StringBuilder out = new StringBuilder();
+            while ((str = br.readLine()) != null) {
+                out.append(str);
+            }
+            return out.toString();
+        } finally {
+            if (br != null) {
+                br.close();
+            }
+        }
+    }
+}
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Images_MediaTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Images_MediaTest.java
index 589b5cd..8bf2516 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Images_MediaTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Images_MediaTest.java
@@ -28,6 +28,7 @@
 import android.graphics.BitmapFactory;
 import android.net.Uri;
 import android.os.Environment;
+import android.platform.test.annotations.Presubmit;
 import android.provider.MediaStore.Images.Media;
 import android.provider.MediaStore.Images.Thumbnails;
 import android.test.InstrumentationTestCase;
@@ -178,6 +179,7 @@
         assertEquals(src.getHeight(), result.getHeight());
     }
 
+    @Presubmit
     public void testGetContentUri() {
         Cursor c = null;
         assertNotNull(c = mContentResolver.query(Media.getContentUri("internal"), null, null, null,
diff --git a/tests/tests/provider/src/android/provider/cts/UserDictionary_WordsTest.java b/tests/tests/provider/src/android/provider/cts/UserDictionary_WordsTest.java
index e226fef..27c48d3 100644
--- a/tests/tests/provider/src/android/provider/cts/UserDictionary_WordsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/UserDictionary_WordsTest.java
@@ -26,6 +26,10 @@
 import java.util.ArrayList;
 import java.util.Locale;
 
+/**
+ * NOTE: user dictionary is now accessible only by the current spellchecker and keyboard, so this
+ * test make sure they are not accessible by apps.
+ */
 public class UserDictionary_WordsTest extends AndroidTestCase {
 
     private ContentResolver mContentResolver;
@@ -68,14 +72,8 @@
 
         Cursor cursor = mContentResolver.query(UserDictionary.Words.CONTENT_URI, WORDS_PROJECTION,
                 UserDictionary.Words.WORD + "='" + word + "'", null, null);
-        assertTrue(cursor.moveToFirst());
-        mAddedBackup.add(Uri.withAppendedPath(UserDictionary.Words.CONTENT_URI,
-                cursor.getString(ID_INDEX)));
+        assertFalse("cursor is not empty", cursor.moveToFirst());
 
-        assertEquals(1, cursor.getCount());
-        assertEquals(word, cursor.getString(WORD_INDEX));
-        assertEquals(frequency, cursor.getInt(FREQUENCY_INDEX));
-        assertNull(cursor.getString(LOCALE_INDEX));
         cursor.close();
     }
 
@@ -92,14 +90,8 @@
 
         Cursor cursor = mContentResolver.query(UserDictionary.Words.CONTENT_URI, WORDS_PROJECTION,
                 UserDictionary.Words.WORD + "='" + word + "'", null, null);
-        assertTrue(cursor.moveToFirst());
-        mAddedBackup.add(Uri.withAppendedPath(UserDictionary.Words.CONTENT_URI,
-                cursor.getString(ID_INDEX)));
+        assertFalse("cursor is not empty", cursor.moveToFirst());
 
-        assertEquals(1, cursor.getCount());
-        assertEquals(word, cursor.getString(WORD_INDEX));
-        assertEquals(expectedFrequency, cursor.getInt(FREQUENCY_INDEX));
-        assertEquals(locale.toString(), cursor.getString(LOCALE_INDEX));
         cursor.close();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/CoreMathVerifier.java b/tests/tests/renderscript/src/android/renderscript/cts/CoreMathVerifier.java
index 1400d86..d094119 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/CoreMathVerifier.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/CoreMathVerifier.java
@@ -312,6 +312,14 @@
             cbrt(in.max32()));
     }
 
+    static private Target.Floaty cos(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+                   Math.cos(in.mid()),
+                   Math.cos(in.min()),
+                   Math.cos(in.max()));
+    }
+
     static private Target.Floaty cos(float f, Target t) {
         Target.Floaty in = t.new32(f);
         return t.new32(
@@ -336,6 +344,22 @@
             cos(in.max32()));
     }
 
+    // Computes the cross product of two double-precision 3D vectors.
+    static private void cross(double[] v1, double[] v2, Target.Floaty[] out, Target t) {
+        Target.Floaty a12 = t.multiply(t.newFloaty(v1[1]), t.newFloaty(v2[2]));
+        Target.Floaty a21 = t.multiply(t.newFloaty(v1[2]), t.newFloaty(v2[1]));
+        out[0] = t.subtract(a12, a21);
+        Target.Floaty a02 = t.multiply(t.newFloaty(v1[0]), t.newFloaty(v2[2]));
+        Target.Floaty a20 = t.multiply(t.newFloaty(v1[2]), t.newFloaty(v2[0]));
+        out[1] = t.subtract(a20, a02);
+        Target.Floaty a01 = t.multiply(t.newFloaty(v1[0]), t.newFloaty(v2[1]));
+        Target.Floaty a10 = t.multiply(t.newFloaty(v1[1]), t.newFloaty(v2[0]));
+        out[2] = t.subtract(a01, a10);
+        if (out.length == 4) {
+            out[3] = t.newFloaty(0.f);
+        }
+    }
+
     // Computes the cross product of two 3D vectors.
     static private void cross(float[] v1, float[] v2, Target.Floaty[] out, Target t) {
         Target.Floaty a12 = t.multiply(t.new32(v1[1]), t.new32(v2[2]));
@@ -395,6 +419,14 @@
             expm1(in.max32()));
     }
 
+    static private Target.Floaty floor(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+                    Math.floor(in.mid()),
+                    Math.floor(in.min()),
+                    Math.floor(in.max()));
+    }
+
     static private Target.Floaty hypot(float x, float y, Target t) {
         Target.Floaty inX = t.new32(x);
         Target.Floaty inY = t.new32(y);
@@ -499,6 +531,11 @@
         }
     }
 
+    static private Target.Floaty rsqrt(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.divide(t.newFloaty(1.), t.sqrt(in));
+    }
+
     static private Target.Floaty rsqrt(float f, Target t) {
         Target.Floaty in = t.new32(f);
         return t.divide(t.new32(1.f), t.sqrt(in));
@@ -1050,6 +1087,15 @@
         args.out = t.new32(Math.copySign(args.inMagnitudeValue, args.inSignValue));
     }
 
+    static public void computeCos(TestCos.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(4, 128);
+        Target.Floaty in = t.newFloaty(args.inVDouble);
+        args.out =  t.newFloaty(
+                        Math.cos(in.mid()),
+                        Math.cos(in.min()),
+                        Math.cos(in.max()));
+    }
+
     static public void computeCos(TestCos.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(4, 128);
         args.out = cos(args.inV, t);
@@ -1065,6 +1111,11 @@
         args.out = cospi(args.inV, t);
     }
 
+    static public void computeCross(TestCross.ArgumentsHalfNHalfNHalfN args, Target t) {
+        t.setPrecision(1, 4);
+        cross(args.inLeftVectorDouble, args.inRightVectorDouble, args.out, t);
+    }
+
     static public void computeCross(TestCross.ArgumentsFloatNFloatNFloatN args, Target t) {
         t.setPrecision(1, 4);
         cross(args.inLeftVector, args.inRightVector, args.out, t);
@@ -1195,6 +1246,11 @@
             Math.max(0.f, r.max32()));
     }
 
+    static public void computeFloor(TestFloor.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(0, 0);
+        args.out = floor(args.inVDouble, t);
+    }
+
     static public void computeFloor(TestFloor.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(0, 0);
         Target.Floaty in = t.new32(args.inV);
@@ -1866,6 +1922,11 @@
             round(in.max32()));
     }
 
+    static public void computeRsqrt(TestRsqrt.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(2, 2);
+        args.out = rsqrt(args.inVDouble, t);
+    }
+
     static public void computeRsqrt(TestRsqrt.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(2, 2);
         args.out = rsqrt(args.inV, t);
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/RSBaseCompute.java b/tests/tests/renderscript/src/android/renderscript/cts/RSBaseCompute.java
index 384e41c..8ef08f3 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/RSBaseCompute.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/RSBaseCompute.java
@@ -129,7 +129,7 @@
             alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
         } else if (dataType == Element.DataType.FLOAT_16) {
             short[] inArray = new short[INPUTSIZE * width];
-            short min = 1024; // 0x0400 in hex, 2^-14, i.e. float16 MIN_NORMAL
+            short min = RSUtils.FLOAT16_MIN_NORMAL;
             short max = 19456; // 0x4c00 in hex, 16.0 in float16
             RSUtils.genRandomFloat16s(seed, min, max, inArray, includeExtremes);
             alloc.copyFrom(inArray);
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/RSUtils.java b/tests/tests/renderscript/src/android/renderscript/cts/RSUtils.java
index e7524a6..a95687d 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/RSUtils.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/RSUtils.java
@@ -26,6 +26,11 @@
  * This class supplies some utils for renderscript tests
  */
 public class RSUtils {
+    public static final short FLOAT16_POSITIVE_INFINITY = (short) 0x7c00;
+    public static final short FLOAT16_NEGATIVE_INFINITY = (short) 0xfc00;
+    public static final short FLOAT16_MIN_NORMAL        = (short) 0x0400;  // 0.00006103516
+    public static final short FLOAT16_MAX_VALUE         = (short) 0x7bff;  // 65504
+
     private static final double[] sInterestingDoubles = {
         0.0,
         1.0,
@@ -182,10 +187,10 @@
         }
         if (includeExtremes) {
             array[r.nextInt(array.length)] = (short) 0x7c01; // NaN
-            array[r.nextInt(array.length)] = (short) 0x7c00; // POSITIVE_INFINITY
-            array[r.nextInt(array.length)] = (short) 0xfc00; // NEGATIVE_INFINITY
-            array[r.nextInt(array.length)] = (short) 0x0400; // MIN_NORMAL, 0.00006103516
-            array[r.nextInt(array.length)] = (short) 0x7bff; // MAX_VALUE, 65504
+            array[r.nextInt(array.length)] = FLOAT16_POSITIVE_INFINITY;
+            array[r.nextInt(array.length)] = FLOAT16_NEGATIVE_INFINITY;
+            array[r.nextInt(array.length)] = FLOAT16_MIN_NORMAL;
+            array[r.nextInt(array.length)] = FLOAT16_MAX_VALUE;
             array[r.nextInt(array.length)] = (short) 0x8400; // -MIN_NORMAL, -0.00006103516
             array[r.nextInt(array.length)] = (short) 0xfbff; // -MAX_VALUE, -65504
         }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/ReduceTest.java b/tests/tests/renderscript/src/android/renderscript/cts/ReduceTest.java
index e30f3d3..b3c495c 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/ReduceTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/ReduceTest.java
@@ -31,13 +31,45 @@
         mScript = new ScriptC_reduce(mRS);
         mScript.set_negInf(Float.NEGATIVE_INFINITY);
         mScript.set_posInf(Float.POSITIVE_INFINITY);
+        mScript.invoke_setInfsHalf(RSUtils.FLOAT16_NEGATIVE_INFINITY, RSUtils.FLOAT16_POSITIVE_INFINITY);
     }
 
     ///////////////////////////////////////////////////////////////////
 
-    private void assertEquals(Int2 javaRslt, Int2 rsRslt) {
-        assertEquals("x", javaRslt.x, rsRslt.x);
-        assertEquals("y", javaRslt.y, rsRslt.y);
+    private void assertEquals(final float[] javaRslt, final float[] rsRslt) {
+        assertEquals("length", javaRslt.length, rsRslt.length);
+        for (int i = 0; i < javaRslt.length; ++i)
+            assertEquals(String.valueOf(i), javaRslt[i], rsRslt[i]);
+    }
+
+    private void assertEquals(final short[] javaRslt, final short[] rsRslt) {
+        assertEquals("length", javaRslt.length, rsRslt.length);
+        for (int i = 0; i < javaRslt.length; ++i)
+            assertEquals(String.valueOf(i), javaRslt[i], rsRslt[i]);
+    }
+
+    private void assertEquals(final Short2[] javaRslt, final Short2[] rsRslt) {
+        assertEquals("length", javaRslt.length, rsRslt.length);
+        for (int i = 0; i < javaRslt.length; ++i)
+            assertEquals(String.valueOf(i), javaRslt[i], rsRslt[i]);
+    }
+
+    private void assertEquals(final String msg, final Int2 javaRslt, final Int2 rsRslt) {
+        assertEquals(msg + "(x)", javaRslt.x, rsRslt.x);
+        assertEquals(msg + "(y)", javaRslt.y, rsRslt.y);
+    }
+
+    private void assertEquals(final Int2 javaRslt, final Int2 rsRslt) {
+        assertEquals("", javaRslt, rsRslt);
+    }
+
+    private void assertEquals(final String msg, final Short2 javaRslt, final Short2 rsRslt) {
+        assertEquals(msg + "(x)", javaRslt.x, rsRslt.x);
+        assertEquals(msg + "(y)", javaRslt.y, rsRslt.y);
+    }
+
+    private void assertEquals(final Short2 javaRslt, final Short2 rsRslt) {
+        assertEquals("", javaRslt, rsRslt);
     }
 
     // Create a zero-initialized Allocation.
@@ -91,6 +123,12 @@
         return array;
     }
 
+    private static short[] createInputArrayHalf(int len, int seed) {
+        short[] array = new short[len];
+        RSUtils.genRandomFloat16s(seed, RSUtils.FLOAT16_MIN_NORMAL, RSUtils.FLOAT16_MAX_VALUE, array, false);
+        return array;
+    }
+
     private static float[] createInputArrayFloat(int len, int seed) {
         Random rand = new Random(seed);
         float[] array = new float[len];
@@ -117,7 +155,7 @@
 
     ///////////////////////////////////////////////////////////////////
 
-    private int addint(int[] input) {
+    private int addint(final int[] input) {
         int rslt = 0;
         for (int idx = 0; idx < input.length; ++idx)
             rslt += input[idx];
@@ -150,7 +188,7 @@
 
     ///////////////////////////////////////////////////////////////////
 
-    private Int2 findMinAndMax(float[] input) {
+    private Int2 findMinAndMax(final float[] input) {
         float minVal = Float.POSITIVE_INFINITY;
         int minIdx = -1;
         float maxVal = Float.NEGATIVE_INFINITY;
@@ -181,6 +219,129 @@
 
     ///////////////////////////////////////////////////////////////////
 
+    private Short2 findMinAndMaxHalf(final short[] inputArray) {
+        Allocation inputAllocation = Allocation.createSized(mRS, Element.F16(mRS), inputArray.length);
+        inputAllocation.copyFrom(inputArray);
+
+        Allocation outputAllocation = Allocation.createSized(mRS, Element.F16_2(mRS), 1);
+
+        mScript.invoke_findMinAndMaxHalf(outputAllocation, inputAllocation);
+
+        short[] outputArray = new short[2];
+        outputAllocation.copyTo(outputArray);
+        return new Short2(outputArray[0], outputArray[1]);
+    }
+
+    private short[] findMinAndMaxHalfIntoArray(final short[] inputArray) {
+        final Short2 vectorResult = findMinAndMaxHalf(inputArray);
+        final short[] arrayResult = new short[] { vectorResult.x, vectorResult.y };
+        return arrayResult;
+    }
+
+    public void testFindMinAndMaxHalf() {
+        // fewer members in the array than there are distinct half values
+        final short[] input = createInputArrayHalf(1000, 23);
+
+        // test Short2 result
+        final Short2 javaRslt = findMinAndMaxHalf(input);
+        final Short2 rsRslt = mScript.reduce_findMinAndMaxHalf(input).get();
+        assertEquals(javaRslt, rsRslt);
+
+        // test short[2] result
+        final short[] javaRsltIntoArray = findMinAndMaxHalfIntoArray(input);
+        final short[] rsRsltIntoArray = mScript.reduce_findMinAndMaxHalfIntoArray(input).get();
+        assertEquals(javaRsltIntoArray, rsRsltIntoArray);
+    }
+
+    ///////////////////////////////////////////////////////////////////
+
+    // The input is a flattened representation of an array of 2-vector
+    private Short2[] findMinAndMaxHalf2(final short[] inputArray) {
+        assertEquals(inputArray.length % 2, 0);
+
+        Allocation inputAllocation = Allocation.createSized(mRS, Element.F16_2(mRS), inputArray.length / 2);
+        inputAllocation.copyFrom(inputArray);
+
+        Allocation outputAllocation = Allocation.createSized(mRS, Element.F16_2(mRS), 2);
+
+        mScript.invoke_findMinAndMaxHalf2(outputAllocation, inputAllocation);
+
+        short[] outputArray = new short[4];
+        outputAllocation.copyTo(outputArray);
+        return new Short2[] { new Short2(outputArray[0], outputArray[1]),
+                              new Short2(outputArray[2], outputArray[3]) };
+    }
+
+    public void testFindMinAndMaxHalf2() {
+        // fewer members in the array than there are distinct half values
+        final short[] input = createInputArrayHalf(1000, 25);
+
+        final Short2[] javaRslt = findMinAndMaxHalf2(input);
+        final Short2[] rsRslt = mScript.reduce_findMinAndMaxHalf2(input).get();
+
+        assertEquals(javaRslt, rsRslt);
+    }
+
+    ///////////////////////////////////////////////////////////////////
+
+    // Both the input and the result are linearized representations of 2x2 matrices.
+    private float[] findMinMat(final float[] inputArray) {
+        float[] result = new float[4];
+        for (int i = 0; i < 4; ++i)
+            result[i] = Float.POSITIVE_INFINITY;
+
+        for (int i = 0; i < inputArray.length; ++i)
+            result[i % 4] = Math.min(result[i % 4], inputArray[i]);
+
+        return result;
+    }
+
+    public void testFindMinMat() {
+        final int length = 100000;
+
+        final float[] inputArray = createInputArrayFloat(4 * length, 24);
+        Allocation inputAllocation = Allocation.createSized(mRS, Element.MATRIX_2X2(mRS), length);
+        inputAllocation.copyFromUnchecked(inputArray);
+
+        final float[] javaRslt = findMinMat(inputArray);
+        final float[] rsRslt = mScript.reduce_findMinMat(inputAllocation).get();
+
+        assertEquals(javaRslt, rsRslt);
+    }
+
+    ///////////////////////////////////////////////////////////////////
+
+    // Both the input and the result are linearized representations of 2x2 matrices.
+    private float[] findMinAndMaxMat(final float[] inputArray) {
+        float[] result = new float[8];
+        for (int i = 0; i < 4; ++i) {
+            result[i+0] = Float.POSITIVE_INFINITY;
+            result[i+4] = Float.NEGATIVE_INFINITY;
+        }
+
+        for (int i = 0; i < inputArray.length; ++i) {
+            result[0 + i % 4] = Math.min(result[0 + i % 4], inputArray[i]);
+            result[4 + i % 4] = Math.max(result[4 + i % 4], inputArray[i]);
+        }
+
+        return result;
+    }
+
+    public void testFindMinAndMaxMat() {
+        final int length = 100000;
+
+        final float[] inputArray = createInputArrayFloat(4 * length, 26);
+        Allocation inputAllocation = Allocation.createSized(mRS, Element.MATRIX_2X2(mRS), length);
+        inputAllocation.copyFromUnchecked(inputArray);
+
+        final float[] javaRslt = findMinAndMaxMat(inputArray);
+        final float[] rsRslt = mScript.reduce_findMinAndMaxMat(inputAllocation).get();
+
+        assertEquals(javaRslt, rsRslt);
+    }
+
+    ///////////////////////////////////////////////////////////////////
+
     public void testFz() {
         final int inputLen = 100000;
         int[] input = createInputArrayInt(inputLen, 5);
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestConvert.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestConvert.java
index 464200d..319b104 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestConvert.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestConvert.java
@@ -10941,7 +10941,7 @@
     }
 
     private void checkConvertDouble2Long2() {
-        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 2, 0x430cbe95l, -4.2949662730000000000e+09, 4.2949662720000000000e+09);
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 2, 0x430cbe95l, -9.2233720368547747840e+18, 9.2233720368547747840e+18);
         try {
             Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
             script.forEach_testConvertLong2Double2Long2(inV, out);
@@ -11009,7 +11009,7 @@
     }
 
     private void checkConvertDouble3Long3() {
-        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 3, 0xa2148389l, -4.2949662730000000000e+09, 4.2949662720000000000e+09);
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 3, 0xa2148389l, -9.2233720368547747840e+18, 9.2233720368547747840e+18);
         try {
             Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
             script.forEach_testConvertLong3Double3Long3(inV, out);
@@ -11077,7 +11077,7 @@
     }
 
     private void checkConvertDouble4Long4() {
-        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 4, 0x11c487dl, -4.2949662730000000000e+09, 4.2949662720000000000e+09);
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 4, 0x11c487dl, -9.2233720368547747840e+18, 9.2233720368547747840e+18);
         try {
             Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
             script.forEach_testConvertLong4Double4Long4(inV, out);
@@ -11568,7 +11568,7 @@
     }
 
     private void checkConvertDouble2Ulong2() {
-        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 2, 0x7e12ff5el, 0.0000000000000000000e+00, 4.2949652480000000000e+09);
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 2, 0x7e12ff5el, 0.0000000000000000000e+00, 1.8446744073709549568e+19);
         try {
             Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
             script.forEach_testConvertUlong2Double2Ulong2(inV, out);
@@ -11636,7 +11636,7 @@
     }
 
     private void checkConvertDouble3Ulong3() {
-        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 3, 0x742e203cl, 0.0000000000000000000e+00, 4.2949652480000000000e+09);
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 3, 0x742e203cl, 0.0000000000000000000e+00, 1.8446744073709549568e+19);
         try {
             Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
             script.forEach_testConvertUlong3Double3Ulong3(inV, out);
@@ -11704,7 +11704,7 @@
     }
 
     private void checkConvertDouble4Ulong4() {
-        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 4, 0x6a49411al, 0.0000000000000000000e+00, 4.2949652480000000000e+09);
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 4, 0x6a49411al, 0.0000000000000000000e+00, 1.8446744073709549568e+19);
         try {
             Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
             script.forEach_testConvertUlong4Double4Ulong4(inV, out);
@@ -18077,7 +18077,7 @@
     }
 
     private void checkConvertFloat2Long2() {
-        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x7d7c0ae0l, -1.0000000000000000000e+00, 0.0000000000000000000e+00);
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x7d7c0ae0l, -9.2233714870989619200e+18, 9.2233714870989619200e+18);
         try {
             Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
             script.forEach_testConvertLong2Float2Long2(inV, out);
@@ -18145,7 +18145,7 @@
     }
 
     private void checkConvertFloat3Long3() {
-        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xdc83cfd4l, -1.0000000000000000000e+00, 0.0000000000000000000e+00);
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xdc83cfd4l, -9.2233714870989619200e+18, 9.2233714870989619200e+18);
         try {
             Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
             script.forEach_testConvertLong3Float3Long3(inV, out);
@@ -18213,7 +18213,7 @@
     }
 
     private void checkConvertFloat4Long4() {
-        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x3b8b94c8l, -1.0000000000000000000e+00, 0.0000000000000000000e+00);
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x3b8b94c8l, -9.2233714870989619200e+18, 9.2233714870989619200e+18);
         try {
             Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
             script.forEach_testConvertLong4Float4Long4(inV, out);
@@ -19540,7 +19540,7 @@
     }
 
     private void checkConvertFloat2Ulong2() {
-        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x4ec4cff7l, 0.0000000000000000000e+00, 0.0000000000000000000e+00);
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x4ec4cff7l, 0.0000000000000000000e+00, 1.8446742974197923840e+19);
         try {
             Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
             script.forEach_testConvertUlong2Float2Ulong2(inV, out);
@@ -19608,7 +19608,7 @@
     }
 
     private void checkConvertFloat3Ulong3() {
-        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x44dff0d5l, 0.0000000000000000000e+00, 0.0000000000000000000e+00);
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x44dff0d5l, 0.0000000000000000000e+00, 1.8446742974197923840e+19);
         try {
             Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
             script.forEach_testConvertUlong3Float3Ulong3(inV, out);
@@ -19676,7 +19676,7 @@
     }
 
     private void checkConvertFloat4Ulong4() {
-        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x3afb11b3l, 0.0000000000000000000e+00, 0.0000000000000000000e+00);
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x3afb11b3l, 0.0000000000000000000e+00, 1.8446742974197923840e+19);
         try {
             Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
             script.forEach_testConvertUlong4Float4Ulong4(inV, out);
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCos.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCos.java
index 4b7751b..9d9b0e5 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCos.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCos.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkCosHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x151d6890l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testCosHalfHalf(inV, out);
+            verifyResultsCosHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCosHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testCosHalfHalf(inV, out);
+            verifyResultsCosHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCosHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCosHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeCos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkCosHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkCosHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x289f4632l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testCosHalf2Half2(inV, out);
+            verifyResultsCosHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCosHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testCosHalf2Half2(inV, out);
+            verifyResultsCosHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCosHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCosHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeCos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkCosHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkCosHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x87a70b26l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testCosHalf3Half3(inV, out);
+            verifyResultsCosHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCosHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testCosHalf3Half3(inV, out);
+            verifyResultsCosHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCosHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCosHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeCos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkCosHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkCosHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xe6aed01al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testCosHalf4Half4(inV, out);
+            verifyResultsCosHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCosHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testCosHalf4Half4(inV, out);
+            verifyResultsCosHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCosHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCosHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeCos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkCosHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testCos() {
         checkCosFloatFloat();
         checkCosFloat2Float2();
         checkCosFloat3Float3();
         checkCosFloat4Float4();
+        checkCosHalfHalf();
+        checkCosHalf2Half2();
+        checkCosHalf3Half3();
+        checkCosHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCos.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCos.rs
index 67f3d14..f7268cc 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCos.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCos.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testCosFloat4Float4(float4 inV) {
     return cos(inV);
 }
+
+half __attribute__((kernel)) testCosHalfHalf(half inV) {
+    return cos(inV);
+}
+
+half2 __attribute__((kernel)) testCosHalf2Half2(half2 inV) {
+    return cos(inV);
+}
+
+half3 __attribute__((kernel)) testCosHalf3Half3(half3 inV) {
+    return cos(inV);
+}
+
+half4 __attribute__((kernel)) testCosHalf4Half4(half4 inV) {
+    return cos(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCross.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCross.java
index 31927b1..57b4a07 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCross.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCross.java
@@ -225,8 +225,214 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfNHalfNHalfN {
+        public short[] inLeftVector;
+        public double[] inLeftVectorDouble;
+        public short[] inRightVector;
+        public double[] inRightVectorDouble;
+        public Target.Floaty[] out;
+    }
+
+    private void checkCrossHalf3Half3Half3() {
+        Allocation inLeftVector = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xfc3afdafl, false);
+        Allocation inRightVector = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xcc0165eal, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInRightVector(inRightVector);
+            script.forEach_testCrossHalf3Half3Half3(inLeftVector, out);
+            verifyResultsCrossHalf3Half3Half3(inLeftVector, inRightVector, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCrossHalf3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRightVector(inRightVector);
+            scriptRelaxed.forEach_testCrossHalf3Half3Half3(inLeftVector, out);
+            verifyResultsCrossHalf3Half3Half3(inLeftVector, inRightVector, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCrossHalf3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCrossHalf3Half3Half3(Allocation inLeftVector, Allocation inRightVector, Allocation out, boolean relaxed) {
+        short[] arrayInLeftVector = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInLeftVector, (short) 42);
+        inLeftVector.copyTo(arrayInLeftVector);
+        short[] arrayInRightVector = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInRightVector, (short) 42);
+        inRightVector.copyTo(arrayInRightVector);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsHalfNHalfNHalfN args = new ArgumentsHalfNHalfNHalfN();
+            // Create the appropriate sized arrays in args
+            args.inLeftVector = new short[3];
+            args.inLeftVectorDouble = new double[3];
+            args.inRightVector = new short[3];
+            args.inRightVectorDouble = new double[3];
+            args.out = new Target.Floaty[3];
+            // Fill args with the input values
+            for (int j = 0; j < 3 ; j++) {
+                args.inLeftVector[j] = arrayInLeftVector[i * 4 + j];
+                args.inLeftVectorDouble[j] = Float16Utils.convertFloat16ToDouble(args.inLeftVector[j]);
+            }
+            for (int j = 0; j < 3 ; j++) {
+                args.inRightVector[j] = arrayInRightVector[i * 4 + j];
+                args.inRightVectorDouble[j] = Float16Utils.convertFloat16ToDouble(args.inRightVector[j]);
+            }
+            Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+            CoreMathVerifier.computeCross(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            for (int j = 0; j < 3 ; j++) {
+                if (!args.out[j].couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+            }
+            if (!valid) {
+                if (!errorFound) {
+                    errorFound = true;
+                    for (int j = 0; j < 3 ; j++) {
+                        message.append("Input inLeftVector: ");
+                        appendVariableToMessage(message, arrayInLeftVector[i * 4 + j]);
+                        message.append("\n");
+                    }
+                    for (int j = 0; j < 3 ; j++) {
+                        message.append("Input inRightVector: ");
+                        appendVariableToMessage(message, arrayInRightVector[i * 4 + j]);
+                        message.append("\n");
+                    }
+                    for (int j = 0; j < 3 ; j++) {
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out[j]);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out[j].couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                    }
+                    message.append("Errors at");
+                }
+                message.append(" [");
+                message.append(Integer.toString(i));
+                message.append("]");
+            }
+        }
+        assertFalse("Incorrect output for checkCrossHalf3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkCrossHalf4Half4Half4() {
+        Allocation inLeftVector = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xa8692054l, false);
+        Allocation inRightVector = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xb7c137a1l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInRightVector(inRightVector);
+            script.forEach_testCrossHalf4Half4Half4(inLeftVector, out);
+            verifyResultsCrossHalf4Half4Half4(inLeftVector, inRightVector, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCrossHalf4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRightVector(inRightVector);
+            scriptRelaxed.forEach_testCrossHalf4Half4Half4(inLeftVector, out);
+            verifyResultsCrossHalf4Half4Half4(inLeftVector, inRightVector, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCrossHalf4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCrossHalf4Half4Half4(Allocation inLeftVector, Allocation inRightVector, Allocation out, boolean relaxed) {
+        short[] arrayInLeftVector = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInLeftVector, (short) 42);
+        inLeftVector.copyTo(arrayInLeftVector);
+        short[] arrayInRightVector = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInRightVector, (short) 42);
+        inRightVector.copyTo(arrayInRightVector);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsHalfNHalfNHalfN args = new ArgumentsHalfNHalfNHalfN();
+            // Create the appropriate sized arrays in args
+            args.inLeftVector = new short[4];
+            args.inLeftVectorDouble = new double[4];
+            args.inRightVector = new short[4];
+            args.inRightVectorDouble = new double[4];
+            args.out = new Target.Floaty[4];
+            // Fill args with the input values
+            for (int j = 0; j < 4 ; j++) {
+                args.inLeftVector[j] = arrayInLeftVector[i * 4 + j];
+                args.inLeftVectorDouble[j] = Float16Utils.convertFloat16ToDouble(args.inLeftVector[j]);
+            }
+            for (int j = 0; j < 4 ; j++) {
+                args.inRightVector[j] = arrayInRightVector[i * 4 + j];
+                args.inRightVectorDouble[j] = Float16Utils.convertFloat16ToDouble(args.inRightVector[j]);
+            }
+            Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+            CoreMathVerifier.computeCross(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            for (int j = 0; j < 4 ; j++) {
+                if (!args.out[j].couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+            }
+            if (!valid) {
+                if (!errorFound) {
+                    errorFound = true;
+                    for (int j = 0; j < 4 ; j++) {
+                        message.append("Input inLeftVector: ");
+                        appendVariableToMessage(message, arrayInLeftVector[i * 4 + j]);
+                        message.append("\n");
+                    }
+                    for (int j = 0; j < 4 ; j++) {
+                        message.append("Input inRightVector: ");
+                        appendVariableToMessage(message, arrayInRightVector[i * 4 + j]);
+                        message.append("\n");
+                    }
+                    for (int j = 0; j < 4 ; j++) {
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out[j]);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out[j].couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                    }
+                    message.append("Errors at");
+                }
+                message.append(" [");
+                message.append(Integer.toString(i));
+                message.append("]");
+            }
+        }
+        assertFalse("Incorrect output for checkCrossHalf4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testCross() {
         checkCrossFloat3Float3Float3();
         checkCrossFloat4Float4Float4();
+        checkCrossHalf3Half3Half3();
+        checkCrossHalf4Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCross.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCross.rs
index e87e0fb..9849707f 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCross.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCross.rs
@@ -30,3 +30,13 @@
     float4 inRightVector = rsGetElementAt_float4(gAllocInRightVector, x);
     return cross(inLeftVector, inRightVector);
 }
+
+half3 __attribute__((kernel)) testCrossHalf3Half3Half3(half3 inLeftVector, unsigned int x) {
+    half3 inRightVector = rsGetElementAt_half3(gAllocInRightVector, x);
+    return cross(inLeftVector, inRightVector);
+}
+
+half4 __attribute__((kernel)) testCrossHalf4Half4Half4(half4 inLeftVector, unsigned int x) {
+    half4 inRightVector = rsGetElementAt_half4(gAllocInRightVector, x);
+    return cross(inLeftVector, inRightVector);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFloor.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFloor.java
index 96c70b9..35238b3 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFloor.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFloor.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkFloorHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x56dc16ffl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testFloorHalfHalf(inV, out);
+            verifyResultsFloorHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFloorHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testFloorHalfHalf(inV, out);
+            verifyResultsFloorHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFloorHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFloorHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFloor(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFloorHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFloorHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x2d925e9l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testFloorHalf2Half2(inV, out);
+            verifyResultsFloorHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFloorHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testFloorHalf2Half2(inV, out);
+            verifyResultsFloorHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFloorHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFloorHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFloor(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFloorHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFloorHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x61e0eaddl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testFloorHalf3Half3(inV, out);
+            verifyResultsFloorHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFloorHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testFloorHalf3Half3(inV, out);
+            verifyResultsFloorHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFloorHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFloorHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFloor(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFloorHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFloorHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xc0e8afd1l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testFloorHalf4Half4(inV, out);
+            verifyResultsFloorHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFloorHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testFloorHalf4Half4(inV, out);
+            verifyResultsFloorHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFloorHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFloorHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFloor(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFloorHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testFloor() {
         checkFloorFloatFloat();
         checkFloorFloat2Float2();
         checkFloorFloat3Float3();
         checkFloorFloat4Float4();
+        checkFloorHalfHalf();
+        checkFloorHalf2Half2();
+        checkFloorHalf3Half3();
+        checkFloorHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFloor.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFloor.rs
index c0c3036..def706d 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFloor.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFloor.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testFloorFloat4Float4(float4 inV) {
     return floor(inV);
 }
+
+half __attribute__((kernel)) testFloorHalfHalf(half inV) {
+    return floor(inV);
+}
+
+half2 __attribute__((kernel)) testFloorHalf2Half2(half2 inV) {
+    return floor(inV);
+}
+
+half3 __attribute__((kernel)) testFloorHalf3Half3(half3 inV) {
+    return floor(inV);
+}
+
+half4 __attribute__((kernel)) testFloorHalf4Half4(half4 inV) {
+    return floor(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRsqrt.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRsqrt.java
index f91495c..118df96 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRsqrt.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRsqrt.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkRsqrtHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x8234e8f1l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testRsqrtHalfHalf(inV, out);
+            verifyResultsRsqrtHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRsqrtHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testRsqrtHalfHalf(inV, out);
+            verifyResultsRsqrtHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRsqrtHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRsqrtHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeRsqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkRsqrtHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkRsqrtHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x175d82cbl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testRsqrtHalf2Half2(inV, out);
+            verifyResultsRsqrtHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRsqrtHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testRsqrtHalf2Half2(inV, out);
+            verifyResultsRsqrtHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRsqrtHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRsqrtHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeRsqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkRsqrtHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkRsqrtHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x766547bfl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testRsqrtHalf3Half3(inV, out);
+            verifyResultsRsqrtHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRsqrtHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testRsqrtHalf3Half3(inV, out);
+            verifyResultsRsqrtHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRsqrtHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRsqrtHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeRsqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkRsqrtHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkRsqrtHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xd56d0cb3l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testRsqrtHalf4Half4(inV, out);
+            verifyResultsRsqrtHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRsqrtHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testRsqrtHalf4Half4(inV, out);
+            verifyResultsRsqrtHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRsqrtHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRsqrtHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeRsqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkRsqrtHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testRsqrt() {
         checkRsqrtFloatFloat();
         checkRsqrtFloat2Float2();
         checkRsqrtFloat3Float3();
         checkRsqrtFloat4Float4();
+        checkRsqrtHalfHalf();
+        checkRsqrtHalf2Half2();
+        checkRsqrtHalf3Half3();
+        checkRsqrtHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRsqrt.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRsqrt.rs
index 579b7af..03ef4a1 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRsqrt.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRsqrt.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testRsqrtFloat4Float4(float4 inV) {
     return rsqrt(inV);
 }
+
+half __attribute__((kernel)) testRsqrtHalfHalf(half inV) {
+    return rsqrt(inV);
+}
+
+half2 __attribute__((kernel)) testRsqrtHalf2Half2(half2 inV) {
+    return rsqrt(inV);
+}
+
+half3 __attribute__((kernel)) testRsqrtHalf3Half3(half3 inV) {
+    return rsqrt(inV);
+}
+
+half4 __attribute__((kernel)) testRsqrtHalf4Half4(half4 inV) {
+    return rsqrt(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/reduce.rs b/tests/tests/renderscript/src/android/renderscript/cts/reduce.rs
index ab2268e..6d7870d 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/reduce.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/reduce.rs
@@ -18,6 +18,19 @@
 
 float negInf, posInf;
 
+static half negInfHalf, posInfHalf;
+
+// At present, no support for global of type half, or for invokable
+// taking an argument of type half.
+static void translate(half *tgt, const short src) {
+  for (int i = 0; i < sizeof(half); ++i)
+    ((char *)tgt)[i] = ((const char *)&src)[i];
+}
+void setInfsHalf(short forNegInfHalf, short forPosInfHalf) {
+  translate(&negInfHalf, forNegInfHalf);
+  translate(&posInfHalf, forPosInfHalf);
+}
+
 /////////////////////////////////////////////////////////////////////////
 
 #pragma rs reduce(addint) \
@@ -27,17 +40,7 @@
 
 /////////////////////////////////////////////////////////////////////////
 
-#pragma rs reduce(dp) \
-  accumulator(dpAccum) combiner(dpSum)
-
-static void dpAccum(float *accum, float in1, float in2) {
-  *accum += in1*in2;
-}
-
-// combiner function
-static void dpSum(float *accum, const float *val) { *accum += *val; }
-
-/////////////////////////////////////////////////////////////////////////
+// Finds LOCATION of min and max float values
 
 #pragma rs reduce(findMinAndMax) \
   initializer(fMMInit) accumulator(fMMAccumulator) \
@@ -84,6 +87,225 @@
 
 /////////////////////////////////////////////////////////////////////////
 
+// finds min and max half values (not their locations)
+
+// tests half input and half2 result
+
+// .. reduction form
+
+#pragma rs reduce(findMinAndMaxHalf) \
+  initializer(fMMHalfInit) accumulator(fMMHalfAccumulator) \
+  combiner(fMMHalfCombiner) outconverter(fMMHalfOutConverter)
+
+typedef struct {
+  half min, max;
+} MinAndMaxHalf;
+
+static void fMMHalfInit(MinAndMaxHalf *accum) {
+  accum->min = posInfHalf;
+  accum->max = negInfHalf;
+}
+
+static void fMMHalfAccumulator(MinAndMaxHalf *accum, half in) {
+  accum->min = fmin(accum->min, in);
+  accum->max = fmax(accum->max, in);
+}
+
+static void fMMHalfCombiner(MinAndMaxHalf *accum,
+                            const MinAndMaxHalf *val) {
+  fMMHalfAccumulator(accum, val->min);
+  fMMHalfAccumulator(accum, val->max);
+}
+
+static void fMMHalfOutConverter(half2 *result,
+                                const MinAndMaxHalf *val) {
+  result->x = val->min;
+  result->y = val->max;
+}
+
+// .. invokable (non reduction) form (no support for half computations in Java)
+
+void findMinAndMaxHalf(rs_allocation out, rs_allocation in) {
+  half min = posInfHalf, max = negInfHalf;
+
+  const uint32_t len = rsAllocationGetDimX(in);
+  for (uint32_t idx = 0; idx < len; ++idx) {
+    const half val = rsGetElementAt_half(in, idx);
+    min = fmin(min, val);
+    max = fmax(max, val);
+  }
+
+  half2 result;
+  result.x = min;
+  result.y = max;
+  rsSetElementAt_half2(out, result, 0);
+}
+
+// tests half input and array of half result;
+//   reuses functions of findMinAndMaxHalf reduction kernel
+
+#pragma rs reduce(findMinAndMaxHalfIntoArray) \
+  initializer(fMMHalfInit) accumulator(fMMHalfAccumulator) \
+  combiner(fMMHalfCombiner) outconverter(fMMHalfOutConverterIntoArray)
+
+static void fMMHalfOutConverterIntoArray(half (*result)[2],
+                                         const MinAndMaxHalf *val) {
+  (*result)[0] = val->min;
+  (*result)[1] = val->max;
+}
+
+/////////////////////////////////////////////////////////////////////////
+
+// finds min and max half2 values (not their locations), element-wise:
+//   result[0].x = fmin(input[...].x)
+//   result[0].y = fmin(input[...].y)
+//   result[1].x = fmax(input[...].x)
+//   result[1].y = fmax(input[...].y)
+
+// tests half2 input and half2[] result
+
+// .. reduction form
+
+#pragma rs reduce(findMinAndMaxHalf2) \
+  initializer(fMMHalf2Init) accumulator(fMMHalf2Accumulator) \
+  combiner(fMMHalf2Combiner) outconverter(fMMHalf2OutConverter)
+
+typedef struct {
+  half2 min, max;
+} MinAndMaxHalf2;
+
+static void fMMHalf2Init(MinAndMaxHalf2 *accum) {
+  accum->min.x = posInfHalf;
+  accum->min.y = posInfHalf;
+  accum->max.x = negInfHalf;
+  accum->max.y = negInfHalf;
+}
+
+static void fMMHalf2Accumulator(MinAndMaxHalf2 *accum, half2 in) {
+  accum->min.x = fmin(accum->min.x, in.x);
+  accum->min.y = fmin(accum->min.y, in.y);
+  accum->max.x = fmax(accum->max.x, in.x);
+  accum->max.y = fmax(accum->max.y, in.y);
+}
+
+static void fMMHalf2Combiner(MinAndMaxHalf2 *accum,
+                            const MinAndMaxHalf2 *val) {
+  fMMHalf2Accumulator(accum, val->min);
+  fMMHalf2Accumulator(accum, val->max);
+}
+
+typedef half2 ArrayOf2Half2[2];
+
+static void fMMHalf2OutConverter(ArrayOf2Half2 *result,
+                                const MinAndMaxHalf2 *val) {
+  (*result)[0] = val->min;
+  (*result)[1] = val->max;
+}
+
+// .. invokable (non reduction) form (no support for half computations in Java)
+
+void findMinAndMaxHalf2(rs_allocation out, rs_allocation in) {
+  half2 min = { posInfHalf, posInfHalf }, max = { negInfHalf, negInfHalf };
+
+  const uint32_t len = rsAllocationGetDimX(in);
+  for (uint32_t idx = 0; idx < len; ++idx) {
+    const half2 val = rsGetElementAt_half2(in, idx);
+    min.x = fmin(min.x, val.x);
+    min.y = fmin(min.y, val.y);
+    max.x = fmax(max.x, val.x);
+    max.y = fmax(max.y, val.y);
+  }
+
+  rsSetElementAt_half2(out, min, 0);
+  rsSetElementAt_half2(out, max, 1);
+}
+
+/////////////////////////////////////////////////////////////////////////
+
+// finds min values (not their locations) from matrix input
+
+// tests matrix input and matrix accumulator
+
+#pragma rs reduce(findMinMat) \
+  initializer(fMinMatInit) accumulator(fMinMatAccumulator) \
+  outconverter(fMinMatOutConverter)
+
+static void fMinMatInit(rs_matrix2x2 *accum) {
+  for (int i = 0; i < 2; ++i)
+    for (int j = 0; j < 2; ++j)
+      rsMatrixSet(accum, i, j, posInf);
+}
+
+static void fMinMatAccumulator(rs_matrix2x2 *accum, rs_matrix2x2 val) {
+  for (int i = 0; i < 2; ++i) {
+    for (int j = 0; j < 2; ++j) {
+      const float accumElt = rsMatrixGet(accum, i, j);
+      const float valElt = rsMatrixGet(&val, i, j);
+      if (valElt < accumElt)
+        rsMatrixSet(accum, i, j, valElt);
+    }
+  }
+}
+
+// reduction does not support matrix result, so use array instead
+static void fMinMatOutConverter(float (*result)[4],  const rs_matrix2x2 *accum) {
+  for (int i = 0; i < 4; ++i)
+    (*result)[i] = accum->m[i];
+}
+
+/////////////////////////////////////////////////////////////////////////
+
+// finds min and max values (not their locations) from matrix input
+
+// tests matrix input and array of matrix accumulator (0 = min, 1 = max)
+
+#pragma rs reduce(findMinAndMaxMat) \
+  initializer(fMinMaxMatInit) accumulator(fMinMaxMatAccumulator) \
+  combiner(fMinMaxMatCombiner) outconverter(fMinMaxMatOutConverter)
+
+typedef rs_matrix2x2 MatrixPair[2];
+enum MatrixPairEntry { MPE_Min = 0, MPE_Max = 1 };  // indices into MatrixPair
+
+static void fMinMaxMatInit(MatrixPair *accum) {
+  for (int i = 0; i < 2; ++i) {
+    for (int j = 0; j < 2; ++j) {
+      rsMatrixSet(&(*accum)[MPE_Min], i, j, posInf);
+      rsMatrixSet(&(*accum)[MPE_Max], i, j, negInf);
+    }
+  }
+}
+
+static void fMinMaxMatAccumulator(MatrixPair *accum, rs_matrix2x2 val) {
+  for (int i = 0; i < 2; ++i) {
+    for (int j = 0; j < 2; ++j) {
+      const float valElt = rsMatrixGet(&val, i, j);
+
+      const float minElt = rsMatrixGet(&(*accum)[MPE_Min], i, j);
+      if (valElt < minElt)
+        rsMatrixSet(&(*accum)[MPE_Min], i, j, valElt);
+
+      const float maxElt = rsMatrixGet(&(*accum)[MPE_Max], i, j);
+      if (valElt > maxElt)
+        rsMatrixSet(&(*accum)[MPE_Max], i, j, valElt);
+    }
+  }
+}
+
+static void fMinMaxMatCombiner(MatrixPair *accum, const MatrixPair *other) {
+  fMinMaxMatAccumulator(accum, (*other)[MPE_Min]);
+  fMinMaxMatAccumulator(accum, (*other)[MPE_Max]);
+}
+
+// reduction does not support matrix result, so use array instead
+static void fMinMaxMatOutConverter(float (*result)[8],  const MatrixPair *accum) {
+  for (int i = 0; i < 4; ++i) {
+    (*result)[i+0] = (*accum)[MPE_Min].m[i];
+    (*result)[i+4] = (*accum)[MPE_Max].m[i];
+  }
+}
+
+/////////////////////////////////////////////////////////////////////////
+
 #pragma rs reduce(fz) \
   initializer(fzInit) \
   accumulator(fzAccum) combiner(fzCombine)
diff --git a/tests/tests/rsblas/AndroidTest.xml b/tests/tests/rsblas/AndroidTest.xml
index 19e6acc..340ca29 100644
--- a/tests/tests/rsblas/AndroidTest.xml
+++ b/tests/tests/rsblas/AndroidTest.xml
@@ -20,5 +20,6 @@
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.cts.rsblas" />
+        <option name="runtime-hint" value="12m57s" />
     </test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/tests/tests/security/Android.mk b/tests/tests/security/Android.mk
index 19547ff..c6ebf93 100644
--- a/tests/tests/security/Android.mk
+++ b/tests/tests/security/Android.mk
@@ -32,7 +32,7 @@
 
 LOCAL_PACKAGE_NAME := CtsSecurityTestCases
 
-LOCAL_SDK_VERSION := 23
+LOCAL_SDK_VERSION := current
 
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
diff --git a/tests/tests/security/jni/Android.mk b/tests/tests/security/jni/Android.mk
index bf229e7..021abb2 100644
--- a/tests/tests/security/jni/Android.mk
+++ b/tests/tests/security/jni/Android.mk
@@ -35,15 +35,15 @@
 		android_security_cts_AudioFlingerBinderTest.cpp \
 		android_security_cts_AudioEffectBinderTest.cpp \
 		android_security_cts_MediaPlayerInfoLeakTest.cpp \
+		android_security_cts_StagefrightFoundationTest.cpp \
 		android_security_cts_GraphicBufferInfoLeakTest.cpp
 
 LOCAL_C_INCLUDES := $(JNI_H_INCLUDE) \
 										$(TOP)/frameworks/native/include/media/openmax
 
-LOCAL_SHARED_LIBRARIES := libbinder libnativehelper_compat_libc++ liblog libdl libmedia libcrypto
+LOCAL_SHARED_LIBRARIES := libnativehelper liblog libbinder libutils libmedia libselinux libdl libcutils libcrypto libstagefright_foundation
 
 LOCAL_C_INCLUDES += ndk/sources/cpufeatures
-LOCAL_STATIC_LIBRARIES := cpufeatures libselinux libutils libcutils
-LOCAL_CXX_STL := libc++_static
+LOCAL_STATIC_LIBRARIES := cpufeatures
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
index 24c87b1..072f59e 100644
--- a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
+++ b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
@@ -29,6 +29,7 @@
 extern int register_android_security_cts_EncryptionTest(JNIEnv* env);
 extern int register_android_security_cts_AudioEffectBinderTest(JNIEnv* env);
 extern int register_android_security_cts_MediaPlayerInfoLeakTest(JNIEnv* env);
+extern int register_android_security_cts_StagefrightFoundationTest(JNIEnv* env);
 extern int register_android_security_cts_GraphicBufferInfoLeakTest(JNIEnv* env);
 
 jint JNI_OnLoad(JavaVM *vm, void *reserved) {
@@ -90,6 +91,10 @@
         return JNI_ERR;
     }
 
+    if (register_android_security_cts_StagefrightFoundationTest(env)) {
+        return JNI_ERR;
+    }
+
     if (register_android_security_cts_GraphicBufferInfoLeakTest(env)) {
         return JNI_ERR;
     }
diff --git a/tests/tests/security/jni/android_security_cts_AudioEffectBinderTest.cpp b/tests/tests/security/jni/android_security_cts_AudioEffectBinderTest.cpp
index 4c27416..6e94fce 100644
--- a/tests/tests/security/jni/android_security_cts_AudioEffectBinderTest.cpp
+++ b/tests/tests/security/jni/android_security_cts_AudioEffectBinderTest.cpp
@@ -119,7 +119,7 @@
     descriptor.type = EFFECT_UIID_EQUALIZER;
     descriptor.uuid = *EFFECT_UUID_NULL;
     const int32_t priority = 0;
-    const int sessionId = AUDIO_SESSION_OUTPUT_MIX;
+    const audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX;
     const audio_io_handle_t io = AUDIO_IO_HANDLE_NONE;
     const String16 opPackageName("Exploitable");
     status_t status;
diff --git a/tests/tests/security/jni/android_security_cts_StagefrightFoundationTest.cpp b/tests/tests/security/jni/android_security_cts_StagefrightFoundationTest.cpp
new file mode 100644
index 0000000..d16bd38
--- /dev/null
+++ b/tests/tests/security/jni/android_security_cts_StagefrightFoundationTest.cpp
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "AudioEffectBinderTest-JNI"
+
+#include <cstdio>
+#include <jni.h>
+#include <binder/Parcel.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+using namespace android;
+
+/*
+ * Native methods used by
+ * cts/tests/tests/security/src/android/security/cts/StagefrightFoundationTest.java
+ */
+
+static jboolean android_security_cts_StagefrightFoundation_test_aMessageFromParcel(
+        JNIEnv* env __unused, jobject thiz __unused)
+{
+    const int kMaxNumItems = 64;
+    const int kNumItems = kMaxNumItems + 1 + 1000;
+    char name[128];
+
+    Parcel data;
+    data.writeInt32(0);  // what
+    data.writeInt32(kNumItems);  // numItems
+    for (int i = 0; i < kMaxNumItems; ++i) {
+        snprintf(name, sizeof(name), "item-%d", i);
+        data.writeCString(name);  // name
+        data.writeInt32(0);  // kTypeInt32
+        data.writeInt32(i);  // value
+    }
+    data.writeCString("evil");  // name
+    data.writeInt32(0);  // kTypeInt32
+    data.writeInt32(0);  // value
+    // NOTE: This could overwrite mNumItems!
+
+    for (int i = 0; i < 1000; ++i) {
+        snprintf(name, sizeof(name), "evil-%d", i);
+        data.writeCString(name);  // name
+        data.writeInt32(0);  // kTypeInt32
+        data.writeInt32(0);  // value
+    }
+
+    data.setDataPosition(0);
+    sp<AMessage> msg = AMessage::FromParcel(data);
+
+    for (int i = 0; i < kMaxNumItems; ++i) {
+        snprintf(name, sizeof(name), "item-%d", i);
+        int32_t value;
+        if (!msg->findInt32(name, &value)) {
+            ALOGE("cannot find value for %s", name);
+            return JNI_FALSE;
+        }
+        if (value != i) {
+            ALOGE("value is changed: expected %d actual %d", i, value);
+            return JNI_FALSE;
+        }
+    }
+    return JNI_TRUE;
+}
+
+int register_android_security_cts_StagefrightFoundationTest(JNIEnv *env)
+{
+    static JNINativeMethod methods[] = {
+        { "native_test_aMessageFromParcel", "()Z",
+                (void *) android_security_cts_StagefrightFoundation_test_aMessageFromParcel},
+    };
+
+    jclass clazz = env->FindClass("android/security/cts/StagefrightFoundationTest");
+    return env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0]));
+}
diff --git a/tests/tests/security/src/android/security/cts/CertificateData.java b/tests/tests/security/src/android/security/cts/CertificateData.java
index ae216ad..f1116e7 100644
--- a/tests/tests/security/src/android/security/cts/CertificateData.java
+++ b/tests/tests/security/src/android/security/cts/CertificateData.java
@@ -106,7 +106,6 @@
       "29:36:21:02:8B:20:ED:02:F5:66:C5:32:D1:D6:ED:90:9F:45:00:2F",
       "37:9A:19:7B:41:85:45:35:0C:A6:03:69:F3:3C:2E:AF:47:4F:20:79",
       "FA:B7:EE:36:97:26:62:FB:2D:B0:2A:F6:BF:03:FD:E8:7C:4B:2F:9B",
-      "8B:AF:4C:9B:1D:F0:2A:92:F7:DA:12:8E:B9:1B:AC:F4:98:60:4B:6F",
       "9F:74:4E:9F:2B:4D:BA:EC:0F:31:2C:50:B6:56:3B:8E:2D:93:C3:11",
       "A1:4B:48:D9:43:EE:0A:0E:40:90:4F:3C:E0:A4:C0:91:93:51:5D:3F",
       "C9:A8:B9:E7:55:80:5E:58:E3:53:77:A7:25:EB:AF:C3:7B:27:CC:D7",
diff --git a/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java b/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
index 5298196..147a5cd 100644
--- a/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
+++ b/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
@@ -121,7 +121,9 @@
 
     private void checkIfMediaServerDiedForDrm(int res) throws Exception {
         if (!convertDmToFl(res, mFlFilePath)) {
-            fail("Can not convert dm to fl");
+            Log.w(TAG, "Can not convert dm to fl, skip checkIfMediaServerDiedForDrm");
+            mMediaPlayer.release();
+            return;
         }
         Log.d(TAG, "intermediate fl file is " + mFlFilePath);
 
diff --git a/tests/tests/security/src/android/security/cts/RestrictedInformationTest.java b/tests/tests/security/src/android/security/cts/RestrictedInformationTest.java
deleted file mode 100644
index d0247e9..0000000
--- a/tests/tests/security/src/android/security/cts/RestrictedInformationTest.java
+++ /dev/null
@@ -1,64 +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.security.cts;
-
-import android.test.AndroidTestCase;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.util.Enumeration;
-import android.content.pm.PackageManager;
-import android.net.wifi.WifiManager;
-import android.content.Context;
-
-/**
- * Check that restricted information is not available
- * to the untrusted_app domain
- */
-public class RestrictedInformationTest extends AndroidTestCase {
-   /*
-    * Test that wifi Mac address is not available through sysfs
-    */
-    public void testWifiMacAddr() throws Exception {
-        /* if wifi does not exist, exit - PASS */
-        PackageManager pm = getContext().getPackageManager();
-        if (!pm.hasSystemFeature(PackageManager.FEATURE_WIFI))
-            return;
-
-        /* Wifi exists, but is not on - FAIL */
-        WifiManager wifi = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
-        assertTrue("Wifi must be enabled to pass this test.", wifi.isWifiEnabled());
-
-        /* Enumerate through the interfaces */
-        Enumeration<NetworkInterface> theInterfaces = NetworkInterface.getNetworkInterfaces();
-
-        while (theInterfaces.hasMoreElements()) {
-            NetworkInterface netif = theInterfaces.nextElement();
-            String name = netif.getName();
-            /* some devices label wifi network interface as eth */
-            if (!name.contains("wlan") && !name.contains("eth"))
-                continue;
-            /* PASS means that getHardwareAddress throws a socket exception */
-            try {
-                byte[] hwAddr = netif.getHardwareAddress();
-                fail("Mac address for " + name + "is accessible: " + new String(hwAddr) +
-                        "\nTo pass this test, label the address with the sysfs_mac_address\n" +
-                        "selinux label. " +
-                        "e.g. https://android-review.googlesource.com/#/c/162180/1\n");
-            } catch (SocketException se) {/* socket exception if MAC blocked - PASS */}
-        }
-    }
-}
diff --git a/tests/tests/security/src/android/security/cts/StagefrightFoundationTest.java b/tests/tests/security/src/android/security/cts/StagefrightFoundationTest.java
new file mode 100644
index 0000000..9999d88
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/StagefrightFoundationTest.java
@@ -0,0 +1,35 @@
+/*
+ * 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.security.cts;
+
+import junit.framework.TestCase;
+
+public class StagefrightFoundationTest extends TestCase {
+
+    static {
+        System.loadLibrary("ctssecurity_jni");
+    }
+
+    /**
+     * Checks that IEffect::command() cannot leak data.
+     */
+    public void test_aMessageFromParcel() throws Exception {
+        assertTrue(native_test_aMessageFromParcel());
+    }
+
+    private static native boolean native_test_aMessageFromParcel();
+}
diff --git a/tests/tests/systemui/AndroidTest.xml b/tests/tests/systemui/AndroidTest.xml
index d98dae6..61bdae3 100644
--- a/tests/tests/systemui/AndroidTest.xml
+++ b/tests/tests/systemui/AndroidTest.xml
@@ -20,5 +20,6 @@
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.systemui.cts" />
+        <option name="runtime-hint" value="10m19s" />
     </test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/tests/tests/telecom/AndroidTest.xml b/tests/tests/telecom/AndroidTest.xml
index 03f64b3..7f34c0c 100644
--- a/tests/tests/telecom/AndroidTest.xml
+++ b/tests/tests/telecom/AndroidTest.xml
@@ -23,5 +23,6 @@
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.telecom.cts" />
+        <option name="runtime-hint" value="10m20s" />
     </test>
 </configuration>
diff --git a/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java b/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
index 6810b71..8cf20bd 100644
--- a/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
+++ b/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
@@ -756,6 +756,24 @@
         );
     }
 
+    void assertDisconnectReason(final Connection connection, final String disconnectReason) {
+        waitUntilConditionIsTrueOrTimeout(
+                new Condition() {
+                    @Override
+                    public Object expected() {
+                        return disconnectReason;
+                    }
+
+                    @Override
+                    public Object actual() {
+                        return connection.getDisconnectCause().getReason();
+                    }
+                },
+                WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
+                "Connection should have been disconnected with reason: " + disconnectReason
+        );
+    }
+
     void assertConferenceState(final Conference conference, final int state) {
         waitUntilConditionIsTrueOrTimeout(
                 new Condition() {
diff --git a/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
index 7d71c0f..fbda2a3 100644
--- a/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
@@ -285,6 +285,29 @@
         assertConnectionState(connection, Connection.STATE_DISCONNECTED);
     }
 
+    public void testRejectIncomingCallWithMessage() {
+        if (!mShouldTestTelecom) {
+            return;
+        }
+        String disconnectReason = "Test reason for disconnect";
+
+        addAndVerifyNewIncomingCall(createTestNumber(), null);
+        final MockConnection connection = verifyConnectionForIncomingCall();
+
+        final MockInCallService inCallService = mInCallCallbacks.getService();
+
+        final Call call = inCallService.getLastCall();
+
+        assertCallState(call, Call.STATE_RINGING);
+        assertConnectionState(connection, Connection.STATE_RINGING);
+
+        call.reject(true, disconnectReason);
+
+        assertCallState(call, Call.STATE_DISCONNECTED);
+        assertConnectionState(connection, Connection.STATE_DISCONNECTED);
+        assertDisconnectReason(connection, disconnectReason);
+    }
+
     public void testCanAddCall_CannotAddForExistingDialingCall() {
         if (!mShouldTestTelecom) {
             return;
diff --git a/tests/tests/telecom/src/android/telecom/cts/MockConnection.java b/tests/tests/telecom/src/android/telecom/cts/MockConnection.java
index 9bb83a1..fe33a8d 100644
--- a/tests/tests/telecom/src/android/telecom/cts/MockConnection.java
+++ b/tests/tests/telecom/src/android/telecom/cts/MockConnection.java
@@ -70,6 +70,16 @@
     }
 
     @Override
+    public void onReject(String reason) {
+        super.onReject();
+        setDisconnected(new DisconnectCause(DisconnectCause.REJECTED, reason));
+        if (mRemoteConnection != null) {
+            mRemoteConnection.reject();
+        }
+        destroy();
+    }
+
+    @Override
     public void onHold() {
         super.onHold();
         setOnHold();
diff --git a/tests/tests/telecom/src/android/telecom/cts/MockConnectionService.java b/tests/tests/telecom/src/android/telecom/cts/MockConnectionService.java
index ad64e5c..48a1c94 100644
--- a/tests/tests/telecom/src/android/telecom/cts/MockConnectionService.java
+++ b/tests/tests/telecom/src/android/telecom/cts/MockConnectionService.java
@@ -73,6 +73,9 @@
             ConnectionRequest request) {
         final MockConnection connection = new MockConnection();
         connection.setAddress(request.getAddress(), CONNECTION_PRESENTATION);
+        connection.setConnectionCapabilities(
+                connection.getConnectionCapabilities() |
+                        Connection.CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION);
         connection.createMockVideoProvider();
         ((Connection) connection).setVideoState(request.getVideoState());
 
diff --git a/tests/tests/telephony/AndroidManifest.xml b/tests/tests/telephony/AndroidManifest.xml
index 6e9545a..e1905d1 100644
--- a/tests/tests/telephony/AndroidManifest.xml
+++ b/tests/tests/telephony/AndroidManifest.xml
@@ -34,6 +34,56 @@
         <provider android:name="android.telephony.cts.MmsPduProvider"
                   android:authorities="telephonyctstest"
                   android:grantUriPermissions="true" />
+
+        <!-- SmsReceiver, MmsReceiver, ComposeSmsActivity, HeadlessSmsSendService together make
+        this a valid SmsApplication (that can be set as the default SMS app). Although some of these
+        classes don't do anything, they are needed to make this a valid candidate for default SMS
+        app. -->
+        <!-- BroadcastReceiver that listens for incoming SMS messages -->
+        <receiver android:name=".SmsReceiver"
+            android:permission="android.permission.BROADCAST_SMS">
+            <intent-filter>
+                <action android:name="android.provider.Telephony.SMS_DELIVER" />
+            </intent-filter>
+        </receiver>
+
+        <!-- BroadcastReceiver that listens for incoming MMS messages -->
+        <receiver android:name=".MmsReceiver"
+            android:permission="android.permission.BROADCAST_WAP_PUSH">
+            <intent-filter>
+                <action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
+                <data android:mimeType="application/vnd.wap.mms-message" />
+            </intent-filter>
+        </receiver>
+
+        <!-- Activity that allows the user to send new SMS/MMS messages -->
+        <activity android:name=".ComposeSmsActivity" >
+            <intent-filter>
+                <action android:name="android.intent.action.SEND" />
+                <action android:name="android.intent.action.SENDTO" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.BROWSABLE" />
+                <data android:scheme="sms" />
+                <data android:scheme="smsto" />
+                <data android:scheme="mms" />
+                <data android:scheme="mmsto" />
+            </intent-filter>
+        </activity>
+
+        <!-- Service that delivers messages from the phone "quick response" -->
+        <service android:name=".HeadlessSmsSendService"
+            android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"
+            android:exported="true" >
+            <intent-filter>
+                <action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="sms" />
+                <data android:scheme="smsto" />
+                <data android:scheme="mms" />
+                <data android:scheme="mmsto" />
+            </intent-filter>
+        </service>
+
         <uses-library android:name="android.test.runner" />
     </application>
 
diff --git a/tests/tests/telephony/src/android/telephony/cts/ComposeSmsActivity.java b/tests/tests/telephony/src/android/telephony/cts/ComposeSmsActivity.java
new file mode 100644
index 0000000..df1f0a9
--- /dev/null
+++ b/tests/tests/telephony/src/android/telephony/cts/ComposeSmsActivity.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.cts;
+
+import android.app.Activity;
+
+/**
+ * SmsReceiver, MmsReceiver, ComposeSmsActivity, HeadlessSmsSendService together make
+ * this a valid SmsApplication (that can be set as the default SMS app). Although some of these
+ * classes don't do anything, they are needed to make this a valid candidate for default SMS
+ * app. -->
+ */
+public class ComposeSmsActivity extends Activity {
+}
diff --git a/tests/tests/telephony/src/android/telephony/cts/HeadlessSmsSendService.java b/tests/tests/telephony/src/android/telephony/cts/HeadlessSmsSendService.java
new file mode 100644
index 0000000..f3fadb31
--- /dev/null
+++ b/tests/tests/telephony/src/android/telephony/cts/HeadlessSmsSendService.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.cts;
+
+import android.annotation.Nullable;
+import android.app.IntentService;
+import android.content.Intent;
+
+/**
+ * SmsReceiver, MmsReceiver, ComposeSmsActivity, HeadlessSmsSendService together make
+ * this a valid SmsApplication (that can be set as the default SMS app). Although some of these
+ * classes don't do anything, they are needed to make this a valid candidate for default SMS
+ * app. -->
+ */
+public class HeadlessSmsSendService extends IntentService {
+    /**
+     * Creates an IntentService.  Invoked by your subclass's constructor.
+     *
+     * @param name Used to name the worker thread, important only for debugging.
+     */
+    public HeadlessSmsSendService(String name) {
+        super(name);
+    }
+
+    @Override
+    protected void onHandleIntent(@Nullable Intent intent) {
+
+    }
+}
diff --git a/tests/tests/telephony/src/android/telephony/cts/MmsReceiver.java b/tests/tests/telephony/src/android/telephony/cts/MmsReceiver.java
new file mode 100644
index 0000000..d7d4b86
--- /dev/null
+++ b/tests/tests/telephony/src/android/telephony/cts/MmsReceiver.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.cts;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * SmsReceiver, MmsReceiver, ComposeSmsActivity, HeadlessSmsSendService together make
+ * this a valid SmsApplication (that can be set as the default SMS app). Although some of these
+ * classes don't do anything, they are needed to make this a valid candidate for default SMS
+ * app. -->
+ */
+public class MmsReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {
+    }
+}
diff --git a/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java b/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java
index 6b72b82a..db7a974 100755
--- a/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java
@@ -25,7 +25,7 @@
 import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.os.SystemClock;
-import android.telephony.SmsManager;
+import android.provider.Telephony;
 import android.telephony.SmsMessage;
 import android.telephony.TelephonyManager;
 import android.test.AndroidTestCase;
@@ -57,6 +57,7 @@
     private static final String SMS_SEND_ACTION = "CTS_SMS_SEND_ACTION";
     private static final String SMS_DELIVERY_ACTION = "CTS_SMS_DELIVERY_ACTION";
     private static final String DATA_SMS_RECEIVED_ACTION = "android.intent.action.DATA_SMS_RECEIVED";
+    public static final String SMS_DELIVER_DEFAULT_APP_ACTION = "CTS_SMS_DELIVERY_ACTION_DEFAULT_APP";
 
     // List of network operators that don't support SMS delivery report
     private static final List<String> NO_DELIVERY_REPORTS =
@@ -190,6 +191,8 @@
     private SmsBroadcastReceiver mSendReceiver;
     private SmsBroadcastReceiver mDeliveryReceiver;
     private SmsBroadcastReceiver mDataSmsReceiver;
+    private SmsBroadcastReceiver mSmsDeliverReceiver;
+    private SmsBroadcastReceiver mSmsReceivedReceiver;
     private PendingIntent mSentIntent;
     private PendingIntent mDeliveredIntent;
     private Intent mSendIntent;
@@ -254,7 +257,7 @@
         return longText.equals(actualMessage);
     }
 
-    public void testSendMessages() throws InterruptedException {
+    public void testSendAndReceiveMessages() throws InterruptedException {
         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
             return;
         }
@@ -267,16 +270,23 @@
         IntentFilter sendIntentFilter = new IntentFilter(SMS_SEND_ACTION);
         IntentFilter deliveryIntentFilter = new IntentFilter(SMS_DELIVERY_ACTION);
         IntentFilter dataSmsReceivedIntentFilter = new IntentFilter(DATA_SMS_RECEIVED_ACTION);
+        IntentFilter smsDeliverIntentFilter = new IntentFilter(SMS_DELIVER_DEFAULT_APP_ACTION);
+        IntentFilter smsReceivedIntentFilter =
+                new IntentFilter(Telephony.Sms.Intents.SMS_RECEIVED_ACTION);
         dataSmsReceivedIntentFilter.addDataScheme("sms");
         dataSmsReceivedIntentFilter.addDataAuthority("localhost", "19989");
 
         mSendReceiver = new SmsBroadcastReceiver(SMS_SEND_ACTION);
         mDeliveryReceiver = new SmsBroadcastReceiver(SMS_DELIVERY_ACTION);
         mDataSmsReceiver = new SmsBroadcastReceiver(DATA_SMS_RECEIVED_ACTION);
+        mSmsDeliverReceiver = new SmsBroadcastReceiver(SMS_DELIVER_DEFAULT_APP_ACTION);
+        mSmsReceivedReceiver = new SmsBroadcastReceiver(Telephony.Sms.Intents.SMS_RECEIVED_ACTION);
 
         getContext().registerReceiver(mSendReceiver, sendIntentFilter);
         getContext().registerReceiver(mDeliveryReceiver, deliveryIntentFilter);
         getContext().registerReceiver(mDataSmsReceiver, dataSmsReceivedIntentFilter);
+        getContext().registerReceiver(mSmsDeliverReceiver, smsDeliverIntentFilter);
+        getContext().registerReceiver(mSmsReceivedReceiver, smsReceivedIntentFilter);
 
         // send single text sms
         init();
@@ -285,6 +295,12 @@
         if (mDeliveryReportSupported) {
             assertTrue(mDeliveryReceiver.waitForCalls(1, TIME_OUT));
         }
+        // non-default app should receive only SMS_RECEIVED_ACTION
+        assertTrue(mSmsReceivedReceiver.waitForCalls(1, TIME_OUT));
+        assertTrue(mSmsDeliverReceiver.waitForCalls(0, 0));
+
+        // due to permission restrictions, currently there is no way to make this test app the
+        // default SMS app
 
         if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
             // TODO: temp workaround, OCTET encoding for EMS not properly supported
@@ -326,6 +342,9 @@
             if (mDeliveryReportSupported) {
               assertTrue(mDeliveryReceiver.waitForCalls(numParts, TIME_OUT));
             }
+            // non-default app should receive only SMS_RECEIVED_ACTION
+            assertTrue(mSmsReceivedReceiver.waitForCalls(1, TIME_OUT));
+            assertTrue(mSmsDeliverReceiver.waitForCalls(0, 0));
         } else {
             // This GSM network doesn't support Multipart SMS message.
             // Skip the test.
@@ -336,6 +355,8 @@
         mSendReceiver.reset();
         mDeliveryReceiver.reset();
         mDataSmsReceiver.reset();
+        mSmsDeliverReceiver.reset();
+        mSmsReceivedReceiver.reset();
         mReceivedDataSms = false;
         mSentIntent = PendingIntent.getBroadcast(getContext(), 0, mSendIntent,
                 PendingIntent.FLAG_ONE_SHOT);
diff --git a/tests/tests/telephony/src/android/telephony/cts/SmsReceiver.java b/tests/tests/telephony/src/android/telephony/cts/SmsReceiver.java
new file mode 100644
index 0000000..4fdadbb
--- /dev/null
+++ b/tests/tests/telephony/src/android/telephony/cts/SmsReceiver.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.cts;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.provider.Telephony;
+
+public class SmsReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (intent != null && intent.getAction().equals(Telephony.Sms.Intents.SMS_DELIVER_ACTION)) {
+            context.sendBroadcast(new Intent(SmsManagerTest.SMS_DELIVER_DEFAULT_APP_ACTION));
+        }
+    }
+}
diff --git a/tests/tests/text/res/layout/keylistener_layout.xml b/tests/tests/text/res/layout/keylistener_layout.xml
index 96a419d..cb8dbad 100644
--- a/tests/tests/text/res/layout/keylistener_layout.xml
+++ b/tests/tests/text/res/layout/keylistener_layout.xml
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  -->
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+<EditText xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/keylistener_textview"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
diff --git a/tests/tests/text/src/android/text/method/cts/BackspaceTest.java b/tests/tests/text/src/android/text/method/cts/BackspaceTest.java
new file mode 100644
index 0000000..fa2e262
--- /dev/null
+++ b/tests/tests/text/src/android/text/method/cts/BackspaceTest.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text.method.cts;
+
+import android.app.Activity;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.Suppress;
+import android.text.InputType;
+import android.text.method.BaseKeyListener;
+import android.text.method.cts.KeyListenerTestCase;
+import android.view.KeyEvent;
+import android.widget.EditText;
+import android.widget.TextView.BufferType;
+
+/**
+ * Test backspace key handling of {@link android.text.method.BaseKeyListner}.
+ */
+public class BackspaceTest extends KeyListenerTestCase {
+    private static final BaseKeyListener mKeyListener = new BaseKeyListener() {
+        public int getInputType() {
+            return InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL;
+        }
+    };
+
+    // Sync the state to the TextView and call onKeyDown with KEYCODE_DEL key event.
+    // Then update the state to the result of TextView.
+    private void backspace(final EditorState state, int modifiers) {
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mTextView.setText(state.mText, BufferType.EDITABLE);
+                mTextView.setKeyListener(mKeyListener);
+                mTextView.setSelection(state.mSelectionStart, state.mSelectionEnd);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+        assertTrue(mTextView.hasWindowFocus());
+
+        final KeyEvent keyEvent = getKey(KeyEvent.KEYCODE_DEL, modifiers);
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mTextView.onKeyDown(keyEvent.getKeyCode(), keyEvent);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+
+        state.mText = mTextView.getText();
+        state.mSelectionStart = mTextView.getSelectionStart();
+        state.mSelectionEnd = mTextView.getSelectionEnd();
+    }
+
+    @SmallTest
+    public void testSurrogatePairs() {
+        EditorState state = new EditorState();
+
+        state.setByString("U+1F441 |");
+        backspace(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("U+1F441 U+1F5E8 |");
+        backspace(state, 0);
+        state.assertEquals("U+1F441 |");
+        backspace(state, 0);
+        state.assertEquals("|");
+    }
+
+    @SmallTest
+    public void testReplacementSpan() {
+        EditorState state = new EditorState();
+
+        // ReplacementSpan will be set to "()" region.
+        state.setByString("'abc' ( 'de' ) 'fg' |");
+        backspace(state, 0);
+        state.assertEquals("'abc' ( 'de' ) 'f' |");
+        backspace(state, 0);
+        state.assertEquals("'abc' ( 'de' ) |");
+        backspace(state, 0);
+        state.assertEquals("'abc' |");
+        backspace(state, 0);
+        state.assertEquals("'ab' |");
+        backspace(state, 0);
+        state.assertEquals("'a' |");
+        backspace(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("'abc' [ ( 'de' ) ] 'fg'");
+        backspace(state, 0);
+        state.assertEquals("'abc' | 'fg'");
+        backspace(state, 0);
+        state.assertEquals("'ab' | 'fg'");
+        backspace(state, 0);
+        state.assertEquals("'a' | 'fg'");
+        backspace(state, 0);
+        state.assertEquals("| 'fg'");
+        backspace(state, 0);
+        state.assertEquals("| 'fg'");
+
+        state.setByString("'ab' [ 'c' ( 'de' ) 'f' ] 'g'");
+        backspace(state, 0);
+        state.assertEquals("'ab' | 'g'");
+        backspace(state, 0);
+        state.assertEquals("'a' | 'g'");
+        backspace(state, 0);
+        state.assertEquals("| 'g'");
+        backspace(state, 0);
+        state.assertEquals("| 'g'");
+    }
+
+    @SmallTest
+    public void testCombiningEnclosingKeycaps() {
+        EditorState state = new EditorState();
+
+        // U+20E3 is COMBINING ENCLOSING KEYCAP.
+        state.setByString("'1' U+20E3 |");
+        backspace(state, 0);
+        state.assertEquals("|");
+
+        // Variation selector before COMBINING ECLOSING KEYCAP
+        state.setByString("'1' U+FE0E U+20E3 |");
+        backspace(state, 0);
+        state.assertEquals("|");
+    }
+
+    @SmallTest
+    public void testVariationSelector() {
+        EditorState state = new EditorState();
+
+        // U+FE0F is VARIATION SELECTOR-16.
+        state.setByString("'#' U+FE0F |");
+        backspace(state, 0);
+        state.assertEquals("|");
+
+        // U+E0100 is VARIATION SELECTOR-17.
+        state.setByString("U+845B U+E0100 |");
+        backspace(state, 0);
+        state.assertEquals("|");
+    }
+
+    @SmallTest
+    public void testFlags() {
+        EditorState state = new EditorState();
+
+        // U+1F1FA is REGIONAL INDICATOR SYMBOL LETTER U.
+        // U+1F1F8 is REGIONAL INDICATOR SYMBOL LETTER S.
+        state.setByString("U+1F1FA U+1F1F8 |");
+        backspace(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("'a' U+1F1FA U+1F1F8 |");
+        backspace(state, 0);
+        state.assertEquals("'a' |");
+        backspace(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("U+1F1FA U+1F1F8 U+1F1FA U+1F1F8 |");
+        backspace(state, 0);
+        state.assertEquals("U+1F1FA U+1F1F8 |");
+        backspace(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("'a' U+1F1FA U+1F1F8 'b' U+1F1FA U+1F1F8 |");
+        backspace(state, 0);
+        state.assertEquals("'a' U+1F1FA U+1F1F8 'b' |");
+        backspace(state, 0);
+        state.assertEquals("'a' U+1F1FA U+1F1F8 |");
+        backspace(state, 0);
+        state.assertEquals("'a' |");
+        backspace(state, 0);
+        state.assertEquals("|");
+    }
+}
diff --git a/tests/tests/text/src/android/text/method/cts/BaseKeyListenerTest.java b/tests/tests/text/src/android/text/method/cts/BaseKeyListenerTest.java
index ba8bad5..8fa8780 100644
--- a/tests/tests/text/src/android/text/method/cts/BaseKeyListenerTest.java
+++ b/tests/tests/text/src/android/text/method/cts/BaseKeyListenerTest.java
@@ -535,17 +535,6 @@
         listener.forwardDelete(mTextView, content, KeyEvent.KEYCODE_FORWARD_DEL, delKeyEvent);
     }
 
-    private KeyEvent getKey(int keycode, int metaState) {
-        long currentTime = System.currentTimeMillis();
-        return new KeyEvent(
-                currentTime,
-                currentTime,
-                KeyEvent.ACTION_DOWN,
-                keycode,
-                0 /* repeat */,
-                metaState);
-    }
-
     /**
      * Prepares mTextView state for tests by synchronously setting the content and key listener, on
      * the UI thread.
diff --git a/tests/tests/text/src/android/text/method/cts/EditorState.java b/tests/tests/text/src/android/text/method/cts/EditorState.java
new file mode 100644
index 0000000..2a4f0b8
--- /dev/null
+++ b/tests/tests/text/src/android/text/method/cts/EditorState.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text.method.cts;
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.text.Editable;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.style.ReplacementSpan;
+
+import junit.framework.Assert;
+
+/**
+ * Represents an editor state.
+ *
+ * The editor state can be specified by following string format.
+ * - Components are separated by space(U+0020).
+ * - Single-quoted string for printable ASCII characters, e.g. 'a', '123'.
+ * - U+XXXX form can be used for a Unicode code point.
+ * - Components inside '[' and ']' are in selection.
+ * - Components inside '(' and ')' are in ReplacementSpan.
+ * - '|' is for specifying cursor position.
+ *
+ * Selection and cursor can not be specified at the same time.
+ *
+ * Example:
+ *   - "'Hello,' | U+0020 'world!'" means "Hello, world!" is displayed and the cursor position
+ *     is 6.
+ *   - "'abc' [ 'def' ] 'ghi'" means "abcdefghi" is displayed and "def" is selected.
+ *   - "U+1F441 | ( U+1F441 U+1F441 )" means three U+1F441 characters are displayed and
+ *     ReplacementSpan is set from offset 2 to 6.
+ */
+public class EditorState {
+    private static final String REPLACEMENT_SPAN_START = "(";
+    private static final String REPLACEMENT_SPAN_END = ")";
+    private static final String SELECTION_START = "[";
+    private static final String SELECTION_END = "]";
+    private static final String CURSOR = "|";
+
+    public Editable mText;
+    public int mSelectionStart = -1;
+    public int mSelectionEnd = -1;
+
+    public EditorState() {
+    }
+
+    /**
+     * A mocked {@link android.text.style.ReplacementSpan} for testing purpose.
+     */
+    private static class MockReplacementSpan extends ReplacementSpan {
+        public int getSize(Paint paint, CharSequence text, int start, int end,
+                Paint.FontMetricsInt fm) {
+            return 0;
+        }
+        public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top,
+                int y, int bottom, Paint paint) {
+        }
+    }
+
+    // Returns true if the code point is ASCII and graph.
+    private boolean isGraphicAscii(int codePoint) {
+        return 0x20 < codePoint && codePoint < 0x7F;
+    }
+
+    // Setup editor state with string. Please see class description for string format.
+    public void setByString(String string) {
+        final StringBuilder sb = new StringBuilder();
+        int replacementSpanStart = -1;
+        int replacementSpanEnd = -1;
+        mSelectionStart = -1;
+        mSelectionEnd = -1;
+
+        final String[] tokens = string.split(" +");
+        for (String token : tokens) {
+            if (token.startsWith("'") && token.endsWith("'")) {
+                for (int i = 1; i < token.length() - 1; ++i) {
+                    final char ch = token.charAt(1);
+                    if (!isGraphicAscii(ch)) {
+                        throw new IllegalArgumentException(
+                                "Only printable characters can be in single quote. " +
+                                "Use U+" + Integer.toHexString(ch).toUpperCase() + " instead");
+                    }
+                }
+                sb.append(token.substring(1, token.length() - 1));
+            } else if (token.startsWith("U+")) {
+                final int codePoint = Integer.parseInt(token.substring(2), 16);
+                if (codePoint < 0 || 0x10FFFF < codePoint) {
+                    throw new IllegalArgumentException("Invalid code point is specified:" + token);
+                }
+                sb.append(Character.toChars(codePoint));
+            } else if (token.equals(CURSOR)) {
+                if (mSelectionStart != -1 || mSelectionEnd != -1) {
+                    throw new IllegalArgumentException(
+                            "Two or more cursor/selection positions are specified.");
+                }
+                mSelectionStart = mSelectionEnd = sb.length();
+            } else if (token.equals(SELECTION_START)) {
+                if (mSelectionStart != -1) {
+                    throw new IllegalArgumentException(
+                            "Two or more cursor/selection positions are specified.");
+                }
+                mSelectionStart = sb.length();
+            } else if (token.equals(SELECTION_END)) {
+                if (mSelectionEnd != -1) {
+                    throw new IllegalArgumentException(
+                            "Two or more cursor/selection positions are specified.");
+                }
+                mSelectionEnd = sb.length();
+            } else if (token.equals(REPLACEMENT_SPAN_START)) {
+                if (replacementSpanStart != -1) {
+                    throw new IllegalArgumentException(
+                            "Only one replacement span is supported");
+                }
+                replacementSpanStart = sb.length();
+            } else if (token.equals(REPLACEMENT_SPAN_END)) {
+                if (replacementSpanEnd != -1) {
+                    throw new IllegalArgumentException(
+                            "Only one replacement span is supported");
+                }
+                replacementSpanEnd = sb.length();
+            } else {
+                throw new IllegalArgumentException("Unknown or invalid token: " + token);
+            }
+        }
+
+        if (mSelectionStart == -1 || mSelectionEnd == -1) {
+              if (mSelectionEnd != -1) {
+                  throw new IllegalArgumentException(
+                          "Selection start position doesn't exist.");
+              } else if (mSelectionStart != -1) {
+                  throw new IllegalArgumentException(
+                          "Selection end position doesn't exist.");
+              } else {
+                  throw new IllegalArgumentException(
+                          "At least cursor position or selection range must be specified.");
+              }
+        } else if (mSelectionStart > mSelectionEnd) {
+              throw new IllegalArgumentException(
+                      "Selection start position appears after end position.");
+        }
+
+        final Spannable spannable = new SpannableString(sb.toString());
+
+        if (replacementSpanStart != -1 || replacementSpanEnd != -1) {
+            if (replacementSpanStart == -1) {
+                throw new IllegalArgumentException(
+                        "ReplacementSpan start position doesn't exist.");
+            }
+            if (replacementSpanEnd == -1) {
+                throw new IllegalArgumentException(
+                        "ReplacementSpan end position doesn't exist.");
+            }
+            if (replacementSpanStart > replacementSpanEnd) {
+                throw new IllegalArgumentException(
+                        "ReplacementSpan start position appears after end position.");
+            }
+            spannable.setSpan(new MockReplacementSpan(), replacementSpanStart, replacementSpanEnd,
+                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+        }
+        mText = Editable.Factory.getInstance().newEditable(spannable);
+    }
+
+    public void assertEquals(String string) {
+        EditorState expected = new EditorState();
+        expected.setByString(string);
+
+        Assert.assertEquals(expected.mText.toString(), mText.toString());
+        Assert.assertEquals(expected.mSelectionStart, mSelectionStart);
+        Assert.assertEquals(expected.mSelectionEnd, mSelectionEnd);
+    }
+}
+
diff --git a/tests/tests/text/src/android/text/method/cts/ForwardDeleteTest.java b/tests/tests/text/src/android/text/method/cts/ForwardDeleteTest.java
new file mode 100644
index 0000000..47c2795
--- /dev/null
+++ b/tests/tests/text/src/android/text/method/cts/ForwardDeleteTest.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text.method.cts;
+
+import android.app.Activity;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.Suppress;
+import android.text.InputType;
+import android.text.method.BaseKeyListener;
+import android.text.method.cts.KeyListenerTestCase;
+import android.view.KeyEvent;
+import android.widget.EditText;
+import android.widget.TextView.BufferType;
+
+/**
+ * Test forward delete key handling of  {@link android.text.method.BaseKeyListener}.
+ */
+public class ForwardDeleteTest extends KeyListenerTestCase {
+    private static final BaseKeyListener mKeyListener = new BaseKeyListener() {
+        public int getInputType() {
+            return InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL;
+        }
+    };
+
+    // Sync the state to the TextView and call onKeyDown with KEYCODE_FORWARD_DEL key event.
+    // Then update the state to the result of TextView.
+    private void forwardDelete(final EditorState state, int modifiers) {
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mTextView.setText(state.mText, BufferType.EDITABLE);
+                mTextView.setKeyListener(mKeyListener);
+                mTextView.setSelection(state.mSelectionStart, state.mSelectionEnd);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+        assertTrue(mTextView.hasWindowFocus());
+
+        final KeyEvent keyEvent = getKey(KeyEvent.KEYCODE_FORWARD_DEL, modifiers);
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mTextView.onKeyDown(keyEvent.getKeyCode(), keyEvent);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+
+        state.mText = mTextView.getText();
+        state.mSelectionStart = mTextView.getSelectionStart();
+        state.mSelectionEnd = mTextView.getSelectionEnd();
+    }
+
+    @SmallTest
+    public void testSurrogatePairs() {
+        EditorState state = new EditorState();
+
+        // U+1F441 is EYE
+        state.setByString("| U+1F441");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // U+1F5E8 is LEFT SPEECH BUBBLE
+        state.setByString("| U+1F441 U+1F5E8");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F5E8");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+    }
+
+    @SmallTest
+    public void testReplacementSpan() {
+        EditorState state = new EditorState();
+
+        state.setByString("| 'abc' ( 'de' ) 'fg'");
+        forwardDelete(state, 0);
+        state.assertEquals("| 'bc' ( 'de' ) 'fg'");
+        forwardDelete(state, 0);
+        state.assertEquals("| 'c' ( 'de' ) 'fg'");
+        forwardDelete(state, 0);
+        state.assertEquals("| ( 'de' ) 'fg'");
+        forwardDelete(state, 0);
+        state.assertEquals("| 'fg'");
+        forwardDelete(state, 0);
+        state.assertEquals("| 'g'");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("'abc' [ ( 'de' ) ] 'fg'");
+        forwardDelete(state, 0);
+        state.assertEquals("'abc' | 'fg'");
+        forwardDelete(state, 0);
+        state.assertEquals("'abc' | 'g'");
+        forwardDelete(state, 0);
+        state.assertEquals("'abc' |");
+        forwardDelete(state, 0);
+        state.assertEquals("'abc' |");
+
+        state.setByString("'ab' [ 'c' ( 'de' ) 'f' ] 'g'");
+        forwardDelete(state, 0);
+        state.assertEquals("'ab' | 'g'");
+        forwardDelete(state, 0);
+        state.assertEquals("'ab' |");
+        forwardDelete(state, 0);
+        state.assertEquals("'ab' |");
+    }
+
+    @SmallTest
+    public void testCombiningEnclosingKeycaps() {
+        EditorState state = new EditorState();
+
+        // U+20E3 is COMBINING ENCLOSING KEYCAP.
+        state.setByString("| '1' U+20E3");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("| '1' U+FE0F U+20E3");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+    }
+
+    @SmallTest
+    public void testVariationSelector() {
+        EditorState state = new EditorState();
+
+        // U+FE0F is VARIATION SELECTOR-16.
+        state.setByString("| '#' U+FE0F");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // U+E0100 is VARIATION SELECTOR-17.
+        state.setByString("| U+845B U+E0100");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+    }
+
+    @SmallTest
+    public void testFlags() {
+        EditorState state = new EditorState();
+
+        // U+1F1FA is REGIONAL INDICATOR SYMBOL LETTER U.
+        // U+1F1F8 is REGIONAL INDICATOR SYMBOL LETTER S.
+        state.setByString("| U+1F1FA U+1F1F8");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("| U+1F1FA U+1F1F8 U+1F1FA U+1F1F8");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F1FA U+1F1F8");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+    }
+}
diff --git a/tests/tests/text/src/android/text/method/cts/KeyListenerTestCase.java b/tests/tests/text/src/android/text/method/cts/KeyListenerTestCase.java
index 4f89ff3..313d380 100644
--- a/tests/tests/text/src/android/text/method/cts/KeyListenerTestCase.java
+++ b/tests/tests/text/src/android/text/method/cts/KeyListenerTestCase.java
@@ -23,8 +23,9 @@
 import android.text.format.DateUtils;
 import android.text.method.cts.KeyListenerCtsActivity;
 import android.text.method.KeyListener;
+import android.view.KeyEvent;
 import android.view.WindowManager;
-import android.widget.TextView;
+import android.widget.EditText;
 
 /**
  * Base class for various KeyListener tests.
@@ -50,7 +51,7 @@
         ActivityInstrumentationTestCase2<KeyListenerCtsActivity> {
     protected KeyListenerCtsActivity mActivity;
     protected Instrumentation mInstrumentation;
-    protected TextView mTextView;
+    protected EditText mTextView;
 
     public KeyListenerTestCase() {
         super("com.android.cts.text", KeyListenerCtsActivity.class);
@@ -62,7 +63,7 @@
 
         mActivity = getActivity();
         mInstrumentation = getInstrumentation();
-        mTextView = (TextView) mActivity.findViewById(R.id.keylistener_textview);
+        mTextView = (EditText) mActivity.findViewById(R.id.keylistener_textview);
 
         mActivity.runOnUiThread(new Runnable() {
             public void run() {
@@ -85,4 +86,10 @@
         });
         mInstrumentation.waitForIdleSync();
     }
+
+    protected static KeyEvent getKey(int keycode, int metaState) {
+        long currentTime = System.currentTimeMillis();
+        return new KeyEvent(currentTime, currentTime, KeyEvent.ACTION_DOWN, keycode,
+                0 /* repeat */, metaState);
+    }
 }
diff --git a/tests/tests/text/src/android/text/style/cts/AbsoluteSizeSpanTest.java b/tests/tests/text/src/android/text/style/cts/AbsoluteSizeSpanTest.java
index bdd3d17..e825bd1 100644
--- a/tests/tests/text/src/android/text/style/cts/AbsoluteSizeSpanTest.java
+++ b/tests/tests/text/src/android/text/style/cts/AbsoluteSizeSpanTest.java
@@ -47,6 +47,14 @@
         assertEquals(-5, absoluteSizeSpan.getSize());
     }
 
+    public void testGetDip() {
+        AbsoluteSizeSpan absoluteSizeSpan = new AbsoluteSizeSpan(5);
+        assertEquals(false, absoluteSizeSpan.getDip());
+
+        absoluteSizeSpan = new AbsoluteSizeSpan(5, true);
+        assertEquals(true, absoluteSizeSpan.getDip());
+    }
+
     public void testUpdateMeasureState() {
         AbsoluteSizeSpan absoluteSizeSpan = new AbsoluteSizeSpan(1);
 
diff --git a/tests/tests/text/src/android/text/style/cts/EasyEditSpanTest.java b/tests/tests/text/src/android/text/style/cts/EasyEditSpanTest.java
new file mode 100644
index 0000000..7405107
--- /dev/null
+++ b/tests/tests/text/src/android/text/style/cts/EasyEditSpanTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text.style.cts;
+
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.style.EasyEditSpan;
+
+public class EasyEditSpanTest extends AndroidTestCase {
+    @SmallTest
+    public void testConstructor() {
+        new EasyEditSpan();
+        new EasyEditSpan(PendingIntent.getActivity(getContext(), 0, new Intent(), 0));
+        Parcel p = Parcel.obtain();
+        try {
+            new EasyEditSpan(p);
+        } finally {
+            p.recycle();
+        }
+    }
+
+    @SmallTest
+    public void testDescribeContents_doesNotThrowException() {
+        EasyEditSpan easyEditSpan = new EasyEditSpan();
+        easyEditSpan.describeContents();
+    }
+
+    @SmallTest
+    public void testGetSpanTypeId_doesNotThrowException() {
+        EasyEditSpan easyEditSpan = new EasyEditSpan();
+        easyEditSpan.getSpanTypeId();
+    }
+
+    @SmallTest
+    public void testWriteToParcel() {
+        Parcel p = Parcel.obtain();
+        try {
+            EasyEditSpan easyEditSpan = new EasyEditSpan();
+            easyEditSpan.writeToParcel(p, 0);
+            p.setDataPosition(0);
+            new EasyEditSpan(p);
+        } finally {
+            p.recycle();
+        }
+    }
+}
diff --git a/tests/tests/text/src/android/text/style/cts/LocaleSpanTest.java b/tests/tests/text/src/android/text/style/cts/LocaleSpanTest.java
index bc93e41..f44cca5 100644
--- a/tests/tests/text/src/android/text/style/cts/LocaleSpanTest.java
+++ b/tests/tests/text/src/android/text/style/cts/LocaleSpanTest.java
@@ -17,9 +17,10 @@
 package android.text.style.cts;
 
 import junit.framework.TestCase;
-
 import android.annotation.NonNull;
 import android.os.Parcel;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.TextPaint;
 import android.text.style.LocaleSpan;
 import android.util.LocaleList;
 
@@ -35,6 +36,7 @@
         assertEquals(locales, cloned.getLocales());
     }
 
+    @SmallTest
     public void testGetLocales() {
         checkGetLocales(LocaleList.getEmptyLocaleList());
         checkGetLocales(LocaleList.forLanguageTags("en"));
@@ -42,6 +44,7 @@
         checkGetLocales(LocaleList.forLanguageTags("de-DE-u-co-phonebk,en-GB,en"));
     }
 
+    @SmallTest
     public void testConstructorWithLocaleList() {
         try {
             new LocaleSpan((LocaleList) null);
@@ -66,4 +69,48 @@
             }
         }
     }
+
+    @SmallTest
+    public void testDescribeContents_doesNotThrowException() {
+        LocaleSpan localeSpan = new LocaleSpan(LocaleList.getEmptyLocaleList());
+        localeSpan.describeContents();
+    }
+
+    @SmallTest
+    public void testGetSpanTypeId_doesNotThrowException() {
+        LocaleSpan localeSpan = new LocaleSpan(LocaleList.getEmptyLocaleList());
+        localeSpan.getSpanTypeId();
+    }
+
+    @SmallTest
+    public void testUpdateDrawState() {
+        LocaleList localeListForSpan = LocaleList.forLanguageTags("en");
+        LocaleSpan localeSpan = new LocaleSpan(localeListForSpan);
+
+        TextPaint tp = new TextPaint();
+        LocaleList localeList = LocaleList.forLanguageTags("fr,de");
+        tp.setTextLocales(localeList);
+        assertEquals(localeList, tp.getTextLocales());
+        assertEquals(localeList.get(0), tp.getTextLocale());
+
+        localeSpan.updateDrawState(tp);
+        assertEquals(localeListForSpan, tp.getTextLocales());
+        assertEquals(localeListForSpan.get(0), tp.getTextLocale());
+    }
+
+    @SmallTest
+    public void testUpdateMeasureState() {
+        LocaleList localeListForSpan = LocaleList.forLanguageTags("en");
+        LocaleSpan localeSpan = new LocaleSpan(localeListForSpan);
+
+        TextPaint tp = new TextPaint();
+        LocaleList localeList = LocaleList.forLanguageTags("fr,de");
+        tp.setTextLocales(localeList);
+        assertEquals(localeList, tp.getTextLocales());
+        assertEquals(localeList.get(0), tp.getTextLocale());
+
+        localeSpan.updateMeasureState(tp);
+        assertEquals(localeListForSpan, tp.getTextLocales());
+        assertEquals(localeListForSpan.get(0), tp.getTextLocale());
+    }
 }
diff --git a/tests/tests/text/src/android/text/style/cts/TtsSpanTest.java b/tests/tests/text/src/android/text/style/cts/TtsSpanTest.java
index 3c320f1..c718a37 100644
--- a/tests/tests/text/src/android/text/style/cts/TtsSpanTest.java
+++ b/tests/tests/text/src/android/text/style/cts/TtsSpanTest.java
@@ -18,6 +18,7 @@
 
 import android.os.Parcel;
 import android.os.PersistableBundle;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.text.style.TtsSpan;
 import junit.framework.TestCase;
 
@@ -25,6 +26,7 @@
 
     PersistableBundle bundle;
 
+    @Override
     protected void setUp() {
         bundle = new PersistableBundle();
         bundle.putString("argument.one", "value.one");
@@ -33,6 +35,7 @@
         bundle.putLong("argument.four", 4);
     }
 
+    @SmallTest
     public void testGetArgs() {
         TtsSpan t = new TtsSpan("test.type.one", bundle);
         PersistableBundle args = t.getArgs();
@@ -43,21 +46,25 @@
         assertEquals(4, args.getLong("argument.four"));
     }
 
+    @SmallTest
     public void testGetType() {
         TtsSpan t = new TtsSpan("test.type.two", bundle);
         assertEquals("test.type.two", t.getType());
     }
 
+    @SmallTest
     public void testDescribeContents() {
         TtsSpan span = new TtsSpan("test.type.three", bundle);
         span.describeContents();
     }
 
+    @SmallTest
     public void testGetSpanTypeId() {
         TtsSpan span = new TtsSpan("test.type.four", bundle);
         span.getSpanTypeId();
     }
 
+    @SmallTest
     public void testWriteAndReadParcel() {
         Parcel p = Parcel.obtain();
         try {
@@ -78,4 +85,423 @@
             p.recycle();
         }
     }
+
+    @SmallTest
+    public void testBuilder() {
+        final TtsSpan t = (new TtsSpan.Builder<>("test.type.builder"))
+                .setStringArgument("argument.string", "value")
+                .setIntArgument("argument.int", Integer.MAX_VALUE)
+                .setLongArgument("argument.long", Long.MAX_VALUE)
+                .build();
+        assertEquals("test.type.builder", t.getType());
+        PersistableBundle args = t.getArgs();
+        assertEquals(3, args.size());
+        assertEquals("value", args.getString("argument.string"));
+        assertEquals(Integer.MAX_VALUE, args.getInt("argument.int"));
+        assertEquals(Long.MAX_VALUE, args.getLong("argument.long"));
+    }
+
+    @SmallTest
+    public void testSemioticClassBuilder() {
+        final TtsSpan t = (new TtsSpan.SemioticClassBuilder<>("test.type.semioticClassBuilder"))
+                .setGender(TtsSpan.GENDER_FEMALE)
+                .setAnimacy(TtsSpan.ANIMACY_ANIMATE)
+                .setMultiplicity(TtsSpan.MULTIPLICITY_SINGLE)
+                .setCase(TtsSpan.CASE_NOMINATIVE)
+                .build();
+        assertEquals("test.type.semioticClassBuilder", t.getType());
+        PersistableBundle args = t.getArgs();
+        assertEquals(4, args.size());
+        assertEquals(TtsSpan.GENDER_FEMALE, args.getString(TtsSpan.ARG_GENDER));
+        assertEquals(TtsSpan.ANIMACY_ANIMATE, args.getString(TtsSpan.ARG_ANIMACY));
+        assertEquals(TtsSpan.MULTIPLICITY_SINGLE, args.getString(TtsSpan.ARG_MULTIPLICITY));
+        assertEquals(TtsSpan.CASE_NOMINATIVE, args.getString(TtsSpan.ARG_CASE));
+    }
+
+    @SmallTest
+    public void testTextBuilder() {
+        {
+            final TtsSpan t = (new TtsSpan.TextBuilder())
+                    .setText("text")
+                    .build();
+            assertEquals(TtsSpan.TYPE_TEXT, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(1, args.size());
+            assertEquals("text", args.getString(TtsSpan.ARG_TEXT));
+        }
+        {
+            final TtsSpan t = (new TtsSpan.TextBuilder("text")).build();
+            assertEquals(TtsSpan.TYPE_TEXT, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(1, args.size());
+            assertEquals("text", args.getString(TtsSpan.ARG_TEXT));
+        }
+    }
+
+    @SmallTest
+    public void testCardinalBuilder() {
+        {
+            final TtsSpan t = (new TtsSpan.CardinalBuilder())
+                    .setNumber(Long.MAX_VALUE)
+                    .build();
+            assertEquals(TtsSpan.TYPE_CARDINAL, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(1, args.size());
+            assertEquals(String.valueOf(Long.MAX_VALUE), args.getString(TtsSpan.ARG_NUMBER));
+        }
+        {
+            final TtsSpan t = (new TtsSpan.CardinalBuilder())
+                    .setNumber("10")
+                    .build();
+            assertEquals(TtsSpan.TYPE_CARDINAL, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(1, args.size());
+            assertEquals("10", args.getString(TtsSpan.ARG_NUMBER));
+        }
+        {
+            final TtsSpan t = (new TtsSpan.CardinalBuilder(Long.MAX_VALUE)).build();
+            assertEquals(TtsSpan.TYPE_CARDINAL, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(1, args.size());
+            assertEquals(String.valueOf(Long.MAX_VALUE), args.getString(TtsSpan.ARG_NUMBER));
+        }
+        {
+            final TtsSpan t = (new TtsSpan.CardinalBuilder("10")).build();
+            assertEquals(TtsSpan.TYPE_CARDINAL, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(1, args.size());
+            assertEquals("10", args.getString(TtsSpan.ARG_NUMBER));
+        }
+    }
+
+    @SmallTest
+    public void testOrdinalBuilder() {
+        {
+            final TtsSpan t = (new TtsSpan.OrdinalBuilder())
+                    .setNumber(Long.MAX_VALUE)
+                    .build();
+            assertEquals(TtsSpan.TYPE_ORDINAL, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(1, args.size());
+            assertEquals(String.valueOf(Long.MAX_VALUE), args.getString(TtsSpan.ARG_NUMBER));
+        }
+        {
+            final TtsSpan t = (new TtsSpan.OrdinalBuilder())
+                    .setNumber("10")
+                    .build();
+            assertEquals(TtsSpan.TYPE_ORDINAL, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(1, args.size());
+            assertEquals("10", args.getString(TtsSpan.ARG_NUMBER));
+        }
+        {
+            final TtsSpan t = (new TtsSpan.OrdinalBuilder(Long.MAX_VALUE)).build();
+            assertEquals(TtsSpan.TYPE_ORDINAL, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(1, args.size());
+            assertEquals(String.valueOf(Long.MAX_VALUE), args.getString(TtsSpan.ARG_NUMBER));
+        }
+        {
+            final TtsSpan t = (new TtsSpan.OrdinalBuilder("10")).build();
+            assertEquals(TtsSpan.TYPE_ORDINAL, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(1, args.size());
+            assertEquals("10", args.getString(TtsSpan.ARG_NUMBER));
+        }
+    }
+
+    @SmallTest
+    public void testDecimalBuilder() {
+        {
+            final TtsSpan t = (new TtsSpan.DecimalBuilder())
+                    .setArgumentsFromDouble(10.25, 1, 2)
+                    .build();
+            assertEquals(TtsSpan.TYPE_DECIMAL, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(2, args.size());
+            assertEquals("10", args.getString(TtsSpan.ARG_INTEGER_PART));
+            assertEquals("25", args.getString(TtsSpan.ARG_FRACTIONAL_PART));
+        }
+        {
+            final TtsSpan t = (new TtsSpan.DecimalBuilder(10.25, 1, 2)).build();
+            assertEquals(TtsSpan.TYPE_DECIMAL, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(2, args.size());
+            assertEquals("10", args.getString(TtsSpan.ARG_INTEGER_PART));
+            assertEquals("25", args.getString(TtsSpan.ARG_FRACTIONAL_PART));
+        }
+        {
+            final TtsSpan t = (new TtsSpan.DecimalBuilder())
+                    .setArgumentsFromDouble(10, 0, 0)
+                    .build();
+            assertEquals(TtsSpan.TYPE_DECIMAL, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(1, args.size());
+            assertEquals("10", args.getString(TtsSpan.ARG_INTEGER_PART));
+        }
+        {
+            final TtsSpan t = (new TtsSpan.DecimalBuilder(10, 0, 0)).build();
+            assertEquals(TtsSpan.TYPE_DECIMAL, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(1, args.size());
+            assertEquals("10", args.getString(TtsSpan.ARG_INTEGER_PART));
+        }
+        {
+            final TtsSpan t = (new TtsSpan.DecimalBuilder())
+                    .setArgumentsFromDouble(10.25, 10, 10)
+                    .build();
+            assertEquals(TtsSpan.TYPE_DECIMAL, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(2, args.size());
+            assertEquals("10", args.getString(TtsSpan.ARG_INTEGER_PART));
+            assertEquals("2500000000", args.getString(TtsSpan.ARG_FRACTIONAL_PART));
+        }
+    }
+
+    @SmallTest
+    public void testFractionBuilder() {
+        {
+            final TtsSpan t = (new TtsSpan.FractionBuilder())
+                    .setIntegerPart(10)
+                    .setNumerator(3)
+                    .setDenominator(100)
+                    .build();
+            assertEquals(TtsSpan.TYPE_FRACTION, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(3, args.size());
+            assertEquals("10", args.getString(TtsSpan.ARG_INTEGER_PART));
+            assertEquals("3", args.getString(TtsSpan.ARG_NUMERATOR));
+            assertEquals("100", args.getString(TtsSpan.ARG_DENOMINATOR));
+        }
+        {
+            final TtsSpan t = (new TtsSpan.FractionBuilder(10, 3, 100)).build();
+            assertEquals(TtsSpan.TYPE_FRACTION, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(3, args.size());
+            assertEquals("10", args.getString(TtsSpan.ARG_INTEGER_PART));
+            assertEquals("3", args.getString(TtsSpan.ARG_NUMERATOR));
+            assertEquals("100", args.getString(TtsSpan.ARG_DENOMINATOR));
+        }
+    }
+
+    @SmallTest
+    public void testMeasureBuilder() {
+        {
+            final TtsSpan t = (new TtsSpan.MeasureBuilder())
+                    .setNumber(10)
+                    .setUnit("unit")
+                    .build();
+            assertEquals(TtsSpan.TYPE_MEASURE, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(2, args.size());
+            assertEquals("10", args.getString(TtsSpan.ARG_NUMBER));
+            assertEquals("unit", args.getString(TtsSpan.ARG_UNIT));
+        }
+        {
+            final TtsSpan t = (new TtsSpan.MeasureBuilder())
+                    .setIntegerPart(10)
+                    .setFractionalPart("25")
+                    .setUnit("unit")
+                    .build();
+            assertEquals(TtsSpan.TYPE_MEASURE, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(3, args.size());
+            assertEquals("10", args.getString(TtsSpan.ARG_INTEGER_PART));
+            assertEquals("25", args.getString(TtsSpan.ARG_FRACTIONAL_PART));
+            assertEquals("unit", args.getString(TtsSpan.ARG_UNIT));
+        }
+        {
+            final TtsSpan t = (new TtsSpan.MeasureBuilder())
+                    .setIntegerPart(10)
+                    .setNumerator(3)
+                    .setDenominator(100)
+                    .setUnit("unit")
+                    .build();
+            assertEquals(TtsSpan.TYPE_MEASURE, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(4, args.size());
+            assertEquals("10", args.getString(TtsSpan.ARG_INTEGER_PART));
+            assertEquals("3", args.getString(TtsSpan.ARG_NUMERATOR));
+            assertEquals("100", args.getString(TtsSpan.ARG_DENOMINATOR));
+            assertEquals("unit", args.getString(TtsSpan.ARG_UNIT));
+        }
+    }
+
+    @SmallTest
+    public void testTimeBuilder() {
+        {
+            final TtsSpan t = (new TtsSpan.TimeBuilder())
+                    .setHours(20)
+                    .setMinutes(50)
+                    .build();
+            assertEquals(TtsSpan.TYPE_TIME, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(2, args.size());
+            assertEquals(20, args.getInt(TtsSpan.ARG_HOURS));
+            assertEquals(50, args.getInt(TtsSpan.ARG_MINUTES));
+        }
+        {
+            final TtsSpan t = (new TtsSpan.TimeBuilder(20, 50)).build();
+            assertEquals(TtsSpan.TYPE_TIME, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(2, args.size());
+            assertEquals(20, args.getInt(TtsSpan.ARG_HOURS));
+            assertEquals(50, args.getInt(TtsSpan.ARG_MINUTES));
+        }
+    }
+
+    @SmallTest
+    public void testDateBuilder() {
+        {
+            final TtsSpan t = (new TtsSpan.DateBuilder())
+                    .setWeekday(3)
+                    .setDay(16)
+                    .setMonth(3)
+                    .setYear(2016)
+                    .build();
+            assertEquals(TtsSpan.TYPE_DATE, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(4, args.size());
+            assertEquals(3, args.getInt(TtsSpan.ARG_WEEKDAY));
+            assertEquals(16, args.getInt(TtsSpan.ARG_DAY));
+            assertEquals(3, args.getInt(TtsSpan.ARG_MONTH));
+            assertEquals(2016, args.getInt(TtsSpan.ARG_YEAR));
+        }
+        {
+            final TtsSpan t = (new TtsSpan.DateBuilder(3, 16, 3, 2016)).build();
+            assertEquals(TtsSpan.TYPE_DATE, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(4, args.size());
+            assertEquals(3, args.getInt(TtsSpan.ARG_WEEKDAY));
+            assertEquals(16, args.getInt(TtsSpan.ARG_DAY));
+            assertEquals(3, args.getInt(TtsSpan.ARG_MONTH));
+            assertEquals(2016, args.getInt(TtsSpan.ARG_YEAR));
+        }
+        {
+            final TtsSpan t = (new TtsSpan.DateBuilder(3, 16, null, null)).build();
+            assertEquals(TtsSpan.TYPE_DATE, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(2, args.size());
+            assertEquals(3, args.getInt(TtsSpan.ARG_WEEKDAY));
+            assertEquals(16, args.getInt(TtsSpan.ARG_DAY));
+        }
+    }
+
+    @SmallTest
+    public void testMoneyBuilder() {
+        final TtsSpan t = (new TtsSpan.MoneyBuilder())
+                .setIntegerPart(10)
+                .setFractionalPart("25")
+                .setCurrency("USD")
+                .setQuantity("1000")
+                .build();
+        assertEquals(TtsSpan.TYPE_MONEY, t.getType());
+        PersistableBundle args = t.getArgs();
+        assertEquals(4, args.size());
+        assertEquals("10", args.getString(TtsSpan.ARG_INTEGER_PART));
+        assertEquals("25", args.getString(TtsSpan.ARG_FRACTIONAL_PART));
+        assertEquals("USD", args.getString(TtsSpan.ARG_CURRENCY));
+        assertEquals("1000", args.getString(TtsSpan.ARG_QUANTITY));
+    }
+
+    @SmallTest
+    public void testTelephoneBuilder() {
+        {
+            final TtsSpan t = (new TtsSpan.TelephoneBuilder())
+                    .setCountryCode("+01")
+                    .setNumberParts("000-000-0000")
+                    .setExtension("0000")
+                    .build();
+            assertEquals(TtsSpan.TYPE_TELEPHONE, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(3, args.size());
+            assertEquals("+01", args.getString(TtsSpan.ARG_COUNTRY_CODE));
+            assertEquals("000-000-0000", args.getString(TtsSpan.ARG_NUMBER_PARTS));
+            assertEquals("0000", args.getString(TtsSpan.ARG_EXTENSION));
+        }
+        {
+            final TtsSpan t = (new TtsSpan.TelephoneBuilder("000-000-0000")).build();
+            assertEquals(TtsSpan.TYPE_TELEPHONE, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(1, args.size());
+            assertEquals("000-000-0000", args.getString(TtsSpan.ARG_NUMBER_PARTS));
+        }
+    }
+
+    @SmallTest
+    public void testElectronicBuilder() {
+        {
+            final TtsSpan t = (new TtsSpan.ElectronicBuilder())
+                    .setEmailArguments("example", "example.com")
+                    .build();
+            assertEquals(TtsSpan.TYPE_ELECTRONIC, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(2, args.size());
+            assertEquals("example", args.getString(TtsSpan.ARG_USERNAME));
+            assertEquals("example.com", args.getString(TtsSpan.ARG_DOMAIN));
+        }
+        {
+            final TtsSpan t = (new TtsSpan.ElectronicBuilder())
+                    .setProtocol("http")
+                    .setDomain("example.com")
+                    .setPort(80)
+                    .setPath("example/index.html")
+                    .setQueryString("arg1=value1&arg2=value2")
+                    .setFragmentId("fragment")
+                    .setUsername("username")
+                    .setPassword("password")
+                    .build();
+            assertEquals(TtsSpan.TYPE_ELECTRONIC, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(8, args.size());
+            assertEquals("http", args.getString(TtsSpan.ARG_PROTOCOL));
+            assertEquals("example.com", args.getString(TtsSpan.ARG_DOMAIN));
+            assertEquals(80, args.getInt(TtsSpan.ARG_PORT));
+            assertEquals("example/index.html", args.getString(TtsSpan.ARG_PATH));
+            assertEquals("arg1=value1&arg2=value2", args.getString(TtsSpan.ARG_QUERY_STRING));
+            assertEquals("fragment", args.getString(TtsSpan.ARG_FRAGMENT_ID));
+            assertEquals("username", args.getString(TtsSpan.ARG_USERNAME));
+            assertEquals("password", args.getString(TtsSpan.ARG_PASSWORD));
+        }
+    }
+
+    @SmallTest
+    public void testDigitsBuilder() {
+        {
+            final TtsSpan t = (new TtsSpan.DigitsBuilder())
+                    .setDigits("12345")
+                    .build();
+            assertEquals(TtsSpan.TYPE_DIGITS, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(1, args.size());
+            assertEquals("12345", args.getString(TtsSpan.ARG_DIGITS));
+        }
+        {
+            final TtsSpan t = (new TtsSpan.DigitsBuilder("12345")).build();
+            assertEquals(TtsSpan.TYPE_DIGITS, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(1, args.size());
+            assertEquals("12345", args.getString(TtsSpan.ARG_DIGITS));
+        }
+    }
+
+    @SmallTest
+    public void testVerbatimBuilder() {
+        {
+            final TtsSpan t = (new TtsSpan.VerbatimBuilder())
+                    .setVerbatim("abcdefg")
+                    .build();
+            assertEquals(TtsSpan.TYPE_VERBATIM, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(1, args.size());
+            assertEquals("abcdefg", args.getString(TtsSpan.ARG_VERBATIM));
+        }
+        {
+            final TtsSpan t = (new TtsSpan.VerbatimBuilder("abcdefg")).build();
+            assertEquals(TtsSpan.TYPE_VERBATIM, t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(1, args.size());
+            assertEquals("abcdefg", args.getString(TtsSpan.ARG_VERBATIM));
+        }
+    }
 }
diff --git a/tests/tests/text/src/android/text/util/cts/LinkifyTest.java b/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
index c0d16de..00f624f 100644
--- a/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
+++ b/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
@@ -25,6 +25,7 @@
 import android.text.util.Linkify;
 import android.text.util.Linkify.MatchFilter;
 import android.text.util.Linkify.TransformFilter;
+import android.util.Patterns;
 import android.widget.TextView;
 
 import java.util.Locale;
@@ -351,6 +352,110 @@
         assertFalse(Linkify.addLinks((Spannable) null, 0));
     }
 
+    @SmallTest
+    public void testAddLinks_addsLinksWhenDefaultSchemeIsNull() {
+        Spannable spannable = new SpannableString("any https://android.com any android.com any");
+        Linkify.addLinks(spannable, Patterns.AUTOLINK_WEB_URL, null, null, null);
+
+        URLSpan[] spans = spannable.getSpans(0, spannable.length(), URLSpan.class);
+        assertEquals("android.com and https://android.com should be linkified", 2, spans.length);
+        assertEquals("https://android.com", spans[0].getURL());
+        assertEquals("android.com", spans[1].getURL());
+    }
+
+    @SmallTest
+    public void testAddLinks_addsLinksWhenSchemesArrayIsNull() {
+        Spannable spannable = new SpannableString("any https://android.com any android.com any");
+        Linkify.addLinks(spannable, Patterns.AUTOLINK_WEB_URL, "http://", null, null);
+
+        URLSpan[] spans = spannable.getSpans(0, spannable.length(), URLSpan.class);
+        assertEquals("android.com and https://android.com should be linkified", 2, spans.length);
+        // expected behavior, passing null schemes array means: prepend defaultScheme to all links.
+        assertEquals("http://https://android.com", spans[0].getURL());
+        assertEquals("http://android.com", spans[1].getURL());
+    }
+
+    @SmallTest
+    public void testAddLinks_prependsDefaultSchemeToBeginingOfLink() {
+        Spannable spannable = new SpannableString("any android.com any");
+        Linkify.addLinks(spannable, Patterns.AUTOLINK_WEB_URL, "http://",
+                new String[] { "http://", "https://"}, null, null);
+
+        URLSpan[] spans = spannable.getSpans(0, spannable.length(), URLSpan.class);
+        assertEquals("android.com should be linkified", 1, spans.length);
+        assertEquals("http://android.com", spans[0].getURL());
+    }
+
+    @SmallTest
+    public void testAddLinks_doesNotPrependSchemeIfSchemeExists() {
+        Spannable spannable = new SpannableString("any https://android.com any");
+        Linkify.addLinks(spannable, Patterns.AUTOLINK_WEB_URL, "http://",
+                new String[] { "http://", "https://"}, null, null);
+
+        URLSpan[] spans = spannable.getSpans(0, spannable.length(), URLSpan.class);
+        assertEquals("android.com should be linkified", 1, spans.length);
+        assertEquals("https://android.com", spans[0].getURL());
+    }
+
+    // Add links with scheme (array)
+
+    @SmallTest
+    public void testAddLinks_withTextView_addsLinksWhenDefaultSchemeIsNull() {
+        Pattern pattern = Pattern.compile("\\b((http|https)://)?android\\.com+\\b");
+        TextView textView = new TextView(mContext);
+        textView.setText("any https://android.com any android.com any");
+
+        Linkify.addLinks(textView, pattern, null, null, null);
+
+        URLSpan[] spans = textView.getUrls();
+        assertEquals("android.com and https://android.com should be linkified", 2, spans.length);
+        assertEquals("https://android.com", spans[0].getURL());
+        assertEquals("android.com", spans[1].getURL());
+    }
+
+    @SmallTest
+    public void testAddLinks_withTextView_addsLinksWhenSchemesArrayIsNull() {
+        Pattern pattern = Pattern.compile("\\b((http|https)://)?android\\.com+\\b");
+        TextView textView = new TextView(mContext);
+        textView.setText("any https://android.com any android.com any");
+
+        Linkify.addLinks(textView, pattern, "http://", null, null);
+
+        URLSpan[] spans = textView.getUrls();
+        assertEquals("android.com and https://android.com should be linkified", 2, spans.length);
+        // expected behavior, passing null schemes array means: prepend defaultScheme to all links.
+        assertEquals("http://https://android.com", spans[0].getURL());
+        assertEquals("http://android.com", spans[1].getURL());
+    }
+
+    @SmallTest
+    public void testAddLinks_withTextView_prependsDefaultSchemeToBeginingOfLink() {
+        Pattern pattern = Pattern.compile("\\b((http|https)://)?android\\.com+\\b");
+        TextView textView = new TextView(mContext);
+        textView.setText("any android.com any");
+
+        Linkify.addLinks(textView, pattern, "http://", new String[] { "http://", "https://"},
+                null, null);
+
+        URLSpan[] spans = textView.getUrls();
+        assertEquals("android.com should be linkified", 1, spans.length);
+        assertEquals("http://android.com", spans[0].getURL());
+    }
+
+    @SmallTest
+    public void testAddLinks_withTextView_doesNotPrependSchemeIfSchemeExists() {
+        Pattern pattern = Pattern.compile("\\b((http|https)://)?android\\.com+\\b");
+        TextView textView = new TextView(mContext);
+        textView.setText("any https://android.com any");
+
+        Linkify.addLinks(textView, pattern, "http://", new String[] { "http://", "https://"},
+                null, null);
+
+        URLSpan[] spans = textView.getUrls();
+        assertEquals("android.com should be linkified", 1, spans.length);
+        assertEquals("https://android.com", spans[0].getURL());
+    }
+
     // WEB_URLS Related Tests
 
     @SmallTest
diff --git a/tests/tests/theme/Android.mk b/tests/tests/theme/Android.mk
index 0f370d0..8b69a09 100644
--- a/tests/tests/theme/Android.mk
+++ b/tests/tests/theme/Android.mk
@@ -24,7 +24,8 @@
 # When built, explicitly put it in the data partition.
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    ctstestrunner platform-test-annotations
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/theme/src/android/theme/cts/DeviceDefaultTest.java b/tests/tests/theme/src/android/theme/cts/DeviceDefaultTest.java
index 77de0b4..fdac2d1 100644
--- a/tests/tests/theme/src/android/theme/cts/DeviceDefaultTest.java
+++ b/tests/tests/theme/src/android/theme/cts/DeviceDefaultTest.java
@@ -21,6 +21,7 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
+import android.platform.test.annotations.Presubmit;
 import android.test.ActivityInstrumentationTestCase2;
 
 public class DeviceDefaultTest extends ActivityInstrumentationTestCase2<DeviceDefaultActivity> {
@@ -57,6 +58,7 @@
         assertNoActionBar(android.R.style.Theme_DeviceDefault_DialogWhenLarge_NoActionBar);
     }
 
+    @Presubmit
     public void testGetActionBar_DeviceDefault_InputMethod() {
         assertNoActionBar(android.R.style.Theme_DeviceDefault_InputMethod);
     }
diff --git a/tests/tests/transition/res/layout/scene10.xml b/tests/tests/transition/res/layout/scene10.xml
new file mode 100644
index 0000000..16e3c20
--- /dev/null
+++ b/tests/tests/transition/res/layout/scene10.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:transitionName="holder"
+                android:id="@+id/holder">
+    <View android:layout_width="10dp"
+          android:layout_height="10dp"
+          android:background="#F00"
+          android:layout_alignParentLeft="true"
+          android:layout_alignParentTop="true"
+          android:id="@+id/redSquare" />
+    <View android:layout_width="10dp"
+          android:layout_height="10dp"
+          android:background="#0F0"
+          android:layout_alignParentRight="true"
+          android:layout_alignParentTop="true"
+          android:id="@+id/greenSquare"/>
+    <View android:layout_width="10dp"
+          android:layout_height="10dp"
+          android:background="#00F"
+          android:layout_alignParentRight="true"
+          android:layout_alignParentBottom="true"
+          android:id="@+id/blueSquare" />
+    <View android:layout_width="10dp"
+          android:layout_height="10dp"
+          android:background="#FF0"
+          android:layout_alignParentLeft="true"
+          android:layout_alignParentBottom="true"
+          android:id="@+id/yellowSquare"/>
+</RelativeLayout>
diff --git a/tests/tests/transition/res/layout/scene9.xml b/tests/tests/transition/res/layout/scene9.xml
new file mode 100644
index 0000000..2eb3762f
--- /dev/null
+++ b/tests/tests/transition/res/layout/scene9.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:transitionName="holder"
+                android:id="@+id/holder">
+    <FrameLayout
+            android:layout_marginTop="50dp"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content">
+        <TextView
+                android:id="@+id/text"
+                android:text="@string/longText"
+                android:layout_width="100dp"
+                android:layout_height="100dp"/>
+    </FrameLayout>
+</RelativeLayout>
diff --git a/tests/tests/transition/src/android/transition/cts/ArcMotionTest.java b/tests/tests/transition/src/android/transition/cts/ArcMotionTest.java
index 6cb5c1c..d6b00cf 100644
--- a/tests/tests/transition/src/android/transition/cts/ArcMotionTest.java
+++ b/tests/tests/transition/src/android/transition/cts/ArcMotionTest.java
@@ -21,7 +21,7 @@
 
 import junit.framework.TestCase;
 
-public class ArcMotionTest extends TestCase {
+public class ArcMotionTest extends PathMotionTest {
 
     public void test90Quadrants() throws Throwable {
         ArcMotion arcMotion = new ArcMotion();
@@ -96,29 +96,6 @@
         return path;
     }
 
-    private void assertPathMatches(Path expectedPath, Path path) {
-        PathMeasure expectedMeasure = new PathMeasure(expectedPath, false);
-        PathMeasure pathMeasure = new PathMeasure(path, false);
-
-        float expectedLength = expectedMeasure.getLength();
-        assertEquals(expectedLength, pathMeasure.getLength(), 0.01f);
-
-        float minLength = Math.min(expectedLength, pathMeasure.getLength());
-
-        float pos[] = new float[2];
-
-        float increment = minLength / 5f;
-        for (float along = 0; along <= minLength; along += increment) {
-            expectedMeasure.getPosTan(along, pos, null);
-            float expectedX = pos[0];
-            float expectedY = pos[1];
-
-            pathMeasure.getPosTan(along, pos, null);
-            assertEquals(expectedX, pos[0], 0.01f);
-            assertEquals(expectedY, pos[1], 0.01f);
-        }
-    }
-
     public void testMaximumAngle() throws Throwable {
         ArcMotion arcMotion = new ArcMotion();
         arcMotion.setMaximumAngle(45f);
diff --git a/tests/tests/transition/src/android/transition/cts/BaseTransitionTest.java b/tests/tests/transition/src/android/transition/cts/BaseTransitionTest.java
index 56ba44b..944ff91 100644
--- a/tests/tests/transition/src/android/transition/cts/BaseTransitionTest.java
+++ b/tests/tests/transition/src/android/transition/cts/BaseTransitionTest.java
@@ -164,24 +164,6 @@
         mTransition.addListener(mListener);
     }
 
-    // Waits at least one frame and it could be more. The animated values should have changed
-    // from the previously recorded values by the end of this method.
-    protected void waitForAnimationFrame() throws Throwable {
-        final CountDownLatch latch = new CountDownLatch(1);
-        runTestOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                Choreographer.getInstance().postFrameCallbackDelayed(new FrameCallback() {
-                    @Override
-                    public void doFrame(long frameTimeNanos) {
-                        latch.countDown();
-                    }
-                }, 16); // make sure it is the next animation frame.
-            }
-        });
-        assertTrue(latch.await(100, TimeUnit.MILLISECONDS));
-    }
-
     public class TestTransition extends Visibility {
 
         public TestTransition() {
diff --git a/tests/tests/transition/src/android/transition/cts/ChangeBoundsTest.java b/tests/tests/transition/src/android/transition/cts/ChangeBoundsTest.java
index a99f175..d5c1245 100644
--- a/tests/tests/transition/src/android/transition/cts/ChangeBoundsTest.java
+++ b/tests/tests/transition/src/android/transition/cts/ChangeBoundsTest.java
@@ -18,7 +18,6 @@
 import android.content.res.Resources;
 import android.graphics.Rect;
 import android.transition.ChangeBounds;
-import android.transition.cts.R;
 import android.util.TypedValue;
 import android.view.View;
 
@@ -62,7 +61,9 @@
     }
 
     public void testResizeClip() throws Throwable {
+        assertEquals(false, mChangeBounds.getResizeClip());
         mChangeBounds.setResizeClip(true);
+        assertEquals(true, mChangeBounds.getResizeClip());
         enterScene(R.layout.scene1);
 
         validateInScene1();
diff --git a/tests/tests/transition/src/android/transition/cts/ChangeClipBoundsTest.java b/tests/tests/transition/src/android/transition/cts/ChangeClipBoundsTest.java
new file mode 100644
index 0000000..9411d29
--- /dev/null
+++ b/tests/tests/transition/src/android/transition/cts/ChangeClipBoundsTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.transition.cts;
+
+import android.graphics.Rect;
+import android.transition.ChangeClipBounds;
+import android.transition.TransitionManager;
+import android.view.View;
+
+public class ChangeClipBoundsTest extends BaseTransitionTest {
+    private ChangeClipBounds mChangeClipBounds;
+
+    public ChangeClipBoundsTest() {
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mChangeClipBounds = new ChangeClipBounds();
+        mTransition = mChangeClipBounds;
+        resetListener();
+    }
+
+    public void testChangeClipBounds() throws Throwable {
+        enterScene(R.layout.scene1);
+
+        final View redSquare = mActivity.findViewById(R.id.redSquare);
+        final Rect newClip = new Rect(redSquare.getLeft() + 10, redSquare.getTop() + 10,
+                redSquare.getRight() - 10, redSquare.getBottom() - 10);
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertNull(redSquare.getClipBounds());
+                TransitionManager.beginDelayedTransition(mSceneRoot, mChangeClipBounds);
+                redSquare.setClipBounds(newClip);
+            }
+        });
+        waitForStart();
+        Thread.sleep(150);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                Rect midClip = redSquare.getClipBounds();
+                assertNotNull(midClip);
+                assertTrue(midClip.left > 0 && midClip.left < newClip.left);
+                assertTrue(midClip.top > 0 && midClip.top < newClip.top);
+                assertTrue(midClip.right < redSquare.getRight() && midClip.right > newClip.right);
+                assertTrue(midClip.bottom < redSquare.getBottom() &&
+                        midClip.bottom > newClip.bottom);
+            }
+        });
+        waitForEnd(400);
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                final Rect endRect = redSquare.getClipBounds();
+                assertNotNull(endRect);
+                assertEquals(newClip, endRect);
+            }
+        });
+
+        resetListener();
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                TransitionManager.beginDelayedTransition(mSceneRoot, mChangeClipBounds);
+                redSquare.setClipBounds(null);
+            }
+        });
+        waitForStart();
+        Thread.sleep(150);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                Rect midClip = redSquare.getClipBounds();
+                assertNotNull(midClip);
+                assertTrue(midClip.left > 0 && midClip.left < newClip.left);
+                assertTrue(midClip.top > 0 && midClip.top < newClip.top);
+                assertTrue(midClip.right < redSquare.getRight() && midClip.right > newClip.right);
+                assertTrue(midClip.bottom < redSquare.getBottom() &&
+                        midClip.bottom > newClip.bottom);
+            }
+        });
+        waitForEnd(400);
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertNotNull(redSquare.getClipBounds());
+            }
+        });
+    }
+}
+
diff --git a/tests/tests/transition/src/android/transition/cts/ChangeImageTransformTest.java b/tests/tests/transition/src/android/transition/cts/ChangeImageTransformTest.java
new file mode 100644
index 0000000..a26e850
--- /dev/null
+++ b/tests/tests/transition/src/android/transition/cts/ChangeImageTransformTest.java
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.transition.cts;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.graphics.Matrix;
+import android.graphics.drawable.Drawable;
+import android.transition.ChangeImageTransform;
+import android.transition.TransitionManager;
+import android.transition.TransitionValues;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.ImageView;
+import android.widget.ImageView.ScaleType;
+
+public class ChangeImageTransformTest extends BaseTransitionTest {
+    ChangeImageTransform mChangeImageTransform;
+    Matrix mStartMatrix;
+    Matrix mEndMatrix;
+    Drawable mImage;
+    ImageView mImageView;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        resetTransition();
+        mStartMatrix = null;
+        mEndMatrix = null;
+        mImage = null;
+        mImageView = null;
+    }
+
+    private void resetTransition() {
+        mChangeImageTransform = new CaptureMatrix();
+        mChangeImageTransform.setDuration(100);
+        mTransition = mChangeImageTransform;
+        resetListener();
+    }
+
+    public void testCenterToFitXY() throws Throwable {
+        transformImage(ScaleType.CENTER, ScaleType.FIT_XY);
+        assertMatrixMatches(centerMatrix(), mStartMatrix);
+        assertMatrixMatches(fitXYMatrix(), mEndMatrix);
+    }
+
+    public void testCenterCropToFitCenter() throws Throwable {
+        transformImage(ScaleType.CENTER_CROP, ScaleType.FIT_CENTER);
+        assertMatrixMatches(centerCropMatrix(), mStartMatrix);
+        assertMatrixMatches(fitCenterMatrix(), mEndMatrix);
+    }
+
+    public void testCenterInsideToFitEnd() throws Throwable {
+        transformImage(ScaleType.CENTER_INSIDE, ScaleType.FIT_END);
+        // CENTER_INSIDE and CENTER are the same when the image is smaller than the View
+        assertMatrixMatches(centerMatrix(), mStartMatrix);
+        assertMatrixMatches(fitEndMatrix(), mEndMatrix);
+    }
+
+    public void testFitStartToCenter() throws Throwable {
+        transformImage(ScaleType.FIT_START, ScaleType.CENTER);
+        assertMatrixMatches(fitStartMatrix(), mStartMatrix);
+        assertMatrixMatches(centerMatrix(), mEndMatrix);
+    }
+
+    private Matrix centerMatrix() {
+        int imageWidth = mImage.getIntrinsicWidth();
+        int imageViewWidth = mImageView.getWidth();
+        float tx = Math.round((imageViewWidth - imageWidth)/2f);
+
+        int imageHeight = mImage.getIntrinsicHeight();
+        int imageViewHeight = mImageView.getHeight();
+        float ty = Math.round((imageViewHeight - imageHeight)/2f);
+
+        Matrix matrix = new Matrix();
+        matrix.postTranslate(tx, ty);
+        return matrix;
+    }
+
+    private Matrix fitXYMatrix() {
+        int imageWidth = mImage.getIntrinsicWidth();
+        int imageViewWidth = mImageView.getWidth();
+        float scaleX = ((float)imageViewWidth)/imageWidth;
+
+        int imageHeight = mImage.getIntrinsicHeight();
+        int imageViewHeight = mImageView.getHeight();
+        float scaleY = ((float)imageViewHeight)/imageHeight;
+
+        Matrix matrix = new Matrix();
+        matrix.postScale(scaleX, scaleY);
+        return matrix;
+    }
+
+    private Matrix centerCropMatrix() {
+        int imageWidth = mImage.getIntrinsicWidth();
+        int imageViewWidth = mImageView.getWidth();
+        float scaleX = ((float)imageViewWidth)/imageWidth;
+
+        int imageHeight = mImage.getIntrinsicHeight();
+        int imageViewHeight = mImageView.getHeight();
+        float scaleY = ((float)imageViewHeight)/imageHeight;
+
+        float maxScale = Math.max(scaleX, scaleY);
+
+        float width = imageWidth * maxScale;
+        float height = imageHeight * maxScale;
+        float tx = Math.round((imageViewWidth - width) / 2f);
+        float ty = Math.round((imageViewHeight - height) / 2f);
+
+        Matrix matrix = new Matrix();
+        matrix.postScale(maxScale, maxScale);
+        matrix.postTranslate(tx, ty);
+        return matrix;
+    }
+
+    private Matrix fitCenterMatrix() {
+        int imageWidth = mImage.getIntrinsicWidth();
+        int imageViewWidth = mImageView.getWidth();
+        float scaleX = ((float)imageViewWidth)/imageWidth;
+
+        int imageHeight = mImage.getIntrinsicHeight();
+        int imageViewHeight = mImageView.getHeight();
+        float scaleY = ((float)imageViewHeight)/imageHeight;
+
+        float minScale = Math.min(scaleX, scaleY);
+
+        float width = imageWidth * minScale;
+        float height = imageHeight * minScale;
+        float tx = (imageViewWidth - width) / 2f;
+        float ty = (imageViewHeight - height) / 2f;
+
+        Matrix matrix = new Matrix();
+        matrix.postScale(minScale, minScale);
+        matrix.postTranslate(tx, ty);
+        return matrix;
+    }
+
+    private Matrix fitStartMatrix() {
+        int imageWidth = mImage.getIntrinsicWidth();
+        int imageViewWidth = mImageView.getWidth();
+        float scaleX = ((float)imageViewWidth)/imageWidth;
+
+        int imageHeight = mImage.getIntrinsicHeight();
+        int imageViewHeight = mImageView.getHeight();
+        float scaleY = ((float)imageViewHeight)/imageHeight;
+
+        float minScale = Math.min(scaleX, scaleY);
+
+        Matrix matrix = new Matrix();
+        matrix.postScale(minScale, minScale);
+        return matrix;
+    }
+
+    private Matrix fitEndMatrix() {
+        int imageWidth = mImage.getIntrinsicWidth();
+        int imageViewWidth = mImageView.getWidth();
+        float scaleX = ((float)imageViewWidth)/imageWidth;
+
+        int imageHeight = mImage.getIntrinsicHeight();
+        int imageViewHeight = mImageView.getHeight();
+        float scaleY = ((float)imageViewHeight)/imageHeight;
+
+        float minScale = Math.min(scaleX, scaleY);
+
+        float width = imageWidth * minScale;
+        float height = imageHeight * minScale;
+        float tx = imageViewWidth - width;
+        float ty = imageViewHeight - height;
+
+        Matrix matrix = new Matrix();
+        matrix.postScale(minScale, minScale);
+        matrix.postTranslate(tx, ty);
+        return matrix;
+    }
+
+    private void assertMatrixMatches(Matrix expected, Matrix matrix) {
+        if (expected == null) {
+            assertNull(matrix);
+            return;
+        }
+        assertNotNull(matrix);
+        float[] expectedValues = new float[9];
+        expected.getValues(expectedValues);
+
+        float[] values = new float[9];
+        matrix.getValues(values);
+
+        for (int i = 0; i < values.length; i++) {
+            final float expectedValue = expectedValues[i];
+            final float value = values[i];
+            assertEquals("Value [" + i + "]", expectedValue, value, 0.01f);
+        }
+    }
+
+    private void transformImage(ScaleType startScale, final ScaleType endScale) throws Throwable {
+        final ImageView imageView = enterImageViewScene(startScale);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                TransitionManager.beginDelayedTransition(mSceneRoot, mChangeImageTransform);
+                imageView.setScaleType(endScale);
+            }
+        });
+        waitForStart();
+        int expectedEndCount = (startScale == endScale) ? 0 : 1;
+        assertEquals(expectedEndCount, mListener.endLatch.getCount());
+        waitForEnd(200);
+    }
+
+    private ImageView enterImageViewScene(final ScaleType scaleType) throws Throwable {
+        enterScene(R.layout.scene4);
+        final ViewGroup container = (ViewGroup) mActivity.findViewById(R.id.holder);
+        final ImageView[] imageViews = new ImageView[1];
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mImageView = new ImageView(mActivity);
+                mImage = mActivity.getDrawable(android.R.drawable.ic_media_play);
+                mImageView.setImageDrawable(mImage);
+                mImageView.setScaleType(scaleType);
+                imageViews[0] = mImageView;
+                container.addView(mImageView);
+                LayoutParams layoutParams = mImageView.getLayoutParams();
+                DisplayMetrics metrics = mActivity.getResources().getDisplayMetrics();
+                float size = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, metrics);
+                layoutParams.width = Math.round(size);
+                layoutParams.height = Math.round(size * 2);
+                mImageView.setLayoutParams(layoutParams);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+        return imageViews[0];
+    }
+
+    private class CaptureMatrix extends ChangeImageTransform {
+        @Override
+        public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
+                TransitionValues endValues) {
+            Animator animator = super.createAnimator(sceneRoot, startValues, endValues);
+            animator.addListener(new CaptureMatrixListener((ImageView) endValues.view));
+            return animator;
+        }
+    }
+
+    private class CaptureMatrixListener extends AnimatorListenerAdapter {
+        private final ImageView mImageView;
+
+        public CaptureMatrixListener(ImageView view) {
+            mImageView = view;
+        }
+
+        @Override
+        public void onAnimationStart(Animator animation) {
+            mStartMatrix = copyMatrix();
+        }
+
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            mEndMatrix = copyMatrix();
+        }
+
+        private Matrix copyMatrix() {
+            Matrix matrix = mImageView.getImageMatrix();
+            if (matrix != null) {
+                matrix = new Matrix(matrix);
+            }
+            return matrix;
+        }
+    }
+}
+
diff --git a/tests/tests/transition/src/android/transition/cts/ChangeScrollTest.java b/tests/tests/transition/src/android/transition/cts/ChangeScrollTest.java
index 9917416..2dee364 100644
--- a/tests/tests/transition/src/android/transition/cts/ChangeScrollTest.java
+++ b/tests/tests/transition/src/android/transition/cts/ChangeScrollTest.java
@@ -15,38 +15,38 @@
  */
 package android.transition.cts;
 
-import android.transition.cts.R;
-
 import android.transition.ChangeScroll;
-import android.transition.Transition;
 import android.transition.TransitionManager;
 import android.view.View;
 
 public class ChangeScrollTest extends BaseTransitionTest {
+    ChangeScroll mChangeScroll;
 
     public ChangeScrollTest() {
     }
 
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mChangeScroll = new ChangeScroll();
+        mTransition = mChangeScroll;
+        resetListener();
+    }
+
     public void testChangeScroll() throws Throwable {
         enterScene(R.layout.scene5);
-        final Transition transition = new ChangeScroll();
-        transition.setDuration(200);
-        SimpleTransitionListener listener = new SimpleTransitionListener();
-        transition.addListener(listener);
         runTestOnUiThread(new Runnable() {
             @Override
             public void run() {
                 final View view = mActivity.findViewById(R.id.text);
-                final int scrollX = view.getScrollX();
-                final int scrollY = view.getScrollY();
-                assertEquals(0, scrollX);
-                assertEquals(0, scrollY);
-                TransitionManager.beginDelayedTransition(mSceneRoot, transition);
+                assertEquals(0, view.getScrollX());
+                assertEquals(0, view.getScrollY());
+                TransitionManager.beginDelayedTransition(mSceneRoot, mChangeScroll);
                 view.scrollTo(150, 300);
             }
         });
-        waitForStart(listener);
-        waitForAnimationFrame();
+        waitForStart();
+        Thread.sleep(150);
         runTestOnUiThread(new Runnable() {
             @Override
             public void run() {
@@ -59,15 +59,13 @@
                 assertTrue(scrollY < 300);
             }
         });
-        waitForEnd(listener, 250);
+        waitForEnd(400);
         runTestOnUiThread(new Runnable() {
             @Override
             public void run() {
                 final View view = mActivity.findViewById(R.id.text);
-                final int scrollX = view.getScrollX();
-                final int scrollY = view.getScrollY();
-                assertEquals(150, scrollX);
-                assertEquals(300, scrollY);
+                assertEquals(150, view.getScrollX());
+                assertEquals(300, view.getScrollY());
             }
         });
     }
diff --git a/tests/tests/transition/src/android/transition/cts/ChangeTransformTest.java b/tests/tests/transition/src/android/transition/cts/ChangeTransformTest.java
new file mode 100644
index 0000000..78a5d82
--- /dev/null
+++ b/tests/tests/transition/src/android/transition/cts/ChangeTransformTest.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.transition.cts;
+
+import android.transition.ChangeTransform;
+import android.transition.TransitionManager;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class ChangeTransformTest extends BaseTransitionTest {
+    ChangeTransform mChangeTransform;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        resetChangeBoundsTransition();
+    }
+
+    private void resetChangeBoundsTransition() {
+        mChangeTransform = new ChangeTransform();
+        mTransition = mChangeTransform;
+        resetListener();
+    }
+
+    public void testTranslation() throws Throwable {
+        enterScene(R.layout.scene1);
+
+        final View redSquare = mActivity.findViewById(R.id.redSquare);
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                TransitionManager.beginDelayedTransition(mSceneRoot, mChangeTransform);
+                redSquare.setTranslationX(500);
+                redSquare.setTranslationY(600);
+            }
+        });
+        waitForStart();
+
+        assertEquals(1, mListener.endLatch.getCount()); // still running
+        // There is no way to validate the intermediate matrix because it uses
+        // hidden properties of the View to execute.
+        waitForEnd(400);
+        assertEquals(500f, redSquare.getTranslationX());
+        assertEquals(600f, redSquare.getTranslationY());
+    }
+
+    public void testRotation() throws Throwable {
+        enterScene(R.layout.scene1);
+
+        final View redSquare = mActivity.findViewById(R.id.redSquare);
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                TransitionManager.beginDelayedTransition(mSceneRoot, mChangeTransform);
+                redSquare.setRotation(45);
+            }
+        });
+        waitForStart();
+
+        assertEquals(1, mListener.endLatch.getCount()); // still running
+        // There is no way to validate the intermediate matrix because it uses
+        // hidden properties of the View to execute.
+        waitForEnd(400);
+        assertEquals(45f, redSquare.getRotation());
+    }
+
+    public void testScale() throws Throwable {
+        enterScene(R.layout.scene1);
+
+        final View redSquare = mActivity.findViewById(R.id.redSquare);
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                TransitionManager.beginDelayedTransition(mSceneRoot, mChangeTransform);
+                redSquare.setScaleX(2f);
+                redSquare.setScaleY(3f);
+            }
+        });
+        waitForStart();
+
+        assertEquals(1, mListener.endLatch.getCount()); // still running
+        // There is no way to validate the intermediate matrix because it uses
+        // hidden properties of the View to execute.
+        waitForEnd(400);
+        assertEquals(2f, redSquare.getScaleX());
+        assertEquals(3f, redSquare.getScaleY());
+    }
+
+    public void testReparent() throws Throwable {
+        assertEquals(true, mChangeTransform.getReparent());
+        enterScene(R.layout.scene5);
+        startTransition(R.layout.scene9);
+        assertEquals(1, mListener.endLatch.getCount()); // still running
+        waitForEnd(400);
+
+        resetListener();
+        mChangeTransform.setReparent(false);
+        assertEquals(false, mChangeTransform.getReparent());
+        startTransition(R.layout.scene5);
+        waitForEnd(0); // no transition to run because reparent == false
+    }
+
+    public void testReparentWithOverlay() throws Throwable {
+        assertEquals(true, mChangeTransform.getReparentWithOverlay());
+        enterScene(R.layout.scene5);
+        startTransition(R.layout.scene9);
+        assertEquals(1, mListener.endLatch.getCount()); // still running
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                View view = new View(mActivity);
+                view.setRight(100);
+                view.setBottom(100);
+                mSceneRoot.getOverlay().add(view);
+                ViewGroup container = (ViewGroup) view.getParent();
+                assertEquals(2, container.getChildCount());
+                mSceneRoot.getOverlay().remove(view);
+                assertTrue(mActivity.findViewById(R.id.text).getVisibility() != View.VISIBLE);
+            }
+        });
+        waitForEnd(400);
+
+        mChangeTransform.setReparentWithOverlay(false);
+        assertEquals(false, mChangeTransform.getReparentWithOverlay());
+        resetListener();
+        startTransition(R.layout.scene5);
+        assertEquals(1, mListener.endLatch.getCount()); // still running
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                View view = new View(mActivity);
+                view.setRight(100);
+                view.setBottom(100);
+                mSceneRoot.getOverlay().add(view);
+                ViewGroup container = (ViewGroup) view.getParent();
+                assertEquals(1, container.getChildCount());
+                mSceneRoot.getOverlay().remove(view);
+                assertEquals(View.VISIBLE, mActivity.findViewById(R.id.text).getVisibility());
+            }
+        });
+        waitForEnd(400);
+    }
+}
+
diff --git a/tests/tests/transition/src/android/transition/cts/ExplodeTest.java b/tests/tests/transition/src/android/transition/cts/ExplodeTest.java
new file mode 100644
index 0000000..e9e2264
--- /dev/null
+++ b/tests/tests/transition/src/android/transition/cts/ExplodeTest.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.transition.cts;
+
+import android.transition.Explode;
+import android.transition.TransitionManager;
+import android.view.View;
+import android.widget.RelativeLayout;
+import android.widget.RelativeLayout.LayoutParams;
+
+public class ExplodeTest extends BaseTransitionTest {
+    Explode mExplode;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        resetTransition();
+    }
+
+    private void resetTransition() {
+        mExplode = new Explode();
+        mTransition = mExplode;
+        resetListener();
+    }
+
+    public void testExplode() throws Throwable {
+        enterScene(R.layout.scene10);
+        final View redSquare = mActivity.findViewById(R.id.redSquare);
+        final View greenSquare = mActivity.findViewById(R.id.greenSquare);
+        final View blueSquare = mActivity.findViewById(R.id.blueSquare);
+        final View yellowSquare = mActivity.findViewById(R.id.yellowSquare);
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                TransitionManager.beginDelayedTransition(mSceneRoot, mTransition);
+                redSquare.setVisibility(View.INVISIBLE);
+                greenSquare.setVisibility(View.INVISIBLE);
+                blueSquare.setVisibility(View.INVISIBLE);
+                yellowSquare.setVisibility(View.INVISIBLE);
+            }
+        });
+        waitForStart();
+        assertEquals(1, mListener.endLatch.getCount());
+        assertEquals(View.VISIBLE, redSquare.getVisibility());
+        assertEquals(View.VISIBLE, greenSquare.getVisibility());
+        assertEquals(View.VISIBLE, blueSquare.getVisibility());
+        assertEquals(View.VISIBLE, yellowSquare.getVisibility());
+        float redStartX = redSquare.getTranslationX();
+        float redStartY = redSquare.getTranslationY();
+
+        Thread.sleep(100);
+        assertTranslation(redSquare, true, true);
+        assertTranslation(greenSquare, false, true);
+        assertTranslation(blueSquare, false, false);
+        assertTranslation(yellowSquare, true, false);
+        assertTrue(redStartX > redSquare.getTranslationX()); // moving left
+        assertTrue(redStartY > redSquare.getTranslationY()); // moving up
+        waitForEnd(400);
+
+        assertNoTranslation(redSquare);
+        assertNoTranslation(greenSquare);
+        assertNoTranslation(blueSquare);
+        assertNoTranslation(yellowSquare);
+        assertEquals(View.INVISIBLE, redSquare.getVisibility());
+        assertEquals(View.INVISIBLE, greenSquare.getVisibility());
+        assertEquals(View.INVISIBLE, blueSquare.getVisibility());
+        assertEquals(View.INVISIBLE, yellowSquare.getVisibility());
+    }
+
+    public void testImplode() throws Throwable {
+        enterScene(R.layout.scene10);
+        final View redSquare = mActivity.findViewById(R.id.redSquare);
+        final View greenSquare = mActivity.findViewById(R.id.greenSquare);
+        final View blueSquare = mActivity.findViewById(R.id.blueSquare);
+        final View yellowSquare = mActivity.findViewById(R.id.yellowSquare);
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                redSquare.setVisibility(View.INVISIBLE);
+                greenSquare.setVisibility(View.INVISIBLE);
+                blueSquare.setVisibility(View.INVISIBLE);
+                yellowSquare.setVisibility(View.INVISIBLE);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                TransitionManager.beginDelayedTransition(mSceneRoot, mTransition);
+                redSquare.setVisibility(View.VISIBLE);
+                greenSquare.setVisibility(View.VISIBLE);
+                blueSquare.setVisibility(View.VISIBLE);
+                yellowSquare.setVisibility(View.VISIBLE);
+            }
+        });
+        waitForStart();
+
+        assertEquals(View.VISIBLE, redSquare.getVisibility());
+        assertEquals(View.VISIBLE, greenSquare.getVisibility());
+        assertEquals(View.VISIBLE, blueSquare.getVisibility());
+        assertEquals(View.VISIBLE, yellowSquare.getVisibility());
+        float redStartX = redSquare.getTranslationX();
+        float redStartY = redSquare.getTranslationY();
+
+        Thread.sleep(100);
+        assertTranslation(redSquare, true, true);
+        assertTranslation(greenSquare, false, true);
+        assertTranslation(blueSquare, false, false);
+        assertTranslation(yellowSquare, true, false);
+        assertTrue(redStartX < redSquare.getTranslationX()); // moving right
+        assertTrue(redStartY < redSquare.getTranslationY()); // moving down
+        waitForEnd(400);
+
+        assertNoTranslation(redSquare);
+        assertNoTranslation(greenSquare);
+        assertNoTranslation(blueSquare);
+        assertNoTranslation(yellowSquare);
+        assertEquals(View.VISIBLE, redSquare.getVisibility());
+        assertEquals(View.VISIBLE, greenSquare.getVisibility());
+        assertEquals(View.VISIBLE, blueSquare.getVisibility());
+        assertEquals(View.VISIBLE, yellowSquare.getVisibility());
+    }
+
+    private void assertTranslation(View view, boolean goLeft, boolean goUp) {
+        float translationX = view.getTranslationX();
+        float translationY = view.getTranslationY();
+
+        if (goLeft) {
+            assertTrue(translationX < 0);
+        } else {
+            assertTrue(translationX > 0);
+        }
+
+        if (goUp) {
+            assertTrue(translationY < 0);
+        } else {
+            assertTrue(translationY > 0);
+        }
+    }
+
+    private void assertNoTranslation(View view) {
+        assertEquals(0f, view.getTranslationX());
+        assertEquals(0f, view.getTranslationY());
+    }
+}
+
diff --git a/tests/tests/transition/src/android/transition/cts/FadeTest.java b/tests/tests/transition/src/android/transition/cts/FadeTest.java
new file mode 100644
index 0000000..a6a1b2f
--- /dev/null
+++ b/tests/tests/transition/src/android/transition/cts/FadeTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.transition.cts;
+
+import android.transition.Fade;
+
+/**
+ * This tests the public API for Fade. The alpha cannot be easily tested as part of CTS,
+ * so those are implementation tests.
+ */
+public class FadeTest extends BaseTransitionTest {
+    Fade mFade;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        resetTransition();
+    }
+
+    private void resetTransition() {
+        mFade = new Fade();
+        mFade.setDuration(200);
+        mTransition = mFade;
+        resetListener();
+    }
+
+    public void testMode() throws Throwable {
+        // Should animate in and out by default
+        enterScene(R.layout.scene4);
+        startTransition(R.layout.scene1);
+        assertEquals(1, mListener.endLatch.getCount());
+        waitForEnd(400);
+
+        resetListener();
+        startTransition(R.layout.scene4);
+        assertEquals(1, mListener.endLatch.getCount());
+        waitForEnd(400);
+
+        // Now only animate in
+        mFade = new Fade(Fade.IN);
+        mTransition = mFade;
+        resetListener();
+        startTransition(R.layout.scene1);
+        assertEquals(1, mListener.endLatch.getCount());
+        waitForEnd(400);
+
+        // No animation since it should only animate in
+        resetListener();
+        startTransition(R.layout.scene4);
+        waitForEnd(0);
+
+        // Now animate out, but no animation should happen since we're animating in.
+        mFade = new Fade(Fade.OUT);
+        mTransition = mFade;
+        resetListener();
+        startTransition(R.layout.scene1);
+        waitForEnd(0);
+
+        // but it should animate out
+        resetListener();
+        startTransition(R.layout.scene4);
+        assertEquals(1, mListener.endLatch.getCount());
+        waitForEnd(400);
+    }
+}
+
diff --git a/tests/tests/transition/src/android/transition/cts/PathMotionTest.java b/tests/tests/transition/src/android/transition/cts/PathMotionTest.java
new file mode 100644
index 0000000..97bf274
--- /dev/null
+++ b/tests/tests/transition/src/android/transition/cts/PathMotionTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.transition.cts;
+
+import android.graphics.Path;
+import android.graphics.PathMeasure;
+
+import junit.framework.TestCase;
+
+public class PathMotionTest extends TestCase {
+    public static void assertPathMatches(Path expectedPath, Path path) {
+        PathMeasure expectedMeasure = new PathMeasure(expectedPath, false);
+        PathMeasure pathMeasure = new PathMeasure(path, false);
+
+        float expectedLength = expectedMeasure.getLength();
+        assertEquals(expectedLength, pathMeasure.getLength(), 0.01f);
+
+        float minLength = Math.min(expectedLength, pathMeasure.getLength());
+
+        float pos[] = new float[2];
+
+        float increment = minLength / 5f;
+        for (float along = 0; along <= minLength; along += increment) {
+            expectedMeasure.getPosTan(along, pos, null);
+            float expectedX = pos[0];
+            float expectedY = pos[1];
+
+            pathMeasure.getPosTan(along, pos, null);
+            assertEquals(expectedX, pos[0], 0.01f);
+            assertEquals(expectedY, pos[1], 0.01f);
+        }
+    }
+}
diff --git a/tests/tests/transition/src/android/transition/cts/PatternPathMotionTest.java b/tests/tests/transition/src/android/transition/cts/PatternPathMotionTest.java
new file mode 100644
index 0000000..5485b4a
--- /dev/null
+++ b/tests/tests/transition/src/android/transition/cts/PatternPathMotionTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.transition.cts;
+
+import android.graphics.Path;
+import android.transition.PatternPathMotion;
+
+public class PatternPathMotionTest extends PathMotionTest {
+
+    public void testStraightPath() throws Throwable {
+        Path pattern = new Path();
+        pattern.moveTo(100, 500);
+        pattern.lineTo(300, 1000);
+
+        PatternPathMotion pathMotion = new PatternPathMotion(pattern);
+        assertPathMatches(pattern, pathMotion.getPatternPath());
+
+        Path expected = new Path();
+        expected.moveTo(0, 0);
+        expected.lineTo(100, 100);
+
+        assertPathMatches(expected, pathMotion.getPath(0, 0, 100, 100));
+    }
+
+    public void testCurve() throws Throwable {
+        Path pattern = new Path();
+        pattern.addArc(0, 0, 100, 100, 0, 180);
+
+        PatternPathMotion pathMotion = new PatternPathMotion(pattern);
+        assertPathMatches(pattern, pathMotion.getPatternPath());
+
+        Path expected = new Path();
+        expected.addArc(-50, 0, 50, 100, -90, 180);
+
+        assertPathMatches(expected, pathMotion.getPath(0, 0, 0, 100));
+    }
+}
+
diff --git a/tests/tests/transition/src/android/transition/cts/SlideBadEdgeTest.java b/tests/tests/transition/src/android/transition/cts/SlideBadEdgeTest.java
new file mode 100644
index 0000000..fefa353
--- /dev/null
+++ b/tests/tests/transition/src/android/transition/cts/SlideBadEdgeTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.transition.cts;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import android.transition.Slide;
+import android.view.Gravity;
+
+import junit.framework.TestCase;
+
+import org.junit.Test;
+
+public class SlideBadEdgeTest extends TestCase {
+
+    private static final Object[][] sBadGravity = {
+            { Gravity.AXIS_CLIP, "AXIS_CLIP" },
+            { Gravity.AXIS_PULL_AFTER, "AXIS_PULL_AFTER" },
+            { Gravity.AXIS_PULL_BEFORE, "AXIS_PULL_BEFORE" },
+            { Gravity.AXIS_SPECIFIED, "AXIS_SPECIFIED" },
+            { Gravity.AXIS_Y_SHIFT, "AXIS_Y_SHIFT" },
+            { Gravity.AXIS_X_SHIFT, "AXIS_X_SHIFT" },
+            { Gravity.CENTER, "CENTER" },
+            { Gravity.CLIP_VERTICAL, "CLIP_VERTICAL" },
+            { Gravity.CLIP_HORIZONTAL, "CLIP_HORIZONTAL" },
+            { Gravity.CENTER_VERTICAL, "CENTER_VERTICAL" },
+            { Gravity.CENTER_HORIZONTAL, "CENTER_HORIZONTAL" },
+            { Gravity.DISPLAY_CLIP_VERTICAL, "DISPLAY_CLIP_VERTICAL" },
+            { Gravity.DISPLAY_CLIP_HORIZONTAL, "DISPLAY_CLIP_HORIZONTAL" },
+            { Gravity.FILL_VERTICAL, "FILL_VERTICAL" },
+            { Gravity.FILL, "FILL" },
+            { Gravity.FILL_HORIZONTAL, "FILL_HORIZONTAL" },
+            { Gravity.HORIZONTAL_GRAVITY_MASK, "HORIZONTAL_GRAVITY_MASK" },
+            { Gravity.NO_GRAVITY, "NO_GRAVITY" },
+            { Gravity.RELATIVE_LAYOUT_DIRECTION, "RELATIVE_LAYOUT_DIRECTION" },
+            { Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK, "RELATIVE_HORIZONTAL_GRAVITY_MASK" },
+            { Gravity.VERTICAL_GRAVITY_MASK, "VERTICAL_GRAVITY_MASK" },
+    };
+
+    @SmallTest
+    public void testBadSide() {
+        for (int i = 0; i < sBadGravity.length; i++) {
+            int badEdge = (Integer) sBadGravity[i][0];
+            String edgeName = (String) sBadGravity[i][1];
+            try {
+                Slide slide = new Slide(badEdge);
+                fail("Should not be able to set slide edge to " + edgeName);
+            } catch (IllegalArgumentException e) {
+                // expected
+            }
+
+            try {
+                Slide slide = new Slide();
+                slide.setSlideEdge(badEdge);
+                fail("Should not be able to set slide edge to " + edgeName);
+            } catch (IllegalArgumentException e) {
+                // expected
+            }
+        }
+    }
+}
+
diff --git a/tests/tests/transition/src/android/transition/cts/SlideDefaultEdgeTest.java b/tests/tests/transition/src/android/transition/cts/SlideDefaultEdgeTest.java
new file mode 100644
index 0000000..060b4cc
--- /dev/null
+++ b/tests/tests/transition/src/android/transition/cts/SlideDefaultEdgeTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.transition.cts;
+
+import android.support.test.rule.ActivityTestRule;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.transition.Slide;
+import android.transition.TransitionManager;
+import android.view.Gravity;
+import android.view.View;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Arrays;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+public class SlideDefaultEdgeTest {
+    @Test
+    @SmallTest
+    public void testDefaultSide() {
+        // default to bottom
+        Slide slide = new Slide();
+        assertEquals(Gravity.BOTTOM, slide.getSlideEdge());
+    }
+}
+
diff --git a/tests/tests/transition/src/android/transition/cts/SlideEdgeTest.java b/tests/tests/transition/src/android/transition/cts/SlideEdgeTest.java
new file mode 100644
index 0000000..01225dc
--- /dev/null
+++ b/tests/tests/transition/src/android/transition/cts/SlideEdgeTest.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.transition.cts;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.transition.Slide;
+import android.transition.TransitionManager;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+
+import org.junit.Test;
+
+import java.util.concurrent.TimeUnit;
+
+@MediumTest
+public class SlideEdgeTest extends ActivityInstrumentationTestCase2<TransitionActivity>  {
+    private static final Object[][] sSlideEdgeArray = {
+            { Gravity.START, "START" },
+            { Gravity.END, "END" },
+            { Gravity.LEFT, "LEFT" },
+            { Gravity.TOP, "TOP" },
+            { Gravity.RIGHT, "RIGHT" },
+            { Gravity.BOTTOM, "BOTTOM" },
+    };
+
+    public SlideEdgeTest() {
+        super(TransitionActivity.class);
+    }
+
+    public void testSetSide() throws Throwable {
+        for (int i = 0; i < sSlideEdgeArray.length; i++) {
+            int slideEdge = (Integer) (sSlideEdgeArray[i][0]);
+            String edgeName = (String) (sSlideEdgeArray[i][1]);
+            Slide slide = new Slide(slideEdge);
+            assertEquals("Edge not set properly in constructor " + edgeName,
+                    slideEdge, slide.getSlideEdge());
+
+            slide = new Slide();
+            slide.setSlideEdge(slideEdge);
+            assertEquals("Edge not set properly with setter " + edgeName,
+                    slideEdge, slide.getSlideEdge());
+        }
+    }
+
+    public void testSlideOut() throws Throwable {
+        for (int i = 0; i < sSlideEdgeArray.length; i++) {
+            final int slideEdge = (Integer) (sSlideEdgeArray[i][0]);
+            final Slide slide = new Slide(slideEdge);
+            final SimpleTransitionListener listener = new SimpleTransitionListener();
+            slide.addListener(listener);
+
+            final Instrumentation instrumentation = getInstrumentation();
+            final Activity activity = getActivity();
+            instrumentation.runOnMainSync(new Runnable() {
+                @Override
+                public void run() {
+                    activity.setContentView(R.layout.scene1);
+                }
+            });
+            instrumentation.waitForIdleSync();
+
+            final View redSquare = activity.findViewById(R.id.redSquare);
+            final View greenSquare = activity.findViewById(R.id.greenSquare);
+            final View hello = activity.findViewById(R.id.hello);
+            final ViewGroup sceneRoot = (ViewGroup) activity.findViewById(R.id.holder);
+
+            instrumentation.runOnMainSync(new Runnable() {
+                @Override
+                public void run() {
+                    TransitionManager.beginDelayedTransition(sceneRoot, slide);
+                    redSquare.setVisibility(View.INVISIBLE);
+                    greenSquare.setVisibility(View.INVISIBLE);
+                    hello.setVisibility(View.INVISIBLE);
+                }
+            });
+            assertTrue(listener.startLatch.await(1, TimeUnit.SECONDS));
+            assertEquals(1, listener.endLatch.getCount());
+            assertEquals(View.VISIBLE, redSquare.getVisibility());
+            assertEquals(View.VISIBLE, greenSquare.getVisibility());
+            assertEquals(View.VISIBLE, hello.getVisibility());
+
+            float redStartX = redSquare.getTranslationX();
+            float redStartY = redSquare.getTranslationY();
+
+            Thread.sleep(200);
+            assertTranslation(slideEdge, redSquare);
+            assertTranslation(slideEdge, greenSquare);
+            assertTranslation(slideEdge, hello);
+
+            final float redMidX = redSquare.getTranslationX();
+            final float redMidY = redSquare.getTranslationY();
+
+            switch (slideEdge) {
+                case Gravity.LEFT:
+                case Gravity.START:
+                    assertTrue(
+                            "isn't sliding out to left. Expecting " + redStartX + " > " + redMidX,
+                            redStartX > redMidX);
+                    break;
+                case Gravity.RIGHT:
+                case Gravity.END:
+                    assertTrue(
+                            "isn't sliding out to right. Expecting " + redStartX + " < " + redMidX,
+                            redStartX < redMidX);
+                    break;
+                case Gravity.TOP:
+                    assertTrue("isn't sliding out to top. Expecting " + redStartY + " > " + redMidY,
+                            redStartY > redSquare.getTranslationY());
+                    break;
+                case Gravity.BOTTOM:
+                    assertTrue(
+                            "isn't sliding out to bottom. Expecting " + redStartY + " < " + redMidY,
+                            redStartY < redSquare.getTranslationY());
+                    break;
+            }
+            assertTrue(listener.endLatch.await(1, TimeUnit.SECONDS));
+            instrumentation.waitForIdleSync();
+
+            assertNoTranslation(redSquare);
+            assertNoTranslation(greenSquare);
+            assertNoTranslation(hello);
+            assertEquals(View.INVISIBLE, redSquare.getVisibility());
+            assertEquals(View.INVISIBLE, greenSquare.getVisibility());
+            assertEquals(View.INVISIBLE, hello.getVisibility());
+        }
+    }
+
+    public void testSlideIn() throws Throwable {
+        for (int i = 0; i < sSlideEdgeArray.length; i++) {
+            final int slideEdge = (Integer) (sSlideEdgeArray[i][0]);
+            final Slide slide = new Slide(slideEdge);
+            final SimpleTransitionListener listener = new SimpleTransitionListener();
+            slide.addListener(listener);
+
+            final Instrumentation instrumentation = getInstrumentation();
+            final Activity activity = getActivity();
+
+            instrumentation.runOnMainSync(new Runnable() {
+                @Override
+                public void run() {
+                    activity.setContentView(R.layout.scene1);
+                }
+            });
+            instrumentation.waitForIdleSync();
+
+            final View redSquare = activity.findViewById(R.id.redSquare);
+            final View greenSquare = activity.findViewById(R.id.greenSquare);
+            final View hello = activity.findViewById(R.id.hello);
+            final ViewGroup sceneRoot = (ViewGroup) activity.findViewById(R.id.holder);
+
+            instrumentation.runOnMainSync(new Runnable() {
+                @Override
+                public void run() {
+                    redSquare.setVisibility(View.INVISIBLE);
+                    greenSquare.setVisibility(View.INVISIBLE);
+                    hello.setVisibility(View.INVISIBLE);
+                }
+            });
+            instrumentation.waitForIdleSync();
+
+            // now slide in
+            instrumentation.runOnMainSync(new Runnable() {
+                @Override
+                public void run() {
+                    TransitionManager.beginDelayedTransition(sceneRoot, slide);
+                    redSquare.setVisibility(View.VISIBLE);
+                    greenSquare.setVisibility(View.VISIBLE);
+                    hello.setVisibility(View.VISIBLE);
+                }
+            });
+            assertTrue(listener.startLatch.await(1, TimeUnit.SECONDS));
+
+            assertEquals(1, listener.endLatch.getCount());
+            assertEquals(View.VISIBLE, redSquare.getVisibility());
+            assertEquals(View.VISIBLE, greenSquare.getVisibility());
+            assertEquals(View.VISIBLE, hello.getVisibility());
+
+            final float redStartX = redSquare.getTranslationX();
+            final float redStartY = redSquare.getTranslationY();
+
+            Thread.sleep(200);
+            assertTranslation(slideEdge, redSquare);
+            assertTranslation(slideEdge, greenSquare);
+            assertTranslation(slideEdge, hello);
+            final float redMidX = redSquare.getTranslationX();
+            final float redMidY = redSquare.getTranslationY();
+
+            switch (slideEdge) {
+                case Gravity.LEFT:
+                case Gravity.START:
+                    assertTrue(
+                            "isn't sliding in from left. Expecting " + redStartX + " < " + redMidX,
+                            redStartX < redMidX);
+                    break;
+                case Gravity.RIGHT:
+                case Gravity.END:
+                    assertTrue(
+                            "isn't sliding in from right. Expecting " + redStartX + " > " + redMidX,
+                            redStartX > redMidX);
+                    break;
+                case Gravity.TOP:
+                    assertTrue(
+                            "isn't sliding in from top. Expecting " + redStartY + " < " + redMidY,
+                            redStartY < redSquare.getTranslationY());
+                    break;
+                case Gravity.BOTTOM:
+                    assertTrue("isn't sliding in from bottom. Expecting " + redStartY + " > "
+                                    + redMidY,
+                            redStartY > redSquare.getTranslationY());
+                    break;
+            }
+            assertTrue(listener.endLatch.await(1, TimeUnit.SECONDS));
+            instrumentation.waitForIdleSync();
+
+            assertNoTranslation(redSquare);
+            assertNoTranslation(greenSquare);
+            assertNoTranslation(hello);
+            assertEquals(View.VISIBLE, redSquare.getVisibility());
+            assertEquals(View.VISIBLE, greenSquare.getVisibility());
+            assertEquals(View.VISIBLE, hello.getVisibility());
+        }
+    }
+
+    private void assertTranslation(int slideEdge, View view) {
+        switch (slideEdge) {
+            case Gravity.LEFT:
+            case Gravity.START:
+                assertTrue(view.getTranslationX() < 0);
+                assertEquals(0f, view.getTranslationY(), 0.01f);
+                break;
+            case Gravity.RIGHT:
+            case Gravity.END:
+                assertTrue(view.getTranslationX() > 0);
+                assertEquals(0f, view.getTranslationY(), 0.01f);
+                break;
+            case Gravity.TOP:
+                assertTrue(view.getTranslationY() < 0);
+                assertEquals(0f, view.getTranslationX(), 0.01f);
+                break;
+            case Gravity.BOTTOM:
+                assertTrue(view.getTranslationY() > 0);
+                assertEquals(0f, view.getTranslationX(), 0.01f);
+                break;
+        }
+    }
+
+    private void assertNoTranslation(View view) {
+        assertEquals(0f, view.getTranslationX(), 0.01f);
+        assertEquals(0f, view.getTranslationY(), 0.01f);
+    }
+}
+
diff --git a/tests/tests/transition/src/android/transition/cts/TransitionSetTest.java b/tests/tests/transition/src/android/transition/cts/TransitionSetTest.java
index 3afe812..adfc36a 100644
--- a/tests/tests/transition/src/android/transition/cts/TransitionSetTest.java
+++ b/tests/tests/transition/src/android/transition/cts/TransitionSetTest.java
@@ -39,10 +39,13 @@
         assertEquals(TransitionSet.ORDERING_TOGETHER, transitionSet.getOrdering());
         enterScene(R.layout.scene1);
         startTransition(R.layout.scene3);
-        assertTrue(fadeListener.startLatch.await(0, TimeUnit.MILLISECONDS));
-        assertTrue(changeBoundsListener.startLatch.await(0, TimeUnit.MILLISECONDS));
-
-        endTransition();
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals(0, fadeListener.startLatch.getCount());
+                assertEquals(0, changeBoundsListener.startLatch.getCount());
+            }
+        });
     }
 
     public void testTransitionSequentially() throws Throwable {
@@ -64,11 +67,20 @@
 
         enterScene(R.layout.scene1);
         startTransition(R.layout.scene3);
-        assertTrue(fadeListener.startLatch.await(0, TimeUnit.MILLISECONDS));
-        assertEquals(1, changeBoundsListener.startLatch.getCount());
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals(0, fadeListener.startLatch.getCount());
+                assertEquals(1, changeBoundsListener.startLatch.getCount());
+            }
+        });
         assertTrue(fadeListener.endLatch.await(400, TimeUnit.MILLISECONDS));
-        assertTrue(changeBoundsListener.startLatch.await(0, TimeUnit.MILLISECONDS));
-        endTransition();
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals(0, changeBoundsListener.startLatch.getCount());
+            }
+        });
     }
 
     public void testTransitionCount() throws Throwable {
diff --git a/tests/tests/transition/src/android/transition/cts/VisibilityTest.java b/tests/tests/transition/src/android/transition/cts/VisibilityTest.java
index 091b229..9b91a36 100644
--- a/tests/tests/transition/src/android/transition/cts/VisibilityTest.java
+++ b/tests/tests/transition/src/android/transition/cts/VisibilityTest.java
@@ -15,15 +15,9 @@
  */
 package android.transition.cts;
 
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
 import android.transition.TransitionValues;
 import android.transition.Visibility;
 import android.view.View;
-import android.view.ViewGroup;
-
-import java.util.HashMap;
-import java.util.concurrent.CountDownLatch;
 
 public class VisibilityTest extends BaseTransitionTest {
     Visibility mVisibilityTransition;
@@ -41,20 +35,31 @@
         assertEquals(Visibility.MODE_IN | Visibility.MODE_OUT, mVisibilityTransition.getMode());
 
         // Should animate in and out
+        enterScene(R.layout.scene4);
+        startTransition(R.layout.scene1);
+        assertEquals(1, mListener.endLatch.getCount());
+        waitForEnd(400);
+
+        resetListener();
         startTransition(R.layout.scene4);
         assertEquals(1, mListener.endLatch.getCount());
-        endTransition();
-        waitForEnd(100);
+        waitForEnd(400);
 
+        // Now only animate in
         resetListener();
         mVisibilityTransition.setMode(Visibility.MODE_IN);
         startTransition(R.layout.scene1);
         assertEquals(1, mListener.endLatch.getCount());
-        endTransition();
-        waitForEnd(100);
+        waitForEnd(400);
 
+        // No animation since it should only animate in
         resetListener();
-        mVisibilityTransition.setMode(Visibility.MODE_OUT); // now it shouldn't do any animation
+        startTransition(R.layout.scene4);
+        waitForEnd(0);
+
+        // Now animate out, but no animation should happen since we're animating in.
+        resetListener();
+        mVisibilityTransition.setMode(Visibility.MODE_OUT);
         startTransition(R.layout.scene1);
         waitForEnd(0);
 
@@ -62,20 +67,7 @@
         resetListener();
         startTransition(R.layout.scene4);
         assertEquals(1, mListener.endLatch.getCount());
-        endTransition();
-        waitForEnd(100);
-
-        // switch the mode to only animate in
-        resetListener();
-        mVisibilityTransition.setMode(Visibility.MODE_IN);
-        startTransition(R.layout.scene1);
-        assertEquals(1, mListener.endLatch.getCount());
-        endTransition();
-        waitForEnd(100);
-
-        // but it shouldn't animate out
-        startTransition(R.layout.scene1);
-        waitForEnd(0);
+        waitForEnd(400);
     }
 
     public void testIsVisible() throws Throwable {
diff --git a/tests/tests/uiautomation/AndroidManifest.xml b/tests/tests/uiautomation/AndroidManifest.xml
index dac6532..6dc28ed 100644
--- a/tests/tests/uiautomation/AndroidManifest.xml
+++ b/tests/tests/uiautomation/AndroidManifest.xml
@@ -52,7 +52,7 @@
 
   </application>
 
-  <instrumentation android:name="android.support.test.uiautomator.UiAutomatorInstrumentationTestRunner"
+  <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                    android:targetPackage="android.app.uiautomation.cts">
         <meta-data android:name="listener"
             android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/uiautomation/AndroidTest.xml b/tests/tests/uiautomation/AndroidTest.xml
index cf15c6b..c4f1665 100644
--- a/tests/tests/uiautomation/AndroidTest.xml
+++ b/tests/tests/uiautomation/AndroidTest.xml
@@ -20,5 +20,6 @@
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.app.uiautomation.cts" />
+        <option name="runtime-hint" value="6m42s" />
     </test>
 </configuration>
diff --git a/tests/tests/uirendering/AndroidTest.xml b/tests/tests/uirendering/AndroidTest.xml
index 30c99db..c89300b 100644
--- a/tests/tests/uirendering/AndroidTest.xml
+++ b/tests/tests/uirendering/AndroidTest.xml
@@ -20,6 +20,6 @@
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.uirendering.cts" />
-        <option name="runtime-hint" value="3m" />
+        <option name="runtime-hint" value="11m55s" />
     </test>
 </configuration>
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapFilterTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapFilterTests.java
index b324b06..d0820e2 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapFilterTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapFilterTests.java
@@ -20,13 +20,15 @@
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.PaintFlagsDrawFilter;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.uirendering.cts.bitmapverifiers.BitmapVerifier;
 import android.uirendering.cts.bitmapverifiers.ColorVerifier;
 import android.uirendering.cts.bitmapverifiers.PerPixelBitmapVerifier;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
 import android.uirendering.cts.testinfrastructure.CanvasClient;
+import org.junit.Test;
 
+@MediumTest
 public class BitmapFilterTests extends ActivityTestBase {
     private static final int WHITE_WEIGHT = 255 * 3;
     private enum FilterEnum {
@@ -75,32 +77,32 @@
     private static final int BIG_GRID_SIZE = TEST_WIDTH * 2;
     private Bitmap mBigGridBitmap = createGridBitmap(BIG_GRID_SIZE, BIG_GRID_SIZE);
 
-    @SmallTest
+    @Test
     public void testPaintFilterScaleUp() {
         runScaleTest(FilterEnum.PAINT_FILTER, true);
     }
 
-    @SmallTest
+    @Test
     public void testPaintFilterScaleDown() {
         runScaleTest(FilterEnum.PAINT_FILTER, false);
     }
 
-    @SmallTest
+    @Test
     public void testDrawFilterRemoveFilterScaleUp() {
         runScaleTest(FilterEnum.REMOVE_FILTER, true);
     }
 
-    @SmallTest
+    @Test
     public void testDrawFilterRemoveFilterScaleDown() {
         runScaleTest(FilterEnum.REMOVE_FILTER, false);
     }
 
-    @SmallTest
+    @Test
     public void testDrawFilterScaleUp() {
         runScaleTest(FilterEnum.ADD_FILTER, true);
     }
 
-    @SmallTest
+    @Test
     public void testDrawFilterScaleDown() {
         runScaleTest(FilterEnum.ADD_FILTER, false);
     }
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/CanvasStateTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/CanvasStateTests.java
index becc2f7..38d884d 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/CanvasStateTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/CanvasStateTests.java
@@ -20,9 +20,13 @@
 import android.graphics.Path;
 import android.graphics.RectF;
 import android.graphics.Region;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
 import android.uirendering.cts.testinfrastructure.CanvasClient;
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 /**
  * Tests of state query-able from canvas at draw time.
@@ -30,9 +34,9 @@
  * Although these tests don't verify drawing content, they still make use of ActivityTestBase's
  * capability to test the hardware accelerated Canvas in the way that it is used by Views.
  */
+@MediumTest
 public class CanvasStateTests extends ActivityTestBase {
-
-    @SmallTest
+    @Test
     public void testClipRectReturnValues() {
         createTest()
                 .addCanvasClient(new CanvasClient() {
@@ -50,7 +54,7 @@
                 .runWithoutVerification();
     }
 
-    @SmallTest
+    @Test
     public void testClipRegionReturnValues() {
         createTest()
                 .addCanvasClient(new CanvasClient() {
@@ -83,7 +87,7 @@
                 .runWithoutVerification();
     }
 
-    @SmallTest
+    @Test
     public void testClipPathReturnValues() {
         createTest()
                 .addCanvasClient(new CanvasClient() {
@@ -104,7 +108,7 @@
                 })
                 .runWithoutVerification();
     }
-    @SmallTest
+    @Test
     public void testQuickReject() {
         createTest()
                 .addCanvasClient(new CanvasClient() {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ColorFilterAlphaTest.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ColorFilterAlphaTest.java
new file mode 100644
index 0000000..483ad87
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ColorFilterAlphaTest.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.uirendering.cts.testclasses;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.PorterDuffColorFilter;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
+import android.uirendering.cts.testinfrastructure.ActivityTestBase;
+import android.uirendering.cts.testinfrastructure.CanvasClient;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.List;
+
+@MediumTest
+@RunWith(Parameterized.class)
+public class ColorFilterAlphaTest extends ActivityTestBase {
+    // We care about one point in each of the four rectangles of different alpha values, as well as
+    // the area outside the rectangles
+
+    public static final int FILTER_COLOR = 0xFFBB0000;
+
+    private static final Point[] TEST_POINTS = new Point[] {
+            new Point(9, 45),
+            new Point(27, 45),
+            new Point(45, 45),
+            new Point(63, 45),
+            new Point(81, 45)
+    };
+
+    private static Object[][] MODES_AND_EXPECTED_COLORS = new Object[][] {
+        { PorterDuff.Mode.DST, new int[] {
+                0xFFE6E6E6, 0xFFCCCCCC, 0xFFB3B3B3, 0xFF999999, 0xFFFFFFFF } },
+
+        { PorterDuff.Mode.SRC_OVER, new int[] {
+                0xFFBB0000, 0xFFBB0000, 0xFFBB0000, 0xFFBB0000, 0xFFBB0000 } },
+
+        { PorterDuff.Mode.DST_OVER, new int[] {
+                0xFFAF1A1A, 0xFFA33333, 0xFF984D4D, 0xFF8B6666, 0xFFBB0000 } },
+
+        { PorterDuff.Mode.SRC_IN, new int[] {
+                0xFFF1CCCC, 0xFFE49999, 0xFFD66666, 0xFFC83333, 0xFFFFFFFF } },
+
+        { PorterDuff.Mode.DST_IN, new int[] {
+                0xFFE6E6E6, 0xFFCCCCCC, 0xFFB3B3B3, 0xFF999999, 0xFFFFFFFF } },
+
+        { PorterDuff.Mode.SRC_OUT, new int[] {
+                0xFFC83333, 0xFFD66666, 0xFFE49999, 0xFFF1CCCC, 0xFFBB0000 } },
+
+        { PorterDuff.Mode.DST_OUT, new int[] {
+                0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF } },
+
+        { PorterDuff.Mode.SRC_ATOP, new int[] {
+                0xFFF1CCCC, 0xFFE49999, 0xFFD66666, 0xFFC93333, 0xFFFFFFFF } },
+
+        { PorterDuff.Mode.DST_ATOP, new int[] {
+                0xFFB01A1A, 0xFFA33333, 0xFF984D4D, 0xFF8B6666, 0xFFBB0000 } },
+
+        { PorterDuff.Mode.XOR, new int[] {
+                0xFFC93333, 0xFFD66666, 0xFFE49999, 0xFFF1CCCC, 0xFFBB0000 } },
+
+        { PorterDuff.Mode.MULTIPLY, new int[] {
+                0xFFDFCCCC, 0xFFBE9999, 0xFF9E6666, 0xFF7E3333, 0xFFFFFFFF } },
+
+        { PorterDuff.Mode.SCREEN, new int[] {
+                0xFFC21A1A, 0xFFC93333, 0xFFD04D4D, 0xFFD66666, 0xFFBB0000 } },
+    };
+
+    @Parameterized.Parameters(name = "{0}")
+    public static List<XfermodeTest.Config> configs() {
+        return XfermodeTest.configs(MODES_AND_EXPECTED_COLORS);
+    }
+
+    private final XfermodeTest.Config mConfig;
+
+    public ColorFilterAlphaTest(XfermodeTest.Config config) {
+        mConfig = config;
+    }
+
+    private static final int[] BLOCK_COLORS = new int[] {
+            0x33808080,
+            0x66808080,
+            0x99808080,
+            0xCC808080,
+            0x00000000
+    };
+
+    private static Bitmap createMultiRectBitmap() {
+        Bitmap bitmap = Bitmap.createBitmap(TEST_WIDTH, TEST_HEIGHT, Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(bitmap);
+        Paint paint = new Paint();
+        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
+        final int blockCount = BLOCK_COLORS.length;
+        final int blockWidth = TEST_WIDTH / blockCount;
+        for (int i = 0 ; i < blockCount; i++) {
+            paint.setColor(BLOCK_COLORS[i]);
+            canvas.drawRect(i * blockWidth, 0, (i + 1) * blockWidth, TEST_HEIGHT, paint);
+        }
+        return bitmap;
+    }
+
+    private CanvasClient mCanvasClient = new CanvasClient() {
+        final Paint mPaint = new Paint();
+        private final Bitmap mBitmap = createMultiRectBitmap();
+
+        @Override
+        public void draw(Canvas canvas, int width, int height) {
+            mPaint.setColorFilter(new PorterDuffColorFilter(FILTER_COLOR, mConfig.mode));
+            canvas.drawBitmap(mBitmap, 0, 0, mPaint);
+        }
+    };
+
+    @Test
+    public void test() {
+        createTest()
+                .addCanvasClient(mCanvasClient, mConfig.hardwareAccelerated)
+                .runWithVerifier(new SamplePointVerifier(TEST_POINTS, mConfig.expectedColors));
+    }
+}
+
+
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
index d3fdb7b..bf68f3e 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
@@ -22,7 +22,7 @@
 import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.graphics.drawable.NinePatchDrawable;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.uirendering.cts.bitmapcomparers.BitmapComparer;
 import android.uirendering.cts.bitmapcomparers.ExactComparer;
 import android.uirendering.cts.bitmapverifiers.BitmapVerifier;
@@ -30,11 +30,13 @@
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
 import android.uirendering.cts.testinfrastructure.CanvasClient;
 import android.uirendering.cts.R;
+import org.junit.Test;
 
+@MediumTest
 public class ExactCanvasTests extends ActivityTestBase {
     private final BitmapComparer mExactComparer = new ExactComparer();
 
-    @SmallTest
+    @Test
     public void testBlueRect() {
         final Rect rect = new Rect(10, 10, 80, 80);
         createTest()
@@ -50,7 +52,7 @@
                 .runWithVerifier(new RectVerifier(Color.WHITE, Color.BLUE, rect));
     }
 
-    @SmallTest
+    @Test
     public void testPoints() {
         createTest()
                 .addCanvasClient(new CanvasClient() {
@@ -68,7 +70,7 @@
                 .runWithComparer(mExactComparer);
     }
 
-    @SmallTest
+    @Test
     public void testBlackRectWithStroke() {
         createTest()
                 .addCanvasClient(new CanvasClient() {
@@ -86,7 +88,7 @@
                 .runWithComparer(mExactComparer);
     }
 
-    @SmallTest
+    @Test
     public void testBlackLineOnGreenBack() {
         createTest()
                 .addCanvasClient(new CanvasClient() {
@@ -102,7 +104,7 @@
                 .runWithComparer(mExactComparer);
     }
 
-    @SmallTest
+    @Test
     public void testDrawRedRectOnBlueBack() {
         createTest()
                 .addCanvasClient(new CanvasClient() {
@@ -117,7 +119,7 @@
                 .runWithComparer(mExactComparer);
     }
 
-    @SmallTest
+    @Test
     public void testDrawLine() {
         createTest()
                 .addCanvasClient(new CanvasClient() {
@@ -135,7 +137,7 @@
                 .runWithComparer(mExactComparer);
     }
 
-    @SmallTest
+    @Test
     public void testDrawWhiteScreen() {
         createTest()
                 .addCanvasClient(new CanvasClient() {
@@ -147,7 +149,7 @@
                 .runWithComparer(mExactComparer);
     }
 
-    @SmallTest
+    @Test
     public void testBasicText() {
         final String testString = "THIS IS A TEST";
         createTest()
@@ -164,7 +166,7 @@
                 .runWithComparer(mExactComparer);
     }
 
-    @SmallTest
+    @Test
     public void testBasicColorXfermode() {
         createTest()
                 .addCanvasClient(new CanvasClient() {
@@ -177,7 +179,7 @@
                 .runWithComparer(mExactComparer);
     }
 
-    @SmallTest
+    @Test
     public void testBluePaddedSquare() {
         final NinePatchDrawable ninePatchDrawable = (NinePatchDrawable)
             getActivity().getResources().getDrawable(R.drawable.blue_padded_square);
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/FontRenderingTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/FontRenderingTests.java
index bac3629..738dcfb 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/FontRenderingTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/FontRenderingTests.java
@@ -22,7 +22,7 @@
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Typeface;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.uirendering.cts.bitmapcomparers.BitmapComparer;
 import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
 import android.uirendering.cts.bitmapverifiers.GoldenImageVerifier;
@@ -30,7 +30,9 @@
 import android.uirendering.cts.testinfrastructure.CanvasClient;
 
 import android.uirendering.cts.R;
+import org.junit.Test;
 
+@MediumTest
 public class FontRenderingTests extends ActivityTestBase {
     // Thresholds are barely loose enough for differences between sw and hw renderers.
     private static final double REGULAR_THRESHOLD = 0.92;
@@ -67,42 +69,42 @@
                 .runWithVerifier(new GoldenImageVerifier(goldenBitmap, comparer));
     }
 
-    @SmallTest
+    @Test
     public void testDefaultFont() {
         fontTestBody("sans-serif",
                 Typeface.NORMAL,
                 R.drawable.hello1);
     }
 
-    @SmallTest
+    @Test
     public void testBoldFont() {
         fontTestBody("sans-serif",
                 Typeface.BOLD,
                 R.drawable.bold1);
     }
 
-    @SmallTest
+    @Test
     public void testItalicFont() {
         fontTestBody("sans-serif",
                 Typeface.ITALIC,
                 R.drawable.italic1);
     }
 
-    @SmallTest
+    @Test
     public void testBoldItalicFont() {
         fontTestBody("sans-serif",
                 Typeface.BOLD | Typeface.ITALIC,
                 R.drawable.bolditalic1);
     }
 
-    @SmallTest
+    @Test
     public void testMediumFont() {
         fontTestBody("sans-serif-medium",
                 Typeface.NORMAL,
                 R.drawable.medium1);
     }
 
-    @SmallTest
+    @Test
     public void testMediumBoldFont() {
         // bold attribute on medium base font = black
         fontTestBody("sans-serif-medium",
@@ -110,28 +112,28 @@
                 R.drawable.black1);
     }
 
-    @SmallTest
+    @Test
     public void testMediumItalicFont() {
         fontTestBody("sans-serif-medium",
                 Typeface.ITALIC,
                 R.drawable.mediumitalic1);
     }
 
-    @SmallTest
+    @Test
     public void testMediumBoldItalicFont() {
         fontTestBody("sans-serif-medium",
                 Typeface.BOLD | Typeface.ITALIC,
                 R.drawable.blackitalic1);
     }
 
-    @SmallTest
+    @Test
     public void testLightFont() {
         fontTestBody("sans-serif-light",
                 Typeface.NORMAL,
                 R.drawable.light1);
     }
 
-    @SmallTest
+    @Test
     public void testLightBoldFont() {
         // bold attribute on light base font = medium
         fontTestBody("sans-serif-light",
@@ -139,28 +141,28 @@
                 R.drawable.medium1);
     }
 
-    @SmallTest
+    @Test
     public void testLightItalicFont() {
         fontTestBody("sans-serif-light",
                 Typeface.ITALIC,
                 R.drawable.lightitalic1);
     }
 
-    @SmallTest
+    @Test
     public void testLightBoldItalicFont() {
         fontTestBody("sans-serif-light",
                 Typeface.BOLD | Typeface.ITALIC,
                 R.drawable.mediumitalic1);
     }
 
-    @SmallTest
+    @Test
     public void testThinFont() {
         fontTestBody("sans-serif-thin",
                 Typeface.NORMAL,
                 R.drawable.thin1);
     }
 
-    @SmallTest
+    @Test
     public void testThinBoldFont() {
         // bold attribute on thin base font = normal
         fontTestBody("sans-serif-thin",
@@ -168,28 +170,28 @@
                 R.drawable.hello1);
     }
 
-    @SmallTest
+    @Test
     public void testThinItalicFont() {
         fontTestBody("sans-serif-thin",
                 Typeface.ITALIC,
                 R.drawable.thinitalic1);
     }
 
-    @SmallTest
+    @Test
     public void testThinBoldItalicFont() {
         fontTestBody("sans-serif-thin",
                 Typeface.BOLD | Typeface.ITALIC,
                 R.drawable.italic1);
     }
 
-    @SmallTest
+    @Test
     public void testBlackFont() {
         fontTestBody("sans-serif-black",
                 Typeface.NORMAL,
                 R.drawable.black1);
     }
 
-    @SmallTest
+    @Test
     public void testBlackBoldFont() {
         // bold attribute on black base font = black
         fontTestBody("sans-serif-black",
@@ -197,14 +199,14 @@
                 R.drawable.black1);
     }
 
-    @SmallTest
+    @Test
     public void testBlackItalicFont() {
         fontTestBody("sans-serif-black",
                 Typeface.ITALIC,
                 R.drawable.blackitalic1);
     }
 
-    @SmallTest
+    @Test
     public void testBlackBoldItalicFont() {
         fontTestBody("sans-serif-black",
                 Typeface.BOLD | Typeface.ITALIC,
@@ -213,42 +215,42 @@
 
     /* condensed fonts */
 
-    @SmallTest
+    @Test
     public void testCondensedFont() {
         fontTestBody("sans-serif-condensed",
                 Typeface.NORMAL,
                 R.drawable.condensed1);
     }
 
-    @SmallTest
+    @Test
     public void testCondensedBoldFont() {
         fontTestBody("sans-serif-condensed",
                 Typeface.BOLD,
                 R.drawable.condensedbold1);
     }
 
-    @SmallTest
+    @Test
     public void testCondensedItalicFont() {
         fontTestBody("sans-serif-condensed",
                 Typeface.ITALIC,
                 R.drawable.condenseditalic1);
     }
 
-    @SmallTest
+    @Test
     public void testCondensedBoldItalicFont() {
         fontTestBody("sans-serif-condensed",
                 Typeface.BOLD | Typeface.ITALIC,
                 R.drawable.condensedbolditalic1);
     }
 
-    @SmallTest
+    @Test
     public void testCondensedLightFont() {
         fontTestBody("sans-serif-condensed-light",
                 Typeface.NORMAL,
                 R.drawable.condensedlight1);
     }
 
-    @SmallTest
+    @Test
     public void testCondensedLightItalicFont() {
         fontTestBody("sans-serif-condensed-light",
                 Typeface.ITALIC,
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java
index 37329af..c070b96 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java
@@ -16,12 +16,12 @@
 package android.uirendering.cts.testclasses;
 
 import android.graphics.Point;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.uirendering.cts.R;
 
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Rect;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.uirendering.cts.bitmapcomparers.BitmapComparer;
 import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
 import android.uirendering.cts.bitmapverifiers.RectVerifier;
@@ -29,10 +29,12 @@
 import android.uirendering.cts.testinfrastructure.CanvasClient;
 import android.uirendering.cts.testinfrastructure.ViewInitializer;
 import android.view.View;
+import org.junit.Test;
 
+@MediumTest
 public class InfrastructureTests extends ActivityTestBase {
 
-    @SmallTest
+    @Test
     public void testScreenshot() {
         for (int i = 0 ; i < 500 ; i ++) {
             takeScreenshot(new Point());
@@ -45,7 +47,7 @@
      * by verifying that two paths that should render differently *do* render
      * differently.
      */
-    @SmallTest
+    @Test
     public void testRenderSpecIsolation() {
         CanvasClient canvasClient = new CanvasClient() {
             @Override
@@ -70,7 +72,7 @@
                 .runWithComparer(inverseComparer);
     }
 
-    @SmallTest
+    @Test
     public void testViewInitializer() {
         final Rect clipRect = new Rect(0, 0, 50, 50);
         ViewInitializer viewInitializer = new ViewInitializer() {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java
index a1338bc..30dbb03 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java
@@ -23,15 +23,20 @@
 import android.graphics.Paint;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.uirendering.cts.bitmapverifiers.ColorVerifier;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
 import android.uirendering.cts.testinfrastructure.ViewInitializer;
 import android.view.View;
 import android.uirendering.cts.R;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
+@MediumTest
+@RunWith(AndroidJUnit4.class)
 public class LayerTests extends ActivityTestBase {
-    @SmallTest
+    @Test
     public void testLayerPaintAlpha() {
         // red channel full strength, other channels 75% strength
         // (since 25% alpha red subtracts from them)
@@ -53,7 +58,7 @@
                 .runWithVerifier(new ColorVerifier(expectedColor));
     }
 
-    @SmallTest
+    @Test
     public void testLayerPaintColorFilter() {
         // Red, fully desaturated. Note that it's not 255/3 in each channel.
         // See ColorMatrix#setSaturation()
@@ -73,7 +78,7 @@
                 .runWithVerifier(new ColorVerifier(expectedColor));
     }
 
-    @SmallTest
+    @Test
     public void testLayerPaintBlend() {
         // Red, drawn underneath opaque white, so output should be white.
         // TODO: consider doing more interesting blending test here
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayoutTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayoutTests.java
index 30851b6..d69126c 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayoutTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayoutTests.java
@@ -17,21 +17,23 @@
 
 import android.graphics.Color;
 import android.graphics.Rect;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.uirendering.cts.bitmapverifiers.ColorVerifier;
 import android.uirendering.cts.bitmapverifiers.RectVerifier;
 import android.uirendering.cts.R;
 
-import android.test.suitebuilder.annotation.SmallTest;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
+import org.junit.Test;
 
+@MediumTest
 public class LayoutTests extends ActivityTestBase {
-    @SmallTest
+    @Test
     public void testSimpleRedLayout() {
         createTest().addLayout(R.layout.simple_red_layout, null, false).runWithVerifier(
                 new ColorVerifier(Color.RED));
     }
 
-    @SmallTest
+    @Test
     public void testSimpleRectLayout() {
         createTest().addLayout(R.layout.simple_rect_layout, null, false).runWithVerifier(
                 new RectVerifier(Color.WHITE, Color.BLUE, new Rect(5, 5, 85, 85)));
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java
index 8c00ecc..03f5e89 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java
@@ -23,7 +23,7 @@
 import android.graphics.Path;
 import android.graphics.Point;
 import android.graphics.Typeface;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
 import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
@@ -33,7 +33,11 @@
 import android.view.ViewGroup;
 import android.webkit.WebView;
 import android.uirendering.cts.R;
+import org.junit.Test;
 
+import static org.junit.Assert.assertNotNull;
+
+@MediumTest
 public class PathClippingTests extends ActivityTestBase {
     // draw circle with hole in it, with stroked circle
     static final CanvasClient sTorusDrawCanvasClient = new CanvasClient() {
@@ -75,7 +79,7 @@
         }
     };
 
-    @SmallTest
+    @Test
     public void testCircleWithCircle() {
         createTest()
                 .addCanvasClient(sTorusDrawCanvasClient, false)
@@ -83,7 +87,7 @@
                 .runWithComparer(new MSSIMComparer(0.90));
     }
 
-    @SmallTest
+    @Test
     public void testCircleWithPoints() {
         createTest()
                 .addCanvasClient(sTorusClipCanvasClient)
@@ -105,7 +109,7 @@
                         }));
     }
 
-    @SmallTest
+    @Test
     public void testViewRotate() {
         createTest()
                 .addLayout(R.layout.blue_padded_layout, new ViewInitializer() {
@@ -137,7 +141,7 @@
                         }));
     }
 
-    @SmallTest
+    @Test
     public void testTextClip() {
         createTest()
                 .addCanvasClient(new CanvasClient() {
@@ -162,7 +166,7 @@
                 .runWithComparer(new MSSIMComparer(0.90));
     }
 
-    @SmallTest
+    @Test
     public void testWebViewClipWithCircle() {
         if (!getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_WEBVIEW)) {
             return; // no WebView to run test on
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PictureTest.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PictureTest.java
index 6619b11..9c8f9ba 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PictureTest.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PictureTest.java
@@ -21,18 +21,20 @@
 import android.graphics.Paint;
 import android.graphics.Picture;
 import android.graphics.Rect;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.uirendering.cts.bitmapverifiers.ColorVerifier;
 import android.uirendering.cts.bitmapverifiers.RectVerifier;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
 import android.uirendering.cts.testinfrastructure.CanvasClient;
+import org.junit.Test;
 
+@MediumTest
 public class PictureTest extends ActivityTestBase {
 
     private static final Rect sRect = new Rect(0, 0, 40, 40);
     private static final Rect sOffsetRect = new Rect(40, 0, 80, 40);
 
-    private static final Picture greenSquare() {
+    private static Picture greenSquare() {
         Paint pt = new Paint();
         pt.setColor(Color.GREEN);
         Picture pic = new Picture();
@@ -44,6 +46,7 @@
         return pic;
     }
 
+    @Test
     public void testPictureRespectsClip() throws Exception {
         createTest()
             .addCanvasClient(
@@ -58,6 +61,7 @@
             ).runWithVerifier(new ColorVerifier(Color.WHITE));
     }
 
+    @Test
     public void testPictureRespectsTranslate() throws Exception {
         createTest()
             .addCanvasClient(
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShaderTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShaderTests.java
index 6500681..16a38e8 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShaderTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShaderTests.java
@@ -25,15 +25,17 @@
 import android.graphics.PorterDuff;
 import android.graphics.RadialGradient;
 import android.graphics.Shader;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
 import android.uirendering.cts.bitmapverifiers.ColorVerifier;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
 import android.uirendering.cts.testinfrastructure.CanvasClient;
 import android.uirendering.cts.R;
+import org.junit.Test;
 
+@MediumTest
 public class ShaderTests extends ActivityTestBase {
-    @SmallTest
+    @Test
     public void testSinglePixelBitmapShader() {
         createTest()
                 .addCanvasClient(new CanvasClient() {
@@ -52,7 +54,7 @@
                 .runWithVerifier(new ColorVerifier(Color.BLUE));
     }
 
-    @SmallTest
+    @Test
     public void testSinglePixelComposeShader() {
         createTest()
                 .addCanvasClient(new CanvasClient() {
@@ -83,7 +85,7 @@
                 .runWithVerifier(new ColorVerifier(Color.BLUE));
     }
 
-    @SmallTest
+    @Test
     public void testComplexShaderUsage() {
         /*
          * This test not only builds a very complex drawing operation, but also tests an
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShadowTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShadowTests.java
index 26c2402..6b9fb79 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShadowTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShadowTests.java
@@ -17,23 +17,40 @@
 
 import android.graphics.Color;
 import android.graphics.Point;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
 
 import android.uirendering.cts.R;
 
-import android.test.suitebuilder.annotation.SmallTest;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
+import android.uirendering.cts.util.CompareUtils;
+import org.junit.Test;
 
+@MediumTest
 public class ShadowTests extends ActivityTestBase {
-    @SmallTest
+
+    private class GrayScaleVerifier extends SamplePointVerifier {
+        public GrayScaleVerifier(Point[] testPoints, int[] expectedColors, int tolerance) {
+            super(testPoints, expectedColors, tolerance) ;
+        }
+
+        @Override
+        protected boolean verifyPixel(int color, int expectedColor) {
+            return super.verifyPixel(color, expectedColor)
+                    && CompareUtils.verifyPixelGrayScale(color, 1);
+        }
+    }
+
+    @Test
     public void testShadowLayout() {
         int shadowColorValue = 0xDB;
         // Android TV theme overrides shadow opacity to be darker.
         if (getActivity().getOnTv()) {
             shadowColorValue = 0xBB;
         }
-        // Use a higher threshold (36) than default value (20);
-        SamplePointVerifier verifier = new SamplePointVerifier(
+
+        // Use a higher threshold than default value (20), since we also double check gray scale;
+        GrayScaleVerifier verifier = new GrayScaleVerifier(
                 new Point[] {
                         // view area
                         new Point(25, 64),
@@ -48,7 +65,8 @@
                         Color.rgb(shadowColorValue, shadowColorValue, shadowColorValue),
                         Color.rgb(shadowColorValue, shadowColorValue, shadowColorValue),
                 },
-                36);
+                48);
+
         createTest()
                 .addLayout(R.layout.simple_shadow_layout, null, true/* HW only */)
                 .runWithVerifier(verifier);
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SweepTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SweepTests.java
index 71b4f3f..f5f59b3 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SweepTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SweepTests.java
@@ -20,21 +20,16 @@
 import android.graphics.Color;
 import android.graphics.LinearGradient;
 import android.graphics.Paint;
-import android.graphics.Point;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
-import android.graphics.RectF;
 import android.graphics.Shader;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.uirendering.cts.bitmapcomparers.BitmapComparer;
 import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
-import android.uirendering.cts.bitmapverifiers.BitmapVerifier;
-import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
 import android.uirendering.cts.testinfrastructure.CanvasClient;
 import android.uirendering.cts.testinfrastructure.DisplayModifier;
 import android.uirendering.cts.testinfrastructure.ResourceModifier;
+import org.junit.Test;
 
 import java.util.LinkedHashMap;
 import java.util.Map;
@@ -42,222 +37,8 @@
 /**
  * Test cases of all combination of resource modifications.
  */
+@MediumTest
 public class SweepTests extends ActivityTestBase {
-    private static final String TAG = "SweepTests";
-
-    public static final int BG_COLOR = 0xFFFFFFFF;
-    public static final int DST_COLOR = 0xFFFFCC44;
-    public static final int SRC_COLOR = 0xFF66AAFF;
-    public static final int MULTIPLY_COLOR = 0xFF668844;
-    public static final int SCREEN_COLOR = 0xFFFFEEFF;
-
-    // These points are in pairs, the first being the lower left corner, the second is only in the
-    // Destination bitmap, the third is the intersection of the two bitmaps, and the fourth is in
-    // the Source bitmap.
-    private final static Point[] XFERMODE_TEST_POINTS = new Point[] {
-            new Point(1, 80), new Point(25, 25), new Point(35, 35), new Point(70, 70)
-    };
-
-    /**
-     * There are 4 locations we care about in any filter testing.
-     *
-     * 1) Both empty
-     * 2) Only src, dst empty
-     * 3) Both src + dst
-     * 4) Only dst, src empty
-     */
-    private final Map<PorterDuff.Mode, int[]> XFERMODE_COLOR_MAP = new LinkedHashMap<PorterDuff.Mode, int[]>() {
-        {
-            put(PorterDuff.Mode.SRC, new int[] {
-                    BG_COLOR, BG_COLOR, SRC_COLOR, SRC_COLOR
-            });
-
-            put(PorterDuff.Mode.DST, new int[] {
-                    BG_COLOR, DST_COLOR, DST_COLOR, BG_COLOR
-            });
-
-            put(PorterDuff.Mode.SRC_OVER, new int[] {
-                    BG_COLOR, DST_COLOR, SRC_COLOR, SRC_COLOR
-            });
-
-            put(PorterDuff.Mode.DST_OVER, new int[] {
-                    BG_COLOR, DST_COLOR, DST_COLOR, SRC_COLOR
-            });
-
-            put(PorterDuff.Mode.SRC_IN, new int[] {
-                    BG_COLOR, BG_COLOR, SRC_COLOR, BG_COLOR
-            });
-
-            put(PorterDuff.Mode.DST_IN, new int[] {
-                    BG_COLOR, BG_COLOR, DST_COLOR, BG_COLOR
-            });
-
-            put(PorterDuff.Mode.SRC_OUT, new int[] {
-                    BG_COLOR, BG_COLOR, BG_COLOR, SRC_COLOR
-            });
-
-            put(PorterDuff.Mode.DST_OUT, new int[] {
-                    BG_COLOR, DST_COLOR, BG_COLOR, BG_COLOR
-            });
-
-            put(PorterDuff.Mode.SRC_ATOP, new int[] {
-                    BG_COLOR, DST_COLOR, SRC_COLOR, BG_COLOR
-            });
-
-            put(PorterDuff.Mode.DST_ATOP, new int[] {
-                    BG_COLOR, BG_COLOR, DST_COLOR, SRC_COLOR
-            });
-
-            put(PorterDuff.Mode.XOR, new int[] {
-                    BG_COLOR, DST_COLOR, BG_COLOR, SRC_COLOR
-            });
-
-            put(PorterDuff.Mode.MULTIPLY, new int[] {
-                    BG_COLOR, BG_COLOR, MULTIPLY_COLOR, BG_COLOR
-            });
-
-            put(PorterDuff.Mode.SCREEN, new int[] {
-                    BG_COLOR, DST_COLOR, SCREEN_COLOR, SRC_COLOR
-            });
-        }
-    };
-
-    private final static DisplayModifier XFERMODE_MODIFIER = new DisplayModifier() {
-        private final RectF mSrcRect = new RectF(30, 30, 80, 80);
-        private final RectF mDstRect = new RectF(10, 10, 60, 60);
-        private final Bitmap mSrcBitmap = createSrc();
-        private final Bitmap mDstBitmap = createDst();
-
-        @Override
-        public void modifyDrawing(Paint paint, Canvas canvas) {
-            int sc = canvas.saveLayer(0, 0, TEST_WIDTH, TEST_HEIGHT, null);
-
-            canvas.drawBitmap(mDstBitmap, 0, 0, null);
-            canvas.drawBitmap(mSrcBitmap, 0, 0, paint);
-
-            canvas.restoreToCount(sc);
-        }
-
-        private Bitmap createSrc() {
-            Bitmap srcB = Bitmap.createBitmap(TEST_WIDTH, TEST_HEIGHT, Bitmap.Config.ARGB_8888);
-            Canvas srcCanvas = new Canvas(srcB);
-            Paint srcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
-            srcPaint.setColor(SRC_COLOR);
-            srcCanvas.drawRect(mSrcRect, srcPaint);
-            return srcB;
-        }
-
-        private Bitmap createDst() {
-            Bitmap dstB = Bitmap.createBitmap(TEST_WIDTH, TEST_HEIGHT, Bitmap.Config.ARGB_8888);
-            Canvas dstCanvas = new Canvas(dstB);
-            Paint dstPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
-            dstPaint.setColor(DST_COLOR);
-            dstCanvas.drawOval(mDstRect, dstPaint);
-            return dstB;
-        }
-    };
-
-    // We care about one point in each of the four rectangles of different alpha values, as well as
-    // the area outside the rectangles
-    private final static Point[] COLOR_FILTER_ALPHA_POINTS = new Point[] {
-            new Point(9, 45),
-            new Point(27, 45),
-            new Point(45, 45),
-            new Point(63, 45),
-            new Point(81, 45)
-    };
-
-    public static final int FILTER_COLOR = 0xFFBB0000;
-    private final Map<PorterDuff.Mode, int[]> COLOR_FILTER_ALPHA_MAP
-            = new LinkedHashMap<PorterDuff.Mode, int[]>() {
-        {
-            put(PorterDuff.Mode.SRC, new int[] {
-                    FILTER_COLOR, FILTER_COLOR, FILTER_COLOR, FILTER_COLOR, FILTER_COLOR
-            });
-
-            put(PorterDuff.Mode.DST, new int[] {
-                    0xFFE6E6E6, 0xFFCCCCCC, 0xFFB3B3B3, 0xFF999999, 0xFFFFFFFF
-            });
-
-            put(PorterDuff.Mode.SRC_OVER, new int[] {
-                    0xFFBB0000, 0xFFBB0000, 0xFFBB0000, 0xFFBB0000, 0xFFBB0000
-            });
-
-            put(PorterDuff.Mode.DST_OVER, new int[] {
-                    0xFFAF1A1A, 0xFFA33333, 0xFF984D4D, 0xFF8B6666, 0xFFBB0000
-            });
-
-            put(PorterDuff.Mode.SRC_IN, new int[] {
-                    0xFFF1CCCC, 0xFFE49999, 0xFFD66666, 0xFFC83333, 0xFFFFFFFF
-            });
-
-            put(PorterDuff.Mode.DST_IN, new int[] {
-                    0xFFE6E6E6, 0xFFCCCCCC, 0xFFB3B3B3, 0xFF999999, 0xFFFFFFFF
-            });
-
-            put(PorterDuff.Mode.SRC_OUT, new int[] {
-                    0xFFC83333, 0xFFD66666, 0xFFE49999, 0xFFF1CCCC, 0xFFBB0000
-            });
-
-            put(PorterDuff.Mode.DST_OUT, new int[] {
-                    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
-            });
-
-            put(PorterDuff.Mode.SRC_ATOP, new int[] {
-                    0xFFF1CCCC, 0xFFE49999, 0xFFD66666, 0xFFC93333, 0xFFFFFFFF
-            });
-
-            put(PorterDuff.Mode.DST_ATOP, new int[] {
-                    0xFFB01A1A, 0xFFA33333, 0xFF984D4D, 0xFF8B6666, 0xFFBB0000
-            });
-
-            put(PorterDuff.Mode.XOR, new int[] {
-                    0xFFC93333, 0xFFD66666, 0xFFE49999, 0xFFF1CCCC, 0xFFBB0000
-            });
-
-            put(PorterDuff.Mode.MULTIPLY, new int[] {
-                    0xFFDFCCCC, 0xFFBE9999, 0xFF9E6666, 0xFF7E3333, 0xFFFFFFFF
-            });
-
-            put(PorterDuff.Mode.SCREEN, new int[] {
-                    0xFFC21A1A, 0xFFC93333, 0xFFD04D4D, 0xFFD66666, 0xFFBB0000
-            });
-        }
-    };
-
-    /**
-     * Draws 5 blocks of different color/opacity to be blended against
-     */
-    private final static DisplayModifier COLOR_FILTER_ALPHA_MODIFIER = new DisplayModifier() {
-        private final int[] BLOCK_COLORS = new int[] {
-                0x33808080,
-                0x66808080,
-                0x99808080,
-                0xCC808080,
-                0x00000000
-        };
-
-        private final Bitmap mBitmap = createQuadRectBitmap();
-
-        public void modifyDrawing(Paint paint, Canvas canvas) {
-            canvas.drawBitmap(mBitmap, 0, 0, paint);
-        }
-
-        private Bitmap createQuadRectBitmap() {
-            Bitmap bitmap = Bitmap.createBitmap(TEST_WIDTH, TEST_HEIGHT, Bitmap.Config.ARGB_8888);
-            Canvas canvas = new Canvas(bitmap);
-            Paint paint = new Paint();
-            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
-            final int blockCount = BLOCK_COLORS.length;
-            final int blockWidth = TEST_WIDTH / blockCount;
-            for (int i = 0 ; i < blockCount; i++) {
-                paint.setColor(BLOCK_COLORS[i]);
-                canvas.drawRect(i * blockWidth, 0, (i + 1) * blockWidth, TEST_HEIGHT, paint);
-            }
-            return bitmap;
-        }
-    };
-
     private final static DisplayModifier COLOR_FILTER_GRADIENT_MODIFIER = new DisplayModifier() {
         private final Rect mBounds = new Rect(30, 30, 150, 150);
         private final int[] mColors = new int[] {
@@ -299,54 +80,25 @@
             new MSSIMComparer(HIGH_THRESHOLD)
     };
 
-    @SmallTest
+    @Test
     public void testBasicDraws() {
-        sweepModifiersForMask(DisplayModifier.Accessor.SHAPES_MASK, null, DEFAULT_MSSIM_COMPARER,
-                null);
+        sweepModifiersForMask(DisplayModifier.Accessor.SHAPES_MASK, null, DEFAULT_MSSIM_COMPARER);
     }
 
-    @SmallTest
+    @Test
     public void testBasicShaders() {
         sweepModifiersForMask(DisplayModifier.Accessor.SHADER_MASK, mCircleDrawModifier,
-                DEFAULT_MSSIM_COMPARER, null);
+                DEFAULT_MSSIM_COMPARER);
     }
 
-    @SmallTest
+    @Test
     public void testColorFilterUsingGradient() {
         sweepModifiersForMask(DisplayModifier.Accessor.COLOR_FILTER_MASK,
-                COLOR_FILTER_GRADIENT_MODIFIER, DEFAULT_MSSIM_COMPARER, null);
-    }
-
-    @SmallTest
-    public void testColorFiltersAlphas() {
-        BitmapVerifier[] bitmapVerifiers =
-                new BitmapVerifier[DisplayModifier.PORTERDUFF_MODES.length];
-        int index = 0;
-        for (PorterDuff.Mode mode : DisplayModifier.PORTERDUFF_MODES) {
-            bitmapVerifiers[index] = new SamplePointVerifier(COLOR_FILTER_ALPHA_POINTS,
-                    COLOR_FILTER_ALPHA_MAP.get(mode));
-            index++;
-        }
-        sweepModifiersForMask(DisplayModifier.Accessor.COLOR_FILTER_MASK,
-                COLOR_FILTER_ALPHA_MODIFIER, null, bitmapVerifiers);
-    }
-
-    @SmallTest
-    public void testXfermodes() {
-        BitmapVerifier[] bitmapVerifiers =
-                new BitmapVerifier[DisplayModifier.PORTERDUFF_MODES.length];
-        int index = 0;
-        for (PorterDuff.Mode mode : DisplayModifier.PORTERDUFF_MODES) {
-            bitmapVerifiers[index] = new SamplePointVerifier(XFERMODE_TEST_POINTS,
-                    XFERMODE_COLOR_MAP.get(mode));
-            index++;
-        }
-        sweepModifiersForMask(DisplayModifier.Accessor.XFERMODE_MASK, XFERMODE_MODIFIER,
-                null, bitmapVerifiers);
+                COLOR_FILTER_GRADIENT_MODIFIER, DEFAULT_MSSIM_COMPARER);
     }
 
     protected void sweepModifiersForMask(int mask, final DisplayModifier drawOp,
-            BitmapComparer[] bitmapComparers, BitmapVerifier[] bitmapVerifiers) {
+                BitmapComparer[] bitmapComparers) {
         if ((mask & DisplayModifier.Accessor.ALL_OPTIONS_MASK) == 0) {
             throw new IllegalArgumentException("Attempt to test with a mask that is invalid");
         }
@@ -371,13 +123,8 @@
         // Create the test cases with each combination
         do {
             canvasClient.setDebugString(modifierAccessor.getDebugString());
-            if (bitmapComparers != null) {
-                int arrIndex = Math.min(index, bitmapComparers.length - 1);
-                createTest().addCanvasClient(canvasClient).runWithComparer(bitmapComparers[arrIndex]);
-            } else {
-                int arrIndex = Math.min(index, bitmapVerifiers.length - 1);
-                createTest().addCanvasClient(canvasClient).runWithVerifier(bitmapVerifiers[arrIndex]);
-            }
+            int arrIndex = Math.min(index, bitmapComparers.length - 1);
+            createTest().addCanvasClient(canvasClient).runWithComparer(bitmapComparers[arrIndex]);
             index++;
         } while (modifierAccessor.step());
     }
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewClippingTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewClippingTests.java
index 2db635f0..3b1df30 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewClippingTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewClippingTests.java
@@ -3,6 +3,7 @@
 import android.graphics.Color;
 import android.graphics.Outline;
 import android.graphics.Rect;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.uirendering.cts.bitmapverifiers.BitmapVerifier;
 import android.uirendering.cts.bitmapverifiers.RectVerifier;
 import android.uirendering.cts.testclasses.view.UnclippedBlueView;
@@ -12,6 +13,7 @@
 import android.view.ViewGroup;
 import android.view.ViewOutlineProvider;
 import android.uirendering.cts.R;
+import org.junit.Test;
 
 /**
  * This tests view clipping by modifying properties of blue_padded_layout, and validating
@@ -19,6 +21,7 @@
  *
  * Since the layout is blue on a white background, this is always done with a RectVerifier.
  */
+@MediumTest
 public class ViewClippingTests extends ActivityTestBase {
     final Rect FULL_RECT = new Rect(0, 0, 90, 90);
     final Rect BOUNDS_RECT = new Rect(0, 0, 80, 80);
@@ -66,30 +69,35 @@
         return new RectVerifier(Color.WHITE, Color.BLUE, blueBoundsRect, 75);
     }
 
+    @Test
     public void testSimpleUnclipped() {
         createTest()
                 .addLayout(R.layout.blue_padded_layout, null)
                 .runWithVerifier(makeClipVerifier(FULL_RECT));
     }
 
+    @Test
     public void testSimpleBoundsClip() {
         createTest()
                 .addLayout(R.layout.blue_padded_layout, BOUNDS_CLIP_INIT)
                 .runWithVerifier(makeClipVerifier(BOUNDS_RECT));
     }
 
+    @Test
     public void testSimpleClipBoundsClip() {
         createTest()
                 .addLayout(R.layout.blue_padded_layout, CLIP_BOUNDS_CLIP_INIT)
                 .runWithVerifier(makeClipVerifier(CLIP_BOUNDS_RECT));
     }
 
+    @Test
     public void testSimplePaddingClip() {
         createTest()
                 .addLayout(R.layout.blue_padded_layout, PADDING_CLIP_INIT)
                 .runWithVerifier(makeClipVerifier(PADDED_RECT));
     }
 
+    @Test
     public void testSimpleOutlineClip() {
         // NOTE: Only HW is supported
         createTest()
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/XfermodeTest.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/XfermodeTest.java
new file mode 100644
index 0000000..c6e9881
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/XfermodeTest.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.uirendering.cts.testclasses;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.RectF;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
+import android.uirendering.cts.testinfrastructure.ActivityTestBase;
+import android.uirendering.cts.testinfrastructure.CanvasClient;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@MediumTest
+@RunWith(Parameterized.class)
+public class XfermodeTest extends ActivityTestBase {
+    /**
+     * There are 4 locations we care about in testing each filter:
+     *
+     * 1) Both empty
+     * 2) Only src, dst empty
+     * 3) Both src + dst
+     * 4) Only dst, src empty
+     */
+    private final static Point[] TEST_POINTS = new Point[] {
+            new Point(1, 80),
+            new Point(25, 25),
+            new Point(35, 35),
+            new Point(70, 70)
+    };
+
+    public static class Config {
+        final boolean hardwareAccelerated;
+        final PorterDuff.Mode mode;
+        final int[] expectedColors;
+
+        Config(boolean hardwareAccelerated, Object[] modeAndExpectedColors) {
+            this.hardwareAccelerated = hardwareAccelerated;
+            mode = (PorterDuff.Mode) modeAndExpectedColors[0];
+            expectedColors = (int[]) modeAndExpectedColors[1];
+        }
+
+        @Override
+        public String toString() {
+            return mode.name() + ", hardwareAccelerated=" + hardwareAccelerated;
+        }
+    };
+
+    public static List<XfermodeTest.Config> configs(Object[][] modesAndExpectedColors) {
+        List<XfermodeTest.Config> configs = new ArrayList<>();
+        for (boolean hardwareAccelerated : new boolean[] {false, true}) {
+            for (Object[] modeAndExpectedColors : modesAndExpectedColors) {
+                configs.add(new XfermodeTest.Config(hardwareAccelerated, modeAndExpectedColors));
+            }
+        }
+        return configs;
+    }
+
+    private static final int BG_COLOR = 0xFFFFFFFF;
+    private static final int DST_COLOR = 0xFFFFCC44;
+    private static final int SRC_COLOR = 0xFF66AAFF;
+    private static final int MULTIPLY_COLOR = 0xFF668844;
+    private static final int SCREEN_COLOR = 0xFFFFEEFF;
+
+    private static Object[][] MODES_AND_EXPECTED_COLORS = new Object[][] {
+        { PorterDuff.Mode.SRC, new int[] {
+                BG_COLOR, BG_COLOR, SRC_COLOR, SRC_COLOR } },
+
+        { PorterDuff.Mode.DST, new int[] {
+                BG_COLOR, DST_COLOR, DST_COLOR, BG_COLOR } },
+
+        { PorterDuff.Mode.SRC_OVER, new int[] {
+                BG_COLOR, DST_COLOR, SRC_COLOR, SRC_COLOR } },
+
+        { PorterDuff.Mode.DST_OVER, new int[] {
+                BG_COLOR, DST_COLOR, DST_COLOR, SRC_COLOR } },
+
+        { PorterDuff.Mode.SRC_IN, new int[] {
+                BG_COLOR, BG_COLOR, SRC_COLOR, BG_COLOR } },
+
+        { PorterDuff.Mode.DST_IN, new int[] {
+                BG_COLOR, BG_COLOR, DST_COLOR, BG_COLOR } },
+
+        { PorterDuff.Mode.SRC_OUT, new int[] {
+                BG_COLOR, BG_COLOR, BG_COLOR, SRC_COLOR } },
+
+        { PorterDuff.Mode.DST_OUT, new int[] {
+                BG_COLOR, DST_COLOR, BG_COLOR, BG_COLOR } },
+
+        { PorterDuff.Mode.SRC_ATOP, new int[] {
+                BG_COLOR, DST_COLOR, SRC_COLOR, BG_COLOR } },
+
+        { PorterDuff.Mode.DST_ATOP, new int[] {
+                BG_COLOR, BG_COLOR, DST_COLOR, SRC_COLOR } },
+
+        { PorterDuff.Mode.XOR, new int[] {
+                BG_COLOR, DST_COLOR, BG_COLOR, SRC_COLOR } },
+
+        { PorterDuff.Mode.MULTIPLY, new int[] {
+                BG_COLOR, BG_COLOR, MULTIPLY_COLOR, BG_COLOR } },
+
+        { PorterDuff.Mode.SCREEN, new int[] {
+                BG_COLOR, DST_COLOR, SCREEN_COLOR, SRC_COLOR } },
+    };
+
+    @Parameterized.Parameters(name = "{0}")
+    public static List<Config> configs() {
+        return configs(MODES_AND_EXPECTED_COLORS);
+    }
+
+    private final Config mConfig;
+
+    public XfermodeTest(Config config) {
+        mConfig = config;
+    }
+
+    private CanvasClient mCanvasClient = new CanvasClient() {
+        final Paint mPaint = new Paint();
+        private final RectF mSrcRect = new RectF(30, 30, 80, 80);
+        private final RectF mDstRect = new RectF(10, 10, 60, 60);
+        private final Bitmap mSrcBitmap = createSrc();
+        private final Bitmap mDstBitmap = createDst();
+
+        @Override
+        public void draw(Canvas canvas, int width, int height) {
+            int sc = canvas.saveLayer(0, 0, TEST_WIDTH, TEST_HEIGHT, null);
+
+            canvas.drawBitmap(mDstBitmap, 0, 0, null);
+            mPaint.setXfermode(new PorterDuffXfermode(mConfig.mode));
+            canvas.drawBitmap(mSrcBitmap, 0, 0, mPaint);
+
+            canvas.restoreToCount(sc);
+        }
+
+        private Bitmap createSrc() {
+            Bitmap srcB = Bitmap.createBitmap(TEST_WIDTH, TEST_HEIGHT, Bitmap.Config.ARGB_8888);
+            Canvas srcCanvas = new Canvas(srcB);
+            Paint srcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+            srcPaint.setColor(SRC_COLOR);
+            srcCanvas.drawRect(mSrcRect, srcPaint);
+            return srcB;
+        }
+
+        private Bitmap createDst() {
+            Bitmap dstB = Bitmap.createBitmap(TEST_WIDTH, TEST_HEIGHT, Bitmap.Config.ARGB_8888);
+            Canvas dstCanvas = new Canvas(dstB);
+            Paint dstPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+            dstPaint.setColor(DST_COLOR);
+            dstCanvas.drawOval(mDstRect, dstPaint);
+            return dstB;
+        }
+    };
+
+    @Test
+    public void test() {
+        createTest()
+                .addCanvasClient(mCanvasClient, mConfig.hardwareAccelerated)
+                .runWithVerifier(new SamplePointVerifier(TEST_POINTS, mConfig.expectedColors));
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
index 69cb688..f82bb40 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
@@ -16,11 +16,13 @@
 package android.uirendering.cts.testinfrastructure;
 
 import android.annotation.Nullable;
+import android.app.Activity;
+import android.app.Instrumentation;
 import android.graphics.Bitmap;
 import android.graphics.Point;
 import android.renderscript.Allocation;
 import android.renderscript.RenderScript;
-import android.test.ActivityInstrumentationTestCase2;
+import android.support.test.rule.ActivityTestRule;
 import android.uirendering.cts.bitmapcomparers.BitmapComparer;
 import android.uirendering.cts.bitmapverifiers.BitmapVerifier;
 import android.uirendering.cts.differencevisualizers.DifferenceVisualizer;
@@ -29,18 +31,23 @@
 import android.util.Log;
 
 import android.support.test.InstrumentationRegistry;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.rules.TestName;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
+import static org.junit.Assert.assertTrue;
+
 /**
  * This class contains the basis for the graphics hardware test classes. Contained within this class
  * are several methods that help with the execution of tests, and should be extended to gain the
  * functionality built in.
  */
-public abstract class ActivityTestBase extends
-        ActivityInstrumentationTestCase2<DrawActivity> {
+public abstract class ActivityTestBase {
     public static final String TAG = "ActivityTestBase";
     public static final boolean DEBUG = false;
     public static final boolean USE_RS = false;
@@ -57,12 +64,18 @@
     private RenderScript mRenderScript;
     private TestCaseBuilder mTestCaseBuilder;
 
+    @Rule
+    public ActivityTestRule<DrawActivity> mActivityRule = new ActivityTestRule<>(
+            DrawActivity.class);
+
+    @Rule
+    public TestName name = new TestName();
+
     /**
      * The default constructor creates the package name and sets the DrawActivity as the class that
      * we would use.
      */
     public ActivityTestBase() {
-        super(DrawActivity.class);
         mDifferenceVisualizer = new PassFailVisualizer();
 
         // Create a location for the files to be held, if it doesn't exist already
@@ -74,26 +87,27 @@
         }
     }
 
-    /**
-     * This method is called before each test case and should be called from the test class that
-     * extends this class.
-     */
-    @Override
+    protected DrawActivity getActivity() {
+        return mActivityRule.getActivity();
+    }
+
+    protected String getName() {
+        return name.getMethodName();
+    }
+
+    protected Instrumentation getInstrumentation() {
+        return InstrumentationRegistry.getInstrumentation();
+    }
+
+    @Before
     public void setUp() {
-        // As the way to access Instrumentation is changed in the new runner, we need to inject it
-        // manually into ActivityInstrumentationTestCase2. ActivityInstrumentationTestCase2 will
-        // be marked as deprecated and replaced with ActivityTestRule.
-        injectInstrumentation(InstrumentationRegistry.getInstrumentation());
         mDifferenceVisualizer = new PassFailVisualizer();
         if (USE_RS) {
             mRenderScript = RenderScript.create(getActivity().getApplicationContext());
         }
     }
 
-    /**
-     * This method will kill the activity so that it can be reset depending on the test.
-     */
-    @Override
+    @After
     public void tearDown() {
         if (mTestCaseBuilder != null) {
             List<TestCase> testCases = mTestCaseBuilder.getTestCases();
@@ -102,7 +116,6 @@
                 throw new IllegalStateException("Must have at least one test case");
             }
 
-
             for (TestCase testCase : testCases) {
                 if (!testCase.wasTestRan) {
                     Log.w(TAG, getName() + " not all of the tests ran");
@@ -111,16 +124,6 @@
             }
             mTestCaseBuilder = null;
         }
-
-        Runnable finishRunnable = new Runnable() {
-
-            @Override
-            public void run() {
-                getActivity().finish();
-            }
-        };
-
-        getActivity().runOnUiThread(finishRunnable);
     }
 
     public Bitmap takeScreenshot(Point testOffset) {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/util/CompareUtils.java b/tests/tests/uirendering/src/android/uirendering/cts/util/CompareUtils.java
index 4f246a4..c80a778 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/util/CompareUtils.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/util/CompareUtils.java
@@ -12,4 +12,17 @@
                 + Math.abs(Color.blue(color) - Color.blue(expectedColor));
         return diff <= threshold;
     }
+
+    /**
+     * @param threshold Per channel differences for R / G / B channel against the average of these 3
+     *                  channels. Should be less than 2 normally.
+     * @return True if the color is close enough to be a gray scale color.
+     */
+    public static boolean verifyPixelGrayScale(int color, int threshold) {
+        int average =  Color.red(color) + Color.green(color) + Color.blue(color);
+        average /= 3;
+        return Math.abs(Color.red(color) - average) <= threshold
+                && Math.abs(Color.green(color) - average) <= threshold
+                && Math.abs(Color.blue(color) - average) <= threshold;
+    }
 }
diff --git a/tests/tests/util/src/android/util/cts/EventLogTest.java b/tests/tests/util/src/android/util/cts/EventLogTest.java
index 2d856c4..2065e32 100644
--- a/tests/tests/util/src/android/util/cts/EventLogTest.java
+++ b/tests/tests/util/src/android/util/cts/EventLogTest.java
@@ -77,7 +77,7 @@
         assertEquals(7, events.size());
 
         // subtract: log header, type byte, final newline
-        final int max = 4096 - 20 - 4 - 1;
+        final int max = 4096 - 20 - 4 - 1 - 8;
 
         // subtract: string header (type + length)
         String val0 = (String) events.get(0).getData();
diff --git a/tests/tests/util/src/android/util/cts/LocaleListTest.java b/tests/tests/util/src/android/util/cts/LocaleListTest.java
index 456b26e..e64d955 100644
--- a/tests/tests/util/src/android/util/cts/LocaleListTest.java
+++ b/tests/tests/util/src/android/util/cts/LocaleListTest.java
@@ -312,6 +312,14 @@
         assertEquals(original, cloneViaParcel(original));
     }
 
+    public void testDescribeContents_doesNotThrowException() {
+        // Just check calling describeContents() should not cause any exceptions.
+        LocaleList.forLanguageTags("en").describeContents();
+        LocaleList.forLanguageTags("").describeContents();
+        LocaleList.forLanguageTags(null).describeContents();
+        LocaleList.getEmptyLocaleList().describeContents();
+    }
+
     private static LocaleList cloneViaParcel(final LocaleList original) {
         Parcel parcel = null;
         try {
diff --git a/tests/tests/view/Android.mk b/tests/tests/view/Android.mk
index eb6cee7..57dc0ce 100644
--- a/tests/tests/view/Android.mk
+++ b/tests/tests/view/Android.mk
@@ -28,7 +28,8 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner mockito-target
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    ctsdeviceutil ctstestrunner mockito-target platform-test-annotations
 
 LOCAL_JNI_SHARED_LIBRARIES := libctsview_jni libnativehelper_compat_libc++
 
diff --git a/tests/tests/view/AndroidTest.xml b/tests/tests/view/AndroidTest.xml
index def111d..c818923 100644
--- a/tests/tests/view/AndroidTest.xml
+++ b/tests/tests/view/AndroidTest.xml
@@ -20,5 +20,6 @@
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.view.cts" />
+        <option name="runtime-hint" value="6m47s" />
     </test>
 </configuration>
diff --git a/tests/tests/view/res/layout/view_layout.xml b/tests/tests/view/res/layout/view_layout.xml
index 9769aa4..c576350 100644
--- a/tests/tests/view/res/layout/view_layout.xml
+++ b/tests/tests/view/res/layout/view_layout.xml
@@ -123,4 +123,14 @@
       </LinearLayout>
     </LinearLayout>
 
+    <FrameLayout
+        android:id="@+id/aggregate_visibility_parent"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content">
+        <android.view.cts.MockView
+            android:id="@+id/mock_view_aggregate_visibility"
+            android:layout_width="10px"
+            android:layout_height="10px" />
+    </FrameLayout>
+
 </LinearLayout>
diff --git a/tests/tests/view/src/android/view/cts/ContentPaneCtsActivity.java b/tests/tests/view/src/android/view/cts/ContentPaneCtsActivity.java
index 5d7b354..f6315c8 100644
--- a/tests/tests/view/src/android/view/cts/ContentPaneCtsActivity.java
+++ b/tests/tests/view/src/android/view/cts/ContentPaneCtsActivity.java
@@ -19,8 +19,7 @@
 import android.app.Activity;
 import android.os.Bundle;
 import android.view.Menu;
-import android.view.MenuItem;
-import android.view.cts.R;
+import android.view.Window;
 
 /**
  * A simple activity to test "Focus Handling"
@@ -30,6 +29,7 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setTheme(android.R.style.Theme_Material_Light);
+        getWindow().requestFeature(Window.FEATURE_OPTIONS_PANEL);
         setContentView(R.layout.viewtreeobserver_layout);
     }
 
diff --git a/tests/tests/view/src/android/view/cts/ContentPaneFocusTest.java b/tests/tests/view/src/android/view/cts/ContentPaneFocusTest.java
index c99679b..eaaea74 100644
--- a/tests/tests/view/src/android/view/cts/ContentPaneFocusTest.java
+++ b/tests/tests/view/src/android/view/cts/ContentPaneFocusTest.java
@@ -16,13 +16,16 @@
 
 package android.view.cts;
 
+import android.app.ActionBar;
 import android.app.Activity;
+import android.content.pm.PackageManager;
 import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.View;
-import android.view.cts.R;
+import android.view.ViewGroup;
+import android.view.ViewParent;
 
 public class ContentPaneFocusTest
         extends ActivityInstrumentationTestCase2<ContentPaneCtsActivity> {
@@ -45,12 +48,34 @@
         sendControlChar('<');
         getInstrumentation().waitForIdleSync();
 
+        ActionBar action = activity.getActionBar();
+        if (action == null || !action.isShowing()) {
+            // No action bar, so we only needed to make sure that the shortcut didn't cause
+            // the framework to crash.
+            return;
+        }
+
+        final View content = activity.findViewById(android.R.id.content);
+        assertNotNull(content);
+        final ViewParent viewParent = content.getParent();
+        assertNotNull(viewParent);
+        assertTrue(viewParent instanceof ViewGroup);
+        ViewGroup parent = (ViewGroup) viewParent;
+        View actionBarView = null;
+        for (int i = 0; i < parent.getChildCount(); i++) {
+            View child = parent.getChildAt(i);
+            if ("android:action_bar".equals(child.getTransitionName())) {
+                actionBarView = child;
+                break;
+            }
+        }
+        assertNotNull(actionBarView);
+        final View actionBar = actionBarView;
         // Should jump to the action bar after control-<
         runTestOnUiThread(new Runnable() {
             @Override
             public void run() {
                 assertFalse(v1.hasFocus());
-                View actionBar = activity.findViewById(com.android.internal.R.id.action_bar);
                 assertTrue(actionBar.hasFocus());
             }
         });
@@ -67,25 +92,42 @@
         getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_UP);
         getInstrumentation().waitForIdleSync();
 
-        // Now it shouldn't go up to action bar -- it doesn't allow taking focus once left
-        runTestOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                assertTrue(v1.hasFocus());
-            }
-        });
+        boolean isTouchScreen = activity.getPackageManager().
+                hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN);
+        if (isTouchScreen) {
+            // Now it shouldn't go up to action bar -- it doesn't allow taking focus once left
+            // but only for touch screens.
+            runTestOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    assertTrue(v1.hasFocus());
+                }
+            });
+        }
     }
 
     private void sendControlChar(char key) throws Throwable {
         KeyEvent tempEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_A);
         KeyCharacterMap map = tempEvent.getKeyCharacterMap();
+        sendControlKey(KeyEvent.ACTION_DOWN);
         KeyEvent[] events = map.getEvents(new char[] {key});
+        final int controlOn = KeyEvent.META_CTRL_ON | KeyEvent.META_CTRL_LEFT_ON;
         for (int i = 0; i < events.length; i++) {
             long time = SystemClock.uptimeMillis();
             KeyEvent event = events[i];
             KeyEvent controlKey = new KeyEvent(time, time, event.getAction(), event.getKeyCode(),
-                    event.getRepeatCount(), event.getMetaState() | KeyEvent.META_CTRL_ON);
+                    event.getRepeatCount(), event.getMetaState() | controlOn);
             getInstrumentation().sendKeySync(controlKey);
+            Thread.sleep(2);
         }
+        sendControlKey(KeyEvent.ACTION_UP);
+    }
+
+    private void sendControlKey(int action) throws Throwable {
+        long time = SystemClock.uptimeMillis();
+        KeyEvent keyEvent = new KeyEvent(time, time, action, KeyEvent.KEYCODE_CTRL_LEFT, 0,
+                KeyEvent.META_CTRL_LEFT_ON | KeyEvent.META_CTRL_ON);
+        getInstrumentation().sendKeySync(keyEvent);
+        Thread.sleep(2);
     }
 }
diff --git a/tests/tests/view/src/android/view/cts/MockView.java b/tests/tests/view/src/android/view/cts/MockView.java
index 0a56369..3e140c2 100644
--- a/tests/tests/view/src/android/view/cts/MockView.java
+++ b/tests/tests/view/src/android/view/cts/MockView.java
@@ -70,10 +70,13 @@
     private boolean mCalledDispatchKeyEventPreIme = false;
     private boolean mCalledOnKeyPreIme = false;
     private boolean mCalledGetPointerIcon = false;
+    private boolean mCalledOnVisibilityAggregated = false;
 
     private int mOldWidth = -1;
     private int mOldHeight = -1;
 
+    private boolean mLastAggregatedVisibility;
+
     public MockView(Context context) {
         super(context);
     }
@@ -616,6 +619,21 @@
         return mCalledGetPointerIcon;
     }
 
+    @Override
+    public void onVisibilityAggregated(boolean isVisible) {
+        super.onVisibilityAggregated(isVisible);
+        mCalledOnVisibilityAggregated = true;
+        mLastAggregatedVisibility = isVisible;
+    }
+
+    public boolean hasCalledOnVisibilityAggregated() {
+        return mCalledOnVisibilityAggregated;
+    }
+
+    public boolean getLastAggregatedVisibility() {
+        return mLastAggregatedVisibility;
+    }
+
     public void reset() {
         mCalledOnCreateContextMenu = false;
 
@@ -655,8 +673,10 @@
         mCalledDispatchKeyEventPreIme = false;
         mCalledOnKeyPreIme = false;
         mCalledGetPointerIcon = false;
+        mCalledOnVisibilityAggregated = false;
 
         mOldWidth = -1;
         mOldHeight = -1;
+        mLastAggregatedVisibility = false;
     }
 }
diff --git a/tests/tests/view/src/android/view/cts/ViewGroupOverlayTest.java b/tests/tests/view/src/android/view/cts/ViewGroupOverlayTest.java
index c4cebb9..46f66ce 100644
--- a/tests/tests/view/src/android/view/cts/ViewGroupOverlayTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewGroupOverlayTest.java
@@ -23,6 +23,7 @@
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.SystemClock;
+import android.platform.test.annotations.Presubmit;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Pair;
@@ -57,6 +58,7 @@
         mContext = getInstrumentation().getTargetContext();
     }
 
+    @Presubmit
     public void testBasics() {
         DrawingUtils.assertAllPixelsOfColor("Default fill", mViewGroupWithOverlay,
                 Color.WHITE, null);
@@ -396,4 +398,4 @@
                 mViewGroupWithOverlay, Color.WHITE, colorRectangles);
 
     }
-}
\ No newline at end of file
+}
diff --git a/tests/tests/view/src/android/view/cts/ViewGroupTest.java b/tests/tests/view/src/android/view/cts/ViewGroupTest.java
index 10e743a..49979ca 100644
--- a/tests/tests/view/src/android/view/cts/ViewGroupTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewGroupTest.java
@@ -27,7 +27,6 @@
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.graphics.drawable.BitmapDrawable;
-import android.os.Build;
 import android.os.Parcelable;
 import android.os.SystemClock;
 import android.test.InstrumentationTestCase;
@@ -1011,18 +1010,6 @@
         assertEquals(2, rect.top);
         assertEquals(1, rect.left);
         assertEquals(1, rect.right);
-
-        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M || Build.VERSION.CODENAME.equals("N")) {
-            textView.setTranslationX(2);
-            textView.setTranslationY(1);
-
-            rect.setEmpty();
-            vg.offsetDescendantRectToMyCoords(textView, rect);
-            assertEquals(3, rect.bottom);
-            assertEquals(3, rect.top);
-            assertEquals(3, rect.left);
-            assertEquals(3, rect.right);
-        }
     }
 
     public void testOffsetRectIntoDescendantCoords() {
@@ -1046,18 +1033,6 @@
         assertEquals(4, rect.top);
         assertEquals(4, rect.left);
         assertEquals(6, rect.right);
-
-        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M || Build.VERSION.CODENAME.equals("N")) {
-            textView.setTranslationX(2);
-            textView.setTranslationY(1);
-
-            rect.set(5, 6, 7, 8);
-            vg.offsetRectIntoDescendantCoords(textView, rect);
-            assertEquals(5, rect.bottom);
-            assertEquals(3, rect.top);
-            assertEquals(2, rect.left);
-            assertEquals(4, rect.right);
-        }
     }
 
     public void testOnAnimationEnd() {
diff --git a/tests/tests/view/src/android/view/cts/ViewTest.java b/tests/tests/view/src/android/view/cts/ViewTest.java
index 1e23660..2082973 100644
--- a/tests/tests/view/src/android/view/cts/ViewTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewTest.java
@@ -3940,6 +3940,89 @@
         assertFalse(view2.hasPointerCapture());
     }
 
+    public void testVisibilityAggregated() throws Throwable {
+        final View grandparent = mActivity.findViewById(R.id.viewlayout_root);
+        final View parent = mActivity.findViewById(R.id.aggregate_visibility_parent);
+        final MockView mv = (MockView) mActivity.findViewById(R.id.mock_view_aggregate_visibility);
+
+        assertEquals(parent, mv.getParent());
+        assertEquals(grandparent, parent.getParent());
+
+        assertTrue(mv.hasCalledOnVisibilityAggregated());
+        assertTrue(mv.getLastAggregatedVisibility());
+
+        final Runnable reset = new Runnable() {
+            @Override
+            public void run() {
+                grandparent.setVisibility(View.VISIBLE);
+                parent.setVisibility(View.VISIBLE);
+                mv.setVisibility(View.VISIBLE);
+                mv.reset();
+            }
+        };
+
+        runTestOnUiThread(reset);
+
+        setVisibilityOnUiThread(parent, View.GONE);
+
+        assertTrue(mv.hasCalledOnVisibilityAggregated());
+        assertFalse(mv.getLastAggregatedVisibility());
+
+        runTestOnUiThread(reset);
+
+        setVisibilityOnUiThread(grandparent, View.GONE);
+
+        assertTrue(mv.hasCalledOnVisibilityAggregated());
+        assertFalse(mv.getLastAggregatedVisibility());
+
+        runTestOnUiThread(reset);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                grandparent.setVisibility(View.GONE);
+                parent.setVisibility(View.GONE);
+                mv.setVisibility(View.VISIBLE);
+
+                grandparent.setVisibility(View.VISIBLE);
+            }
+        });
+
+        assertTrue(mv.hasCalledOnVisibilityAggregated());
+        assertFalse(mv.getLastAggregatedVisibility());
+
+        runTestOnUiThread(reset);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                grandparent.setVisibility(View.GONE);
+                parent.setVisibility(View.INVISIBLE);
+
+                grandparent.setVisibility(View.VISIBLE);
+            }
+        });
+
+        assertTrue(mv.hasCalledOnVisibilityAggregated());
+        assertFalse(mv.getLastAggregatedVisibility());
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                parent.setVisibility(View.VISIBLE);
+            }
+        });
+
+        assertTrue(mv.getLastAggregatedVisibility());
+    }
+
+    private void setVisibilityOnUiThread(final View view, int visibility) throws Throwable {
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                view.setVisibility(visibility);
+            }
+        });
+    }
+
     private static class MockViewGroup extends ViewGroup {
         boolean isStartActionModeForChildCalled = false;
         int startActionModeForChildType = ActionMode.TYPE_PRIMARY;
diff --git a/tests/tests/view/src/android/view/inputmethod/cts/InputMethodInfoTest.java b/tests/tests/view/src/android/view/inputmethod/cts/InputMethodInfoTest.java
index dd7de51..3e071b6 100644
--- a/tests/tests/view/src/android/view/inputmethod/cts/InputMethodInfoTest.java
+++ b/tests/tests/view/src/android/view/inputmethod/cts/InputMethodInfoTest.java
@@ -25,7 +25,6 @@
 import android.content.pm.ServiceInfo;
 import android.content.res.Resources;
 import android.os.Parcel;
-import android.os.storage.StorageManager;
 import android.test.AndroidTestCase;
 import android.util.Printer;
 import android.view.inputmethod.InputMethod;
@@ -244,10 +243,6 @@
             return;
         }
 
-        if (!StorageManager.isFileEncryptedNativeOrEmulated()) {
-            return;
-        }
-
         final InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
         final List<InputMethodInfo> imis = imm.getInputMethodList();
         boolean hasEncryptionAwareInputMethod = false;
diff --git a/tests/tests/webkit/Android.mk b/tests/tests/webkit/Android.mk
index eb468dd..3a09f77 100644
--- a/tests/tests/webkit/Android.mk
+++ b/tests/tests/webkit/Android.mk
@@ -23,7 +23,12 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner org.apache.http.legacy
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctsdeviceutillegacy ctstestserver ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    ctsdeviceutil \
+    ctsdeviceutillegacy \
+    ctstestserver \
+    ctstestrunner \
+    platform-test-annotations
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/webkit/src/android/webkit/cts/CookieTest.java b/tests/tests/webkit/src/android/webkit/cts/CookieTest.java
index cca7e35..4f89ec1 100644
--- a/tests/tests/webkit/src/android/webkit/cts/CookieTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/CookieTest.java
@@ -17,6 +17,7 @@
 package android.webkit.cts;
 
 import android.cts.util.NullWebViewUtils;
+import android.platform.test.annotations.Presubmit;
 import android.test.ActivityInstrumentationTestCase2;
 import android.webkit.CookieManager;
 import android.webkit.CookieSyncManager;
@@ -56,6 +57,7 @@
         assertFalse(mCookieManager.hasCookies());
     }
 
+    @Presubmit
     public void testDomain() {
         if (!NullWebViewUtils.isWebViewAvailable()) {
             return;
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java
index 6768b6f..a4ebaca 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.cts.util.NullWebViewUtils;
 import android.cts.util.PollingCheck;
+import android.os.StrictMode;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
 import android.util.Log;
@@ -89,4 +90,20 @@
         assertEquals("42", m.group(1)); // value got incremented
     }
 
+    @UiThreadTest
+    public void testStrictModeNotViolatedOnStartup() throws Throwable {
+        StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
+        StrictMode.ThreadPolicy testPolicy = new StrictMode.ThreadPolicy.Builder()
+            .detectDiskReads()
+            .penaltyLog()
+            .penaltyDeath()
+            .build();
+        StrictMode.setThreadPolicy(testPolicy);
+        try {
+            mActivity.createAndAttachWebView();
+        } finally {
+            StrictMode.setThreadPolicy(oldPolicy);
+        }
+    }
+
 }
diff --git a/tests/tests/widget/Android.mk b/tests/tests/widget/Android.mk
index c5c3de3..96f10fc 100644
--- a/tests/tests/widget/Android.mk
+++ b/tests/tests/widget/Android.mk
@@ -21,7 +21,12 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_STATIC_JAVA_LIBRARIES += mockito-target android-common ctsdeviceutil ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES += \
+    mockito-target \
+    android-common \
+    ctsdeviceutil \
+    ctstestrunner \
+    platform-test-annotations
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
diff --git a/tests/tests/widget/AndroidTest.xml b/tests/tests/widget/AndroidTest.xml
index d943b85..ed7742a 100644
--- a/tests/tests/widget/AndroidTest.xml
+++ b/tests/tests/widget/AndroidTest.xml
@@ -21,6 +21,6 @@
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.widget.cts" />
-        <option name="runtime-hint" value="3m" />
+        <option name="runtime-hint" value="11m55s" />
     </test>
 </configuration>
diff --git a/tests/tests/widget/res/layout/popup_window_item.xml b/tests/tests/widget/res/layout/popup_window_item.xml
new file mode 100644
index 0000000..b53fd22
--- /dev/null
+++ b/tests/tests/widget/res/layout/popup_window_item.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/text1"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/popup_row_height"
+    android:textAppearance="?android:attr/textAppearanceListItemSmall"
+    android:gravity="center_vertical"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" />
diff --git a/tests/tests/widget/res/layout/popupwindow.xml b/tests/tests/widget/res/layout/popupwindow.xml
index 7746da8..d84770d 100644
--- a/tests/tests/widget/res/layout/popupwindow.xml
+++ b/tests/tests/widget/res/layout/popupwindow.xml
@@ -20,29 +20,37 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
-    <View android:id="@+id/anchor_upper"
+    <android.widget.cts.MockViewForListPopupWindow
+        android:id="@+id/anchor_upper_left"
         android:layout_width="10dp"
         android:layout_height="10dp"
         android:layout_alignParentTop="true"
+        android:layout_alignParentLeft="true"
+        android:background="#f0f" />
+
+    <View android:id="@+id/anchor_upper"
+        android:layout_width="10dp"
+        android:layout_height="30dp"
+        android:layout_alignParentTop="true"
         android:layout_centerHorizontal="true"
         android:background="#f00" />
 
     <View android:id="@+id/anchor_lower"
         android:layout_width="10dp"
-        android:layout_height="10dp"
+        android:layout_height="30dp"
         android:layout_alignParentBottom="true"
         android:layout_centerHorizontal="true"
         android:background="#0f0" />
 
     <View android:id="@+id/anchor_middle_left"
-        android:layout_width="10dp"
+        android:layout_width="30dp"
         android:layout_height="10dp"
         android:layout_alignParentLeft="true"
         android:layout_centerVertical="true"
         android:background="#00f" />
 
     <View android:id="@+id/anchor_middle_right"
-        android:layout_width="10dp"
+        android:layout_width="30dp"
         android:layout_height="10dp"
         android:layout_alignParentRight="true"
         android:layout_centerVertical="true"
diff --git a/tests/tests/widget/res/layout/tabhost_custom.xml b/tests/tests/widget/res/layout/tabhost_custom.xml
new file mode 100644
index 0000000..5308a18
--- /dev/null
+++ b/tests/tests/widget/res/layout/tabhost_custom.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<TabWidget
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/tabs"
+    android:layout_width="match_parent"
+    android:layout_height="68dip"
+    android:tabStripEnabled="false"
+    android:tabStripLeft="@drawable/icon_red"
+    android:tabStripRight="@drawable/icon_green" />
diff --git a/tests/tests/widget/res/layout/tabhost_layout.xml b/tests/tests/widget/res/layout/tabhost_layout.xml
index 1bae57a..de766f9 100644
--- a/tests/tests/widget/res/layout/tabhost_layout.xml
+++ b/tests/tests/widget/res/layout/tabhost_layout.xml
@@ -24,8 +24,7 @@
         android:layout_height="68dip"
         android:paddingLeft="1dip"
         android:paddingRight="1dip"
-        android:paddingTop="4dip"
-    />
+        android:paddingTop="4dip" />
 
     <FrameLayout android:id="@android:id/tabcontent"
         android:layout_width="match_parent"
diff --git a/tests/tests/widget/res/menu/popup_menu.xml b/tests/tests/widget/res/menu/popup_menu.xml
new file mode 100644
index 0000000..f50efc5
--- /dev/null
+++ b/tests/tests/widget/res/menu/popup_menu.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 Google Inc.
+
+     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.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/action_highlight"
+          android:title="@string/popup_menu_highlight" />
+    <item android:id="@+id/action_edit"
+          android:title="@string/popup_menu_edit" />
+    <item android:id="@+id/action_delete"
+          android:title="@string/popup_menu_delete" />
+    <item android:id="@+id/action_ignore"
+          android:title="@string/popup_menu_ignore" />
+    <item android:id="@+id/action_share"
+          android:title="@string/popup_menu_share">
+        <menu>
+            <item android:id="@+id/action_share_email"
+                  android:title="@string/popup_menu_share_email" />
+            <item android:id="@+id/action_share_circles"
+                  android:title="@string/popup_menu_share_circles" />
+        </menu>
+    </item>
+    <item android:id="@+id/action_print"
+          android:title="@string/popup_menu_print" />
+</menu>
diff --git a/tests/tests/widget/res/transition/custom_transition.xml b/tests/tests/widget/res/transition/custom_transition.xml
new file mode 100644
index 0000000..cb8ea5c
--- /dev/null
+++ b/tests/tests/widget/res/transition/custom_transition.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<transition xmlns:android="http://schemas.android.com/apk/res/android"
+            class="android.widget.cts.PopupWindowTest$CustomTransition"
+            android:duration="250" />
diff --git a/tests/tests/widget/res/values/dimens.xml b/tests/tests/widget/res/values/dimens.xml
new file mode 100644
index 0000000..3690039
--- /dev/null
+++ b/tests/tests/widget/res/values/dimens.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources>
+    <dimen name="popup_row_height">48dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/tests/tests/widget/res/values/strings.xml b/tests/tests/widget/res/values/strings.xml
index 51d8708..d889772 100644
--- a/tests/tests/widget/res/values/strings.xml
+++ b/tests/tests/widget/res/values/strings.xml
@@ -177,4 +177,14 @@
 text, I would love to see the kind of devices you guys now use! Guys, maybe some devices need longer string!
 I think so, so how about double this string, like copy and paste! </string>
     <string name="rectangle200">"M 0,0 l 200,0 l 0, 200 l -200, 0 z"</string>
+
+    <string name="popup_show">Show popup</string>
+    <string name="popup_menu_highlight">Highlight</string>
+    <string name="popup_menu_edit">Edit</string>
+    <string name="popup_menu_delete">Delete</string>
+    <string name="popup_menu_ignore">Ignore</string>
+    <string name="popup_menu_share">Share</string>
+    <string name="popup_menu_share_email">Via email</string>
+    <string name="popup_menu_share_circles">To my circles</string>
+    <string name="popup_menu_print">Print</string>
 </resources>
diff --git a/tests/tests/widget/res/values/styles.xml b/tests/tests/widget/res/values/styles.xml
index 81925cc..da22652 100644
--- a/tests/tests/widget/res/values/styles.xml
+++ b/tests/tests/widget/res/values/styles.xml
@@ -35,6 +35,18 @@
         <item name="type16">Typed Value!</item>
     </style>
 
+    <style name="PopupWindow" parent="@android:style/Widget.Material.ListPopupWindow" />
+
+    <style name="PopupWindow.NullTransitions">
+        <item name="android:popupEnterTransition">@null</item>
+        <item name="android:popupExitTransition">@null</item>
+    </style>
+
+    <style name="PopupWindow.CustomTransitions">
+        <item name="android:popupEnterTransition">@transition/custom_transition</item>
+        <item name="android:popupExitTransition">@transition/custom_transition</item>
+    </style>
+
     <style name="TextViewWithoutColorAndAppearance">
         <item name="android:textSize">18sp</item>
     </style>
@@ -169,4 +181,11 @@
         <item name="android:windowSwipeToDismiss">false</item>
     </style>
 
+    <style name="PopupEmptyStyle" />
+
+    <style name="TabWidgetCustomStyle" parent="android:Widget.TabWidget">
+        <item name="android:tabStripEnabled">false</item>
+        <item name="android:tabStripLeft">@drawable/icon_green</item>
+        <item name="android:tabStripRight">@drawable/icon_red</item>
+    </style>
 </resources>
diff --git a/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java b/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java
index 1fc0cef..bdda79a 100644
--- a/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java
@@ -16,22 +16,19 @@
 
 package android.widget.cts;
 
-import android.content.res.ColorStateList;
-import android.cts.util.WidgetTestUtils;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.ColorFilter;
-import android.graphics.PorterDuff;
-
-import android.widget.cts.R;
-
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.cts.util.PollingCheck;
+import android.cts.util.WidgetTestUtils;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.graphics.drawable.BitmapDrawable;
@@ -47,6 +44,8 @@
 import android.widget.FrameLayout.LayoutParams;
 import android.widget.LinearLayout;
 import android.widget.TextView;
+import android.widget.cts.R;
+import android.widget.cts.util.ViewTestUtils;
 
 import java.io.IOException;
 
@@ -88,12 +87,8 @@
         assertTrue(mFrameLayout.getWidth() > foreground.getIntrinsicWidth());
         assertNull(mFrameLayout.getForeground());
 
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                mFrameLayout.setForeground(foreground);
-            }
-        });
-        mInstrumentation.waitForIdleSync();
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mFrameLayout,
+                () -> mFrameLayout.setForeground(foreground));
         assertSame(foreground, mFrameLayout.getForeground());
         // check the default gravity FILL, it completely fills its container
         assertTrue(foreground.isVisible());
@@ -108,18 +103,16 @@
         assertEquals(mFrameLayout.getWidth(), rect.right - rect.left);
 
         // should get a new foreground again, because former foreground has been stretched
-        final BitmapDrawable newForeground
-                = (BitmapDrawable) mActivity.getResources().getDrawable(R.drawable.size_48x48);
+        final BitmapDrawable newForeground =
+                (BitmapDrawable) mActivity.getResources().getDrawable(R.drawable.size_48x48);
         compareScaledPixels(48, newForeground.getIntrinsicHeight());
         compareScaledPixels(48, newForeground.getIntrinsicWidth());
         assertTrue(mFrameLayout.getHeight() > newForeground.getIntrinsicHeight());
         assertTrue(mFrameLayout.getWidth() > foreground.getIntrinsicWidth());
 
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                mFrameLayout.setForeground(newForeground);
-                mFrameLayout.setForegroundGravity(Gravity.CENTER);
-            }
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mFrameLayout, () -> {
+            mFrameLayout.setForeground(newForeground);
+            mFrameLayout.setForegroundGravity(Gravity.CENTER);
         });
         mInstrumentation.waitForIdleSync();
         assertSame(newForeground, mFrameLayout.getForeground());
@@ -132,24 +125,19 @@
     }
 
     public void testGatherTransparentRegion() {
-        final LinearLayout container
-                = (LinearLayout) mActivity.findViewById(R.id.framelayout_container);
+        final LinearLayout container =
+                (LinearLayout) mActivity.findViewById(R.id.framelayout_container);
         final Drawable foreground = mActivity.getResources().getDrawable(R.drawable.size_48x48);
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                mFrameLayout.setForeground(foreground);
-                mFrameLayout.setForegroundGravity(Gravity.CENTER);
-            }
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mFrameLayout, () -> {
+            mFrameLayout.setForeground(foreground);
+            mFrameLayout.setForegroundGravity(Gravity.CENTER);
         });
         mInstrumentation.waitForIdleSync();
         Region region = new Region(foreground.getBounds());
         assertTrue(mFrameLayout.gatherTransparentRegion(region));
 
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                container.requestTransparentRegion(mFrameLayout);
-            }
-        });
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mFrameLayout,
+                () -> container.requestTransparentRegion(mFrameLayout));
         mInstrumentation.waitForIdleSync();
         region = new Region(foreground.getBounds());
         assertTrue(mFrameLayout.gatherTransparentRegion(region));
@@ -168,11 +156,9 @@
         assertEquals(textView.getMeasuredWidth(), frameLayout.getMeasuredWidth());
 
         // measureAll is false and text view is GONE, text view will NOT be measured
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                textView.setVisibility(View.GONE);
-                frameLayout.requestLayout();
-            }
+        mActivity.runOnUiThread(() -> {
+            textView.setVisibility(View.GONE);
+            frameLayout.requestLayout();
         });
         mInstrumentation.waitForIdleSync();
         assertFalse(frameLayout.getConsiderGoneChildrenWhenMeasuring());
@@ -183,11 +169,9 @@
         assertEquals(button.getMeasuredWidth(), frameLayout.getMeasuredWidth());
 
         // measureAll is true and text view is GONE, text view will be measured
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                frameLayout.setMeasureAllChildren(true);
-                frameLayout.requestLayout();
-            }
+        mActivity.runOnUiThread(() -> {
+            frameLayout.setMeasureAllChildren(true);
+            frameLayout.requestLayout();
         });
         mInstrumentation.waitForIdleSync();
         assertTrue(frameLayout.getConsiderGoneChildrenWhenMeasuring());
diff --git a/tests/tests/widget/src/android/widget/cts/LinearLayoutTest.java b/tests/tests/widget/src/android/widget/cts/LinearLayoutTest.java
index 76fa782..895184d 100644
--- a/tests/tests/widget/src/android/widget/cts/LinearLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/LinearLayoutTest.java
@@ -16,24 +16,24 @@
 
 package android.widget.cts;
 
-import android.graphics.Color;
-import android.view.View;
-import android.view.ViewTreeObserver;
 import org.xmlpull.v1.XmlPullParser;
 
 import android.app.Activity;
 import android.content.Context;
+import android.graphics.Color;
 import android.test.ActivityInstrumentationTestCase;
 import android.test.ViewAsserts;
 import android.util.AttributeSet;
 import android.util.Xml;
+import android.view.View;
+import android.view.View.MeasureSpec;
 import android.view.ViewGroup;
-import android.widget.LinearLayout.LayoutParams;
+import android.view.ViewTreeObserver;
 import android.widget.AbsoluteLayout;
 import android.widget.LinearLayout;
+import android.widget.LinearLayout.LayoutParams;
 import android.widget.ListView;
 import android.widget.TextView;
-
 import android.widget.cts.R;
 
 import java.util.concurrent.CountDownLatch;
@@ -177,6 +177,54 @@
         assertEquals(Math.ceil(parentWidth * 0.3), weight03.getWidth(), 1.0);
     }
 
+    public void testWeightDistribution() {
+        LinearLayout layout = new LinearLayout(mActivity);
+        for (int i = 0; i < 3; i++) {
+            layout.addView(new View(mActivity), new LayoutParams(0, 0, 1));
+        }
+
+        int size = 100;
+        int spec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
+
+        for (int i = 0; i < 3; i++) {
+            View child = layout.getChildAt(i);
+            LayoutParams lp = (LayoutParams) child.getLayoutParams();
+            lp.height = 0;
+            lp.width = LayoutParams.MATCH_PARENT;
+            child.setLayoutParams(lp);
+        }
+        layout.setOrientation(LinearLayout.VERTICAL);
+        layout.measure(spec, spec);
+        layout.layout(0, 0, size, size);
+        assertEquals(100, layout.getWidth());
+        assertEquals(100, layout.getChildAt(0).getWidth());
+        assertEquals(100, layout.getChildAt(1).getWidth());
+        assertEquals(100, layout.getChildAt(2).getWidth());
+        assertEquals(100, layout.getHeight());
+        assertEquals(33, layout.getChildAt(0).getHeight());
+        assertEquals(33, layout.getChildAt(1).getHeight());
+        assertEquals(34, layout.getChildAt(2).getHeight());
+
+        for (int i = 0; i < 3; i++) {
+            View child = layout.getChildAt(i);
+            LayoutParams lp = (LayoutParams) child.getLayoutParams();
+            lp.height = LayoutParams.MATCH_PARENT;
+            lp.width = 0;
+            child.setLayoutParams(lp);
+        }
+        layout.setOrientation(LinearLayout.HORIZONTAL);
+        layout.measure(spec, spec);
+        layout.layout(0, 0, size, size);
+        assertEquals(100, layout.getWidth());
+        assertEquals(33, layout.getChildAt(0).getWidth());
+        assertEquals(33, layout.getChildAt(1).getWidth());
+        assertEquals(34, layout.getChildAt(2).getWidth());
+        assertEquals(100, layout.getHeight());
+        assertEquals(100, layout.getChildAt(0).getHeight());
+        assertEquals(100, layout.getChildAt(1).getHeight());
+        assertEquals(100, layout.getChildAt(2).getHeight());
+    }
+
     public void testGenerateLayoutParams() {
         ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(320, 240);
         MockLinearLayout mockLinearLayout = new MockLinearLayout(mContext);
diff --git a/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java b/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
index da5b9fe..abe7848 100644
--- a/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
@@ -23,11 +23,13 @@
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.SystemClock;
+import android.platform.test.annotations.Presubmit;
 import android.support.test.InstrumentationRegistry;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.view.Display;
 import android.view.Gravity;
+import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
@@ -104,6 +106,11 @@
         new ListPopupWindow(mActivity, null, 0, android.R.style.Widget_Material_ListPopupWindow);
     }
 
+    public void noDefaultVisibility() {
+        mPopupWindow = new ListPopupWindow(mActivity);
+        assertFalse(mPopupWindow.isShowing());
+    }
+
     public void testAccessBackground() {
         mPopupWindowBuilder = new Builder();
         mPopupWindowBuilder.show();
@@ -280,8 +287,6 @@
 
     public void testDismiss() {
         mPopupWindowBuilder = new Builder();
-        assertFalse(mPopupWindow.isShowing());
-
         mPopupWindowBuilder.show();
         assertTrue(mPopupWindow.isShowing());
 
@@ -510,6 +515,7 @@
         assertTrue(lastChildOnScreenXY[1] + lastListChild.getHeight() <= promptViewOnScreenXY[1]);
     }
 
+    @Presubmit
     public void testAccessSelection() throws Throwable {
         mPopupWindowBuilder = new Builder().withItemSelectedListener();
         mPopupWindowBuilder.show();
@@ -569,6 +575,204 @@
         verifyNoMoreInteractions(mPopupWindowBuilder.mOnItemSelectedListener);
     }
 
+    public void testNoDefaultDismissalWithBackButton() throws Throwable {
+        mPopupWindowBuilder = new Builder().withDismissListener();
+        mPopupWindowBuilder.show();
+
+        // Send BACK key event. As we don't have any custom code that dismisses ListPopupWindow,
+        // and ListPopupWindow doesn't track that system-level key event on its own, ListPopupWindow
+        // should stay visible
+        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
+        verify(mPopupWindowBuilder.mOnDismissListener, never()).onDismiss();
+        assertTrue(mPopupWindow.isShowing());
+    }
+
+    public void testCustomDismissalWithBackButton() throws Throwable {
+        mPopupWindowBuilder = new Builder().withAnchor(R.id.anchor_upper_left)
+                .withDismissListener();
+        mPopupWindowBuilder.show();
+
+        // "Point" our custom extension of EditText to our ListPopupWindow
+        final MockViewForListPopupWindow anchor =
+                (MockViewForListPopupWindow) mPopupWindow.getAnchorView();
+        anchor.wireTo(mPopupWindow);
+        // Request focus on our EditText
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                anchor.requestFocus();
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+        assertTrue(anchor.isFocused());
+
+        // Send BACK key event. As our custom extension of EditText calls
+        // ListPopupWindow.onKeyPreIme, the end result should be the dismissal of the
+        // ListPopupWindow
+        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
+        verify(mPopupWindowBuilder.mOnDismissListener, times(1)).onDismiss();
+        assertFalse(mPopupWindow.isShowing());
+    }
+
+    public void testListSelectionWithDPad() throws Throwable {
+        mPopupWindowBuilder = new Builder().withAnchor(R.id.anchor_upper_left)
+                .withDismissListener().withItemSelectedListener();
+        mPopupWindowBuilder.show();
+
+        // "Point" our custom extension of EditText to our ListPopupWindow
+        final MockViewForListPopupWindow anchor =
+                (MockViewForListPopupWindow) mPopupWindow.getAnchorView();
+        anchor.wireTo(mPopupWindow);
+        // Request focus on our EditText
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                anchor.requestFocus();
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+        assertTrue(anchor.isFocused());
+
+        // Select entry #1 in the popup list
+        final ListView listView = mPopupWindow.getListView();
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, listView, new Runnable() {
+            public void run() {
+                mPopupWindow.setSelection(1);
+            }
+        });
+        verify(mPopupWindowBuilder.mOnItemSelectedListener, times(1)).onItemSelected(
+                any(AdapterView.class), any(View.class), eq(1), eq(1L));
+
+        // Send DPAD_DOWN key event. As our custom extension of EditText calls
+        // ListPopupWindow.onKeyDown and onKeyUp, the end result should be transfer of selection
+        // down one row
+        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
+        mInstrumentation.waitForIdleSync();
+
+        // At this point we expect that item #2 was selected
+        verify(mPopupWindowBuilder.mOnItemSelectedListener, times(1)).onItemSelected(
+                any(AdapterView.class), any(View.class), eq(2), eq(2L));
+
+        // Send a DPAD_UP key event. As our custom extension of EditText calls
+        // ListPopupWindow.onKeyDown and onKeyUp, the end result should be transfer of selection
+        // up one row
+        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_UP);
+        mInstrumentation.waitForIdleSync();
+
+        // At this point we expect that item #1 was selected
+        verify(mPopupWindowBuilder.mOnItemSelectedListener, times(2)).onItemSelected(
+                any(AdapterView.class), any(View.class), eq(1), eq(1L));
+
+        // Send one more DPAD_UP key event. As our custom extension of EditText calls
+        // ListPopupWindow.onKeyDown and onKeyUp, the end result should be transfer of selection
+        // up one more row
+        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_UP);
+        mInstrumentation.waitForIdleSync();
+
+        // At this point we expect that item #0 was selected
+        verify(mPopupWindowBuilder.mOnItemSelectedListener, times(1)).onItemSelected(
+                any(AdapterView.class), any(View.class), eq(0), eq(0L));
+
+        // Send ENTER key event. As our custom extension of EditText calls
+        // ListPopupWindow.onKeyDown and onKeyUp, the end result should be dismissal of
+        // the popup window
+        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_ENTER);
+        mInstrumentation.waitForIdleSync();
+
+        verify(mPopupWindowBuilder.mOnDismissListener, times(1)).onDismiss();
+        assertFalse(mPopupWindow.isShowing());
+
+        verifyNoMoreInteractions(mPopupWindowBuilder.mOnItemSelectedListener);
+        verifyNoMoreInteractions(mPopupWindowBuilder.mOnDismissListener);
+    }
+
+    /**
+     * Emulates a drag-down gestures by injecting ACTION events with {@link Instrumentation}.
+     */
+    private void emulateDragDownGesture(int emulatedX, int emulatedStartY, int swipeAmount) {
+        // The logic below uses Instrumentation to emulate a swipe / drag gesture to bring up
+        // the popup content.
+
+        // Inject DOWN event
+        long downTime = SystemClock.uptimeMillis();
+        MotionEvent eventDown = MotionEvent.obtain(
+                downTime, downTime, MotionEvent.ACTION_DOWN, emulatedX, emulatedStartY, 1);
+        mInstrumentation.sendPointerSync(eventDown);
+
+        // Inject a sequence of MOVE events that emulate a "swipe down" gesture
+        for (int i = 0; i < 10; i++) {
+            long moveTime = SystemClock.uptimeMillis();
+            final int moveY = emulatedStartY + swipeAmount * i / 10;
+            MotionEvent eventMove = MotionEvent.obtain(
+                    moveTime, moveTime, MotionEvent.ACTION_MOVE, emulatedX, moveY, 1);
+            mInstrumentation.sendPointerSync(eventMove);
+            // sleep for a bit to emulate a 200ms swipe
+            SystemClock.sleep(20);
+        }
+
+        // Inject UP event
+        long upTime = SystemClock.uptimeMillis();
+        MotionEvent eventUp = MotionEvent.obtain(
+                upTime, upTime, MotionEvent.ACTION_UP, emulatedX, emulatedStartY + swipeAmount, 1);
+        mInstrumentation.sendPointerSync(eventUp);
+
+        // Wait for the system to process all events in the queue
+        mInstrumentation.waitForIdleSync();
+    }
+
+    public void testCreateOnDragListener() throws Throwable {
+        // In this test we want precise control over the height of the popup content since
+        // we need to know by how much to swipe down to end the emulated gesture over the
+        // specific item in the popup. This is why we're using a popup style that removes
+        // all decoration around the popup content, as well as our own row layout with known
+        // height.
+        mPopupWindowBuilder = new Builder()
+                .withPopupStyleAttr(R.style.PopupEmptyStyle)
+                .withContentRowLayoutId(R.layout.popup_window_item)
+                .withItemClickListener().withDismissListener();
+
+        // Configure ListPopupWindow without showing it
+        mPopupWindowBuilder.configure();
+
+        // Get the anchor view and configure it with ListPopupWindow's drag-to-open listener
+        final View anchor = mActivity.findViewById(mPopupWindowBuilder.mAnchorId);
+        View.OnTouchListener dragListener = mPopupWindow.createDragToOpenListener(anchor);
+        anchor.setOnTouchListener(dragListener);
+        // And also configure it to show the popup window on click
+        anchor.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                mPopupWindow.show();
+            }
+        });
+
+        // Get the height of a row item in our popup window
+        final int popupRowHeight = mActivity.getResources().getDimensionPixelSize(
+                R.dimen.popup_row_height);
+
+        final int[] anchorOnScreenXY = new int[2];
+        anchor.getLocationOnScreen(anchorOnScreenXY);
+
+        // Compute the start coordinates of a downward swipe and the amount of swipe. We'll
+        // be swiping by twice the row height. That, combined with the swipe originating in the
+        // center of the anchor should result in clicking the second row in the popup.
+        int emulatedX = anchorOnScreenXY[0] + anchor.getWidth() / 2;
+        int emulatedStartY = anchorOnScreenXY[1] + anchor.getHeight() / 2;
+        int swipeAmount = 2 * popupRowHeight;
+
+        // Emulate drag-down gesture with a sequence of motion events
+        emulateDragDownGesture(emulatedX, emulatedStartY, swipeAmount);
+
+        // We expect the swipe / drag gesture to result in clicking the second item in our list.
+        verify(mPopupWindowBuilder.mOnItemClickListener, times(1)).onItemClick(
+                any(AdapterView.class), any(View.class), eq(1), eq(1L));
+        // Since our item click listener calls dismiss() on the popup, we expect the popup to not
+        // be showing
+        assertFalse(mPopupWindow.isShowing());
+        // At this point our popup should have notified its dismiss listener
+        verify(mPopupWindowBuilder.mOnDismissListener, times(1)).onDismiss();
+    }
+
     /**
      * Inner helper class to configure an instance of <code>ListPopupWindow</code> for the
      * specific test. The main reason for its existence is that once a popup window is shown
@@ -585,10 +789,15 @@
         private int mHorizontalOffset;
         private int mVerticalOffset;
         private int mDropDownGravity;
+        private int mAnchorId = R.id.anchor_upper;
+        private int mContentRowLayoutId = android.R.layout.simple_list_item_1;
 
         private boolean mHasWindowLayoutType;
         private int mWindowLayoutType;
 
+        private boolean mUseCustomPopupStyle;
+        private int mPopupStyleAttr;
+
         private View mPromptView;
         private int mPromptPosition;
 
@@ -597,7 +806,22 @@
         private PopupWindow.OnDismissListener mOnDismissListener;
 
         public Builder() {
-            mPopupWindow = new ListPopupWindow(mActivity);
+        }
+
+        public Builder withAnchor(int anchorId) {
+            mAnchorId = anchorId;
+            return this;
+        }
+
+        public Builder withContentRowLayoutId(int contentRowLayoutId) {
+            mContentRowLayoutId = contentRowLayoutId;
+            return this;
+        }
+
+        public Builder withPopupStyleAttr(int popupStyleAttr) {
+            mUseCustomPopupStyle = true;
+            mPopupStyleAttr = popupStyleAttr;
+            return this;
         }
 
         public Builder ignoreContentWidth() {
@@ -687,7 +911,12 @@
             return width;
         }
 
-        private void show() {
+        private void configure() {
+            if (mUseCustomPopupStyle) {
+                mPopupWindow = new ListPopupWindow(mActivity, null, mPopupStyleAttr, 0);
+            } else {
+                mPopupWindow = new ListPopupWindow(mActivity);
+            }
             final String[] POPUP_CONTENT =
                     new String[]{"Alice", "Bob", "Charlie", "Deirdre", "El"};
             final BaseAdapter listPopupAdapter = new BaseAdapter() {
@@ -714,7 +943,7 @@
                 public View getView(int position, View convertView, ViewGroup parent) {
                     if (convertView == null) {
                         convertView = LayoutInflater.from(mActivity).inflate(
-                                android.R.layout.simple_list_item_1, parent, false);
+                                mContentRowLayoutId, parent, false);
                         ViewHolder viewHolder = new ViewHolder();
                         viewHolder.title = (TextView) convertView.findViewById(android.R.id.text1);
                         convertView.setTag(viewHolder);
@@ -727,7 +956,7 @@
             };
 
             mPopupWindow.setAdapter(listPopupAdapter);
-            mPopupWindow.setAnchorView(mActivity.findViewById(R.id.anchor_upper));
+            mPopupWindow.setAnchorView(mActivity.findViewById(mAnchorId));
 
             // The following mock listeners have to be set before the call to show() as
             // they are set on the internally constructed drop down.
@@ -780,6 +1009,10 @@
                 mPopupWindow.setPromptPosition(mPromptPosition);
                 mPopupWindow.setPromptView(mPromptView);
             }
+        }
+
+        private void show() {
+            configure();
 
             mInstrumentation.runOnMainSync(new Runnable() {
                 public void run() {
diff --git a/tests/tests/widget/src/android/widget/cts/MockViewForListPopupWindow.java b/tests/tests/widget/src/android/widget/cts/MockViewForListPopupWindow.java
new file mode 100644
index 0000000..dc6cfc6
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/MockViewForListPopupWindow.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.cts;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.widget.EditText;
+import android.widget.ListPopupWindow;
+
+public class MockViewForListPopupWindow extends EditText {
+    private ListPopupWindow mListPopupWindow;
+
+    public MockViewForListPopupWindow(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public MockViewForListPopupWindow(Context context) {
+        super(context);
+    }
+
+    public void wireTo(ListPopupWindow listPopupWindow) {
+        mListPopupWindow = listPopupWindow;
+    }
+
+    @Override
+    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+        if (mListPopupWindow != null) {
+            return mListPopupWindow.onKeyPreIme(keyCode, event);
+        }
+        return super.onKeyPreIme(keyCode, event);
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        if (mListPopupWindow != null) {
+            return mListPopupWindow.onKeyDown(keyCode, event);
+        }
+        return super.onKeyDown(keyCode, event);
+    }
+
+    @Override
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
+        if (mListPopupWindow != null) {
+            return mListPopupWindow.onKeyUp(keyCode, event);
+        }
+        return super.onKeyUp(keyCode, event);
+    }
+}
+
diff --git a/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java b/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java
index 206b794..2339101 100644
--- a/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java
+++ b/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java
@@ -16,21 +16,32 @@
 
 package android.widget.cts;
 
-import static org.mockito.Mockito.*;
-
 import android.app.Activity;
 import android.app.Instrumentation;
+import android.os.SystemClock;
+import android.support.test.InstrumentationRegistry;
 import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.view.Gravity;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.SubMenu;
+import android.view.View;
 import android.widget.PopupMenu;
 
-import android.widget.cts.R;
+import static org.mockito.Mockito.*;
 
+@SmallTest
 public class PopupMenuTest extends
         ActivityInstrumentationTestCase2<MockPopupWindowCtsActivity> {
     private Instrumentation mInstrumentation;
     private Activity mActivity;
 
+    private Builder mBuilder;
+    private PopupMenu mPopupMenu;
+
     public PopupMenuTest() {
         super("android.widget.cts", MockPopupWindowCtsActivity.class);
     }
@@ -42,43 +53,382 @@
         mActivity = getActivity();
     }
 
-    public void testAccessGravity() {
-        PopupMenu popupMenu = new PopupMenu(mActivity,
-                mActivity.findViewById(R.id.anchor_middle_left));
-        assertEquals(Gravity.NO_GRAVITY, popupMenu.getGravity());
-
-        popupMenu.setGravity(Gravity.TOP);
-        assertEquals(Gravity.TOP, popupMenu.getGravity());
+    @Override
+    protected void tearDown() throws Exception {
+        if (mPopupMenu != null) {
+            try {
+                runTestOnUiThread(new Runnable() {
+                    @Override
+                    public void run() {
+                        mPopupMenu.dismiss();
+                    }
+                });
+            } catch (Throwable t) {
+                throw new RuntimeException(t);
+            }
+        }
+        super.tearDown();
     }
 
-    public void testOnDismissListener() {
-        final PopupMenu popupMenu = new PopupMenu(mActivity,
-                mActivity.findViewById(R.id.anchor_middle_left));
-        PopupMenu.OnDismissListener listener = mock(PopupMenu.OnDismissListener.class);
-        popupMenu.setOnDismissListener(listener);
+    private void verifyMenuContent() {
+        final Menu menu = mPopupMenu.getMenu();
+        assertEquals(6, menu.size());
+        assertEquals(R.id.action_highlight, menu.getItem(0).getItemId());
+        assertEquals(R.id.action_edit, menu.getItem(1).getItemId());
+        assertEquals(R.id.action_delete, menu.getItem(2).getItemId());
+        assertEquals(R.id.action_ignore, menu.getItem(3).getItemId());
+        assertEquals(R.id.action_share, menu.getItem(4).getItemId());
+        assertEquals(R.id.action_print, menu.getItem(5).getItemId());
 
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                popupMenu.show();
-            }
-        });
-        mInstrumentation.waitForIdleSync();
-        verify(listener, never()).onDismiss(popupMenu);
-
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                popupMenu.dismiss();
-            }
-        });
-        mInstrumentation.waitForIdleSync();
-        verify(listener, times(1)).onDismiss(popupMenu);
-
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                popupMenu.dismiss();
-            }
-        });
-        mInstrumentation.waitForIdleSync();
-        verify(listener, times(1)).onDismiss(popupMenu);
+        final SubMenu shareSubMenu = menu.getItem(4).getSubMenu();
+        assertNotNull(shareSubMenu);
+        assertEquals(2, shareSubMenu.size());
+        assertEquals(R.id.action_share_email, shareSubMenu.getItem(0).getItemId());
+        assertEquals(R.id.action_share_circles, shareSubMenu.getItem(1).getItemId());
     }
-}
+
+    public void testPopulateViaInflater() throws Throwable {
+        mBuilder = new Builder().inflateWithInflater(true);
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                mBuilder.show();
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+
+        verifyMenuContent();
+    }
+
+    public void testDirectPopulate() throws Throwable {
+        mBuilder = new Builder().inflateWithInflater(false);
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                mBuilder.show();
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+
+        verifyMenuContent();
+    }
+
+    public void testAccessGravity() throws Throwable {
+        mBuilder = new Builder();
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                mBuilder.show();
+            }
+        });
+
+        assertEquals(Gravity.NO_GRAVITY, mPopupMenu.getGravity());
+        mPopupMenu.setGravity(Gravity.TOP);
+        assertEquals(Gravity.TOP, mPopupMenu.getGravity());
+    }
+
+    public void testConstructorWithGravity() throws Throwable {
+        mBuilder = new Builder().withGravity(Gravity.TOP);
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                mBuilder.show();
+            }
+        });
+
+        assertEquals(Gravity.TOP, mPopupMenu.getGravity());
+    }
+
+    public void testDismissalViaAPI() throws Throwable {
+        mBuilder = new Builder().withDismissListener();
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                mBuilder.show();
+            }
+        });
+
+        mInstrumentation.waitForIdleSync();
+        verify(mBuilder.mOnDismissListener, never()).onDismiss(mPopupMenu);
+
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                mPopupMenu.dismiss();
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+        verify(mBuilder.mOnDismissListener, times(1)).onDismiss(mPopupMenu);
+
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                mPopupMenu.dismiss();
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+        // Shouldn't have any more interactions with our dismiss listener since the menu was
+        // already dismissed when we called dismiss()
+        verifyNoMoreInteractions(mBuilder.mOnDismissListener);
+    }
+
+    public void testNestedDismissalViaAPI() throws Throwable {
+        // Use empty popup style to remove all transitions from the popup. That way we don't
+        // need to synchronize with the popup window enter transition before proceeding to
+        // "click" a submenu item.
+        mBuilder = new Builder().withDismissListener()
+                .withPopupStyleAttr(R.style.PopupEmptyStyle);
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                mBuilder.show();
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+        verify(mBuilder.mOnDismissListener, never()).onDismiss(mPopupMenu);
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mPopupMenu.getMenu().performIdentifierAction(R.id.action_share, 0);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mPopupMenu.getMenu().findItem(R.id.action_share).getSubMenu().
+                        performIdentifierAction(R.id.action_share_email, 0);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                mPopupMenu.dismiss();
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+        verify(mBuilder.mOnDismissListener, times(1)).onDismiss(mPopupMenu);
+
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                mPopupMenu.dismiss();
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+        // Shouldn't have any more interactions with our dismiss listener since the menu was
+        // already dismissed when we called dismiss()
+        verifyNoMoreInteractions(mBuilder.mOnDismissListener);
+    }
+
+    public void testDismissalViaTouch() throws Throwable {
+        // Use empty popup style to remove all transitions from the popup. That way we don't
+        // need to synchronize with the popup window enter transition before proceeding to
+        // emulate a click outside the popup window bounds.
+        mBuilder = new Builder().withDismissListener()
+                .withPopupStyleAttr(R.style.PopupEmptyStyle);
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                mBuilder.show();
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+
+        // Determine the location of the anchor on the screen so that we can emulate
+        // a tap outside of the popup bounds to dismiss the popup
+        final int[] anchorOnScreenXY = new int[2];
+        mBuilder.mAnchor.getLocationOnScreen(anchorOnScreenXY);
+
+        int emulatedTapX = anchorOnScreenXY[0] + 10;
+        int emulatedTapY = anchorOnScreenXY[1] - 20;
+
+        // The logic below uses Instrumentation to emulate a tap outside the bounds of the
+        // displayed popup menu. This tap is then treated by the framework to be "split" as
+        // the ACTION_OUTSIDE for the popup itself, as well as DOWN / MOVE / UP for the underlying
+        // view root if the popup is not modal.
+        // It is not correct to emulate these two sequences separately in the test, as it
+        // wouldn't emulate the user-facing interaction for this test. Note that usage
+        // of Instrumentation is necessary here since Espresso's actions operate at the level
+        // of view or data. Also, we don't want to use View.dispatchTouchEvent directly as
+        // that would require emulation of two separate sequences as well.
+
+        // Inject DOWN event
+        long downTime = SystemClock.uptimeMillis();
+        MotionEvent eventDown = MotionEvent.obtain(
+                downTime, downTime, MotionEvent.ACTION_DOWN, emulatedTapX, emulatedTapY, 1);
+        mInstrumentation.sendPointerSync(eventDown);
+
+        // Inject MOVE event
+        long moveTime = SystemClock.uptimeMillis();
+        MotionEvent eventMove = MotionEvent.obtain(
+                moveTime, moveTime, MotionEvent.ACTION_MOVE, emulatedTapX, emulatedTapY, 1);
+        mInstrumentation.sendPointerSync(eventMove);
+
+        // Inject UP event
+        long upTime = SystemClock.uptimeMillis();
+        MotionEvent eventUp = MotionEvent.obtain(
+                upTime, upTime, MotionEvent.ACTION_UP, emulatedTapX, emulatedTapY, 1);
+        mInstrumentation.sendPointerSync(eventUp);
+
+        // Wait for the system to process all events in the queue
+        mInstrumentation.waitForIdleSync();
+
+        // At this point our popup should have notified its dismiss listener
+        verify(mBuilder.mOnDismissListener, times(1)).onDismiss(mPopupMenu);
+    }
+
+    public void testSimpleMenuItemClickViaAPI() throws Throwable {
+        mBuilder = new Builder().withMenuItemClickListener().withDismissListener();
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                mBuilder.show();
+            }
+        });
+
+        // Verify that our menu item click listener hasn't been called yet
+        verify(mBuilder.mOnMenuItemClickListener, never()).onMenuItemClick(any(MenuItem.class));
+
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                mPopupMenu.getMenu().performIdentifierAction(R.id.action_highlight, 0);
+            }
+        });
+
+        // Verify that our menu item click listener has been called with the expected menu item
+        verify(mBuilder.mOnMenuItemClickListener, times(1)).onMenuItemClick(
+                mPopupMenu.getMenu().findItem(R.id.action_highlight));
+
+        // Popup menu should be automatically dismissed on selecting an item
+        verify(mBuilder.mOnDismissListener, times(1)).onDismiss(mPopupMenu);
+        verifyNoMoreInteractions(mBuilder.mOnDismissListener);
+    }
+
+    public void testSubMenuClickViaAPI() throws Throwable {
+        // Use empty popup style to remove all transitions from the popup. That way we don't
+        // need to synchronize with the popup window enter transition before proceeding to
+        // "click" a submenu item.
+        mBuilder = new Builder().withDismissListener().withMenuItemClickListener()
+                .withPopupStyleAttr(R.style.PopupEmptyStyle);
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                mBuilder.show();
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+
+        // Verify that our menu item click listener hasn't been called yet
+        verify(mBuilder.mOnMenuItemClickListener, never()).onMenuItemClick(any(MenuItem.class));
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mPopupMenu.getMenu().performIdentifierAction(R.id.action_share, 0);
+            }
+        });
+        // Verify that our menu item click listener has been called on "share" action
+        verify(mBuilder.mOnMenuItemClickListener, times(1)).onMenuItemClick(
+                mPopupMenu.getMenu().findItem(R.id.action_share));
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mPopupMenu.getMenu().findItem(R.id.action_share).getSubMenu().
+                        performIdentifierAction(R.id.action_share_email, 0);
+            }
+        });
+
+        // Verify that out menu item click listener has been called with the expected menu item
+        verify(mBuilder.mOnMenuItemClickListener, times(1)).onMenuItemClick(
+                mPopupMenu.getMenu().findItem(R.id.action_share).getSubMenu()
+                        .findItem(R.id.action_share_email));
+        verifyNoMoreInteractions(mBuilder.mOnMenuItemClickListener);
+
+        // Popup menu should be automatically dismissed on selecting an item
+        verify(mBuilder.mOnDismissListener, times(1)).onDismiss(mPopupMenu);
+        verifyNoMoreInteractions(mBuilder.mOnDismissListener);
+    }
+
+    /**
+     * Inner helper class to configure an instance of {@link PopupMenu} for the specific test.
+     * The main reason for its existence is that once a popup menu is shown with the show() method,
+     * most of its configuration APIs are no-ops. This means that we can't add logic that is
+     * specific to a certain test once it's shown and we have a reference to a displayed
+     * {@link PopupMenu}.
+     */
+    public class Builder {
+        private boolean mHasDismissListener;
+        private boolean mHasMenuItemClickListener;
+        private boolean mInflateWithInflater;
+
+        private boolean mUseCustomPopupStyle;
+        private int mPopupStyleAttr = android.R.attr.popupMenuStyle;
+
+        private boolean mUseCustomGravity;
+        private int mGravity = Gravity.NO_GRAVITY;
+
+        private PopupMenu.OnMenuItemClickListener mOnMenuItemClickListener;
+        private PopupMenu.OnDismissListener mOnDismissListener;
+
+        private View mAnchor;
+
+        public Builder withMenuItemClickListener() {
+            mHasMenuItemClickListener = true;
+            return this;
+        }
+
+        public Builder withDismissListener() {
+            mHasDismissListener = true;
+            return this;
+        }
+
+        public Builder inflateWithInflater(boolean inflateWithInflater) {
+            mInflateWithInflater = inflateWithInflater;
+            return this;
+        }
+
+        public Builder withPopupStyleAttr(int popupStyleAttr) {
+            mUseCustomPopupStyle = true;
+            mPopupStyleAttr = popupStyleAttr;
+            return this;
+        }
+
+        public Builder withGravity(int gravity) {
+            mUseCustomGravity = true;
+            mGravity = gravity;
+            return this;
+        }
+
+        private void configure() {
+            mAnchor = mActivity.findViewById(R.id.anchor_middle_left);
+            if (!mUseCustomGravity && !mUseCustomPopupStyle) {
+                mPopupMenu = new PopupMenu(mActivity, mAnchor);
+            } else if (!mUseCustomPopupStyle) {
+                mPopupMenu = new PopupMenu(mActivity, mAnchor, mGravity);
+            } else {
+                mPopupMenu = new PopupMenu(mActivity, mAnchor, Gravity.NO_GRAVITY,
+                        mPopupStyleAttr, 0);
+            }
+
+            if (mInflateWithInflater) {
+                final MenuInflater menuInflater = mPopupMenu.getMenuInflater();
+                menuInflater.inflate(R.menu.popup_menu, mPopupMenu.getMenu());
+            } else {
+                mPopupMenu.inflate(R.menu.popup_menu);
+            }
+
+            if (mHasMenuItemClickListener) {
+                // Register a mock listener to be notified when a menu item in our popup menu has
+                // been clicked.
+                mOnMenuItemClickListener = mock(PopupMenu.OnMenuItemClickListener.class);
+                mPopupMenu.setOnMenuItemClickListener(mOnMenuItemClickListener);
+            }
+
+            if (mHasDismissListener) {
+                // Register a mock listener to be notified when our popup menu is dismissed.
+                mOnDismissListener = mock(PopupMenu.OnDismissListener.class);
+                mPopupMenu.setOnDismissListener(mOnDismissListener);
+            }
+        }
+
+        public void show() {
+            configure();
+            // Show the popup menu
+            mPopupMenu.show();
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
index db67787..7f5f6e7 100644
--- a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
@@ -18,6 +18,7 @@
 
 import static org.mockito.Mockito.*;
 
+import android.util.AttributeSet;
 import org.mockito.InOrder;
 
 import android.app.Activity;
@@ -130,6 +131,52 @@
         assertTrue(mPopupWindow.isFocusable());
     }
 
+    public void testAccessEnterExitTransitions() {
+        PopupWindow w;
+
+        w = new PopupWindow(mActivity, null, 0, 0);
+        assertNull(w.getEnterTransition());
+        assertNull(w.getExitTransition());
+
+        w = new PopupWindow(mActivity, null, 0, R.style.PopupWindow_NullTransitions);
+        assertNull(w.getEnterTransition());
+        assertNull(w.getExitTransition());
+
+        w = new PopupWindow(mActivity, null, 0, R.style.PopupWindow_CustomTransitions);
+        assertTrue(w.getEnterTransition() instanceof CustomTransition);
+        assertTrue(w.getExitTransition() instanceof CustomTransition);
+
+        Transition enterTransition = new CustomTransition();
+        Transition exitTransition = new CustomTransition();
+        w = new PopupWindow(mActivity, null, 0, 0);
+        w.setEnterTransition(enterTransition);
+        w.setExitTransition(exitTransition);
+        assertEquals(enterTransition, w.getEnterTransition());
+        assertEquals(exitTransition, w.getExitTransition());
+
+        w.setEnterTransition(null);
+        w.setExitTransition(null);
+        assertNull(w.getEnterTransition());
+        assertNull(w.getExitTransition());
+    }
+
+    public static class CustomTransition extends Transition {
+        public CustomTransition() {
+        }
+
+        // This constructor is needed for reflection-based creation of a transition when
+        // the transition is defined in layout XML via attribute.
+        public CustomTransition(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+
+        @Override
+        public void captureStartValues(TransitionValues transitionValues) {}
+
+        @Override
+        public void captureEndValues(TransitionValues transitionValues) {}
+    }
+
     public void testAccessBackground() {
         mPopupWindow = new PopupWindow(mActivity);
 
diff --git a/tests/tests/widget/src/android/widget/cts/TabHostTest.java b/tests/tests/widget/src/android/widget/cts/TabHostTest.java
index 0544c24..8756687 100644
--- a/tests/tests/widget/src/android/widget/cts/TabHostTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TabHostTest.java
@@ -16,25 +16,26 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
-
 import android.app.Activity;
 import android.app.ActivityGroup;
 import android.content.Intent;
 import android.cts.util.WidgetTestUtils;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.view.View;
 import android.widget.ListView;
 import android.widget.TabHost;
-import android.widget.TextView;
 import android.widget.TabHost.OnTabChangeListener;
 import android.widget.TabHost.TabSpec;
+import android.widget.TextView;
+
+import static org.mockito.Mockito.*;
 
 /**
  * Test {@link TabHost}.
  */
+@SmallTest
 public class TabHostTest extends ActivityInstrumentationTestCase2<TabHostCtsActivity> {
     private static final String TAG_TAB1 = "tab 1";
     private static final String TAG_TAB2 = "tab 2";
@@ -182,18 +183,12 @@
         assertEquals(0, tabHost.getCurrentTab());
         assertNotNull(tabHost.getCurrentView());
 
-        /*
-        TODO: Uncomment after fixing clearAllTabs() issue.
-        The code below throws a NullPointerException in clearAllTabs(). The method throwing the
-        exception is TabWidget.onFocusChange().
-
         tabHost.clearAllTabs();
 
         assertEquals(0, tabHost.getTabWidget().getChildCount());
         assertEquals(0, tabHost.getTabContentView().getChildCount());
         assertEquals(-1, tabHost.getCurrentTab());
         assertNull(tabHost.getCurrentView());
-        */
     }
 
     public void testGetTabWidget() {
@@ -334,25 +329,23 @@
         TabHost tabHost = mActivity.getTabHost();
 
         // add a tab, and change current tab to the new tab
-        MockOnTabChangeListener listener = new MockOnTabChangeListener();
-        tabHost.setOnTabChangedListener(listener);
+        OnTabChangeListener mockTabChangeListener = mock(OnTabChangeListener.class);
+        tabHost.setOnTabChangedListener(mockTabChangeListener);
 
         TabSpec tabSpec = tabHost.newTabSpec(TAG_TAB2);
         tabSpec.setIndicator(TAG_TAB2);
         tabSpec.setContent(new MyTabContentFactoryList());
         tabHost.addTab(tabSpec);
         tabHost.setCurrentTab(1);
-        assertTrue(listener.hasCalledOnTabChanged());
+        verify(mockTabChangeListener, times(1)).onTabChanged(TAG_TAB2);
 
         // change current tab to the first one
-        listener.reset();
         tabHost.setCurrentTab(0);
-        assertTrue(listener.hasCalledOnTabChanged());
+        verify(mockTabChangeListener, times(1)).onTabChanged(TabHostCtsActivity.INITIAL_TAB_TAG);
 
         // set the same tab
-        listener.reset();
         tabHost.setCurrentTab(0);
-        assertFalse(listener.hasCalledOnTabChanged());
+        verifyNoMoreInteractions(mockTabChangeListener);
     }
 
     @UiThreadTest
@@ -387,21 +380,4 @@
             return lv;
         }
     }
-
-    private class MockOnTabChangeListener implements OnTabChangeListener {
-        private boolean mCalledOnTabChanged = false;
-
-        boolean hasCalledOnTabChanged() {
-            return mCalledOnTabChanged;
-        }
-
-        void reset() {
-            mCalledOnTabChanged = false;
-        }
-
-        public void onTabChanged(String tabId) {
-            mCalledOnTabChanged = true;
-        }
-    }
-
 }
diff --git a/tests/tests/widget/src/android/widget/cts/TabWidgetTest.java b/tests/tests/widget/src/android/widget/cts/TabWidgetTest.java
index f44117a..58fbf46 100644
--- a/tests/tests/widget/src/android/widget/cts/TabWidgetTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TabWidgetTest.java
@@ -19,19 +19,24 @@
 
 import android.app.Activity;
 import android.content.Context;
+import android.graphics.drawable.Drawable;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.LinearLayout;
+import android.widget.LinearLayout.LayoutParams;
 import android.widget.ListView;
 import android.widget.RelativeLayout;
 import android.widget.TabWidget;
 import android.widget.TextView;
-import android.widget.LinearLayout.LayoutParams;
+import android.widget.cts.util.TestUtils;
 
 /**
  * Test {@link TabWidget}.
  */
+@SmallTest
 public class TabWidgetTest extends ActivityInstrumentationTestCase2<TabHostCtsActivity> {
     private Activity mActivity;
 
@@ -53,6 +58,76 @@
         new TabWidget(mActivity, null, 0);
     }
 
+    public void testConstructorWithStyle() {
+        TabWidget tabWidget = new TabWidget(mActivity, null, 0, R.style.TabWidgetCustomStyle);
+
+        assertFalse(tabWidget.isStripEnabled());
+
+        Drawable leftStripDrawable = tabWidget.getLeftStripDrawable();
+        assertNotNull(leftStripDrawable);
+        TestUtils.assertAllPixelsOfColor("Left strip green", leftStripDrawable,
+                leftStripDrawable.getIntrinsicWidth(), leftStripDrawable.getIntrinsicHeight(),
+                true, 0xFF00FF00, 1, false);
+
+        Drawable rightStripDrawable = tabWidget.getRightStripDrawable();
+        assertNotNull(rightStripDrawable);
+        TestUtils.assertAllPixelsOfColor("Right strip red", rightStripDrawable,
+                rightStripDrawable.getIntrinsicWidth(), rightStripDrawable.getIntrinsicHeight(),
+                true, 0xFFFF0000, 1, false);
+    }
+
+    public void testInflateFromXml() {
+        LayoutInflater inflater = LayoutInflater.from(mActivity);
+        TabWidget tabWidget = (TabWidget) inflater.inflate(R.layout.tabhost_custom, null, false);
+
+        assertFalse(tabWidget.isStripEnabled());
+
+        Drawable leftStripDrawable = tabWidget.getLeftStripDrawable();
+        assertNotNull(leftStripDrawable);
+        TestUtils.assertAllPixelsOfColor("Left strip red", leftStripDrawable,
+                leftStripDrawable.getIntrinsicWidth(), leftStripDrawable.getIntrinsicHeight(),
+                true, 0xFFFF0000, 1, false);
+
+        Drawable rightStripDrawable = tabWidget.getRightStripDrawable();
+        assertNotNull(rightStripDrawable);
+        TestUtils.assertAllPixelsOfColor("Right strip green", rightStripDrawable,
+                rightStripDrawable.getIntrinsicWidth(), rightStripDrawable.getIntrinsicHeight(),
+                true, 0xFF00FF00, 1, false);
+    }
+
+    @UiThreadTest
+    public void testTabCount() {
+        TabHostCtsActivity activity = getActivity();
+        TabWidget tabWidget = activity.getTabWidget();
+
+        // We have one tab added in onCreate() of our activity
+        assertEquals(1, tabWidget.getTabCount());
+
+        for (int i = 1; i < 10; i++) {
+            tabWidget.addView(new TextView(mActivity));
+            assertEquals(i + 1, tabWidget.getTabCount());
+        }
+    }
+
+    @UiThreadTest
+    public void testTabViews() {
+        TabHostCtsActivity activity = getActivity();
+        TabWidget tabWidget = activity.getTabWidget();
+
+        // We have one tab added in onCreate() of our activity. We "reach" into the default tab
+        // indicator layout in the same way we do in TabHost_TabSpecTest tests.
+        TextView tab0 = (TextView) tabWidget.getChildTabViewAt(0).findViewById(android.R.id.title);
+        assertNotNull(tab0);
+        assertEquals(TabHostCtsActivity.INITIAL_TAB_LABEL, tab0.getText());
+
+        for (int i = 1; i < 10; i++) {
+            TextView toAdd = new TextView(mActivity);
+            toAdd.setText("Tab #" + i);
+            tabWidget.addView(toAdd);
+            assertEquals(toAdd, tabWidget.getChildTabViewAt(i));
+        }
+    }
+
     public void testChildDrawableStateChanged() {
         MockTabWidget mockTabWidget = new MockTabWidget(mActivity);
         TextView tv0 = new TextView(mActivity);
@@ -138,8 +213,11 @@
         }
     }
 
+    @UiThreadTest
     public void testSetEnabled() {
-        TabWidget tabWidget = new TabWidget(mActivity);
+        TabHostCtsActivity activity = getActivity();
+        TabWidget tabWidget = activity.getTabWidget();
+
         tabWidget.addView(new TextView(mActivity));
         tabWidget.addView(new TextView(mActivity));
         assertTrue(tabWidget.isEnabled());
@@ -194,6 +272,78 @@
         }
     }
 
+    @UiThreadTest
+    public void testStripEnabled() {
+        TabHostCtsActivity activity = getActivity();
+        TabWidget tabWidget = activity.getTabWidget();
+
+        tabWidget.setStripEnabled(true);
+        assertTrue(tabWidget.isStripEnabled());
+
+        tabWidget.setStripEnabled(false);
+        assertFalse(tabWidget.isStripEnabled());
+    }
+
+    @UiThreadTest
+    public void testStripDrawables() {
+        TabHostCtsActivity activity = getActivity();
+        TabWidget tabWidget = activity.getTabWidget();
+
+        // Test setting left strip drawable
+        tabWidget.setLeftStripDrawable(R.drawable.icon_green);
+        Drawable leftStripDrawable = tabWidget.getLeftStripDrawable();
+        assertNotNull(leftStripDrawable);
+        TestUtils.assertAllPixelsOfColor("Left strip green", leftStripDrawable,
+                leftStripDrawable.getIntrinsicWidth(), leftStripDrawable.getIntrinsicHeight(),
+                true, 0xFF00FF00, 1, false);
+
+        tabWidget.setLeftStripDrawable(activity.getResources().getDrawable(
+                R.drawable.icon_red, null));
+        leftStripDrawable = tabWidget.getLeftStripDrawable();
+        assertNotNull(leftStripDrawable);
+        TestUtils.assertAllPixelsOfColor("Left strip red", leftStripDrawable,
+                leftStripDrawable.getIntrinsicWidth(), leftStripDrawable.getIntrinsicHeight(),
+                true, 0xFFFF0000, 1, false);
+
+        // Test setting right strip drawable
+        tabWidget.setRightStripDrawable(R.drawable.icon_red);
+        Drawable rightStripDrawable = tabWidget.getRightStripDrawable();
+        assertNotNull(rightStripDrawable);
+        TestUtils.assertAllPixelsOfColor("Right strip red", rightStripDrawable,
+                rightStripDrawable.getIntrinsicWidth(), rightStripDrawable.getIntrinsicHeight(),
+                true, 0xFFFF0000, 1, false);
+
+        tabWidget.setRightStripDrawable(activity.getResources().getDrawable(
+                R.drawable.icon_green, null));
+        rightStripDrawable = tabWidget.getRightStripDrawable();
+        assertNotNull(rightStripDrawable);
+        TestUtils.assertAllPixelsOfColor("Left strip green", rightStripDrawable,
+                rightStripDrawable.getIntrinsicWidth(), rightStripDrawable.getIntrinsicHeight(),
+                true, 0xFF00FF00, 1, false);
+    }
+
+    @UiThreadTest
+    public void testDividerDrawables() {
+        TabHostCtsActivity activity = getActivity();
+        TabWidget tabWidget = activity.getTabWidget();
+
+        tabWidget.setDividerDrawable(R.drawable.icon_blue);
+        Drawable dividerDrawable = tabWidget.getDividerDrawable();
+        assertNotNull(dividerDrawable);
+        TestUtils.assertAllPixelsOfColor("Divider blue", dividerDrawable,
+                dividerDrawable.getIntrinsicWidth(), dividerDrawable.getIntrinsicHeight(),
+                true, 0xFF0000FF, 1, false);
+
+        tabWidget.setDividerDrawable(activity.getResources().getDrawable(
+                R.drawable.icon_yellow, null));
+        dividerDrawable = tabWidget.getDividerDrawable();
+        assertNotNull(dividerDrawable);
+        TestUtils.assertAllPixelsOfColor("Divider yellow", dividerDrawable,
+                dividerDrawable.getIntrinsicWidth(), dividerDrawable.getIntrinsicHeight(),
+                true, 0xFFFFFF00, 1, false);
+
+    }
+
     public void testOnFocusChange() {
         // onFocusChange() is implementation details, do NOT test
     }
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index 406e079..a95e43d 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -16,14 +16,6 @@
 
 package android.widget.cts;
 
-import android.graphics.drawable.ColorDrawable;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.text.Html;
-import android.text.Spanned;
-import android.widget.cts.R;
-
-import org.xmlpull.v1.XmlPullParserException;
-
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.app.Instrumentation.ActivityMonitor;
@@ -42,6 +34,7 @@
 import android.graphics.RectF;
 import android.graphics.Typeface;
 import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
@@ -49,13 +42,16 @@
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.TouchUtils;
 import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.text.Editable;
+import android.text.Html;
 import android.text.InputFilter;
 import android.text.InputType;
 import android.text.Layout;
 import android.text.Selection;
 import android.text.Spannable;
 import android.text.SpannableString;
+import android.text.Spanned;
 import android.text.TextPaint;
 import android.text.TextUtils;
 import android.text.TextUtils.TruncateAt;
@@ -76,13 +72,14 @@
 import android.text.method.TimeKeyListener;
 import android.text.method.TransformationMethod;
 import android.text.style.URLSpan;
+import android.text.style.UnderlineSpan;
 import android.text.util.Linkify;
 import android.util.DisplayMetrics;
 import android.util.LocaleList;
 import android.util.TypedValue;
+import android.view.ActionMode;
 import android.view.ContextMenu;
 import android.view.ContextMenu.ContextMenuInfo;
-import android.view.ActionMode;
 import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.Menu;
@@ -105,6 +102,8 @@
 import android.widget.TextView.BufferType;
 import android.widget.TextView.OnEditorActionListener;
 
+import org.xmlpull.v1.XmlPullParserException;
+
 import java.io.IOException;
 import java.util.Locale;
 
@@ -824,6 +823,39 @@
         assertEquals(0, mTextView.getLineHeight());
     }
 
+    public void testSetElegantLineHeight() {
+        mTextView = findTextView(R.id.textview_text);
+        assertFalse(mTextView.getPaint().isElegantTextHeight());
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mTextView.setWidth(mTextView.getWidth() / 3);
+                mTextView.setPadding(1, 2, 3, 4);
+                mTextView.setGravity(Gravity.BOTTOM);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+
+        int oldHeight = mTextView.getHeight();
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mTextView.setElegantTextHeight(true);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+
+        assertTrue(mTextView.getPaint().isElegantTextHeight());
+        assertTrue(mTextView.getHeight() > oldHeight);
+
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mTextView.setElegantTextHeight(false);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+        assertFalse(mTextView.getPaint().isElegantTextHeight());
+        assertTrue(mTextView.getHeight() == oldHeight);
+    }
+
     public void testInstanceState() {
         // Do not test. Implementation details.
     }
@@ -2391,6 +2423,7 @@
 
     public void testSetIncludeFontPadding() {
         mTextView = findTextView(R.id.textview_text);
+        assertTrue(mTextView.getIncludeFontPadding());
         mActivity.runOnUiThread(new Runnable() {
             public void run() {
                 mTextView.setWidth(mTextView.getWidth() / 3);
@@ -2409,6 +2442,7 @@
         mInstrumentation.waitForIdleSync();
 
         assertTrue(mTextView.getHeight() < oldHeight);
+        assertFalse(mTextView.getIncludeFontPadding());
     }
 
     public void testScroll() {
@@ -3981,10 +4015,53 @@
                 mTextView.getText().toString());
 
         ExtractedText et = new ExtractedText();
+
+        // Update text and selection.
         et.text = "test";
+        et.selectionStart = 0;
+        et.selectionEnd = 2;
 
         mTextView.setExtractedText(et);
         assertEquals("test", mTextView.getText().toString());
+        assertEquals(0, mTextView.getSelectionStart());
+        assertEquals(2, mTextView.getSelectionEnd());
+
+        // Use partialStartOffset and partialEndOffset
+        et.partialStartOffset = 2;
+        et.partialEndOffset = 3;
+        et.text = "x";
+        et.selectionStart = 2;
+        et.selectionEnd = 3;
+
+        mTextView.setExtractedText(et);
+        assertEquals("text", mTextView.getText().toString());
+        assertEquals(2, mTextView.getSelectionStart());
+        assertEquals(3, mTextView.getSelectionEnd());
+
+        // Update text with spans.
+        final SpannableString ss = new SpannableString("ex");
+        ss.setSpan(new UnderlineSpan(), 0, 2, 0);
+        ss.setSpan(new URLSpan("ctstest://TextView/test"), 1, 2, 0);
+
+        et.text = ss;
+        et.partialStartOffset = 1;
+        et.partialEndOffset = 3;
+        mTextView.setExtractedText(et);
+
+        assertEquals("text", mTextView.getText().toString());
+        final Editable editable = mTextView.getEditableText();
+        final UnderlineSpan[] underlineSpans = mTextView.getEditableText().getSpans(
+                0, editable.length(), UnderlineSpan.class);
+        assertEquals(1, underlineSpans.length);
+        assertEquals(1, editable.getSpanStart(underlineSpans[0]));
+        assertEquals(3, editable.getSpanEnd(underlineSpans[0]));
+
+        final URLSpan[] urlSpans = mTextView.getEditableText().getSpans(
+                0, editable.length(), URLSpan.class);
+        assertEquals(1, urlSpans.length);
+        assertEquals(2, editable.getSpanStart(urlSpans[0]));
+        assertEquals(3, editable.getSpanEnd(urlSpans[0]));
+        assertEquals("ctstest://TextView/test", urlSpans[0].getURL());
     }
 
     public void testMoveCursorToVisibleOffset() throws Throwable {
diff --git a/tests/tests/widget/src/android/widget/cts/util/TestUtils.java b/tests/tests/widget/src/android/widget/cts/util/TestUtils.java
new file mode 100644
index 0000000..3b11d0e
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/util/TestUtils.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.cts.util;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.ColorInt;
+import android.support.annotation.NonNull;
+import android.util.Pair;
+import android.view.View;
+import android.view.ViewParent;
+import junit.framework.Assert;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TestUtils {
+    /**
+     * This method takes a view and returns a single bitmap that is the layered combination
+     * of background drawables of this view and all its ancestors. It can be used to abstract
+     * away the specific implementation of a view hierarchy that is not exposed via class APIs
+     * or a view hierarchy that depends on the platform version. Instead of hard-coded lookups
+     * of particular inner implementations of such a view hierarchy that can break during
+     * refactoring or on newer platform versions, calling this API returns a "combined" background
+     * of the view.
+     *
+     * For example, it is useful to get the combined background of a popup / dropdown without
+     * delving into the inner implementation details of how that popup is implemented on a
+     * particular platform version.
+     */
+    public static Bitmap getCombinedBackgroundBitmap(View view) {
+        final int bitmapWidth = view.getWidth();
+        final int bitmapHeight = view.getHeight();
+
+        // Create a bitmap
+        final Bitmap bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight,
+                Bitmap.Config.ARGB_8888);
+        // Create a canvas that wraps the bitmap
+        final Canvas canvas = new Canvas(bitmap);
+
+        // As the draw pass starts at the top of view hierarchy, our first step is to traverse
+        // the ancestor hierarchy of our view and collect a list of all ancestors with non-null
+        // and visible backgrounds. At each step we're keeping track of the combined offsets
+        // so that we can properly combine all of the visuals together in the next pass.
+        List<View> ancestorsWithBackgrounds = new ArrayList<>();
+        List<Pair<Integer, Integer>> ancestorOffsets = new ArrayList<>();
+        int offsetX = 0;
+        int offsetY = 0;
+        while (true) {
+            final Drawable backgroundDrawable = view.getBackground();
+            if ((backgroundDrawable != null) && backgroundDrawable.isVisible()) {
+                ancestorsWithBackgrounds.add(view);
+                ancestorOffsets.add(Pair.create(offsetX, offsetY));
+            }
+            // Go to the parent
+            ViewParent parent = view.getParent();
+            if (!(parent instanceof View)) {
+                // We're done traversing the ancestor chain
+                break;
+            }
+
+            // Update the offsets based on the location of current view in its parent's bounds
+            offsetX += view.getLeft();
+            offsetY += view.getTop();
+
+            view = (View) parent;
+        }
+
+        // Now we're going to iterate over the collected ancestors in reverse order (starting from
+        // the topmost ancestor) and draw their backgrounds into our combined bitmap. At each step
+        // we are respecting the offsets of our original view in the coordinate system of the
+        // currently drawn ancestor.
+        final int layerCount = ancestorsWithBackgrounds.size();
+        for (int i = layerCount - 1; i >= 0; i--) {
+            View ancestor = ancestorsWithBackgrounds.get(i);
+            Pair<Integer, Integer> offsets = ancestorOffsets.get(i);
+
+            canvas.translate(offsets.first, offsets.second);
+            ancestor.getBackground().draw(canvas);
+            canvas.translate(-offsets.first, -offsets.second);
+        }
+
+        return bitmap;
+    }
+
+    /**
+     * Checks whether all the pixels in the specified drawable are of the same specified color.
+     *
+     * In case there is a color mismatch, the behavior of this method depends on the
+     * <code>throwExceptionIfFails</code> parameter. If it is <code>true</code>, this method will
+     * throw an <code>Exception</code> describing the mismatch. Otherwise this method will call
+     * <code>Assert.fail</code> with detailed description of the mismatch.
+     */
+    public static void assertAllPixelsOfColor(String failMessagePrefix, @NonNull Drawable drawable,
+            int drawableWidth, int drawableHeight, boolean callSetBounds, @ColorInt int color,
+            int allowedComponentVariance, boolean throwExceptionIfFails) {
+            // Create a bitmap
+            Bitmap bitmap = Bitmap.createBitmap(drawableWidth, drawableHeight,
+                    Bitmap.Config.ARGB_8888);
+            // Create a canvas that wraps the bitmap
+            Canvas canvas = new Canvas(bitmap);
+            if (callSetBounds) {
+                // Configure the drawable to have bounds that match the passed size
+                drawable.setBounds(0, 0, drawableWidth, drawableHeight);
+            }
+            // And ask the drawable to draw itself to the canvas / bitmap
+            drawable.draw(canvas);
+
+        try {
+            assertAllPixelsOfColor(failMessagePrefix, bitmap, drawableWidth, drawableHeight, color,
+                    allowedComponentVariance, throwExceptionIfFails);
+        } finally {
+            bitmap.recycle();
+        }
+    }
+
+    /**
+     * Checks whether all the pixels in the specified bitmap are of the same specified color.
+     *
+     * In case there is a color mismatch, the behavior of this method depends on the
+     * <code>throwExceptionIfFails</code> parameter. If it is <code>true</code>, this method will
+     * throw an <code>Exception</code> describing the mismatch. Otherwise this method will call
+     * <code>Assert.fail</code> with detailed description of the mismatch.
+     */
+    public static void assertAllPixelsOfColor(String failMessagePrefix, @NonNull Bitmap bitmap,
+            int bitmapWidth, int bitmapHeight, @ColorInt int color,
+            int allowedComponentVariance, boolean throwExceptionIfFails) {
+            int[] rowPixels = new int[bitmapWidth];
+        for (int row = 0; row < bitmapHeight; row++) {
+            bitmap.getPixels(rowPixels, 0, bitmapWidth, 0, row, bitmapWidth, 1);
+            for (int column = 0; column < bitmapWidth; column++) {
+                int sourceAlpha = Color.alpha(rowPixels[column]);
+                int sourceRed = Color.red(rowPixels[column]);
+                int sourceGreen = Color.green(rowPixels[column]);
+                int sourceBlue = Color.blue(rowPixels[column]);
+
+                int expectedAlpha = Color.alpha(color);
+                int expectedRed = Color.red(color);
+                int expectedGreen = Color.green(color);
+                int expectedBlue = Color.blue(color);
+
+                int varianceAlpha = Math.abs(sourceAlpha - expectedAlpha);
+                int varianceRed = Math.abs(sourceRed - expectedRed);
+                int varianceGreen = Math.abs(sourceGreen - expectedGreen);
+                int varianceBlue = Math.abs(sourceBlue - expectedBlue);
+
+                boolean isColorMatch = (varianceAlpha <= allowedComponentVariance)
+                        && (varianceRed <= allowedComponentVariance)
+                        && (varianceGreen <= allowedComponentVariance)
+                        && (varianceBlue <= allowedComponentVariance);
+
+                if (!isColorMatch) {
+                    String mismatchDescription = failMessagePrefix
+                            + ": expected all drawable colors to be ["
+                            + expectedAlpha + "," + expectedRed + ","
+                            + expectedGreen + "," + expectedBlue
+                            + "] but at position (" + row + "," + column + ") out of ("
+                            + bitmapWidth + "," + bitmapHeight + ") found ["
+                            + sourceAlpha + "," + sourceRed + ","
+                            + sourceGreen + "," + sourceBlue + "]";
+                    if (throwExceptionIfFails) {
+                        throw new RuntimeException(mismatchDescription);
+                    } else {
+                        Assert.fail(mismatchDescription);
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/widget/src/android/widget/cts/util/ViewTestUtils.java b/tests/tests/widget/src/android/widget/cts/util/ViewTestUtils.java
index ca6c528..02ac28c 100644
--- a/tests/tests/widget/src/android/widget/cts/util/ViewTestUtils.java
+++ b/tests/tests/widget/src/android/widget/cts/util/ViewTestUtils.java
@@ -23,7 +23,7 @@
 import android.view.ViewTreeObserver;
 import android.view.ViewTreeObserver.OnDrawListener;
 
-import java.util.concurrent.Semaphore;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -41,34 +41,25 @@
      */
     public static void runOnMainAndDrawSync(Instrumentation instrumentation,
             final View view, final Runnable runner) {
-        final Semaphore token = new Semaphore(0);
-        final Runnable releaseToken = new Runnable() {
-            @Override
-            public void run() {
-                token.release();
-            }
-        };
+        final CountDownLatch latch = new CountDownLatch(1);
 
-        instrumentation.runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                final ViewTreeObserver observer = view.getViewTreeObserver();
-                final OnDrawListener listener = new OnDrawListener() {
-                    @Override
-                    public void onDraw() {
-                        observer.removeOnDrawListener(this);
-                        view.post(releaseToken);
-                    }
-                };
+        instrumentation.runOnMainSync(() -> {
+            final ViewTreeObserver observer = view.getViewTreeObserver();
+            final OnDrawListener listener = new OnDrawListener() {
+                @Override
+                public void onDraw() {
+                    observer.removeOnDrawListener(this);
+                    view.post(() -> latch.countDown());
+                }
+            };
 
-                observer.addOnDrawListener(listener);
-                runner.run();
-            }
+            observer.addOnDrawListener(listener);
+            runner.run();
         });
 
         try {
             Assert.assertTrue("Expected draw pass occurred within 5 seconds",
-                    token.tryAcquire(5, TimeUnit.SECONDS));
+                    latch.await(5, TimeUnit.SECONDS));
         } catch (InterruptedException e) {
             throw new RuntimeException(e);
         }
diff --git a/tests/vm/AndroidTest.xml b/tests/vm/AndroidTest.xml
index 2bac07b..fc1098b 100644
--- a/tests/vm/AndroidTest.xml
+++ b/tests/vm/AndroidTest.xml
@@ -20,5 +20,6 @@
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.vm.cts" />
+        <option name="runtime-hint" value="20m14s" />
     </test>
 </configuration>
diff --git a/tools/cts-tradefed/res/config/collect-tests-only.xml b/tools/cts-tradefed/res/config/collect-tests-only.xml
new file mode 100644
index 0000000..1c22b11
--- /dev/null
+++ b/tools/cts-tradefed/res/config/collect-tests-only.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs CTS from a pre-existing CTS installation">
+
+    <include name="cts" />
+
+    <!-- This tells cts-tradefed and the server what the plan name is, reports that have this plan
+         name should not be accepted, as it doesn't actually run the tests it simply marks all of
+         them as passed.
+         Obviously no one would modify the report before uploadng to falsify this
+         information, as that would be dishonest, and dishonesty kills kittens :'( -->
+    <option name="compatibility:plan" value="collect-tests-only" />
+
+    <!-- Tell all AndroidJUnitTests to only list the tests -->
+    <option name="compatibility:test-arg" value="com.android.tradefed.testtype.AndroidJUnitTest:collect-tests-only:true" />
+
+    <!-- Tell all GTests to only list the tests -->
+    <option name="compatibility:test-arg" value="com.android.tradefed.testtype.GTest:collect-tests-only:true" />
+
+    <!-- Tell all HostTests to only list the tests -->
+    <option name="compatibility:test-arg" value="com.android.tradefed.testtype.HostTest:collect-tests-only:true" />
+
+</configuration>
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
new file mode 100644
index 0000000..4d656b1
--- /dev/null
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -0,0 +1,218 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Configuration with CTS known failures" >
+    <!-- <option name="compatibility:exclude-filter" value="MODULE_NAME" /> Excludes whole module -->
+    <!-- <option name="compatibility:exclude-filter" value="MODULE_NAME PACKAGE_NAME" /> Excludes whole package -->
+    <!-- <option name="compatibility:exclude-filter" value="MODULE_NAME PACKAGE_NAME.CLASS_NAME" /> Excludes whole class -->
+    <!-- <option name="compatibility:exclude-filter" value="MODULE_NAME PACKAGE_NAME.CLASS_NAME#TEST_NAME" /> Excludes individual test -->
+
+    <!-- b/17595050 -->
+    <option name="compatibility:exclude-filter" value="CtsAccessibilityServiceTestCases android.accessibilityservice.cts.AccessibilityTextTraversalTest#testActionNextAndPreviousAtGranularityPageOverText" />
+    <option name="compatibility:exclude-filter" value="CtsAccessibilityServiceTestCases android.accessibilityservice.cts.AccessibilityTextTraversalTest#testActionNextAndPreviousAtGranularityPageOverTextExtend" />
+
+    <!-- b/17508787 -->
+    <option name="compatibility:exclude-filter" value="CtsAdminTestCases android.admin.cts.DevicePolicyManagerTest#testUninstallAllUserCaCerts_failIfNotProfileOwner" />
+
+    <!-- b/23776083 -->
+    <option name="compatibility:exclude-filter" value="CtsAlarmClockTestCases android.alarmclock.cts.DismissAlarmTest#testAll" />
+    <option name="compatibility:exclude-filter" value="CtsAlarmClockTestCases android.alarmclock.cts.SetAlarmTest#testAll" />
+    <option name="compatibility:exclude-filter" value="CtsAlarmClockTestCases android.alarmclock.cts.SnoozeAlarmTest#testAll" />
+
+    <!-- b/17993121 -->
+    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testAppWidgetProviderCallbacks" />
+    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testBindAppWidget" />
+    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testCollectionWidgets" />
+    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testDeleteHost" />
+    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testDeleteHosts" />
+    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testGetAppWidgetIds" />
+    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testGetAppWidgetInfo" />
+    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testGetAppWidgetOptions" />
+    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testPartiallyUpdateAppWidgetViaWidgetId" />
+    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testPartiallyUpdateAppWidgetViaWidgetIds" />
+    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testTwoAppWidgetProviderCallbacks" />
+    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testUpdateAppWidgetViaComponentName" />
+    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testUpdateAppWidgetViaWidgetId" />
+    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testUpdateAppWidgetViaWidgetIds" />
+
+    <!-- b/21668302 -->
+    <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.AssistantContentViewTest#testAssistantContentViewDimens" />
+    <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.ExtraAssistDataTest#testAssistContentAndAssistData" />
+    <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.FocusChangeTest#testLayerCausesUnderlyingActivityToLoseFocus" />
+    <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.LargeViewHierarchyTest#testTextView" />
+    <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.ScreenshotTest#testBlueScreenshot" />
+    <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.ScreenshotTest#testGreenScreenshot" />
+    <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.ScreenshotTest#testRedScreenshot" />
+    <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.TextViewTest#testTextView" />
+    <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.WebViewTest#testWebView" />
+
+    <!-- b/23776099 -->
+    <option name="compatibility:exclude-filter" value="CtsCallLogTestCases android.calllog.cts.CallLogBackupTest#testSingleCallBackup" />
+
+    <!-- b/17530117 -->
+    <option name="compatibility:exclude-filter" value="CtsCameraTestCases android.hardware.camera2.cts.AllocationTest#testBlackWhite" />
+    <option name="compatibility:exclude-filter" value="CtsCameraTestCases android.hardware.camera2.cts.AllocationTest#testParamSensitivity" />
+    <!-- b/17989532 -->
+    <option name="compatibility:exclude-filter" value="CtsCameraTestCases android.hardware.camera2.cts.SurfaceViewPreviewTest#testPreparePerformance" />
+    <!-- b/23008511 -->
+    <option name="compatibility:exclude-filter" value="CtsCameraTestCases android.hardware.cts.CameraTest#testPreviewFpsRange" />
+
+    <option name="compatibility:exclude-filter" value="CtsCarTestCases" />
+
+    <!-- b/27578806 -->
+    <option name="compatibility:exclude-filter" value="CtsCppToolsTestCases com.android.cts.cpptools.RunAsHostTest#testRunAs" />
+
+    <!-- b/23776893 -->
+    <option name="compatibility:exclude-filter" value="CtsDumpsysHostTestCases android.dumpsys.cts.DumpsysHostTest#testBatterystatsOutput" />
+    <option name="compatibility:exclude-filter" value="CtsDumpsysHostTestCases android.dumpsys.cts.DumpsysHostTest#testGfxinfoFramestats" />
+
+    <!-- b/22922206 b/27534791 -->
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SensorBatchingTests#testAccelerometer_50hz_batching" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SensorBatchingTests#testAccelerometer_fastest_batching" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SensorBatchingTests#testGravity_50hz_batching" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SensorBatchingTests#testGravity_fastest_batching" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SensorBatchingTests#testGyroscope_50hz_batching" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SensorBatchingTests#testGyroscope_50hz_flush" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SensorBatchingTests#testGyroscope_fastest_batching" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SensorBatchingTests#testLinearAcceleration_50hz_batching" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SensorBatchingTests#testLinearAcceleration_fastest_batching" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SensorBatchingTests#testMagneticField_50hz_batching" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SensorBatchingTests#testMagneticField_fastest_batching" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SensorBatchingTests#testMagneticFieldUncalibrated_50hz_batching" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SensorBatchingTests#testMagneticFieldUncalibrated_fastest_batching" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SensorBatchingTests#testPressure_50hz_batching" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SensorBatchingTests#testPressure_fastest_batching" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SensorBatchingTests#testRotationVector_50hz_batching" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SensorBatchingTests#testRotationVector_50hz_flush" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SensorBatchingTests#testRotationVector_fastest_batching" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SensorIntegrationTests#testSensorsMovingRates" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SensorIntegrationTests#testSensorsWithSeveralClients" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SensorTest#testBatchAndFlush" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SensorTest#testSensorTimeStamps" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SingleSensorTests#testGyroscope_15hz" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SingleSensorTests#testGyroscope_1hz" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SingleSensorTests#testMagneticField_1hz" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SingleSensorTests#testMagneticField_50hz" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SingleSensorTests#testMagneticFieldUncalibrated_200hz" />
+    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.SingleSensorTests#testOrientation_5hz" />
+
+    <!-- b/16720689 -->
+    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowDebuggerLaunchTest#testDebuggerLaunch001" />
+    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowDebuggerLaunchTest#testDebuggerLaunch002" />
+    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowDebuggerLaunchTest#testDebuggerLaunch003" />
+    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowDebuggerLaunchTest#testDebuggerLaunch004" />
+    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowLaunchDebugger001#testDebugger002" />
+    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowLaunchDebugger002#testDebugger" />
+    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.Events.ClassUnloadTest#testClassUnloadEvent" />
+    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.Events.MonitorContendedEnteredTest#testMonitorContendedEnteredForClassMatch" />
+    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.Events.MonitorContendedEnterTest#testMonitorContendedEnterForClassMatch" />
+    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitedTest#testMonitorWaitedForClassExclude" />
+    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitedTest#testMonitorWaitedForClassMatchExact" />
+    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitedTest#testMonitorWaitedForClassMatchFirst" />
+    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitedTest#testMonitorWaitedForClassMatchSecond" />
+    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitedTest#testMonitorWaitedForClassOnly" />
+    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitTest#testMonitorWaitForClassExclude" />
+    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitTest#testMonitorWaitForClassMatchExact" />
+    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitTest#testMonitorWaitForClassMatchFirst" />
+    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitTest#testMonitorWaitForClassMatchSecond" />
+    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitTest#testMonitorWaitForClassOnly" />
+    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.ReferenceType.ClassFileVersionTest#testClassFileVersion001" />
+    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.ReferenceType.NestedTypesTest#testNestedTypes001" />
+    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.ThreadReference.StopTest#testStop001" />
+    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.VirtualMachine.HoldEventsTest#testHoldEvents001" />
+    <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.VirtualMachine.ReleaseEventsTest#testReleaseEvents001" />
+
+    <!-- b/18117279 b/21262226 b/23144425 -->
+    <option name="compatibility:exclude-filter" value="CtsJobSchedulerTestCases android.jobscheduler.cts.ConnectivityConstraintTest#testConnectivityConstraintExecutes_withMobile" />
+    <option name="compatibility:exclude-filter" value="CtsJobSchedulerTestCases android.jobscheduler.cts.ConnectivityConstraintTest#testConnectivityConstraintExecutes_withWifi" />
+    <option name="compatibility:exclude-filter" value="CtsJobSchedulerTestCases android.jobscheduler.cts.ConnectivityConstraintTest#testUnmeteredConstraintExecutes_withWifi" />
+    <option name="compatibility:exclude-filter" value="CtsJobSchedulerTestCases android.jobscheduler.cts.ConnectivityConstraintTest#testUnmeteredConstraintFails_withMobile" />
+    <option name="compatibility:exclude-filter" value="CtsJobSchedulerTestCases android.jobscheduler.cts.TimingConstraintsTest#testJobParameters_unexpiredDeadline" />
+
+    <!-- b/25850508 -->
+    <option name="compatibility:exclude-filter" value="CtsMediaStressTestCases android.mediastress.cts.preconditions.MediaPreparerTest#testCopyMediaFiles" />
+    <option name="compatibility:exclude-filter" value="CtsMediaStressTestCases android.mediastress.cts.preconditions.MediaPreparerTest#testGetMaxVideoPlaybackResolutionFound" />
+    <option name="compatibility:exclude-filter" value="CtsMediaStressTestCases android.mediastress.cts.preconditions.MediaPreparerTest#testGetMaxVideoPlaybackResolutionNotFound" />
+    <option name="compatibility:exclude-filter" value="CtsMediaStressTestCases android.mediastress.cts.preconditions.MediaPreparerTest#testMediaFilesExistOnDeviceFalse" />
+    <option name="compatibility:exclude-filter" value="CtsMediaStressTestCases android.mediastress.cts.preconditions.MediaPreparerTest#testMediaFilesExistOnDeviceTrue" />
+    <option name="compatibility:exclude-filter" value="CtsMediaStressTestCases android.mediastress.cts.preconditions.MediaPreparerTest#testSetMountPoint" />
+    <option name="compatibility:exclude-filter" value="CtsMediaStressTestCases android.mediastress.cts.preconditions.MediaPreparerTest#testSkipMediaDownload" />
+
+    <!-- b/17144778 -->
+    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ImageReaderDecoderTest#testHwAVCDecode360pForFlexibleYuv" />
+    <!-- b/23827982 -->
+    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogH264FlexArbitraryW" />
+    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogH264SurfArbitraryW" />
+
+    <!-- b/25651805 -->
+    <option name="compatibility:exclude-filter" value="CtsNetTestCases android.net.cts.ConnectivityManagerTest#testRestrictedNetworks" />
+    <!-- b/18682315 -->
+    <option name="compatibility:exclude-filter" value="CtsNetTestCases android.net.cts.SSLCertificateSocketFactoryTest#testCreateSocket" />
+    <option name="compatibility:exclude-filter" value="CtsNetTestCases android.net.cts.SSLCertificateSocketFactoryTest#test_createSocket_bind" />
+    <option name="compatibility:exclude-filter" value="CtsNetTestCases android.net.cts.SSLCertificateSocketFactoryTest#test_createSocket_simple" />
+    <option name="compatibility:exclude-filter" value="CtsNetTestCases android.net.cts.SSLCertificateSocketFactoryTest#test_createSocket_wrapping" />
+
+    <!-- b/17394321 -->
+    <option name="compatibility:exclude-filter" value="CtsOpenGlPerfTestCases android.openglperf.cts.GlAppSwitchTest#testGlActivitySwitchingFast" />
+    <option name="compatibility:exclude-filter" value="CtsOpenGlPerfTestCases android.openglperf.cts.GlAppSwitchTest#testGlActivitySwitchingSlow" />
+
+    <!-- b/18091590 -->
+    <option name="compatibility:exclude-filter" value="CtsOpenGlPerfTestCases android.openglperf.cts.GlVboPerfTest#testVboWithVaryingIndexBufferNumbers" />
+
+    <!-- b/23192492 -->
+    <option name="compatibility:exclude-filter" value="CtsPermission2TestCases android.permission2.cts.ProtectedBroadcastsTest#testSendProtectedBroadcasts" />
+
+    <option name="compatibility:exclude-filter" value="CtsSampleDeviceTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsSampleHostTestCases" />
+
+    <!-- b/18461670 -->
+    <option name="compatibility:exclude-filter" value="CtsSecurityTestCases android.security.cts.AudioPolicyBinderTest#test_getStreamVolumeLeak" />
+    <option name="compatibility:exclude-filter" value="CtsSecurityTestCases android.security.cts.AudioPolicyBinderTest#test_isStreamActive" />
+    <option name="compatibility:exclude-filter" value="CtsSecurityTestCases android.security.cts.AudioPolicyBinderTest#test_isStreamActiveRemotely" />
+    <option name="compatibility:exclude-filter" value="CtsSecurityTestCases android.security.cts.AudioPolicyBinderTest#test_startAudioSource" />
+    <option name="compatibility:exclude-filter" value="CtsSecurityTestCases android.security.cts.AudioPolicyBinderTest#test_startOutput" />
+    <option name="compatibility:exclude-filter" value="CtsSecurityTestCases android.security.cts.AudioPolicyBinderTest#test_stopOutput" />
+    <!-- b/27218502 -->
+    <option name="compatibility:exclude-filter" value="CtsSecurityTestCases android.security.cts.MediaCryptoTest#testMediaCryptoClearKey" />
+    <option name="compatibility:exclude-filter" value="CtsSecurityTestCases android.security.cts.MediaCryptoTest#testMediaCryptoWidevine" />
+
+    <!-- b/26150806 -->
+    <option name="compatibility:exclude-filter" value="CtsSignatureTestCases android.signature.cts.tests" />
+
+    <!-- b/23427621 -->
+    <option name="compatibility:exclude-filter" value="CtsSystemUiTestCases android.systemui.cts.LightStatusBarTests#testLightStatusBarIcons" />
+
+    <!-- b/23604254 -->
+    <option name="compatibility:exclude-filter" value="CtsTelecomTestCases android.telecom.cts.ExtendedInCallServiceTest#testAddNewOutgoingCallAndThenDisconnect" />
+    <option name="compatibility:exclude-filter" value="CtsTelecomTestCases android.telecom.cts.RemoteConferenceTest#testRemoteConferenceCallbacks_ConferenceableConnections" />
+
+    <!-- b/23979591 -->
+    <option name="compatibility:exclude-filter" value="CtsTelephonyTestCases android.telephony.cts.CellInfoTest#testCellInfo" />
+
+    <!-- b/23779020 -->
+    <option name="compatibility:exclude-filter" value="CtsTransitionTestCases android.transition.cts.ChangeScrollTest#testChangeScroll" />
+
+    <!-- b/17536113 -->
+    <option name="compatibility:exclude-filter" value="CtsUsageStatsTestCases android.app.usage.cts.UsageStatsTest#testNoAccessSilentlyFails" />
+    <option name="compatibility:exclude-filter" value="CtsUsageStatsTestCases android.app.usage.cts.UsageStatsTest#testOrderedActivityLaunchSequenceInEventLog" />
+    <option name="compatibility:exclude-filter" value="CtsUsageStatsTestCases android.app.usage.cts.UsageStatsTest#testPackageUsageStatsIntervals" />
+    <option name="compatibility:exclude-filter" value="CtsUsageStatsTestCases android.app.usage.cts.UsageStatsTest#testUsageEventsParceling" />
+
+    <!-- b/23238984 -->
+    <option name="compatibility:exclude-filter" value="CtsVoiceSettingsTestCases android.voicesettings.cts.ZenModeTest#testAll" />
+
+    <!-- b/26235244 -->
+    <option name="compatibility:exclude-filter" value="android.util.cts.EventLogTest#testWriteEventWithOversizeValue" />
+</configuration>
diff --git a/tools/cts-tradefed/res/config/cts-preconditions.xml b/tools/cts-tradefed/res/config/cts-preconditions.xml
index e01df10..efe8e3f 100644
--- a/tools/cts-tradefed/res/config/cts-preconditions.xml
+++ b/tools/cts-tradefed/res/config/cts-preconditions.xml
@@ -38,6 +38,7 @@
 
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
         <option name="run-command" value="rm -rf /sdcard/device-info-files" />
+        <option name="run-command" value="rm -rf /sdcard/report-log-files" />
     </target_preparer>
 
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DeviceInfoCollector">
@@ -47,4 +48,9 @@
         <option name="dest-dir" value="device-info-files/"/>
     </target_preparer>
 
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ReportLogCollector">
+        <option name="src-dir" value="/sdcard/report-log-files/"/>
+        <option name="dest-dir" value="report-log-files/"/>
+    </target_preparer>
+
 </configuration>
diff --git a/tools/cts-tradefed/res/config/cts.xml b/tools/cts-tradefed/res/config/cts.xml
index 8104570..2eb0c3e 100644
--- a/tools/cts-tradefed/res/config/cts.xml
+++ b/tools/cts-tradefed/res/config/cts.xml
@@ -17,18 +17,12 @@
 
     <include name="everything" />
     <include name="cts-preconditions" />
+    <include name="cts-known-failures" />
 
     <option name="compatibility:plan" value="cts" />
 
     <option name="enable-root" value="false" />
 
-    <!-- Exclude sample test cases -->
-    <option name="compatibility:exclude-filter" value="CtsSampleDeviceTestCases" />
-    <option name="compatibility:exclude-filter" value="CtsSampleHostTestCases" />
-
-    <!-- Exclude automotive only test cases for now -->
-    <option name="compatibility:exclude-filter" value="CtsAutomotiveTestCases" />
-
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.PropertyCheck">
         <option name="property-name" value="ro.build.type" />
         <option name="expected-value" value="user"/> <!-- Device should have user build -->
@@ -41,4 +35,5 @@
         <option name="throw-error" value="false"/> <!-- Only print warning if not en-US -->
     </target_preparer>
     <template-include name="reporters" default="basic-reporters" />
+
 </configuration>
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java
index b75a67a..b68073d 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java
@@ -316,10 +316,6 @@
         // mName means 'apk file name' for instrumentation tests
         instrTest.addInstallApk(String.format("%s.apk", mName), mAppNameSpace);
         mDigest = generateDigest(testCaseDir, String.format("%s.apk", mName));
-        if (mTests.size() > 1000) {
-            // TODO: hack, large test suites can take longer to collect tests, increase timeout
-            instrTest.setCollectsTestsShellTimeout(10 * 60 * 1000);
-        }
         return instrTest;
     }
 
diff --git a/tools/utils/buildCts.py b/tools/utils/buildCts.py
index 9923fcd..f983b15 100755
--- a/tools/utils/buildCts.py
+++ b/tools/utils/buildCts.py
@@ -118,20 +118,20 @@
     packages.sort()
 
     plan = tools.TestPlan(packages)
-    plan.Exclude('android\.car.*')
+    plan.Exclude('android\.car')
     plan.Exclude('android\.performance.*')
     self.__WritePlan(plan, 'CTS')
     self.__WritePlan(plan, 'CTS-TF')
 
     plan = tools.TestPlan(packages)
-    plan.Exclude('android\.car.*')
+    plan.Exclude('android\.car')
     plan.Exclude('android\.performance.*')
     plan.Exclude('android\.media\.cts\.StreamingMediaPlayerTest.*')
     # Test plan to not include media streaming tests
     self.__WritePlan(plan, 'CTS-No-Media-Stream')
 
     plan = tools.TestPlan(packages)
-    plan.Exclude('android\.car.*')
+    plan.Exclude('android\.car')
     plan.Exclude('android\.performance.*')
     self.__WritePlan(plan, 'SDK')
 
@@ -140,19 +140,16 @@
     self.__WritePlan(plan, 'Android')
 
     plan = tools.TestPlan(packages)
-    plan.Exclude('android\.car.*')
     plan.Include(r'android\.core\.tests.*')
     plan.Exclude(r'android\.core\.tests\.libcore\.package\.harmony*')
     self.__WritePlan(plan, 'Java')
 
     # TODO: remove this once the tests are fixed and merged into Java plan above.
     plan = tools.TestPlan(packages)
-    plan.Exclude('android\.car.*')
     plan.Include(r'android\.core\.tests\.libcore\.package\.harmony*')
     self.__WritePlan(plan, 'Harmony')
 
     plan = tools.TestPlan(packages)
-    plan.Exclude('android\.car.*')
     plan.Include(r'android\.core\.vm-tests-tf')
     self.__WritePlan(plan, 'VM-TF')
 
@@ -174,7 +171,7 @@
     plan.Include('android\.telephony')
     plan.Include('android\.nativemedia.*')
     plan.Include('com\.android\.cts\..*')#TODO(stuartscott): Should PDK have all these?
-    plan.Exclude('android\.car.*')
+    plan.Exclude('android\.car')
     self.__WritePlan(plan, 'PDK')
 
     temporarily_known_failure_tests = BuildCtsTemporarilyKnownFailureList();
@@ -183,7 +180,7 @@
 
     # CTS Stable plan
     plan = tools.TestPlan(packages)
-    plan.Exclude('android\.car.*')
+    plan.Exclude('android\.car')
     plan.Exclude(r'android\.browser')
     for package, test_list in flaky_tests.iteritems():
       plan.ExcludeTests(package, test_list)
@@ -198,7 +195,6 @@
     for package, test_list in flaky_tests.iteritems():
       plan.Include(package+'$')
       plan.IncludeTests(package, test_list)
-    plan.Exclude('android\.car.*')
     self.__WritePlan(plan, 'CTS-flaky')
 
     small_tests = BuildAospSmallSizeTestList()
@@ -211,7 +207,6 @@
     for package, test_list in small_tests.iteritems():
       plan.Include(package+'$')
     plan.Exclude(r'android\.browser')
-    plan.Exclude('android\.car.*')
     for package, test_list in flaky_tests.iteritems():
       plan.ExcludeTests(package, test_list)
     for package, test_list in releasekey_tests.iteritems():
@@ -229,7 +224,6 @@
       plan.ExcludeTests(package, test_list)
     for package, test_list in releasekey_tests.iteritems():
       plan.ExcludeTests(package, test_list)
-    plan.Exclude('android\.car.*')
     self.__WritePlan(plan, 'CTS-kitkat-medium')
     self.__WritePlan(plan, 'CTS-public-medium')
 
@@ -326,7 +320,7 @@
     plan.Exclude(r'android\.view$')
     plan.Exclude(r'android\.mediastress$')
     plan.Exclude(r'android\.browser')
-    plan.Exclude('android\.car.*')
+    plan.Exclude('android\.car')
     for package, test_list in flaky_tests.iteritems():
       plan.ExcludeTests(package, test_list)
     for package, test_list in releasekey_tests.iteritems():
diff --git a/tools/vm-tests-tf/Android.mk b/tools/vm-tests-tf/Android.mk
index 1704d84..ef6aa84 100644
--- a/tools/vm-tests-tf/Android.mk
+++ b/tools/vm-tests-tf/Android.mk
@@ -44,8 +44,7 @@
 LOCAL_MODULE_CLASS := JAVA_LIBRARIES
 LOCAL_MODULE_TAGS := optional
 
-LOCAL_JAVA_LIBRARIES := dx dasm cfassembler junit
-LOCAL_JAVA_LIBRARIES += jack
+LOCAL_JAVA_LIBRARIES := dx dasm cfassembler junit jsr305lib
 
 LOCAL_CLASSPATH := $(HOST_JDK_TOOLS_JAR)