Merge "Fix MixedProfileOwnerTest#testApplicationRestrictions" into nyc-dev
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 d7dc418..ee98618 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -1520,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>
@@ -1624,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/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/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/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 3b86b65..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,16 +17,18 @@
 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 {
@@ -36,6 +38,8 @@
             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 {
@@ -46,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/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/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java
index c2f17c53..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,43 +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_deniesOnceButAllowsAskingAgain() throws Exception {
-        runDeviceTests(CLIENT_PKG, ".DocumentsClientTest",
-                "testOpenExternalDirectory_deniesOnceButAllowsAskingAgain");
-    }
-
-    public void testOpenExternalDirectory_deniesOnceForAll() throws Exception {
-        runDeviceTests(CLIENT_PKG, ".DocumentsClientTest",
-                "testOpenExternalDirectory_deniesOnceForAll");
-    }
-
-    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");
     }
@@ -136,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/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java
index 6c9108d..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,162 +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 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 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);
-    }
-
-    public void testOpenExternalDirectory_deniesOnceButAllowsAskingAgain() 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 testOpenExternalDirectory_deniesOnceForAll() 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;
-    }
-
     public void testGetContent() throws Exception {
         if (!supportedHardware()) return;
 
@@ -660,147 +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 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/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/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/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/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index 6a22a5c..5fe6fb7 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,14 @@
         }
     }
 
+    // Execute HardwarePropertiesManagerTest as a device owner.
+    public void testHardwarePropertiesManagerAsDeviceOwner() throws Exception {
+        if (!mHasFeature)
+            return;
+
+        executeDeviceTestMethod(".HardwarePropertiesManagerTest", "testHardwarePropertiesManager");
+    }
+
     private void executeDeviceOwnerTest(String testClassName) throws Exception {
         if (!mHasFeature) {
             return;
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/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/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/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/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index 2d1443a..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",
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/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/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/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/car/src/android/car/cts/CarPackageManagerTest.java b/tests/tests/car/src/android/car/cts/CarPackageManagerTest.java
index 2865710..dc5fe0a 100644
--- a/tests/tests/car/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/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/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_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_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_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_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_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_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_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_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/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
index 0dcff12..4b01916 100644
--- a/tests/tests/graphics/src/android/graphics/cts/OutlineTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/OutlineTest.java
@@ -20,16 +20,19 @@
 import android.graphics.Path;
 import android.graphics.Rect;
 import android.test.suitebuilder.annotation.SmallTest;
-import junit.framework.TestCase;
 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 extends TestCase {
+public class OutlineTest {
     @Test
     public void testDefaults() {
         Outline outline = new Outline();
 
-        assertEquals(0.0f, outline.getAlpha());
+        assertEquals(0.0f, outline.getAlpha(), 0.0f);
         assertTrue(outline.isEmpty());
         Rect outRect = new Rect();
         assertFalse(outline.getRect(outRect));
@@ -41,19 +44,19 @@
         Outline outline = new Outline();
 
         outline.setAlpha(1.0f);
-        assertEquals(1.0f, outline.getAlpha());
+        assertEquals(1.0f, outline.getAlpha(), 0.0f);
 
         outline.setAlpha(0.0f);
-        assertEquals(0.0f, outline.getAlpha());
+        assertEquals(0.0f, outline.getAlpha(), 0.0f);
 
         outline.setAlpha(0.45f);
-        assertEquals(0.45f, outline.getAlpha());
+        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());
+        assertEquals(4f, outline.getAlpha(), 0.0f);
         outline.setAlpha(-30f);
-        assertEquals(-30f, outline.getAlpha());
+        assertEquals(-30f, outline.getAlpha(), 0.0f);
     }
 
     @Test
@@ -101,14 +104,14 @@
         assertFalse(outline.isEmpty());
         assertTrue(outline.getRect(outRect));
         assertEquals(new Rect(10, 10, 20, 20), outRect);
-        assertEquals(5f, outline.getRadius());
+        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());
+        assertEquals(4f, outline.getRadius(), 0.0f);
         assertTrue(outline.canClip());
     }
 
@@ -154,12 +157,12 @@
 
         Rect outRect = new Rect();
         outline.setRoundRect(15, 10, 45, 40, 30.0f);
-        assertEquals(30.0f, outline.getRadius());
+        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());
+        assertEquals(0.0f, outline.getRadius(), 0.0f);
         assertTrue(outline.getRect(outRect));
         assertEquals(new Rect(5, 10, 15, 20), outRect);
 
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/VectorDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java
index ac1d9b3..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
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 b92e754..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
@@ -49,16 +49,10 @@
   name: "android.icu.dev.test.format.PluralRulesTest#testOverUnderflow",
   bug: "27566754"
 },
-// 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.format.NumberFormatTest#TestDataDrivenJDK",
-  ],
-  result: "SUCCESS"
+  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",
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/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/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..f3d7983
--- /dev/null
+++ b/tests/tests/media/libndkaudio/Android.mk
@@ -0,0 +1,57 @@
+# 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
+
+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..9df1658
--- /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..4d17a18
--- /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..9026c60
--- /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* 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..0363d2c
--- /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* TAG = "AudioSource";

+

+AudioSource::AudioSource(int numChannels)

+ : numChannels_(numChannels),

+   numBuffFrames_(SystemParams::getNumBufferFrames()),

+   lastReadSize_(0)

+{}

+

+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..bd1b40a
--- /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..06c7e45
--- /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..b1fc03e
--- /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..a7cde62
--- /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..2eb26ea
--- /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..27cfa36
--- /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* 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..cd339b4
--- /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..05d4a68
--- /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 * 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..28944bc
--- /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/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/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/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/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/net/src/android/net/wifi/cts/WifiManagerTest.java b/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
index 55fd1f5..5497454 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
@@ -484,6 +484,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/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/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/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/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/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/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/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/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/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/src/android/text/method/cts/BackspaceTest.java b/tests/tests/text/src/android/text/method/cts/BackspaceTest.java
index 8900f9a..fa2e262 100644
--- a/tests/tests/text/src/android/text/method/cts/BackspaceTest.java
+++ b/tests/tests/text/src/android/text/method/cts/BackspaceTest.java
@@ -132,10 +132,6 @@
         state.setByString("'1' U+FE0E U+20E3 |");
         backspace(state, 0);
         state.assertEquals("|");
-
-        state.setByString("'1' U+E0101 U+20E3 |");
-        backspace(state, 0);
-        state.assertEquals("|");
     }
 
     @SmallTest
@@ -154,24 +150,6 @@
     }
 
     @SmallTest
-    public void testEmojiZWJSequence() {
-        EditorState state = new EditorState();
-
-        // U+200D is ZERO WIDTH JOINER.
-        state.setByString("U+1F441 U+200D U+1F5E8 |");
-        backspace(state, 0);
-        state.assertEquals("|");
-
-        state.setByString("U+1F441 U+200D U+1F5E8 U+FE0E |");
-        backspace(state, 0);
-        state.assertEquals("|");
-
-        state.setByString("U+1F468 U+200D U+2764 U+FE0F U+200D U+1F48B U+200D U+1F468 |");
-        backspace(state, 0);
-        state.assertEquals("|");
-    }
-
-    @SmallTest
     public void testFlags() {
         EditorState state = new EditorState();
 
@@ -203,14 +181,4 @@
         backspace(state, 0);
         state.assertEquals("|");
     }
-
-    @SmallTest
-    public void testEmojiModifier() {
-        EditorState state = new EditorState();
-
-        // U+1F3FB is EMOJI MODIFIER FITZPATRICK TYPE-1-2.
-        state.setByString("U+1F466 U+1F3FB |");
-        backspace(state, 0);
-        state.assertEquals("|");
-    }
 }
diff --git a/tests/tests/text/src/android/text/method/cts/ForwardDeleteTest.java b/tests/tests/text/src/android/text/method/cts/ForwardDeleteTest.java
index 7ba6285..47c2795 100644
--- a/tests/tests/text/src/android/text/method/cts/ForwardDeleteTest.java
+++ b/tests/tests/text/src/android/text/method/cts/ForwardDeleteTest.java
@@ -124,6 +124,10 @@
         state.setByString("| '1' U+20E3");
         forwardDelete(state, 0);
         state.assertEquals("|");
+
+        state.setByString("| '1' U+FE0F U+20E3");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
     }
 
     @SmallTest
@@ -142,20 +146,6 @@
     }
 
     @SmallTest
-    public void testEmojiZeroWidthJoinerSequence() {
-        EditorState state = new EditorState();
-
-        // U+200D is ZERO WIDTH JOINER.
-        state.setByString("| U+1F441 U+200D U+1F5E8");
-        forwardDelete(state, 0);
-        state.assertEquals("|");
-
-        state.setByString("| U+1F468 U+200D U+2764 U+FE0F U+200D U+1F48B U+200D U+1F468");
-        forwardDelete(state, 0);
-        state.assertEquals("|");
-    }
-
-    @SmallTest
     public void testFlags() {
         EditorState state = new EditorState();
 
@@ -171,14 +161,4 @@
         forwardDelete(state, 0);
         state.assertEquals("|");
     }
-
-    @SmallTest
-    public void testEmojiModifier() {
-        EditorState state = new EditorState();
-
-        // U+1F3FB is EMOJI MODIFIER FITZPATRICK TYPE-1-2.
-        state.setByString("| U+1F466 U+1F3FB");
-        forwardDelete(state, 0);
-        state.assertEquals("|");
-    }
 }
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/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/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 0e5fb0f..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,10 @@
 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;
@@ -33,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() {
@@ -53,7 +54,7 @@
                 .runWithoutVerification();
     }
 
-    @SmallTest
+    @Test
     public void testClipRegionReturnValues() {
         createTest()
                 .addCanvasClient(new CanvasClient() {
@@ -86,7 +87,7 @@
                 .runWithoutVerification();
     }
 
-    @SmallTest
+    @Test
     public void testClipPathReturnValues() {
         createTest()
                 .addCanvasClient(new CanvasClient() {
@@ -107,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
index 56ca467..483ad87 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ColorFilterAlphaTest.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ColorFilterAlphaTest.java
@@ -32,6 +32,7 @@
 
 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
@@ -130,7 +131,6 @@
     };
 
     @Test
-    @MediumTest
     public void test() {
         createTest()
                 .addCanvasClient(mCanvasClient, mConfig.hardwareAccelerated)
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/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 ae5f05d..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,9 +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() {
@@ -77,7 +79,7 @@
         }
     };
 
-    @SmallTest
+    @Test
     public void testCircleWithCircle() {
         createTest()
                 .addCanvasClient(sTorusDrawCanvasClient, false)
@@ -85,7 +87,7 @@
                 .runWithComparer(new MSSIMComparer(0.90));
     }
 
-    @SmallTest
+    @Test
     public void testCircleWithPoints() {
         createTest()
                 .addCanvasClient(sTorusClipCanvasClient)
@@ -107,7 +109,7 @@
                         }));
     }
 
-    @SmallTest
+    @Test
     public void testViewRotate() {
         createTest()
                 .addLayout(R.layout.blue_padded_layout, new ViewInitializer() {
@@ -139,7 +141,7 @@
                         }));
     }
 
-    @SmallTest
+    @Test
     public void testTextClip() {
         createTest()
                 .addCanvasClient(new CanvasClient() {
@@ -164,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 bc76757..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,14 +17,16 @@
 
 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 {
 
     private class GrayScaleVerifier extends SamplePointVerifier {
@@ -39,7 +41,7 @@
         }
     }
 
-    @SmallTest
+    @Test
     public void testShadowLayout() {
         int shadowColorValue = 0xDB;
         // Android TV theme overrides shadow opacity to be darker.
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
index 857d3ab..c6e9881 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/XfermodeTest.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/XfermodeTest.java
@@ -33,6 +33,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
+@MediumTest
 @RunWith(Parameterized.class)
 public class XfermodeTest extends ActivityTestBase {
     /**
@@ -173,7 +174,6 @@
     };
 
     @Test
-    @MediumTest
     public void test() {
         createTest()
                 .addCanvasClient(mCanvasClient, mConfig.hardwareAccelerated)
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/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/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 0c7b5e8..d84770d 100644
--- a/tests/tests/widget/res/layout/popupwindow.xml
+++ b/tests/tests/widget/res/layout/popupwindow.xml
@@ -30,27 +30,27 @@
 
     <View android:id="@+id/anchor_upper"
         android:layout_width="10dp"
-        android:layout_height="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/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/styles.xml b/tests/tests/widget/res/values/styles.xml
index 14d575b..e92cf25 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>
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 1bdde5a..abe7848 100644
--- a/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.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.support.test.InstrumentationRegistry;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -105,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();
@@ -281,8 +287,6 @@
 
     public void testDismiss() {
         mPopupWindowBuilder = new Builder();
-        assertFalse(mPopupWindow.isShowing());
-
         mPopupWindowBuilder.show();
         assertTrue(mPopupWindow.isShowing());
 
@@ -511,6 +515,7 @@
         assertTrue(lastChildOnScreenXY[1] + lastListChild.getHeight() <= promptViewOnScreenXY[1]);
     }
 
+    @Presubmit
     public void testAccessSelection() throws Throwable {
         mPopupWindowBuilder = new Builder().withItemSelectedListener();
         mPopupWindowBuilder.show();
@@ -599,6 +604,7 @@
             }
         });
         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
@@ -608,6 +614,165 @@
         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
@@ -625,10 +790,14 @@
         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;
 
@@ -637,7 +806,6 @@
         private PopupWindow.OnDismissListener mOnDismissListener;
 
         public Builder() {
-            mPopupWindow = new ListPopupWindow(mActivity);
         }
 
         public Builder withAnchor(int anchorId) {
@@ -645,6 +813,17 @@
             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() {
             mIgnoreContentWidth = true;
             return this;
@@ -732,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() {
@@ -759,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);
@@ -825,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
index 8e280fe..dc6cfc6 100644
--- a/tests/tests/widget/src/android/widget/cts/MockViewForListPopupWindow.java
+++ b/tests/tests/widget/src/android/widget/cts/MockViewForListPopupWindow.java
@@ -44,5 +44,21 @@
         }
         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 8df2930..2339101 100644
--- a/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java
+++ b/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java
@@ -124,6 +124,17 @@
         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() {
@@ -154,6 +165,56 @@
         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
@@ -234,6 +295,52 @@
 
         // 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);
     }
 
     /**
@@ -247,8 +354,13 @@
         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;
 
@@ -270,13 +382,28 @@
         }
 
         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);
-            mPopupMenu = new PopupMenu(mActivity, mAnchor, Gravity.NO_GRAVITY, mPopupStyleAttr, 0);
+            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());
diff --git a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
index db67787..fe8b2c4 100644
--- a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
@@ -130,6 +130,43 @@
         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 {
+        @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/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index acaaf65..a95e43d 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -72,6 +72,7 @@
 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;
@@ -4014,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/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..d8d8608
--- /dev/null
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -0,0 +1,215 @@
+<?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" />
+</configuration>
diff --git a/tools/cts-tradefed/res/config/cts.xml b/tools/cts-tradefed/res/config/cts.xml
index c54f355..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="CtsCarTestCases" />
-
     <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)