Merge "Revert "add CTS tests for concurrent audio capture"" into oc-dev
diff --git a/apps/CameraITS/tools/run_all_tests.py b/apps/CameraITS/tools/run_all_tests.py
index 9e98b79..070bada 100644
--- a/apps/CameraITS/tools/run_all_tests.py
+++ b/apps/CameraITS/tools/run_all_tests.py
@@ -63,7 +63,8 @@
     # Not yet mandated tests
     NOT_YET_MANDATED = {
         "scene0": [
-            "test_jitter"
+            "test_jitter",
+            "test_burst_capture"
             ],
         "scene1": [
             "test_ae_af",
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileManager.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileManager.java
index 1d585ac..035dc3f 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileManager.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileManager.java
@@ -56,6 +56,10 @@
               "<OutputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"4\" SampleRates=\"44100,48000,88200,96000\" />" +
               "<InputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"4\" SampleRates=\"44100,48000,88200,96000\" />" +
             "</PeripheralProfile>" +
+            "<PeripheralProfile ProfileName=\"AudioBox USB\" ProfileDescription=\"Presonus AudioBox USB\" ProductName=\"USB-Audio - AudioBox USB\">" +
+              "<OutputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"4\" SampleRates=\"44100,48000\" />" +
+              "<InputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"4\" SampleRates=\"44100,48000\" />" +
+            "</PeripheralProfile>" +
           "</ProfileList>";
 
     // XML Tags and Attributes
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/IntentFiltersTestHelper.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/IntentFiltersTestHelper.java
index acd346a..476eb80 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/IntentFiltersTestHelper.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/IntentFiltersTestHelper.java
@@ -29,6 +29,7 @@
 import android.media.audiofx.AudioEffect;
 import android.net.Uri;
 import android.nfc.cardemulation.CardEmulation;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.UserHandle;
@@ -67,7 +68,6 @@
                 new Intent(AlarmClock.ACTION_SET_TIMER),
                 new Intent(AlarmClock.ACTION_SHOW_ALARMS),
                 new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS),
-                new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS),
                 new Intent(Settings.ACTION_CAPTIONING_SETTINGS),
                 new Intent(Settings.ACTION_DATE_SETTINGS),
                 new Intent(Settings.ACTION_DEVICE_INFO_SETTINGS),
@@ -266,6 +266,11 @@
             notForwardedIntentsFromManaged.add(
                     new Intent(Settings.ACTION_PRINT_SETTINGS));
         }
+
+        if (Build.TYPE.equals("user")) {
+            forwardedIntentsFromManaged.add(
+                    new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS));
+        }
     }
 
     public boolean checkCrossProfileIntentFilters(int flag) {
diff --git a/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/EncryptionAppTest.java b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/EncryptionAppTest.java
index a047732..15197a0 100644
--- a/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/EncryptionAppTest.java
+++ b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/EncryptionAppTest.java
@@ -92,8 +92,6 @@
         mDevice.waitForIdle();
 
         // Set a PIN for this user
-        mDevice.executeShellCommand("settings put global require_password_to_decrypt 0");
-        mDevice.executeShellCommand("locksettings set-disabled false");
         mDevice.executeShellCommand("locksettings set-pin 12345");
     }
 
@@ -107,8 +105,6 @@
 
         // Clear PIN for this user
         mDevice.executeShellCommand("locksettings clear --old 12345");
-        mDevice.executeShellCommand("locksettings set-disabled true");
-        mDevice.executeShellCommand("settings delete global require_password_to_decrypt");
     }
 
     public void doBootCountBefore() throws Exception {
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/AndroidManifest.xml
index e591c25..63caebc 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/AndroidManifest.xml
@@ -63,6 +63,7 @@
             android:theme="@android:style/Theme.NoDisplay">
             <!-- TEST: ephemeral apps can start this activity using directed intent -->
         </activity>
+
         <service
             android:name=".EphemeralService">
             <!-- TEST: ephemeral apps can see this service using query methods -->
@@ -76,6 +77,15 @@
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
         </service>
+
+        <provider
+            android:name=".EphemeralProvider"
+            android:authorities="com.android.cts.ephemeralapp1.provider"
+            android:exported="true">
+            <intent-filter android:priority="0">
+                <action android:name="com.android.cts.ephemeraltest.QUERY" />
+            </intent-filter>
+        </provider>
     </application>
 
     <instrumentation
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
index ada9c36..c0f4d2b 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
@@ -22,6 +22,7 @@
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.fail;
 
+import android.annotation.Nullable;
 import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -32,6 +33,7 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.database.Cursor;
 import android.net.Uri;
 import android.os.Build;
 import android.os.IBinder;
@@ -135,6 +137,53 @@
 
     @Test
     public void testQuery() throws Exception {
+        // query normal activities
+        {
+            final Intent queryIntent = new Intent(ACTION_QUERY);
+            final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
+                    .getPackageManager().queryIntentActivities(queryIntent, 0 /*flags*/);
+            if (resolveInfo == null || resolveInfo.size() == 0) {
+                fail("didn't resolve any intents");
+            }
+            assertThat(resolveInfo.size(), is(2));
+            assertThat(resolveInfo.get(0).activityInfo.packageName,
+                    is("com.android.cts.ephemeralapp1"));
+            assertThat(resolveInfo.get(0).activityInfo.name,
+                    is("com.android.cts.ephemeralapp1.EphemeralActivity"));
+            assertThat(resolveInfo.get(0).instantAppAvailable,
+                    is(true));
+            assertThat(resolveInfo.get(1).activityInfo.packageName,
+                    is("com.android.cts.normalapp"));
+            assertThat(resolveInfo.get(1).activityInfo.name,
+                    is("com.android.cts.normalapp.ExposedActivity"));
+            assertThat(resolveInfo.get(1).instantAppAvailable,
+                    is(false));
+        }
+
+        // query normal activities; directed package
+        {
+            final Intent queryIntent = new Intent(ACTION_QUERY);
+            final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
+                    .getPackageManager().queryIntentActivities(queryIntent, 0 /*flags*/);
+            if (resolveInfo == null || resolveInfo.size() == 0) {
+                fail("didn't resolve any intents");
+            }
+            assertThat(resolveInfo.size(), is(2));
+            assertThat(resolveInfo.get(0).activityInfo.packageName,
+                    is("com.android.cts.ephemeralapp1"));
+            assertThat(resolveInfo.get(0).activityInfo.name,
+                    is("com.android.cts.ephemeralapp1.EphemeralActivity"));
+            assertThat(resolveInfo.get(0).instantAppAvailable,
+                    is(true));
+            assertThat(resolveInfo.get(1).activityInfo.packageName,
+                    is("com.android.cts.normalapp"));
+            assertThat(resolveInfo.get(1).activityInfo.name,
+                    is("com.android.cts.normalapp.ExposedActivity"));
+            assertThat(resolveInfo.get(1).instantAppAvailable,
+                    is(false));
+        }
+
+        // query normal activities; directed component
         {
             final Intent queryIntent = new Intent(ACTION_QUERY);
             final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
@@ -176,6 +225,93 @@
             assertThat(resolveInfo.get(1).instantAppAvailable,
                     is(false));
         }
+
+        {
+            final Intent queryIntent = new Intent(ACTION_QUERY);
+            queryIntent.setPackage("com.android.cts.ephemeralapp1");
+            final List<ResolveInfo> resolveInfo = InstrumentationRegistry
+                    .getContext().getPackageManager().queryIntentServices(queryIntent, 0 /*flags*/);
+            if (resolveInfo == null || resolveInfo.size() == 0) {
+                fail("didn't resolve any intents");
+            }
+            assertThat(resolveInfo.size(), is(1));
+            assertThat(resolveInfo.get(0).serviceInfo.packageName,
+                    is("com.android.cts.ephemeralapp1"));
+            assertThat(resolveInfo.get(0).serviceInfo.name,
+                    is("com.android.cts.ephemeralapp1.EphemeralService"));
+        }
+
+        {
+            final Intent queryIntent = new Intent(ACTION_QUERY);
+            queryIntent.setComponent(
+                    new ComponentName("com.android.cts.ephemeralapp1",
+                            "com.android.cts.ephemeralapp1.EphemeralService"));
+            final List<ResolveInfo> resolveInfo = InstrumentationRegistry
+                    .getContext().getPackageManager().queryIntentServices(queryIntent, 0 /*flags*/);
+            if (resolveInfo == null || resolveInfo.size() == 0) {
+                fail("didn't resolve any intents");
+            }
+            assertThat(resolveInfo.size(), is(1));
+            assertThat(resolveInfo.get(0).serviceInfo.packageName,
+                    is("com.android.cts.ephemeralapp1"));
+            assertThat(resolveInfo.get(0).serviceInfo.name,
+                    is("com.android.cts.ephemeralapp1.EphemeralService"));
+        }
+
+        {
+            final Intent queryIntent = new Intent(ACTION_QUERY);
+            final List<ResolveInfo> resolveInfo = InstrumentationRegistry
+                    .getContext().getPackageManager().queryIntentContentProviders(
+                            queryIntent, 0 /*flags*/);
+            if (resolveInfo == null || resolveInfo.size() == 0) {
+                fail("didn't resolve any intents");
+            }
+            assertThat(resolveInfo.size(), is(2));
+            assertThat(resolveInfo.get(0).providerInfo.packageName,
+                    is("com.android.cts.ephemeralapp1"));
+            assertThat(resolveInfo.get(0).providerInfo.name,
+                    is("com.android.cts.ephemeralapp1.EphemeralProvider"));
+            assertThat(resolveInfo.get(1).providerInfo.packageName,
+                    is("com.android.cts.normalapp"));
+            assertThat(resolveInfo.get(1).providerInfo.name,
+                    is("com.android.cts.normalapp.ExposedProvider"));
+            assertThat(resolveInfo.get(1).instantAppAvailable,
+                    is(false));
+        }
+
+        {
+            final Intent queryIntent = new Intent(ACTION_QUERY);
+            queryIntent.setPackage("com.android.cts.ephemeralapp1");
+            final List<ResolveInfo> resolveInfo = InstrumentationRegistry
+                    .getContext().getPackageManager().queryIntentContentProviders(
+                            queryIntent, 0 /*flags*/);
+            if (resolveInfo == null || resolveInfo.size() == 0) {
+                fail("didn't resolve any intents");
+            }
+            assertThat(resolveInfo.size(), is(1));
+            assertThat(resolveInfo.get(0).providerInfo.packageName,
+                    is("com.android.cts.ephemeralapp1"));
+            assertThat(resolveInfo.get(0).providerInfo.name,
+                    is("com.android.cts.ephemeralapp1.EphemeralProvider"));
+        }
+
+        {
+            final Intent queryIntent = new Intent(ACTION_QUERY);
+            queryIntent.setComponent(
+                    new ComponentName("com.android.cts.ephemeralapp1",
+                            "com.android.cts.ephemeralapp1.EphemeralProvider"));
+            final List<ResolveInfo> resolveInfo = InstrumentationRegistry
+                    .getContext().getPackageManager().queryIntentContentProviders(
+                            queryIntent, 0 /*flags*/);
+            if (resolveInfo == null || resolveInfo.size() == 0) {
+                fail("didn't resolve any intents");
+            }
+            assertThat(resolveInfo.size(), is(1));
+            assertThat(resolveInfo.get(0).providerInfo.packageName,
+                    is("com.android.cts.ephemeralapp1"));
+            assertThat(resolveInfo.get(0).providerInfo.name,
+                    is("com.android.cts.ephemeralapp1.EphemeralProvider"));
+        }
     }
 
     @Test
@@ -230,6 +366,48 @@
         // provide any feedback. The alternative is to wait for the broadcast timeout
         // but it's silly to artificially slow down CTS. We'll rely on queryIntentService
         // to check whether or not the service is actually exposed
+
+        // bind to the normal service; directed package
+        {
+            final Intent startNormalIntent = new Intent(ACTION_START_NORMAL);
+            startNormalIntent.setPackage("com.android.cts.normalapp");
+            final TestServiceConnection connection = new TestServiceConnection();
+            try {
+                assertThat(InstrumentationRegistry.getContext().bindService(
+                        startNormalIntent, connection, Context.BIND_AUTO_CREATE /*flags*/),
+                        is(false));
+            } finally {
+                InstrumentationRegistry.getContext().unbindService(connection);
+            }
+        }
+
+        // bind to the normal service; directed component
+        {
+            final Intent startNormalIntent = new Intent(ACTION_START_NORMAL);
+            startNormalIntent.setComponent(new ComponentName(
+                    "com.android.cts.normalapp", "com.android.cts.normalapp.NormalService"));
+            final TestServiceConnection connection = new TestServiceConnection();
+            try {
+                assertThat(InstrumentationRegistry.getContext().bindService(
+                        startNormalIntent, connection, Context.BIND_AUTO_CREATE /*flags*/),
+                        is(false));
+            } finally {
+                InstrumentationRegistry.getContext().unbindService(connection);
+            }
+        }
+
+        // connect to the normal provider
+        {
+            final String provider = "content://com.android.cts.normalapp.provider/table";
+            final Cursor testCursor = InstrumentationRegistry
+                    .getContext().getContentResolver().query(
+                            Uri.parse(provider),
+                            null /*projection*/,
+                            null /*selection*/,
+                            null /*selectionArgs*/,
+                            null /*sortOrder*/);
+            assertThat(testCursor, is(nullValue()));
+        }
     }
 
     @Test
@@ -376,12 +554,43 @@
                         is("onBind"));
                 assertThat(testResult.getStatus(),
                         is("PASS"));
+                assertThat(testResult.getEphemeralPackageInfoExposed(),
+                        is(true));
                 assertThat(testResult.getException(),
                         is(nullValue()));
             } finally {
                 InstrumentationRegistry.getContext().unbindService(connection);
             }
         }
+
+        // connect to exposed provider
+        {
+            final String provider = "content://com.android.cts.normalapp.exposed.provider/table";
+            final Cursor testCursor = InstrumentationRegistry
+                    .getContext().getContentResolver().query(
+                            Uri.parse(provider),
+                            null /*projection*/,
+                            null /*selection*/,
+                            null /*selectionArgs*/,
+                            null /*sortOrder*/);
+            assertThat(testCursor, is(notNullValue()));
+            assertThat(testCursor.getCount(), is(1));
+            assertThat(testCursor.getColumnCount(), is(2));
+            assertThat(testCursor.moveToFirst(), is(true));
+            assertThat(testCursor.getInt(0), is(1));
+            assertThat(testCursor.getString(1), is("ExposedProvider"));
+            final TestResult testResult = getResult();
+            assertThat(testResult.getPackageName(),
+                    is("com.android.cts.normalapp"));
+            assertThat(testResult.getComponentName(),
+                    is("ExposedProvider"));
+            assertThat(testResult.getStatus(),
+                    is("PASS"));
+            assertThat(testResult.getEphemeralPackageInfoExposed(),
+                    is(true));
+            assertThat(testResult.getException(),
+                    is(nullValue()));
+        }
     }
 
     @Test
@@ -607,6 +816,24 @@
                 InstrumentationRegistry.getContext().unbindService(connection);
             }
         }
+
+        // connect to the instant app provider
+        {
+            final String provider = "content://com.android.cts.ephemeralapp1.provider/table";
+            final Cursor testCursor = InstrumentationRegistry
+                    .getContext().getContentResolver().query(
+                            Uri.parse(provider),
+                            null /*projection*/,
+                            null /*selection*/,
+                            null /*selectionArgs*/,
+                            null /*sortOrder*/);
+            assertThat(testCursor, is(notNullValue()));
+            assertThat(testCursor.getCount(), is(1));
+            assertThat(testCursor.getColumnCount(), is(2));
+            assertThat(testCursor.moveToFirst(), is(true));
+            assertThat(testCursor.getInt(0), is(1));
+            assertThat(testCursor.getString(1), is("InstantAppProvider"));
+        }
     }
 
     @Test
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/EphemeralProvider.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/EphemeralProvider.java
new file mode 100644
index 0000000..d34d494
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/EphemeralProvider.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.ephemeralapp1;
+
+import android.content.ContentProvider;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.UriMatcher;
+import android.database.CharArrayBuffer;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.database.DataSetObserver;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.os.Bundle;
+
+public class EphemeralProvider extends ContentProvider {
+    private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+    static {
+        sUriMatcher.addURI("com.android.cts.ephemeralapp1.provider", "table", 1);
+    }
+    private static final String[] sColumnNames = { "_ID", "name" };
+    private static final MatrixCursor sCursor = new MatrixCursor(sColumnNames, 1);
+    static {
+        sCursor.newRow().add(1).add("InstantAppProvider");
+    }
+
+    @Override
+    public boolean onCreate() {
+        return true;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+            String sortOrder) {
+        return (sUriMatcher.match(uri) != 1) ? null : sCursor;
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        return null;
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        return null;
+    }
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        return 0;
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+        return 0;
+    }
+
+}
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp2/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp2/AndroidManifest.xml
index 06d569e..78c282b 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp2/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp2/AndroidManifest.xml
@@ -43,12 +43,23 @@
                 <action android:name="com.android.cts.ephemeraltest.START_EPHEMERAL" />
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
-          </activity>
-          <!-- This should still not be visible to other Instant Apps -->
-          <activity
-            android:name=".FakeExposedActivity"
+        </activity>
+
+        <!-- This should still not be visible to other Instant Apps -->
+        <activity
+            android:name=".ExposedActivity"
             android:visibleToInstantApps="true"
             android:theme="@android:style/Theme.NoDisplay" />
+
+        <!-- This should still not be visible to other Instant Apps -->
+        <provider
+            android:name=".EphemeralProvider"
+            android:authorities="com.android.cts.ephemeralapp2.provider"
+            android:exported="true">
+            <intent-filter android:priority="0">
+                <action android:name="com.android.cts.ephemeraltest.QUERY" />
+            </intent-filter>
+        </provider>
     </application>
 
     <instrumentation
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/AndroidManifest.xml
index ff542a4..4c27dba 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/AndroidManifest.xml
@@ -64,6 +64,7 @@
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
         </activity>
+
         <service
             android:name=".NormalService">
             <!-- TEST: ephemeral apps can't see this service using query methods -->
@@ -91,6 +92,24 @@
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
         </service>
+
+        <provider
+            android:name=".NormalProvider"
+            android:authorities="com.android.cts.normalapp.provider"
+            android:exported="true">
+            <intent-filter android:priority="-20">
+                <action android:name="com.android.cts.ephemeraltest.QUERY" />
+            </intent-filter>
+        </provider>
+        <provider
+            android:name=".ExposedProvider"
+            android:authorities="com.android.cts.normalapp.exposed.provider"
+            android:visibleToInstantApps="true"
+            android:exported="true">
+            <intent-filter android:priority="-10">
+                <action android:name="com.android.cts.ephemeraltest.QUERY" />
+            </intent-filter>
+        </provider>
     </application>
 
     <instrumentation
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ClientTest.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ClientTest.java
index d428158..14ee824 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ClientTest.java
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ClientTest.java
@@ -17,6 +17,8 @@
 package com.android.cts.normalapp;
 
 import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.fail;
 
@@ -27,6 +29,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ResolveInfo;
+import android.database.Cursor;
 import android.net.Uri;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
@@ -83,9 +86,9 @@
 
     @Test
     public void testQuery() throws Exception {
-        final Intent queryIntent = new Intent(ACTION_QUERY);
         // query activities without flags
         {
+            final Intent queryIntent = new Intent(ACTION_QUERY);
             final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
                     .getPackageManager().queryIntentActivities(queryIntent, 0 /*flags*/);
             if (resolveInfo == null || resolveInfo.size() == 0) {
@@ -108,6 +111,7 @@
 
         // query activities asking for ephemeral apps [we should only get normal apps]
         {
+            final Intent queryIntent = new Intent(ACTION_QUERY);
             final int MATCH_EPHEMERAL = 0x00800000;
 
             final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
@@ -130,8 +134,29 @@
                     is(false));
         }
 
+        // query activities; directed package
+        {
+            final Intent queryIntent = new Intent(ACTION_QUERY);
+            queryIntent.setPackage("com.android.cts.ephemeralapp1");
+            final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
+                    .getPackageManager().queryIntentActivities(queryIntent, 0 /*flags*/);
+            assertThat(resolveInfo.size(), is(0));
+        }
+
+        // query activities; directed component
+        {
+            final Intent queryIntent = new Intent(ACTION_QUERY);
+            queryIntent.setComponent(
+                    new ComponentName("com.android.cts.ephemeralapp1",
+                            "com.android.cts.ephemeralapp1.EphemeralActivity"));
+            final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
+                    .getPackageManager().queryIntentActivities(queryIntent, 0 /*flags*/);
+            assertThat(resolveInfo.size(), is(0));
+        }
+
         // query services without flags
         {
+            final Intent queryIntent = new Intent(ACTION_QUERY);
             final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
                     .getPackageManager().queryIntentServices(queryIntent, 0 /*flags*/);
             if (resolveInfo == null || resolveInfo.size() == 0) {
@@ -154,6 +179,7 @@
 
         // query services asking for ephemeral apps [we should only get normal apps]
         {
+            final Intent queryIntent = new Intent(ACTION_QUERY);
             final int MATCH_EPHEMERAL = 0x00800000;
 
             final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
@@ -175,6 +201,92 @@
             assertThat(resolveInfo.get(1).instantAppAvailable,
                     is(false));
         }
+
+        // query services; directed package
+        {
+            final Intent queryIntent = new Intent(ACTION_QUERY);
+            queryIntent.setPackage("com.android.cts.ephemeralapp1");
+            final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
+                    .getPackageManager().queryIntentServices(queryIntent, 0 /*flags*/);
+            assertThat(resolveInfo.size(), is(0));
+        }
+
+        // query services; directed component
+        {
+            final Intent queryIntent = new Intent(ACTION_QUERY);
+            queryIntent.setComponent(
+                    new ComponentName("com.android.cts.ephemeralapp1",
+                            "com.android.cts.ephemeralapp1.EphemeralService"));
+            final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
+                    .getPackageManager().queryIntentServices(queryIntent, 0 /*flags*/);
+            assertThat(resolveInfo.size(), is(0));
+        }
+
+        // query content providers without flags
+        {
+            final Intent queryIntent = new Intent(ACTION_QUERY);
+            final List<ResolveInfo> resolveInfo = InstrumentationRegistry
+                    .getContext().getPackageManager().queryIntentContentProviders(
+                            queryIntent, 0 /*flags*/);
+            if (resolveInfo == null || resolveInfo.size() == 0) {
+                fail("didn't resolve any intents");
+            }
+            assertThat(resolveInfo.size(), is(2));
+            assertThat(resolveInfo.get(0).providerInfo.packageName,
+                    is("com.android.cts.normalapp"));
+            assertThat(resolveInfo.get(0).providerInfo.name,
+                    is("com.android.cts.normalapp.ExposedProvider"));
+            assertThat(resolveInfo.get(1).providerInfo.packageName,
+                    is("com.android.cts.normalapp"));
+            assertThat(resolveInfo.get(1).providerInfo.name,
+                    is("com.android.cts.normalapp.NormalProvider"));
+            assertThat(resolveInfo.get(1).instantAppAvailable,
+                    is(false));
+        }
+
+        // query content providers asking for ephemeral apps [we should only get normal apps]
+        {
+            final Intent queryIntent = new Intent(ACTION_QUERY);
+            final int MATCH_EPHEMERAL = 0x00800000;
+
+            final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
+                    .getPackageManager().queryIntentContentProviders(
+                            queryIntent, MATCH_EPHEMERAL);
+            if (resolveInfo == null || resolveInfo.size() == 0) {
+                fail("didn't resolve any intents");
+            }
+            assertThat(resolveInfo.size(), is(2));
+            assertThat(resolveInfo.get(0).providerInfo.packageName,
+                    is("com.android.cts.normalapp"));
+            assertThat(resolveInfo.get(0).providerInfo.name,
+                    is("com.android.cts.normalapp.ExposedProvider"));
+            assertThat(resolveInfo.get(1).providerInfo.packageName,
+                    is("com.android.cts.normalapp"));
+            assertThat(resolveInfo.get(1).providerInfo.name,
+                    is("com.android.cts.normalapp.NormalProvider"));
+            assertThat(resolveInfo.get(1).instantAppAvailable,
+                    is(false));
+        }
+
+        // query content providers; directed package
+        {
+            final Intent queryIntent = new Intent(ACTION_QUERY);
+            queryIntent.setPackage("com.android.cts.ephemeralapp1");
+            final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
+                    .getPackageManager().queryIntentContentProviders(queryIntent, 0 /*flags*/);
+            assertThat(resolveInfo.size(), is(0));
+        }
+
+        // query content providers; directed component
+        {
+            final Intent queryIntent = new Intent(ACTION_QUERY);
+            queryIntent.setComponent(
+                    new ComponentName("com.android.cts.ephemeralapp1",
+                            "com.android.cts.ephemeralapp1.EphemeralProvider"));
+            final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
+                    .getPackageManager().queryIntentContentProviders(queryIntent, 0 /*flags*/);
+            assertThat(resolveInfo.size(), is(0));
+        }
     }
 
     @Test
@@ -220,6 +332,24 @@
             assertThat(testResult.getException(),
                     is("android.content.pm.PackageManager$NameNotFoundException"));
         }
+
+        // connect to the normal provider
+        {
+            final String provider = "content://com.android.cts.normalapp.provider/table";
+            final Cursor testCursor = InstrumentationRegistry
+                    .getContext().getContentResolver().query(
+                            Uri.parse(provider),
+                            null /*projection*/,
+                            null /*selection*/,
+                            null /*selectionArgs*/,
+                            null /*sortOrder*/);
+            assertThat(testCursor, is(notNullValue()));
+            assertThat(testCursor.getCount(), is(1));
+            assertThat(testCursor.getColumnCount(), is(2));
+            assertThat(testCursor.moveToFirst(), is(true));
+            assertThat(testCursor.getInt(0), is(1));
+            assertThat(testCursor.getString(1), is("NormalProvider"));
+        }
     }
 
     @Test
@@ -269,6 +399,19 @@
             assertThat("com.android.cts.ephemeralapp1", is(testResult.getPackageName()));
             assertThat("EphemeralActivity", is(testResult.getComponentName()));
         }
+
+        // connect to the instant app provider
+        {
+            final String provider = "content://com.android.cts.ephemeralapp1.provider/table";
+            final Cursor testCursor = InstrumentationRegistry
+                    .getContext().getContentResolver().query(
+                            Uri.parse(provider),
+                            null /*projection*/,
+                            null /*selection*/,
+                            null /*selectionArgs*/,
+                            null /*sortOrder*/);
+            assertThat(testCursor, is(nullValue()));
+        }
     }
 
     private TestResult getResult() {
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ExposedProvider.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ExposedProvider.java
new file mode 100644
index 0000000..99658d4
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ExposedProvider.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.normalapp;
+
+import android.content.ContentProvider;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.UriMatcher;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.database.CharArrayBuffer;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.database.DataSetObserver;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.os.Bundle;
+
+import com.android.cts.util.TestResult;
+
+public class ExposedProvider extends ContentProvider {
+    private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+    static {
+        sUriMatcher.addURI("com.android.cts.normalapp.exposed.provider", "table", 1);
+    }
+    private static final String[] sColumnNames = { "_ID", "name" };
+    private static final MatrixCursor sCursor = new MatrixCursor(sColumnNames, 1);
+    static {
+        sCursor.newRow().add(1).add("ExposedProvider");
+    }
+
+    @Override
+    public boolean onCreate() {
+        return true;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+            String sortOrder) {
+        boolean canAccessInstantApp = false;
+        String exception = null;
+        try {
+            canAccessInstantApp = tryAccessingInstantApp();
+        } catch (Throwable t) {
+            exception = t.getClass().getName();
+        }
+
+        TestResult.getBuilder()
+                .setPackageName("com.android.cts.normalapp")
+                .setComponentName("ExposedProvider")
+                .setStatus("PASS")
+                .setException(exception)
+                .setEphemeralPackageInfoExposed(canAccessInstantApp)
+                .build()
+                .broadcast(getContext());
+
+        return (sUriMatcher.match(uri) != 1) ? null : sCursor;
+    }
+
+    private boolean tryAccessingInstantApp() throws NameNotFoundException {
+        final PackageInfo info = getContext().getPackageManager()
+                .getPackageInfo("com.android.cts.ephemeralapp1", 0 /*flags*/);
+        return (info != null);
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        return null;
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        return null;
+    }
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        return 0;
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+        return 0;
+    }
+
+}
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/NormalProvider.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/NormalProvider.java
new file mode 100644
index 0000000..8351a27
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/NormalProvider.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.normalapp;
+
+import android.content.ContentProvider;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.UriMatcher;
+import android.database.CharArrayBuffer;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.database.DataSetObserver;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.os.Bundle;
+
+public class NormalProvider extends ContentProvider {
+    private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+    static {
+        sUriMatcher.addURI("com.android.cts.normalapp.provider", "table", 1);
+    }
+    private static final String[] sColumnNames = { "_ID", "name" };
+    private static final MatrixCursor sCursor = new MatrixCursor(sColumnNames, 1);
+    static {
+        sCursor.newRow().add(1).add("NormalProvider");
+    }
+
+    @Override
+    public boolean onCreate() {
+        return true;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+            String sortOrder) {
+        return (sUriMatcher.match(uri) != 1) ? null : sCursor;
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        return null;
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        return null;
+    }
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        return 0;
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+        return 0;
+    }
+
+}
diff --git a/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/StorageTest.java b/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/StorageTest.java
index 22eaaea..9778f12 100644
--- a/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/StorageTest.java
+++ b/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/StorageTest.java
@@ -41,6 +41,7 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.util.UUID;
 
 /**
  * Client app for verifying storage behaviors.
@@ -85,8 +86,10 @@
     public void testVerifySpaceApi() throws Exception {
         final StorageManager sm = getContext().getSystemService(StorageManager.class);
 
-        final long cacheSize = sm.getCacheSizeBytes(getContext().getCacheDir());
-        final long extCacheSize = sm.getCacheSizeBytes(getContext().getExternalCacheDir());
+        final long cacheSize = sm.getCacheSizeBytes(
+                sm.getUuidForPath(getContext().getCacheDir()));
+        final long extCacheSize = sm.getCacheSizeBytes(
+                sm.getUuidForPath(getContext().getExternalCacheDir()));
         if (cacheSize == extCacheSize) {
             assertMostlyEquals(CACHE_ALL, cacheSize);
         } else {
@@ -97,22 +100,28 @@
 
     public void testVerifyQuotaApi() throws Exception {
         final StorageManager sm = getContext().getSystemService(StorageManager.class);
-        assertTrue("Apps must have at least 10MB quota",
-                sm.getCacheQuotaBytes(getContext().getCacheDir()) > 10 * MB_IN_BYTES);
+
+        final long cacheSize = sm.getCacheQuotaBytes(
+                sm.getUuidForPath(getContext().getCacheDir()));
+        assertTrue("Apps must have at least 10MB quota", cacheSize > 10 * MB_IN_BYTES);
     }
 
     public void testVerifyAllocateApi() throws Exception {
         final StorageManager sm = getContext().getSystemService(StorageManager.class);
 
         final File filesDir = getContext().getFilesDir();
-        assertTrue("Apps must be able to allocate internal space",
-                sm.getAllocatableBytes(filesDir, 0) > 10 * MB_IN_BYTES);
         final File extDir = Environment.getExternalStorageDirectory();
+
+        final UUID filesUuid = sm.getUuidForPath(filesDir);
+        final UUID extUuid = sm.getUuidForPath(extDir);
+
+        assertTrue("Apps must be able to allocate internal space",
+                sm.getAllocatableBytes(filesUuid, 0) > 10 * MB_IN_BYTES);
         assertTrue("Apps must be able to allocate external space",
-                sm.getAllocatableBytes(extDir, 0) > 10 * MB_IN_BYTES);
+                sm.getAllocatableBytes(extUuid, 0) > 10 * MB_IN_BYTES);
 
         // Should always be able to allocate 1MB indirectly
-        sm.allocateBytes(filesDir, 1 * MB_IN_BYTES, 0);
+        sm.allocateBytes(filesUuid, 1 * MB_IN_BYTES, 0);
 
         // Should always be able to allocate 1MB directly
         final File filesFile = makeUniqueFile(filesDir);
diff --git a/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/UtilsReceiver.java b/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/UtilsReceiver.java
index bab84aa..2845185 100644
--- a/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/UtilsReceiver.java
+++ b/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/UtilsReceiver.java
@@ -50,13 +50,13 @@
     public static Bundle doAllocation(Context context, Bundle extras) {
         final StorageManager sm = context.getSystemService(StorageManager.class);
 
-        final double fraction = extras.getDouble(EXTRA_FRACTION, 0);
-        final long quota = sm.getCacheQuotaBytes(context.getCacheDir());
-        final long bytes = (long) (quota * fraction);
-        final long time = extras.getLong(EXTRA_TIME, System.currentTimeMillis());
-
         long allocated = 0;
         try {
+            final double fraction = extras.getDouble(EXTRA_FRACTION, 0);
+            final long quota = sm.getCacheQuotaBytes(sm.getUuidForPath(context.getCacheDir()));
+            final long bytes = (long) (quota * fraction);
+            final long time = extras.getLong(EXTRA_TIME, System.currentTimeMillis());
+
             while (allocated < bytes) {
                 final File f = makeUniqueFile(context.getCacheDir());
                 final long size = 1024 * 1024;
@@ -64,15 +64,15 @@
                 f.setLastModified(time);
                 allocated += Os.stat(f.getAbsolutePath()).st_blocks * 512;
             }
+
+            Log.d(TAG, "Quota " + quota + ", target " + bytes + ", allocated " + allocated);
+
+            final Bundle res = new Bundle();
+            res.putLong(EXTRA_BYTES, allocated);
+            return res;
         } catch (Exception e) {
             Log.e(TAG, "Failed to allocate cache files", e);
             return null;
         }
-
-        Log.d(TAG, "Quota " + quota + ", target " + bytes + ", allocated " + allocated);
-
-        final Bundle res = new Bundle();
-        res.putLong(EXTRA_BYTES, allocated);
-        return res;
     }
 }
diff --git a/hostsidetests/appsecurity/test-apps/StorageStatsApp/src/com/android/cts/storagestatsapp/StorageStatsTest.java b/hostsidetests/appsecurity/test-apps/StorageStatsApp/src/com/android/cts/storagestatsapp/StorageStatsTest.java
index 72a420d..41439f0 100644
--- a/hostsidetests/appsecurity/test-apps/StorageStatsApp/src/com/android/cts/storagestatsapp/StorageStatsTest.java
+++ b/hostsidetests/appsecurity/test-apps/StorageStatsApp/src/com/android/cts/storagestatsapp/StorageStatsTest.java
@@ -16,6 +16,8 @@
 
 package com.android.cts.storagestatsapp;
 
+import static android.os.storage.StorageManager.UUID_DEFAULT;
+
 import static com.android.cts.storageapp.Utils.CACHE_ALL;
 import static com.android.cts.storageapp.Utils.DATA_ALL;
 import static com.android.cts.storageapp.Utils.MB_IN_BYTES;
@@ -54,6 +56,7 @@
 import com.android.cts.storageapp.UtilsReceiver;
 
 import java.io.File;
+import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -81,15 +84,18 @@
                     .getSystemService(StorageStatsManager.class);
             assertTrue("You're running kernel 3.18 or newer (" + uname.release + ") which "
                     + "means that CONFIG_QUOTA, CONFIG_QFMT_V2, CONFIG_QUOTACTL and the "
-                    + "'quota' fstab option on /data are required", stats.isQuotaSupported(null));
+                    + "'quota' fstab option on /data are required",
+                    stats.isQuotaSupported(UUID_DEFAULT));
         }
     }
 
     public void testVerifySummary() throws Exception {
         final StorageStatsManager stats = getContext().getSystemService(StorageStatsManager.class);
 
-        assertAtLeast(Environment.getDataDirectory().getTotalSpace(), stats.getTotalBytes(null));
-        assertAtLeast(Environment.getDataDirectory().getUsableSpace(), stats.getFreeBytes(null));
+        assertAtLeast(Environment.getDataDirectory().getTotalSpace(),
+                stats.getTotalBytes(UUID_DEFAULT));
+        assertAtLeast(Environment.getDataDirectory().getUsableSpace(),
+                stats.getFreeBytes(UUID_DEFAULT));
     }
 
     public void testVerifyStats() throws Exception {
@@ -97,13 +103,13 @@
         final int uid = android.os.Process.myUid();
         final UserHandle user = UserHandle.getUserHandleForUid(uid);
 
-        final StorageStats beforeApp = stats.queryStatsForUid(null, uid);
-        final StorageStats beforeUser = stats.queryStatsForUser(null, user);
+        final StorageStats beforeApp = stats.queryStatsForUid(UUID_DEFAULT, uid);
+        final StorageStats beforeUser = stats.queryStatsForUser(UUID_DEFAULT, user);
 
         useSpace(getContext());
 
-        final StorageStats afterApp = stats.queryStatsForUid(null, uid);
-        final StorageStats afterUser = stats.queryStatsForUser(null, user);
+        final StorageStats afterApp = stats.queryStatsForUid(UUID_DEFAULT, uid);
+        final StorageStats afterUser = stats.queryStatsForUser(UUID_DEFAULT, user);
 
         final long deltaData = DATA_ALL;
         assertMostlyEquals(deltaData, afterApp.getDataBytes() - beforeApp.getDataBytes());
@@ -121,8 +127,8 @@
         final ApplicationInfo a = pm.getApplicationInfo(PKG_A, 0);
         final ApplicationInfo b = pm.getApplicationInfo(PKG_B, 0);
 
-        final StorageStats as = stats.queryStatsForUid(null, a.uid);
-        final StorageStats bs = stats.queryStatsForUid(null, b.uid);
+        final StorageStats as = stats.queryStatsForUid(UUID_DEFAULT, a.uid);
+        final StorageStats bs = stats.queryStatsForUid(UUID_DEFAULT, b.uid);
 
         assertMostlyEquals(DATA_ALL * 2, as.getDataBytes());
         assertMostlyEquals(CACHE_ALL * 2, as.getCacheBytes());
@@ -140,7 +146,7 @@
         final int uid = android.os.Process.myUid();
         final UserHandle user = UserHandle.getUserHandleForUid(uid);
 
-        final ExternalStorageStats before = stats.queryExternalStatsForUser(null, user);
+        final ExternalStorageStats before = stats.queryExternalStatsForUser(UUID_DEFAULT, user);
 
         final File dir = Environment.getExternalStorageDirectory();
         final File downloadsDir = Environment.getExternalStoragePublicDirectory(
@@ -158,7 +164,7 @@
         useWrite(audio, 5 * MB_IN_BYTES);
         useWrite(internal, 7 * MB_IN_BYTES);
 
-        final ExternalStorageStats afterInit = stats.queryExternalStatsForUser(null, user);
+        final ExternalStorageStats afterInit = stats.queryExternalStatsForUser(UUID_DEFAULT, user);
 
         assertMostlyEquals(17 * MB_IN_BYTES, afterInit.getTotalBytes() - before.getTotalBytes());
         assertMostlyEquals(5 * MB_IN_BYTES, afterInit.getAudioBytes() - before.getAudioBytes());
@@ -168,7 +174,7 @@
         // Rename to ensure that stats are updated
         video.renameTo(new File(dir, System.nanoTime() + ".PnG"));
 
-        final ExternalStorageStats afterRename = stats.queryExternalStatsForUser(null, user);
+        final ExternalStorageStats afterRename = stats.queryExternalStatsForUser(UUID_DEFAULT, user);
 
         assertMostlyEquals(17 * MB_IN_BYTES, afterRename.getTotalBytes() - before.getTotalBytes());
         assertMostlyEquals(5 * MB_IN_BYTES, afterRename.getAudioBytes() - before.getAudioBytes());
@@ -199,7 +205,7 @@
         logCommand("sync");
 
         final long manualSize = getSizeManual(Environment.getExternalStorageDirectory());
-        final long statsSize = stats.queryExternalStatsForUser(null, user).getTotalBytes();
+        final long statsSize = stats.queryExternalStatsForUser(UUID_DEFAULT, user).getTotalBytes();
 
         assertMostlyEquals(manualSize, statsSize);
     }
@@ -220,9 +226,10 @@
         final UserHandle user = android.os.Process.myUserHandle();
 
         final File filesDir = context.getFilesDir();
+        final UUID filesUuid = sm.getUuidForPath(filesDir);
 
-        final long beforeAllocatable = sm.getAllocatableBytes(filesDir, 0);
-        final long beforeFree = stats.getFreeBytes(null);
+        final long beforeAllocatable = sm.getAllocatableBytes(filesUuid, 0);
+        final long beforeFree = stats.getFreeBytes(UUID_DEFAULT);
         final long beforeRaw = filesDir.getUsableSpace();
 
         Log.d(TAG, "Before raw " + beforeRaw + ", free " + beforeFree + ", allocatable "
@@ -239,16 +246,16 @@
         // Apps using up some cache space shouldn't change how much we can
         // allocate, or how much we think is free; but it should decrease real
         // disk space.
-        if (stats.isQuotaSupported(null)) {
+        if (stats.isQuotaSupported(UUID_DEFAULT)) {
             assertMostlyEquals(beforeAllocatable,
-                    sm.getAllocatableBytes(filesDir, 0), 10 * MB_IN_BYTES);
+                    sm.getAllocatableBytes(filesUuid, 0), 10 * MB_IN_BYTES);
             assertMostlyEquals(beforeFree,
-                    stats.getFreeBytes(null), 10 * MB_IN_BYTES);
+                    stats.getFreeBytes(UUID_DEFAULT), 10 * MB_IN_BYTES);
         } else {
             assertMostlyEquals(beforeAllocatable - totalAllocated,
-                    sm.getAllocatableBytes(filesDir, 0), 10 * MB_IN_BYTES);
+                    sm.getAllocatableBytes(filesUuid, 0), 10 * MB_IN_BYTES);
             assertMostlyEquals(beforeFree - totalAllocated,
-                    stats.getFreeBytes(null), 10 * MB_IN_BYTES);
+                    stats.getFreeBytes(UUID_DEFAULT), 10 * MB_IN_BYTES);
         }
         assertMostlyEquals(beforeRaw - totalAllocated,
                 filesDir.getUsableSpace(), 10 * MB_IN_BYTES);
@@ -259,7 +266,7 @@
         // Allocate some space for ourselves, which should trim away at
         // over-quota app first, even though its files are newer.
         final long clear1 = filesDir.getUsableSpace() + (targetB / 2);
-        sm.allocateBytes(filesDir, clear1, 0);
+        sm.allocateBytes(filesUuid, clear1, 0);
 
         assertMostlyEquals(targetA, getCacheBytes(PKG_A, user));
         assertMostlyEquals(targetB / 2, getCacheBytes(PKG_B, user), 2 * MB_IN_BYTES);
@@ -269,7 +276,7 @@
         // they're tied for cache ratios, we expect to clear about half of the
         // remaining space from each of them.
         final long clear2 = filesDir.getUsableSpace() + (targetB / 2);
-        sm.allocateBytes(filesDir, clear2, 0);
+        sm.allocateBytes(filesUuid, clear2, 0);
 
         assertMostlyEquals(targetA / 2, getCacheBytes(PKG_A, user), 2 * MB_IN_BYTES);
         assertMostlyEquals(targetA / 2, getCacheBytes(PKG_B, user), 2 * MB_IN_BYTES);
@@ -313,7 +320,7 @@
         tomb.setLastModified(tombTime);
 
         final long clear1 = group.getUsableSpace() + (8 * MB_IN_BYTES);
-        sm.allocateBytes(group, clear1, 0);
+        sm.allocateBytes(sm.getUuidForPath(group), clear1, 0);
 
         assertTrue(a.exists());
         assertTrue(b.exists());
@@ -327,9 +334,9 @@
         assertTrue(i.exists()); assertEquals(0, i.length());
     }
 
-    private long getCacheBytes(String pkg, UserHandle user) {
+    private long getCacheBytes(String pkg, UserHandle user) throws Exception {
         return getContext().getSystemService(StorageStatsManager.class)
-                .queryStatsForPackage(null, pkg, user).getCacheBytes();
+                .queryStatsForPackage(UUID_DEFAULT, pkg, user).getCacheBytes();
     }
 
     private long doAllocateReceiver(String pkg, double fraction, long time) throws Exception {
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DelegationTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DelegationTest.java
index 302f9da..c9cf648 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DelegationTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DelegationTest.java
@@ -44,6 +44,7 @@
     private static final String DELEGATE_PKG = "com.android.cts.delegate";
     private static final String DELEGATE_ACTIVITY_NAME =
             DELEGATE_PKG + ".DelegatedScopesReceiverActivity";
+    private static final String TEST_PKG = "com.android.cts.apprestrictions.targetapp";
 
     // Broadcasts received from the delegate app.
     private static final String ACTION_REPORT_SCOPES = "com.android.cts.delegate.report_scopes";
@@ -130,6 +131,53 @@
                 .getDelegatedScopes(ADMIN_RECEIVER_COMPONENT, NON_EXISTENT_PKG).isEmpty());
     }
 
+    public void testCanRetrieveDelegates() {
+        final List<String> someScopes = Arrays.asList(
+                DELEGATION_APP_RESTRICTIONS,
+                DELEGATION_ENABLE_SYSTEM_APP);
+        final List<String> otherScopes = Arrays.asList(
+                DELEGATION_BLOCK_UNINSTALL,
+                DELEGATION_ENABLE_SYSTEM_APP);
+
+        // In the beginning there are no delegates.
+        assertTrue("No delegates should be found", getDelegatePackages(DELEGATION_APP_RESTRICTIONS)
+                .isEmpty());
+        assertTrue("No delegates should be found", getDelegatePackages(DELEGATION_BLOCK_UNINSTALL)
+                .isEmpty());
+        assertTrue("No delegates should be found", getDelegatePackages(DELEGATION_ENABLE_SYSTEM_APP)
+                .isEmpty());
+
+        // After delegating scopes to two packages.
+        mDevicePolicyManager.setDelegatedScopes(ADMIN_RECEIVER_COMPONENT,
+                DELEGATE_PKG, someScopes);
+        mDevicePolicyManager.setDelegatedScopes(ADMIN_RECEIVER_COMPONENT,
+                TEST_PKG, otherScopes);
+
+        // The expected delegates are returned.
+        assertTrue("Expected delegate not found", getDelegatePackages(DELEGATION_APP_RESTRICTIONS)
+                .contains(DELEGATE_PKG));
+        assertTrue("Expected delegate not found", getDelegatePackages(DELEGATION_BLOCK_UNINSTALL)
+                .contains(TEST_PKG));
+        assertTrue("Expected delegate not found", getDelegatePackages(DELEGATION_ENABLE_SYSTEM_APP)
+                .contains(DELEGATE_PKG));
+        assertTrue("Expected delegate not found", getDelegatePackages(DELEGATION_ENABLE_SYSTEM_APP)
+                .contains(TEST_PKG));
+
+        // Packages are only returned in their recpective scopes.
+        assertFalse("Unexpected delegate package", getDelegatePackages(DELEGATION_APP_RESTRICTIONS)
+                .contains(TEST_PKG));
+        assertFalse("Unexpected delegate package", getDelegatePackages(DELEGATION_BLOCK_UNINSTALL)
+                .contains(DELEGATE_PKG));
+        assertFalse("Unexpected delegate package", getDelegatePackages(DELEGATION_CERT_INSTALL)
+                .contains(DELEGATE_PKG));
+        assertFalse("Unexpected delegate package", getDelegatePackages(DELEGATION_CERT_INSTALL)
+                .contains(TEST_PKG));
+    }
+
+    private List<String> getDelegatePackages(String scope) {
+        return mDevicePolicyManager.getDelegatePackages(ADMIN_RECEIVER_COMPONENT, scope);
+    }
+
     private void startAndWaitDelegateActivity() throws InterruptedException {
         mContext.startActivity(new Intent()
                 .setComponent(new ComponentName(DELEGATE_PKG, DELEGATE_ACTIVITY_NAME))
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/AdminActionBookkeepingTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/AdminActionBookkeepingTest.java
index ff51e9e..0694d76 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/AdminActionBookkeepingTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/AdminActionBookkeepingTest.java
@@ -16,7 +16,6 @@
 package com.android.cts.deviceowner;
 
 import android.app.admin.DevicePolicyManager;
-import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.os.Process;
@@ -25,7 +24,6 @@
 import com.android.org.conscrypt.TrustedCertificateStore;
 
 import java.io.ByteArrayInputStream;
-import java.lang.reflect.Method;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateFactory;
 import java.util.List;
@@ -133,9 +131,7 @@
         mDevicePolicyManager.setNetworkLoggingEnabled(getWho(), true);
 
         long timeBefore = System.currentTimeMillis();
-        final Method retrieveNetworkLogsMethod = DevicePolicyManager.class.getDeclaredMethod(
-                "retrieveNetworkLogs", ComponentName.class, long.class);
-        retrieveNetworkLogsMethod.invoke(mDevicePolicyManager, getWho(), 0 /* batchToken */);
+        mDevicePolicyManager.retrieveNetworkLogs(getWho(), 0 /* batchToken */);
         long timeAfter = System.currentTimeMillis();
 
         final long newTimestamp = mDevicePolicyManager.getLastNetworkLogRetrievalTime();
diff --git a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBgVsFgActions.java b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBgVsFgActions.java
index 7528cac..4570cdf 100644
--- a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBgVsFgActions.java
+++ b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBgVsFgActions.java
@@ -16,11 +16,14 @@
 
 package com.android.server.cts.device.batterystats;
 
+import android.accounts.Account;
+import android.app.Activity;
 import android.app.ActivityManager;
 import android.content.BroadcastReceiver;
 import android.app.job.JobInfo;
 import android.app.job.JobScheduler;
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -31,6 +34,7 @@
 import android.os.Looper;
 import android.util.Log;
 
+
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -40,6 +44,7 @@
 
     public static final String KEY_ACTION = "action";
     public static final String ACTION_JOB_SCHEDULE = "action.jobs";
+    public static final String ACTION_SYNC = "action.sync";
     public static final String ACTION_WIFI_SCAN = "action.wifi_scan";
 
     /** Perform the action specified by the given action code (see constants above). */
@@ -53,6 +58,9 @@
             case ACTION_JOB_SCHEDULE:
                 doScheduleJob(ctx);
                 break;
+            case ACTION_SYNC:
+                doSync(ctx);
+                break;
             case ACTION_WIFI_SCAN:
                 doWifi(ctx);
                 break;
@@ -86,6 +94,41 @@
         }.execute();
     }
 
+    private static void doSync(Context ctx) {
+        BatteryStatsAuthenticator.removeAllAccounts(ctx);
+        final Account account = BatteryStatsAuthenticator.getTestAccount();
+        // Create the test account.
+        BatteryStatsAuthenticator.ensureTestAccount(ctx);
+        // Force set is syncable.
+        ContentResolver.setMasterSyncAutomatically(true);
+        ContentResolver.setIsSyncable(account, BatteryStatsProvider.AUTHORITY, 1);
+
+        new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(Void... params) {
+                try {
+                    Log.v(TAG, "Starting sync");
+                    BatteryStatsSyncAdapter.requestSync(account);
+                    sleep(500);
+                } catch (Exception e) {
+                    Log.e(TAG, "Exception trying to sync", e);
+                }
+                BatteryStatsAuthenticator.removeAllAccounts(ctx);
+                return null;
+            }
+
+            @Override
+            protected void onPostExecute(Void aVoid) {
+                super.onPostExecute(aVoid);
+                Log.v(TAG, "Finished sync method");
+                // If ctx is an Activity, finish it when sync is done. If it's a service, don't.
+                if(ctx instanceof Activity){
+                    ((Activity) ctx).finish();
+                }
+            }
+        }.execute();
+    }
+
     private static void doWifi(Context ctx) {
         IntentFilter intentFilter = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
         CountDownLatch onReceiveLatch = new CountDownLatch(1);
diff --git a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsForegroundActivity.java b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsForegroundActivity.java
index d6869a1..c41b244 100644
--- a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsForegroundActivity.java
+++ b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsForegroundActivity.java
@@ -18,6 +18,7 @@
 
 import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions
         .ACTION_JOB_SCHEDULE;
+import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions.ACTION_SYNC;
 import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions.KEY_ACTION;
 import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions.doAction;
 import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions.isAppInBackground;
@@ -51,7 +52,12 @@
             Log.w(TAG, "Couldn't determine if app is in foreground. Proceeding with test anyway");
         }
 
-        doAction(this, intent.getStringExtra(KEY_ACTION));
-        finish();
+        String action = intent.getStringExtra(KEY_ACTION);
+        doAction(this, action);
+
+        // ACTION_SYNC will finish itself. Others get finished here.
+        if (!ACTION_SYNC.equals(action)) {
+            finish();
+        }
     }
 }
diff --git a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsProcessStateTests.java b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsProcessStateTests.java
index c619166..c40c950 100644
--- a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsProcessStateTests.java
+++ b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsProcessStateTests.java
@@ -34,12 +34,7 @@
     public void testForegroundService() throws Exception {
         Intent intent = new Intent();
         intent.setClass(mContext, SimpleForegroundService.class);
-        Notification notification = new Notification.Builder(mContext, "Foreground Service")
-                .setContentTitle("CTS Foreground")
-                .setSmallIcon(android.R.drawable.ic_secure)
-                .build();
-        mContext.getSystemService(NotificationManager.class).startServiceInForeground(intent,
-                1, notification);
+        mContext.startForegroundService(intent);
         Thread.sleep(3000);
     }
 
diff --git a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsWifiTransferTests.java b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsWifiTransferTests.java
index 394a070..de0954d 100644
--- a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsWifiTransferTests.java
+++ b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsWifiTransferTests.java
@@ -63,6 +63,9 @@
     /** String extra of any error encountered during wifi transfer. */
     private static final String EXTRA_TRANSFER_ERROR = "transfer_error";
 
+    /** String extra: the service is required to startForeground() */
+    private static final String EXTRA_FOREGROUND = "fg";
+
     private static final int READ_BUFFER_SIZE = 4096;
 
     /** Server to send requests to. */
@@ -120,15 +123,10 @@
         if (!mHasFeature) {
             return;
         }
-        mTransferService.putExtra(EXTRA_ACTION, action);
-        Notification notification =
-            new Notification.Builder(mContext, "Wifi Transfer Foreground Service")
-                    .setContentTitle("Wifi Transfer Foreground")
-                    .setContentText("Wifi Transfer Foreground")
-                    .setSmallIcon(android.R.drawable.ic_secure)
-                    .build();
-        mContext.getSystemService(NotificationManager.class).startServiceInForeground(mTransferService,
-                1, notification);
+        Intent launchIntent = new Intent(mTransferService)
+                .putExtra(EXTRA_ACTION, action)
+                .putExtra(EXTRA_FOREGROUND, true);
+        mContext.startForegroundService(launchIntent);
 
         mResultsReceivedSignal.await(10, TimeUnit.SECONDS);
         assertTrue("Got error: " + mError, mError == null);
@@ -155,6 +153,16 @@
 
         @Override
         protected void onHandleIntent(Intent intent) {
+            if (intent.getBooleanExtra(EXTRA_FOREGROUND, false)) {
+                Notification notification =
+                        new Notification.Builder(this, "Wifi Transfer Foreground Service")
+                                .setContentTitle("Wifi Transfer Foreground")
+                                .setContentText("Wifi Transfer Foreground")
+                                .setSmallIcon(android.R.drawable.ic_secure)
+                                .build();
+                startForeground(1, notification);
+            }
+
             String error = null;
             switch (intent.getStringExtra(EXTRA_ACTION)) {
                 case ACTION_DOWNLOAD:
diff --git a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/SimpleForegroundService.java b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/SimpleForegroundService.java
index b8d4507..ed21615 100644
--- a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/SimpleForegroundService.java
+++ b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/SimpleForegroundService.java
@@ -16,6 +16,7 @@
 
 package com.android.server.cts.device.batterystats;
 
+import android.app.Notification;
 import android.app.Service;
 import android.content.Intent;
 import android.os.Handler;
@@ -67,6 +68,12 @@
 
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
+        Notification notification = new Notification.Builder(this, "Foreground Service")
+                .setContentTitle("CTS Foreground")
+                .setSmallIcon(android.R.drawable.ic_secure)
+                .build();
+        startForeground(1, notification);
+
         Message msg = mServiceHandler.obtainMessage();
         msg.arg1 = startId;
         mServiceHandler.sendMessage(msg);
diff --git a/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java b/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java
index f6e9e31..3a96ccb 100644
--- a/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java
@@ -42,6 +42,7 @@
     // Constants from BatteryStatsBgVsFgActions.java (not directly accessible here).
     public static final String KEY_ACTION = "action";
     public static final String ACTION_JOB_SCHEDULE = "action.jobs";
+    public static final String ACTION_SYNC = "action.sync";
     public static final String ACTION_WIFI_SCAN = "action.wifi_scan";
 
     @Override
@@ -136,6 +137,26 @@
         batteryOffScreenOn();
     }
 
+    public void testSyncBgVsFg() throws Exception {
+        batteryOnScreenOff();
+        installPackage(DEVICE_SIDE_TEST_APK, true);
+
+        // Foreground test.
+        executeForeground(ACTION_SYNC);
+        Thread.sleep(3_000);
+        // Allow one or two syncs in this time frame (not just one) due to unpredictable syncs.
+        assertValueRange("sy", DEVICE_SIDE_SYNC_COMPONENT, 6, 1, 2); // count
+        assertValueRange("sy", DEVICE_SIDE_SYNC_COMPONENT, 8, 0, 0); // background_count
+
+        // Background test.
+        executeBackground(ACTION_SYNC);
+        Thread.sleep(3_000);
+        assertValueRange("sy", DEVICE_SIDE_SYNC_COMPONENT, 6, 2, 4); // count
+        assertValueRange("sy", DEVICE_SIDE_SYNC_COMPONENT, 8, 1, 2); // background_count
+
+        batteryOffScreenOn();
+    }
+
     public void testWifiScans() throws Exception {
         batteryOnScreenOff();
         installPackage(DEVICE_SIDE_TEST_APK, true);
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java
index 2fc0bc2..0f2965c 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java
@@ -143,6 +143,8 @@
         assertBackgroundNetworkAccess(true);
         setBatterySaverMode(true);
         assertBackgroundNetworkAccess(false);
+        // Use setBatterySaverMode API to leave power-save mode instead of plugging in charger
+        setBatterySaverMode(false);
         turnBatteryOn();
         assertBackgroundNetworkAccess(true);
 
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 15daed9..b6857ae 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
@@ -100,6 +100,7 @@
     protected ConnectivityManager mCm;
     protected WifiManager mWfm;
     protected int mUid;
+    private int mMyUid;
     private String mMeteredWifi;
     private MyServiceClient mServiceClient;
     private boolean mHasWatch;
@@ -115,7 +116,7 @@
         mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
         mWfm = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
         mUid = getUid(TEST_APP2_PKG);
-        final int myUid = getUid(mContext.getPackageName());
+        mMyUid = getUid(mContext.getPackageName());
         mServiceClient = new MyServiceClient(mContext);
         mServiceClient.bind();
         mHasWatch = mContext.getPackageManager().hasSystemFeature(
@@ -128,7 +129,7 @@
         mSupported = setUpActiveNetworkMeteringState();
 
         Log.i(TAG, "Apps status on " + getName() + ":\n"
-                + "\ttest app: uid=" + myUid + ", state=" + getProcessStateByUid(myUid) + "\n"
+                + "\ttest app: uid=" + mMyUid + ", state=" + getProcessStateByUid(mMyUid) + "\n"
                 + "\tapp2: uid=" + mUid + ", state=" + getProcessStateByUid(mUid));
    }
 
@@ -204,6 +205,21 @@
         assertEquals("wrong status", toString(expectedStatus), actualStatus);
     }
 
+    protected void assertMyRestrictBackgroundStatus(int expectedStatus) throws Exception {
+        final int actualStatus = mCm.getRestrictBackgroundStatus();
+        assertEquals("Wrong status", toString(expectedStatus), toString(actualStatus));
+    }
+
+    protected boolean isMyRestrictBackgroundStatus(int expectedStatus) throws Exception {
+        final int actualStatus = mCm.getRestrictBackgroundStatus();
+        if (expectedStatus != actualStatus) {
+            Log.d(TAG, "Expected: " + toString(expectedStatus)
+                    + " but actual: " + toString(actualStatus));
+            return false;
+        }
+        return true;
+    }
+
     protected void assertBackgroundNetworkAccess(boolean expectAllowed) throws Exception {
         assertBackgroundState(); // Sanity check.
         assertNetworkAccess(expectAllowed);
@@ -700,9 +716,9 @@
         Log.i(TAG, "Setting Battery Saver Mode to " + enabled);
         if (enabled) {
             turnBatteryOff();
-            executeSilentShellCommand("settings put global low_power 1");
+            executeSilentShellCommand("cmd power set-mode 1");
         } else {
-            executeSilentShellCommand("settings put global low_power 0");
+            executeSilentShellCommand("cmd power set-mode 0");
             turnBatteryOn();
         }
     }
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
index c3537c8..599a31c 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
@@ -20,16 +20,21 @@
 import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
 import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED;
 
+import android.util.Log;
+
 public class DataSaverModeTest extends AbstractRestrictBackgroundNetworkTestCase {
 
     private static final String[] REQUIRED_WHITELISTED_PACKAGES = {
         "com.android.providers.downloads"
     };
 
+    private boolean mIsDataSaverSupported;
+
     @Override
     public void setUp() throws Exception {
         super.setUp();
 
+        mIsDataSaverSupported = isDataSaverSupported();
         if (!isSupported()) return;
 
         // Set initial state.
@@ -59,6 +64,32 @@
         return setMeteredNetwork();
     }
 
+    @Override
+    protected boolean isSupported() throws Exception {
+        if (!mIsDataSaverSupported) {
+            Log.i(TAG, "Skipping " + getClass() + "." + getName()
+                    + "() because device does not support Data Saver Mode");
+        }
+        return mIsDataSaverSupported && super.isSupported();
+    }
+
+    /**
+     * As per CDD requirements, if the device doesn't support data saver mode then
+     * ConnectivityManager.getRestrictBackgroundStatus() will always return
+     * RESTRICT_BACKGROUND_STATUS_DISABLED. So, enable the data saver mode and check if
+     * ConnectivityManager.getRestrictBackgroundStatus() for an app in background returns
+     * RESTRICT_BACKGROUND_STATUS_DISABLED or not.
+     */
+    private boolean isDataSaverSupported() throws Exception {
+        assertMyRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_DISABLED);
+        try {
+            setRestrictBackground(true);
+            return !isMyRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_DISABLED);
+        } finally {
+            setRestrictBackground(false);
+        }
+    }
+
     public void testGetRestrictBackgroundStatus_disabled() throws Exception {
         if (!isSupported()) return;
 
diff --git a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
index 8ed60e6..46779de 100644
--- a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
+++ b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
@@ -251,9 +251,9 @@
     /**
      * Asserts that no vendor domains are exempted from the prohibition on Binder use.
      *
-     * <p>NOTE: There's no explicit CDD requirement for this because this is a temporary crutch
-     * during Android O development. This test will be removed before Android O.
-     * TODO(b/35870313): Remove this test once b/35870313 is fixed.
+     * <p>NOTE: binder_in_vendor_violators attribute is only there to help bring up Treble devices.
+     * It offers a convenient way to temporarily bypass the prohibition on Binder use in vendor
+     * domains. This attribute must not be used on production Treble devices.
      */
     public void testNoExemptionsForBinderInVendorBan() throws Exception {
         if (!isFullTrebleDevice()) {
@@ -273,9 +273,10 @@
      * Asserts that no domains are exempted from the prohibition on initiating socket communications
      * between core and vendor domains.
      *
-     * <p>NOTE: There's no explicit CDD requirement for this because this is a temporary crutch
-     * during Android O development. This test will be removed before Android O.
-     * TODO(b/36577153): Remove this test once b/36577153 is fixed.
+     * <p>NOTE: socket_between_core_and_vendor_violators attribute is only there to help bring up
+     * Treble devices. It offers a convenient way to temporarily bypass the prohibition on
+     * initiating socket communications between core and vendor domains. This attribute must not be
+     * used on production Treble devices.
      */
     public void testNoExemptionsForSocketsBetweenCoreAndVendorBan() throws Exception {
         if (!isFullTrebleDevice()) {
@@ -295,52 +296,25 @@
 
     /**
      * Asserts that no vendor domains are exempted from the prohibition on directly
-     * accessing /data outside /data/vendor.
-     *
-     * <p>NOTE: There's no explicit CDD requirement for this because this is a temporary crutch
-     * during Android O development. This test will be removed before Android O.
-     * TODO(b/34980020): Remove this test once b/34980020 is fixed.
-     */
-    public void testNoExemptionsForCoreDataInVendor() throws Exception {
+     * executing binaries from /system.
+     * */
+    public void testNoExemptionsForVendorExecutingCore() throws Exception {
         if (!isFullTrebleDevice()) {
             return;
         }
 
         Set<String> types =
                 sepolicyAnalyzeGetTypesAssociatedWithAttribute(
-                        "coredata_in_vendor_violators");
+                        "vendor_executes_system_violators");
         if (!types.isEmpty()) {
             List<String> sortedTypes = new ArrayList<>(types);
             Collections.sort(sortedTypes);
-            fail("Policy exempts domains from ban on vendor domains accessing data partition"
-                    + " outside /data/vendor: " + sortedTypes);
+            fail("Policy exempts vendor domains from ban on executing files in /system: "
+                    + sortedTypes);
         }
     }
 
     /**
-     * Asserts that no core domains are exempted from the prohibition on directly
-     * accessing /data/vendor.
-     *
-     * <p>NOTE: There's no explicit CDD requirement for this because this is a temporary crutch
-     * during Android O development. This test will be removed before Android O.
-     * TODO(b/34980020): Remove this test once b/34980020 is fixed.
-     */
-    public void testNoExemptionsForVendorDataInCore() throws Exception {
-        if (!isFullTrebleDevice()) {
-            return;
-        }
-
-        Set<String> types =
-                sepolicyAnalyzeGetTypesAssociatedWithAttribute(
-                        "vendordata_in_core_violators");
-        if (!types.isEmpty()) {
-            List<String> sortedTypes = new ArrayList<>(types);
-            Collections.sort(sortedTypes);
-            fail("Policy exempts domains from ban on core domains accessing vendor data"
-                    + " in /data/vendor: " + sortedTypes);
-        }
-    }
-    /**
      * Tests that mlstrustedsubject does not include untrusted_app
      * and that mlstrustedobject does not include app_data_file.
      * This helps prevent circumventing the per-user isolation of
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/AndroidManifest.xml b/hostsidetests/services/activityandwindowmanager/activitymanager/app/AndroidManifest.xml
index 3cdc754..d7800c4 100755
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/app/AndroidManifest.xml
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/AndroidManifest.xml
@@ -90,6 +90,14 @@
                 android:exported="true"
                 android:taskAffinity="nobody.but.PipActivity"
         />
+        <activity android:name=".PipActivity2"
+                  android:resizeableActivity="false"
+                  android:supportsPictureInPicture="true"
+                  android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
+                  android:exported="true"
+                  android:taskAffinity="nobody.but.PipActivity2"
+        />
+
         <activity android:name=".AlwaysFocusablePipActivity"
                   android:theme="@style/Theme.Transparent"
                   android:resizeableActivity="false"
@@ -325,6 +333,11 @@
                  android:permission="android.permission.BIND_VOICE_INTERACTION"
                  android:exported="true" />
 
+        <activity android:name=".SplashscreenActivity"
+            android:taskAffinity="nobody.but.SplashscreenActivity"
+            android:theme="@style/SplashscreenTheme"
+            android:exported="true" />
+
         <service android:name="com.android.cts.verifier.vr.MockVrListenerService"
                  android:exported="true"
                  android:enabled="true"
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/res/values/colors.xml b/hostsidetests/services/activityandwindowmanager/activitymanager/app/res/values/colors.xml
new file mode 100644
index 0000000..2a51310
--- /dev/null
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/res/values/colors.xml
@@ -0,0 +1,19 @@
+<!--
+  ~ Copyright (C) 2017 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT 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>
+    <drawable name="red">#ff0000</drawable>
+</resources>
\ No newline at end of file
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/res/values/styles.xml b/hostsidetests/services/activityandwindowmanager/activitymanager/app/res/values/styles.xml
index 7fc6725..5068ea9 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/app/res/values/styles.xml
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/res/values/styles.xml
@@ -40,4 +40,7 @@
     <style name="NoPreview">
         <item name="android:windowDisablePreview">true</item>
     </style>
+    <style name="SplashscreenTheme" parent="@android:style/Theme.Material.NoActionBar">
+        <item name="android:windowSplashscreenContent">@drawable/red</item>
+    </style>
 </resources>
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivity2.java b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivity2.java
new file mode 100644
index 0000000..53b4f75
--- /dev/null
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivity2.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.cts;
+
+/**
+ * A secondary activity that has the same behavior as {@link PipActivity}.
+ */
+public class PipActivity2 extends PipActivity {
+}
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/SplashscreenActivity.java b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/SplashscreenActivity.java
new file mode 100644
index 0000000..22391bd
--- /dev/null
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/SplashscreenActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.SystemClock;
+
+/**
+ * Activity that shows a custom splashscreen when being launched.
+ */
+public class SplashscreenActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        // Make sure splash screen is visible. The test won't take 5 seconds because the condition
+        // such that we can dump the state will trigger much earlier and then the test will just
+        // kill us.
+        SystemClock.sleep(5000);
+    }
+}
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/VirtualDisplayActivity.java b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/VirtualDisplayActivity.java
index a31e985..8374f7c 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/VirtualDisplayActivity.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/VirtualDisplayActivity.java
@@ -18,8 +18,6 @@
 
 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
-import static android.hardware.display.DisplayManager
-        .VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
 
 import android.app.Activity;
 import android.content.Intent;
@@ -42,8 +40,6 @@
 
     private static final int DEFAULT_DENSITY_DPI = 160;
     private static final String KEY_DENSITY_DPI = "density_dpi";
-    private static final String KEY_CAN_SHOW_WITH_INSECURE_KEYGUARD
-            = "can_show_with_insecure_keyguard";
     private static final String KEY_PUBLIC_DISPLAY = "public_display";
     private static final String KEY_RESIZE_DISPLAY = "resize_display";
     private static final String KEY_COUNT = "count";
@@ -165,20 +161,13 @@
 
         int flags = 0;
 
-        final boolean canShowWithInsecureKeyguard
-                = entry.extras.getBoolean(KEY_CAN_SHOW_WITH_INSECURE_KEYGUARD);
-        if (canShowWithInsecureKeyguard) {
-            flags |= VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
-        }
-
         final boolean publicDisplay = entry.extras.getBoolean(KEY_PUBLIC_DISPLAY);
         if (publicDisplay) {
             flags |= VIRTUAL_DISPLAY_FLAG_PUBLIC | VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
         }
 
         Log.d(TAG, "createVirtualDisplay: " + width + "x" + height + ", dpi: "
-                + densityDpi + ", canShowWithInsecureKeyguard=" + canShowWithInsecureKeyguard
-                + ", publicDisplay=" + publicDisplay);
+                + densityDpi + ", publicDisplay=" + publicDisplay);
         try {
             VirtualDisplay virtualDisplay = mDisplayManager.createVirtualDisplay(
                     "VirtualDisplay" + mVirtualDisplays.size(), width,
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerActivityVisibilityTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerActivityVisibilityTests.java
index 5665c29..c89b9c4 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerActivityVisibilityTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerActivityVisibilityTests.java
@@ -18,9 +18,15 @@
 
 import static android.server.cts.ActivityManagerState.STATE_RESUMED;
 
+import android.platform.test.annotations.Presubmit;
+
 import java.lang.Exception;
 import java.lang.String;
 
+import static com.android.ddmlib.Log.LogLevel.INFO;
+
+import com.android.tradefed.log.LogUtil.CLog;
+
 /**
  * Build: mmma -j32 cts/hostsidetests/services
  * Run: cts/hostsidetests/services/activityandwindowmanager/util/run-test CtsServicesHostTestCases android.server.cts.ActivityManagerActivityVisibilityTests
@@ -142,6 +148,11 @@
     }
 
     public void testTranslucentActivityOverDockedStack() throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(INFO, "Skipping test: no multi-window support");
+            return;
+        }
+
         launchActivityInDockStack(DOCKED_ACTIVITY_NAME);
         mAmWmState.computeState(mDevice, new String[] {DOCKED_ACTIVITY_NAME});
         launchActivityInStack(TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID);
@@ -157,6 +168,7 @@
         mAmWmState.assertVisibility(TRANSLUCENT_ACTIVITY_NAME, true);
     }
 
+    @Presubmit
     public void testTurnScreenOnActivity() throws Exception {
         sleepDevice();
         launchActivity(TURN_SCREEN_ON_ACTIVITY_NAME);
@@ -165,6 +177,11 @@
     }
 
     public void testFinishActivityInNonFocusedStack() throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(INFO, "Skipping test: no multi-window support");
+            return;
+        }
+
         // Launch two activities in docked stack.
         launchActivityInDockStack(LAUNCHING_ACTIVITY);
         getLaunchActivityBuilder().setTargetActivityName(BROADCAST_RECEIVER_ACTIVITY).execute();
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerAppConfigurationTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerAppConfigurationTests.java
index 284f1a7..31f82ac 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerAppConfigurationTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerAppConfigurationTests.java
@@ -55,6 +55,11 @@
      * docked state.
      */
     public void testConfigurationUpdatesWhenResizedFromFullscreen() throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
+            return;
+        }
+
         String logSeparator = clearLogcat();
         launchActivityInStack(RESIZEABLE_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID);
         final ReportedSizes fullscreenSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
@@ -73,6 +78,11 @@
      * from docked state to fullscreen (reverse).
      */
     public void testConfigurationUpdatesWhenResizedFromDockedStack() throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
+            return;
+        }
+
         String logSeparator = clearLogcat();
         launchActivityInStack(RESIZEABLE_ACTIVITY_NAME, DOCKED_STACK_ID);
         final ReportedSizes dockedSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
@@ -103,7 +113,13 @@
      * Same as {@link #testConfigurationUpdatesWhenRotatingWhileFullscreen()} but when the Activity
      * is in the docked stack.
      */
+    @Presubmit
     public void testConfigurationUpdatesWhenRotatingWhileDocked() throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
+            return;
+        }
+
         setDeviceRotation(0);
         final String logSeparator = clearLogcat();
         launchActivityInDockStack(LAUNCHING_ACTIVITY);
@@ -124,6 +140,11 @@
      * is launched to side from docked stack.
      */
     public void testConfigurationUpdatesWhenRotatingToSideFromDocked() throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
+            return;
+        }
+
         setDeviceRotation(0);
 
         final String logSeparator = clearLogcat();
@@ -171,6 +192,7 @@
     /**
      * Same as {@link #testSameConfigurationFullSplitFullRelaunch} but without relaunch.
      */
+    @Presubmit
     public void testSameConfigurationFullSplitFullNoRelaunch() throws Exception {
         moveActivityFullSplitFull(RESIZEABLE_ACTIVITY_NAME);
     }
@@ -183,6 +205,11 @@
      * Asserts that initial and final reported sizes in fullscreen stack are the same.
      */
     private void moveActivityFullSplitFull(String activityName) throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
+            return;
+        }
+
         // Launch to fullscreen stack and record size.
         String logSeparator = clearLogcat();
         launchActivityInStack(activityName, FULLSCREEN_WORKSPACE_STACK_ID);
@@ -367,6 +394,11 @@
      * Asserts that initial and final reported sizes in docked stack are the same.
      */
     private void moveActivitySplitFullSplit(String activityName) throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
+            return;
+        }
+
         // Launch to docked stack and record size.
         String logSeparator = clearLogcat();
         launchActivityInStack(activityName, DOCKED_STACK_ID);
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerConfigChangeTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerConfigChangeTests.java
index ba56639..cf4f803 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerConfigChangeTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerConfigChangeTests.java
@@ -16,9 +16,14 @@
 
 package android.server.cts;
 
+import android.platform.test.annotations.Presubmit;
+
 import static android.server.cts.ActivityManagerState.STATE_RESUMED;
 import static android.server.cts.StateLogger.logE;
 
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.log.LogUtil.CLog;
+
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -51,11 +56,13 @@
         testRotation(NO_RELAUNCH_ACTIVITY_NAME, 2, 0, 0);
     }
 
+    @Presubmit
     public void testChangeFontScaleRelaunch() throws Exception {
         // Should relaunch and receive no onConfigurationChanged()
         testChangeFontScale(TEST_ACTIVITY_NAME, true /* relaunch */);
     }
 
+    @Presubmit
     public void testChangeFontScaleNoRelaunch() throws Exception {
         // Should receive onConfigurationChanged() and no relaunch
         testChangeFontScale(NO_RELAUNCH_ACTIVITY_NAME, false /* relaunch */);
@@ -69,8 +76,21 @@
         final String[] waitForActivitiesVisible = new String[] {activityName};
         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
 
-        setDeviceRotation(4 - rotationStep);
+        final int initialRotation = 4 - rotationStep;
+        setDeviceRotation(initialRotation);
         mAmWmState.computeState(mDevice, waitForActivitiesVisible);
+        final int actualStackId = mAmWmState.getAmState().getTaskByActivityName(
+                activityName).mStackId;
+        final int displayId = mAmWmState.getAmState().getStackById(actualStackId).mDisplayId;
+        final int newDeviceRotation = getDeviceRotation(displayId);
+        if (newDeviceRotation == INVALID_DEVICE_ROTATION) {
+            CLog.logAndDisplay(LogLevel.WARN, "Got an invalid device rotation value. "
+                    + "Continuing the test despite of that, but it is likely to fail.");
+        } else if (newDeviceRotation != initialRotation) {
+            CLog.logAndDisplay(LogLevel.INFO, "This device doesn't support user rotation "
+                    + "mode. Not continuing the rotation checks.");
+            return;
+        }
 
         for (int rotation = 0; rotation < 4; rotation += rotationStep) {
             final String logSeparator = clearLogcat();
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTests.java
index ea25e04..cda836f 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTests.java
@@ -15,6 +15,8 @@
  */
 package android.server.cts;
 
+import android.platform.test.annotations.Presubmit;
+
 import com.android.tradefed.device.CollectingOutputReceiver;
 import com.android.tradefed.device.DeviceNotAvailableException;
 
@@ -345,6 +347,7 @@
     /**
      * Tests launching an activity on virtual display.
      */
+    @Presubmit
     public void testLaunchActivityOnSecondaryDisplay() throws Exception {
         if (!supportsMultiDisplay()) { return; }
 
@@ -381,6 +384,7 @@
      * command and without specifying the display id - the second activity must appear on the
      * primary display.
      */
+    @Presubmit
     public void testConsequentLaunchActivity() throws Exception {
         if (!supportsMultiDisplay()) { return; }
 
@@ -413,6 +417,7 @@
      * Tests launching an activity on virtual display and then launching another activity from the
      * first one - it must appear on the secondary display, because it was launched from there.
      */
+    @Presubmit
     public void testConsequentLaunchActivityFromSecondaryDisplay() throws Exception {
         if (!supportsMultiDisplay()) { return; }
 
@@ -474,6 +479,7 @@
      * Tests launching activities on secondary and then on primary display to see if the stack
      * visibility is not affected.
      */
+    @Presubmit
     public void testLaunchActivitiesAffectsVisibility() throws Exception {
         if (!supportsMultiDisplay()) { return; }
 
@@ -506,6 +512,7 @@
     /**
      * Test that move-task works when moving between displays.
      */
+    @Presubmit
     public void testMoveTaskBetweenDisplays() throws Exception {
         if (!supportsMultiDisplay()) { return; }
 
@@ -536,6 +543,7 @@
      * is moved correctly.
      * This version launches virtual display creator to fullscreen stack.
      */
+    @Presubmit
     public void testStackFocusSwitchOnDisplayRemoved() throws Exception {
         if (!supportsMultiDisplay()) { return; }
 
@@ -898,54 +906,9 @@
     }
 
     /**
-     * Test that show-with-insecure-keyguard virtual display is showing content when device is
-     * locked.
-     */
-    public void testShowWhenLockedVirtualDisplay() throws Exception {
-        if (!supportsMultiDisplay()) { return; }
-
-        // Create new show-with-insecure-keyguard virtual display.
-        final DisplayState newDisplay = new VirtualDisplayBuilder(this)
-                .setCanShowWithInsecureKeyguard(true)
-                .build();
-        mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
-
-        // Launch activity on new secondary display.
-        launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mDisplayId);
-        mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true /* visible */);
-
-        // Lock the device.
-        sleepDevice();
-        mAmWmState.waitForActivityState(mDevice, TEST_ACTIVITY_NAME, STATE_STOPPED);
-        mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true /* visible */);
-
-        // Unlock and check if visibility is back.
-        wakeUpAndUnlockDevice();
-        mAmWmState.waitForActivityState(mDevice, TEST_ACTIVITY_NAME, STATE_RESUMED);
-        mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true /* visible */);
-    }
-
-    /**
-     * Test that only private virtual display can show content with insecure keyguard.
-     */
-    public void testShowWhenLockedPublicVirtualDisplay() throws Exception {
-        if (!supportsMultiDisplay()) { return; }
-
-        // Try to create new show-with-insecure-keyguard public virtual display.
-        final DisplayState newDisplay = new VirtualDisplayBuilder(this)
-                .setPublicDisplay(true)
-                .setCanShowWithInsecureKeyguard(true)
-                .setMustBeCreated(false)
-                .build();
-
-        // Check that the display is not created.
-        mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
-        assertNull(newDisplay);
-    }
-
-    /**
      * Test that all activities that were on the private display are destroyed on display removal.
      */
+    @Presubmit
     public void testContentDestroyOnDisplayRemoved() throws Exception {
         if (!supportsMultiDisplay()) { return; }
 
@@ -1000,6 +963,7 @@
     /**
      * Test that the update of display metrics updates all its content.
      */
+    @Presubmit
     public void testDisplayResize() throws Exception {
         if (!supportsMultiDisplay()) { return; }
 
@@ -1080,6 +1044,7 @@
      * Tests that when activities that handle configuration changes are moved between displays,
      * they receive onMovedToDisplay and onConfigurationChanged callbacks.
      */
+    @Presubmit
     public void testOnMovedToDisplayCallback() throws Exception {
         if (!supportsMultiDisplay()) { return; }
 
@@ -1312,7 +1277,8 @@
      * Test that display overrides apply correctly and won't be affected by display changes.
      * This sets overrides to display size and density, initiates a display changed event by locking
      * and unlocking the phone and verifies that overrides are kept.
-     * */
+     */
+    @Presubmit
     public void testForceDisplayMetrics() throws Exception {
         launchHomeActivity();
 
@@ -1485,8 +1451,6 @@
      * @param densityDpi provide custom density for the display.
      * @param launchInSplitScreen start {@link VirtualDisplayActivity} to side from
      *                            {@link LaunchingActivity} on primary display.
-     * @param canShowWithInsecureKeyguard allow showing content when device is showing an insecure
-     *                                    keyguard.
      * @param publicDisplay make display public.
      * @param mustBeCreated should assert if the display was or wasn't created.
      * @param resizeDisplay should resize display when surface size changes.
@@ -1494,8 +1458,8 @@
      * @throws Exception
      */
     private List<DisplayState> createVirtualDisplays(int densityDpi, boolean launchInSplitScreen,
-            boolean canShowWithInsecureKeyguard, boolean publicDisplay, boolean mustBeCreated,
-            boolean resizeDisplay, int displayCount) throws Exception {
+            boolean publicDisplay, boolean mustBeCreated, boolean resizeDisplay, int displayCount)
+            throws Exception {
         // Start an activity that is able to create virtual displays.
         if (launchInSplitScreen) {
             getLaunchActivityBuilder().setToSide(true)
@@ -1509,8 +1473,8 @@
         final int originalDisplayCount = originalDS.mDisplayStates.size();
 
         // Create virtual display with custom density dpi.
-        executeShellCommand(getCreateVirtualDisplayCommand(densityDpi, canShowWithInsecureKeyguard,
-                publicDisplay, resizeDisplay, displayCount));
+        executeShellCommand(getCreateVirtualDisplayCommand(densityDpi, publicDisplay, resizeDisplay,
+                displayCount));
         mVirtualDisplayCreated = true;
 
         // Wait for the virtual display to be created and get configurations.
@@ -1711,7 +1675,6 @@
 
         private int mDensityDpi = CUSTOM_DENSITY_DPI;
         private boolean mLaunchInSplitScreen = false;
-        private boolean mCanShowWithInsecureKeyguard = false;
         private boolean mPublicDisplay = false;
         private boolean mMustBeCreated = true;
         private boolean mResizeDisplay = true;
@@ -1730,12 +1693,6 @@
             return this;
         }
 
-        public VirtualDisplayBuilder setCanShowWithInsecureKeyguard(
-                boolean canShowWithInsecureKeyguard) {
-            mCanShowWithInsecureKeyguard = canShowWithInsecureKeyguard;
-            return this;
-        }
-
         public VirtualDisplayBuilder setPublicDisplay(boolean publicDisplay) {
             mPublicDisplay = publicDisplay;
             return this;
@@ -1756,15 +1713,13 @@
         }
 
         public List<DisplayState> build(int count) throws Exception {
-            return mTests.createVirtualDisplays(mDensityDpi, mLaunchInSplitScreen,
-                    mCanShowWithInsecureKeyguard, mPublicDisplay, mMustBeCreated, mResizeDisplay,
-                    count);
+            return mTests.createVirtualDisplays(mDensityDpi, mLaunchInSplitScreen, mPublicDisplay,
+                    mMustBeCreated, mResizeDisplay, count);
         }
     }
 
-    private static String getCreateVirtualDisplayCommand(int densityDpi,
-            boolean canShowWithInsecureKeyguard, boolean publicDisplay, boolean resizeDisplay,
-            int displayCount) {
+    private static String getCreateVirtualDisplayCommand(int densityDpi, boolean publicDisplay,
+            boolean resizeDisplay, int displayCount) {
         final StringBuilder commandBuilder
                 = new StringBuilder(getAmStartCmd(VIRTUAL_DISPLAY_ACTIVITY));
         commandBuilder.append(" -f 0x20000000");
@@ -1773,8 +1728,6 @@
             commandBuilder.append(" --ei density_dpi ").append(densityDpi);
         }
         commandBuilder.append(" --ei count ").append(displayCount);
-        commandBuilder.append(" --ez can_show_with_insecure_keyguard ")
-                .append(canShowWithInsecureKeyguard);
         commandBuilder.append(" --ez public_display ").append(publicDisplay);
         commandBuilder.append(" --ez resize_display ").append(resizeDisplay);
         return commandBuilder.toString();
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
index 1cf60f4..d5ba74e 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
@@ -16,6 +16,9 @@
 
 package android.server.cts;
 
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.log.LogUtil.CLog;
+
 import java.awt.Rectangle;
 
 /**
@@ -36,6 +39,11 @@
     private static final int STACK_SIZE = 300;
 
     public void testStackList() throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+            return;
+        }
+
         launchActivity(TEST_ACTIVITY_NAME);
         mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
         mAmWmState.assertContainsStack("Must contain home stack.", HOME_STACK_ID);
@@ -45,6 +53,11 @@
     }
 
     public void testDockActivity() throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+            return;
+        }
+
         launchActivityInDockStack(TEST_ACTIVITY_NAME);
         mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
         mAmWmState.assertContainsStack("Must contain home stack.", HOME_STACK_ID);
@@ -52,6 +65,11 @@
     }
 
     public void testNonResizeableNotDocked() throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+            return;
+        }
+
         launchActivityInDockStack(NON_RESIZEABLE_ACTIVITY_NAME);
         mAmWmState.computeState(mDevice, new String[] {NON_RESIZEABLE_ACTIVITY_NAME});
 
@@ -62,6 +80,11 @@
     }
 
     public void testLaunchToSide() throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+            return;
+        }
+
         launchActivityInDockStack(LAUNCHING_ACTIVITY);
         mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
         getLaunchActivityBuilder().setToSide(true).execute();
@@ -72,6 +95,11 @@
     }
 
     public void testLaunchToSideAndBringToFront() throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+            return;
+        }
+
         launchActivityInDockStack(LAUNCHING_ACTIVITY);
         final String[] waitForFirstVisible = new String[] {TEST_ACTIVITY_NAME};
         final String[] waitForSecondVisible = new String[] {NO_RELAUNCH_ACTIVITY_NAME};
@@ -107,6 +135,11 @@
     }
 
     public void testLaunchToSideMultiple() throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+            return;
+        }
+
         launchActivityInDockStack(LAUNCHING_ACTIVITY);
         mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
         final String[] waitForActivitiesVisible =
@@ -148,6 +181,11 @@
 
     private void launchTargetToSide(String targetActivityName,
                                     boolean taskCountMustIncrement) throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+            return;
+        }
+
         launchActivityInDockStack(LAUNCHING_ACTIVITY);
         mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
 
@@ -203,6 +241,11 @@
     }
 
     public void testLaunchToSideMultipleWithFlag() throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+            return;
+        }
+
         launchActivityInDockStack(LAUNCHING_ACTIVITY);
         mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
         final String[] waitForActivitiesVisible =
@@ -232,6 +275,11 @@
     }
 
     public void testRotationWhenDocked() throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+            return;
+        }
+
         launchActivityInDockStack(LAUNCHING_ACTIVITY);
         mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
         getLaunchActivityBuilder().setToSide(true).execute();
@@ -263,6 +311,11 @@
     }
 
     public void testRotationWhenDockedWhileLocked() throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+            return;
+        }
+
         launchActivityInDockStack(LAUNCHING_ACTIVITY);
         mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
         getLaunchActivityBuilder().setToSide(true).execute();
@@ -283,6 +336,11 @@
     }
 
     public void testRotationWhileDockMinimized() throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+            return;
+        }
+
         launchActivityInDockStackAndMinimize(TEST_ACTIVITY_NAME);
         assertDockMinimized();
         mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
@@ -314,6 +372,11 @@
     }
 
     public void testFinishDockActivityWhileMinimized() throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+            return;
+        }
+
         launchActivityInDockStackAndMinimize(FINISHABLE_ACTIVITY_NAME);
         assertDockMinimized();
 
@@ -324,6 +387,11 @@
     }
 
     public void testDockedStackToMinimizeWhenUnlocked() throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+            return;
+        }
+
         launchActivityInDockStack(TEST_ACTIVITY_NAME);
         mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
         sleepDevice();
@@ -333,6 +401,11 @@
     }
 
     public void testMinimizedStateWhenUnlockedAndUnMinimized() throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+            return;
+        }
+
         launchActivityInDockStackAndMinimize(FINISHABLE_ACTIVITY_NAME);
         assertDockMinimized();
 
@@ -346,6 +419,11 @@
     }
 
     public void testResizeDockedStack() throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+            return;
+        }
+
         launchActivityInDockStack(DOCKED_ACTIVITY_NAME);
         mAmWmState.computeState(mDevice, new String[] {DOCKED_ACTIVITY_NAME});
         launchActivityInStack(TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID);
@@ -364,6 +442,11 @@
     }
 
     public void testActivityLifeCycleOnResizeDockedStack() throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+            return;
+        }
+
         final String[] waitTestActivityName = new String[] {TEST_ACTIVITY_NAME};
         launchActivity(TEST_ACTIVITY_NAME);
         mAmWmState.computeState(mDevice, waitTestActivityName);
@@ -414,6 +497,11 @@
     }
 
     public void testStackListOrderLaunchDockedActivity() throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+            return;
+        }
+
         launchActivityInDockStack(TEST_ACTIVITY_NAME);
         mAmWmState.computeState(mDevice, new String[]{TEST_ACTIVITY_NAME});
 
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerManifestLayoutTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerManifestLayoutTests.java
index b7df926..e6df4b2 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerManifestLayoutTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerManifestLayoutTests.java
@@ -82,6 +82,10 @@
     }
 
     public void testMinimalSizeDocked() throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(INFO, "Skipping test: no multi-window support");
+            return;
+        }
         testMinimalSize(DOCKED_STACK_ID);
     }
 
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
index 666ca73..a6372a2 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
@@ -38,6 +38,7 @@
     private static final String NON_RESIZEABLE_ACTIVITY = "NonResizeableActivity";
     private static final String RESUME_WHILE_PAUSING_ACTIVITY = "ResumeWhilePausingActivity";
     private static final String PIP_ACTIVITY = "PipActivity";
+    private static final String PIP_ACTIVITY2 = "PipActivity2";
     private static final String ALWAYS_FOCUSABLE_PIP_ACTIVITY = "AlwaysFocusablePipActivity";
     private static final String LAUNCH_INTO_PINNED_STACK_PIP_ACTIVITY =
             "LaunchIntoPinnedStackPipActivity";
@@ -467,6 +468,27 @@
                 ALWAYS_FOCUSABLE_PIP_ACTIVITY)));
     }
 
+    public void testDisallowMultipleTasksInPinnedStack() throws Exception {
+        if (!supportsPip()) return;
+
+        // Launch first PIP activity
+        launchActivity(PIP_ACTIVITY, EXTRA_ENTER_PIP, "true");
+
+        // Launch second PIP activity
+        launchActivity(PIP_ACTIVITY2, EXTRA_ENTER_PIP, "true");
+
+        final ActivityStack pinnedStack = mAmWmState.getAmState().getStackById(PINNED_STACK_ID);
+        assertEquals(1, pinnedStack.getTasks().size());
+
+        assertTrue(pinnedStack.getTasks().get(0).mRealActivity.equals(getActivityComponentName(
+                PIP_ACTIVITY2)));
+
+        final ActivityStack fullScreenStack = mAmWmState.getAmState().getStackById(
+                FULLSCREEN_WORKSPACE_STACK_ID);
+        assertTrue(fullScreenStack.getBottomTask().mRealActivity.equals(getActivityComponentName(
+                PIP_ACTIVITY)));
+    }
+
     public void testPipUnPipOverHome() throws Exception {
         if (!supportsPip()) return;
 
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerReplaceWindowTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerReplaceWindowTests.java
index 59d632a..3aa3ce0 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerReplaceWindowTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerReplaceWindowTests.java
@@ -49,6 +49,11 @@
     }
 
     private void testReplaceWindow_Dock(boolean relaunch) throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(INFO, "Skipping test: no multi-window support");
+            return;
+        }
+
         final String activityName =
                 relaunch ? SLOW_CREATE_ACTIVITY_NAME : NO_RELAUNCH_ACTIVITY_NAME;
         final String windowName = getWindowName(activityName);
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/KeyguardLockedTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/KeyguardLockedTests.java
index 28161bc..a3099ae 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/KeyguardLockedTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/KeyguardLockedTests.java
@@ -45,6 +45,9 @@
     }
 
     public void testLockAndUnlock() throws Exception {
+        if (!isHandheld()) {
+            return;
+        }
         gotoKeyguard();
         mAmWmState.waitForKeyguardShowingAndNotOccluded(mDevice);
         assertShowingAndNotOccluded();
@@ -54,6 +57,9 @@
     }
 
     public void testDismissKeyguard() throws Exception {
+        if (!isHandheld()) {
+            return;
+        }
         gotoKeyguard();
         mAmWmState.waitForKeyguardShowingAndNotOccluded(mDevice);
         assertShowingAndNotOccluded();
@@ -65,6 +71,9 @@
     }
 
     public void testDismissKeyguard_whileOccluded() throws Exception {
+        if (!isHandheld()) {
+            return;
+        }
         gotoKeyguard();
         mAmWmState.waitForKeyguardShowingAndNotOccluded(mDevice);
         assertShowingAndNotOccluded();
@@ -80,6 +89,9 @@
     }
 
     public void testDismissKeyguard_fromShowWhenLocked_notAllowed() throws Exception {
+        if (!isHandheld()) {
+            return;
+        }
         gotoKeyguard();
         mAmWmState.waitForKeyguardShowingAndNotOccluded(mDevice);
         assertShowingAndNotOccluded();
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/KeyguardTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/KeyguardTests.java
index f17221ef..877369a 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/KeyguardTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/KeyguardTests.java
@@ -217,6 +217,9 @@
     }
 
     public void testDismissKeyguard_fromShowWhenLocked_notAllowed() throws Exception {
+        if (!isHandheld()) {
+            return;
+        }
         gotoKeyguard();
         mAmWmState.waitForKeyguardShowingAndNotOccluded(mDevice);
         assertShowingAndNotOccluded();
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/SplashscreenTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/SplashscreenTests.java
new file mode 100644
index 0000000..4694d7a
--- /dev/null
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/SplashscreenTests.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.cts;
+
+import java.awt.Color;
+import java.awt.Rectangle;
+import java.awt.image.BufferedImage;
+
+/**
+ * Build: mmma -j32 cts/hostsidetests/services
+ * Run: cts/hostsidetests/services/activityandwindowmanager/util/run-test CtsServicesHostTestCases android.server.cts.SplashscreenTests
+ */
+public class SplashscreenTests extends ActivityManagerTestBase {
+
+    public void testSplashscreenContent() throws Exception {
+        launchActivityNoWait("SplashscreenActivity");
+        mAmWmState.waitForAppTransitionIdle(mDevice);
+        mAmWmState.getWmState().getStableBounds();
+        final BufferedImage image = takeScreenshot();
+        assertAllColor(image, mAmWmState.getWmState().getStableBounds(), Color.RED.getRGB());
+    }
+
+    private void assertAllColor(BufferedImage img, Rectangle bounds, int expectedColor) {
+        for (int x = bounds.x; x < bounds.x + bounds.width; x++) {
+            for (int y = bounds.y; y < bounds.y + bounds.height; y++) {
+                assertTrue(x < img.getWidth());
+                assertTrue(y < img.getHeight());
+                final int color = img.getRGB(x, y);
+                assertEquals("Colors must match at x=" + x + " y=" + y, expectedColor, color);
+            }
+        }
+    }
+}
diff --git a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityAndWindowManagersState.java b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityAndWindowManagersState.java
index ece45f2..9f4cf6c 100644
--- a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityAndWindowManagersState.java
+++ b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityAndWindowManagersState.java
@@ -34,13 +34,12 @@
 
 import junit.framework.Assert;
 
-import java.awt.*;
+import java.awt.Rectangle;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 import java.util.function.BiPredicate;
 import java.util.function.Predicate;
-import java.util.regex.Pattern;
 
 /** Combined state of the activity manager and window manager. */
 public class ActivityAndWindowManagersState extends Assert {
@@ -195,7 +194,8 @@
             mAmState.computeState(device);
             mWmState.computeState(device);
             if (shouldWaitForValidStacks(compareTaskAndStackBounds)
-                    || shouldWaitForActivities(waitForActivitiesVisible, stackIds, packageName)) {
+                    || shouldWaitForActivities(waitForActivitiesVisible, stackIds, packageName)
+                    || shouldWaitForWindows()) {
                 log("***Waiting for valid stacks and activities states...");
                 try {
                     Thread.sleep(1000);
@@ -252,6 +252,12 @@
                 "***Waiting for focused stack...");
     }
 
+    void waitForAppTransitionIdle(ITestDevice device) throws Exception {
+        waitForWithWmState(device,
+                state -> WindowManagerState.APP_STATE_IDLE.equals(state.getAppTransitionState()),
+                "***Waiting for app transition idle...");
+    }
+
     void waitForWithAmState(ITestDevice device, Predicate<ActivityManagerState> waitCondition,
             String message) throws Exception{
         waitFor(device, (amState, wmState) -> waitCondition.test(amState), message);
@@ -283,6 +289,7 @@
         } while (retriesLeft-- > 0);
     }
 
+    /** @return true if should wait for valid stacks state. */
     private boolean shouldWaitForValidStacks(boolean compareTaskAndStackBounds) {
         if (!taskListsInAmAndWmAreEqual()) {
             // We want to wait for equal task lists in AM and WM in case we caught them in the
@@ -304,9 +311,24 @@
             log("***taskBoundsInAMAndWMAreEqual=false : " + e.getMessage());
             return true;
         }
+        final int stackCount = mAmState.getStackCount();
+        if (stackCount == 0) {
+            log("***stackCount=" + stackCount);
+            return true;
+        }
+        final int resumedActivitiesCount = mAmState.getResumedActivitiesCount();
+        if (!mAmState.getKeyguardControllerState().keyguardShowing && resumedActivitiesCount != 1) {
+            log("***resumedActivitiesCount=" + resumedActivitiesCount);
+            return true;
+        }
+        if (mAmState.getFocusedActivity() == null) {
+            log("***focusedActivity=null");
+            return true;
+        }
         return false;
     }
 
+    /** @return true if should wait for some activities to become visible. */
     private boolean shouldWaitForActivities(String[] waitForActivitiesVisible, int[] stackIds,
             String packageName) {
         if (waitForActivitiesVisible == null || waitForActivitiesVisible.length == 0) {
@@ -353,6 +375,24 @@
         return !allActivityWindowsVisible || !tasksInCorrectStacks;
     }
 
+    /** @return true if should wait valid windows state. */
+    private boolean shouldWaitForWindows() {
+        if (mWmState.getFrontWindow() == null) {
+            log("***frontWindow=null");
+            return true;
+        }
+        if (mWmState.getFocusedWindow() == null) {
+            log("***focusedWindow=null");
+            return true;
+        }
+        if (mWmState.getFocusedApp() == null) {
+            log("***focusedApp=null");
+            return true;
+        }
+
+        return false;
+    }
+
     private boolean shouldWaitForDebuggerWindow() {
         List<WindowManagerState.WindowState> matchingWindowStates = new ArrayList<>();
         mWmState.getMatchingVisibleWindowState("android.server.cts", matchingWindowStates);
diff --git a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerTestBase.java b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerTestBase.java
index 96bcc1c..4ef07cf 100644
--- a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerTestBase.java
+++ b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerTestBase.java
@@ -21,8 +21,11 @@
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.result.InputStreamSource;
 import com.android.tradefed.testtype.DeviceTestCase;
 
+import java.awt.*;
+import java.awt.image.BufferedImage;
 import java.lang.Exception;
 import java.lang.Integer;
 import java.lang.String;
@@ -37,6 +40,8 @@
 
 import android.server.cts.ActivityManagerState.ActivityStack;
 
+import javax.imageio.ImageIO;
+
 public abstract class ActivityManagerTestBase extends DeviceTestCase {
     private static final boolean PRETEND_DEVICE_SUPPORTS_PIP = false;
     private static final boolean PRETEND_DEVICE_SUPPORTS_FREEFORM = false;
@@ -115,6 +120,8 @@
 
     static final String AM_MOVE_TASK = "am stack move-task ";
 
+    private static final String AM_SUPPORTS_SPLIT_SCREEN_MULTIWINDOW =
+            "am supports-split-screen-multiwindow";
     private static final String AM_NO_HOME_SCREEN = "am no-home-screen";
 
     private static final String INPUT_KEYEVENT_HOME = "input keyevent 3";
@@ -289,13 +296,25 @@
         mDevice.executeShellCommand(command, outputReceiver);
     }
 
+    protected BufferedImage takeScreenshot() throws Exception {
+        final InputStreamSource stream = mDevice.getScreenshot("PNG", false /* rescale */);
+        if (stream == null) {
+            fail("Failed to take screenshot of device");
+        }
+        return ImageIO.read(stream.createInputStream());
+    }
+
     protected void launchActivity(final String targetActivityName, final String... keyValuePairs)
             throws Exception {
         executeShellCommand(getAmStartCmd(targetActivityName, keyValuePairs));
-
         mAmWmState.waitForValidState(mDevice, targetActivityName);
     }
 
+    protected void launchActivityNoWait(final String targetActivityName,
+            final String... keyValuePairs) throws Exception {
+        executeShellCommand(getAmStartCmd(targetActivityName, keyValuePairs));
+    }
+
     protected void launchActivityInNewTask(final String targetActivityName) throws Exception {
         executeShellCommand(getAmStartCmdInNewTask(targetActivityName));
         mAmWmState.waitForValidState(mDevice, targetActivityName);
@@ -506,6 +525,13 @@
                 && !hasDeviceFeature("android.software.watch");
     }
 
+    protected boolean supportsSplitScreenMultiWindow() throws DeviceNotAvailableException {
+        CollectingOutputReceiver outputReceiver = new CollectingOutputReceiver();
+        executeShellCommand(AM_SUPPORTS_SPLIT_SCREEN_MULTIWINDOW, outputReceiver);
+        String output = outputReceiver.getOutput();
+        return !output.startsWith("false");
+    }
+
     protected boolean noHomeScreen() throws DeviceNotAvailableException {
         CollectingOutputReceiver outputReceiver = new CollectingOutputReceiver();
         executeShellCommand(AM_NO_HOME_SCREEN, outputReceiver);
@@ -710,70 +736,139 @@
         return uniqueString;
     }
 
-    protected void assertActivityLifecycle(String activityName, boolean relaunched,
+    void assertActivityLifecycle(String activityName, boolean relaunched,
             String logSeparator) throws DeviceNotAvailableException {
+        int retriesLeft = 5;
+        String resultString;
+        do {
+            resultString = verifyLifecycleCondition(activityName, logSeparator, relaunched);
+            if (resultString != null) {
+                log("***Waiting for valid lifecycle state: " + resultString);
+                try {
+                    Thread.sleep(1000);
+                } catch (InterruptedException e) {
+                    log(e.toString());
+                }
+            } else {
+                break;
+            }
+        } while (retriesLeft-- > 0);
+
+        assertNull(resultString, resultString);
+    }
+
+    /** @return Error string if lifecycle counts don't match, null if everything is fine. */
+    private String verifyLifecycleCondition(String activityName, String logSeparator,
+            boolean relaunched) throws DeviceNotAvailableException {
         final ActivityLifecycleCounts lifecycleCounts = new ActivityLifecycleCounts(activityName,
                 logSeparator);
-
         if (relaunched) {
             if (lifecycleCounts.mDestroyCount < 1) {
-                fail(activityName + " must have been destroyed. mDestroyCount="
-                        + lifecycleCounts.mDestroyCount);
+                return activityName + " must have been destroyed. mDestroyCount="
+                        + lifecycleCounts.mDestroyCount;
             }
             if (lifecycleCounts.mCreateCount < 1) {
-                fail(activityName + " must have been (re)created. mCreateCount="
-                        + lifecycleCounts.mCreateCount);
+                return activityName + " must have been (re)created. mCreateCount="
+                        + lifecycleCounts.mCreateCount;
             }
         } else {
             if (lifecycleCounts.mDestroyCount > 0) {
-                fail(activityName + " must *NOT* have been destroyed. mDestroyCount="
-                        + lifecycleCounts.mDestroyCount);
+                return activityName + " must *NOT* have been destroyed. mDestroyCount="
+                        + lifecycleCounts.mDestroyCount;
             }
             if (lifecycleCounts.mCreateCount > 0) {
-                fail(activityName + " must *NOT* have been (re)created. mCreateCount="
-                        + lifecycleCounts.mCreateCount);
+                return activityName + " must *NOT* have been (re)created. mCreateCount="
+                        + lifecycleCounts.mCreateCount;
             }
             if (lifecycleCounts.mConfigurationChangedCount < 1) {
-                fail(activityName + " must have received configuration changed. "
+                return activityName + " must have received configuration changed. "
                         + "mConfigurationChangedCount="
-                        + lifecycleCounts.mConfigurationChangedCount);
+                        + lifecycleCounts.mConfigurationChangedCount;
             }
         }
+        return null;
     }
 
     protected void assertRelaunchOrConfigChanged(
             String activityName, int numRelaunch, int numConfigChange, String logSeparator)
             throws DeviceNotAvailableException {
+        int retriesLeft = 5;
+        String resultString;
+        do {
+            resultString = verifyRelaunchOrConfigChanged(activityName, numRelaunch, numConfigChange,
+                    logSeparator);
+            if (resultString != null) {
+                log("***Waiting for relaunch or config changed: " + resultString);
+                try {
+                    Thread.sleep(1000);
+                } catch (InterruptedException e) {
+                    log(e.toString());
+                }
+            } else {
+                break;
+            }
+        } while (retriesLeft-- > 0);
+
+        assertNull(resultString, resultString);
+    }
+
+    /** @return Error string if lifecycle counts don't match, null if everything is fine. */
+    private String verifyRelaunchOrConfigChanged(String activityName, int numRelaunch,
+            int numConfigChange, String logSeparator) throws DeviceNotAvailableException {
         final ActivityLifecycleCounts lifecycleCounts = new ActivityLifecycleCounts(activityName,
                 logSeparator);
 
         if (lifecycleCounts.mDestroyCount != numRelaunch) {
-            fail(activityName + " has been destroyed " + lifecycleCounts.mDestroyCount
-                    + " time(s), expecting " + numRelaunch);
+            return activityName + " has been destroyed " + lifecycleCounts.mDestroyCount
+                    + " time(s), expecting " + numRelaunch;
         } else if (lifecycleCounts.mCreateCount != numRelaunch) {
-            fail(activityName + " has been (re)created " + lifecycleCounts.mCreateCount
-                    + " time(s), expecting " + numRelaunch);
+            return activityName + " has been (re)created " + lifecycleCounts.mCreateCount
+                    + " time(s), expecting " + numRelaunch;
         } else if (lifecycleCounts.mConfigurationChangedCount != numConfigChange) {
-            fail(activityName + " has received " + lifecycleCounts.mConfigurationChangedCount
-                    + " onConfigurationChanged() calls, expecting " + numConfigChange);
+            return activityName + " has received " + lifecycleCounts.mConfigurationChangedCount
+                    + " onConfigurationChanged() calls, expecting " + numConfigChange;
         }
+        return null;
     }
 
     protected void assertActivityDestroyed(String activityName, String logSeparator)
             throws DeviceNotAvailableException {
+        int retriesLeft = 5;
+        String resultString;
+        do {
+            resultString = verifyActivityDestroyed(activityName, logSeparator);
+            if (resultString != null) {
+                log("***Waiting for activity destroyed: " + resultString);
+                try {
+                    Thread.sleep(1000);
+                } catch (InterruptedException e) {
+                    log(e.toString());
+                }
+            } else {
+                break;
+            }
+        } while (retriesLeft-- > 0);
+
+        assertNull(resultString, resultString);
+    }
+
+    /** @return Error string if lifecycle counts don't match, null if everything is fine. */
+    private String verifyActivityDestroyed(String activityName, String logSeparator)
+            throws DeviceNotAvailableException {
         final ActivityLifecycleCounts lifecycleCounts = new ActivityLifecycleCounts(activityName,
                 logSeparator);
 
         if (lifecycleCounts.mDestroyCount != 1) {
-            fail(activityName + " has been destroyed " + lifecycleCounts.mDestroyCount
-                    + " time(s), expecting single destruction.");
+            return activityName + " has been destroyed " + lifecycleCounts.mDestroyCount
+                    + " time(s), expecting single destruction.";
         } else if (lifecycleCounts.mCreateCount != 0) {
-            fail(activityName + " has been (re)created " + lifecycleCounts.mCreateCount
-                    + " time(s), not expecting any.");
+            return activityName + " has been (re)created " + lifecycleCounts.mCreateCount
+                    + " time(s), not expecting any.";
         } else if (lifecycleCounts.mConfigurationChangedCount != 0) {
-            fail(activityName + " has received " + lifecycleCounts.mConfigurationChangedCount
-                    + " onConfigurationChanged() calls, not expecting any.");
+            return activityName + " has received " + lifecycleCounts.mConfigurationChangedCount
+                    + " onConfigurationChanged() calls, not expecting any.";
         }
+        return null;
     }
 
     protected String[] getDeviceLogsForComponent(String componentName, String logSeparator)
@@ -861,6 +956,27 @@
 
     ReportedSizes getLastReportedSizesForActivity(String activityName, String logSeparator)
             throws DeviceNotAvailableException {
+        int retriesLeft = 5;
+        ReportedSizes result;
+        do {
+            result = readLastReportedSizes(activityName, logSeparator);
+            if (result == null) {
+                log("***Waiting for sizes to be reported...");
+                try {
+                    Thread.sleep(1000);
+                } catch (InterruptedException e) {
+                    log(e.toString());
+                    // Well I guess we are not waiting...
+                }
+            } else {
+                break;
+            }
+        } while (retriesLeft-- > 0);
+        return result;
+    }
+
+    private ReportedSizes readLastReportedSizes(String activityName, String logSeparator)
+            throws DeviceNotAvailableException {
         final String[] lines = getDeviceLogsForComponent(activityName, logSeparator);
         for (int i = lines.length - 1; i >= 0; i--) {
             final String line = lines[i].trim();
diff --git a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/WindowManagerState.java b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/WindowManagerState.java
index f9ad434..0cdf13e 100644
--- a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/WindowManagerState.java
+++ b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/WindowManagerState.java
@@ -37,7 +37,7 @@
 
 public class WindowManagerState {
 
-    public static  final String TRANSIT_ACTIVITY_OPEN = "TRANSIT_ACTIVITY_OPEN";
+    public static final String TRANSIT_ACTIVITY_OPEN = "TRANSIT_ACTIVITY_OPEN";
     public static final String TRANSIT_ACTIVITY_CLOSE = "TRANSIT_ACTIVITY_CLOSE";
     public static final String TRANSIT_TASK_OPEN = "TRANSIT_TASK_OPEN";
     public static final String TRANSIT_TASK_CLOSE = "TRANSIT_TASK_CLOSE";
@@ -53,6 +53,8 @@
     public static final String TRANSIT_KEYGUARD_OCCLUDE = "TRANSIT_KEYGUARD_OCCLUDE";
     public static final String TRANSIT_KEYGUARD_UNOCCLUDE = "TRANSIT_KEYGUARD_UNOCCLUDE";
 
+    public static final String APP_STATE_IDLE = "APP_STATE_IDLE";
+
     private static final String DUMPSYS_WINDOW = "dumpsys window -a";
 
     private static final Pattern sWindowPattern =
@@ -87,6 +89,8 @@
 
     private static final Pattern sLastAppTransitionPattern =
             Pattern.compile("mLastUsedAppTransition=(.+)");
+    private static final Pattern sAppTransitionStatePattern =
+            Pattern.compile("mAppTransitionState=(.+)");
 
     private static final Pattern sStackIdPattern = Pattern.compile("mStackId=(\\d+)");
 
@@ -120,6 +124,7 @@
     private String mFocusedWindow = null;
     private String mFocusedApp = null;
     private String mLastTransition = null;
+    private String mAppTransitionState = null;
     private String mInputMethodWindowAppToken = null;
     private Rectangle mStableBounds = new Rectangle();
     private final Rectangle mDefaultPinnedStackBounds = new Rectangle();
@@ -157,7 +162,7 @@
             dump = outputReceiver.getOutput();
             parseSysDump(dump);
 
-            retry = mWindowStates.isEmpty() || mFocusedWindow == null || mFocusedApp == null;
+            retry = mWindowStates.isEmpty() || mFocusedApp == null;
         } while (retry && retriesLeft-- > 0);
 
         if (retry) {
@@ -260,6 +265,15 @@
                 continue;
             }
 
+            matcher = sAppTransitionStatePattern.matcher(line);
+            if (matcher.matches()) {
+                log(line);
+                final String appTransitionState = matcher.group(1);
+                log(appTransitionState);
+                mAppTransitionState = appTransitionState;
+                continue;
+            }
+
             matcher = sLastAppTransitionPattern.matcher(line);
             if (matcher.matches()) {
                 log(line);
@@ -442,6 +456,10 @@
         return mLastTransition;
     }
 
+    String getAppTransitionState() {
+        return mAppTransitionState;
+    }
+
     int getFrontStackId(int displayId) {
         return mDisplayStacks.get(displayId).get(0).mStackId;
     }
diff --git a/hostsidetests/services/activityandwindowmanager/windowmanager/src/android/server/cts/CrossAppDragAndDropTests.java b/hostsidetests/services/activityandwindowmanager/windowmanager/src/android/server/cts/CrossAppDragAndDropTests.java
index f594123..6281e16 100644
--- a/hostsidetests/services/activityandwindowmanager/windowmanager/src/android/server/cts/CrossAppDragAndDropTests.java
+++ b/hostsidetests/services/activityandwindowmanager/windowmanager/src/android/server/cts/CrossAppDragAndDropTests.java
@@ -24,6 +24,7 @@
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.regex.Pattern;
 
 public class CrossAppDragAndDropTests extends DeviceTestCase {
     // Constants copied from ActivityManager.StackId. If they are changed there, these must be
@@ -42,12 +43,18 @@
 
     private static final String AM_FORCE_STOP = "am force-stop ";
     private static final String AM_MOVE_TASK = "am stack move-task ";
+    private static final String AM_RESIZE_TASK = "am task resize ";
     private static final String AM_REMOVE_STACK = "am stack remove ";
     private static final String AM_START_N = "am start -n ";
     private static final String AM_STACK_LIST = "am stack list";
     private static final String INPUT_MOUSE_SWIPE = "input mouse swipe ";
     private static final String TASK_ID_PREFIX = "taskId";
 
+    // Regex pattern to match adb shell am stack list output of the form:
+    // taskId=<TASK_ID>: <componentName> bounds=[LEFT,TOP][RIGHT,BOTTOM]
+    private static final String TASK_REGEX_PATTERN_STRING =
+            "taskId=[0-9]+: %s bounds=\\[[0-9]+,[0-9]+\\]\\[[0-9]+,[0-9]+\\]";
+
     private static final int SWIPE_DURATION_MS = 500;
 
     private static final String SOURCE_PACKAGE_NAME = "android.wm.cts.dndsourceapp";
@@ -94,6 +101,9 @@
     private static final String RESULT_EXCEPTION = "Exception";
     private static final String RESULT_NULL_DROP_PERMISSIONS = "Null DragAndDropPermissions";
 
+    private static final String AM_SUPPORTS_SPLIT_SCREEN_MULTIWINDOW =
+            "am supports-split-screen-multiwindow";
+
     private ITestDevice mDevice;
 
     private Map<String, String> mSourceResults;
@@ -145,6 +155,12 @@
         return AM_MOVE_TASK + taskId + " " + stackId + " true";
     }
 
+    private String getResizeTaskCommand(int taskId, Point topLeft, Point bottomRight)
+            throws Exception {
+        return AM_RESIZE_TASK + taskId + " " + topLeft.x + " " + topLeft.y + " " + bottomRight.x
+                + " " + bottomRight.y;
+    }
+
     private String getComponentName(String packageName, String activityName) {
         return packageName + "/" + packageName + "." + activityName;
     }
@@ -195,6 +211,24 @@
         waitForResume(packageName, activityName);
     }
 
+    /**
+     * @param displaySize size of the display
+     * @param leftSide {@code true} to launch the app taking up the left half of the display,
+     *         {@code false} to launch the app taking up the right half of the display.
+     */
+    private void launchFreeformActivity(String packageName, String activityName, String mode,
+            Point displaySize, boolean leftSide) throws Exception{
+        clearLogs();
+        final String componentName = getComponentName(packageName, activityName);
+        executeShellCommand(getStartCommand(componentName, mode) + " --stack "
+                + FREEFORM_WORKSPACE_STACK_ID);
+        waitForResume(packageName, activityName);
+        Point topLeft = new Point(leftSide ? 0 : displaySize.x / 2, 0);
+        Point bottomRight = new Point(leftSide ? displaySize.x / 2 : displaySize.x, displaySize.y);
+        executeShellCommand(getResizeTaskCommand(getActivityTaskId(componentName), topLeft,
+                bottomRight));
+    }
+
     private void waitForResume(String packageName, String activityName) throws Exception {
         final String fullActivityName = packageName + "." + activityName;
         int retryCount = 3;
@@ -238,6 +272,7 @@
         builder.append("\nParsing adb shell am output: " );
         builder.append(output);
         CLog.i(builder.toString());
+        final Pattern pattern = Pattern.compile(String.format(TASK_REGEX_PATTERN_STRING, name));
         for (String line : output.split("\\n")) {
             final String truncatedLine;
             // Only look for the activity name before the "topActivity" string.
@@ -247,7 +282,7 @@
             } else {
                 truncatedLine = line;
             }
-            if (truncatedLine.contains(name)) {
+            if (pattern.matcher(truncatedLine).find()) {
                 return truncatedLine;
             }
         }
@@ -280,6 +315,12 @@
         return -1;
     }
 
+    private Point getDisplaySize() throws Exception {
+        final String output = executeShellCommand("wm size");
+        final String[] sizes = output.split(" ")[2].split("x");
+        return new Point(Integer.valueOf(sizes[0].trim()), Integer.valueOf(sizes[1].trim()));
+    }
+
     private Point getWindowCenter(String name) throws Exception {
         Point p1 = new Point();
         Point p2 = new Point();
@@ -343,8 +384,19 @@
             return;
         }
 
-        launchDockedActivity(mSourcePackageName, SOURCE_ACTIVITY_NAME, sourceMode);
-        launchFullscreenActivity(mTargetPackageName, TARGET_ACTIVITY_NAME, targetMode);
+        if (supportsSplitScreenMultiWindow()) {
+            launchDockedActivity(mSourcePackageName, SOURCE_ACTIVITY_NAME, sourceMode);
+            launchFullscreenActivity(mTargetPackageName, TARGET_ACTIVITY_NAME, targetMode);
+        } else if (supportsFreeformMultiWindow()) {
+            // Fallback to try to launch two freeform windows side by side.
+            Point displaySize = getDisplaySize();
+            launchFreeformActivity(mSourcePackageName, SOURCE_ACTIVITY_NAME, sourceMode,
+                    displaySize, true /* leftSide */);
+            launchFreeformActivity(mTargetPackageName, TARGET_ACTIVITY_NAME, targetMode,
+                    displaySize, false /* leftSide */);
+        } else {
+            return;
+        }
 
         clearLogs();
 
@@ -412,6 +464,14 @@
         }
     }
 
+    private boolean supportsSplitScreenMultiWindow() throws DeviceNotAvailableException {
+        return !executeShellCommand(AM_SUPPORTS_SPLIT_SCREEN_MULTIWINDOW).startsWith("false");
+    }
+
+    private boolean supportsFreeformMultiWindow() throws DeviceNotAvailableException {
+        return mDevice.hasFeature("feature:android.software.freeform_window_management");
+    }
+
     public void testCancelSoon() throws Exception {
         assertDropResult(CANCEL_SOON, REQUEST_NONE, RESULT_MISSING);
     }
diff --git a/tests/JobScheduler/src/android/jobscheduler/MockJobService.java b/tests/JobScheduler/src/android/jobscheduler/MockJobService.java
index 7d06682..1955483 100644
--- a/tests/JobScheduler/src/android/jobscheduler/MockJobService.java
+++ b/tests/JobScheduler/src/android/jobscheduler/MockJobService.java
@@ -26,6 +26,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.net.Uri;
 import android.os.Process;
 import android.util.Log;
 
@@ -99,16 +100,90 @@
             while ((work = params.dequeueWork()) != null) {
                 Log.i(TAG, "Received work #" + index + ": " + work.getIntent());
                 mReceivedWork.add(work.getIntent());
-                params.completeWork(work);
-                if (index < expectedWork.length && expectedWork[index].subitems != null) {
-                    final TestWorkItem[] sub = expectedWork[index].subitems;
-                    final JobInfo ji = expectedWork[index].jobInfo;
-                    final JobScheduler js = (JobScheduler) getSystemService(
-                            Context.JOB_SCHEDULER_SERVICE);
-                    for (int subi = 0; subi < sub.length; subi++) {
-                        js.enqueue(ji, new JobWorkItem(sub[subi].intent));
+
+                if (index < expectedWork.length) {
+                    TestWorkItem expected = expectedWork[index];
+                    int grantFlags = work.getIntent().getFlags();
+                    if (expected.requireUrisGranted != null) {
+                        for (int ui = 0; ui < expected.requireUrisGranted.length; ui++) {
+                            if ((grantFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
+                                if (checkUriPermission(expected.requireUrisGranted[ui],
+                                        Process.myPid(), Process.myUid(),
+                                        Intent.FLAG_GRANT_READ_URI_PERMISSION)
+                                        != PackageManager.PERMISSION_GRANTED) {
+                                    TestEnvironment.getTestEnvironment().notifyExecution(params,
+                                            permCheckRead, permCheckWrite, null,
+                                            "Expected read permission but not granted: "
+                                                    + expected.requireUrisGranted[ui]
+                                                    + " @ #" + index);
+                                    return false;
+                                }
+                            }
+                            if ((grantFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
+                                if (checkUriPermission(expected.requireUrisGranted[ui],
+                                        Process.myPid(), Process.myUid(),
+                                        Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
+                                        != PackageManager.PERMISSION_GRANTED) {
+                                    TestEnvironment.getTestEnvironment().notifyExecution(params,
+                                            permCheckRead, permCheckWrite, null,
+                                            "Expected write permission but not granted: "
+                                                    + expected.requireUrisGranted[ui]
+                                                    + " @ #" + index);
+                                    return false;
+                                }
+                            }
+                        }
+                    }
+                    if (expected.requireUrisNotGranted != null) {
+                        // XXX note no delay here, current impl will have fully revoked the
+                        // permission by the time we return from completing the last work.
+                        for (int ui = 0; ui < expected.requireUrisNotGranted.length; ui++) {
+                            if ((grantFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
+                                if (checkUriPermission(expected.requireUrisNotGranted[ui],
+                                        Process.myPid(), Process.myUid(),
+                                        Intent.FLAG_GRANT_READ_URI_PERMISSION)
+                                        != PackageManager.PERMISSION_DENIED) {
+                                    TestEnvironment.getTestEnvironment().notifyExecution(params,
+                                            permCheckRead, permCheckWrite, null,
+                                            "Not expected read permission but granted: "
+                                                    + expected.requireUrisNotGranted[ui]
+                                                    + " @ #" + index);
+                                    return false;
+                                }
+                            }
+                            if ((grantFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
+                                if (checkUriPermission(expected.requireUrisNotGranted[ui],
+                                        Process.myPid(), Process.myUid(),
+                                        Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
+                                        != PackageManager.PERMISSION_DENIED) {
+                                    TestEnvironment.getTestEnvironment().notifyExecution(params,
+                                            permCheckRead, permCheckWrite, null,
+                                            "Not expected write permission but granted: "
+                                                    + expected.requireUrisNotGranted[ui]
+                                                    + " @ #" + index);
+                                    return false;
+                                }
+                            }
+                        }
                     }
                 }
+
+                params.completeWork(work);
+
+                if (index < expectedWork.length) {
+                    TestWorkItem expected = expectedWork[index];
+                    if (expected.subitems != null) {
+                        final TestWorkItem[] sub = expected.subitems;
+                        final JobInfo ji = expected.jobInfo;
+                        final JobScheduler js = (JobScheduler) getSystemService(
+                                Context.JOB_SCHEDULER_SERVICE);
+                        for (int subi = 0; subi < sub.length; subi++) {
+                            js.enqueue(ji, new JobWorkItem(sub[subi].intent));
+                        }
+                    }
+                }
+
+                index++;
             }
             Log.i(TAG, "Done with all work at #" + index);
             // We don't notifyExecution here because we want to make sure the job properly
@@ -130,17 +205,32 @@
         public final Intent intent;
         public final JobInfo jobInfo;
         public final TestWorkItem[] subitems;
+        public final Uri[] requireUrisGranted;
+        public final Uri[] requireUrisNotGranted;
 
         public TestWorkItem(Intent _intent) {
             intent = _intent;
             jobInfo = null;
             subitems = null;
+            requireUrisGranted = null;
+            requireUrisNotGranted = null;
         }
 
         public TestWorkItem(Intent _intent, JobInfo _jobInfo, TestWorkItem[] _subitems) {
             intent = _intent;
             jobInfo = _jobInfo;
             subitems = _subitems;
+            requireUrisGranted = null;
+            requireUrisNotGranted = null;
+        }
+
+        public TestWorkItem(Intent _intent, Uri[] _requireUrisGranted,
+                Uri[] _requireUrisNotGranted) {
+            intent = _intent;
+            jobInfo = null;
+            subitems = null;
+            requireUrisGranted = _requireUrisGranted;
+            requireUrisNotGranted = _requireUrisNotGranted;
         }
     }
 
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/ClipDataJobTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/ClipDataJobTest.java
index 47089d4..03d941e 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/ClipDataJobTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/ClipDataJobTest.java
@@ -73,7 +73,7 @@
         // Schedule the job, the system should now also be holding a URI grant for us.
         kTestEnvironment.setExpectedExecutions(1);
         mJobScheduler.schedule(mBuilder.setRequiresStorageNotLow(true)
-                .setClipData(mClipData, Intent.FLAG_GRANT_READ_URI_PERMISSION
+                .setClipData(mFirstClipData, Intent.FLAG_GRANT_READ_URI_PERMISSION
                         | Intent.FLAG_GRANT_WRITE_URI_PERMISSION).build());
 
         // Remove the explicit grant, we should still have a grant due to the job.
@@ -105,7 +105,7 @@
     public void testClipDataGrant_Failed() throws Exception {
         try {
             mJobScheduler.schedule(mBuilder.setRequiresStorageNotLow(true)
-                    .setClipData(mClipData, Intent.FLAG_GRANT_READ_URI_PERMISSION
+                    .setClipData(mFirstClipData, Intent.FLAG_GRANT_READ_URI_PERMISSION
                             | Intent.FLAG_GRANT_WRITE_URI_PERMISSION).build());
         } catch (SecurityException e) {
             return;
@@ -131,7 +131,7 @@
         // Schedule the job, the system should now also be holding a URI grant for us.
         kTestEnvironment.setExpectedExecutions(1);
         mJobScheduler.schedule(mBuilder.setMinimumLatency(60*60*1000)
-                .setClipData(mClipData, Intent.FLAG_GRANT_READ_URI_PERMISSION
+                .setClipData(mFirstClipData, Intent.FLAG_GRANT_READ_URI_PERMISSION
                         | Intent.FLAG_GRANT_WRITE_URI_PERMISSION).build());
 
         // Remove the explicit grant, we should still have a grant due to the job.
@@ -145,7 +145,7 @@
 
         // Now reschedule the job to have it happen right now.
         mJobScheduler.schedule(mBuilder.setMinimumLatency(0)
-                .setClipData(mClipData, Intent.FLAG_GRANT_READ_URI_PERMISSION
+                .setClipData(mFirstClipData, Intent.FLAG_GRANT_READ_URI_PERMISSION
                         | Intent.FLAG_GRANT_WRITE_URI_PERMISSION).build());
         assertTrue("Job with storage not low constraint did not fire when storage not low.",
                 kTestEnvironment.awaitExecution());
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java
index a7c7003..0a3ff9c 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java
@@ -163,6 +163,27 @@
                 kTestEnvironment.awaitExecution());
     }
 
+    /**
+     * Schedule a job with a metered connectivity constraint, and ensure that it executes
+     * on on a mobile data connection.
+     */
+    public void testConnectivityConstraintExecutes_metered() throws Exception {
+        if (!checkDeviceSupportsMobileData()) {
+            return;
+        }
+        disconnectWifiToConnectToMobile();
+
+        kTestEnvironment.setExpectedExecutions(1);
+        mJobScheduler.schedule(
+                mBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_METERED)
+                        .build());
+
+        sendExpediteStableChargingBroadcast();
+
+        assertTrue("Job with metered connectivity constraint did not fire on mobile.",
+                kTestEnvironment.awaitExecution());
+    }
+
     // --------------------------------------------------------------------------------------------
     // Negatives - schedule jobs under conditions that require that they fail.
     // --------------------------------------------------------------------------------------------
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/ConstraintTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/ConstraintTest.java
index c92e521..bcc1e08 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/ConstraintTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/ConstraintTest.java
@@ -17,7 +17,6 @@
 
 import android.annotation.TargetApi;
 import android.app.Instrumentation;
-import android.app.job.JobInfo;
 import android.app.job.JobScheduler;
 import android.content.ClipData;
 import android.content.ComponentName;
@@ -30,7 +29,6 @@
 import android.os.Bundle;
 import android.os.Process;
 import android.os.SystemClock;
-import android.test.AndroidTestCase;
 import android.test.InstrumentationTestCase;
 import android.util.Log;
 
@@ -67,7 +65,10 @@
 
     Uri mFirstUri;
     Bundle mFirstUriBundle;
-    ClipData mClipData;
+    Uri mSecondUri;
+    Bundle mSecondUriBundle;
+    ClipData mFirstClipData;
+    ClipData mSecondClipData;
 
     boolean mStorageStateChanged;
 
@@ -82,8 +83,13 @@
         mFirstUri = Uri.parse("content://" + JOBPERM_AUTHORITY + "/protected/foo");
         mFirstUriBundle = new Bundle();
         mFirstUriBundle.putParcelable("uri", mFirstUri);
-        mClipData = new ClipData("JobPerm", new String[] { "application/*" },
+        mSecondUri = Uri.parse("content://" + JOBPERM_AUTHORITY + "/protected/bar");
+        mSecondUriBundle = new Bundle();
+        mSecondUriBundle.putParcelable("uri", mSecondUri);
+        mFirstClipData = new ClipData("JobPerm1", new String[] { "application/*" },
                 new ClipData.Item(mFirstUri));
+        mSecondClipData = new ClipData("JobPerm2", new String[] { "application/*" },
+                new ClipData.Item(mSecondUri));
         try {
             SystemUtil.runShellCommand(getInstrumentation(), "cmd activity set-inactive "
                     + mContext.getPackageName() + " false");
@@ -122,10 +128,23 @@
         getContext().sendBroadcast(EXPEDITE_STABLE_CHARGING);
     }
 
+    public void assertHasUriPermission(Uri uri, int grantFlags) {
+        if ((grantFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
+            assertEquals(PackageManager.PERMISSION_GRANTED,
+                    getContext().checkUriPermission(uri, Process.myPid(),
+                            Process.myUid(), Intent.FLAG_GRANT_READ_URI_PERMISSION));
+        }
+        if ((grantFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
+            assertEquals(PackageManager.PERMISSION_GRANTED,
+                    getContext().checkUriPermission(uri, Process.myPid(),
+                            Process.myUid(), Intent.FLAG_GRANT_WRITE_URI_PERMISSION));
+        }
+    }
+
     void waitPermissionRevoke(Uri uri, int access, long timeout) {
         long startTime = SystemClock.elapsedRealtime();
         while (getContext().checkUriPermission(uri, Process.myPid(), Process.myUid(), access)
-                != PackageManager.PERMISSION_GRANTED) {
+                != PackageManager.PERMISSION_DENIED) {
             try {
                 Thread.sleep(50);
             } catch (InterruptedException e) {
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/EnqueueJobWorkTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/EnqueueJobWorkTest.java
index ad5a20f..402233b 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/EnqueueJobWorkTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/EnqueueJobWorkTest.java
@@ -22,6 +22,7 @@
 import android.content.ContentProviderClient;
 import android.content.Intent;
 import android.jobscheduler.MockJobService.TestWorkItem;
+import android.net.Uri;
 
 import java.util.ArrayList;
 
@@ -44,13 +45,13 @@
         super.setUp();
 
         mBuilder = new JobInfo.Builder(ENQUEUE_WORK_JOB_ID, kJobServiceComponent);
-        //mProvider = getContext().getContentResolver().acquireContentProviderClient(mFirstUri);
+        mProvider = getContext().getContentResolver().acquireContentProviderClient(mFirstUri);
     }
 
     @Override
     public void tearDown() throws Exception {
         super.tearDown();
-        //mProvider.close();
+        mProvider.close();
         mJobScheduler.cancel(ENQUEUE_WORK_JOB_ID);
     }
 
@@ -74,19 +75,19 @@
         }
         for (int i = 0; i < received.size(); i++) {
             Intent work = received.get(i);
-            if (i >= expected.length) {
-                fail("Received more than " + expected.length + " work items, first extra is "
-                        + work);
-            }
-            if (!intentEquals(work, expectedArray.get(i).intent)) {
-                fail("Received work #" + i + " " + work + " but expected " + expected[i]);
-            }
             if (i < expected.length && expected[i].subitems != null) {
                 TestWorkItem[] sub = expected[i].subitems;
                 for (int j = 0; j < sub.length; j++) {
                     expectedArray.add(sub[j]);
                 }
             }
+            if (i >= expectedArray.size()) {
+                fail("Received more than " + expected.length + " work items, first extra is "
+                        + work);
+            }
+            if (!intentEquals(work, expectedArray.get(i).intent)) {
+                fail("Received work #" + i + " " + work + " but expected " + expected[i]);
+            }
         }
         if (received.size() < expected.length) {
             fail("Received only " + received.size() + " work items, but expected "
@@ -176,4 +177,61 @@
                 kTestEnvironment.awaitExecution());
         compareWork(work, kTestEnvironment.getLastReceivedWork());
     }
+
+    /**
+     * Test basic enqueueing batches of work.
+     */
+    public void testEnqueueMultipleUriGrantWork() throws Exception {
+        // Start out with storage low, so job is enqueued but not executed yet.
+        setStorageState(true);
+
+        // We need to get a permission grant so that we can grant it to ourself.
+        mProvider.call("grant", MY_PACKAGE, mFirstUriBundle);
+        mProvider.call("grant", MY_PACKAGE, mSecondUriBundle);
+        assertHasUriPermission(mFirstUri, Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+        assertHasUriPermission(mSecondUri, Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+        Intent work1 = new Intent("work1");
+        work1.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+        work1.setData(mFirstUri);
+        work1.setClipData(mSecondClipData);
+
+        Intent work2 = new Intent("work2");
+        work2.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+        work2.setData(mFirstUri);
+
+        TestWorkItem[] work = new TestWorkItem[] {
+                new TestWorkItem(work1, new Uri[] { mFirstUri, mSecondUri}, new Uri[0]),
+                new TestWorkItem(work2, new Uri[] { mFirstUri }, new Uri[] { mSecondUri}) };
+        kTestEnvironment.setExpectedExecutions(1);
+        kTestEnvironment.setExpectedWork(work);
+        JobInfo ji = mBuilder.setOverrideDeadline(0).setRequiresStorageNotLow(true).build();
+        mJobScheduler.enqueue(ji, new JobWorkItem(work1));
+        mJobScheduler.enqueue(ji, new JobWorkItem(work2));
+
+        // Remove the explicit grant, we should still have a grant due to the job.
+        mProvider.call("revoke", MY_PACKAGE, mFirstUriBundle);
+        mProvider.call("revoke", MY_PACKAGE, mSecondUriBundle);
+        assertHasUriPermission(mFirstUri, Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+        assertHasUriPermission(mSecondUri, Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+        kTestEnvironment.readyToWork();
+
+        // Now allow the job to run.
+        setStorageState(false);
+
+        assertTrue("Job with work enqueued did not fire.",
+                kTestEnvironment.awaitExecution());
+        compareWork(work, kTestEnvironment.getLastReceivedWork());
+
+        // And wait for everything to be cleaned up.
+        waitPermissionRevoke(mFirstUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, 5000);
+        waitPermissionRevoke(mSecondUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, 5000);
+    }
 }
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
index 1185813..1979e97 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
@@ -23,7 +23,6 @@
 import android.test.InstrumentationTestCase;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
-import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
 import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
 import android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener;
 
@@ -83,15 +82,6 @@
         assertFalse(mAccessibilityManager.removeTouchExplorationStateChangeListener(listener));
     }
 
-    public void testAddAndRemoveServiceStateChangeListener() throws Exception {
-        AccessibilityServicesStateChangeListener listener = () -> {
-            // Do Nothing
-        };
-        assertTrue(mAccessibilityManager.addAccessibilityServicesStateChangeListener(listener));
-        assertTrue(mAccessibilityManager.removeAccessibilityServicesStateChangeListener(listener));
-        assertFalse(mAccessibilityManager.removeAccessibilityServicesStateChangeListener(listener));
-    }
-
     public void testIsTouchExplorationEnabled() throws Exception {
         new PollingCheck() {
             @Override
@@ -240,44 +230,6 @@
         waitForTouchExplorationEnabled();
     }
 
-    public void testServiceStateChanges_stateChangeListenersCalled() throws Exception {
-        final Object waitObject = new Object();
-        final AtomicBoolean listenerCalled = new AtomicBoolean(false);
-        final SpeakingAccessibilityService service =
-                SpeakingAccessibilityService.sConnectedInstance;
-        final AccessibilityServicesStateChangeListener listener = () -> {
-            synchronized (waitObject) {
-                listenerCalled.set(true);
-                waitObject.notifyAll();
-            }
-        };
-
-        mAccessibilityManager.addAccessibilityServicesStateChangeListener(listener);
-        // Verify called on info change
-        final AccessibilityServiceInfo initialInfo = service.getServiceInfo();
-        AccessibilityServiceInfo tempInfo = service.getServiceInfo();
-        tempInfo.flags ^= AccessibilityServiceInfo.FLAG_ENABLE_ACCESSIBILITY_VOLUME;
-        try {
-            service.setServiceInfo(tempInfo);
-            assertListenerCalled(listenerCalled, waitObject);
-        } finally {
-            service.setServiceInfo(initialInfo);
-        }
-
-        // Verify called on service disabled
-        listenerCalled.set(false);
-        ServiceControlUtils.turnAccessibilityOff(getInstrumentation());
-        assertListenerCalled(listenerCalled, waitObject);
-
-        // Verify called on service enabled
-        listenerCalled.set(false);
-        ServiceControlUtils.enableSpeakingAndVibratingServices(getInstrumentation());
-        assertListenerCalled(listenerCalled, waitObject);
-
-        mAccessibilityManager.removeAccessibilityServicesStateChangeListener(listener);
-
-    }
-
     private void assertListenerCalled(AtomicBoolean listenerCalled, Object waitObject)
             throws Exception {
         long timeoutTime = System.currentTimeMillis() + WAIT_FOR_ACCESSIBILITY_ENABLED_TIMEOUT;
diff --git a/tests/app/src/android/app/cts/ActivityManagerTest.java b/tests/app/src/android/app/cts/ActivityManagerTest.java
index e3e7c53..f29ae1e 100644
--- a/tests/app/src/android/app/cts/ActivityManagerTest.java
+++ b/tests/app/src/android/app/cts/ActivityManagerTest.java
@@ -36,6 +36,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
 import android.platform.test.annotations.RestrictedBuildTest;
 import android.test.InstrumentationTestCase;
 
@@ -398,6 +399,20 @@
         Thread.sleep(WAIT_TIME);
     }
 
+   /**
+    * Gets the value of com.android.internal.R.bool.config_noHomeScreen.
+    * @return true if no home screen is supported, false otherwise.
+    */
+   private boolean noHomeScreen() {
+       try {
+           return getInstrumentation().getContext().getResources().getBoolean(
+                   Resources.getSystem().getIdentifier("config_noHomeScreen", "bool", "android"));
+       } catch (Resources.NotFoundException e) {
+           // Assume there's a home screen.
+           return false;
+       }
+    }
+
     /**
      * Verify that the TimeTrackingAPI works properly when starting and ending an activity.
      */
@@ -429,10 +444,20 @@
         assertEquals(RESULT_PASS, appEndReceiver.waitForActivity());
         appEndReceiver.close();
 
-        // At this time the timerReceiver should not fire, even though the activity has shut down,
-        // because we are back to the home screen.
-        assertEquals(RESULT_TIMEOUT, timeReceiver.waitForActivity());
-        assertTrue(timeReceiver.mTimeUsed == 0);
+        if (!noHomeScreen()) {
+            // At this time the timerReceiver should not fire, even though the activity has shut
+            // down, because we are back to the home screen. Going to the home screen does not
+            // qualify as the user leaving the activity's flow. The time tracking is considered
+            // complete only when the user switches to another activity that is not part of the
+            // tracked flow.
+            assertEquals(RESULT_TIMEOUT, timeReceiver.waitForActivity());
+            assertTrue(timeReceiver.mTimeUsed == 0);
+        } else {
+            // With platforms that have no home screen, focus is returned to something else that is
+            // considered a completion of the tracked activity flow, and hence time tracking is
+            // triggered.
+            assertEquals(RESULT_PASS, timeReceiver.waitForActivity());
+        }
 
         // Issuing now another activity will trigger the timing information release.
         final Intent dummyIntent = new Intent(context, MockApplicationActivity.class);
@@ -525,9 +550,20 @@
         assertEquals(RESULT_PASS, appEndReceiver.waitForActivity());
         appEndReceiver.close();
 
-        // At this time the timerReceiver should not fire, even though the activity has shut down.
-        assertEquals(RESULT_TIMEOUT, timeReceiver.waitForActivity());
-        assertTrue(timeReceiver.mTimeUsed == 0);
+        if (!noHomeScreen()) {
+            // At this time the timerReceiver should not fire, even though the activity has shut
+            // down, because we are back to the home screen. Going to the home screen does not
+            // qualify as the user leaving the activity's flow. The time tracking is considered
+            // complete only when the user switches to another activity that is not part of the
+            // tracked flow.
+            assertEquals(RESULT_TIMEOUT, timeReceiver.waitForActivity());
+            assertTrue(timeReceiver.mTimeUsed == 0);
+        } else {
+            // With platforms that have no home screen, focus is returned to something else that is
+            // considered a completion of the tracked activity flow, and hence time tracking is
+            // triggered.
+            assertEquals(RESULT_PASS, timeReceiver.waitForActivity());
+        }
 
         // Issue another activity so that the timing information gets released.
         final Intent dummyIntent = new Intent(context, MockApplicationActivity.class);
diff --git a/tests/app/src/android/app/cts/AlertWindowsTests.java b/tests/app/src/android/app/cts/AlertWindowsTests.java
index 6d76d3b..f7c8ff8 100644
--- a/tests/app/src/android/app/cts/AlertWindowsTests.java
+++ b/tests/app/src/android/app/cts/AlertWindowsTests.java
@@ -17,41 +17,48 @@
 package android.app.cts;
 
 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
+import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE_DEPRECATED;
 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
 import static android.content.Context.BIND_ALLOW_OOM_MANAGEMENT;
 import static android.content.Context.BIND_AUTO_CREATE;
 import static android.content.Context.BIND_NOT_FOREGROUND;
+
 import static com.android.app2.AlertWindowService.MSG_ADD_ALERT_WINDOW;
 import static com.android.app2.AlertWindowService.MSG_ON_ALERT_WINDOW_ADDED;
 import static com.android.app2.AlertWindowService.MSG_ON_ALERT_WINDOW_REMOVED;
 import static com.android.app2.AlertWindowService.MSG_REMOVE_ALERT_WINDOW;
 import static com.android.app2.AlertWindowService.MSG_REMOVE_ALL_ALERT_WINDOWS;
 import static com.android.app2.AlertWindowService.NOTIFICATION_MESSENGER_EXTRA;
+
 import static org.junit.Assert.assertEquals;
 
-import android.platform.test.annotations.Presubmit;
-import com.android.app2.AlertWindowService;
-import com.android.compatibility.common.util.SystemUtil;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.runner.RunWith;
-import org.junit.Test;
-
 import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
 import android.os.Messenger;
+import android.platform.test.annotations.Presubmit;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
 import android.util.Log;
 
+import com.android.app2.AlertWindowService;
+import com.android.compatibility.common.util.SystemUtil;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.function.Function;
+
 /**
  * Build: mmma -j32 cts/tests/app
  * Run: cts/hostsidetests/services/activityandwindowmanager/util/run-test CtsAppTestCases android.app.cts.AlertWindowsTests
@@ -61,12 +68,20 @@
 public class AlertWindowsTests {
 
     private static final String TAG = "AlertWindowsTests";
+
     private static final boolean DEBUG = false;
     private static final long WAIT_TIME_MS = 2 * 1000;
 
+    private static final String SDK25_PACKAGE_NAME = "com.android.appSdk25";
+
     private Messenger mService;
     private String mServicePackageName;
+    private int mServiceUid;
+
+    private PackageManager mPm;
+
     private ActivityManager mAm;
+    private ActivityManager mAm25; // ActivityManager created for an SDK 25 app context.
 
     private final Messenger mMessenger = new Messenger(new IncomingHandler(Looper.getMainLooper()));
     private final Object mAddedLock = new Object();
@@ -76,7 +91,12 @@
     public void setUp() throws Exception {
         if (DEBUG) Log.e(TAG, "setUp");
         final Context context = InstrumentationRegistry.getTargetContext();
+
+        mPm = context.getPackageManager();
+
         mAm = context.getSystemService(ActivityManager.class);
+        mAm25 = context.createPackageContext(SDK25_PACKAGE_NAME, 0)
+                .getSystemService(ActivityManager.class);
 
         final Intent intent = new Intent();
         intent.setClassName(AlertWindowService.class.getPackage().getName(),
@@ -107,27 +127,34 @@
     public void testAlertWindowOomAdj() throws Exception {
         setAlertWindowPermission(true /* allow */);
 
-        assertImportance(IMPORTANCE_PERCEPTIBLE);
+        assertPackageImportance(IMPORTANCE_PERCEPTIBLE, IMPORTANCE_PERCEPTIBLE_DEPRECATED);
+        assertUidImportance(IMPORTANCE_PERCEPTIBLE, IMPORTANCE_PERCEPTIBLE_DEPRECATED);
+
         addAlertWindow();
         // Process importance should be increased to visible when the service has an alert window.
-        assertImportance(IMPORTANCE_VISIBLE);
+        assertPackageImportance(IMPORTANCE_VISIBLE, IMPORTANCE_VISIBLE);
+
+        // TODO: Somehow getUidImportance still returns 230 (IMPORTANCE_PERCEPTIBLE) instead of
+        // IMPORTANCE_VISIBLE(200)
+        // assertUidImportance(IMPORTANCE_VISIBLE, IMPORTANCE_VISIBLE);
+
         addAlertWindow();
-        assertImportance(IMPORTANCE_VISIBLE);
+        assertPackageImportance(IMPORTANCE_VISIBLE, IMPORTANCE_VISIBLE);
 
         setAlertWindowPermission(false /* allow */);
         // Process importance should no longer be visible since its alert windows are not allowed to
         // be visible.
-        assertImportance(IMPORTANCE_PERCEPTIBLE);
+        assertPackageImportance(IMPORTANCE_PERCEPTIBLE, IMPORTANCE_PERCEPTIBLE_DEPRECATED);
         setAlertWindowPermission(true /* allow */);
         // They can show again so importance should be visible again.
-        assertImportance(IMPORTANCE_VISIBLE);
+        assertPackageImportance(IMPORTANCE_VISIBLE, IMPORTANCE_VISIBLE);
 
         removeAlertWindow();
-        assertImportance(IMPORTANCE_VISIBLE);
+        assertPackageImportance(IMPORTANCE_VISIBLE, IMPORTANCE_VISIBLE);
         removeAlertWindow();
         // Process importance should no longer be visible when the service no longer as alert
         // windows.
-        assertImportance(IMPORTANCE_PERCEPTIBLE);
+        assertPackageImportance(IMPORTANCE_PERCEPTIBLE, IMPORTANCE_PERCEPTIBLE_DEPRECATED);
     }
 
     private void addAlertWindow() throws Exception {
@@ -152,7 +179,8 @@
         SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), cmd);
     }
 
-    private void assertImportance(int expected) throws Exception {
+    private void assertImportance(Function<ActivityManager, Integer> apiCaller,
+            int expectedForO, int expectedForPreO) throws Exception {
         int retry = 3;
         int actual;
 
@@ -161,10 +189,29 @@
             // for changes in the uid importance. However, the way it is currently structured
             // doesn't really work for this use case right now...
             Thread.sleep(500);
-            actual = mAm.getPackageImportance(mServicePackageName);
-        } while (actual != expected && --retry > 0);
+            actual = apiCaller.apply(mAm);
+        } while (actual != expectedForO && --retry > 0);
 
-        assertEquals(expected, actual);
+        assertEquals(expectedForO, actual);
+
+        // Check the result for pre-O apps.
+        assertEquals(expectedForPreO, (int) apiCaller.apply(mAm25));
+    }
+
+    /**
+     * Make sure {@link ActivityManager#getPackageImportance} returns the expected value.
+     */
+    private void assertPackageImportance(int expectedForO, int expectedForPreO) throws Exception {
+        assertImportance(am -> am.getPackageImportance(mServicePackageName),
+                expectedForO, expectedForPreO);
+    }
+
+    /**
+     * Make sure {@link ActivityManager#getUidImportance(int)} returns the expected value.
+     */
+    private void assertUidImportance(int expectedForO, int expectedForPreO) throws Exception {
+        assertImportance(am -> am.getUidImportance(mServiceUid),
+                expectedForO, expectedForPreO);
     }
 
     private final ServiceConnection mConnection = new ServiceConnection() {
@@ -173,6 +220,11 @@
             if (DEBUG) Log.e(TAG, "onServiceConnected");
             mService = new Messenger(service);
             mServicePackageName = name.getPackageName();
+            try {
+                mServiceUid = mPm.getPackageUid(mServicePackageName, 0);
+            } catch (NameNotFoundException e) {
+                throw new RuntimeException("getPackageUid() failed.", e);
+            }
             synchronized (mConnection) {
                 notifyAll();
             }
@@ -183,6 +235,7 @@
             if (DEBUG) Log.e(TAG, "onServiceDisconnected");
             mService = null;
             mServicePackageName = null;
+            mServiceUid = 0;
         }
     };
 
diff --git a/tests/app/src/android/app/cts/NotificationChannelTest.java b/tests/app/src/android/app/cts/NotificationChannelTest.java
index 74047be..70ec9cf 100644
--- a/tests/app/src/android/app/cts/NotificationChannelTest.java
+++ b/tests/app/src/android/app/cts/NotificationChannelTest.java
@@ -25,6 +25,7 @@
 import android.media.AudioAttributes;
 import android.net.Uri;
 import android.os.Parcel;
+import android.provider.Settings;
 import android.test.AndroidTestCase;
 
 public class NotificationChannelTest extends AndroidTestCase {
@@ -52,7 +53,7 @@
         assertEquals(false, channel.shouldVibrate());
         assertEquals(null, channel.getVibrationPattern());
         assertEquals(IMPORTANCE_DEFAULT, channel.getImportance());
-        assertEquals(null, channel.getSound());
+        assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, channel.getSound());
         assertTrue(channel.canShowBadge());
         assertEquals(Notification.AUDIO_ATTRIBUTES_DEFAULT, channel.getAudioAttributes());
         assertEquals(null, channel.getGroup());
diff --git a/tests/autofillservice/AndroidManifest.xml b/tests/autofillservice/AndroidManifest.xml
index 663fe40..32bf5a5 100644
--- a/tests/autofillservice/AndroidManifest.xml
+++ b/tests/autofillservice/AndroidManifest.xml
@@ -51,8 +51,10 @@
             </intent-filter>
         </activity>
         <activity android:name=".EmptyActivity"/>
+        <activity android:name=".DummyActivity"/>
         <activity android:name=".OutOfProcessLoginActivity"
             android:process="android.autofillservice.cts.outside"/>
+        <activity android:name=".FragmentContainerActivity" />
 
         <service
             android:name=".InstrumentedAutoFillService"
diff --git a/tests/autofillservice/res/layout/fragment_container.xml b/tests/autofillservice/res/layout/fragment_container.xml
new file mode 100644
index 0000000..156efad
--- /dev/null
+++ b/tests/autofillservice/res/layout/fragment_container.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  * Copyright (C) 2017 The Android Open Source Project
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *      http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:id="@+id/rootContainer" />
diff --git a/tests/autofillservice/res/layout/fragment_with_edittext.xml b/tests/autofillservice/res/layout/fragment_with_edittext.xml
new file mode 100644
index 0000000..e0d4584
--- /dev/null
+++ b/tests/autofillservice/res/layout/fragment_with_edittext.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  * Copyright (C) 2017 The Android Open Source Project
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *      http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT 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:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <EditText android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:id="@+id/editText1" />
+
+    <EditText android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:id="@+id/editText2" />
+</LinearLayout>
diff --git a/tests/autofillservice/res/layout/view_attribute_test_activity.xml b/tests/autofillservice/res/layout/view_attribute_test_activity.xml
index e383d6c..96c0186 100644
--- a/tests/autofillservice/res/layout/view_attribute_test_activity.xml
+++ b/tests/autofillservice/res/layout/view_attribute_test_activity.xml
@@ -19,34 +19,6 @@
     android:layout_width="match_parent" android:layout_height="match_parent"
     android:orientation="vertical" android:id="@+id/rootContainer">
 
-    <EditText android:id="@+id/firstLevelDefault" android:layout_width="wrap_content"
-        android:layout_height="wrap_content" />
-
-    <EditText android:id="@+id/firstLevelInherit" android:layout_width="wrap_content"
-        android:layout_height="wrap_content" android:autofillMode="inherit" />
-
-    <EditText android:id="@+id/firstLevelAuto" android:layout_width="wrap_content"
-        android:layout_height="wrap_content" android:autofillMode="auto" />
-
-    <EditText android:id="@+id/firstLevelManual" android:layout_width="wrap_content"
-        android:layout_height="wrap_content" android:autofillMode="manual" />
-
-    <LinearLayout android:id="@+id/manualContainer" android:layout_width="wrap_content"
-        android:layout_height="wrap_content" android:autofillMode="manual"
-        android:orientation="vertical">
-        <EditText android:id="@+id/manualContainerDefault" android:layout_width="wrap_content"
-            android:layout_height="wrap_content" />
-
-        <EditText android:id="@+id/manualContainerInherit" android:layout_width="wrap_content"
-            android:layout_height="wrap_content" android:autofillMode="inherit" />
-
-        <EditText android:id="@+id/manualContainerAuto" android:layout_width="wrap_content"
-            android:layout_height="wrap_content" android:autofillMode="auto" />
-
-        <EditText android:id="@+id/manualContainerManual" android:layout_width="wrap_content"
-            android:layout_height="wrap_content" android:autofillMode="manual" />
-    </LinearLayout>
-
     <TextView android:id="@+id/textViewNoHint" android:layout_width="wrap_content"
         android:layout_height="wrap_content" />
     <TextView android:id="@+id/textViewHintCustom" android:layout_width="wrap_content"
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AbstractAutoFillActivity.java b/tests/autofillservice/src/android/autofillservice/cts/AbstractAutoFillActivity.java
index f0b56d4..efc0b2c 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AbstractAutoFillActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AbstractAutoFillActivity.java
@@ -50,8 +50,8 @@
         });
         try {
             if (!latch.await(timeoutMs, TimeUnit.MILLISECONDS)) {
-                throw new AssertionError(
-                        "action on UI thread timed out after " + timeoutMs + " ms");
+                throw new RetryableException("action on UI thread timed out after %d ms",
+                        timeoutMs);
             }
         } catch (InterruptedException e) {
             Thread.currentThread().interrupt();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
index df61e37..d18e621 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
@@ -32,6 +32,7 @@
 import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.BeforeClass;
+import org.junit.Rule;
 import org.junit.runner.RunWith;
 
 /**
@@ -48,6 +49,9 @@
 
     protected static final Replier sReplier = InstrumentedAutoFillService.getReplier();
 
+    @Rule
+    public final RetryRule mRetryRule = new RetryRule(2);
+
     @BeforeClass
     public static void removeLockScreen() {
         runShellCommand("input keyevent KEYCODE_WAKEUP");
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AutoFinishSessionTest.java b/tests/autofillservice/src/android/autofillservice/cts/AutoFinishSessionTest.java
new file mode 100644
index 0000000..4a0e992
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/AutoFinishSessionTest.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.autofillservice.cts;
+
+import static android.autofillservice.cts.FragmentContainerActivity.FRAGMENT_TAG;
+import static android.autofillservice.cts.Helper.FILL_TIMEOUT_MS;
+import static android.autofillservice.cts.Helper.eventually;
+import static android.autofillservice.cts.Helper.findNodeByResourceId;
+import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_GENERIC;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.Fragment;
+import android.autofillservice.cts.InstrumentedAutoFillService.SaveRequest;
+import android.content.Intent;
+import android.service.autofill.SaveInfo;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.test.rule.ActivityTestRule;
+import android.view.ViewGroup;
+import android.widget.EditText;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+/**
+ * Tests that the session finishes when the views and fragments go away
+ */
+public class AutoFinishSessionTest extends AutoFillServiceTestCase {
+    @Rule
+    public final ActivityTestRule<FragmentContainerActivity> mActivityRule =
+            new ActivityTestRule<>(FragmentContainerActivity.class);
+    private FragmentContainerActivity mActivity;
+    private EditText mEditText1;
+    private EditText mEditText2;
+    private Fragment mFragment;
+    private ViewGroup mParent;
+
+    @Before
+    public void initViews() {
+        mActivity = mActivityRule.getActivity();
+        mEditText1 = mActivity.findViewById(R.id.editText1);
+        mEditText2 = mActivity.findViewById(R.id.editText2);
+        mFragment = mActivity.getFragmentManager().findFragmentByTag(FRAGMENT_TAG);
+        mParent = ((ViewGroup) mEditText1.getParent());
+
+        assertThat(mFragment).isNotNull();
+    }
+
+    private void removeViewsBaseTest(@NonNull Runnable firstRemove, @Nullable Runnable firstCheck,
+            @Nullable Runnable secondRemove, String... viewsToSave)
+            throws Exception {
+        enableService();
+        try {
+            // Set expectations.
+            sReplier.addResponse(new CannedFillResponse.Builder()
+                    .setFlags(SaveInfo.FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE)
+                    .setRequiredSavableIds(SAVE_DATA_TYPE_GENERIC, viewsToSave).build());
+
+            // Trigger autofill
+            eventually(() -> {
+                mActivity.syncRunOnUiThread(() -> mEditText2.requestFocus());
+                mActivity.syncRunOnUiThread(() -> mEditText1.requestFocus());
+
+                try {
+                    sReplier.getNextFillRequest();
+                } catch (InterruptedException e) {
+                    throw new RuntimeException(e);
+                }
+            }, (int) (FILL_TIMEOUT_MS * 2));
+
+            sUiBot.assertNoDatasets();
+
+            // remove first set of views
+            mActivity.syncRunOnUiThread(() -> {
+                mEditText1.setText("editText1-filled");
+                mEditText2.setText("editText2-filled");
+            });
+            firstRemove.run();
+
+            // Check state between remove operations
+            if (firstCheck != null) {
+                firstCheck.run();
+            }
+
+            // remove second set of views
+            if (secondRemove != null) {
+                secondRemove.run();
+            }
+
+            // Save should be shows after all remove operations were executed
+            sUiBot.saveForAutofill(true, SAVE_DATA_TYPE_GENERIC);
+
+            SaveRequest saveRequest = sReplier.getNextSaveRequest();
+            for (String view : viewsToSave) {
+                assertThat(findNodeByResourceId(saveRequest.structure, view)
+                        .getAutofillValue().getTextValue().toString()).isEqualTo(view + "-filled");
+            }
+        } finally {
+            disableService();
+        }
+    }
+
+    @Test
+    public void removeBothViewsToFinishSession() throws Exception {
+        removeViewsBaseTest(
+                () -> mActivity.syncRunOnUiThread(
+                        () -> ((ViewGroup) mEditText1.getParent()).removeView(mEditText1)),
+                () -> sUiBot.assertSaveNotShowing(SAVE_DATA_TYPE_GENERIC),
+                () -> mActivity.syncRunOnUiThread(
+                        () -> ((ViewGroup) mEditText2.getParent()).removeView(mEditText2)),
+                "editText1", "editText2");
+    }
+
+    @Test
+    public void removeOneViewToFinishSession() throws Exception {
+        removeViewsBaseTest(
+                () -> mActivity.syncRunOnUiThread(() -> {
+                    // Do not trigger new partition when switching to editText2
+                    mEditText2.setFocusable(false);
+
+                    mParent.removeView(mEditText1);
+                }),
+                null,
+                null,
+                "editText1");
+    }
+
+    @Test
+    public void hideOneViewToFinishSession() throws Exception {
+        removeViewsBaseTest(
+                () -> mActivity.syncRunOnUiThread(
+                        () -> mEditText1.setVisibility(ViewGroup.INVISIBLE)),
+                null,
+                null,
+                "editText1");
+    }
+
+    @Test
+    public void removeFragmentToFinishSession() throws Exception {
+        removeViewsBaseTest(
+                () -> mActivity.syncRunOnUiThread(
+                        () -> mActivity.getFragmentManager().beginTransaction().remove(
+                                mFragment).commitNow()),
+                null,
+                null,
+                "editText1", "editText2");
+    }
+
+    @Test
+    public void removeParentToFinishSession() throws Exception {
+        removeViewsBaseTest(
+                () -> mActivity.syncRunOnUiThread(
+                        () -> ((ViewGroup) mParent.getParent()).removeView(mParent)),
+                null,
+                null,
+                "editText1", "editText2");
+    }
+
+    @Test
+    public void hideParentToFinishSession() throws Exception {
+        removeViewsBaseTest(
+                () -> mActivity.syncRunOnUiThread(() -> mParent.setVisibility(ViewGroup.INVISIBLE)),
+                null,
+                null,
+                "editText1", "editText2");
+    }
+
+    /**
+     * An activity that is currently getting autofilled might go into the background. While the
+     * tracked views are not visible on the screen anymore, this should not trigger a save.
+     */
+    public void activityToBackgroundShouldNotTriggerSave(@Nullable Runnable removeInBackGround,
+            @Nullable Runnable removeInForeGroup) throws Exception {
+        enableService();
+        try {
+            // Set expectations.
+            sReplier.addResponse(new CannedFillResponse.Builder()
+                    .setFlags(SaveInfo.FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE)
+                    .setRequiredSavableIds(SAVE_DATA_TYPE_GENERIC, "editText1").build());
+
+            // Trigger autofill
+            eventually(() -> {
+                mActivity.syncRunOnUiThread(() -> mEditText2.requestFocus());
+                mActivity.syncRunOnUiThread(() -> mEditText1.requestFocus());
+
+                try {
+                    sReplier.getNextFillRequest();
+                } catch (InterruptedException e) {
+                    throw new RuntimeException(e);
+                }
+            }, (int) (FILL_TIMEOUT_MS * 2));
+
+            sUiBot.assertNoDatasets();
+
+            mActivity.syncRunOnUiThread(() -> {
+                mEditText1.setText("editText1-filled");
+                mEditText2.setText("editText2-filled");
+            });
+
+            // Start activity on top
+            mActivity.startActivity(new Intent(getContext(),
+                    ManualAuthenticationActivity.class));
+            mActivity.waitUntilStopped();
+
+            if (removeInBackGround != null) {
+                removeInBackGround.run();
+            }
+
+            sUiBot.assertSaveNotShowing(SAVE_DATA_TYPE_GENERIC);
+
+            // Remove previously started activity from top
+            sUiBot.selectById("android.autofillservice.cts:id/button");
+            mActivity.waitUntilResumed();
+
+            if (removeInForeGroup != null) {
+                sUiBot.assertSaveNotShowing(SAVE_DATA_TYPE_GENERIC);
+
+                removeInForeGroup.run();
+            }
+
+            // Save should be shows after all remove operations were executed
+            sUiBot.saveForAutofill(true, SAVE_DATA_TYPE_GENERIC);
+
+            SaveRequest saveRequest = sReplier.getNextSaveRequest();
+            assertThat(findNodeByResourceId(saveRequest.structure, "editText1")
+                    .getAutofillValue().getTextValue().toString()).isEqualTo("editText1-filled");
+        } finally {
+            disableService();
+        }
+    }
+
+    @Test
+    public void removeViewInBackground() throws Exception {
+        activityToBackgroundShouldNotTriggerSave(
+                () -> mActivity.syncRunOnUiThread(() -> {
+                    // Do not trigger new partition when switching to editText2
+                    mEditText2.setFocusable(false);
+
+                    mParent.removeView(mEditText1);
+                }),
+                null);
+    }
+
+    @Test
+    public void hideViewInBackground() throws Exception {
+        activityToBackgroundShouldNotTriggerSave(
+                () -> mActivity.syncRunOnUiThread(() -> {
+                    // Do not trigger new partition when switching to editText2
+                    mEditText2.setFocusable(false);
+
+                    mEditText1.setVisibility(ViewGroup.INVISIBLE);
+                }),
+                null);
+    }
+
+    @Test
+    public void hideParentInBackground() throws Exception {
+        activityToBackgroundShouldNotTriggerSave(
+                () -> mActivity.syncRunOnUiThread(() -> mParent.setVisibility(ViewGroup.INVISIBLE)),
+                null);
+    }
+
+    @Test
+    public void removeParentInBackground() throws Exception {
+        activityToBackgroundShouldNotTriggerSave(
+                () -> mActivity.syncRunOnUiThread(
+                        () -> ((ViewGroup) mParent.getParent()).removeView(mParent)),
+                null);
+    }
+
+    @Test
+    public void removeViewAfterBackground() throws Exception {
+        activityToBackgroundShouldNotTriggerSave(
+                () -> mActivity.syncRunOnUiThread(() -> {
+                    // Do not trigger new fill request when closing activity
+                    mEditText1.setFocusable(false);
+                    mEditText2.setFocusable(false);
+                }),
+                () -> mActivity.syncRunOnUiThread(() -> {
+                    mParent.removeView(mEditText1);
+                }));
+    }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java b/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
index 2fa29ce..b4f5f06 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
@@ -66,6 +66,7 @@
     private final String[] mAuthenticationIds;
     private final CharSequence mNegativeActionLabel;
     private final IntentSender mNegativeActionListener;
+    private final int mFlags;
 
     private CannedFillResponse(Builder builder) {
         mDatasets = builder.mDatasets;
@@ -79,6 +80,7 @@
         mAuthenticationIds = builder.mAuthenticationIds;
         mNegativeActionLabel = builder.mNegativeActionLabel;
         mNegativeActionListener = builder.mNegativeActionListener;
+        mFlags = builder.mFlags;
     }
 
     /**
@@ -101,8 +103,17 @@
             }
         }
         if (mRequiredSavableIds != null) {
-            final SaveInfo.Builder saveInfo = new SaveInfo.Builder(mSaveType,
-                    getAutofillIds(structure, mRequiredSavableIds));
+            final SaveInfo.Builder saveInfo;
+
+            if (mRequiredSavableIds == null) {
+                saveInfo = new SaveInfo.Builder(mSaveType, null);
+            } else {
+                saveInfo = new SaveInfo.Builder(mSaveType,
+                        getAutofillIds(structure, mRequiredSavableIds));
+            }
+
+            saveInfo.setFlags(mFlags);
+
             if (mOptionalSavableIds != null) {
                 saveInfo.setOptionalIds(getAutofillIds(structure, mOptionalSavableIds));
             }
@@ -126,6 +137,7 @@
         return "CannedFillResponse: [datasets=" + mDatasets
                 + ", requiredSavableIds=" + Arrays.toString(mRequiredSavableIds)
                 + ", optionalSavableIds=" + Arrays.toString(mOptionalSavableIds)
+                + ", mFlags=" + mFlags
                 + ", saveDescription=" + mSaveDescription
                 + ", hasPresentation=" + (mPresentation != null)
                 + ", hasAuthentication=" + (mAuthentication != null)
@@ -145,6 +157,7 @@
         private String[] mAuthenticationIds;
         private CharSequence mNegativeActionLabel;
         private IntentSender mNegativeActionListener;
+        private int mFlags;
 
         public Builder addDataset(CannedDataset dataset) {
             mDatasets.add(dataset);
@@ -160,6 +173,11 @@
             return this;
         }
 
+        public Builder setFlags(int flags) {
+            mFlags = flags;
+            return this;
+        }
+
         /**
          * Sets the optional savable ids based on they {@code resourceId}.
          */
diff --git a/tests/autofillservice/src/android/autofillservice/cts/DummyActivity.java b/tests/autofillservice/src/android/autofillservice/cts/DummyActivity.java
new file mode 100644
index 0000000..a1f5bd9
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/DummyActivity.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.autofillservice.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TextView;
+
+public class DummyActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        TextView text = new TextView(this);
+        text.setText("foo");
+        setContentView(text);
+    }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/FragmentContainerActivity.java b/tests/autofillservice/src/android/autofillservice/cts/FragmentContainerActivity.java
new file mode 100644
index 0000000..7be4496
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/FragmentContainerActivity.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.autofillservice.cts;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Activity containing an fragment
+ */
+public class FragmentContainerActivity extends AbstractAutoFillActivity {
+    static final String FRAGMENT_TAG =
+            FragmentContainerActivity.class.getName() + "#FRAGMENT_TAG";
+    private CountDownLatch mResumed = new CountDownLatch(1);
+    private CountDownLatch mStopped = new CountDownLatch(0);
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.fragment_container);
+
+        // have to manually add fragment as we cannot remove it otherwise
+        getFragmentManager().beginTransaction().add(R.id.rootContainer,
+                new FragmentWithEditText(), FRAGMENT_TAG).commitNow();
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+
+        mStopped = new CountDownLatch(1);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+
+        mResumed.countDown();
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+
+        mResumed = new CountDownLatch(1);
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+
+        mStopped.countDown();
+    }
+
+    public boolean waitUntilResumed() throws InterruptedException {
+        return mResumed.await(Helper.UI_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+    }
+
+    public boolean waitUntilStopped() throws InterruptedException {
+        return mStopped.await(Helper.UI_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+    }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/FragmentWithEditText.java b/tests/autofillservice/src/android/autofillservice/cts/FragmentWithEditText.java
new file mode 100644
index 0000000..963daff
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/FragmentWithEditText.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.autofillservice.cts;
+
+import android.support.annotation.Nullable;
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.EditText;
+
+/**
+ * A fragment with containing a single {@link EditText}
+ */
+public class FragmentWithEditText extends Fragment {
+    @Override
+    @Nullable public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
+            Bundle savedInstanceState) {
+        return inflater.inflate(R.layout.fragment_with_edittext, null);
+    }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/GridActivity.java b/tests/autofillservice/src/android/autofillservice/cts/GridActivity.java
index 6df6f10..c9b6d30 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/GridActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/GridActivity.java
@@ -113,7 +113,7 @@
         onCell(row, column, (c) -> queue.offer(c.getText().toString()));
         final String text = queue.poll(100, TimeUnit.MILLISECONDS);
         if (text == null) {
-            throw new AssertionError("text not set in 100ms");
+            throw new RetryableException("text not set in 100ms");
         }
         return text;
     }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java b/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
index c78a6e1..bd69587 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
@@ -107,7 +107,7 @@
         final String state = sConnectionStates.poll(CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS);
         if (state == null) {
             dumpAutofillService();
-            throw new AssertionError("not connected in " + CONNECTION_TIMEOUT_MS + " ms");
+            throw new RetryableException("not connected in %d ms", CONNECTION_TIMEOUT_MS);
         }
         assertWithMessage("Invalid connection state").that(state).isEqualTo(STATE_CONNECTED);
     }
@@ -122,7 +122,7 @@
         final String state = sConnectionStates.poll(2 * IDLE_UNBIND_TIMEOUT_MS,
                 TimeUnit.MILLISECONDS);
         if (state == null) {
-            throw new AssertionError("not disconnected in " + IDLE_UNBIND_TIMEOUT_MS + " ms");
+            throw new RetryableException("not disconnected in %d ms", IDLE_UNBIND_TIMEOUT_MS);
         }
         assertWithMessage("Invalid connection state").that(state).isEqualTo(STATE_DISCONNECTED);
     }
@@ -221,8 +221,8 @@
         FillRequest getNextFillRequest() throws InterruptedException {
             final FillRequest request = mFillRequests.poll(FILL_TIMEOUT_MS, TimeUnit.MILLISECONDS);
             if (request == null) {
-                throw new AssertionError(
-                        "onFillRequest() not called in " + FILL_TIMEOUT_MS + " ms");
+                throw new RetryableException("onFillRequest() not called in %s ms",
+                        FILL_TIMEOUT_MS);
             }
             return request;
         }
@@ -245,8 +245,8 @@
         SaveRequest getNextSaveRequest() throws InterruptedException {
             final SaveRequest request = mSaveRequests.poll(SAVE_TIMEOUT_MS, TimeUnit.MILLISECONDS);
             if (request == null) {
-                throw new AssertionError(
-                        "onSaveRequest() not called in " + SAVE_TIMEOUT_MS + " ms");
+                throw new RetryableException(
+                        "onSaveRequest() not called in %d ms", SAVE_TIMEOUT_MS);
             }
             return request;
         }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
index e294c33..635af0c 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
@@ -39,7 +39,6 @@
 import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_USERNAME;
 import static android.text.InputType.TYPE_NULL;
 import static android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD;
-import static android.view.View.AUTOFILL_MODE_MANUAL;
 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
 import static android.view.autofill.AutofillManager.FLAG_MANUAL_REQUEST;
 
@@ -64,6 +63,7 @@
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeProvider;
 import android.view.autofill.AutofillManager;
+import android.widget.RemoteViews;
 
 import org.junit.After;
 import org.junit.Before;
@@ -1216,14 +1216,13 @@
         assertThat(usernameContainer.getChildCount()).isEqualTo(2);
     }
 
-    @Test
     public void testAutofillManuallyOneDataset() throws Exception {
         // Set service.
         enableService();
 
         // And activity.
         mActivity.onUsername((v) -> {
-            v.setAutofillMode(AUTOFILL_MODE_MANUAL);
+            // v.setAutofillMode(AUTOFILL_MODE_MANUAL);
             // TODO(b/33197203, b/33802548): setting an empty text, otherwise longPress() does not
             // display the AUTOFILL context menu. Need to fix it, but it's a test case issue...
             v.setText("");
@@ -1250,12 +1249,10 @@
         mActivity.assertAutoFilled();
     }
 
-    @Test
     public void testAutofillManuallyTwoDatasetsPickFirst() throws Exception {
         autofillManuallyTwoDatasets(true);
     }
 
-    @Test
     public void testAutofillManuallyTwoDatasetsPickSecond() throws Exception {
         autofillManuallyTwoDatasets(false);
     }
@@ -1266,7 +1263,7 @@
 
         // And activity.
         mActivity.onUsername((v) -> {
-            v.setAutofillMode(AUTOFILL_MODE_MANUAL);
+            //v.setAutofillMode(AUTOFILL_MODE_MANUAL);
             // TODO(b/33197203, b/33802548): setting an empty text, otherwise longPress() does not
             // display the AUTOFILL context menu. Need to fix it, but it's a test case issue...
             v.setText("");
@@ -1460,4 +1457,47 @@
             setUserRestrictionForAutofill(false);
         }
     }
+
+    @Test
+    public void testClickCustomButton() throws Exception {
+        // Set service.
+        enableService();
+
+        Intent intent = new Intent(getContext(), EmptyActivity.class);
+        IntentSender sender = PendingIntent.getActivity(getContext(), 0, intent,
+                PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_CANCEL_CURRENT)
+                .getIntentSender();
+
+        RemoteViews presentation = new RemoteViews(getContext().getPackageName(),
+                R.layout.list_item);
+        presentation.setTextViewText(R.id.text1, "Poke");
+        Intent firstIntent = new Intent(getContext(), DummyActivity.class);
+        presentation.setOnClickPendingIntent(R.id.text1, PendingIntent.getActivity(
+                getContext(), 0, firstIntent, PendingIntent.FLAG_ONE_SHOT
+                        | PendingIntent.FLAG_CANCEL_CURRENT));
+
+        // Set expectations.
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .setAuthentication(sender)
+                .setPresentation(presentation)
+                .build());
+
+        // Trigger auto-fill.
+        mActivity.onUsername(View::requestFocus);
+
+        // Wait for onFill() before proceeding.
+        sReplier.getNextFillRequest();
+
+        // Click on the custom button
+        sUiBot.selectByText("Poke");
+
+        // Make sure the click worked
+        sUiBot.selectByText("foo");
+
+        // Go back to the filled app.
+        sUiBot.pressBack();
+
+        // The session should be gone
+        assertNoDanglingSessions();
+    }
 }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/ManualAuthenticationActivity.java b/tests/autofillservice/src/android/autofillservice/cts/ManualAuthenticationActivity.java
index c2af4cc1..32844d4 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/ManualAuthenticationActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/ManualAuthenticationActivity.java
@@ -49,25 +49,24 @@
         setContentView(R.layout.single_button_activity);
 
         findViewById(R.id.button).setOnClickListener((v) -> {
-            // We should get the assist structure
             AssistStructure structure = getIntent().getParcelableExtra(
                     AutofillManager.EXTRA_ASSIST_STRUCTURE);
-            assertWithMessage("structure not called").that(structure).isNotNull();
+            if (structure != null) {
+                Parcelable result;
+                if (sResponse != null) {
+                    result = sResponse.asFillResponse(structure);
+                } else if (sDataset != null) {
+                    result = sDataset.asDataset(structure);
+                } else {
+                    throw new IllegalStateException("no dataset or response");
+                }
 
-            Parcelable result = null;
-            if (sResponse != null) {
-                result = sResponse.asFillResponse(structure);
-            } else if (sDataset != null) {
-                result = sDataset.asDataset(structure);
-            } else {
-                throw new IllegalStateException("no dataset or response");
+                // Pass on the auth result
+                Intent intent = new Intent();
+                intent.putExtra(AutofillManager.EXTRA_AUTHENTICATION_RESULT, result);
+                setResult(RESULT_OK, intent);
             }
 
-            // Pass on the auth result
-            Intent intent = new Intent();
-            intent.putExtra(AutofillManager.EXTRA_AUTHENTICATION_RESULT, result);
-            setResult(RESULT_OK, intent);
-
             // Done
             finish();
         });
diff --git a/tests/autofillservice/src/android/autofillservice/cts/MyAutofillCallback.java b/tests/autofillservice/src/android/autofillservice/cts/MyAutofillCallback.java
index 13887fa..48b0c2f 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/MyAutofillCallback.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/MyAutofillCallback.java
@@ -50,7 +50,7 @@
     MyEvent getEvent() throws InterruptedException {
         final MyEvent event = mEvents.poll(CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS);
         if (event == null) {
-            throw new AssertionError("no event in " + CONNECTION_TIMEOUT_MS + " ms");
+            throw new RetryableException("no event in %d ms", CONNECTION_TIMEOUT_MS);
         }
         return event;
     }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/RetryRule.java b/tests/autofillservice/src/android/autofillservice/cts/RetryRule.java
new file mode 100644
index 0000000..a4db0f4
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/RetryRule.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.autofillservice.cts;
+
+import android.util.Log;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+/**
+ * Custom JUnit4 rule that retry tests when they fail due to a {@link RetryableException}.
+ */
+public class RetryRule implements TestRule {
+
+    private static final String TAG = "RetryRule";
+    private final int mMaxAttempts;
+
+    public RetryRule(int maxAttempts) {
+        if (maxAttempts < 2) {
+            throw new IllegalArgumentException(
+                    "Must retry at least once; otherwise, what's the point?");
+        }
+        mMaxAttempts = maxAttempts;
+    }
+
+    @Override
+    public Statement apply(Statement base, Description description) {
+        return new Statement() {
+
+            @Override
+            public void evaluate() throws Throwable {
+                RetryableException caught = null;
+                for (int i = 1; i <= mMaxAttempts; i++) {
+                    try {
+                        base.evaluate();
+                        return;
+                    } catch (RetryableException e) {
+                        caught = e;
+                        Log.w(TAG,
+                                description.getDisplayName() + ": attempt " + i + " failed: " + e);
+                    }
+                }
+                throw caught;
+            }
+        };
+    }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/RetryRuleTest.java b/tests/autofillservice/src/android/autofillservice/cts/RetryRuleTest.java
new file mode 100644
index 0000000..50ae8c8
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/RetryRuleTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.autofillservice.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.Description;
+import org.junit.runner.RunWith;
+import org.junit.runners.model.Statement;
+
+@RunWith(AndroidJUnit4.class)
+public class RetryRuleTest {
+
+    private final Description mDescription = Description.createSuiteDescription("Whatever");
+
+    private static final RetryableException sRetryableException =
+            new RetryableException("Y U NO RETRY?");
+
+    private static class RetryableStatement extends Statement {
+        private final int mNumberFailures;
+        private int mNumberCalls;
+
+        RetryableStatement(int numberFailures) {
+            mNumberFailures = numberFailures;
+        }
+
+        @Override
+        public void evaluate() throws Throwable {
+            mNumberCalls ++;
+            if (mNumberCalls <= mNumberFailures) {
+                throw sRetryableException;
+            }
+        }
+
+        @Override
+        public String toString() {
+            return "RetryableStatement: failures=" + mNumberFailures + ", calls=" + mNumberCalls;
+        }
+    }
+
+    @Test
+    public void testPass() throws Throwable {
+        final RetryRule rule = new RetryRule(2);
+        rule.apply(new RetryableStatement(1), mDescription).evaluate();
+    }
+
+    @Test
+    public void testFail() throws Throwable {
+        final RetryRule rule = new RetryRule(2);
+        try {
+            rule.apply(new RetryableStatement(2), mDescription).evaluate();
+            throw new AssertionError("2ND CALL, Y U NO FAIL?");
+        } catch (RetryableException e) {
+            assertThat(e).isSameAs(sRetryableException);
+        }
+    }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/RetryableException.java b/tests/autofillservice/src/android/autofillservice/cts/RetryableException.java
new file mode 100644
index 0000000..9b9d651
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/RetryableException.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.autofillservice.cts;
+
+/**
+ * Exception that cause the {@link RetryRule} to re-try a test.
+ */
+public class RetryableException extends RuntimeException {
+
+    public RetryableException(String msg) {
+        super(msg);
+    }
+
+    public RetryableException(String format, Object...args) {
+        this(String.format(format, args));
+    }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
index 1f98171..deba8b7 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
@@ -92,7 +92,7 @@
             // not showing...
             return;
         }
-        throw new AssertionError("floating ui is shown: " + ui);
+        throw new RetryableException("floating ui is shown: %s", ui);
     }
 
     /**
@@ -202,6 +202,13 @@
     }
 
     /**
+     * Presses the back button.
+     */
+    void pressBack() {
+        mDevice.pressBack();
+    }
+
+    /**
      * Asserts the save snackbar is not showing and returns it.
      */
     void assertSaveNotShowing(int type) {
@@ -212,7 +219,7 @@
             // not showing (in which case it wouldn't need a type as parameter).
             return;
         }
-        throw new AssertionError("snack bar is showing");
+        throw new RetryableException("snack bar is showing");
     }
 
     private String getSaveTypeString(int type) {
@@ -328,7 +335,7 @@
             }
             menuNames.append("'").append(menuName).append("' ");
         }
-        throw new AssertionError("no '" + expectedText + "' on " + menuNames);
+        throw new RetryableException("no '%s' on '%s'", expectedText, menuNames);
     }
 
     /**
@@ -375,8 +382,8 @@
             }
             SystemClock.sleep(napTime);
         }
-        throw new AssertionError("Object with selector " + selector + " not found in "
-                + mTimeout + " ms");
+        throw new RetryableException("Object with selector '%s' not found in %d ms",
+                selector, mTimeout);
     }
 
     /**
@@ -405,9 +412,10 @@
             }
             SystemClock.sleep(napTime);
         }
-        throw new AssertionError("Objects with selector " + selector + " not found in "
-                + mTimeout + " ms");
+        throw new RetryableException("Objects with selector '%s' not found in %d ms",
+                selector, mTimeout);
     }
+
     private UiObject2 findDatasetPicker() {
         final UiObject2 picker = waitForObject(By.res("android", RESOURCE_ID_DATASET_PICKER));
 
@@ -429,6 +437,6 @@
                 return;
             }
         }
-        throw new AssertionError("Title (" + expectedTitle + ") not found for " + object);
+        throw new RetryableException("Title '%s' not found for %s", expectedTitle, object);
     }
 }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/ViewAttributesTest.java b/tests/autofillservice/src/android/autofillservice/cts/ViewAttributesTest.java
index 54b474e..763c57f 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/ViewAttributesTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/ViewAttributesTest.java
@@ -18,16 +18,9 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.testng.Assert.assertThrows;
-
-import android.autofillservice.cts.InstrumentedAutoFillService.FillRequest;
-import android.support.annotation.NonNull;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
 import android.view.View;
-import android.widget.EditText;
-import android.widget.LinearLayout;
-import android.widget.TextView;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -41,227 +34,10 @@
             new ActivityTestRule<>(ViewAttributesTestActivity.class);
 
     private ViewAttributesTestActivity mActivity;
-    private EditText mFirstLevelDefault;
-    private EditText mFirstLevelManual;
-    private EditText mFirstLevelAuto;
-    private EditText mFirstLevelInherit;
-    private EditText mManualContainerInherit;
-    private EditText mManualContainerDefault;
-    private EditText mManualContainerManual;
-    private EditText mManualContainerAuto;
-    private OneTimeTextWatcher mFirstLevelDefaultTextWatcher;
 
     @Before
     public void setActivity() {
         mActivity = mActivityRule.getActivity();
-        mFirstLevelDefault = (EditText) mActivity.findViewById(R.id.firstLevelDefault);
-        mFirstLevelManual = (EditText) mActivity.findViewById(R.id.firstLevelManual);
-        mFirstLevelAuto = (EditText) mActivity.findViewById(R.id.firstLevelAuto);
-        mFirstLevelInherit = (EditText) mActivity.findViewById(R.id.firstLevelInherit);
-        mManualContainerDefault = (EditText) mActivity.findViewById(R.id.manualContainerDefault);
-        mManualContainerManual = (EditText) mActivity.findViewById(R.id.manualContainerManual);
-        mManualContainerAuto = (EditText) mActivity.findViewById(R.id.manualContainerAuto);
-        mManualContainerInherit = (EditText) mActivity.findViewById(R.id.manualContainerInherit);
-    }
-
-    private void runOnUiThreadSync(@NonNull Runnable r) throws InterruptedException {
-        RuntimeException exceptionOnUiThread[] = {null};
-
-        synchronized (this) {
-            mActivity.runOnUiThread(() -> {
-                synchronized (this) {
-                    try {
-                        r.run();
-                    } catch (RuntimeException e) {
-                        exceptionOnUiThread[0] = e;
-                    }
-                    this.notify();
-                }
-            });
-
-            wait();
-        }
-
-        if (exceptionOnUiThread[0] != null) {
-            throw exceptionOnUiThread[0];
-        }
-    }
-
-    /**
-     * Sets the expectation for an auto-fill request, so it can be asserted through
-     * {@link #assertAutoFilled()} later.
-     */
-    void expectAutoFill() {
-        mFirstLevelDefaultTextWatcher = new OneTimeTextWatcher("firstLevelDefault",
-                mFirstLevelDefault, "filled");
-        mFirstLevelDefault.addTextChangedListener(mFirstLevelDefaultTextWatcher);
-    }
-
-    /**
-     * Asserts the activity was auto-filled with the values passed to
-     * {@link #expectAutoFill()}.
-     */
-    void assertAutoFilled() throws Exception {
-        mFirstLevelDefaultTextWatcher.assertAutoFilled();
-    }
-
-    /**
-     * Try to auto-fill by moving the focus to {@code field}. If the field should trigger an
-     * auto-fill the auto-fill UI should show up.
-     *
-     * @param field    The field to move the focus to
-     * @param expectUI If the auto-fill UI is expected to show up
-     *
-     * @throws Exception If something unexpected happened
-     */
-    private void checkFieldBehavior(@NonNull EditText field, boolean expectUI) throws Exception {
-        if (expectUI) {
-            assertThat(field.getResolvedAutofillMode()).isEqualTo(View.AUTOFILL_MODE_AUTO);
-        } else {
-            assertThat(field.getResolvedAutofillMode()).isEqualTo(View.AUTOFILL_MODE_MANUAL);
-        }
-
-        // Make sure the requestFocus triggers a change
-        if (field == mFirstLevelManual) {
-            runOnUiThreadSync(() -> mFirstLevelDefault.requestFocus());
-        } else {
-            runOnUiThreadSync(() -> mFirstLevelManual.requestFocus());
-        }
-
-        enableService();
-
-        try {
-            sReplier.addResponse(new CannedFillResponse.Builder()
-                    .addDataset(new CannedFillResponse.CannedDataset.Builder()
-                            .setField("firstLevelDefault", "filled")
-                            .setField("firstLevelManual", "filled")
-                            .setField("firstLevelAuto", "filled")
-                            .setField("firstLevelInherit", "filled")
-                            .setField("manualContainerDefault", "filled")
-                            .setField("manualContainerManual", "filled")
-                            .setField("manualContainerAuto", "filled")
-                            .setField("manualContainerInherit", "filled")
-                            .setPresentation(createPresentation("dataset"))
-                            .build())
-                    .build());
-
-            expectAutoFill();
-
-            runOnUiThreadSync(() -> field.requestFocus());
-
-            Throwable exceptionDuringAutoFillTrigger = null;
-            try {
-                sReplier.getNextFillRequest();
-                sUiBot.selectDataset("dataset");
-            } catch (Throwable e) {
-                if (expectUI) {
-                    throw e;
-                } else {
-                    exceptionDuringAutoFillTrigger = e;
-                }
-            }
-
-            if (expectUI) {
-                assertAutoFilled();
-            } else {
-                assertThat(exceptionDuringAutoFillTrigger).isNotNull();
-            }
-        } finally {
-            disableService();
-        }
-    }
-
-    @Test
-    public void checkDefaultValue() {
-        assertThat(mFirstLevelDefault.getAutofillMode()).isEqualTo(View.AUTOFILL_MODE_INHERIT);
-    }
-
-    @Test
-    public void checkInheritValue() {
-        assertThat(mFirstLevelInherit.getAutofillMode()).isEqualTo(View.AUTOFILL_MODE_INHERIT);
-    }
-
-    @Test
-    public void checkAutoValue() {
-        assertThat(mFirstLevelAuto.getAutofillMode()).isEqualTo(View.AUTOFILL_MODE_AUTO);
-    }
-
-    @Test
-    public void checkManualValue() {
-        assertThat(mFirstLevelManual.getAutofillMode()).isEqualTo(View.AUTOFILL_MODE_MANUAL);
-    }
-
-    @Test
-    public void checkNestedDefaultValue() {
-        assertThat(mManualContainerDefault.getAutofillMode()).isEqualTo(
-                View.AUTOFILL_MODE_INHERIT);
-    }
-
-    @Test
-    public void checkNestedInheritValue() {
-        assertThat(mManualContainerInherit.getAutofillMode()).isEqualTo(
-                View.AUTOFILL_MODE_INHERIT);
-    }
-
-    @Test
-    public void checkNestedAutoValue() {
-        assertThat(mManualContainerAuto.getAutofillMode()).isEqualTo(View.AUTOFILL_MODE_AUTO);
-    }
-
-    @Test
-    public void checkNestedManualValue() {
-        assertThat(mManualContainerManual.getAutofillMode()).isEqualTo(View.AUTOFILL_MODE_MANUAL);
-    }
-
-    @Test
-    public void checkDefaultBehavior() throws Exception {
-        checkFieldBehavior(mFirstLevelDefault, true);
-    }
-
-    @Test
-    public void checkInheritBehavior() throws Exception {
-        checkFieldBehavior(mFirstLevelInherit, true);
-    }
-
-    @Test
-    public void checkAutoBehavior() throws Exception {
-        checkFieldBehavior(mFirstLevelAuto, true);
-    }
-
-    @Test
-    public void checkManualBehavior() throws Exception {
-        checkFieldBehavior(mFirstLevelManual, false);
-    }
-
-    @Test
-    public void checkNestedDefaultBehavior() throws Exception {
-        checkFieldBehavior(mManualContainerDefault, false);
-    }
-
-    @Test
-    public void checkNestedInheritBehavior() throws Exception {
-        checkFieldBehavior(mManualContainerInherit, false);
-    }
-
-    @Test
-    public void checkNestedAutoBehavior() throws Exception {
-        checkFieldBehavior(mManualContainerAuto, true);
-    }
-
-    @Test
-    public void checkNestedManualBehavior() throws Exception {
-        checkFieldBehavior(mManualContainerManual, false);
-    }
-
-    @Test
-    public void checksetAutofillMode() {
-        mFirstLevelDefault.setAutofillMode(View.AUTOFILL_MODE_MANUAL);
-        assertThat(mFirstLevelDefault.getAutofillMode()).isEqualTo(View.AUTOFILL_MODE_MANUAL);
-    }
-
-    @Test
-    public void checkIllegalAutoFillModeSet() throws Exception {
-        assertThrows(IllegalArgumentException.class, () -> mFirstLevelDefault.setAutofillMode(-1));
     }
 
     @Test
@@ -317,85 +93,4 @@
         assertThat(v.getAutofillHints()).isEqualTo(new String[]{View.AUTOFILL_HINT_PASSWORD,
                 View.AUTOFILL_HINT_EMAIL_ADDRESS});
     }
-
-    @Test
-    public void attachViewToManualContainer() throws Exception {
-        runOnUiThreadSync(() -> mFirstLevelManual.requestFocus());
-        enableService();
-
-        try {
-            View view = new TextView(mActivity);
-
-            view.setLayoutParams(
-                    new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
-                            LinearLayout.LayoutParams.WRAP_CONTENT));
-
-            assertThat(view.getAutofillMode()).isEqualTo(View.AUTOFILL_MODE_INHERIT);
-            assertThat(view.getResolvedAutofillMode()).isEqualTo(View.AUTOFILL_MODE_AUTO);
-
-            // Requesting focus should not trigger any mishaps
-            runOnUiThreadSync(() -> view.requestFocus());
-
-            LinearLayout attachmentPoint = (LinearLayout) mActivity.findViewById(
-                    R.id.manualContainer);
-            runOnUiThreadSync(() -> attachmentPoint.addView(view));
-
-            assertThat(view.getResolvedAutofillMode()).isEqualTo(View.AUTOFILL_MODE_MANUAL);
-        } finally {
-            disableService();
-        }
-    }
-
-    @Test
-    public void attachNestedViewToContainer() throws Exception {
-        runOnUiThreadSync(() -> mFirstLevelManual.requestFocus());
-        enableService();
-
-        try {
-            // Create view and viewGroup but do not attach to window
-            LinearLayout container = (LinearLayout) mActivity.getLayoutInflater().inflate(
-                    R.layout.nested_layout, null);
-            EditText field = container.findViewById(R.id.field);
-
-            assertThat(field.getAutofillMode()).isEqualTo(View.AUTOFILL_MODE_INHERIT);
-            assertThat(container.getAutofillMode()).isEqualTo(View.AUTOFILL_MODE_INHERIT);
-
-            // Resolved mode for detached views should behave as documented
-            assertThat(field.getResolvedAutofillMode()).isEqualTo(View.AUTOFILL_MODE_AUTO);
-            assertThat(container.getResolvedAutofillMode()).isEqualTo(View.AUTOFILL_MODE_AUTO);
-
-            // Requesting focus should not trigger any mishaps
-            runOnUiThreadSync(() -> field.requestFocus());
-
-            // Set up auto-fill service and response
-            sReplier.addResponse(new CannedFillResponse.Builder()
-                    .addDataset(new CannedFillResponse.CannedDataset.Builder()
-                            .setField("field", "filled")
-                            .setPresentation(createPresentation("dataset"))
-                            .build())
-                    .build());
-
-            OneTimeTextWatcher mViewWatcher = new OneTimeTextWatcher("field", field, "filled");
-            field.addTextChangedListener(mViewWatcher);
-
-            // As the focus is set to "field", attaching "container" should trigger an auto-fill
-            // request on "field"
-            LinearLayout attachmentPoint = (LinearLayout) mActivity.findViewById(
-                    R.id.rootContainer);
-            runOnUiThreadSync(() -> attachmentPoint.addView(container));
-
-            // Now the resolved auto-fill modes make sense, hence check them
-            assertThat(field.getResolvedAutofillMode()).isEqualTo(View.AUTOFILL_MODE_AUTO);
-            assertThat(container.getResolvedAutofillMode()).isEqualTo(View.AUTOFILL_MODE_AUTO);
-
-            // We should now be able to select the data set
-            sReplier.getNextFillRequest();
-            sUiBot.selectDataset("dataset");
-
-            // Check if auto-fill operation worked
-            mViewWatcher.assertAutoFilled();
-        } finally {
-            disableService();
-        }
-    }
 }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java
index 6b97195..0344830 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java
@@ -127,7 +127,7 @@
         try {
             VirtualContainerView.assertHtmlInfo(username);
             VirtualContainerView.assertHtmlInfo(password);
-        } catch (AssertionError e) {
+        } catch (AssertionError | RuntimeException e) {
             dumpStructure("HtmlInfo failed", request.structure);
             throw e;
         }
diff --git a/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java b/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java
index 6ae3011..b51e338 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java
@@ -1649,10 +1649,6 @@
                     checkMeteringRect(afRegions);
                 }
             }
-            // ZSL must default to OFF
-            if (request.get(CONTROL_ENABLE_ZSL) != null) {
-                mCollector.expectKeyValueEquals(request, CONTROL_ENABLE_ZSL, false);
-            }
         }
 
         // Sensor settings.
@@ -1915,6 +1911,13 @@
             }
         }
 
+        // Enable ZSL
+        if (template != CameraDevice.TEMPLATE_STILL_CAPTURE) {
+            if (mStaticInfo.areKeysAvailable(CONTROL_ENABLE_ZSL)) {
+                    mCollector.expectKeyValueEquals(request, CONTROL_ENABLE_ZSL, false);
+            }
+        }
+
         int[] outputFormats = mStaticInfo.getAvailableFormats(
                 StaticMetadata.StreamDirection.Output);
         boolean supportRaw = false;
diff --git a/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java b/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
index 6c48418..e011131 100644
--- a/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
@@ -1262,7 +1262,11 @@
     private long getExposureValue(CaptureResult result) throws Exception {
         int expTimeUs = (int) (getValueNotNull(result, CaptureResult.SENSOR_EXPOSURE_TIME) / 1000);
         int sensitivity = getValueNotNull(result, CaptureResult.SENSOR_SENSITIVITY);
-        return expTimeUs * sensitivity;
+        Integer postRawSensitivity = result.get(CaptureResult.CONTROL_POST_RAW_SENSITIVITY_BOOST);
+        if (postRawSensitivity != null) {
+            return (long) sensitivity * postRawSensitivity / 100 * expTimeUs;
+        }
+        return (long) sensitivity * expTimeUs;
     }
 
     private long getMaxExposureValue(CaptureRequest.Builder request, long maxExposureTimeUs,
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index e4ca5af..655621c 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -296,5 +296,12 @@
     "android.telecom.cts.WiredHeadsetTest"
   ],
   bug: 26149528
+},
+{
+  desciption: "Seems to be failing on X86, flaky on arm. Root cause to be investigated",
+  names: [
+    "android.webkit.cts.WebViewClientTest#testOnRenderProcessGone"
+  ],
+  bug: 37281280
 }
 ]
diff --git a/tests/fragment/src/android/fragment/cts/FragmentAnimatorTest.java b/tests/fragment/src/android/fragment/cts/FragmentAnimatorTest.java
index b5e9cad..f234155 100644
--- a/tests/fragment/src/android/fragment/cts/FragmentAnimatorTest.java
+++ b/tests/fragment/src/android/fragment/cts/FragmentAnimatorTest.java
@@ -59,11 +59,8 @@
     public ActivityTestRule<FragmentTestActivity> mActivityRule =
             new ActivityTestRule<FragmentTestActivity>(FragmentTestActivity.class);
 
-    private Instrumentation mInstrumentation;
-
     @Before
     public void setupContainer() {
-        mInstrumentation = InstrumentationRegistry.getInstrumentation();
         FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container);
     }
 
@@ -365,12 +362,12 @@
                 .replace(R.id.fragmentContainer, fragment2, "2")
                 .addToBackStack(null)
                 .commit();
-        mInstrumentation.runOnMainSync(fm1::executePendingTransactions);
+        mActivityRule.runOnUiThread(fm1::executePendingTransactions);
         FragmentTestUtil.waitForExecution(mActivityRule);
 
         fm1.popBackStack();
 
-        mInstrumentation.runOnMainSync(fm1::executePendingTransactions);
+        mActivityRule.runOnUiThread(fm1::executePendingTransactions);
         FragmentTestUtil.waitForExecution(mActivityRule);
         // Now fragment2 should be animating away
         assertFalse(fragment2.isAdded());
diff --git a/tests/fragment/src/android/fragment/cts/FragmentExecuteTests.java b/tests/fragment/src/android/fragment/cts/FragmentExecuteTests.java
index 7d65b8c..6e6cda9 100644
--- a/tests/fragment/src/android/fragment/cts/FragmentExecuteTests.java
+++ b/tests/fragment/src/android/fragment/cts/FragmentExecuteTests.java
@@ -41,11 +41,8 @@
     public ActivityTestRule<FragmentTestActivity> mActivityRule =
             new ActivityTestRule<FragmentTestActivity>(FragmentTestActivity.class);
 
-    private Instrumentation mInstrumentation;
-
     @Before
     public void setupContentView() {
-        mInstrumentation = InstrumentationRegistry.getInstrumentation();
         FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container);
     }
 
@@ -58,7 +55,7 @@
         final FragmentManager fm = mActivityRule.getActivity().getFragmentManager();
         final StrictViewFragment fragment = new StrictViewFragment();
 
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 fm.beginTransaction()
diff --git a/tests/fragment/src/android/fragment/cts/FragmentOptimizationTest.java b/tests/fragment/src/android/fragment/cts/FragmentOptimizationTest.java
index f91eb65..bbd8d10 100644
--- a/tests/fragment/src/android/fragment/cts/FragmentOptimizationTest.java
+++ b/tests/fragment/src/android/fragment/cts/FragmentOptimizationTest.java
@@ -15,11 +15,11 @@
  */
 package android.fragment.cts;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 import android.app.FragmentManager;
-import android.app.Instrumentation;
-import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
@@ -39,14 +39,12 @@
 
     private ViewGroup mContainer;
     private FragmentManager mFM;
-    private Instrumentation mInstrumentation;
 
     @Before
     public void setup() {
         FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container);
         mContainer = (ViewGroup) mActivityRule.getActivity().findViewById(R.id.fragmentContainer);
         mFM = mActivityRule.getActivity().getFragmentManager();
-        mInstrumentation = InstrumentationRegistry.getInstrumentation();
     }
 
     // Test that when you add and replace a fragment that only the replace's add
@@ -55,7 +53,7 @@
     public void addReplace() throws Throwable {
         final CountCallsFragment fragment1 = new CountCallsFragment();
         final StrictViewFragment fragment2 = new StrictViewFragment();
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 mFM.beginTransaction().add(R.id.fragmentContainer, fragment1).addToBackStack(null).commit();
@@ -69,7 +67,7 @@
         assertEquals(0, fragment1.onCreateViewCount);
         FragmentTestUtil.assertChildren(mContainer, fragment2);
 
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 mFM.popBackStack();
@@ -92,7 +90,7 @@
         FragmentTestUtil.assertChildren(mContainer, fragment1);
 
         // Now pop and add
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 mFM.popBackStack();
@@ -116,7 +114,7 @@
     public void middlePop() throws Throwable {
         final CountCallsFragment fragment1 = new CountCallsFragment();
         final CountCallsFragment fragment2 = new CountCallsFragment();
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 mFM.beginTransaction()
@@ -146,7 +144,7 @@
     public void optimizeRemove() throws Throwable {
         final CountCallsFragment fragment1 = new CountCallsFragment();
         final int[] id = new int[1];
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 id[0] = mFM.beginTransaction()
@@ -186,7 +184,7 @@
         FragmentTestUtil.executePendingTransactions(mActivityRule);
         assertEquals(1, fragment1.onCreateViewCount);
 
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 mFM.beginTransaction()
@@ -224,7 +222,7 @@
         assertEquals(1, fragment1.onAttachCount);
         FragmentTestUtil.assertChildren(mContainer, fragment1);
 
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 mFM.beginTransaction().detach(fragment1).addToBackStack(null).commit();
@@ -274,7 +272,7 @@
         assertEquals(0, fragment1.onCreateViewCount);
         FragmentTestUtil.assertChildren(mContainer);
 
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 mFM.beginTransaction().attach(fragment1).addToBackStack(null).commit();
@@ -318,7 +316,7 @@
         assertEquals(1, fragment1.onHideCount);
         FragmentTestUtil.assertChildren(mContainer, fragment1);
 
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 mFM.beginTransaction()
@@ -353,7 +351,7 @@
         assertEquals(0, fragment1.onShowCount);
         assertEquals(1, fragment1.onHideCount);
 
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 mFM.beginTransaction().show(fragment1).addToBackStack(null).commit();
@@ -373,7 +371,7 @@
         assertEquals(0, fragment1.onShowCount);
         assertEquals(1, fragment1.onHideCount);
 
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 mFM.beginTransaction().show(fragment1).addToBackStack(null).commit();
@@ -408,7 +406,7 @@
         assertEquals(0, fragment1.onHideCount);
         FragmentTestUtil.assertChildren(mContainer, fragment1);
 
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 mFM.beginTransaction().hide(fragment1).addToBackStack(null).commit();
@@ -445,7 +443,7 @@
 
         final CountCallsFragment fragment2 = new CountCallsFragment();
 
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 mFM.beginTransaction()
@@ -470,7 +468,7 @@
     @Test
     public void addPopBackStack() throws Throwable {
         final CountCallsFragment fragment1 = new CountCallsFragment();
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 mFM.beginTransaction()
@@ -493,7 +491,7 @@
     public void popNonBackStack() throws Throwable {
         final CountCallsFragment fragment1 = new CountCallsFragment();
         final CountCallsFragment fragment2 = new CountCallsFragment();
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 mFM.beginTransaction()
@@ -519,7 +517,7 @@
     public void noOptimization() throws Throwable {
         final CountCallsFragment fragment1 = new CountCallsFragment();
         final CountCallsFragment fragment2 = new CountCallsFragment();
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 mFM.beginTransaction()
diff --git a/tests/fragment/src/android/fragment/cts/FragmentTestUtil.java b/tests/fragment/src/android/fragment/cts/FragmentTestUtil.java
index c175164..62c4906 100644
--- a/tests/fragment/src/android/fragment/cts/FragmentTestUtil.java
+++ b/tests/fragment/src/android/fragment/cts/FragmentTestUtil.java
@@ -23,10 +23,8 @@
 import android.app.FragmentController;
 import android.app.FragmentManager;
 import android.app.FragmentManagerNonConfig;
-import android.app.Instrumentation;
 import android.os.Looper;
 import android.os.Parcelable;
-import android.support.test.InstrumentationRegistry;
 import android.support.test.rule.ActivityTestRule;
 import android.util.Pair;
 import android.view.View;
@@ -42,9 +40,14 @@
         // the UI thread and then the execution will be added onto the queue after that.
         // The two-cycle wait makes sure fragments have the opportunity to complete both
         // before returning.
-        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
-        instrumentation.runOnMainSync(() -> {});
-        instrumentation.runOnMainSync(() -> {});
+        try {
+            rule.runOnUiThread(() -> {
+            });
+            rule.runOnUiThread(() -> {
+            });
+        } catch (Throwable t) {
+            throw new RuntimeException(t);
+        }
     }
 
     private static void runOnUiThreadRethrow(ActivityTestRule<? extends Activity> rule,
diff --git a/tests/fragment/src/android/fragment/cts/FragmentTransitionTest.java b/tests/fragment/src/android/fragment/cts/FragmentTransitionTest.java
index 43a9590..7421377 100644
--- a/tests/fragment/src/android/fragment/cts/FragmentTransitionTest.java
+++ b/tests/fragment/src/android/fragment/cts/FragmentTransitionTest.java
@@ -15,7 +15,8 @@
  */
 package android.fragment.cts;
 
-import static junit.framework.Assert.*;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.fail;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -23,22 +24,20 @@
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
 
-import com.android.compatibility.common.util.transition.TargetTracking;
-import com.android.compatibility.common.util.transition.TrackingTransition;
-
 import android.app.Fragment;
 import android.app.FragmentManager;
 import android.app.FragmentTransaction;
-import android.app.Instrumentation;
 import android.app.SharedElementCallback;
 import android.graphics.Rect;
 import android.os.Bundle;
-import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
 import android.support.test.rule.ActivityTestRule;
 import android.transition.TransitionSet;
 import android.view.View;
 
+import com.android.compatibility.common.util.transition.TargetTracking;
+import com.android.compatibility.common.util.transition.TrackingTransition;
+
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -68,7 +67,6 @@
     public ActivityTestRule<FragmentTestActivity> mActivityRule =
             new ActivityTestRule<FragmentTestActivity>(FragmentTestActivity.class);
 
-    private Instrumentation mInstrumentation;
     private FragmentManager mFragmentManager;
 
     public FragmentTransitionTest(final boolean optimize) {
@@ -77,7 +75,6 @@
 
     @Before
     public void setup() throws Throwable {
-        mInstrumentation = InstrumentationRegistry.getInstrumentation();
         mFragmentManager = mActivityRule.getActivity().getFragmentManager();
         FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container);
     }
@@ -163,7 +160,7 @@
         final TransitionFragment fragment2 = new TransitionFragment();
         fragment2.setLayoutId(R.layout.scene2);
 
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 mFragmentManager.beginTransaction()
@@ -966,7 +963,7 @@
         final View startRed = findRed();
         final Rect startSharedRect = getBoundsOnScreen(startBlue);
 
-        mInstrumentation.runOnMainSync(() -> {
+        mActivityRule.runOnUiThread(() -> {
             for (int i = 0; i < numPops; i++) {
                 mFragmentManager.popBackStack();
             }
diff --git a/tests/fragment/src/android/fragment/cts/FragmentViewTests.java b/tests/fragment/src/android/fragment/cts/FragmentViewTests.java
index 6f96811..e9c80e0 100644
--- a/tests/fragment/src/android/fragment/cts/FragmentViewTests.java
+++ b/tests/fragment/src/android/fragment/cts/FragmentViewTests.java
@@ -46,13 +46,6 @@
     public ActivityTestRule<FragmentTestActivity> mActivityRule =
             new ActivityTestRule<FragmentTestActivity>(FragmentTestActivity.class);
 
-    private Instrumentation mInstrumentation;
-
-    @Before
-    public void setupInstrumentation() {
-        mInstrumentation = InstrumentationRegistry.getInstrumentation();
-    }
-
     // Test that adding a fragment adds the Views in the proper order. Popping the back stack
     // should remove the correct Views.
     @Test
@@ -156,7 +149,7 @@
         fm.beginTransaction().add(R.id.fragmentContainer, fragment1).commit();
         FragmentTestUtil.executePendingTransactions(mActivityRule);
 
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 try {
@@ -917,7 +910,7 @@
 
         final StrictViewFragment fragment2 = new StrictViewFragment();
         final StrictViewFragment fragment3 = new StrictViewFragment();
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 fm.popBackStack();
diff --git a/tests/fragment/src/android/fragment/cts/PostponedTransitionTest.java b/tests/fragment/src/android/fragment/cts/PostponedTransitionTest.java
index a3c43aa..2b89bc2 100644
--- a/tests/fragment/src/android/fragment/cts/PostponedTransitionTest.java
+++ b/tests/fragment/src/android/fragment/cts/PostponedTransitionTest.java
@@ -26,10 +26,8 @@
 import android.app.FragmentController;
 import android.app.FragmentManager;
 import android.app.FragmentManagerNonConfig;
-import android.app.Instrumentation;
 import android.os.Bundle;
 import android.os.Parcelable;
-import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
@@ -50,12 +48,10 @@
     public ActivityTestRule<FragmentTestActivity> mActivityRule =
             new ActivityTestRule<FragmentTestActivity>(FragmentTestActivity.class);
 
-    private Instrumentation mInstrumentation;
     private PostponedFragment1 mBeginningFragment;
 
     @Before
     public void setupContainer() throws Throwable {
-        mInstrumentation = InstrumentationRegistry.getInstrumentation();
         FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container);
         final FragmentManager fm = mActivityRule.getActivity().getFragmentManager();
         mBeginningFragment = new PostponedFragment1();
@@ -119,7 +115,7 @@
         final int commit[] = new int[1];
         // Need to run this on the UI thread so that the transaction doesn't start
         // between the two
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 commit[0] = fm.beginTransaction()
@@ -489,7 +485,7 @@
         final TransitionFragment fragment4 = new PostponedFragment2();
         final StrictFragment strictFragment2 = new StrictFragment();
 
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 fm.beginTransaction()
@@ -539,7 +535,7 @@
 
         final View startBlue2 = fragment2.getView().findViewById(R.id.blueSquare);
 
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivityRule.runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 fm.beginTransaction()
@@ -664,7 +660,7 @@
         assertTrue(fragment2.isAdded());
         assertTrue(fragment2.getView().isAttachedToWindow());
 
-        mInstrumentation.runOnMainSync(() -> {
+        mActivityRule.runOnUiThread(() -> {
             assertTrue(fm2.popBackStackImmediate());
         });
 
diff --git a/tests/pdf/Android.mk b/tests/pdf/Android.mk
new file mode 100644
index 0000000..1e4a1ca
--- /dev/null
+++ b/tests/pdf/Android.mk
@@ -0,0 +1,44 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_MULTILIB := both
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_STATIC_JAVA_LIBRARIES += \
+    android-support-test \
+    mockito-target-minus-junit4 \
+    compatibility-device-util \
+    ctstestrunner \
+    android-support-annotations \
+    junit \
+    legacy-android-test
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_PACKAGE_NAME := CtsPdfTestCases
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
+
diff --git a/tests/pdf/AndroidManifest.xml b/tests/pdf/AndroidManifest.xml
new file mode 100644
index 0000000..495b5da
--- /dev/null
+++ b/tests/pdf/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.graphics.pdf.cts">
+
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="android.graphics.pdf.cts"
+                     android:label="CTS tests of android.graphics.pdf">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
+
+</manifest>
+
diff --git a/tests/pdf/AndroidTest.xml b/tests/pdf/AndroidTest.xml
new file mode 100644
index 0000000..e7c0794
--- /dev/null
+++ b/tests/pdf/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 Pdf test cases">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsPdfTestCases.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.graphics.pdf.cts" />
+        <option name="runtime-hint" value="5m" />
+    </test>
+</configuration>
diff --git a/tests/tests/graphics/res/raw/a4_portrait_rgbb.pdf b/tests/pdf/res/raw/a4_portrait_rgbb.pdf
similarity index 100%
rename from tests/tests/graphics/res/raw/a4_portrait_rgbb.pdf
rename to tests/pdf/res/raw/a4_portrait_rgbb.pdf
Binary files differ
diff --git a/tests/tests/graphics/res/raw/a5_portrait_rgbb.pdf b/tests/pdf/res/raw/a5_portrait_rgbb.pdf
similarity index 100%
rename from tests/tests/graphics/res/raw/a5_portrait_rgbb.pdf
rename to tests/pdf/res/raw/a5_portrait_rgbb.pdf
Binary files differ
diff --git a/tests/tests/graphics/res/raw/a5_portrait_rgbb_1_6_printscaling_default.pdf b/tests/pdf/res/raw/a5_portrait_rgbb_1_6_printscaling_default.pdf
similarity index 100%
rename from tests/tests/graphics/res/raw/a5_portrait_rgbb_1_6_printscaling_default.pdf
rename to tests/pdf/res/raw/a5_portrait_rgbb_1_6_printscaling_default.pdf
Binary files differ
diff --git a/tests/tests/graphics/res/raw/a5_portrait_rgbb_1_6_printscaling_none.pdf b/tests/pdf/res/raw/a5_portrait_rgbb_1_6_printscaling_none.pdf
similarity index 100%
rename from tests/tests/graphics/res/raw/a5_portrait_rgbb_1_6_printscaling_none.pdf
rename to tests/pdf/res/raw/a5_portrait_rgbb_1_6_printscaling_none.pdf
Binary files differ
diff --git a/tests/pdf/res/raw/testimage.jpg b/tests/pdf/res/raw/testimage.jpg
new file mode 100644
index 0000000..d3dae03
--- /dev/null
+++ b/tests/pdf/res/raw/testimage.jpg
Binary files differ
diff --git a/tests/tests/graphics/res/raw/two_pages.pdf b/tests/pdf/res/raw/two_pages.pdf
similarity index 100%
rename from tests/tests/graphics/res/raw/two_pages.pdf
rename to tests/pdf/res/raw/two_pages.pdf
Binary files differ
diff --git a/tests/tests/graphics/src/android/graphics/pdf/cts/PdfDocumentTest.java b/tests/pdf/src/android/graphics/pdf/cts/PdfDocumentTest.java
similarity index 100%
rename from tests/tests/graphics/src/android/graphics/pdf/cts/PdfDocumentTest.java
rename to tests/pdf/src/android/graphics/pdf/cts/PdfDocumentTest.java
diff --git a/tests/tests/graphics/src/android/graphics/pdf/cts/PdfRendererTest.java b/tests/pdf/src/android/graphics/pdf/cts/PdfRendererTest.java
similarity index 99%
rename from tests/tests/graphics/src/android/graphics/pdf/cts/PdfRendererTest.java
rename to tests/pdf/src/android/graphics/pdf/cts/PdfRendererTest.java
index 530ac1b..2f0158e 100644
--- a/tests/tests/graphics/src/android/graphics/pdf/cts/PdfRendererTest.java
+++ b/tests/pdf/src/android/graphics/pdf/cts/PdfRendererTest.java
@@ -34,7 +34,7 @@
 import android.graphics.Color;
 import android.graphics.Matrix;
 import android.graphics.Rect;
-import android.graphics.cts.R;
+import android.graphics.pdf.cts.R;
 import android.graphics.pdf.PdfRenderer;
 import android.graphics.pdf.PdfRenderer.Page;
 import android.os.ParcelFileDescriptor;
diff --git a/tests/tests/graphics/src/android/graphics/pdf/cts/PdfRendererTransformTest.java b/tests/pdf/src/android/graphics/pdf/cts/PdfRendererTransformTest.java
similarity index 100%
rename from tests/tests/graphics/src/android/graphics/pdf/cts/PdfRendererTransformTest.java
rename to tests/pdf/src/android/graphics/pdf/cts/PdfRendererTransformTest.java
diff --git a/tests/tests/graphics/src/android/graphics/pdf/cts/Utils.java b/tests/pdf/src/android/graphics/pdf/cts/Utils.java
similarity index 98%
rename from tests/tests/graphics/src/android/graphics/pdf/cts/Utils.java
rename to tests/pdf/src/android/graphics/pdf/cts/Utils.java
index 2e2de3e..4d43e09 100644
--- a/tests/tests/graphics/src/android/graphics/pdf/cts/Utils.java
+++ b/tests/pdf/src/android/graphics/pdf/cts/Utils.java
@@ -53,8 +53,8 @@
 
     static final int A4_WIDTH_PTS = 595;
     static final int A4_HEIGHT_PTS = 841;
-    static final int A4_PORTRAIT = android.graphics.cts.R.raw.a4_portrait_rgbb;
-    static final int A5_PORTRAIT = android.graphics.cts.R.raw.a5_portrait_rgbb;
+    static final int A4_PORTRAIT = android.graphics.pdf.cts.R.raw.a4_portrait_rgbb;
+    static final int A5_PORTRAIT = android.graphics.pdf.cts.R.raw.a5_portrait_rgbb;
 
     /**
      * Create a {@link PdfRenderer} pointing to a file copied from a resource.
diff --git a/tests/sensor/src/android/hardware/cts/SensorDirectReportTest.java b/tests/sensor/src/android/hardware/cts/SensorDirectReportTest.java
index 547f44c..8866a39 100644
--- a/tests/sensor/src/android/hardware/cts/SensorDirectReportTest.java
+++ b/tests/sensor/src/android/hardware/cts/SensorDirectReportTest.java
@@ -40,7 +40,6 @@
  *
  * This testcase tests operation of:
  *   - SensorManager.createDirectChannel()
- *   - SensorManager.configureDirectReport()
  *   - SensorDirectChannel.*
  *   - Sensor.getHighestDirectReportRateLevel()
  *   - Sensor.isDirectChannelTypeSupported()
@@ -89,7 +88,7 @@
     protected void setUp() throws Exception {
         mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
 
-        mNeedMemoryFile = isMemoryTypeNeeded(SensorDirectChannel.TYPE_ASHMEM);
+        mNeedMemoryFile = isMemoryTypeNeeded(SensorDirectChannel.TYPE_MEMORY_FILE);
         mNeedHardwareBuffer = isMemoryTypeNeeded(SensorDirectChannel.TYPE_HARDWARE_BUFFER);
 
         if (mNeedMemoryFile) {
@@ -129,28 +128,28 @@
     public void testAccelerometerAshmemNormal() {
         runSensorDirectReportTest(
                 Sensor.TYPE_ACCELEROMETER,
-                SensorDirectChannel.TYPE_ASHMEM,
+                SensorDirectChannel.TYPE_MEMORY_FILE,
                 SensorDirectChannel.RATE_NORMAL);
     }
 
     public void testGyroscopeAshmemNormal() {
         runSensorDirectReportTest(
                 Sensor.TYPE_GYROSCOPE,
-                SensorDirectChannel.TYPE_ASHMEM,
+                SensorDirectChannel.TYPE_MEMORY_FILE,
                 SensorDirectChannel.RATE_NORMAL);
     }
 
     public void testMagneticFieldAshmemNormal() {
         runSensorDirectReportTest(
                 Sensor.TYPE_MAGNETIC_FIELD,
-                SensorDirectChannel.TYPE_ASHMEM,
+                SensorDirectChannel.TYPE_MEMORY_FILE,
                 SensorDirectChannel.RATE_NORMAL);
     }
 
     public void testAccelerometerAshmemFast() {
         runSensorDirectReportTest(
                 Sensor.TYPE_ACCELEROMETER,
-                SensorDirectChannel.TYPE_ASHMEM,
+                SensorDirectChannel.TYPE_MEMORY_FILE,
                 SensorDirectChannel.RATE_FAST);
 
     }
@@ -158,21 +157,21 @@
     public void testGyroscopeAshmemFast() {
         runSensorDirectReportTest(
                 Sensor.TYPE_GYROSCOPE,
-                SensorDirectChannel.TYPE_ASHMEM,
+                SensorDirectChannel.TYPE_MEMORY_FILE,
                 SensorDirectChannel.RATE_FAST);
     }
 
     public void testMagneticFieldAshmemFast() {
         runSensorDirectReportTest(
                 Sensor.TYPE_MAGNETIC_FIELD,
-                SensorDirectChannel.TYPE_ASHMEM,
+                SensorDirectChannel.TYPE_MEMORY_FILE,
                 SensorDirectChannel.RATE_FAST);
     }
 
     public void testAccelerometerAshmemVeryFast() {
         runSensorDirectReportTest(
                 Sensor.TYPE_ACCELEROMETER,
-                SensorDirectChannel.TYPE_ASHMEM,
+                SensorDirectChannel.TYPE_MEMORY_FILE,
                 SensorDirectChannel.RATE_VERY_FAST);
 
     }
@@ -180,14 +179,14 @@
     public void testGyroscopeAshmemVeryFast() {
         runSensorDirectReportTest(
                 Sensor.TYPE_GYROSCOPE,
-                SensorDirectChannel.TYPE_ASHMEM,
+                SensorDirectChannel.TYPE_MEMORY_FILE,
                 SensorDirectChannel.RATE_VERY_FAST);
     }
 
     public void testMagneticFieldAshmemVeryFast() {
         runSensorDirectReportTest(
                 Sensor.TYPE_MAGNETIC_FIELD,
-                SensorDirectChannel.TYPE_ASHMEM,
+                SensorDirectChannel.TYPE_MEMORY_FILE,
                 SensorDirectChannel.RATE_VERY_FAST);
     }
 
@@ -263,39 +262,40 @@
             return;
         }
 
-        mChannel = null;
         try {
             switch(memType) {
-                case SensorDirectChannel.TYPE_ASHMEM:
+                case SensorDirectChannel.TYPE_MEMORY_FILE:
                     assertTrue("MemoryFile is null", mMemoryFile != null);
                     mChannel = mSensorManager.createDirectChannel(mMemoryFile);
-                    assertTrue("createDirectChannel(MemoryFile) failed", mChannel != null);
                     break;
                 case SensorDirectChannel.TYPE_HARDWARE_BUFFER:
                     assertTrue("HardwareBuffer is null", mHardwareBuffer != null);
                     mChannel = mSensorManager.createDirectChannel(mHardwareBuffer);
-                    assertTrue("createDirectChannel(HardwareBuffer) failed", mChannel != null);
                     break;
                 default:
                     Log.e(TAG, "Specified illegal memory type " + memType);
                     return;
             }
+        } catch (IllegalStateException e) {
+            mChannel = null;
+        }
+        assertTrue("createDirectChannel failed", mChannel != null);
+
+        try {
             assertTrue("Shared memory is not formatted", isSharedMemoryFormatted(memType));
             waitBeforeStartSensor();
 
-            int token = mSensorManager.configureDirectChannel(mChannel, s, rateLevel);
+            int token = mChannel.configure(s, rateLevel);
             assertTrue("configure direct mChannel failed", token > 0);
 
             waitSensorCollection();
 
             //stop sensor and analyze content
-            mSensorManager.configureDirectChannel(mChannel, s, SensorDirectChannel.RATE_STOP);
+            mChannel.configure(s, SensorDirectChannel.RATE_STOP);
             checkSharedMemoryContent(s, memType, rateLevel, token);
         } finally {
-            if (mChannel != null) {
-                mChannel.close();
-                mChannel = null;
-            }
+            mChannel.close();
+            mChannel = null;
         }
     }
 
@@ -348,7 +348,7 @@
     }
 
     private boolean isSharedMemoryFormatted(int memType) {
-        if (memType == SensorDirectChannel.TYPE_ASHMEM) {
+        if (memType == SensorDirectChannel.TYPE_MEMORY_FILE) {
             if (!readMemoryFileContent()) {
                 Log.e(TAG, "Read MemoryFile content fail");
                 return false;
@@ -369,7 +369,7 @@
     }
 
     private void checkSharedMemoryContent(Sensor s, int memType, int rateLevel, int token) {
-        if (memType == SensorDirectChannel.TYPE_ASHMEM) {
+        if (memType == SensorDirectChannel.TYPE_MEMORY_FILE) {
             assertTrue("read MemoryFile content failed", readMemoryFileContent());
         } else {
             assertTrue("read HardwareBuffer content failed", readHardwareBufferContent());
diff --git a/tests/signature/Android.mk b/tests/signature/Android.mk
index 6a8dcf9..8502c59 100644
--- a/tests/signature/Android.mk
+++ b/tests/signature/Android.mk
@@ -27,7 +27,9 @@
 
 LOCAL_SDK_VERSION := current
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner \
+    compatibility-device-util \
+    android-support-test
 
 include $(BUILD_CTS_PACKAGE)
 
diff --git a/tests/signature/AndroidManifest.xml b/tests/signature/AndroidManifest.xml
index 52090ce..41a4233 100644
--- a/tests/signature/AndroidManifest.xml
+++ b/tests/signature/AndroidManifest.xml
@@ -17,6 +17,7 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="android.signature.cts">
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
 
     <application>
@@ -27,4 +28,4 @@
                      android:targetPackage="android.signature.cts"
                      android:label="API Signature Test"/>
 
-</manifest>
\ No newline at end of file
+</manifest>
diff --git a/tests/signature/AndroidTest.xml b/tests/signature/AndroidTest.xml
index 038d0d0..6d23620 100644
--- a/tests/signature/AndroidTest.xml
+++ b/tests/signature/AndroidTest.xml
@@ -14,6 +14,11 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Signature test cases">
+   <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="device" />
+        <option name="config-filename" value="CtsSignatureTestCases" />
+        <option name="version" value="1.0" />
+    </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
         <option name="run-command" value="mkdir -p /data/local/tmp/signature-test-packages" />
         <option name='run-command'
diff --git a/tests/signature/DynamicConfig.xml b/tests/signature/DynamicConfig.xml
new file mode 100644
index 0000000..e078476
--- /dev/null
+++ b/tests/signature/DynamicConfig.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 Google Inc.
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<!--
+    Bug: 33305737 android.intent.action.ACTION_CARRIER_SETUP
+    Bug: 36980009 android.intent.action.QUICKBOOT_POWERON
+    Bug: 36977779 android.intent.action.MASTER_CLEAR
+-->
+<dynamicConfig>
+    <entry key ="intent_whitelist">
+      <value>android.intent.action.ACTION_CARRIER_SETUP</value>
+      <value>android.intent.action.QUICKBOOT_POWERON</value>
+    </entry>
+</dynamicConfig>
diff --git a/tests/signature/src/android/signature/cts/IntentTest.java b/tests/signature/src/android/signature/cts/IntentTest.java
index c0d3e84..3d674ab 100644
--- a/tests/signature/src/android/signature/cts/IntentTest.java
+++ b/tests/signature/src/android/signature/cts/IntentTest.java
@@ -57,6 +57,8 @@
 import android.support.test.runner.AndroidJUnit4;
 import android.util.Log;
 
+import com.android.compatibility.common.util.DynamicConfigDeviceSide;
+
 import java.io.BufferedReader;
 import java.io.InputStreamReader;
 import java.io.IOException;
@@ -90,19 +92,21 @@
             new File("/data/local/tmp/signature-test-packages");
     private static final String ANDROID_INTENT_PREFIX = "android.intent.action";
     private static final String ACTION_LINE_PREFIX = "          Action: ";
-    private static final Set<String> INTENT_WHITELIST = getIntentWhitelist();
+    private static final String MODULE_NAME = "CtsSignatureTestCases";
 
     private PackageManager mPackageManager;
+    private Set<String> intentWhitelist;
 
     @Before
-    public void setupPackageManager() {
+    public void setupPackageManager() throws Exception {
       mPackageManager = InstrumentationRegistry.getContext().getPackageManager();
+      intentWhitelist = getIntentWhitelist();
     }
 
     @Test
     public void shouldNotFindUnexpectedIntents() throws Exception {
         Set<String> platformIntents = lookupPlatformIntents();
-        platformIntents.addAll(INTENT_WHITELIST);
+        platformIntents.addAll(intentWhitelist);
 
         Set<String> allInvalidIntents = new HashSet<>();
 
@@ -268,9 +272,18 @@
         }
     }
 
-    private static Set<String> getIntentWhitelist() {
+    private static Set<String> getIntentWhitelist() throws Exception {
         Set<String> whitelist = new HashSet<>();
 
+        DynamicConfigDeviceSide dcds = new DynamicConfigDeviceSide(MODULE_NAME);
+        List<String> intentWhitelist = dcds.getValues("intent_whitelist");
+
+        // Log the whitelist Intent
+        for (String intent : intentWhitelist) {
+           Log.d(TAG, String.format("whitelist add: %s", intent));
+           whitelist.add(intent);
+        }
+
         return whitelist;
     }
 }
diff --git a/tests/tests/bluetooth/Android.mk b/tests/tests/bluetooth/Android.mk
index d980e37..c02b23d 100644
--- a/tests/tests/bluetooth/Android.mk
+++ b/tests/tests/bluetooth/Android.mk
@@ -25,6 +25,7 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_JAVA_LIBRARIES += android.test.runner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeScanTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeScanTest.java
index fd1c7d2..066de74 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeScanTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeScanTest.java
@@ -28,6 +28,7 @@
 import android.content.pm.PackageManager;
 import android.os.ParcelUuid;
 import android.os.SystemClock;
+import android.support.test.InstrumentationRegistry;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.MediumTest;
 import android.util.Log;
@@ -85,6 +86,9 @@
         if (!mLocationOn) {
             TestUtils.enableLocation(getContext());
         }
+        InstrumentationRegistry.getInstrumentation().getUiAutomation().executeShellCommand(
+                "pm grant android.bluetooth.cts android.permission.ACCESS_COARSE_LOCATION"
+        );
     }
 
     @Override
diff --git a/tests/tests/content/src/android/content/cts/ContentResolverTest.java b/tests/tests/content/src/android/content/cts/ContentResolverTest.java
index 0ceda3a..e5e8fe4 100644
--- a/tests/tests/content/src/android/content/cts/ContentResolverTest.java
+++ b/tests/tests/content/src/android/content/cts/ContentResolverTest.java
@@ -24,7 +24,6 @@
 import android.content.res.AssetFileDescriptor;
 import android.database.ContentObserver;
 import android.database.Cursor;
-import android.database.PageViewCursor;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.CancellationSignal;
@@ -35,6 +34,7 @@
 import android.util.Log;
 
 import com.android.compatibility.common.util.PollingCheck;
+import com.android.internal.util.ArrayUtils;
 
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -419,41 +419,10 @@
     }
 
     /**
-     * Verifies that paging arguments are handled correctly
-     * when the provider supports paging.
+     * Verifies that paging information is correctly relayed, and that
+     * honored arguments from a supporting client are returned correctly.
      */
-    public void testQuery_InProcessProvider_NoAutoPaging() {
-
-        mContentResolver.delete(TABLE1_URI, null, null);
-        ContentValues values = new ContentValues();
-
-        for (int i = 0; i < 100; i++) {
-            values.put(COLUMN_KEY_NAME, i);
-            mContentResolver.insert(TABLE1_URI, values);
-        }
-
-        Bundle queryArgs = new Bundle();
-        queryArgs.putInt(ContentResolver.QUERY_ARG_OFFSET, 10);
-        queryArgs.putInt(ContentResolver.QUERY_ARG_LIMIT, 3);
-
-        mCursor = mContentResolver.query(TABLE1_URI, null, queryArgs, null);
-        int col = mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME);
-
-        Bundle extras = mCursor.getExtras();
-        extras = extras != null ? extras : Bundle.EMPTY;
-
-        assertEquals(100, mCursor.getCount());
-        assertFalse(extras.containsKey(PageViewCursor.EXTRA_AUTO_PAGED));
-        assertFalse(extras.containsKey(ContentResolver.EXTRA_TOTAL_SIZE));
-
-        mCursor.close();
-    }
-
-    /**
-     * Verifies that paging arguments are handled correctly
-     * when the provider supports paging.
-     */
-    public void testQuery_OutOfProcessProvider_AutoPaging() {
+    public void testQuery_PagedResults() {
 
         Bundle queryArgs = new Bundle();
         queryArgs.putInt(ContentResolver.QUERY_ARG_OFFSET, 10);
@@ -461,88 +430,30 @@
         queryArgs.putInt(TestPagingContentProvider.RECORDSET_SIZE, 100);
 
         mCursor = mContentResolver.query(
-                TestPagingContentProvider.UNPAGED_DATA_URI, null, queryArgs, null);
-
-        Bundle extras = mCursor.getExtras();
-        extras = extras != null ? extras : Bundle.EMPTY;
-
-        assertEquals(3, mCursor.getCount());
-        assertTrue(extras.getBoolean(PageViewCursor.EXTRA_AUTO_PAGED));
-        assertTrue(extras.containsKey(ContentResolver.EXTRA_TOTAL_SIZE));
-        assertEquals(100, extras.getInt(ContentResolver.EXTRA_TOTAL_SIZE));
-
-        int col = mCursor.getColumnIndexOrThrow(TestPagingContentProvider.COLUMN_POS);
-
-        mCursor.moveToNext();
-        assertEquals(10, mCursor.getInt(col));
-        mCursor.moveToNext();
-        assertEquals(11, mCursor.getInt(col));
-        mCursor.moveToNext();
-        assertEquals(12, mCursor.getInt(col));
-
-        assertFalse(mCursor.moveToNext());
-
-        mCursor.close();
-    }
-
-    /**
-     * Verifies that paging arguments are handled correctly
-     * when the provider supports paging.
-     */
-    public void testQuery_OutOfProcessProvider_AutoPaging_OffsetOutOfBounds() {
-
-        Bundle queryArgs = new Bundle();
-        queryArgs.putInt(ContentResolver.QUERY_ARG_OFFSET, 10);
-        queryArgs.putInt(ContentResolver.QUERY_ARG_LIMIT, 3);
-        queryArgs.putInt(TestPagingContentProvider.RECORDSET_SIZE, 100);
-
-        mCursor = mContentResolver.query(
-                TestPagingContentProvider.UNPAGED_DATA_URI, null, queryArgs, null);
-
-        Bundle extras = mCursor.getExtras();
-        extras = extras != null ? extras : Bundle.EMPTY;
-
-        assertEquals(3, mCursor.getCount());
-        assertTrue(extras.getBoolean(PageViewCursor.EXTRA_AUTO_PAGED));
-        assertTrue(extras.containsKey(ContentResolver.EXTRA_TOTAL_SIZE));
-        assertEquals(100, extras.getInt(ContentResolver.EXTRA_TOTAL_SIZE));
-
-        int col = mCursor.getColumnIndexOrThrow(TestPagingContentProvider.COLUMN_POS);
-
-        mCursor.moveToNext();
-        assertEquals(10, mCursor.getInt(col));
-        mCursor.moveToNext();
-        assertEquals(11, mCursor.getInt(col));
-        mCursor.moveToNext();
-        assertEquals(12, mCursor.getInt(col));
-
-        assertFalse(mCursor.moveToNext());
-
-        mCursor.close();
-    }
-
-    /**
-     * Verifies that auto-paging isn't applied when the underlying remote
-     * provider has already applied paging.
-     */
-    public void testQuery_OutOfProcessProvider_NoAutoPagingForAlreadyPagedResults() {
-
-        Bundle queryArgs = new Bundle();
-        queryArgs.putInt(ContentResolver.QUERY_ARG_OFFSET, 20);
-        queryArgs.putInt(ContentResolver.QUERY_ARG_LIMIT, 2);
-        queryArgs.putInt(TestPagingContentProvider.RECORDSET_SIZE, 500);
-
-        mCursor = mContentResolver.query(
                 TestPagingContentProvider.PAGED_DATA_URI, null, queryArgs, null);
 
         Bundle extras = mCursor.getExtras();
         extras = extras != null ? extras : Bundle.EMPTY;
 
-        assertFalse(extras.getBoolean(PageViewCursor.EXTRA_AUTO_PAGED));
+        assertEquals(3, mCursor.getCount());
+        assertTrue(extras.containsKey(ContentResolver.EXTRA_TOTAL_SIZE));
+        assertEquals(100, extras.getInt(ContentResolver.EXTRA_TOTAL_SIZE));
 
-        // we don't test the contents of the self-paged cursor
-        // because that's provided by TestPagingContentProvider
-        // a test-only test support class.
+        String[] honoredArgs = extras.getStringArray(ContentResolver.EXTRA_HONORED_ARGS);
+        assertNotNull(honoredArgs);
+        assertTrue(ArrayUtils.contains(honoredArgs, ContentResolver.QUERY_ARG_OFFSET));
+        assertTrue(ArrayUtils.contains(honoredArgs, ContentResolver.QUERY_ARG_LIMIT));
+
+        int col = mCursor.getColumnIndexOrThrow(TestPagingContentProvider.COLUMN_POS);
+
+        mCursor.moveToNext();
+        assertEquals(10, mCursor.getInt(col));
+        mCursor.moveToNext();
+        assertEquals(11, mCursor.getInt(col));
+        mCursor.moveToNext();
+        assertEquals(12, mCursor.getInt(col));
+
+        assertFalse(mCursor.moveToNext());
 
         mCursor.close();
     }
diff --git a/tests/tests/dpi/AndroidManifest.xml b/tests/tests/dpi/AndroidManifest.xml
index 118050e..8b02670 100644
--- a/tests/tests/dpi/AndroidManifest.xml
+++ b/tests/tests/dpi/AndroidManifest.xml
@@ -18,6 +18,9 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="android.dpi.cts">
 
+    <uses-sdk
+        android:minSdkVersion="23"
+        android:targetSdkVersion="23" />
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
     <application>
         <uses-library android:name="android.test.runner" />
diff --git a/tests/tests/graphics/assets/red-adobergb.png b/tests/tests/graphics/assets/red-adobergb.png
new file mode 100644
index 0000000..adbff91
--- /dev/null
+++ b/tests/tests/graphics/assets/red-adobergb.png
Binary files differ
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapColorSpaceTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapColorSpaceTest.java
index 5012e1c..8fc7a3b 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapColorSpaceTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapColorSpaceTest.java
@@ -38,6 +38,7 @@
 import java.util.Arrays;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
@@ -520,6 +521,22 @@
     }
 
     @Test
+    public void guessAdobeRGB() {
+        BitmapFactory.Options opts = new BitmapFactory.Options();
+        opts.inJustDecodeBounds = true;
+
+        try (InputStream in = mResources.getAssets().open("red-adobergb.png")) {
+            Bitmap b = BitmapFactory.decodeStream(in, null, opts);
+            ColorSpace cs = opts.outColorSpace;
+            assertNull(b);
+            assertNotNull(cs);
+            assertSame(ColorSpace.get(ColorSpace.Named.ADOBE_RGB), cs);
+        } catch (IOException e) {
+            fail();
+        }
+    }
+
+    @Test
     public void guessUnknown() {
         BitmapFactory.Options opts = new BitmapFactory.Options();
         opts.inJustDecodeBounds = true;
@@ -552,6 +569,99 @@
     }
 
     @Test
+    public void inColorSpaceP3ToSRGB() {
+        BitmapFactory.Options opts = new BitmapFactory.Options();
+        opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.SRGB);
+
+        try (InputStream in = mResources.getAssets().open("green-p3.png")) {
+            Bitmap b = BitmapFactory.decodeStream(in, null, opts);
+            ColorSpace cs = b.getColorSpace();
+            assertNotNull(cs);
+            assertSame(ColorSpace.get(ColorSpace.Named.SRGB), cs);
+            assertEquals(opts.inPreferredColorSpace, opts.outColorSpace);
+
+            verifyGetPixel(b, 0x3ff00ff, 0xff00ff00);
+        } catch (IOException e) {
+            fail();
+        }
+    }
+
+    @Test
+    public void inColorSpaceSRGBToP3() {
+        BitmapFactory.Options opts = new BitmapFactory.Options();
+        opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.DISPLAY_P3);
+
+        try (InputStream in = mResources.getAssets().open("green-srgb.png")) {
+            Bitmap b = BitmapFactory.decodeStream(in, null, opts);
+            ColorSpace cs = b.getColorSpace();
+            assertNotNull(cs);
+            assertSame(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), cs);
+            assertEquals(opts.inPreferredColorSpace, opts.outColorSpace);
+
+            verifyGetPixel(b, 0x75fb4cff, 0xff00ff00);
+        } catch (IOException e) {
+            fail();
+        }
+    }
+
+    @Test
+    public void inColorSpaceRGBA16F() {
+        BitmapFactory.Options opts = new BitmapFactory.Options();
+        opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.ADOBE_RGB);
+
+        try (InputStream in = mResources.getAssets().open("prophoto-rgba16f.png")) {
+            Bitmap b = BitmapFactory.decodeStream(in, null, opts);
+            ColorSpace cs = b.getColorSpace();
+            assertNotNull(cs);
+            assertSame(ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB), cs);
+            assertNotEquals(opts.inPreferredColorSpace, opts.outColorSpace);
+        } catch (IOException e) {
+            fail();
+        }
+    }
+
+    @Test
+    public void inColorSpace565() {
+        BitmapFactory.Options opts = new BitmapFactory.Options();
+        opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.ADOBE_RGB);
+        opts.inPreferredConfig = Bitmap.Config.RGB_565;
+
+        try (InputStream in = mResources.getAssets().open("green-p3.png")) {
+            Bitmap b = BitmapFactory.decodeStream(in, null, opts);
+            ColorSpace cs = b.getColorSpace();
+            assertNotNull(cs);
+            assertSame(ColorSpace.get(ColorSpace.Named.SRGB), cs);
+            assertNotEquals(opts.inPreferredColorSpace, opts.outColorSpace);
+        } catch (IOException e) {
+            fail();
+        }
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void inColorSpaceNotRGB() {
+        BitmapFactory.Options opts = new BitmapFactory.Options();
+        opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.CIE_LAB);
+
+        try (InputStream in = mResources.getAssets().open("green-p3.png")) {
+            BitmapFactory.decodeStream(in, null, opts);
+        } catch (IOException e) {
+            fail();
+        }
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void inColorSpaceNoTransferParameters() {
+        BitmapFactory.Options opts = new BitmapFactory.Options();
+        opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB);
+
+        try (InputStream in = mResources.getAssets().open("green-p3.png")) {
+            BitmapFactory.decodeStream(in, null, opts);
+        } catch (IOException e) {
+            fail();
+        }
+    }
+
+    @Test
     public void copy() {
         Bitmap b = BitmapFactory.decodeResource(mResources, R.drawable.robot);
         Bitmap c = b.copy(Bitmap.Config.ARGB_8888, false);
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapRegionDecoderTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapRegionDecoderTest.java
index 04b4aba..aea201c 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapRegionDecoderTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapRegionDecoderTest.java
@@ -31,9 +31,11 @@
 import android.graphics.BitmapRegionDecoder;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.ColorSpace;
 import android.graphics.Rect;
 import android.os.ParcelFileDescriptor;
 import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
@@ -63,9 +65,33 @@
             R.drawable.gif_test, R.drawable.bmp_test
     };
     private static final String[] NAMES_TEMP_FILES = new String[] {
-        "baseline_temp.jpg", "progressive_temp.jpg", "baseline_restart_temp.jpg",
-        "progressive_restart_temp.jpg", "png_temp.png", "webp_temp.webp",
-        "gif_temp.gif", "bmp_temp.bmp"
+            "baseline_temp.jpg", "progressive_temp.jpg", "baseline_restart_temp.jpg",
+            "progressive_restart_temp.jpg", "png_temp.png", "webp_temp.webp",
+            "gif_temp.gif", "bmp_temp.bmp"
+    };
+
+    // Do not change the order!
+    private static final String[] ASSET_NAMES = {
+            "prophoto-rgba16f.png",
+            "green-p3.png",
+            "red-adobergb.png",
+            "green-srgb.png",
+    };
+    private static final ColorSpace.Named[][] ASSET_COLOR_SPACES = {
+            // ARGB8888
+            {
+                    ColorSpace.Named.LINEAR_EXTENDED_SRGB,
+                    ColorSpace.Named.DISPLAY_P3,
+                    ColorSpace.Named.ADOBE_RGB,
+                    ColorSpace.Named.SRGB
+            },
+            // RGB565
+            {
+                    ColorSpace.Named.SRGB,
+                    ColorSpace.Named.SRGB,
+                    ColorSpace.Named.SRGB,
+                    ColorSpace.Named.SRGB
+            }
     };
 
     // The width and height of the above image.
@@ -78,6 +104,7 @@
     private static final int NUM_TEST_IMAGES = 6;
 
     private static final int TILE_SIZE = 256;
+    private static final int SMALL_TILE_SIZE = 16;
 
     // Configurations for BitmapFactory.Options
     private static final Config[] COLOR_CONFIGS = new Config[] {Config.ARGB_8888,
@@ -171,6 +198,7 @@
         }
     }
 
+    @LargeTest
     @Test
     public void testDecodeRegionInputStream() throws IOException {
         Options opts = new BitmapFactory.Options();
@@ -197,6 +225,7 @@
         }
     }
 
+    @LargeTest
     @Test
     public void testDecodeRegionInputStreamInBitmap() throws IOException {
         Options opts = new BitmapFactory.Options();
@@ -228,6 +257,7 @@
         }
     }
 
+    @LargeTest
     @Test
     public void testDecodeRegionByteArray() throws IOException {
         Options opts = new BitmapFactory.Options();
@@ -255,6 +285,7 @@
         }
     }
 
+    @LargeTest
     @Test
     public void testDecodeRegionStringAndFileDescriptor() throws IOException {
         Options opts = new BitmapFactory.Options();
@@ -327,6 +358,7 @@
     //     (2) The width, height, and Config of inBitmap are never changed.
     //     (3) All of the pixels decoded into inBitmap exactly match the pixels
     //         of a decode where inBitmap is NULL.
+    @LargeTest
     @Test
     public void testInBitmapReuse() throws IOException {
         Options defaultOpts = new BitmapFactory.Options();
@@ -409,6 +441,145 @@
         assertEquals(Config.HARDWARE, hardwareBitmap.getConfig());
     }
 
+    @Test
+    public void testOutColorType() throws IOException {
+        Options opts = new BitmapFactory.Options();
+        for (int i = 0; i < NUM_TEST_IMAGES; ++i) {
+            for (int j = 0; j < SAMPLESIZES.length; ++j) {
+                for (int k = 0; k < COLOR_CONFIGS.length; ++k) {
+                    opts.inSampleSize = SAMPLESIZES[j];
+                    opts.inPreferredConfig = COLOR_CONFIGS[k];
+
+                    InputStream is1 = obtainInputStream(RES_IDS[i]);
+                    BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is1, false);
+                    Bitmap region = decoder.decodeRegion(
+                            new Rect(0, 0, TILE_SIZE, TILE_SIZE), opts);
+                    decoder.recycle();
+
+                    assertSame(opts.inPreferredConfig, opts.outConfig);
+                    assertSame(opts.outConfig, region.getConfig());
+                    region.recycle();
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testOutColorSpace() throws IOException {
+        Options opts = new BitmapFactory.Options();
+        for (int i = 0; i < ASSET_NAMES.length; i++) {
+            for (int j = 0; j < SAMPLESIZES.length; ++j) {
+                for (int k = 0; k < COLOR_CONFIGS.length; ++k) {
+                    opts.inPreferredConfig = COLOR_CONFIGS[k];
+
+                    String assetName = ASSET_NAMES[i];
+                    InputStream is1 = obtainInputStream(assetName);
+                    BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is1, false);
+                    Bitmap region = decoder.decodeRegion(
+                            new Rect(0, 0, SMALL_TILE_SIZE, SMALL_TILE_SIZE), opts);
+                    decoder.recycle();
+
+                    ColorSpace expected = ColorSpace.get(ASSET_COLOR_SPACES[k][i]);
+                    assertSame(expected, opts.outColorSpace);
+                    assertSame(expected, region.getColorSpace());
+                    region.recycle();
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testReusedColorSpace() throws IOException {
+        Bitmap b = Bitmap.createBitmap(SMALL_TILE_SIZE, SMALL_TILE_SIZE, Config.ARGB_8888,
+                false, ColorSpace.get(ColorSpace.Named.ADOBE_RGB));
+
+        Options opts = new BitmapFactory.Options();
+        opts.inBitmap = b;
+
+        // sRGB
+        BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(
+                obtainInputStream(ASSET_NAMES[3]), false);
+        Bitmap region = decoder.decodeRegion(
+                new Rect(0, 0, SMALL_TILE_SIZE, SMALL_TILE_SIZE), opts);
+        decoder.recycle();
+
+        assertEquals(ColorSpace.get(ColorSpace.Named.SRGB), region.getColorSpace());
+
+        // DisplayP3
+        decoder = BitmapRegionDecoder.newInstance(obtainInputStream(ASSET_NAMES[1]), false);
+        region = decoder.decodeRegion(new Rect(0, 0, SMALL_TILE_SIZE, SMALL_TILE_SIZE), opts);
+        decoder.recycle();
+
+        assertEquals(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), region.getColorSpace());
+    }
+
+    @Test
+    public void testInColorSpace() throws IOException {
+        Options opts = new BitmapFactory.Options();
+        for (int i = 0; i < NUM_TEST_IMAGES; ++i) {
+            for (int j = 0; j < SAMPLESIZES.length; ++j) {
+                opts.inSampleSize = SAMPLESIZES[j];
+                opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.DISPLAY_P3);
+
+                InputStream is1 = obtainInputStream(RES_IDS[i]);
+                BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is1, false);
+                Bitmap region = decoder.decodeRegion(new Rect(0, 0, TILE_SIZE, TILE_SIZE), opts);
+                decoder.recycle();
+
+                assertSame(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), opts.outColorSpace);
+                assertSame(opts.outColorSpace, region.getColorSpace());
+                region.recycle();
+            }
+        }
+    }
+
+    @Test
+    public void testInColorSpaceRGBA16F() throws IOException {
+        Options opts = new BitmapFactory.Options();
+        opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.ADOBE_RGB);
+
+        InputStream is1 = obtainInputStream(ASSET_NAMES[0]); // ProPhoto 16 bit
+        BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is1, false);
+        Bitmap region = decoder.decodeRegion(new Rect(0, 0, SMALL_TILE_SIZE, SMALL_TILE_SIZE), opts);
+        decoder.recycle();
+
+        assertSame(ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB), region.getColorSpace());
+        region.recycle();
+    }
+
+    @Test
+    public void testInColorSpace565() throws IOException {
+        Options opts = new BitmapFactory.Options();
+        opts.inPreferredConfig = Config.RGB_565;
+        opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.ADOBE_RGB);
+
+        InputStream is1 = obtainInputStream(ASSET_NAMES[1]); // Display P3
+        BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is1, false);
+        Bitmap region = decoder.decodeRegion(new Rect(0, 0, SMALL_TILE_SIZE, SMALL_TILE_SIZE), opts);
+        decoder.recycle();
+
+        assertSame(ColorSpace.get(ColorSpace.Named.SRGB), region.getColorSpace());
+        region.recycle();
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testInColorSpaceNotRgb() throws IOException {
+        Options opts = new BitmapFactory.Options();
+        opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.CIE_LAB);
+        InputStream is1 = obtainInputStream(RES_IDS[0]);
+        BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is1, false);
+        Bitmap region = decoder.decodeRegion(new Rect(0, 0, TILE_SIZE, TILE_SIZE), opts);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testInColorSpaceNoTransferParameters() throws IOException {
+        Options opts = new BitmapFactory.Options();
+        opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB);
+        InputStream is1 = obtainInputStream(RES_IDS[0]);
+        BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is1, false);
+        Bitmap region = decoder.decodeRegion(new Rect(0, 0, TILE_SIZE, TILE_SIZE), opts);
+    }
+
     private void compareRegionByRegion(BitmapRegionDecoder decoder,
             Options opts, int mseMargin, Bitmap wholeImage) {
         int width = decoder.getWidth();
@@ -459,6 +630,10 @@
         return mRes.openRawResource(resId);
     }
 
+    private InputStream obtainInputStream(String assetName) throws IOException {
+        return mRes.getAssets().open(assetName);
+    }
+
     private byte[] obtainByteArray(int resId) throws IOException {
         InputStream is = obtainInputStream(resId);
         ByteArrayOutputStream os = new ByteArrayOutputStream();
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapShaderTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapShaderTest.java
index 1cc81bf..0b4f29f 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapShaderTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapShaderTest.java
@@ -161,35 +161,4 @@
         Assert.assertArrayEquals(new int[] { Color.RED, Color.BLUE, Color.BLUE, Color.RED },
                 pixels);
     }
-
-    @Test
-    public void testSetTileMode() {
-        Bitmap bitmap = Bitmap.createBitmap(2, 1, Config.ARGB_8888);
-        bitmap.setPixel(0, 0, Color.RED);
-        bitmap.setPixel(1, 0, Color.BLUE);
-        Bitmap dstBitmap = Bitmap.createBitmap(4, 1, Config.ARGB_8888);
-        Canvas canvas = new Canvas(dstBitmap);
-        Paint paint = new Paint();
-        int[] pixels = new int[4];
-
-
-        // use clamp, verify
-        BitmapShader shader = new BitmapShader(bitmap,
-                Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
-        paint.setShader(shader);
-        canvas.drawRect(0, 0, 4, 1, paint);
-
-        dstBitmap.getPixels(pixels, 0, 4, 0, 0, 4, 1);
-        Assert.assertArrayEquals(new int[] { Color.RED, Color.BLUE, Color.BLUE, Color.BLUE },
-                pixels);
-
-        // set to use mirror, verify
-        // Note: we don't need to re-apply shader on paint, it's picked up automatically.
-        shader.set(bitmap, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR);
-        canvas.drawRect(0, 0, 4, 1, paint);
-
-        dstBitmap.getPixels(pixels, 0, 4, 0, 0, 4, 1);
-        Assert.assertArrayEquals(new int[] { Color.RED, Color.BLUE, Color.BLUE, Color.RED },
-                pixels);
-    }
 }
diff --git a/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java b/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
index 69dbcd8..a113afa 100644
--- a/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
@@ -1112,6 +1112,19 @@
     }
 
     @Test
+    public void testClipInversePath() {
+        final Path p = new Path();
+        p.addRoundRect(new RectF(0, 0, 10, 10), 0.5f, 0.5f, Direction.CW);
+        p.setFillType(Path.FillType.INVERSE_WINDING);
+        assertTrue(mCanvas.clipPath(p, Op.INTERSECT));
+
+        mCanvas.drawColor(PAINT_COLOR);
+
+        assertEquals(Color.TRANSPARENT, mMutableBitmap.getPixel(0, 0));
+        assertEquals(PAINT_COLOR, mMutableBitmap.getPixel(0, 20));
+    }
+
+    @Test
     public void testGetDrawFilter() {
         assertNull(mCanvas.getDrawFilter());
         final DrawFilter dF = new DrawFilter();
diff --git a/tests/tests/graphics/src/android/graphics/cts/ColorMatrixColorFilterTest.java b/tests/tests/graphics/src/android/graphics/cts/ColorMatrixColorFilterTest.java
index f8714ee..61d46b2 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ColorMatrixColorFilterTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ColorMatrixColorFilterTest.java
@@ -15,7 +15,6 @@
  */
 package android.graphics.cts;
 
-import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 
 import android.graphics.Bitmap;
@@ -98,55 +97,5 @@
         canvas.drawPoint(0, 0, paint);
         ColorUtils.verifyColor(Color.BLUE, bitmap.getPixel(0, 0));
     }
-
-    @Test
-    public void testGetSetMatrix() {
-        ColorMatrixColorFilter filter = new ColorMatrixColorFilter(new ColorMatrix());
-        ColorMatrix getMatrix = new ColorMatrix();
-        filter.getColorMatrix(getMatrix);
-        assertEquals(new ColorMatrix(), getMatrix);
-
-        ColorMatrix scaleTranslate = new ColorMatrix(new float[] {
-                2, 0, 0, 0, 5,
-                0, 2, 0, 0, 5,
-                0, 0, 2, 0, 5,
-                0, 0, 0, 2, 5
-        });
-
-        filter.setColorMatrix(scaleTranslate);
-
-        filter.getColorMatrix(getMatrix);
-        assertEquals(scaleTranslate, getMatrix);
-        assertArrayEquals(scaleTranslate.getArray(), getMatrix.getArray(), 0);
-
-        filter.setColorMatrixArray(null);
-        filter.getColorMatrix(getMatrix);
-        assertEquals(new ColorMatrix(), getMatrix);
-    }
-
-    @Test
-    public void testSetMatrixDraw() {
-        ColorMatrixColorFilter filter = new ColorMatrixColorFilter(new ColorMatrix(new float[] {
-                2, 0, 0, 0, 5,
-                0, 2, 0, 0, 5,
-                0, 0, 2, 0, 5,
-                0, 0, 0, 1, 0
-        }));
-
-        Bitmap bitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
-        Canvas canvas = new Canvas(bitmap);
-        Paint paint = new Paint();
-        paint.setColorFilter(filter);
-
-
-        paint.setColor(0xFF101010);
-        canvas.drawPaint(paint);
-        ColorUtils.verifyColor(0xFF252525, bitmap.getPixel(0, 0));
-
-
-        filter.setColorMatrix(null);
-        canvas.drawPaint(paint);
-        ColorUtils.verifyColor(0xFF101010, bitmap.getPixel(0, 0));
-    }
 }
 
diff --git a/tests/tests/graphics/src/android/graphics/cts/Color_ColorLongTest.java b/tests/tests/graphics/src/android/graphics/cts/Color_ColorLongTest.java
index 2e76b85..f7893c7 100644
--- a/tests/tests/graphics/src/android/graphics/cts/Color_ColorLongTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/Color_ColorLongTest.java
@@ -84,6 +84,11 @@
         assertEquals(p3, colorSpace(pack(0.5f, 0.7f, 1.0f, 1.0f, p3)));
     }
 
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidColorSpace() {
+        colorSpace(0xffffffffffffffffL);
+    }
+
     @Test
     public void testIsSrgb() {
         ColorSpace p3 = ColorSpace.get(Named.DISPLAY_P3);
diff --git a/tests/tests/graphics/src/android/graphics/cts/ComposeShaderTest.java b/tests/tests/graphics/src/android/graphics/cts/ComposeShaderTest.java
index 2a83f32..8c8911e 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ComposeShaderTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ComposeShaderTest.java
@@ -101,72 +101,6 @@
     }
 
     @Test
-    public void testSet() {
-        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 redShader = new BitmapShader(redBitmap, TileMode.CLAMP, TileMode.CLAMP);
-        BitmapShader cyanShader = new BitmapShader(cyanBitmap, TileMode.CLAMP, TileMode.CLAMP);
-
-        PorterDuffXfermode xferMode = new PorterDuffXfermode(PorterDuff.Mode.ADD);
-
-        ComposeShader shader = new ComposeShader(redShader, cyanShader, xferMode);
-
-        Bitmap bitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
-        Canvas canvas = new Canvas(bitmap);
-        Paint paint = new Paint();
-        paint.setShader(shader);
-        canvas.drawPaint(paint);
-
-        // red + cyan = white
-        assertEquals(Color.WHITE, bitmap.getPixel(0, 0));
-
-        // set to be multiply mode, and immediately redraw
-        shader.set(redShader, cyanShader, PorterDuff.Mode.MULTIPLY);
-        canvas.drawPaint(paint);
-
-        // red * cyan = black
-        assertEquals(Color.BLACK, bitmap.getPixel(0, 0));
-    }
-
-    @Test
-    public void testInnerShaderMutate() {
-        // verify that calling a setter on a child shader updates this shader
-        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);
-        Bitmap greenBitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
-        greenBitmap.eraseColor(Color.GREEN);
-
-        BitmapShader redShader = new BitmapShader(redBitmap, TileMode.CLAMP, TileMode.CLAMP);
-        BitmapShader cyanShader = new BitmapShader(cyanBitmap, TileMode.CLAMP, TileMode.CLAMP);
-
-        ComposeShader shader = new ComposeShader(redShader, cyanShader, PorterDuff.Mode.ADD);
-
-
-        Bitmap bitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
-        Canvas canvas = new Canvas(bitmap);
-        Paint paint = new Paint();
-        paint.setShader(shader);
-        canvas.drawPaint(paint);
-
-        // red + cyan = white
-        assertEquals(Color.WHITE, bitmap.getPixel(0, 0));
-
-        // update one of the child shaders to point at a different bitmap
-        cyanShader.set(greenBitmap, TileMode.CLAMP, TileMode.CLAMP);
-
-        // and verify the change is picked up immediately by next paint
-        canvas.drawPaint(paint);
-
-        // red + green = yellow
-        assertEquals(Color.YELLOW, bitmap.getPixel(0, 0));
-    }
-
-    @Test
     public void testChildLocalMatrix() {
         Matrix translate1x1 = new Matrix();
         translate1x1.setTranslate(1, 1);
diff --git a/tests/tests/graphics/src/android/graphics/cts/FontVariationAxisTest.java b/tests/tests/graphics/src/android/graphics/cts/FontVariationAxisTest.java
index 929cd96..8aeefba 100644
--- a/tests/tests/graphics/src/android/graphics/cts/FontVariationAxisTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/FontVariationAxisTest.java
@@ -37,19 +37,18 @@
 
     @Test
     public void testConstruction() throws FontVariationAxis.InvalidFormatException {
-        new FontVariationAxis("abcd", 1.0f);
-        new FontVariationAxis("    ", 0.0f);
-        new FontVariationAxis("A X ", -1.0f);
+        new FontVariationAxis("wght", 1.0f);
+        new FontVariationAxis("PRIV", -1.0f);
     }
 
     @Test
     public void testGetterTest() throws FontVariationAxis.InvalidFormatException {
-        FontVariationAxis axis = new FontVariationAxis("abcd", 1.0f);
-        assertEquals("abcd", axis.getTag());
+        FontVariationAxis axis = new FontVariationAxis("wght", 1.0f);
+        assertEquals("wght", axis.getTag());
         assertEquals(1.0f, axis.getStyleValue(), FLOT_EQUALITY_PREC);
 
-        axis = new FontVariationAxis("    ", -1.0f);
-        assertEquals("    ", axis.getTag());
+        axis = new FontVariationAxis("PRIV", -1.0f);
+        assertEquals("PRIV", axis.getTag());
         assertEquals(-1.0f, axis.getStyleValue(), FLOT_EQUALITY_PREC);
     }
 
@@ -94,36 +93,36 @@
         assertEquals("wdth", axes[0].getTag());
         assertEquals(0.5f, axes[0].getStyleValue(), FLOT_EQUALITY_PREC);
 
-        axes = FontVariationAxis.fromFontVariationSettings("'AX  ' 1");
+        axes = FontVariationAxis.fromFontVariationSettings("'PRIV' 1");
         assertEquals(1, axes.length);
-        assertEquals("AX  ", axes[0].getTag());
+        assertEquals("PRIV", axes[0].getTag());
         assertEquals(1.0f, axes[0].getStyleValue(), FLOT_EQUALITY_PREC);
 
-        axes = FontVariationAxis.fromFontVariationSettings("'AX  '\t1");
+        axes = FontVariationAxis.fromFontVariationSettings("'PRIV'\t1");
         assertEquals(1, axes.length);
-        assertEquals("AX  ", axes[0].getTag());
+        assertEquals("PRIV", axes[0].getTag());
         assertEquals(1.0f, axes[0].getStyleValue(), FLOT_EQUALITY_PREC);
 
-        axes = FontVariationAxis.fromFontVariationSettings("'AX  '\n1");
+        axes = FontVariationAxis.fromFontVariationSettings("'PRIV'\n1");
         assertEquals(1, axes.length);
-        assertEquals("AX  ", axes[0].getTag());
+        assertEquals("PRIV", axes[0].getTag());
         assertEquals(1.0f, axes[0].getStyleValue(), FLOT_EQUALITY_PREC);
 
-        axes = FontVariationAxis.fromFontVariationSettings("'AX  '\r1");
+        axes = FontVariationAxis.fromFontVariationSettings("'PRIV'\r1");
         assertEquals(1, axes.length);
-        assertEquals("AX  ", axes[0].getTag());
+        assertEquals("PRIV", axes[0].getTag());
         assertEquals(1.0f, axes[0].getStyleValue(), FLOT_EQUALITY_PREC);
 
-        axes = FontVariationAxis.fromFontVariationSettings("'AX  '\r\t\n 1");
+        axes = FontVariationAxis.fromFontVariationSettings("'PRIV'\r\t\n 1");
         assertEquals(1, axes.length);
-        assertEquals("AX  ", axes[0].getTag());
+        assertEquals("PRIV", axes[0].getTag());
         assertEquals(1.0f, axes[0].getStyleValue(), FLOT_EQUALITY_PREC);
 
-        axes = FontVariationAxis.fromFontVariationSettings("'wdth' 10,'AX  '\r1");
+        axes = FontVariationAxis.fromFontVariationSettings("'wdth' 10,'PRIV'\r1");
         assertEquals(2, axes.length);
         assertEquals("wdth", axes[0].getTag());
         assertEquals(10.0f, axes[0].getStyleValue(), FLOT_EQUALITY_PREC);
-        assertEquals("AX  ", axes[1].getTag());
+        assertEquals("PRIV", axes[1].getTag());
         assertEquals(1.0f, axes[1].getStyleValue(), FLOT_EQUALITY_PREC);
     }
 
@@ -155,8 +154,7 @@
 
         final FontVariationAxis[] axes = {
             new FontVariationAxis("wght", 1.0f),
-            new FontVariationAxis("    ", 2.0f),
-            new FontVariationAxis("AX  ", 3.0f)
+            new FontVariationAxis("PRIV", 3.0f)
         };
 
         String stringData = FontVariationAxis.toFontVariationSettings(axes);
diff --git a/tests/tests/graphics/src/android/graphics/cts/LightingColorFilterTest.java b/tests/tests/graphics/src/android/graphics/cts/LightingColorFilterTest.java
index e4ba072..da2b934 100644
--- a/tests/tests/graphics/src/android/graphics/cts/LightingColorFilterTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/LightingColorFilterTest.java
@@ -16,8 +16,6 @@
 
 package android.graphics.cts;
 
-import static org.junit.Assert.assertEquals;
-
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.Config;
 import android.graphics.Canvas;
@@ -91,51 +89,4 @@
     private void verifyColor(int expected, int actual) {
         ColorUtils.verifyColor(expected, actual, TOLERANCE);
     }
-
-    @Test
-    public void testGetSet() {
-        LightingColorFilter filter = new LightingColorFilter(Color.WHITE, Color.BLACK);
-        assertEquals(Color.WHITE, filter.getColorMultiply());
-        assertEquals(Color.BLACK, filter.getColorAdd());
-
-        filter.setColorMultiply(Color.RED);
-        filter.setColorAdd(Color.BLUE);
-
-        assertEquals(Color.RED, filter.getColorMultiply());
-        assertEquals(Color.BLUE, filter.getColorAdd());
-    }
-
-    @Test
-    public void testSetDraw() {
-        LightingColorFilter filter = new LightingColorFilter(Color.CYAN, Color.BLACK);
-
-        Bitmap bitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
-        Canvas canvas = new Canvas(bitmap);
-        Paint paint = new Paint();
-        paint.setColorFilter(filter);
-
-        // test initial state
-        paint.setColor(Color.YELLOW);
-        canvas.drawPaint(paint);
-        // Cyan * yellow = green
-        ColorUtils.verifyColor(Color.GREEN, bitmap.getPixel(0, 0));
-
-
-        // test set color multiply
-        filter.setColorMultiply(Color.MAGENTA);
-        paint.setColor(Color.YELLOW);
-        canvas.drawPaint(paint);
-        // Magenta * yellow = red
-        ColorUtils.verifyColor(Color.RED, bitmap.getPixel(0, 0));
-
-
-        // test set color add
-        filter.setColorMultiply(Color.WHITE);
-        filter.setColorAdd(Color.MAGENTA);
-        paint.setColor(Color.GREEN);
-        canvas.drawPaint(paint);
-        // Magenta + green = white
-        ColorUtils.verifyColor(Color.WHITE, bitmap.getPixel(0, 0));
-
-    }
 }
diff --git a/tests/tests/graphics/src/android/graphics/cts/LinearGradientTest.java b/tests/tests/graphics/src/android/graphics/cts/LinearGradientTest.java
index 8555193..185e6a1 100644
--- a/tests/tests/graphics/src/android/graphics/cts/LinearGradientTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/LinearGradientTest.java
@@ -84,35 +84,6 @@
     }
 
     @Test
-    public void testSet() {
-        // only using 2 pixel wide gradient since we don't care about interpolation here.
-        // Note: we align start/end to be center pixel so colors at those pixels are exact.
-        LinearGradient gradient = new LinearGradient(0.5f, 0, 1.5f, 0,
-                Color.RED, Color.BLUE, TileMode.CLAMP);
-
-        Bitmap bitmap = Bitmap.createBitmap(3, 1, Config.ARGB_8888);
-        Canvas canvas = new Canvas(bitmap);
-
-        Paint paint = new Paint();
-        paint.setShader(gradient);
-        canvas.drawPaint(paint);
-
-
-        // red, blue, clamped to blue
-        ColorUtils.verifyColor(Color.RED, bitmap.getPixel(0, 0), 5);
-        ColorUtils.verifyColor(Color.BLUE, bitmap.getPixel(1, 0), 5);
-        ColorUtils.verifyColor(Color.BLUE, bitmap.getPixel(2, 0), 5);
-
-        gradient.set(0.5f, 0, 1.5f, 0, Color.GREEN, Color.WHITE, TileMode.MIRROR);
-        canvas.drawPaint(paint);
-
-        // green, white, mirrored to green
-        ColorUtils.verifyColor(Color.GREEN, bitmap.getPixel(0, 0), 5);
-        ColorUtils.verifyColor(Color.WHITE, bitmap.getPixel(1, 0), 5);
-        ColorUtils.verifyColor(Color.GREEN, bitmap.getPixel(2, 0), 5);
-    }
-
-    @Test
     public void testZeroScaleMatrix() {
         LinearGradient gradient = new LinearGradient(0.5f, 0, 1.5f, 0,
                 Color.RED, Color.BLUE, TileMode.CLAMP);
diff --git a/tests/tests/graphics/src/android/graphics/cts/MovieTest.java b/tests/tests/graphics/src/android/graphics/cts/MovieTest.java
index f5c7aa3..22fa7c3 100644
--- a/tests/tests/graphics/src/android/graphics/cts/MovieTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/MovieTest.java
@@ -28,7 +28,7 @@
 import android.graphics.Movie;
 import android.graphics.Paint;
 import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
+import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
 import com.android.compatibility.common.util.WidgetTestUtils;
@@ -44,7 +44,7 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 
-@MediumTest
+@SmallTest
 @RunWith(AndroidJUnit4.class)
 public class MovieTest {
     private final int MOVIE = R.drawable.animated;
diff --git a/tests/tests/graphics/src/android/graphics/cts/PorterDuffColorFilterTest.java b/tests/tests/graphics/src/android/graphics/cts/PorterDuffColorFilterTest.java
index a2438ee..0beadae 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PorterDuffColorFilterTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PorterDuffColorFilterTest.java
@@ -27,8 +27,6 @@
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
-import com.android.compatibility.common.util.ColorUtils;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -83,52 +81,4 @@
         assertEquals(Color.CYAN, target.getPixel(width / 4, height * 3 / 4));
         assertEquals(Color.CYAN, target.getPixel(width * 3 / 4, height * 3 / 4));
     }
-
-    @Test
-    public void testGetSet() {
-        PorterDuffColorFilter filter = new PorterDuffColorFilter(
-                Color.RED, PorterDuff.Mode.MULTIPLY);
-
-        assertEquals(Color.RED, filter.getColor());
-        assertEquals(PorterDuff.Mode.MULTIPLY, filter.getMode());
-
-        filter.setColor(Color.GREEN);
-        filter.setMode(PorterDuff.Mode.ADD);
-
-        assertEquals(Color.GREEN, filter.getColor());
-        assertEquals(PorterDuff.Mode.ADD, filter.getMode());
-    }
-
-    @Test
-    public void testSetDraw() {
-        PorterDuffColorFilter filter = new PorterDuffColorFilter(
-                Color.CYAN, PorterDuff.Mode.MULTIPLY);
-
-        Bitmap bitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
-        Canvas canvas = new Canvas(bitmap);
-        Paint paint = new Paint();
-        paint.setColorFilter(filter);
-
-        // test initial state
-        paint.setColor(Color.YELLOW);
-        canvas.drawPaint(paint);
-        // Cyan * yellow = green
-        ColorUtils.verifyColor(Color.GREEN, bitmap.getPixel(0, 0));
-
-
-        // test set color
-        filter.setColor(Color.MAGENTA);
-        paint.setColor(Color.YELLOW);
-        canvas.drawPaint(paint);
-        // Magenta * yellow = red
-        ColorUtils.verifyColor(Color.RED, bitmap.getPixel(0, 0));
-
-
-        // test set mode
-        filter.setMode(PorterDuff.Mode.ADD);
-        paint.setColor(Color.GREEN);
-        canvas.drawPaint(paint);
-        // Magenta + green = white
-        ColorUtils.verifyColor(Color.WHITE, bitmap.getPixel(0, 0));
-    }
 }
diff --git a/tests/tests/graphics/src/android/graphics/cts/RadialGradientTest.java b/tests/tests/graphics/src/android/graphics/cts/RadialGradientTest.java
index e8a0cbc..d133bb9 100644
--- a/tests/tests/graphics/src/android/graphics/cts/RadialGradientTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/RadialGradientTest.java
@@ -35,34 +35,6 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class RadialGradientTest {
-    @Test
-    public void testSet() {
-        // only using 1 pixel radius gradient since we don't care about interpolation here.
-        // Note: we align start/end to be center pixel so colors at those pixels are exact.
-        RadialGradient gradient = new RadialGradient(0.5f, 0.5f, 1,
-                Color.RED, Color.BLUE, TileMode.CLAMP);
-
-        Bitmap bitmap = Bitmap.createBitmap(3, 1, Config.ARGB_8888);
-        Canvas canvas = new Canvas(bitmap);
-
-        Paint paint = new Paint();
-        paint.setShader(gradient);
-        canvas.drawPaint(paint);
-
-
-        // red, blue, clamped to blue
-        ColorUtils.verifyColor(Color.RED, bitmap.getPixel(0, 0), 5);
-        ColorUtils.verifyColor(Color.BLUE, bitmap.getPixel(1, 0), 5);
-        ColorUtils.verifyColor(Color.BLUE, bitmap.getPixel(2, 0), 5);
-
-        gradient.set(0.5f, 0.5f, 1, Color.GREEN, Color.WHITE, TileMode.MIRROR);
-        canvas.drawPaint(paint);
-
-        // green, white, mirrored to green
-        ColorUtils.verifyColor(Color.GREEN, bitmap.getPixel(0, 0), 5);
-        ColorUtils.verifyColor(Color.WHITE, bitmap.getPixel(1, 0), 5);
-        ColorUtils.verifyColor(Color.GREEN, bitmap.getPixel(2, 0), 5);
-    }
 
     @Test
     public void testZeroScaleMatrix() {
diff --git a/tests/tests/graphics/src/android/graphics/cts/SweepGradientTest.java b/tests/tests/graphics/src/android/graphics/cts/SweepGradientTest.java
index ceea7a7..cb7ec0a 100644
--- a/tests/tests/graphics/src/android/graphics/cts/SweepGradientTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/SweepGradientTest.java
@@ -22,7 +22,6 @@
 import android.graphics.Bitmap.Config;
 import android.graphics.Canvas;
 import android.graphics.Color;
-import android.graphics.LinearGradient;
 import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.Rect;
@@ -148,33 +147,6 @@
     }
 
     @Test
-    public void testSet() {
-        // Only use two pixel wide bitmap since we don't care about interpolation here.
-        // Note: we place the gradient in between the two pixels, so both are solid colors.
-        SweepGradient gradient = new SweepGradient(1, 0.5f,
-                new int[] {Color.BLUE, Color.RED, Color.BLUE}, null);
-
-        Bitmap bitmap = Bitmap.createBitmap(2, 1, Config.ARGB_8888);
-        Canvas canvas = new Canvas(bitmap);
-
-        Paint paint = new Paint();
-        paint.setShader(gradient);
-        canvas.drawPaint(paint);
-
-        // red to left, blue to right
-        ColorUtils.verifyColor(Color.RED, bitmap.getPixel(0, 0), 5);
-        ColorUtils.verifyColor(Color.BLUE, bitmap.getPixel(1, 0), 5);
-
-        gradient.set(1, 0.5f,
-                new int[] {Color.GREEN, Color.YELLOW, Color.GREEN}, null);
-        canvas.drawPaint(paint);
-
-        // yellow to left, green to right
-        ColorUtils.verifyColor(Color.YELLOW, bitmap.getPixel(0, 0), 5);
-        ColorUtils.verifyColor(Color.GREEN, bitmap.getPixel(1, 0), 5);
-    }
-
-    @Test
     public void testZeroScaleMatrix() {
         SweepGradient gradient = new SweepGradient(1, 0.5f,
                 new int[] {Color.BLUE, Color.RED, Color.BLUE}, null);
diff --git a/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java b/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
index b0adf26..3a1c1cf 100644
--- a/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
@@ -21,11 +21,13 @@
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import android.content.Context;
+import android.content.res.AssetManager;
 import android.graphics.Paint;
 import android.graphics.Typeface;
 import android.graphics.fonts.FontVariationAxis;
@@ -357,6 +359,88 @@
     }
 
     @Test
+    public void testTypefaceBuilder_fallback() throws IOException {
+        final File validFile = new File(obtainPath());
+        final File invalidFile = new File("/some/invalid/path/to/font/file");
+        final AssetManager assets = mContext.getAssets();
+        // By default, returns null if no fallback font is specified.
+        assertNull(new Typeface.Builder(invalidFile).build());
+
+        assertNull(new Typeface.Builder(validFile)
+                .setTtcIndex(100 /* non-existing ttc index */).build());
+
+        assertNull(new Typeface.Builder(assets, "invalid path").build());
+
+        assertNull(new Typeface.Builder(assets, "samplefont.ttf")
+                .setTtcIndex(100 /* non-existing ttc index */).build());
+
+        // If fallback is set, the builder never returns null.
+        assertNotNull(new Typeface.Builder(invalidFile).setFallback("").build());
+
+        assertNotNull(new Typeface.Builder(invalidFile).setFallback("invalid name").build());
+
+        Typeface sansSerifTypeface = new Typeface.Builder(invalidFile)
+                .setFallback("sans-serif").build();
+        assertNotNull(sansSerifTypeface);
+
+        Typeface serifTypeface = new Typeface.Builder(invalidFile).setFallback("serif").build();
+        assertNotNull(serifTypeface);
+
+        Typeface boldSansSerifTypeface = new Typeface.Builder(invalidFile)
+                .setFallback("sans-serif").setWeight(700).build();
+        assertNotNull(boldSansSerifTypeface);
+
+        Typeface boldSerifTypeface = new Typeface.Builder(invalidFile)
+                .setFallback("serif").setWeight(700).build();
+        assertNotNull(boldSerifTypeface);
+
+        Typeface italicSansSerifTypeface = new Typeface.Builder(invalidFile)
+                .setFallback("sans-serif").setItalic(true).build();
+        assertNotNull(italicSansSerifTypeface);
+
+        Typeface italicSerifTypeface = new Typeface.Builder(invalidFile)
+                .setFallback("serif").setItalic(true).build();
+        assertNotNull(italicSerifTypeface);
+
+        // All fallbacks should be different each other.
+        assertNotSame(sansSerifTypeface, serifTypeface);
+        assertNotSame(sansSerifTypeface, boldSansSerifTypeface);
+        assertNotSame(sansSerifTypeface, boldSerifTypeface);
+        assertNotSame(sansSerifTypeface, italicSansSerifTypeface);
+        assertNotSame(sansSerifTypeface, italicSerifTypeface);
+        assertNotSame(serifTypeface, boldSansSerifTypeface);
+        assertNotSame(serifTypeface, boldSerifTypeface);
+        assertNotSame(serifTypeface, italicSansSerifTypeface);
+        assertNotSame(serifTypeface, italicSerifTypeface);
+        assertNotSame(boldSansSerifTypeface, boldSerifTypeface);
+        assertNotSame(boldSansSerifTypeface, italicSansSerifTypeface);
+        assertNotSame(boldSansSerifTypeface, italicSerifTypeface);
+        assertNotSame(boldSerifTypeface, italicSansSerifTypeface);
+        assertNotSame(boldSerifTypeface, italicSerifTypeface);
+        assertNotSame(italicSansSerifTypeface, italicSerifTypeface);
+
+        // Cache should work for the same fallback.
+        assertSame(sansSerifTypeface,
+                new Typeface.Builder(assets, "samplefont.ttf").setFallback("sans-serif")
+                        .setTtcIndex(100 /* non-existing ttc index */).build());
+        assertSame(serifTypeface,
+                new Typeface.Builder(assets, "samplefont.ttf").setFallback("serif")
+                        .setTtcIndex(100 /* non-existing ttc index */).build());
+        assertSame(boldSansSerifTypeface,
+                new Typeface.Builder(assets, "samplefont.ttf").setFallback("sans-serif")
+                        .setTtcIndex(100 /* non-existing ttc index */).setWeight(700).build());
+        assertSame(boldSerifTypeface,
+                new Typeface.Builder(assets, "samplefont.ttf").setFallback("serif")
+                        .setTtcIndex(100 /* non-existing ttc index */).setWeight(700).build());
+        assertSame(italicSansSerifTypeface,
+                new Typeface.Builder(assets, "samplefont.ttf").setFallback("sans-serif")
+                        .setTtcIndex(100 /* non-existing ttc index */).setItalic(true).build());
+        assertSame(italicSerifTypeface,
+                new Typeface.Builder(assets, "samplefont.ttf").setFallback("serif")
+                        .setTtcIndex(100 /* non-existing ttc index */).setItalic(true).build());
+    }
+
+    @Test
     public void testTypefaceBuilder_FileSourceFD() {
         try (FileInputStream fis = new FileInputStream(obtainPath())) {
             assertNotNull(new Typeface.Builder(fis.getFD()).build());
@@ -392,4 +476,27 @@
             assertNotEquals(widthDefaultTypeface, widthCustomTypeface, 1.0f);
         }
     }
+
+    @Test
+    public void testTypefaceBuilder_customFallback() {
+        final String fontPath = "samplefont2.ttf";
+        final Typeface regularTypeface = new Typeface.Builder(mContext.getAssets(), fontPath)
+                .setWeight(400).build();
+        final Typeface blackTypeface = new Typeface.Builder(mContext.getAssets(), fontPath)
+                .setWeight(900).build();
+
+        // W is not supported by samplefont2.ttf
+        final String testString = "WWWWWWWWWWWWWWWWWWWWW";
+
+        final Paint p = new Paint();
+        p.setTextSize(128);
+
+        p.setTypeface(regularTypeface);
+        final float widthFromRegular = p.measureText(testString);
+
+        p.setTypeface(blackTypeface);
+        final float widthFromBlack = p.measureText(testString);
+
+        assertTrue(Math.abs(widthFromRegular - widthFromBlack) > 1.0f);
+    }
 }
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedStateListDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedStateListDrawableTest.java
index f8cd816..2e986cb 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedStateListDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedStateListDrawableTest.java
@@ -204,9 +204,11 @@
         DrawableTestUtils.setResourcesDensity(res, densityDpi / 2);
         final StateListDrawable halfDrawable =
                 (StateListDrawable) cs.newDrawable(res);
+        // NOTE: densityDpi may not be an even number, so account for *actual* scaling in asserts
+        final float approxHalf = (float)(densityDpi / 2) / densityDpi;
         for (int i = 0; i < count; i++) {
             halfDrawable.selectDrawable(i);
-            assertEquals(Math.round(origWidth[i] / 2f), halfDrawable.getIntrinsicWidth());
+            assertEquals(Math.round(origWidth[i] * approxHalf), halfDrawable.getIntrinsicWidth());
         }
 
         // Set density to double original.
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableParameterizedTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableParameterizedTest.java
index 1c9f9b3..29da030 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableParameterizedTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableParameterizedTest.java
@@ -30,7 +30,9 @@
 import android.graphics.cts.R;
 import android.graphics.drawable.AnimatedVectorDrawable;
 import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
 import android.support.test.filters.MediumTest;
+import android.support.test.filters.SmallTest;
 import android.support.test.rule.ActivityTestRule;
 import android.util.Log;
 import android.view.View;
@@ -50,7 +52,7 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
-@MediumTest
+@LargeTest
 @RunWith(Parameterized.class)
 public class AnimatedVectorDrawableParameterizedTest {
     @Rule
@@ -183,6 +185,7 @@
         return frameLatch.await(timeout, TimeUnit.MILLISECONDS);
     }
 
+    @SmallTest
     @Test
     public void testSingleFrameAnimation() throws Throwable {
         int resId = R.drawable.avd_single_frame;
@@ -208,6 +211,7 @@
         });
     }
 
+    @MediumTest
     @Test
     public void testEmptyAnimatorSet() throws Throwable {
         int resId = R.drawable.avd_empty_animator;
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
index 65aad83..d1f6282 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
@@ -36,7 +36,8 @@
 import android.graphics.drawable.AnimatedVectorDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Drawable.ConstantState;
-import android.support.test.filters.MediumTest;
+import android.support.test.filters.LargeTest;
+import android.support.test.filters.SmallTest;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
 import android.util.AttributeSet;
@@ -50,7 +51,7 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
-@MediumTest
+@LargeTest
 @RunWith(AndroidJUnit4.class)
 public class AnimatedVectorDrawableTest {
     private static final int IMAGE_WIDTH = 64;
@@ -75,6 +76,7 @@
         mResources = mActivity.getResources();
     }
 
+    @SmallTest
     @Test
     public void testInflate() throws Exception {
         // Setup AnimatedVectorDrawable from xml file
@@ -144,6 +146,7 @@
         assertEquals(1, constantState.getChangingConfigurations());
     }
 
+    @SmallTest
     @Test
     public void testMutate() {
         AnimatedVectorDrawable d1 = (AnimatedVectorDrawable) mResources.getDrawable(mResId);
@@ -178,6 +181,7 @@
         }
     }
 
+    @SmallTest
     @Test
     public void testGetOpacity() {
         AnimatedVectorDrawable d1 = (AnimatedVectorDrawable) mResources.getDrawable(mResId);
@@ -186,6 +190,7 @@
         assertEquals("Still translucent", PixelFormat.TRANSLUCENT, d1.getOpacity());
     }
 
+    @SmallTest
     @Test
     public void testColorFilter() {
         PorterDuffColorFilter filter = new PorterDuffColorFilter(Color.RED, PorterDuff.Mode.SRC_IN);
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/CustomAnimationScaleListDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/CustomAnimationScaleListDrawableTest.java
index 136ae2d..abba96e 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/CustomAnimationScaleListDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/CustomAnimationScaleListDrawableTest.java
@@ -24,6 +24,7 @@
 import android.graphics.drawable.DrawableContainer;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
+import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
 import org.junit.After;
@@ -39,7 +40,7 @@
  * on animation duration scale. When the scale is 0, it is a static drawable, otherwise, it is an
  * animatable drawable.
  */
-@MediumTest
+@SmallTest
 @RunWith(AndroidJUnit4.class)
 public class CustomAnimationScaleListDrawableTest {
     private static final int DRAWABLE_ID = R.drawable.custom_animation_scale_list_drawable;
@@ -58,7 +59,6 @@
         ValueAnimator.setDurationScale(mOriginalScale);
     }
 
-    @MediumTest
     @Test
     public void testNonZeroDurationScale() {
         // Set the duration scale to a non-zero value will cause the AnimationScaleListDrawable's
@@ -69,7 +69,6 @@
         assertTrue(dr.getCurrent() instanceof Animatable);
     }
 
-    @MediumTest
     @Test
     public void testZeroDurationScale() {
         // Set the duration scale to zero will cause the AnimationScaleListDrawable's current
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/DefaultFocusHighlightTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/DefaultFocusHighlightTest.java
new file mode 100644
index 0000000..c8d057a
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/DefaultFocusHighlightTest.java
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.graphics.drawable.cts;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.BitmapFactory;
+import android.graphics.NinePatch;
+import android.graphics.Picture;
+import android.graphics.cts.R;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.DrawableContainer;
+import android.graphics.drawable.DrawableContainer.DrawableContainerState;
+import android.graphics.drawable.GradientDrawable;
+import android.graphics.drawable.LevelListDrawable;
+import android.graphics.drawable.NinePatchDrawable;
+import android.graphics.drawable.PaintDrawable;
+import android.graphics.drawable.PictureDrawable;
+import android.graphics.drawable.RippleDrawable;
+import android.graphics.drawable.ShapeDrawable;
+import android.graphics.drawable.StateListDrawable;
+import android.graphics.drawable.shapes.RectShape;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.StateSet;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class DefaultFocusHighlightTest {
+
+    // The target context.
+    private Context mContext;
+
+    @Before
+    public void setup() {
+        mContext = InstrumentationRegistry.getTargetContext();
+    }
+
+    private static final int A_COLOR = 0x920424;
+    private static final int[] NO_STATE_FOCUSED = new int[] { android.R.attr.state_enabled };
+    private static final int[] ONLY_STATE_FOCUSED = new int[] { android.R.attr.state_focused };
+    private static final int[] STATE_FOCUSED_WITH_POS =
+            new int[] { android.R.attr.state_focused, android.R.attr.state_hovered };
+    private static final int[] STATE_FOCUSED_WITH_NEG =
+            new int[] { android.R.attr.state_focused,  -android.R.attr.state_hovered };
+    private static final int[] STATE_FOCUSED_WITH_ENABLED =
+            new int[] { android.R.attr.state_focused, android.R.attr.state_enabled };
+
+    final static int[] FOCUSED_STATE =
+            new int[] { android.R.attr.state_focused, android.R.attr.state_enabled };
+
+    @UiThreadTest
+    @Test
+    public void testStateListDrawable() {
+        Drawable d;
+        // Empty state spec
+        d = DrawableFactory.createStateListDrawable(
+                new int[][] {}
+            );
+        d.setState(FOCUSED_STATE);
+        assertFalse(d.hasFocusStateSpecified());
+
+        // Wild card
+        d = DrawableFactory.createStateListDrawable(
+                new int[][] { StateSet.WILD_CARD }
+            );
+        d.setState(FOCUSED_STATE);
+        assertFalse(d.hasFocusStateSpecified());
+
+        // No state spec of state_focused=true
+        d = DrawableFactory.createStateListDrawable(
+                new int[][] { NO_STATE_FOCUSED }
+            );
+        d.setState(FOCUSED_STATE);
+        assertFalse(d.hasFocusStateSpecified());
+
+        // One state spec of only state_focused=true
+        d = DrawableFactory.createStateListDrawable(
+                new int[][] { ONLY_STATE_FOCUSED }
+            );
+        d.setState(FOCUSED_STATE);
+        assertTrue(d.hasFocusStateSpecified());
+
+        // One state spec of state_focused=true and something=true, but no state spec of
+        // state_focused=true and something=false (something is not enabled)
+        d = DrawableFactory.createStateListDrawable(
+                new int[][] { STATE_FOCUSED_WITH_POS }
+            );
+        d.setState(FOCUSED_STATE);
+        assertTrue(d.hasFocusStateSpecified());
+
+        // One state spec of state_focused=true and something=true, and one spec of
+        // state_focused=true and something=false (something is not enabled)
+        d = DrawableFactory.createStateListDrawable(
+            new int[][] { STATE_FOCUSED_WITH_POS, STATE_FOCUSED_WITH_NEG }
+        );
+        d.setState(FOCUSED_STATE);
+        assertTrue(d.hasFocusStateSpecified());
+
+        // One state spec of state_focused=true and enabled=true
+        d = DrawableFactory.createStateListDrawable(
+            new int[][] { STATE_FOCUSED_WITH_ENABLED }
+        );
+        d.setState(FOCUSED_STATE);
+        assertTrue(d.hasFocusStateSpecified());
+    }
+
+    @UiThreadTest
+    @Test
+    public void testRippleDrawable() {
+        Drawable d = DrawableFactory.createRippleDrawable();
+        d.setState(FOCUSED_STATE);
+        assertTrue(d.hasFocusStateSpecified());
+    }
+
+    @UiThreadTest
+    @Test
+    public void testPictureDrawable() {
+        Drawable d = DrawableFactory.createPictureDrawable(null);
+        d.setState(FOCUSED_STATE);
+        assertFalse(d.hasFocusStateSpecified());
+
+        d = DrawableFactory.createPictureDrawable(new Picture());
+        d.setState(FOCUSED_STATE);
+        assertFalse(d.hasFocusStateSpecified());
+    }
+
+    @UiThreadTest
+    @Test
+    public void testColorStateListHandledDrawable() {
+        final Drawable[] drawables = new Drawable[] {
+            DrawableFactory.createShapeDrawable(),
+            DrawableFactory.createPaintDrawable(),
+            DrawableFactory.createBitmapDrawable(mContext),
+            DrawableFactory.createColorDrawable(),
+            DrawableFactory.createGradientDrawable(),
+            DrawableFactory.createNinePatchDrawable(mContext),
+        };
+        final ColorStateList[] stateLists = new ColorStateList[] {
+            // Empty state spec
+            new ColorStateList(
+                new int[][] {  },
+                new int[] {  }),
+            // Wild card
+            new ColorStateList(
+                new int[][] { StateSet.WILD_CARD },
+                new int[] { A_COLOR }),
+            // No state spec of state_focused=true
+            new ColorStateList(
+                new int[][] { NO_STATE_FOCUSED },
+                new int[] { A_COLOR }),
+            // One state spec of only state_focused=true
+            new ColorStateList(
+                new int[][] { ONLY_STATE_FOCUSED },
+                new int[] { A_COLOR }),
+            // One state spec of state_focused=true and something=true,
+            // but no state spec of state_focused=true and something=false
+            new ColorStateList(
+                new int[][] { STATE_FOCUSED_WITH_POS },
+                new int[] { A_COLOR }),
+            // One state spec of state_focused=true and something=true,
+            // and one spec of state_focused=true and something=false
+            new ColorStateList(
+                new int[][] { STATE_FOCUSED_WITH_POS, STATE_FOCUSED_WITH_NEG },
+                new int[] { A_COLOR, A_COLOR }),
+        };
+        final boolean[] expectedResults = new boolean[] {
+            // Empty state spec
+            false,
+            // Wild card
+            false,
+            // No state spec of state_focused=true
+            false,
+            // One state spec of only state_focused=true
+            true,
+            // One state spec of state_focused=true and something=true,
+            // but no state spec of state_focused=true and something=false
+            true,
+            // One state spec of state_focused=true and something=true,
+            // and one spec of state_focused=true and something=false
+            true
+        };
+        assertEquals(stateLists.length, expectedResults.length);
+        for (Drawable drawable : drawables) {
+            // No ColorStateList set
+            String drawableName = drawable.getClass().toString();
+            String errorMsg = "[" + drawableName + "] Testing no ColorStateList failed.";
+            drawable.setState(FOCUSED_STATE);
+            assertFalse(errorMsg, drawable.hasFocusStateSpecified());
+            // With ColorStateList set
+            for (int i = 0; i < stateLists.length; i++) {
+                ColorStateList stateList = stateLists[i];
+                boolean expectedResult = expectedResults[i];
+                drawable.setTintList(stateList);
+                errorMsg = "[" + drawableName + "] Testing ColorStateList No." + i + " failed.";
+
+                drawable.setState(FOCUSED_STATE);
+                if (expectedResult) {
+                    assertTrue(errorMsg, drawable.hasFocusStateSpecified());
+                } else {
+                    assertFalse(errorMsg, drawable.hasFocusStateSpecified());
+                }
+            }
+        }
+    }
+
+    @UiThreadTest
+    @Test
+    public void testDrawableContainer() {
+        MockDrawableContainer container;
+        DrawableContainerState containerState;
+
+        // Empty
+        container = new MockDrawableContainer();
+        containerState = (DrawableContainerState) new LevelListDrawable().getConstantState();
+        assertNotNull(containerState);
+        container.setConstantState(containerState);
+        container.setState(FOCUSED_STATE);
+        assertFalse(container.hasFocusStateSpecified());
+
+        // No drawable of state_focused=true
+        container = new MockDrawableContainer();
+        containerState = (DrawableContainerState) new LevelListDrawable().getConstantState();
+        assertNotNull(containerState);
+        container.setConstantState(containerState);
+        containerState.addChild(DrawableFactory.createPaintDrawable());
+        containerState.addChild(DrawableFactory.createBitmapDrawable(mContext));
+        containerState.addChild(DrawableFactory.createColorDrawable());
+        container.selectDrawable(0);
+        container.setState(FOCUSED_STATE);
+        assertFalse(container.hasFocusStateSpecified());
+        container.selectDrawable(1);
+        container.setState(FOCUSED_STATE);
+        assertFalse(container.hasFocusStateSpecified());
+        container.selectDrawable(2);
+        container.setState(FOCUSED_STATE);
+        assertFalse(container.hasFocusStateSpecified());
+
+        // Only drawables of state_focused=true
+        container = new MockDrawableContainer();
+        containerState = (DrawableContainerState) new LevelListDrawable().getConstantState();
+        assertNotNull(containerState);
+        container.setConstantState(containerState);
+        containerState.addChild(DrawableFactory.createRippleDrawable());
+        containerState.addChild(
+            DrawableFactory.createStateListDrawable(
+                new int[][] { STATE_FOCUSED_WITH_POS, STATE_FOCUSED_WITH_NEG }
+            )
+        );
+        container.selectDrawable(0);
+        container.setState(FOCUSED_STATE);
+        assertTrue(container.hasFocusStateSpecified());
+        container.selectDrawable(1);
+        container.setState(FOCUSED_STATE);
+        assertTrue(container.hasFocusStateSpecified());
+
+        // Both drawables of state_focused=true and state_focused=false
+        containerState.addChild(DrawableFactory.createColorDrawable());
+        container.selectDrawable(2);
+        container.setState(FOCUSED_STATE);
+        assertFalse(container.hasFocusStateSpecified());
+        container.selectDrawable(1);
+        container.setState(FOCUSED_STATE);
+        assertTrue(container.hasFocusStateSpecified());
+        container.selectDrawable(0);
+        container.setState(FOCUSED_STATE);
+        assertTrue(container.hasFocusStateSpecified());
+    }
+
+    static class DrawableFactory {
+        static ShapeDrawable createShapeDrawable() {
+            return new ShapeDrawable(new RectShape());
+        }
+        static PaintDrawable createPaintDrawable() {
+            PaintDrawable paintDrawable = new PaintDrawable();
+            paintDrawable.setCornerRadius(1.5f);
+            return paintDrawable;
+        }
+        static BitmapDrawable createBitmapDrawable(Context context) {
+            Bitmap bitmap = Bitmap.createBitmap(200, 300, Config.ARGB_8888);
+            BitmapDrawable bitmapDrawable = new BitmapDrawable(context.getResources(), bitmap);
+            return bitmapDrawable;
+        }
+        static ColorDrawable createColorDrawable() {
+            return new ColorDrawable(A_COLOR);
+        }
+        static GradientDrawable createGradientDrawable() {
+            GradientDrawable gradientDrawable = new GradientDrawable();
+            gradientDrawable.setColor(A_COLOR);
+            gradientDrawable.setCornerRadius(10f);
+            return gradientDrawable;
+        }
+        static NinePatchDrawable createNinePatchDrawable(Context context) {
+            Resources res = context.getResources();
+            Bitmap bitmap = BitmapFactory.decodeResource(res, R.drawable.ninepatch_0);
+            NinePatch np = new NinePatch(bitmap, bitmap.getNinePatchChunk(), null);
+            NinePatchDrawable ninePatchDrawable = new NinePatchDrawable(res, np);
+            return ninePatchDrawable;
+        }
+        static RippleDrawable createRippleDrawable() {
+            RippleDrawable rippleDrawable =
+                    new RippleDrawable(ColorStateList.valueOf(A_COLOR), null, null);
+            return rippleDrawable;
+        }
+        static PictureDrawable createPictureDrawable(Picture picture) {
+            PictureDrawable pictureDrawable = new PictureDrawable(picture);
+            return pictureDrawable;
+        }
+        static StateListDrawable createStateListDrawable(int[][] stateList) {
+            StateListDrawable drawable = new StateListDrawable();
+            ColorDrawable colorDrawable = DrawableFactory.createColorDrawable();
+            for (int i = 0; i < stateList.length; i++) {
+                drawable.addState(stateList[i], colorDrawable);
+            }
+            return drawable;
+        }
+    }
+
+    // We're calling protected methods in DrawableContainer.
+    // So we have to extend it here to make it accessible.
+    private class MockDrawableContainer extends DrawableContainer {
+        @Override
+        protected void setConstantState(DrawableContainerState state) {
+            super.setConstantState(state);
+        }
+    }
+
+}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/GradientDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/GradientDrawableTest.java
index eb660f3..b798fb8 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/GradientDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/GradientDrawableTest.java
@@ -52,6 +52,7 @@
 import java.io.IOException;
 import java.util.Arrays;
 
+@SmallTest
 @RunWith(AndroidJUnit4.class)
 public class GradientDrawableTest {
     private Resources mResources;
@@ -61,7 +62,6 @@
         mResources = InstrumentationRegistry.getTargetContext().getResources();
     }
 
-    @SmallTest
     @Test
     public void testConstructor() {
         int[] color = new int[] {1, 2, 3};
@@ -71,7 +71,6 @@
         new GradientDrawable(null, null);
     }
 
-    @SmallTest
     @Test
     public void testGetOpacity() {
         GradientDrawable gradientDrawable = new GradientDrawable();
@@ -105,7 +104,6 @@
 
     }
 
-    @SmallTest
     @Test
     public void testSetOrientation() {
         GradientDrawable gradientDrawable = new GradientDrawable();
@@ -117,7 +115,6 @@
                 orientation, gradientDrawable.getOrientation());
     }
 
-    @SmallTest
     @Test
     public void testSetCornerRadii() {
         float[] radii = new float[] {1.0f, 2.0f, 3.0f};
@@ -136,7 +133,6 @@
         gradientDrawable.setCornerRadii(null);
     }
 
-    @SmallTest
     @Test
     public void testSetCornerRadius() {
         GradientDrawable gradientDrawable = new GradientDrawable();
@@ -145,7 +141,6 @@
         gradientDrawable.setCornerRadius(-2.5f);
     }
 
-    @SmallTest
     @Test
     public void testGetCornerRadius() {
         GradientDrawable gradientDrawable = new GradientDrawable();
@@ -160,7 +155,6 @@
         assertEquals(0, gradientDrawable.getCornerRadius(), 0);
     }
 
-    @SmallTest
     @Test
     public void testSetStroke() {
         helpTestSetStroke(2, Color.RED);
@@ -174,7 +168,6 @@
         // TODO: Verify stroke properties.
     }
 
-    @SmallTest
     @Test
     public void testSetStroke_WidthGap() {
         verifySetStroke_WidthGap(2, Color.RED, 3.4f, 5.5f);
@@ -189,7 +182,6 @@
         // TODO: Verify stroke properties.
     }
 
-    @SmallTest
     @Test
     public void testSetStrokeList() {
         verifySetStrokeList(2, ColorStateList.valueOf(Color.RED));
@@ -204,7 +196,6 @@
         // TODO: Verify stroke properties.
     }
 
-    @SmallTest
     @Test
     public void testSetStrokeList_WidthGap() {
         verifySetStrokeList_WidthGap(2, ColorStateList.valueOf(Color.RED), 3.4f, 5.5f);
@@ -219,7 +210,6 @@
         // TODO: Verify stroke properties.
     }
 
-    @SmallTest
     @Test
     public void testSetSize() {
         verifySetSize(6, 4);
@@ -235,7 +225,6 @@
         assertEquals(height, gradientDrawable.getIntrinsicHeight());
     }
 
-    @SmallTest
     @Test
     public void testSetShape() {
         GradientDrawable gradientDrawable = new GradientDrawable();
@@ -252,7 +241,6 @@
                 shape, gradientDrawable.getShape());
     }
 
-    @SmallTest
     @Test
     public void testSetGradientType() {
         GradientDrawable gradientDrawable = new GradientDrawable();
@@ -269,7 +257,6 @@
                 gradientType, gradientDrawable.getGradientType());
     }
 
-    @SmallTest
     @Test
     public void testSetGradientCenter() {
         GradientDrawable gradientDrawable = new GradientDrawable();
@@ -294,7 +281,6 @@
         assertEquals(centerY, gradientDrawable.getGradientCenterY(), 0.01f);
     }
 
-    @SmallTest
     @Test
     public void testSetGradientRadius() {
         GradientDrawable gradientDrawable = new GradientDrawable();
@@ -303,7 +289,6 @@
         gradientDrawable.setGradientRadius(-3.6f);
     }
 
-    @SmallTest
     @Test
     public void testSetUseLevel() {
         GradientDrawable gradientDrawable = new GradientDrawable();
@@ -322,7 +307,6 @@
                 useLevel, gradientDrawable.getUseLevel());
     }
 
-    @SmallTest
     @Test
     public void testDraw() {
         GradientDrawable gradientDrawable = new GradientDrawable();
@@ -333,7 +317,6 @@
         gradientDrawable.draw(null);
     }
 
-    @SmallTest
     @Test
     public void testSetColor() {
         GradientDrawable gradientDrawable = new GradientDrawable();
@@ -350,7 +333,6 @@
                 gradientDrawable.getColor().getDefaultColor());
     }
 
-    @SmallTest
     @Test
     public void testSetColors() {
         GradientDrawable gradientDrawable = new GradientDrawable();
@@ -367,7 +349,6 @@
                 colors, gradientDrawable.getColors());
     }
 
-    @SmallTest
     @Test
     public void testSetColorList() {
         GradientDrawable gradientDrawable = new GradientDrawable();
@@ -382,7 +363,6 @@
         assertEquals("Color was set to null (TRANSPARENT)", color, gradientDrawable.getColor());
     }
 
-    @SmallTest
     @Test
     public void testGetChangingConfigurations() {
         GradientDrawable gradientDrawable = new GradientDrawable();
@@ -395,7 +375,6 @@
         assertEquals(-20, gradientDrawable.getChangingConfigurations());
     }
 
-    @SmallTest
     @Test
     public void testSetAlpha() {
         GradientDrawable gradientDrawable = new GradientDrawable();
@@ -404,7 +383,6 @@
         gradientDrawable.setAlpha(-1);
     }
 
-    @SmallTest
     @Test
     public void testSetDither() {
         GradientDrawable gradientDrawable = new GradientDrawable();
@@ -413,7 +391,6 @@
         gradientDrawable.setDither(false);
     }
 
-    @SmallTest
     @Test
     public void testSetColorFilter() {
         GradientDrawable gradientDrawable = new GradientDrawable();
@@ -424,7 +401,6 @@
         gradientDrawable.setColorFilter(null);
     }
 
-    @SmallTest
     @Test
     public void testInflate() throws XmlPullParserException, IOException {
         GradientDrawable gradientDrawable = new GradientDrawable();
@@ -469,7 +445,6 @@
         }
     }
 
-    @SmallTest
     @Test
     public void testInflateGradientRadius() throws XmlPullParserException, IOException {
         Rect parentBounds = new Rect(0, 0, 100, 100);
@@ -490,7 +465,6 @@
         assertEquals(50.0f, radius, 0.0f);
     }
 
-    @SmallTest
     @Test
     public void testGetIntrinsicWidth() {
         GradientDrawable gradientDrawable = new GradientDrawable();
@@ -501,7 +475,6 @@
         assertEquals(-10, gradientDrawable.getIntrinsicWidth());
     }
 
-    @SmallTest
     @Test
     public void testGetIntrinsicHeight() {
         GradientDrawable gradientDrawable = new GradientDrawable();
@@ -512,14 +485,12 @@
         assertEquals(-15, gradientDrawable.getIntrinsicHeight());
     }
 
-    @SmallTest
     @Test
     public void testGetConstantState() {
         GradientDrawable gradientDrawable = new GradientDrawable();
         assertNotNull(gradientDrawable.getConstantState());
     }
 
-    @SmallTest
     @Test
     public void testMutate() {
         GradientDrawable d1 =
@@ -555,17 +526,28 @@
         assertEquals(40, d3.getIntrinsicWidth());
     }
 
-    @MediumTest
     @Test
     public void testPreloadDensity() throws XmlPullParserException, IOException {
         final int densityDpi = mResources.getConfiguration().densityDpi;
         try {
+            DrawableTestUtils.setResourcesDensity(mResources, densityDpi);
             verifyPreloadDensityInner(mResources, densityDpi);
         } finally {
             DrawableTestUtils.setResourcesDensity(mResources, densityDpi);
         }
     }
 
+    @Test
+    public void testPreloadDensity_tvdpi() throws XmlPullParserException, IOException {
+        final int densityDpi = mResources.getConfiguration().densityDpi;
+        try {
+            DrawableTestUtils.setResourcesDensity(mResources, 213);
+            verifyPreloadDensityInner(mResources, 213);
+        } finally {
+            DrawableTestUtils.setResourcesDensity(mResources, densityDpi);
+        }
+    }
+
     private void verifyPreloadDensityInner(Resources res, int densityDpi)
             throws XmlPullParserException, IOException {
         final Rect tempPadding = new Rect();
@@ -581,15 +563,17 @@
         final Rect origPadding = new Rect();
         preloadedDrawable.getPadding(origPadding);
 
-        // Set density to half of original. Unlike offsets, which are
+        // Set density to approximately half of original. Unlike offsets, which are
         // truncated, dimensions are rounded to the nearest pixel.
         DrawableTestUtils.setResourcesDensity(res, densityDpi / 2);
         final GradientDrawable halfDrawable =
                 (GradientDrawable) preloadedConstantState.newDrawable(res);
-        assertEquals(Math.round(origWidth / 2f), halfDrawable.getIntrinsicWidth());
-        assertEquals(Math.round(origHeight / 2f), halfDrawable.getIntrinsicHeight());
+        // NOTE: densityDpi may not be an even number, so account for *actual* scaling in asserts
+        final float approxHalf = (float)(densityDpi / 2) / densityDpi;
+        assertEquals(Math.round(origWidth * approxHalf), halfDrawable.getIntrinsicWidth());
+        assertEquals(Math.round(origHeight * approxHalf), halfDrawable.getIntrinsicHeight());
         assertTrue(halfDrawable.getPadding(tempPadding));
-        assertEquals((int) (origPadding.left / 2f), tempPadding.left);
+        assertEquals((int) (origPadding.left * approxHalf), tempPadding.left);
 
         // Set density to double original.
         DrawableTestUtils.setResourcesDensity(res, densityDpi * 2);
@@ -609,20 +593,21 @@
         assertTrue(origDrawable.getPadding(tempPadding));
         assertEquals(origPadding, tempPadding);
 
-        // Some precision is lost when scaling the half-density
-        // drawable back up to the original density. Padding is
-        // always truncated, rather than rounded.
+        // Reproduce imprecise truncated scale down, and back up. Note these aren't rounded.
+        final float approxDouble = 1 / approxHalf;
         final Rect sloppyOrigPadding = new Rect();
-        sloppyOrigPadding.left = 2 * (origPadding.left / 2);
-        sloppyOrigPadding.top = 2 * (origPadding.top / 2);
-        sloppyOrigPadding.right = 2 * (origPadding.right / 2);
-        sloppyOrigPadding.bottom = 2 * (origPadding.bottom / 2);
+        sloppyOrigPadding.left = (int)(approxDouble * ((int)(origPadding.left * approxHalf)));
+        sloppyOrigPadding.top = (int)(approxDouble * ((int)(origPadding.top * approxHalf)));
+        sloppyOrigPadding.right = (int)(approxDouble * ((int)(origPadding.right * approxHalf)));
+        sloppyOrigPadding.bottom = (int)(approxDouble * ((int)(origPadding.bottom * approxHalf)));
 
         // Ensure theme density is applied correctly.
         final Theme t = res.newTheme();
         halfDrawable.applyTheme(t);
-        assertEquals(2 * Math.round(origWidth / 2f), halfDrawable.getIntrinsicWidth());
-        assertEquals(2 * Math.round(origHeight / 2f), halfDrawable.getIntrinsicHeight());
+        assertEquals(Math.round(approxDouble * Math.round(origWidth * approxHalf)),
+                halfDrawable.getIntrinsicWidth());
+        assertEquals(Math.round(approxDouble * Math.round(origHeight * approxHalf)),
+                halfDrawable.getIntrinsicHeight());
         assertTrue(halfDrawable.getPadding(tempPadding));
         assertEquals(sloppyOrigPadding, tempPadding);
         doubleDrawable.applyTheme(t);
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/InsetDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/InsetDrawableTest.java
index 3fcdf82..5eb89fc 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/InsetDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/InsetDrawableTest.java
@@ -342,12 +342,25 @@
         final Resources res = mContext.getResources();
         final int densityDpi = res.getConfiguration().densityDpi;
         try {
+            DrawableTestUtils.setResourcesDensity(res, densityDpi);
             verifyPreloadDensityInner(res, densityDpi);
         } finally {
             DrawableTestUtils.setResourcesDensity(res, densityDpi);
         }
     }
 
+    @Test
+    public void testPreloadDensity_tvdpi() throws XmlPullParserException, IOException {
+        final Resources res = mContext.getResources();
+        final int densityDpi = res.getConfiguration().densityDpi;
+        try {
+            DrawableTestUtils.setResourcesDensity(res, 213);
+            verifyPreloadDensityInner(res, 213);
+        } finally {
+            DrawableTestUtils.setResourcesDensity(res, densityDpi);
+        }
+    }
+
     private void verifyPreloadDensityInner(Resources res, int densityDpi)
             throws XmlPullParserException, IOException {
         // Capture initial state at default density.
@@ -359,12 +372,14 @@
         final int origInsetHoriz = preloadedDrawable.getIntrinsicWidth()
                 - preloadedDrawable.getDrawable().getIntrinsicWidth();
 
-        // Set density to half of original. Unlike offsets, which are
+        // Set density to approximately half of original. Unlike offsets, which are
         // truncated, dimensions are rounded to the nearest pixel.
         DrawableTestUtils.setResourcesDensity(res, densityDpi / 2);
         final InsetDrawable halfDrawable =
                 (InsetDrawable) preloadedConstantState.newDrawable(res);
-        assertEquals(Math.round(origInsetHoriz / 2f), halfDrawable.getIntrinsicWidth()
+        // NOTE: densityDpi may not be an even number, so account for *actual* scaling in asserts
+        final float approxHalf = (float)(densityDpi / 2) / densityDpi;
+        assertEquals(Math.round(origInsetHoriz * approxHalf), halfDrawable.getIntrinsicWidth()
                 - halfDrawable.getDrawable().getIntrinsicWidth());
 
         // Set density to double original.
@@ -384,8 +399,10 @@
         // Ensure theme density is applied correctly.
         final Theme t = res.newTheme();
         halfDrawable.applyTheme(t);
-        assertEquals(origInsetHoriz, halfDrawable.getIntrinsicWidth()
-                - halfDrawable.getDrawable().getIntrinsicWidth());
+        float approxDouble = 1 / approxHalf;
+        // Reproduce imprecise truncated scale down, and back up. Note that we don't round.
+        assertEquals((int)(approxDouble * ((int)(origInsetHoriz * approxHalf))),
+                halfDrawable.getIntrinsicWidth() - halfDrawable.getDrawable().getIntrinsicWidth());
         doubleDrawable.applyTheme(t);
         assertEquals(origInsetHoriz, doubleDrawable.getIntrinsicWidth()
                 - doubleDrawable.getDrawable().getIntrinsicWidth());
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java
index 22491ee..ed9a187 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java
@@ -1678,12 +1678,25 @@
         final Resources res = mContext.getResources();
         final int densityDpi = res.getConfiguration().densityDpi;
         try {
+            DrawableTestUtils.setResourcesDensity(res, densityDpi);
             verifyPreloadDensityInner(res, densityDpi);
         } finally {
             DrawableTestUtils.setResourcesDensity(res, densityDpi);
         }
     }
 
+    @Test
+    public void testPreloadDensity_tvdpi() throws XmlPullParserException, IOException {
+        final Resources res = mContext.getResources();
+        final int densityDpi = res.getConfiguration().densityDpi;
+        try {
+            DrawableTestUtils.setResourcesDensity(res, 213);
+            verifyPreloadDensityInner(res, 213);
+        } finally {
+            DrawableTestUtils.setResourcesDensity(res, densityDpi);
+        }
+    }
+
     private void verifyPreloadDensityInner(Resources res, int densityDpi)
             throws XmlPullParserException, IOException {
         // Capture initial state at default density.
@@ -1714,11 +1727,13 @@
         DrawableTestUtils.setResourcesDensity(res, densityDpi / 2);
         final LayerDrawable halfDrawable =
                 (LayerDrawable) preloadedConstantState.newDrawable(res);
-        final int halfContentWidth = Math.round(initialContentWidth / 2f);
-        final int halfLeftPadding = initialLeftPadding / 2;
-        final int halfRightPadding = initialRightPadding / 2;
-        final int halfContentInsetL = initialContentInsetL / 2;
-        final int halfContentInsetR = initialContentInsetR / 2;
+        // NOTE: densityDpi may not be an even number, so account for *actual* scaling in asserts
+        final float approxHalf = (float)(densityDpi / 2) / densityDpi;
+        final int halfContentWidth = Math.round(initialContentWidth * approxHalf);
+        final int halfLeftPadding = (int) (initialLeftPadding * approxHalf);
+        final int halfRightPadding = (int) (initialRightPadding * approxHalf);
+        final int halfContentInsetL = (int) (initialContentInsetL * approxHalf);
+        final int halfContentInsetR = (int) (initialContentInsetR * approxHalf);
         final int halfIntrinsicWidth = halfContentWidth + halfContentInsetL + halfContentInsetR;
         assertEquals(halfLeftPadding, halfDrawable.getLeftPadding());
         assertEquals(halfRightPadding, halfDrawable.getRightPadding());
@@ -1726,14 +1741,18 @@
         assertEquals(halfContentInsetR, halfDrawable.getLayerInsetLeft(0));
         assertEquals(halfContentWidth, halfDrawable.getLayerWidth(0));
         assertEquals(halfIntrinsicWidth, halfDrawable.getIntrinsicWidth());
-        assertEquals(initialBottomPadding / 2, halfDrawable.getBottomPadding());
-        assertEquals(initialTopPadding / 2, halfDrawable.getTopPadding());
-        assertEquals(initialLayerInsetLeft / 2,halfDrawable.getLayerInsetLeft(0));
-        assertEquals(initialLayerInsetRight / 2, halfDrawable.getLayerInsetRight(0));
-        assertEquals(initialLayerInsetTop / 2, halfDrawable.getLayerInsetTop(0));
-        assertEquals(initialLayerInsetBottom / 2, halfDrawable.getLayerInsetBottom(0));
-        assertEquals(Math.round(initialLayerWidth / 2f), halfDrawable.getLayerWidth(0));
-        assertEquals(Math.round(initialLayerHeight / 2f), halfDrawable.getLayerHeight(0));
+        assertEquals((int) (initialBottomPadding * approxHalf), halfDrawable.getBottomPadding());
+        assertEquals((int) (initialTopPadding * approxHalf), halfDrawable.getTopPadding());
+        assertEquals((int) (initialLayerInsetLeft * approxHalf),
+                halfDrawable.getLayerInsetLeft(0));
+        assertEquals((int) (initialLayerInsetRight * approxHalf),
+                halfDrawable.getLayerInsetRight(0));
+        assertEquals((int) (initialLayerInsetTop * approxHalf),
+                halfDrawable.getLayerInsetTop(0));
+        assertEquals((int) (initialLayerInsetBottom * approxHalf),
+                halfDrawable.getLayerInsetBottom(0));
+        assertEquals(Math.round(initialLayerWidth * approxHalf), halfDrawable.getLayerWidth(0));
+        assertEquals(Math.round(initialLayerHeight * approxHalf), halfDrawable.getLayerHeight(0));
 
         // Set density to double original.
         DrawableTestUtils.setResourcesDensity(res, densityDpi * 2);
@@ -1779,20 +1798,31 @@
         // The half-density drawable will scale-up all of the values that were
         // previously scaled-down, so we need to capture the rounding errors.
         halfDrawable.applyTheme(t);
-        assertEquals(halfLeftPadding * 2, halfDrawable.getLeftPadding());
-        assertEquals(halfRightPadding * 2, halfDrawable.getRightPadding());
-        assertEquals(halfContentInsetL * 2, halfDrawable.getLayerInsetRight(0));
-        assertEquals(halfContentInsetR * 2, halfDrawable.getLayerInsetLeft(0));
-        assertEquals(halfContentWidth * 2, halfDrawable.getLayerWidth(0));
+
+        // Reproduce imprecise truncated scale down, and back up. Note that we don't round.
+        float approxDouble = 1 / approxHalf;
+        assertEquals((int) (halfLeftPadding * approxDouble), halfDrawable.getLeftPadding());
+        assertEquals((int) (halfRightPadding * approxDouble), halfDrawable.getRightPadding());
+        assertEquals((int) (halfContentInsetL * approxDouble), halfDrawable.getLayerInsetRight(0));
+        assertEquals((int) (halfContentInsetR * approxDouble), halfDrawable.getLayerInsetLeft(0));
+        assertEquals((int) (halfContentWidth * approxDouble), halfDrawable.getLayerWidth(0));
         assertEquals(halfIntrinsicWidth * 2, halfDrawable.getIntrinsicWidth());
-        assertEquals(2 * (initialBottomPadding / 2), halfDrawable.getBottomPadding());
-        assertEquals(2 * (initialTopPadding / 2), halfDrawable.getTopPadding());
-        assertEquals(2 * (initialLayerInsetLeft / 2), halfDrawable.getLayerInsetLeft(0));
-        assertEquals(2 * (initialLayerInsetRight / 2), halfDrawable.getLayerInsetRight(0));
-        assertEquals(2 * (initialLayerInsetTop / 2), halfDrawable.getLayerInsetTop(0));
-        assertEquals(2 * (initialLayerInsetBottom / 2), halfDrawable.getLayerInsetBottom(0));
-        assertEquals(2 * Math.round(initialLayerWidth / 2f), halfDrawable.getLayerWidth(0));
-        assertEquals(2 * Math.round(initialLayerHeight / 2f), halfDrawable.getLayerHeight(0));
+        assertEquals((int) ((int) (initialBottomPadding * approxHalf) * approxDouble),
+                halfDrawable.getBottomPadding());
+        assertEquals((int) ((int) (initialTopPadding * approxHalf) * approxDouble),
+                halfDrawable.getTopPadding());
+        assertEquals((int) ((int) (initialLayerInsetLeft * approxHalf) * approxDouble),
+                halfDrawable.getLayerInsetLeft(0));
+        assertEquals((int) ((int) (initialLayerInsetRight * approxHalf) * approxDouble),
+                halfDrawable.getLayerInsetRight(0));
+        assertEquals((int) ((int) (initialLayerInsetTop * approxHalf) * approxDouble),
+                halfDrawable.getLayerInsetTop(0));
+        assertEquals((int) ((int) (initialLayerInsetBottom * approxHalf) * approxDouble),
+                halfDrawable.getLayerInsetBottom(0));
+        assertEquals(Math.round(Math.round(initialLayerWidth * approxHalf) * approxDouble),
+                halfDrawable.getLayerWidth(0));
+        assertEquals(Math.round(Math.round(initialLayerHeight * approxHalf) * approxDouble),
+                halfDrawable.getLayerHeight(0));
 
         // The double-density drawable will scale-down all of the values that
         // were previously scaled-up, so we don't need to worry about rounding.
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/ShapeDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/ShapeDrawableTest.java
index 80d604e..d563102 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/ShapeDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/ShapeDrawableTest.java
@@ -36,6 +36,7 @@
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
 import android.graphics.PorterDuff.Mode;
+import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
 import android.graphics.Shader;
 import android.graphics.cts.R;
@@ -219,6 +220,18 @@
         assertNull(shapeDrawable.getShaderFactory());
     }
 
+    @Test
+    public void testSetXfermode() {
+        ShapeDrawable shapeDrawable = new ShapeDrawable();
+
+        PorterDuffXfermode xfermode = new PorterDuffXfermode(Mode.SRC_OVER);
+        shapeDrawable.setXfermode(xfermode);
+        assertSame(xfermode, shapeDrawable.getPaint().getXfermode());
+
+        shapeDrawable.setXfermode(null);
+        assertNull(shapeDrawable.getPaint().getXfermode());
+    }
+
     public static class MockShaderFactory extends ShaderFactory {
         public Shader resize(int width, int height) {
             return null;
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/StateListDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/StateListDrawableTest.java
index fb3445e..6499594 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/StateListDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/StateListDrawableTest.java
@@ -229,10 +229,12 @@
         DrawableTestUtils.setResourcesDensity(res, densityDpi / 2);
         final StateListDrawable halfDrawable =
                 (StateListDrawable) preloadedConstantState.newDrawable(res);
+        // NOTE: densityDpi may not be an even number, so account for *actual* scaling in asserts
+        final float approxHalf = (float)(densityDpi / 2) / densityDpi;
         halfDrawable.selectDrawable(0);
-        assertEquals(Math.round(origWidth0 / 2f), halfDrawable.getIntrinsicWidth());
+        assertEquals(Math.round(origWidth0 * approxHalf), halfDrawable.getIntrinsicWidth());
         halfDrawable.selectDrawable(1);
-        assertEquals(Math.round(origWidth1 / 2f), halfDrawable.getIntrinsicWidth());
+        assertEquals(Math.round(origWidth1 * approxHalf), halfDrawable.getIntrinsicWidth());
 
         // Set density to double original.
         DrawableTestUtils.setResourcesDensity(res, densityDpi * 2);
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 16c6961..276bf50 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java
@@ -33,7 +33,6 @@
 import android.graphics.drawable.Drawable.ConstantState;
 import android.graphics.drawable.VectorDrawable;
 import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.util.AttributeSet;
@@ -50,6 +49,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 
+@SmallTest
 @RunWith(AndroidJUnit4.class)
 public class VectorDrawableTest {
     private static final String LOGTAG = "VectorDrawableTest";
@@ -200,31 +200,26 @@
         mResources = InstrumentationRegistry.getTargetContext().getResources();
     }
 
-    @MediumTest
     @Test
     public void testBasicVectorDrawables() throws XmlPullParserException, IOException {
         verifyVectorDrawables(BASIC_ICON_RES_IDS, BASIC_GOLDEN_IMAGES, null);
     }
 
-    @MediumTest
     @Test
     public void testLMVectorDrawables() throws XmlPullParserException, IOException {
         verifyVectorDrawables(L_M_ICON_RES_IDS, L_M_GOLDEN_IMAGES, null);
     }
 
-    @MediumTest
     @Test
     public void testNVectorDrawables() throws XmlPullParserException, IOException {
         verifyVectorDrawables(N_ICON_RES_IDS, N_GOLDEN_IMAGES, null);
     }
 
-    @MediumTest
     @Test
     public void testVectorDrawableGradient() throws XmlPullParserException, IOException {
         verifyVectorDrawables(GRADIENT_ICON_RES_IDS, GRADIENT_GOLDEN_IMAGES, null);
     }
 
-    @MediumTest
     @Test
     public void testColorStateList() throws XmlPullParserException, IOException {
         for (int i = 0; i < STATEFUL_STATE_SETS.length; i++) {
@@ -344,7 +339,6 @@
         return builder.toString();
     }
 
-    @SmallTest
     @Test
     public void testGetChangingConfigurations() {
         VectorDrawable vectorDrawable = new VectorDrawable();
@@ -369,7 +363,6 @@
         assertEquals(0xffff,  vectorDrawable.getChangingConfigurations());
     }
 
-    @SmallTest
     @Test
     public void testGetConstantState() {
         VectorDrawable vectorDrawable = new VectorDrawable();
@@ -383,7 +376,6 @@
         assertEquals(1, constantState.getChangingConfigurations());
     }
 
-    @SmallTest
     @Test
     public void testMutate() {
         // d1 and d2 will be mutated, while d3 will not.
@@ -419,7 +411,6 @@
         }
     }
 
-    @SmallTest
     @Test
     public void testColorFilter() {
         PorterDuffColorFilter filter = new PorterDuffColorFilter(Color.RED, Mode.SRC_IN);
@@ -429,18 +420,6 @@
         assertEquals(filter, vectorDrawable.getColorFilter());
     }
 
-    @SmallTest
-    @Test
-    public void testPreloadDensity() throws XmlPullParserException, IOException {
-        final int densityDpi = mResources.getConfiguration().densityDpi;
-        try {
-            verifyPreloadDensityInner(mResources, densityDpi);
-        } finally {
-            DrawableTestUtils.setResourcesDensity(mResources, densityDpi);
-        }
-    }
-
-    @SmallTest
     @Test
     public void testGetOpacity () throws XmlPullParserException, IOException {
         VectorDrawable vectorDrawable = new VectorDrawable();
@@ -455,6 +434,28 @@
                 vectorDrawable.getOpacity());
     }
 
+    @Test
+    public void testPreloadDensity() throws XmlPullParserException, IOException {
+        final int densityDpi = mResources.getConfiguration().densityDpi;
+        try {
+            DrawableTestUtils.setResourcesDensity(mResources, densityDpi);
+            verifyPreloadDensityInner(mResources, densityDpi);
+        } finally {
+            DrawableTestUtils.setResourcesDensity(mResources, densityDpi);
+        }
+    }
+
+    @Test
+    public void testPreloadDensity_tvdpi() throws XmlPullParserException, IOException {
+        final int densityDpi = mResources.getConfiguration().densityDpi;
+        try {
+            DrawableTestUtils.setResourcesDensity(mResources, 213);
+            verifyPreloadDensityInner(mResources, 213);
+        } finally {
+            DrawableTestUtils.setResourcesDensity(mResources, densityDpi);
+        }
+    }
+
     private void verifyPreloadDensityInner(Resources res, int densityDpi)
             throws XmlPullParserException, IOException {
         // Capture initial state at default density.
@@ -470,7 +471,9 @@
         DrawableTestUtils.setResourcesDensity(res, densityDpi / 2);
         final VectorDrawable halfDrawable =
                 (VectorDrawable) preloadedConstantState.newDrawable(res);
-        assertEquals(Math.round(origWidth / 2f), halfDrawable.getIntrinsicWidth());
+        // NOTE: densityDpi may not be an even number, so account for *actual* scaling in asserts
+        final float approxHalf = (float)(densityDpi / 2) / densityDpi;
+        assertEquals(Math.round(origWidth * approxHalf), halfDrawable.getIntrinsicWidth());
 
         // Set density to double original.
         DrawableTestUtils.setResourcesDensity(res, densityDpi * 2);
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
index f01b833..b7f7c8e 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
@@ -109,6 +109,7 @@
             .compile("([0-9]{4})-([0-9]{2})-[0-9]{2}");
 
     private static final int KM_ERROR_INVALID_INPUT_LENGTH = -21;
+    private static final int KM_ERROR_PERMISSION_DENIED = 6;
 
     public void testVersionParser() throws Exception {
         // Non-numerics/empty give version 0
@@ -211,6 +212,29 @@
         }
     }
 
+    public void testEcAttestation_KeyStoreExceptionWhenRequestingUniqueId() throws Exception {
+        String keystoreAlias = "test_key";
+        KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(keystoreAlias, PURPOSE_SIGN)
+                .setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
+                .setDigests(DIGEST_NONE, DIGEST_SHA256, DIGEST_SHA512)
+                .setAttestationChallenge(new byte[128])
+                .setUniqueIdIncluded(true)
+                .build();
+
+        try {
+            generateKeyPair(KEY_ALGORITHM_EC, spec);
+            fail("Attestation should have failed.");
+        } catch (ProviderException e) {
+            // Attestation is expected to fail because of lack of permissions.
+            KeyStoreException cause = (KeyStoreException) e.getCause();
+            assertEquals(KM_ERROR_PERMISSION_DENIED, cause.getErrorCode());
+        } finally {
+            KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
+            keyStore.load(null);
+            keyStore.deleteEntry(keystoreAlias);
+        }
+    }
+
     public void testRsaAttestation() throws Exception {
         int[] keySizes = { // Smallish sizes to keep test runtimes down.
                 512, 768, 1024
diff --git a/tests/tests/location/src/android/location/cts/LocationTest.java b/tests/tests/location/src/android/location/cts/LocationTest.java
index bec6350..3e291cf 100644
--- a/tests/tests/location/src/android/location/cts/LocationTest.java
+++ b/tests/tests/location/src/android/location/cts/LocationTest.java
@@ -282,10 +282,6 @@
         location.setVerticalAccuracyMeters(1.0f);
         assertEquals(1.0, location.getVerticalAccuracyMeters(), DELTA);
         assertTrue(location.hasVerticalAccuracy());
-
-        location.removeVerticalAccuracy();
-        assertEquals(0.0, location.getVerticalAccuracyMeters(), DELTA);
-        assertFalse(location.hasVerticalAccuracy());
     }
 
     public void testAccessSpeedAccuracy() {
@@ -295,10 +291,6 @@
         location.setSpeedAccuracyMetersPerSecond(1.0f);
         assertEquals(1.0, location.getSpeedAccuracyMetersPerSecond(), DELTA);
         assertTrue(location.hasSpeedAccuracy());
-
-        location.removeSpeedAccuracy();
-        assertEquals(0.0, location.getSpeedAccuracyMetersPerSecond(), DELTA);
-        assertFalse(location.hasSpeedAccuracy());
     }
 
     public void testAccessBearingAccuracy() {
@@ -308,10 +300,6 @@
         location.setBearingAccuracyDegrees(1.0f);
         assertEquals(1.0, location.getBearingAccuracyDegrees(), DELTA);
         assertTrue(location.hasBearingAccuracy());
-
-        location.removeBearingAccuracy();
-        assertEquals(0.0, location.getBearingAccuracyDegrees(), DELTA);
-        assertFalse(location.hasBearingAccuracy());
     }
 
 
diff --git a/tests/tests/media/src/android/media/cts/MediaBrowserServiceTest.java b/tests/tests/media/src/android/media/cts/MediaBrowserServiceTest.java
index 0cbbe7e..99c0ac1 100644
--- a/tests/tests/media/src/android/media/cts/MediaBrowserServiceTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaBrowserServiceTest.java
@@ -36,13 +36,63 @@
             "android.media.cts", "android.media.cts.StubMediaBrowserService");
     private final Object mWaitLock = new Object();
 
-    private final ConnectionCallback mConnectionCallback = new ConnectionCallback();
-    private final SubscriptionCallback mSubscriptionCallback = new SubscriptionCallback();
-    private final ItemCallback mItemCallback = new ItemCallback();
-    private final SearchCallback mSearchCallback = new SearchCallback();
+    private final MediaBrowser.ConnectionCallback mConnectionCallback =
+            new MediaBrowser.ConnectionCallback() {
+        @Override
+        public void onConnected() {
+            synchronized (mWaitLock) {
+                mMediaBrowserService = StubMediaBrowserService.sInstance;
+                mWaitLock.notify();
+            }
+        }
+    };
+
+    private final MediaBrowser.SubscriptionCallback mSubscriptionCallback =
+            new MediaBrowser.SubscriptionCallback() {
+            @Override
+            public void onChildrenLoaded(String parentId, List<MediaItem> children) {
+                synchronized (mWaitLock) {
+                    mOnChildrenLoaded = true;
+                    if (children != null) {
+                        for (MediaItem item : children) {
+                            assertRootHints(item);
+                        }
+                    }
+                    mWaitLock.notify();
+                }
+            }
+
+            @Override
+            public void onChildrenLoaded(String parentId, List<MediaItem> children,
+                    Bundle options) {
+                synchronized (mWaitLock) {
+                    mOnChildrenLoadedWithOptions = true;
+                    if (children != null) {
+                        for (MediaItem item : children) {
+                            assertRootHints(item);
+                        }
+                    }
+                    mWaitLock.notify();
+                }
+            }
+        };
+
+    private final MediaBrowser.ItemCallback mItemCallback = new MediaBrowser.ItemCallback() {
+        @Override
+        public void onItemLoaded(MediaItem item) {
+            synchronized (mWaitLock) {
+                mOnItemLoaded = true;
+                assertRootHints(item);
+                mWaitLock.notify();
+            }
+        }
+    };
 
     private MediaBrowser mMediaBrowser;
     private StubMediaBrowserService mMediaBrowserService;
+    private boolean mOnChildrenLoaded;
+    private boolean mOnChildrenLoadedWithOptions;
+    private boolean mOnItemLoaded;
     private Bundle mRootHints;
 
     @Override
@@ -72,15 +122,14 @@
 
     public void testNotifyChildrenChanged() throws Exception {
         synchronized (mWaitLock) {
-            mSubscriptionCallback.reset();
             mMediaBrowser.subscribe(StubMediaBrowserService.MEDIA_ID_ROOT, mSubscriptionCallback);
             mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mSubscriptionCallback.mOnChildrenLoaded);
+            assertTrue(mOnChildrenLoaded);
 
-            mSubscriptionCallback.reset();
+            mOnChildrenLoaded = false;
             mMediaBrowserService.notifyChildrenChanged(StubMediaBrowserService.MEDIA_ID_ROOT);
             mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mSubscriptionCallback.mOnChildrenLoaded);
+            assertTrue(mOnChildrenLoaded);
         }
     }
 
@@ -92,54 +141,53 @@
             options.putInt(MediaBrowser.EXTRA_PAGE_SIZE, pageSize);
             options.putInt(MediaBrowser.EXTRA_PAGE, page);
 
-            mSubscriptionCallback.reset();
             mMediaBrowser.subscribe(StubMediaBrowserService.MEDIA_ID_ROOT, options,
                     mSubscriptionCallback);
             mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mSubscriptionCallback.mOnChildrenLoadedWithOptions);
+            assertTrue(mOnChildrenLoadedWithOptions);
 
-            mSubscriptionCallback.reset();
+            mOnChildrenLoadedWithOptions = false;
             mMediaBrowserService.notifyChildrenChanged(StubMediaBrowserService.MEDIA_ID_ROOT);
             mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mSubscriptionCallback.mOnChildrenLoadedWithOptions);
+            assertTrue(mOnChildrenLoadedWithOptions);
         }
     }
 
     public void testDelayedNotifyChildrenChanged() throws Exception {
         synchronized (mWaitLock) {
-            mSubscriptionCallback.reset();
+            mOnChildrenLoaded = false;
             mMediaBrowser.subscribe(StubMediaBrowserService.MEDIA_ID_CHILDREN_DELAYED,
                     mSubscriptionCallback);
             mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
-            assertFalse(mSubscriptionCallback.mOnChildrenLoaded);
+            assertFalse(mOnChildrenLoaded);
 
             mMediaBrowserService.sendDelayedNotifyChildrenChanged();
             mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mSubscriptionCallback.mOnChildrenLoaded);
+            assertTrue(mOnChildrenLoaded);
 
-            mSubscriptionCallback.reset();
+            mOnChildrenLoaded = false;
             mMediaBrowserService.notifyChildrenChanged(
                     StubMediaBrowserService.MEDIA_ID_CHILDREN_DELAYED);
             mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
-            assertFalse(mSubscriptionCallback.mOnChildrenLoaded);
+            assertFalse(mOnChildrenLoaded);
 
             mMediaBrowserService.sendDelayedNotifyChildrenChanged();
             mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mSubscriptionCallback.mOnChildrenLoaded);
+            assertTrue(mOnChildrenLoaded);
         }
     }
 
     public void testDelayedItem() throws Exception {
         synchronized (mWaitLock) {
-            mItemCallback.reset();
-            mMediaBrowser.getItem(StubMediaBrowserService.MEDIA_ID_CHILDREN_DELAYED, mItemCallback);
+            mOnItemLoaded = false;
+            mMediaBrowser.getItem(StubMediaBrowserService.MEDIA_ID_CHILDREN_DELAYED,
+                    mItemCallback);
             mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
-            assertFalse(mItemCallback.mOnItemLoaded);
+            assertFalse(mOnItemLoaded);
 
-            mItemCallback.reset();
             mMediaBrowserService.sendDelayedItemLoaded();
             mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mItemCallback.mOnItemLoaded);
+            assertTrue(mOnItemLoaded);
         }
     }
 
@@ -155,60 +203,6 @@
         assertEquals(val, browserRoot.getExtras().getString(key));
     }
 
-    public void testSearch() throws Exception {
-        final String key = "test-key";
-        final String val = "test-val";
-
-        final MediaBrowser.SearchCallback searchCallback =
-                (MediaBrowser.SearchCallback) mSearchCallback;
-        final MediaBrowserService mediaBrowserService = (MediaBrowserService) mMediaBrowserService;
-
-        synchronized (mWaitLock) {
-            mSearchCallback.reset();
-            mMediaBrowser.search(StubMediaBrowserService.SEARCH_QUERY_FOR_NO_RESULT, null,
-                    mSearchCallback);
-            mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
-            assertTrue(mSearchCallback.mOnSearchResult);
-            assertTrue(mSearchCallback.mSearchResults != null
-                    && mSearchCallback.mSearchResults.size() == 0);
-            assertEquals(null, mSearchCallback.mSearchExtras);
-            // just call the callback once directly so it's marked as tested
-            mediaBrowserService.onSearch(
-                    StubMediaBrowserService.SEARCH_QUERY_FOR_NO_RESULT, null, null);
-            searchCallback.onSearchResult(StubMediaBrowserService.SEARCH_QUERY_FOR_NO_RESULT,
-                    mSearchCallback.mSearchExtras, mSearchCallback.mSearchResults);
-
-            mSearchCallback.reset();
-            mMediaBrowser.search(StubMediaBrowserService.SEARCH_QUERY_FOR_ERROR, null,
-                    mSearchCallback);
-            mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
-            assertTrue(mSearchCallback.mOnSearchResult);
-            assertNull(mSearchCallback.mSearchResults);
-            assertEquals(null, mSearchCallback.mSearchExtras);
-            // just call the callback once directly so it's marked as tested
-            mediaBrowserService.onSearch(
-                    StubMediaBrowserService.SEARCH_QUERY_FOR_ERROR, null, null);
-            searchCallback.onError(StubMediaBrowserService.SEARCH_QUERY_FOR_ERROR, null);
-
-            mSearchCallback.reset();
-            Bundle extras = new Bundle();
-            extras.putString(key, val);
-            mMediaBrowser.search(StubMediaBrowserService.SEARCH_QUERY, extras, mSearchCallback);
-            mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
-            assertTrue(mSearchCallback.mOnSearchResult);
-            assertNotNull(mSearchCallback.mSearchResults);
-            for (MediaItem item : mSearchCallback.mSearchResults) {
-                assertTrue(item.getMediaId().contains(StubMediaBrowserService.SEARCH_QUERY));
-            }
-            assertNotNull(mSearchCallback.mSearchExtras);
-            assertEquals(val, mSearchCallback.mSearchExtras.getString(key));
-            // just call the callback once directly so it's marked as tested
-            mediaBrowserService.onSearch(StubMediaBrowserService.SEARCH_QUERY, extras, null);
-            searchCallback.onSearchResult(StubMediaBrowserService.SEARCH_QUERY,
-                    mSearchCallback.mSearchExtras, mSearchCallback.mSearchResults);
-        }
-    }
-
     private void assertRootHints(MediaItem item) {
         Bundle rootHints = item.getDescription().getExtras();
         assertNotNull(rootHints);
@@ -219,100 +213,4 @@
         assertEquals(mRootHints.getBoolean(BrowserRoot.EXTRA_SUGGESTED),
                 rootHints.getBoolean(BrowserRoot.EXTRA_SUGGESTED));
     }
-
-    private class ConnectionCallback extends MediaBrowser.ConnectionCallback {
-        @Override
-        public void onConnected() {
-            synchronized (mWaitLock) {
-                mMediaBrowserService = StubMediaBrowserService.sInstance;
-                mWaitLock.notify();
-            }
-        }
-    }
-
-    private class SubscriptionCallback extends MediaBrowser.SubscriptionCallback {
-        boolean mOnChildrenLoaded;
-        boolean mOnChildrenLoadedWithOptions;
-
-        @Override
-        public void onChildrenLoaded(String parentId, List<MediaItem> children) {
-            synchronized (mWaitLock) {
-                mOnChildrenLoaded = true;
-                if (children != null) {
-                    for (MediaItem item : children) {
-                        assertRootHints(item);
-                    }
-                }
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onChildrenLoaded(String parentId, List<MediaItem> children,
-                Bundle options) {
-            synchronized (mWaitLock) {
-                mOnChildrenLoadedWithOptions = true;
-                if (children != null) {
-                    for (MediaItem item : children) {
-                        assertRootHints(item);
-                    }
-                }
-                mWaitLock.notify();
-            }
-        }
-
-        public void reset() {
-            mOnChildrenLoaded = false;
-            mOnChildrenLoadedWithOptions = false;
-        }
-    }
-
-    private class ItemCallback extends MediaBrowser.ItemCallback {
-        boolean mOnItemLoaded;
-
-        @Override
-        public void onItemLoaded(MediaItem item) {
-            synchronized (mWaitLock) {
-                mOnItemLoaded = true;
-                assertRootHints(item);
-                mWaitLock.notify();
-            }
-        }
-
-        public void reset() {
-            mOnItemLoaded = false;
-        }
-    }
-
-    private class SearchCallback extends MediaBrowser.SearchCallback {
-        boolean mOnSearchResult;
-        Bundle mSearchExtras;
-        List<MediaItem> mSearchResults;
-
-        @Override
-        public void onSearchResult(String query, Bundle extras, List<MediaItem> items) {
-            synchronized (mWaitLock) {
-                mOnSearchResult = true;
-                mSearchResults = items;
-                mSearchExtras = extras;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onError(String query, Bundle extras) {
-            synchronized (mWaitLock) {
-                mOnSearchResult = true;
-                mSearchResults = null;
-                mSearchExtras = extras;
-                mWaitLock.notify();
-            }
-        }
-
-        public void reset() {
-            mOnSearchResult = false;
-            mSearchExtras = null;
-            mSearchResults = null;
-        }
-    }
 }
diff --git a/tests/tests/media/src/android/media/cts/MediaCasTest.java b/tests/tests/media/src/android/media/cts/MediaCasTest.java
index d2ae849..a3cdefc 100644
--- a/tests/tests/media/src/android/media/cts/MediaCasTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCasTest.java
@@ -18,6 +18,7 @@
 
 import android.media.MediaCas;
 import android.media.MediaCas.PluginDescriptor;
+import android.media.MediaCas.Session;
 import android.media.MediaCasException;
 import android.media.MediaCasException.UnsupportedCasException;
 import android.media.MediaCasStateException;
@@ -181,10 +182,10 @@
                 }, null);
             } finally {
                 if (mediaCas != null) {
-                    mediaCas.release();
+                    mediaCas.close();
                 }
                 if (descrambler != null) {
-                    descrambler.release();
+                    descrambler.close();
                 }
             }
         }
@@ -213,10 +214,10 @@
             }
         } finally {
             if (unsupportedCAS != null) {
-                unsupportedCAS.release();
+                unsupportedCAS.close();
             }
             if (unsupportedDescrambler != null) {
-                unsupportedDescrambler.release();
+                unsupportedDescrambler.close();
             }
         }
     }
@@ -247,24 +248,22 @@
             byte[] pvtData = new byte[256];
             mediaCas.setPrivateData(pvtData);
 
-            int program_number = 72849;
-            int elementary_PID = 256;
-            byte[] sessionId = mediaCas.openSession(72849);
-            if (sessionId == null || sessionId.length == 0) {
+            Session session = mediaCas.openSession();
+            if (session == null) {
                 fail("Can't open session for program");
             }
 
-            mediaCas.setSessionPrivateData(sessionId, pvtData);
+            session.setPrivateData(pvtData);
 
-            byte[] streamSessionId = mediaCas.openSession(72849, 256);
-            if (streamSessionId == null || streamSessionId.length == 0) {
+            Session streamSession = mediaCas.openSession();
+            if (streamSession == null) {
                 fail("Can't open session for stream");
             }
-            mediaCas.setSessionPrivateData(streamSessionId, pvtData);
+            streamSession.setPrivateData(pvtData);
 
-            descrambler.setMediaCasSession(sessionId);
+            descrambler.setMediaCasSession(session);
 
-            descrambler.setMediaCasSession(streamSessionId);
+            descrambler.setMediaCasSession(streamSession);
 
             mediaCas.refreshEntitlements(3, null);
 
@@ -291,8 +290,8 @@
             mediaCas.processEmm(emmData);
 
             byte[] ecmData = loadByteArrayFromString(sEcmBufferStr);
-            mediaCas.processEcm(sessionId, ecmData);
-            mediaCas.processEcm(streamSessionId, ecmData);
+            session.processEcm(ecmData);
+            streamSession.processEcm(ecmData);
 
             ByteBuffer outputBuf = descrambleTestInputBuffer(descrambler);
             ByteBuffer expectedOutputBuf = ByteBuffer.wrap(
@@ -300,14 +299,14 @@
             assertTrue("Incorrect decryption result",
                     expectedOutputBuf.compareTo(outputBuf) == 0);
 
-            mediaCas.closeSession(sessionId);
-            mediaCas.closeSession(streamSessionId);
+            session.close();
+            streamSession.close();
         } finally {
             if (mediaCas != null) {
-                mediaCas.release();
+                mediaCas.close();
             }
             if (descrambler != null) {
-                descrambler.release();
+                descrambler.close();
             }
         }
     }
@@ -324,28 +323,28 @@
             descrambler = new MediaDescrambler(sClearKeySystemId);
             mediaCas.provision(sProvisionStr);
 
-            byte[] sessionId = mediaCas.openSession(72849);
-            if (sessionId == null || sessionId.length == 0) {
+            Session session = mediaCas.openSession();
+            if (session == null) {
                 fail("Can't open session for program");
             }
 
-            byte[] streamSessionId = mediaCas.openSession(72849, 256);
-            if (streamSessionId == null || streamSessionId.length == 0) {
+            Session streamSession = mediaCas.openSession();
+            if (streamSession == null) {
                 fail("Can't open session for stream");
             }
 
-            mediaCas.release();
+            mediaCas.close();
             mediaCas = null;
 
             try {
-                descrambler.setMediaCasSession(sessionId);
+                descrambler.setMediaCasSession(session);
                 fail("Program session not closed after MediaCas is released");
             } catch (MediaCasStateException e) {
                 Log.d(TAG, "setMediaCasSession throws "
                         + e.getDiagnosticInfo() + " (as expected)");
             }
             try {
-                descrambler.setMediaCasSession(streamSessionId);
+                descrambler.setMediaCasSession(streamSession);
                 fail("Stream session not closed after MediaCas is released");
             } catch (MediaCasStateException e) {
                 Log.d(TAG, "setMediaCasSession throws "
@@ -353,10 +352,10 @@
             }
         } finally {
             if (mediaCas != null) {
-                mediaCas.release();
+                mediaCas.close();
             }
             if (descrambler != null) {
-                descrambler.release();
+                descrambler.close();
             }
         }
     }
@@ -393,26 +392,31 @@
                 Log.d(TAG, "processEmm throws ArrayIndexOutOfBoundsException (as expected)");
             }
 
-            byte[] invalidSessionId = new byte[] {};
+            // open a session, then close it so that it should become invalid
+            Session invalidSession = mediaCas.openSession();
+            if (invalidSession == null) {
+                fail("Can't open session for program");
+            }
+            invalidSession.close();
 
             byte[] ecmData = loadByteArrayFromString(sEcmBufferStr);
 
             // processEcm should fail with an invalid session id
             try {
-                mediaCas.processEcm(invalidSessionId, ecmData);
+                invalidSession.processEcm(ecmData);
                 fail("processEcm shouldn't succeed with invalid session id");
             } catch (MediaCasStateException e) {
                 Log.d(TAG, "processEcm throws " + e.getDiagnosticInfo() + " (as expected)");
             }
 
-            byte[] sessionId = mediaCas.openSession(72849);
-            if (sessionId == null || sessionId.length == 0) {
+            Session session = mediaCas.openSession();
+            if (session == null) {
                 fail("Can't open session for program");
             }
 
             // processEcm should fail without provisioning
             try {
-                mediaCas.processEcm(sessionId, ecmData);
+                session.processEcm(ecmData);
                 fail("processEcm shouldn't succeed without provisioning");
             } catch (MediaCasException.NotProvisionedException e) {
                 Log.d(TAG, "processEcm throws NotProvisionedException (as expected)");
@@ -423,7 +427,7 @@
 
             // processEcm should fail with ecm buffer that's too short
             try {
-                mediaCas.processEcm(sessionId, ecmData, 0, 8);
+                session.processEcm(ecmData, 0, 8);
                 fail("processEcm shouldn't succeed with truncated ecm");
             } catch (IllegalArgumentException e) {
                 Log.d(TAG, "processEcm throws " + e.toString() + " (as expected)");
@@ -432,7 +436,7 @@
             // processEcm should fail with ecm with bad descriptor count
             try {
                 ecmData[17] = 3; // change the descriptor count field to 3 (invalid)
-                mediaCas.processEcm(sessionId, ecmData);
+                session.processEcm(ecmData);
                 fail("processEcm shouldn't succeed with altered descriptor count");
             } catch (MediaCasStateException e) {
                 Log.d(TAG, "processEcm throws " + e.getDiagnosticInfo() + " (as expected)");
@@ -444,7 +448,7 @@
 
             // setMediaCasSession should fail with an invalid session id
             try {
-                descrambler.setMediaCasSession(invalidSessionId);
+                descrambler.setMediaCasSession(invalidSession);
                 fail("setMediaCasSession shouldn't succeed with invalid session id");
             } catch (MediaCasStateException e) {
                 Log.d(TAG, "setMediaCasSession throws "
@@ -460,7 +464,7 @@
             }
 
             // Now set a valid session, should still fail because no valid ecm is processed
-            descrambler.setMediaCasSession(sessionId);
+            descrambler.setMediaCasSession(session);
             try {
                 ByteBuffer outputBuf = descrambleTestInputBuffer(descrambler);
                 fail("descramble should fail without valid ecm");
@@ -469,10 +473,10 @@
             }
         } finally {
             if (mediaCas != null) {
-                mediaCas.release();
+                mediaCas.close();
             }
             if (descrambler != null) {
-                descrambler.release();
+                descrambler.close();
             }
         }
     }
@@ -537,7 +541,7 @@
         ByteBuffer inputBuf = ByteBuffer.wrap(
                 loadByteArrayFromString(sInputBufferStr));
         ByteBuffer outputBuf = ByteBuffer.allocate(inputBuf.capacity());
-        descrambler.descramble(inputBuf, 0, outputBuf, 0, cryptoInfo);
+        descrambler.descramble(inputBuf, outputBuf, cryptoInfo);
 
         return outputBuf;
     }
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecClearKeyPlayer.java b/tests/tests/media/src/android/media/cts/MediaCodecClearKeyPlayer.java
index 253a5ab..99f2790 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecClearKeyPlayer.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecClearKeyPlayer.java
@@ -230,8 +230,6 @@
     private void prepareVideo() throws IOException {
         boolean hasVideo = false;
 
-        android.media.DrmInitData drmInitData = mVideoExtractor.getDrmInitData();
-
         for (int i = mVideoExtractor.getTrackCount(); i-- > 0;) {
             MediaFormat format = mVideoExtractor.getTrackFormat(i);
             String mime = format.getString(MediaFormat.KEY_MIME);
@@ -244,11 +242,10 @@
             Log.d(TAG, "video track #" + i + " " + format + " " + mime +
                   " Width:" + mMediaFormatWidth + ", Height:" + mMediaFormatHeight);
 
-            if (mScrambled && drmInitData != null && mime.startsWith("video/")) {
-                android.media.DrmInitData.SchemeInitData schemeInitData =
-                        drmInitData.get(new UUID(0, i));
-                if (schemeInitData != null) {
-                    mDescrambler.setMediaCasSession(schemeInitData.data);
+            if (mScrambled && mime.startsWith("video/")) {
+                MediaExtractor.CasInfo casInfo = mVideoExtractor.getCasInfo(i);
+                if (casInfo != null && casInfo.getSession() != null) {
+                    mDescrambler.setMediaCasSession(casInfo.getSession());
                 }
             }
 
@@ -291,23 +288,18 @@
 
     private void initCasAndDescrambler(MediaExtractor extractor) throws MediaCasException {
         int trackCount = extractor.getTrackCount();
-        android.media.DrmInitData drmInitData = extractor.getDrmInitData();
         for (int trackId = 0; trackId < trackCount; trackId++) {
             android.media.MediaFormat format = extractor.getTrackFormat(trackId);
             String mime = format.getString(android.media.MediaFormat.KEY_MIME);
             Log.d(TAG, "track "+ trackId + ": " + mime);
             if ("video/scrambled".equals(mime) || "audio/scrambled".equals(mime)) {
-                if (drmInitData == null) {
-                    throw new IllegalArgumentException("found scrambled track without drmInitData!");
+                MediaExtractor.CasInfo casInfo = extractor.getCasInfo(trackId);
+                if (casInfo != null) {
+                    mMediaCas = new MediaCas(casInfo.getSystemId());
+                    mDescrambler = new MediaDescrambler(casInfo.getSystemId());
+                    mMediaCas.provision(sProvisionStr);
+                    extractor.setMediaCas(mMediaCas);
                 }
-                android.media.DrmInitData.SchemeInitData schemeInitData =
-                        drmInitData.get(new UUID(0, trackId));
-                int CA_system_id = (schemeInitData.data[0] & 0xff)
-                                | ((schemeInitData.data[1] & 0xff) << 8);
-                mMediaCas = new MediaCas(CA_system_id);
-                mDescrambler = new MediaDescrambler(CA_system_id);
-                mMediaCas.provision(sProvisionStr);
-                extractor.setMediaCas(mMediaCas);
             }
         }
     }
@@ -550,12 +542,12 @@
         }
 
         if (mMediaCas != null) {
-            mMediaCas.release();
+            mMediaCas.close();
             mMediaCas = null;
         }
 
         if (mDescrambler != null) {
-            mDescrambler.release();
+            mDescrambler.close();
             mDescrambler = null;
         }
 
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecTest.java b/tests/tests/media/src/android/media/cts/MediaCodecTest.java
index 9b941a2..56cbc93 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecTest.java
@@ -32,10 +32,10 @@
 import android.media.MediaFormat;
 import android.media.MediaCodecInfo.CodecCapabilities;
 import android.media.MediaCodecInfo.CodecProfileLevel;
-import android.media.MediaMetricsSet;
 import android.opengl.GLES20;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.os.PersistableBundle;
 import android.support.test.filters.SmallTest;
 import android.platform.test.annotations.RequiresDevice;
 import android.test.AndroidTestCase;
@@ -919,17 +919,17 @@
                 // good
             }
 
-            MediaMetricsSet metricsSet = encoder.getMetrics();
-            if (metricsSet == null) {
+            PersistableBundle metrics = encoder.getMetrics();
+            if (metrics == null) {
                 fail("getMetrics() returns null");
-            } else if (metricsSet.isEmpty()) {
+            } else if (metrics.isEmpty()) {
                 fail("getMetrics() returns empty results");
             }
-            int encoding = metricsSet.getInt(MediaMetricsSet.MediaCodec.KEY_ENCODER, -1);
+            int encoding = metrics.getInt(MediaCodec.MetricsConstants.ENCODER, -1);
             if (encoding != 1) {
                 fail("getMetrics() returns bad encoder value " + encoding);
             }
-            String theCodec = metricsSet.getString(MediaMetricsSet.MediaCodec.KEY_CODEC, null);
+            String theCodec = metrics.getString(MediaCodec.MetricsConstants.CODEC, null);
             if (theCodec == null) {
                 fail("getMetrics() returns null codec value ");
             }
@@ -989,17 +989,17 @@
                 // good
             }
 
-            MediaMetricsSet metricsSet = encoder.getMetrics();
-            if (metricsSet == null) {
+            PersistableBundle metrics = encoder.getMetrics();
+            if (metrics == null) {
                 fail("getMetrics() returns null");
-            } else if (metricsSet.isEmpty()) {
+            } else if (metrics.isEmpty()) {
                 fail("getMetrics() returns empty results");
             }
-            int encoding = metricsSet.getInt(MediaMetricsSet.MediaCodec.KEY_ENCODER, -1);
+            int encoding = metrics.getInt(MediaCodec.MetricsConstants.ENCODER, -1);
             if (encoding != 1) {
                 fail("getMetrics() returns bad encoder value " + encoding);
             }
-            String theCodec = metricsSet.getString(MediaMetricsSet.MediaCodec.KEY_CODEC, null);
+            String theCodec = metrics.getString(MediaCodec.MetricsConstants.CODEC, null);
             if (theCodec == null) {
                 fail("getMetrics() returns null codec value ");
             }
@@ -1050,17 +1050,17 @@
                         throw new RuntimeException("decoder does not generate non-empty output.");
                     }
 
-                    MediaMetricsSet metricsSet = mediaCodec.getMetrics();
-                    if (metricsSet == null) {
+                    PersistableBundle metrics = mediaCodec.getMetrics();
+                    if (metrics == null) {
                         fail("getMetrics() returns null");
-                    } else if (metricsSet.isEmpty()) {
+                    } else if (metrics.isEmpty()) {
                         fail("getMetrics() returns empty results");
                     }
-                    int encoder = metricsSet.getInt(MediaMetricsSet.MediaCodec.KEY_ENCODER, -1);
+                    int encoder = metrics.getInt(MediaCodec.MetricsConstants.ENCODER, -1);
                     if (encoder != 0) {
                         fail("getMetrics() returns bad encoder value " + encoder);
                     }
-                    String theCodec = metricsSet.getString(MediaMetricsSet.MediaCodec.KEY_CODEC, null);
+                    String theCodec = metrics.getString(MediaCodec.MetricsConstants.CODEC, null);
                     if (theCodec == null) {
                         fail("getMetrics() returns null codec value ");
                     }
@@ -1071,17 +1071,17 @@
                     mediaCodec.flush();
 
                     completed.set(runDecodeTillFirstOutput(mediaCodec, mediaExtractor));
-                    metricsSet = mediaCodec.getMetrics();
-                    if (metricsSet == null) {
+                    metrics = mediaCodec.getMetrics();
+                    if (metrics == null) {
                         fail("getMetrics() returns null");
-                    } else if (metricsSet.isEmpty()) {
+                    } else if (metrics.isEmpty()) {
                         fail("getMetrics() returns empty results");
                     }
-                    int encoding = metricsSet.getInt(MediaMetricsSet.MediaCodec.KEY_ENCODER, -1);
+                    int encoding = metrics.getInt(MediaCodec.MetricsConstants.ENCODER, -1);
                     if (encoding != 0) {
                         fail("getMetrics() returns bad encoder value " + encoding);
                     }
-                    String theCodec2 = metricsSet.getString(MediaMetricsSet.MediaCodec.KEY_CODEC, null);
+                    String theCodec2 = metrics.getString(MediaCodec.MetricsConstants.CODEC, null);
                     if (theCodec2 == null) {
                         fail("getMetrics() returns null codec value ");
                     }
@@ -1092,17 +1092,17 @@
                     if (mediaCodec != null) {
                         mediaCodec.stop();
 
-                        MediaMetricsSet metricsSet = mediaCodec.getMetrics();
-                        if (metricsSet == null) {
+                        PersistableBundle metrics = mediaCodec.getMetrics();
+                        if (metrics == null) {
                             fail("getMetrics() returns null");
-                        } else if (metricsSet.isEmpty()) {
+                        } else if (metrics.isEmpty()) {
                             fail("getMetrics() returns empty results");
                         }
-                        int encoder = metricsSet.getInt(MediaMetricsSet.MediaCodec.KEY_ENCODER, -1);
+                        int encoder = metrics.getInt(MediaCodec.MetricsConstants.ENCODER, -1);
                         if (encoder != 0) {
                             fail("getMetrics() returns bad encoder value " + encoder);
                         }
-                        String theCodec = metricsSet.getString(MediaMetricsSet.MediaCodec.KEY_CODEC, null);
+                        String theCodec = metrics.getString(MediaCodec.MetricsConstants.CODEC, null);
                         if (theCodec == null) {
                             fail("getMetrics() returns null codec value ");
                         }
@@ -1166,14 +1166,14 @@
             }
             assertTrue("Wrong output buffer index", outputBufferIndex >= 0);
 
-            MediaMetricsSet metricsSet = mediaCodec.getMetrics();
-            Log.d(TAG, "getMetrics after first buffer metricsSet says: " + metricsSet);
+            PersistableBundle metrics = mediaCodec.getMetrics();
+            Log.d(TAG, "getMetrics after first buffer metrics says: " + metrics);
 
-            int encoder = metricsSet.getInt(MediaMetricsSet.MediaCodec.KEY_ENCODER, -1);
+            int encoder = metrics.getInt(MediaCodec.MetricsConstants.ENCODER, -1);
             if (encoder != 0) {
                 fail("getMetrics() returns bad encoder value " + encoder);
             }
-            String theCodec = metricsSet.getString(MediaMetricsSet.MediaCodec.KEY_CODEC, null);
+            String theCodec = metrics.getString(MediaCodec.MetricsConstants.CODEC, null);
             if (theCodec == null) {
                 fail("getMetrics() returns null codec value ");
             }
diff --git a/tests/tests/media/src/android/media/cts/MediaControllerTest.java b/tests/tests/media/src/android/media/cts/MediaControllerTest.java
index 9aaf1aa..17588ee 100644
--- a/tests/tests/media/src/android/media/cts/MediaControllerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaControllerTest.java
@@ -19,11 +19,8 @@
 import android.media.AudioManager;
 import android.media.Rating;
 import android.media.VolumeProvider;
-import android.media.MediaDescription;
 import android.media.session.MediaController;
 import android.media.session.MediaSession;
-import android.media.session.MediaSession.QueueItem;
-import android.media.session.PlaybackState;
 import android.media.session.PlaybackState.CustomAction;
 import android.net.Uri;
 import android.os.Bundle;
@@ -53,7 +50,6 @@
         super.setUp();
         mSession = new MediaSession(getContext(), SESSION_TAG);
         mSession.setCallback(mCallback, mHandler);
-        mSession.setFlags(MediaSession.FLAG_HANDLES_QUEUE_COMMANDS);
         mController = mSession.getController();
     }
 
@@ -88,53 +84,6 @@
         }
     }
 
-    public void testAddRemoveQueueItems() throws Exception {
-        final String mediaId = "media_id";
-        final String mediaTitle = "media_title";
-        MediaDescription itemDescription = new MediaDescription.Builder()
-                .setMediaId(mediaId).setTitle(mediaTitle).build();
-        final MediaSession.Callback callback = (MediaSession.Callback) mCallback;
-
-        synchronized (mWaitLock) {
-            mCallback.reset();
-            mController.addQueueItem(itemDescription);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnAddQueueItemCalled);
-            assertEquals(-1, mCallback.mQueueIndex);
-            assertEquals(mediaId, mCallback.mQueueDescription.getMediaId());
-            assertEquals(mediaTitle, mCallback.mQueueDescription.getTitle());
-            // just call the callback once directly so it's marked as tested
-            callback.onAddQueueItem(mCallback.mQueueDescription);
-
-            mCallback.reset();
-            mController.addQueueItem(itemDescription, 0);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnAddQueueItemAtCalled);
-            assertEquals(0, mCallback.mQueueIndex);
-            assertEquals(mediaId, mCallback.mQueueDescription.getMediaId());
-            assertEquals(mediaTitle, mCallback.mQueueDescription.getTitle());
-            // just call the callback once directly so it's marked as tested
-            callback.onAddQueueItem(mCallback.mQueueDescription, mCallback.mQueueIndex);
-
-            mCallback.reset();
-            mController.removeQueueItemAt(0);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnRemoveQueueItemAtCalled);
-            assertEquals(0, mCallback.mQueueIndex);
-            // just call the callback once directly so it's marked as tested
-            callback.onRemoveQueueItemAt(mCallback.mQueueIndex);
-
-            mCallback.reset();
-            mController.removeQueueItem(itemDescription);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnRemoveQueueItemCalled);
-            assertEquals(mediaId, mCallback.mQueueDescription.getMediaId());
-            assertEquals(mediaTitle, mCallback.mQueueDescription.getTitle());
-            // just call the callback once directly so it's marked as tested
-            callback.onRemoveQueueItem(mCallback.mQueueDescription);
-        }
-    }
-
     public void testVolumeControl() throws Exception {
         VolumeProvider vp = new VolumeProvider(VolumeProvider.VOLUME_CONTROL_ABSOLUTE, 11, 5) {
             @Override
@@ -346,26 +295,6 @@
             assertTrue(mCallback.mOnPrepareFromUriCalled);
             assertEquals(uri, mCallback.mUri);
             assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
-            // just call the callback once directly so it's marked as tested
-            callback.onPrepareFromUri(mCallback.mUri, mCallback.mExtras);
-
-            mCallback.reset();
-            final int repeatMode = PlaybackState.REPEAT_MODE_ALL;
-            controls.setRepeatMode(repeatMode);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSetRepeatModeCalled);
-            assertEquals(repeatMode, mCallback.mRepeatMode);
-            // just call the callback once directly so it's marked as tested
-            callback.onSetRepeatMode(mCallback.mRepeatMode);
-
-            mCallback.reset();
-            final boolean shuffleModeEnabled = true;
-            controls.setShuffleModeEnabled(shuffleModeEnabled);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnSetShuffleModeEnabledCalled);
-            assertEquals(shuffleModeEnabled, mCallback.mShuffleModeEnabled);
-            // just call the callback once directly so it's marked as tested
-            callback.onSetShuffleModeEnabled(mCallback.mShuffleModeEnabled);
         }
     }
 
@@ -389,8 +318,6 @@
     private class MediaSessionCallback extends MediaSession.Callback {
         private long mSeekPosition;
         private long mQueueItemId;
-        private int mQueueIndex;
-        private MediaDescription mQueueDescription;
         private Rating mRating;
         private String mMediaId;
         private String mQuery;
@@ -399,8 +326,6 @@
         private String mCommand;
         private Bundle mExtras;
         private ResultReceiver mCommandCallback;
-        private int mRepeatMode;
-        private boolean mShuffleModeEnabled;
 
         private boolean mOnPlayCalled;
         private boolean mOnPauseCalled;
@@ -421,18 +346,10 @@
         private boolean mOnPrepareFromMediaIdCalled;
         private boolean mOnPrepareFromSearchCalled;
         private boolean mOnPrepareFromUriCalled;
-        private boolean mOnSetRepeatModeCalled;
-        private boolean mOnSetShuffleModeEnabledCalled;
-        private boolean mOnAddQueueItemCalled;
-        private boolean mOnAddQueueItemAtCalled;
-        private boolean mOnRemoveQueueItemCalled;
-        private boolean mOnRemoveQueueItemAtCalled;
 
         public void reset() {
             mSeekPosition = -1;
             mQueueItemId = -1;
-            mQueueIndex = -1;
-            mQueueDescription = null;
             mRating = null;
             mMediaId = null;
             mQuery = null;
@@ -441,8 +358,6 @@
             mExtras = null;
             mCommand = null;
             mCommandCallback = null;
-            mShuffleModeEnabled = false;
-            mRepeatMode = PlaybackState.REPEAT_MODE_NONE;
 
             mOnPlayCalled = false;
             mOnPauseCalled = false;
@@ -463,12 +378,6 @@
             mOnPrepareFromMediaIdCalled = false;
             mOnPrepareFromSearchCalled = false;
             mOnPrepareFromUriCalled = false;
-            mOnSetRepeatModeCalled = false;
-            mOnSetShuffleModeEnabledCalled = false;
-            mOnAddQueueItemCalled = false;
-            mOnAddQueueItemAtCalled = false;
-            mOnRemoveQueueItemCalled = false;
-            mOnRemoveQueueItemAtCalled = false;
         }
 
         @Override
@@ -642,60 +551,5 @@
                 mWaitLock.notify();
             }
         }
-
-        @Override
-        public void onSetRepeatMode(int repeatMode) {
-            synchronized (mWaitLock) {
-                mOnSetRepeatModeCalled = true;
-                mRepeatMode = repeatMode;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onSetShuffleModeEnabled(boolean enabled) {
-            synchronized (mWaitLock) {
-                mOnSetShuffleModeEnabledCalled = true;
-                mShuffleModeEnabled = enabled;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onAddQueueItem(MediaDescription description) {
-            synchronized (mWaitLock) {
-                mOnAddQueueItemCalled = true;
-                mQueueDescription = description;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onAddQueueItem(MediaDescription description, int index) {
-            synchronized (mWaitLock) {
-                mOnAddQueueItemAtCalled = true;
-                mQueueIndex = index;
-                mQueueDescription = description;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onRemoveQueueItem(MediaDescription description) {
-            synchronized (mWaitLock) {
-                mOnRemoveQueueItemCalled = true;
-                mQueueDescription = description;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onRemoveQueueItemAt(int index) {
-            synchronized (mWaitLock) {
-                mOnRemoveQueueItemAtCalled = true;
-                mQueueIndex = index;
-                mWaitLock.notify();
-            }
-        }
     }
 }
diff --git a/tests/tests/media/src/android/media/cts/MediaExtractorTest.java b/tests/tests/media/src/android/media/cts/MediaExtractorTest.java
index 7248c7d..b6f34f4 100644
--- a/tests/tests/media/src/android/media/cts/MediaExtractorTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaExtractorTest.java
@@ -17,12 +17,12 @@
 package android.media.cts;
 
 import android.media.cts.R;
-import android.media.MediaMetricsSet;
 
 import android.content.res.AssetFileDescriptor;
 import android.content.res.Resources;
 import android.media.MediaDataSource;
 import android.media.MediaExtractor;
+import android.os.PersistableBundle;
 import android.test.AndroidTestCase;
 
 import java.io.IOException;
@@ -110,12 +110,12 @@
         }
 
         // verify some getMetrics() behaviors while we're here.
-        MediaMetricsSet metricsSet = mExtractor.getMetrics();
-        if (metricsSet == null) {
+        PersistableBundle metrics = mExtractor.getMetrics();
+        if (metrics == null) {
             fail("getMetrics() returns no data");
         } else {
             // ensure existence of some known fields
-            int tracks = metricsSet.getInt(MediaMetricsSet.MediaExtractor.KEY_TRACKS, -1);
+            int tracks = metrics.getInt(MediaExtractor.MetricsConstants.TRACKS, -1);
             if (tracks != trackCount) {
                 fail("getMetrics() trackCount expect " + trackCount + " got " + tracks);
             }
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java b/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
index 2431bf2..82b992d 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
@@ -20,8 +20,8 @@
 import android.content.res.AssetFileDescriptor;
 import android.content.res.Resources;
 import android.media.MediaPlayer;
-import android.media.MediaMetricsSet;
 import android.net.Uri;
+import android.os.PersistableBundle;
 import android.test.ActivityInstrumentationTestCase2;
 
 import com.android.compatibility.common.util.MediaUtils;
@@ -324,15 +324,15 @@
         }
 
         // validate a few MediaMetrics.
-        MediaMetricsSet metricsSet = mMediaPlayer.getMetrics();
-        if (metricsSet == null) {
+        PersistableBundle metrics = mMediaPlayer.getMetrics();
+        if (metrics == null) {
             fail("MediaPlayer.getMetrics() returned null metrics");
-        } else if (metricsSet.isEmpty()) {
+        } else if (metrics.isEmpty()) {
             fail("MediaPlayer.getMetrics() returned empty metrics");
         } else {
 
-            int size = metricsSet.size();
-            Set<String> keys = metricsSet.keySet();
+            int size = metrics.size();
+            Set<String> keys = metrics.keySet();
 
             if (keys == null) {
                 fail("MediaMetricsSet returned no keys");
@@ -341,22 +341,22 @@
             }
 
             // we played something; so one of these should be non-null
-            String vmime = metricsSet.getString(MediaMetricsSet.MediaPlayer.KEY_MIME_VIDEO, null);
-            String amime = metricsSet.getString(MediaMetricsSet.MediaPlayer.KEY_MIME_AUDIO, null);
+            String vmime = metrics.getString(MediaPlayer.MetricsConstants.MIME_TYPE_VIDEO, null);
+            String amime = metrics.getString(MediaPlayer.MetricsConstants.MIME_TYPE_AUDIO, null);
             if (vmime == null && amime == null) {
                 fail("getMetrics() returned neither video nor audio mime value");
             }
 
-            long duration = metricsSet.getLong(MediaMetricsSet.MediaPlayer.KEY_DURATION, -2);
+            long duration = metrics.getLong(MediaPlayer.MetricsConstants.DURATION, -2);
             if (duration == -2) {
                 fail("getMetrics() didn't return a duration");
             }
-            long playing = metricsSet.getLong(MediaMetricsSet.MediaPlayer.KEY_PLAYING, -2);
+            long playing = metrics.getLong(MediaPlayer.MetricsConstants.PLAYING, -2);
             if (playing == -2) {
                 fail("getMetrics() didn't return a playing time");
             }
-            if (!keys.contains(MediaMetricsSet.MediaPlayer.KEY_PLAYING)) {
-                fail("MediaMetricsSet.keys() missing: " + MediaMetricsSet.MediaPlayer.KEY_PLAYING);
+            if (!keys.contains(MediaPlayer.MetricsConstants.PLAYING)) {
+                fail("MediaMetricsSet.keys() missing: " + MediaPlayer.MetricsConstants.PLAYING);
             }
         }
 
diff --git a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
index fbf51ca..d3c392c 100644
--- a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
@@ -30,10 +30,10 @@
 import android.media.MediaRecorder.OnErrorListener;
 import android.media.MediaRecorder.OnInfoListener;
 import android.media.MediaMetadataRetriever;
-import android.media.MediaMetricsSet;
 import android.os.ConditionVariable;
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
+import android.os.PersistableBundle;
 import android.support.test.filters.SmallTest;
 import android.platform.test.annotations.RequiresDevice;
 import android.test.ActivityInstrumentationTestCase2;
@@ -230,14 +230,14 @@
 
 
         // verify some getMetrics() behaviors while we're here.
-        MediaMetricsSet metricsSet = mMediaRecorder.getMetrics();
-        if (metricsSet == null) {
+        PersistableBundle metrics = mMediaRecorder.getMetrics();
+        if (metrics == null) {
             fail("MediaRecorder.getMetrics() returned null metrics");
-        } else if (metricsSet.isEmpty()) {
+        } else if (metrics.isEmpty()) {
             fail("MediaRecorder.getMetrics() returned empty metrics");
         } else {
-            int size = metricsSet.size();
-            Set<String> keys = metricsSet.keySet();
+            int size = metrics.size();
+            Set<String> keys = metrics.keySet();
 
             if (size == 0) {
                 fail("MediaRecorder.getMetrics().size() reports empty record");
@@ -250,14 +250,14 @@
             }
 
             // ensure existence of some known fields
-            int videoBitRate = metricsSet.getInt(MediaMetricsSet.MediaRecorder.KEY_VIDEO_BITRATE, -1);
+            int videoBitRate = metrics.getInt(MediaRecorder.MetricsConstants.VIDEO_BITRATE, -1);
             if (videoBitRate != VIDEO_BIT_RATE_IN_BPS) {
                 fail("getMetrics() videoEncodeBitrate set " +
                      VIDEO_BIT_RATE_IN_BPS + " got " + videoBitRate);
             }
 
             // careful when comparing floating point numbers
-            double captureFrameRate = metricsSet.getDouble(MediaMetricsSet.MediaRecorder.KEY_CAPTURE_FPS, -1);
+            double captureFrameRate = metrics.getDouble(MediaRecorder.MetricsConstants.CAPTURE_FPS, -1);
             if (captureFrameRate < 0) {
                 fail("getMetrics() capture framerate reports " + captureFrameRate);
             }
@@ -304,14 +304,14 @@
         Thread.sleep(RECORD_TIME_MS);
 
         // verify some getMetrics() behaviors while we're here.
-        MediaMetricsSet metricsSet = mMediaRecorder.getMetrics();
-        if (metricsSet == null) {
+        PersistableBundle metrics = mMediaRecorder.getMetrics();
+        if (metrics == null) {
             fail("MediaRecorder.getMetrics() returned null metrics");
-        } else if (metricsSet.isEmpty()) {
+        } else if (metrics.isEmpty()) {
             fail("MediaRecorder.getMetrics() returned empty metrics");
         } else {
-            int size = metricsSet.size();
-            Set<String> keys = metricsSet.keySet();
+            int size = metrics.size();
+            Set<String> keys = metrics.keySet();
 
             if (size == 0) {
                 fail("MediaRecorder.getMetrics().size() reports empty record");
@@ -324,14 +324,14 @@
             }
 
             // ensure existence of some known fields
-            int videoBitRate = metricsSet.getInt(MediaMetricsSet.MediaRecorder.KEY_VIDEO_BITRATE, -1);
+            int videoBitRate = metrics.getInt(MediaRecorder.MetricsConstants.VIDEO_BITRATE, -1);
             if (videoBitRate != VIDEO_BIT_RATE_IN_BPS) {
                 fail("getMetrics() videoEncodeBitrate set " +
                      VIDEO_BIT_RATE_IN_BPS + " got " + videoBitRate);
             }
 
             // careful when comparing floating point numbers
-            double captureFrameRate = metricsSet.getDouble(MediaMetricsSet.MediaRecorder.KEY_CAPTURE_FPS, -1);
+            double captureFrameRate = metrics.getDouble(MediaRecorder.MetricsConstants.CAPTURE_FPS, -1);
             if (captureFrameRate < 0) {
                 fail("getMetrics() capture framerate reports " + captureFrameRate);
             }
@@ -520,6 +520,19 @@
         fos.close();
     }
 
+    public void testSetOutputFile() throws Exception {
+        if (!hasCamera()) {
+            return;
+        }
+        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
+        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
+        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
+        mMediaRecorder.setPreviewDisplay(mActivity.getSurfaceHolder().getSurface());
+        mMediaRecorder.setOutputFile(mOutFile);
+        long maxFileSize = MAX_FILE_SIZE * 10;
+        recordMedia(maxFileSize, mOutFile);
+    }
+
     public void testRecordingAudioInRawFormats() throws Exception {
         int testsRun = 0;
         if (hasAmrNb()) {
@@ -771,7 +784,8 @@
                     } else if (mFileIndex < 6) {
                         try {
                             String path = OUTPUT_PATH + mFileIndex;
-                            mMediaRecorder.setNextOutputFile(path);
+                            File nextFile = new File(path);
+                            mMediaRecorder.setNextOutputFile(nextFile);
                             recordFileList.add(path);
                             mFileIndex++;
                         } catch (IOException e) {
diff --git a/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java b/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java
index 50b3033..07f63da 100644
--- a/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java
@@ -149,6 +149,9 @@
         session.setPlaybackState(state);
         session.setActive(true);
 
+        // A media playback is also needed to receive media key events.
+        Utils.assertMediaPlaybackStarted(getInstrumentation().getTargetContext());
+
         // Ensure that the listener is called for media key event,
         // and any other media sessions don't get the key.
         MediaKeyListener listener = new MediaKeyListener(2, true, handler);
diff --git a/tests/tests/media/src/android/media/cts/MediaSessionTest.java b/tests/tests/media/src/android/media/cts/MediaSessionTest.java
index b84bf1c..5f13a2e 100644
--- a/tests/tests/media/src/android/media/cts/MediaSessionTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaSessionTest.java
@@ -222,28 +222,6 @@
             mSession.setSessionActivity(pi);
             assertEquals(pi, controller.getSessionActivity());
 
-            // test setRepeatMode
-            mCallback.resetLocked();
-            final int repeatMode = PlaybackState.REPEAT_MODE_ALL;
-            mSession.setRepeatMode(repeatMode);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnRepeatModeChangedCalled);
-            assertEquals(repeatMode, mCallback.mRepeatMode);
-            assertEquals(repeatMode, controller.getRepeatMode());
-            // just call the callback once directly so it's marked as tested
-            callback.onRepeatModeChanged(mCallback.mRepeatMode);
-
-            // test setShuffleModeEnabled
-            mCallback.resetLocked();
-            final boolean shuffleModeEnabled = true;
-            mSession.setShuffleModeEnabled(shuffleModeEnabled);
-            mWaitLock.wait(TIME_OUT_MS);
-            assertTrue(mCallback.mOnShuffleModeChangedCalled);
-            assertEquals(shuffleModeEnabled, mCallback.mShuffleModeEnabled);
-            assertEquals(shuffleModeEnabled, controller.isShuffleModeEnabled());
-            // just call the callback once directly so it's marked as tested
-            callback.onShuffleModeChanged(mCallback.mShuffleModeEnabled);
-
             // test setActivity
             mSession.setActive(true);
             assertTrue(mSession.isActive());
@@ -354,6 +332,9 @@
                 .setState(PlaybackState.STATE_PLAYING, 0L, 0.0f).build();
         mSession.setPlaybackState(defaultState);
 
+        // A media playback is also needed to receive media key events.
+        Utils.assertMediaPlaybackStarted(getContext());
+
         synchronized (mWaitLock) {
             sessionCallback.reset();
             simulateMediaKeyInput(KeyEvent.KEYCODE_MEDIA_PLAY);
@@ -474,8 +455,6 @@
         private volatile boolean mOnAudioInfoChangedCalled;
         private volatile boolean mOnSessionDestroyedCalled;
         private volatile boolean mOnSessionEventCalled;
-        private volatile boolean mOnRepeatModeChangedCalled;
-        private volatile boolean mOnShuffleModeChangedCalled;
 
         private volatile PlaybackState mPlaybackState;
         private volatile MediaMetadata mMediaMetadata;
@@ -484,8 +463,6 @@
         private volatile String mEvent;
         private volatile Bundle mExtras;
         private volatile MediaController.PlaybackInfo mPlaybackInfo;
-        private volatile int mRepeatMode;
-        private volatile boolean mShuffleModeEnabled;
 
         public void resetLocked() {
             mOnPlaybackStateChangedCalled = false;
@@ -496,8 +473,6 @@
             mOnAudioInfoChangedCalled = false;
             mOnSessionDestroyedCalled = false;
             mOnSessionEventCalled = false;
-            mOnRepeatModeChangedCalled = false;
-            mOnShuffleModeChangedCalled = false;
 
             mPlaybackState = null;
             mMediaMetadata = null;
@@ -505,8 +480,6 @@
             mTitle = null;
             mExtras = null;
             mPlaybackInfo = null;
-            mRepeatMode = PlaybackState.REPEAT_MODE_NONE;
-            mShuffleModeEnabled = false;
         }
 
         @Override
@@ -580,24 +553,6 @@
                 mWaitLock.notify();
             }
         }
-
-        @Override
-        public void onRepeatModeChanged(int repeatMode) {
-            synchronized (mWaitLock) {
-                mOnRepeatModeChangedCalled = true;
-                mRepeatMode = repeatMode;
-                mWaitLock.notify();
-            }
-        }
-
-        @Override
-        public void onShuffleModeChanged(boolean enabled) {
-            synchronized (mWaitLock) {
-                mOnShuffleModeChangedCalled = true;
-                mShuffleModeEnabled = enabled;
-                mWaitLock.notify();
-            }
-        }
     }
 
     private class MediaSessionCallback extends MediaSession.Callback {
diff --git a/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java b/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java
index 96b33da..3dff5bf 100644
--- a/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java
@@ -99,12 +99,19 @@
         return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT);
     }
 
+    private boolean isTV() {
+        return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY);
+    }
+
     public void testConstructors() {
         new RingtoneManager(mActivity);
         new RingtoneManager(mContext);
     }
 
     public void testAccessMethods() {
+        if (isTV()) {
+            return;
+        }
         if (!hasAudioOutput()) {
             Log.i(TAG, "Skipping testAccessMethods(): device doesn't have audio output.");
             return;
@@ -145,6 +152,9 @@
     }
 
     public void testStopPreviousRingtone() {
+        if (isTV()) {
+            return;
+        }
         if (!hasAudioOutput()) {
             Log.i(TAG, "Skipping testStopPreviousRingtone(): device doesn't have audio output.");
             return;
diff --git a/tests/tests/media/src/android/media/cts/RingtoneTest.java b/tests/tests/media/src/android/media/cts/RingtoneTest.java
index 1477f3f..31ae5bb 100644
--- a/tests/tests/media/src/android/media/cts/RingtoneTest.java
+++ b/tests/tests/media/src/android/media/cts/RingtoneTest.java
@@ -107,10 +107,18 @@
 
     private boolean hasAudioOutput() {
         return getInstrumentation().getContext().getPackageManager()
-            .hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT);
+                .hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT);
+    }
+
+    private boolean isTV() {
+        return getInstrumentation().getContext().getPackageManager()
+                .hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY);
     }
 
     public void testRingtone() {
+        if (isTV()) {
+            return;
+        }
         if (!hasAudioOutput()) {
             Log.i(TAG, "Skipping testRingtone(): device doesn't have audio output.");
             return;
diff --git a/tests/tests/media/src/android/media/cts/StubMediaBrowserService.java b/tests/tests/media/src/android/media/cts/StubMediaBrowserService.java
index 888b3d4..9f90a75 100644
--- a/tests/tests/media/src/android/media/cts/StubMediaBrowserService.java
+++ b/tests/tests/media/src/android/media/cts/StubMediaBrowserService.java
@@ -45,10 +45,6 @@
         MEDIA_ID_CHILDREN_DELAYED
     };
 
-    static final String SEARCH_QUERY = "test_media_children";
-    static final String SEARCH_QUERY_FOR_NO_RESULT = "query no result";
-    static final String SEARCH_QUERY_FOR_ERROR = "query for error";
-
     static StubMediaBrowserService sInstance;
 
     /* package private */ static MediaSession sSession;
@@ -76,8 +72,10 @@
     public void onLoadChildren(final String parentMediaId, final Result<List<MediaItem>> result) {
         List<MediaItem> mediaItems = new ArrayList<>();
         if (MEDIA_ID_ROOT.equals(parentMediaId)) {
+            Bundle rootHints = getBrowserRootHints();
             for (String id : MEDIA_ID_CHILDREN) {
-                mediaItems.add(createMediaItem(id));
+                mediaItems.add(new MediaItem(new MediaDescription.Builder()
+                        .setMediaId(id).setExtras(rootHints).build(), MediaItem.FLAG_BROWSABLE));
             }
             result.sendResult(mediaItems);
         } else if (MEDIA_ID_CHILDREN_DELAYED.equals(parentMediaId)) {
@@ -101,7 +99,9 @@
 
         for (String id : MEDIA_ID_CHILDREN) {
             if (id.equals(itemId)) {
-                result.sendResult(createMediaItem(id));
+                result.sendResult(new MediaItem(new MediaDescription.Builder()
+                        .setMediaId(id).setExtras(getBrowserRootHints()).build(),
+                                MediaItem.FLAG_BROWSABLE));
                 return;
             }
         }
@@ -109,27 +109,6 @@
         super.onLoadItem(itemId, result);
     }
 
-    @Override
-    public void onSearch(String query, Bundle extras, Result<List<MediaItem>> result) {
-        if (result == null) {
-            // called the callback to mark as tested
-            return;
-        }
-        if (SEARCH_QUERY_FOR_NO_RESULT.equals(query)) {
-            result.sendResult(Collections.<MediaItem>emptyList());
-        } else if (SEARCH_QUERY_FOR_ERROR.equals(query)) {
-            result.sendResult(null);
-        } else if (SEARCH_QUERY.equals(query)) {
-            List<MediaItem> items = new ArrayList<>();
-            for (String id : MEDIA_ID_CHILDREN) {
-                if (id.contains(query)) {
-                    items.add(createMediaItem(id));
-                }
-            }
-            result.sendResult(items);
-        }
-    }
-
     public void sendDelayedNotifyChildrenChanged() {
         if (mPendingLoadChildrenResult != null) {
             mPendingLoadChildrenResult.sendResult(Collections.<MediaItem>emptyList());
@@ -147,10 +126,4 @@
             mPendingLoadItemResult = null;
         }
     }
-
-    private MediaItem createMediaItem(String id) {
-        return new MediaItem(new MediaDescription.Builder()
-                .setMediaId(id).setExtras(getBrowserRootHints()).build(),
-                MediaItem.FLAG_BROWSABLE);
-    }
 }
diff --git a/tests/tests/media/src/android/media/cts/Utils.java b/tests/tests/media/src/android/media/cts/Utils.java
index e8ceeae..fb461fe 100644
--- a/tests/tests/media/src/android/media/cts/Utils.java
+++ b/tests/tests/media/src/android/media/cts/Utils.java
@@ -20,15 +20,28 @@
 import android.app.UiAutomation;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.media.AudioManager;
+import android.media.AudioPlaybackConfiguration;
+import android.media.MediaPlayer;
+import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.ParcelFileDescriptor;
 import android.provider.Settings;
 
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.List;
 import java.util.Scanner;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.Assert;
 
 public class Utils {
+    private static final String TAG = "CtsMediaTestUtil";
+    private static final int TEST_TIMING_TOLERANCE_MS = 50;
+
     public static void enableAppOps(String packageName, String operation,
             Instrumentation instrumentation) {
         setAppOps(packageName, operation, instrumentation, true);
@@ -113,4 +126,53 @@
         }
         uiAutomation.destroy();
     }
+
+    /**
+     * Assert that a media playback is started and an active {@link AudioPlaybackConfiguration}
+     * is created once. The playback will be stopped immediately after that.
+     * <p>For a media session to receive media button events, an actual playback is needed.
+     */
+    static void assertMediaPlaybackStarted(Context context) {
+        final AudioManager am = new AudioManager(context);
+        final HandlerThread handlerThread = new HandlerThread(TAG);
+        handlerThread.start();
+        final TestAudioPlaybackCallback callback = new TestAudioPlaybackCallback();
+        MediaPlayer mediaPlayer = null;
+
+        try {
+            final int activeConfigSizeBeforeStart = am.getActivePlaybackConfigurations().size();
+            final Handler handler = new Handler(handlerThread.getLooper());
+
+            am.registerAudioPlaybackCallback(callback, handler);
+            mediaPlayer = MediaPlayer.create(context, R.raw.sine1khzs40dblong);
+            mediaPlayer.start();
+            if (!callback.mCountDownLatch.await(TEST_TIMING_TOLERANCE_MS, TimeUnit.MILLISECONDS)
+                    || callback.mActiveConfigSize != activeConfigSizeBeforeStart + 1) {
+                Assert.fail("Failed to create an active AudioPlaybackConfiguration");
+            }
+        } catch (InterruptedException e) {
+            Assert.fail("Failed to create an active AudioPlaybackConfiguration");
+        } finally {
+            am.unregisterAudioPlaybackCallback(callback);
+            if (mediaPlayer != null) {
+                mediaPlayer.stop();
+                mediaPlayer.release();
+                mediaPlayer = null;
+            }
+            handlerThread.quitSafely();
+        }
+    }
+
+    private static class TestAudioPlaybackCallback extends AudioManager.AudioPlaybackCallback {
+        private final CountDownLatch mCountDownLatch = new CountDownLatch(1);
+        private int mActiveConfigSize;
+
+        @Override
+        public void onPlaybackConfigChanged(List<AudioPlaybackConfiguration> configs) {
+            // For non-framework apps, only anonymized active AudioPlaybackCallbacks will be
+            // notified.
+            mActiveConfigSize = configs.size();
+            mCountDownLatch.countDown();
+        }
+    }
 }
diff --git a/tests/tests/nativemedia/aaudio/Android.mk b/tests/tests/nativemedia/aaudio/Android.mk
index af46aee..e37df49 100644
--- a/tests/tests/nativemedia/aaudio/Android.mk
+++ b/tests/tests/nativemedia/aaudio/Android.mk
@@ -27,7 +27,9 @@
     frameworks/av/media/libaaudio/include
 
 LOCAL_SRC_FILES := \
-    src/test_aaudio.cpp
+    src/test_aaudio.cpp \
+    src/test_aaudio_misc.cpp \
+    src/test_aaudio_callback.cpp
 
 LOCAL_SHARED_LIBRARIES := \
     libaaudio \
diff --git a/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp b/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp
index 77c91e4..37b434e 100644
--- a/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp
+++ b/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp
@@ -21,17 +21,9 @@
 #include <utils/Log.h>
 
 #include <aaudio/AAudio.h>
-#include <aaudio/AAudioDefinitions.h>
+#include "test_aaudio.h"
 
-
-#define NANOS_PER_MICROSECOND ((int64_t)1000)
-#define NANOS_PER_MILLISECOND (NANOS_PER_MICROSECOND * 1000)
-#define MILLIS_PER_SECOND     1000
-#define NANOS_PER_SECOND      (NANOS_PER_MILLISECOND * MILLIS_PER_SECOND)
-
-#define DEFAULT_STATE_TIMEOUT  (500 * NANOS_PER_MILLISECOND)
-
-static int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC) {
+int64_t getNanoseconds(clockid_t clockId) {
     struct timespec time;
     int result = clock_gettime(clockId, &time);
     if (result < 0) {
@@ -136,10 +128,12 @@
 
     // Check to see what kind of stream we actually got.
     actualSampleRate = AAudioStream_getSampleRate(aaudioStream);
-    ASSERT_TRUE(actualSampleRate >= 44100 && actualSampleRate <= 96000);  // TODO what is range?
+    ASSERT_GE(actualSampleRate, 44100);
+    ASSERT_LE(actualSampleRate, 96000); // TODO what is min/max?
 
     actualSamplesPerFrame = AAudioStream_getSamplesPerFrame(aaudioStream);
-    ASSERT_TRUE(actualSamplesPerFrame >= 1 && actualSamplesPerFrame <= 16); // TODO what is max?
+    ASSERT_GE(actualSamplesPerFrame, 1);
+    ASSERT_LE(actualSamplesPerFrame, 16); // TODO what is min/max?
 
     actualSharingMode = AAudioStream_getSharingMode(aaudioStream);
     ASSERT_TRUE(actualSharingMode == AAUDIO_SHARING_MODE_EXCLUSIVE
@@ -151,7 +145,8 @@
     // ASSERT_NE(AAUDIO_DEVICE_UNSPECIFIED, AAudioStream_getDeviceId(aaudioStream));
 
     framesPerBurst = AAudioStream_getFramesPerBurst(aaudioStream);
-    ASSERT_TRUE(framesPerBurst >= 16 && framesPerBurst <= 1024); // TODO what is min/max?
+    ASSERT_GE(framesPerBurst, 16);
+    ASSERT_LE(framesPerBurst, 10000); // TODO what is min/max?
 
     // Allocate a buffer for the audio data.
     // TODO handle possibility of other data formats
@@ -270,10 +265,13 @@
     aaudioFramesRead = AAudioStream_getFramesRead(aaudioStream);
     EXPECT_EQ(aaudioFramesRead, aaudioFramesWritten);
 
+    sleep(1); // FIXME - The write returns 0 if we remove this sleep! Why?
+
     // The buffer should be empty after a flush so we should be able to write.
     framesWritten = AAudioStream_write(aaudioStream, data, framesPerBurst, timeoutNanos);
     // There should be some room for priming the buffer.
-    ASSERT_TRUE(framesWritten > 0 && framesWritten <= framesPerBurst);
+    ASSERT_GT(framesWritten, 0);
+    ASSERT_LE(framesWritten, framesPerBurst);
 
     EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
     free(data);
@@ -291,60 +289,6 @@
 }
 */
 
-#define AAUDIO_THREAD_ANSWER          1826375
-#define AAUDIO_THREAD_DURATION_MSEC       500
-
-static void *TestAAudioStreamThreadProc(void *arg) {
-    AAudioStream* aaudioStream = (AAudioStream*) reinterpret_cast<size_t>(arg);
-    aaudio_stream_state_t state;
-
-    // Use this to sleep by waiting for something that won't happen.
-    state = AAudioStream_getState(aaudioStream);
-    AAudioStream_waitForStateChange(aaudioStream, AAUDIO_STREAM_STATE_PAUSED, &state,
-            AAUDIO_THREAD_DURATION_MSEC * NANOS_PER_MILLISECOND);
-    return reinterpret_cast<void *>(AAUDIO_THREAD_ANSWER);
-}
-
-// Test creating a stream related thread.
-TEST(test_aaudio, aaudio_stream_thread_basic) {
-    AAudioStreamBuilder *aaudioBuilder = nullptr;
-    AAudioStream *aaudioStream = nullptr;
-    aaudio_result_t result = AAUDIO_OK;
-    void *threadResult;
-
-    // Use an AAudioStreamBuilder to define the stream.
-    result = AAudio_createStreamBuilder(&aaudioBuilder);
-    ASSERT_EQ(AAUDIO_OK, result);
-
-    // Create an AAudioStream using the Builder.
-    ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
-
-    // Start a thread.
-    ASSERT_EQ(AAUDIO_OK, AAudioStream_createThread(aaudioStream,
-            10 * NANOS_PER_MILLISECOND,
-            TestAAudioStreamThreadProc,
-            reinterpret_cast<void *>(aaudioStream)));
-    // Thread already started.
-    ASSERT_NE(AAUDIO_OK, AAudioStream_createThread(aaudioStream,   // should fail!
-            10 * NANOS_PER_MILLISECOND,
-            TestAAudioStreamThreadProc,
-            reinterpret_cast<void *>(aaudioStream)));
-
-    // Wait for the thread to finish.
-    ASSERT_EQ(AAUDIO_OK, AAudioStream_joinThread(aaudioStream,
-            &threadResult, 2 * AAUDIO_THREAD_DURATION_MSEC * NANOS_PER_MILLISECOND));
-    // The thread returns a special answer.
-    ASSERT_EQ(AAUDIO_THREAD_ANSWER, (int)reinterpret_cast<size_t>(threadResult));
-
-    // Thread should already be joined.
-    ASSERT_NE(AAUDIO_OK, AAudioStream_joinThread(aaudioStream,  // should fail!
-            &threadResult, 2 * AAUDIO_THREAD_DURATION_MSEC * NANOS_PER_MILLISECOND));
-
-    // Cleanup
-    EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(aaudioBuilder));
-    EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
-}
-
 int main(int argc, char **argv) {
     testing::InitGoogleTest(&argc, argv);
 
diff --git a/tests/tests/nativemedia/aaudio/src/test_aaudio.h b/tests/tests/nativemedia/aaudio/src/test_aaudio.h
new file mode 100644
index 0000000..dbb111d
--- /dev/null
+++ b/tests/tests/nativemedia/aaudio/src/test_aaudio.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 CTS_MEDIA_TEST_AAUDIO_H
+#define CTS_MEDIA_TEST_AAUDIO_H
+
+#define NANOS_PER_MICROSECOND ((int64_t)1000)
+#define NANOS_PER_MILLISECOND (NANOS_PER_MICROSECOND * 1000)
+#define MILLIS_PER_SECOND     1000
+#define NANOS_PER_SECOND      (NANOS_PER_MILLISECOND * MILLIS_PER_SECOND)
+
+#define DEFAULT_STATE_TIMEOUT  (500 * NANOS_PER_MILLISECOND)
+
+int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC);
+
+#endif //CTS_MEDIA_TEST_AAUDIO_H
diff --git a/tests/tests/nativemedia/aaudio/src/test_aaudio_callback.cpp b/tests/tests/nativemedia/aaudio/src/test_aaudio_callback.cpp
new file mode 100644
index 0000000..2ec1e1c
--- /dev/null
+++ b/tests/tests/nativemedia/aaudio/src/test_aaudio_callback.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "AAudioTest"
+
+#include <gtest/gtest.h>
+#include <utils/Log.h>
+
+#include <aaudio/AAudio.h>
+#include "test_aaudio.h"
+
+typedef struct AAudioCallbackTestData {
+    int32_t callbackCount;
+    int32_t expectedFramesPerCallback;
+    int32_t actualFramesPerCallback;
+} AAudioCallbackTestData;
+
+// Callback function that fills the audio output buffer.
+static aaudio_data_callback_result_t MyDataCallbackProc(
+        AAudioStream *stream,
+        void *userData,
+        void *audioData,
+        int32_t numFrames
+) {
+    AAudioCallbackTestData *myData = (AAudioCallbackTestData *) userData;
+
+    if (numFrames != myData->expectedFramesPerCallback) {
+        // record unexpected framecounts
+        myData->actualFramesPerCallback = numFrames;
+    } else if (myData->actualFramesPerCallback == 0) {
+        // record at least one frame count
+        myData->actualFramesPerCallback = numFrames;
+    }
+    int32_t samplesPerFrame = AAudioStream_getSamplesPerFrame(stream);
+    int32_t numSamples = samplesPerFrame * numFrames;
+    if (AAudioStream_getFormat(stream) == AAUDIO_FORMAT_PCM_I16) {
+        int16_t *shortData = (int16_t *) audioData;
+        for (int i = 0; i < numSamples; i++) *shortData++ = 0;
+    } else if (AAudioStream_getFormat(stream) == AAUDIO_FORMAT_PCM_FLOAT) {
+        float *floatData = (float *) audioData;
+        for (int i = 0; i < numSamples; i++) *floatData++ = 0.0f;
+    }
+    myData->callbackCount++;
+    return AAUDIO_CALLBACK_RESULT_CONTINUE;
+}
+
+// Test Writing to an AAudioStream using a Callback
+void runtest_aaudio_callback(aaudio_sharing_mode_t requestedSharingMode,
+                             int32_t framesPerDataCallback) {
+    AAudioCallbackTestData myTestData = { 0, 0, 0 };
+    const int32_t requestedSampleRate = 48000;
+    const int32_t requestedSamplesPerFrame = 2;
+    const aaudio_audio_format_t requestedDataFormat = AAUDIO_FORMAT_PCM_I16;
+
+    int32_t actualSampleRate = -1;
+    int32_t actualSamplesPerFrame = -1;
+    aaudio_audio_format_t actualDataFormat = AAUDIO_FORMAT_INVALID;
+    aaudio_sharing_mode_t actualSharingMode;
+    int32_t framesPerBurst = -1;
+    int32_t actualBufferSize = 0;
+    int32_t actualFramesPerDataCallback = 0;
+
+    aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNINITIALIZED;
+    AAudioStreamBuilder *builder = nullptr;
+    AAudioStream *stream = nullptr;
+
+    aaudio_result_t result = AAUDIO_OK;
+
+    // Use an AAudioStreamBuilder to define the stream.
+    result = AAudio_createStreamBuilder(&builder);
+    ASSERT_EQ(AAUDIO_OK, result);
+
+    // Request stream properties.
+    AAudioStreamBuilder_setDeviceId(builder, AAUDIO_DEVICE_UNSPECIFIED);
+    AAudioStreamBuilder_setDirection(builder, AAUDIO_DIRECTION_OUTPUT);
+    AAudioStreamBuilder_setSampleRate(builder, requestedSampleRate);
+    AAudioStreamBuilder_setSamplesPerFrame(builder, requestedSamplesPerFrame);
+    AAudioStreamBuilder_setFormat(builder, requestedDataFormat);
+    AAudioStreamBuilder_setSharingMode(builder, requestedSharingMode);
+    AAudioStreamBuilder_setBufferCapacityInFrames(builder, 2000);
+
+    AAudioStreamBuilder_setDataCallback(builder, MyDataCallbackProc, &myTestData);
+    if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
+        AAudioStreamBuilder_setFramesPerDataCallback(builder, framesPerDataCallback);
+    }
+
+    // Create an AAudioStream using the Builder.
+    ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(builder, &stream));
+    EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(builder));
+
+    EXPECT_EQ(AAUDIO_STREAM_STATE_OPEN, AAudioStream_getState(stream));
+    EXPECT_EQ(AAUDIO_DIRECTION_OUTPUT, AAudioStream_getDirection(stream));
+
+    // Check to see what kind of stream we actually got.
+    actualSampleRate = AAudioStream_getSampleRate(stream);
+    ASSERT_TRUE(actualSampleRate >= 44100 && actualSampleRate <= 96000);  // TODO what is range?
+
+    actualSamplesPerFrame = AAudioStream_getSamplesPerFrame(stream);
+    ASSERT_TRUE(actualSamplesPerFrame >= 1 && actualSamplesPerFrame <= 16); // TODO what is max?
+
+    actualSharingMode = AAudioStream_getSharingMode(stream);
+    ASSERT_TRUE(actualSharingMode == AAUDIO_SHARING_MODE_EXCLUSIVE
+                || actualSharingMode == AAUDIO_SHARING_MODE_SHARED);
+
+    actualDataFormat = AAudioStream_getFormat(stream);
+
+    // TODO test this on full build
+    // ASSERT_NE(AAUDIO_DEVICE_UNSPECIFIED, AAudioStream_getDeviceId(stream));
+
+    framesPerBurst = AAudioStream_getFramesPerBurst(stream);
+    ASSERT_TRUE(framesPerBurst >= 16 && framesPerBurst <= 1024); // TODO what is min/max?
+
+    actualFramesPerDataCallback = AAudioStream_getFramesPerDataCallback(stream);
+    if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
+        ASSERT_EQ(framesPerDataCallback, actualFramesPerDataCallback);
+    }
+
+    actualBufferSize = AAudioStream_getBufferSizeInFrames(stream);
+    actualBufferSize = AAudioStream_setBufferSizeInFrames(stream, actualBufferSize);
+    ASSERT_TRUE(actualBufferSize > 0);
+
+    // Start/stop more than once to see if it fails after the first time.
+    // Write some data and measure the rate to see if the timing is OK.
+    for (int loopIndex = 0; loopIndex < 2; loopIndex++) {
+        myTestData.callbackCount = 0;
+        myTestData.expectedFramesPerCallback = actualFramesPerDataCallback;
+
+        // Start and wait for server to respond.
+        ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(stream));
+        ASSERT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(stream,
+                                                             AAUDIO_STREAM_STATE_STARTING,
+                                                             &state,
+                                                             DEFAULT_STATE_TIMEOUT));
+        EXPECT_EQ(AAUDIO_STREAM_STATE_STARTED, state);
+
+        sleep(2);
+
+        // For more coverage, alternate pausing and stopping.
+        if ((loopIndex & 1) == 0) {
+            // Request async pause and wait for server to say that it has completed the request.
+            ASSERT_EQ(AAUDIO_OK, AAudioStream_requestPause(stream));
+            EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(stream,
+                                                                 AAUDIO_STREAM_STATE_PAUSING,
+                                                                 &state,
+                                                                 DEFAULT_STATE_TIMEOUT));
+            EXPECT_EQ(AAUDIO_STREAM_STATE_PAUSED, state);
+        } else {
+            // Request async stop and wait for server to say that it has completed the request.
+            ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStop(stream));
+            EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(stream,
+                                                                 AAUDIO_STREAM_STATE_STOPPING,
+                                                                 &state,
+                                                                 DEFAULT_STATE_TIMEOUT));
+            EXPECT_EQ(AAUDIO_STREAM_STATE_STOPPED, state);
+        }
+
+        int32_t oldCallbackCount = myTestData.callbackCount;
+        EXPECT_GT(oldCallbackCount, 10);
+        sleep(1);
+        EXPECT_EQ(oldCallbackCount, myTestData.callbackCount); // expect not advancing
+
+        if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
+            ASSERT_EQ(framesPerDataCallback, myTestData.actualFramesPerCallback);
+        }
+    }
+
+    EXPECT_EQ(AAUDIO_OK, AAudioStream_close(stream));
+}
+
+// Test Using an AAudioStream callback in SHARED mode.
+
+TEST(test_aaudio, aaudio_callback_shared_unspecified) {
+runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, AAUDIO_UNSPECIFIED);
+}
+
+TEST(test_aaudio, aaudio_callback_shared_109) {
+runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, 109); // arbitrary prime number < 192
+}
+
+TEST(test_aaudio, aaudio_callback_shared_223) {
+runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, 223); // arbitrary prime number > 192
+}
diff --git a/tests/tests/nativemedia/aaudio/src/test_aaudio_misc.cpp b/tests/tests/nativemedia/aaudio/src/test_aaudio_misc.cpp
new file mode 100644
index 0000000..a26f17a
--- /dev/null
+++ b/tests/tests/nativemedia/aaudio/src/test_aaudio_misc.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "AAudioTest"
+#include <utils/Log.h>
+
+#include <gtest/gtest.h>
+
+#include <aaudio/AAudio.h>
+
+// Make sure enums do not change value.
+TEST(test_aaudio_misc, aaudio_freeze_enums) {
+
+    ASSERT_EQ(0, AAUDIO_DIRECTION_OUTPUT);
+    ASSERT_EQ(1, AAUDIO_DIRECTION_INPUT);
+
+    ASSERT_EQ(-1, AAUDIO_FORMAT_INVALID);
+    ASSERT_EQ(0, AAUDIO_FORMAT_UNSPECIFIED);
+    ASSERT_EQ(1, AAUDIO_FORMAT_PCM_I16);
+    ASSERT_EQ(2, AAUDIO_FORMAT_PCM_FLOAT);
+    ASSERT_EQ(3, AAUDIO_FORMAT_PCM_I8_24);
+    ASSERT_EQ(4, AAUDIO_FORMAT_PCM_I32);
+
+    ASSERT_EQ(0, AAUDIO_OK);
+    ASSERT_EQ(-900, AAUDIO_ERROR_BASE);
+    ASSERT_EQ(-899, AAUDIO_ERROR_DISCONNECTED);
+    ASSERT_EQ(-898, AAUDIO_ERROR_ILLEGAL_ARGUMENT);
+    ASSERT_EQ(-897, AAUDIO_ERROR_INCOMPATIBLE);
+    ASSERT_EQ(-896, AAUDIO_ERROR_INTERNAL);
+    ASSERT_EQ(-895, AAUDIO_ERROR_INVALID_STATE);
+    ASSERT_EQ(-894, AAUDIO_ERROR_UNEXPECTED_STATE);
+    ASSERT_EQ(-893, AAUDIO_ERROR_UNEXPECTED_VALUE);
+    ASSERT_EQ(-892, AAUDIO_ERROR_INVALID_HANDLE);
+    ASSERT_EQ(-891, AAUDIO_ERROR_INVALID_QUERY);
+    ASSERT_EQ(-890, AAUDIO_ERROR_UNIMPLEMENTED);
+    ASSERT_EQ(-889, AAUDIO_ERROR_UNAVAILABLE);
+    ASSERT_EQ(-888, AAUDIO_ERROR_NO_FREE_HANDLES);
+    ASSERT_EQ(-887, AAUDIO_ERROR_NO_MEMORY);
+    ASSERT_EQ(-886, AAUDIO_ERROR_NULL);
+    ASSERT_EQ(-885, AAUDIO_ERROR_TIMEOUT);
+    ASSERT_EQ(-884, AAUDIO_ERROR_WOULD_BLOCK);
+    ASSERT_EQ(-883, AAUDIO_ERROR_INVALID_FORMAT);
+    ASSERT_EQ(-882, AAUDIO_ERROR_OUT_OF_RANGE);
+    ASSERT_EQ(-881, AAUDIO_ERROR_NO_SERVICE);
+
+    ASSERT_EQ(0, AAUDIO_STREAM_STATE_UNINITIALIZED);
+    ASSERT_EQ(1, AAUDIO_STREAM_STATE_UNKNOWN);
+    ASSERT_EQ(2, AAUDIO_STREAM_STATE_OPEN);
+    ASSERT_EQ(3, AAUDIO_STREAM_STATE_STARTING);
+    ASSERT_EQ(4, AAUDIO_STREAM_STATE_STARTED);
+    ASSERT_EQ(5, AAUDIO_STREAM_STATE_PAUSING);
+    ASSERT_EQ(6, AAUDIO_STREAM_STATE_PAUSED);
+    ASSERT_EQ(7, AAUDIO_STREAM_STATE_FLUSHING);
+    ASSERT_EQ(8, AAUDIO_STREAM_STATE_FLUSHED);
+    ASSERT_EQ(9, AAUDIO_STREAM_STATE_STOPPING);
+    ASSERT_EQ(10, AAUDIO_STREAM_STATE_STOPPED);
+    ASSERT_EQ(11, AAUDIO_STREAM_STATE_CLOSING);
+    ASSERT_EQ(12, AAUDIO_STREAM_STATE_CLOSED);
+
+    ASSERT_EQ(0, AAUDIO_SHARING_MODE_EXCLUSIVE);
+    ASSERT_EQ(1, AAUDIO_SHARING_MODE_SHARED);
+
+    ASSERT_EQ(0, AAUDIO_CALLBACK_RESULT_CONTINUE);
+    ASSERT_EQ(1, AAUDIO_CALLBACK_RESULT_STOP);
+}
diff --git a/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java
index 24871ca..83f087b 100644
--- a/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -45,12 +45,15 @@
 
 import com.android.internal.telephony.PhoneConstants;
 
+import java.io.File;
+import java.io.FileNotFoundException;
 import java.io.InputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.net.Socket;
 import java.net.InetSocketAddress;
 import java.util.HashMap;
+import java.util.Scanner;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
@@ -74,6 +77,17 @@
             "Host: " + TEST_HOST + "\r\n" +
             "Connection: keep-alive\r\n\r\n";
 
+    // Base path for IPv6 sysctls
+    private static final String IPV6_SYSCTL_DIR = "/proc/sys/net/ipv6/conf";
+
+    // Expected values for MIN|MAX_PLEN.
+    private static final int IPV6_WIFI_ACCEPT_RA_RT_INFO_MIN_PLEN = 48;
+    private static final int IPV6_WIFI_ACCEPT_RA_RT_INFO_MAX_PLEN = 64;
+
+    // Expected values for RFC 7559 router soliciations.
+    // Maximum number of router solicitations to send. -1 means no limit.
+    private static final int IPV6_WIFI_ROUTER_SOLICITATIONS = -1;
+
     // Action sent to ConnectivityActionReceiver when a network callback is sent via PendingIntent.
     private static final String NETWORK_CALLBACK_ACTION =
             "ConnectivityManagerTest.NetworkCallbackAction";
@@ -91,6 +105,7 @@
     private PackageManager mPackageManager;
     private final HashMap<Integer, NetworkConfig> mNetworks =
             new HashMap<Integer, NetworkConfig>();
+    boolean mWifiConnectAttempted;
 
     @Override
     protected void setUp() throws Exception {
@@ -99,6 +114,7 @@
         mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
         mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
         mPackageManager = mContext.getPackageManager();
+        mWifiConnectAttempted = false;
 
         // Get com.android.internal.R.array.networkAttributes
         int resId = mContext.getResources().getIdentifier("networkAttributes", "array", "android");
@@ -116,6 +132,27 @@
         }
     }
 
+    @Override
+    protected void tearDown() throws Exception {
+        // Return WiFi to its original disabled state after tests that explicitly connect.
+        if (mWifiConnectAttempted) {
+            disconnectFromWifi(null);
+        }
+    }
+
+    /**
+     * Make sure WiFi is connected to an access point if it is not already. If
+     * WiFi is enabled as a result of this function, it will be disabled
+     * automatically in tearDown().
+     */
+    private Network ensureWifiConnected() {
+        if (mWifiManager.isWifiEnabled()) {
+            return getWifiNetwork();
+        }
+        mWifiConnectAttempted = true;
+        return connectToWifi();
+    }
+
     public void testIsNetworkTypeValid() {
         assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE));
         assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_WIFI));
@@ -298,14 +335,10 @@
         final TestNetworkCallback defaultTrackingCallback = new TestNetworkCallback();
         mCm.registerDefaultNetworkCallback(defaultTrackingCallback);
 
-        final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled();
         Network wifiNetwork = null;
 
         try {
-            // Make sure WiFi is connected to an access point to start with.
-            if (!previousWifiEnabledState) {
-                connectToWifi();
-            }
+            ensureWifiConnected();
 
             // Now we should expect to get a network callback about availability of the wifi
             // network even if it was already connected as a state-based action when the callback
@@ -321,11 +354,6 @@
         } finally {
             mCm.unregisterNetworkCallback(callback);
             mCm.unregisterNetworkCallback(defaultTrackingCallback);
-
-            // Return WiFi to its original enabled/disabled state.
-            if (!previousWifiEnabledState) {
-                disconnectFromWifi(wifiNetwork);
-            }
         }
     }
 
@@ -357,13 +385,8 @@
         // We will register for a WIFI network being available or lost.
         mCm.registerNetworkCallback(makeWifiNetworkRequest(), pendingIntent);
 
-        final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled();
-
         try {
-            // Make sure WiFi is connected to an access point to start with.
-            if (!previousWifiEnabledState) {
-                connectToWifi();
-            }
+            ensureWifiConnected();
 
             // Now we expect to get the Intent delivered notifying of the availability of the wifi
             // network even if it was already connected as a state-based action when the callback
@@ -376,11 +399,6 @@
             mCm.unregisterNetworkCallback(pendingIntent);
             pendingIntent.cancel();
             mContext.unregisterReceiver(receiver);
-
-            // Return WiFi to its original enabled/disabled state.
-            if (!previousWifiEnabledState) {
-                disconnectFromWifi(null);
-            }
         }
     }
 
@@ -761,4 +779,42 @@
             fail("No exception thrown when restricted network requested.");
         } catch (SecurityException expected) {}
     }
+
+    private Scanner makeWifiSysctlScanner(String key) throws FileNotFoundException {
+        Network network = ensureWifiConnected();
+        String iface = mCm.getLinkProperties(network).getInterfaceName();
+        String path = IPV6_SYSCTL_DIR + "/" + iface + "/" + key;
+        return new Scanner(new File(path));
+    }
+
+    /** Verify that accept_ra_rt_info_min_plen exists and is set to the expected value */
+    public void testAcceptRaRtInfoMinPlen() throws Exception {
+        Scanner s = makeWifiSysctlScanner("accept_ra_rt_info_min_plen");
+        assertEquals(IPV6_WIFI_ACCEPT_RA_RT_INFO_MIN_PLEN, s.nextInt());
+    }
+
+    /** Verify that accept_ra_rt_info_max_plen exists and is set to the expected value */
+    public void testAcceptRaRtInfoMaxPlen() throws Exception {
+        Scanner s = makeWifiSysctlScanner("accept_ra_rt_info_max_plen");
+        assertEquals(IPV6_WIFI_ACCEPT_RA_RT_INFO_MAX_PLEN, s.nextInt());
+    }
+
+    /** Verify that router_solicitations exists and is set to the expected value */
+    public void testRouterSolicitations() throws Exception {
+        Scanner s = makeWifiSysctlScanner("router_solicitations");
+        assertEquals(IPV6_WIFI_ROUTER_SOLICITATIONS, s.nextInt());
+    }
+
+    /** Verify that router_solicitation_max_interval exists and is in an acceptable interval */
+    public void testRouterSolicitationMaxInterval() throws Exception {
+        Scanner s = makeWifiSysctlScanner("router_solicitation_max_interval");
+        int interval = s.nextInt();
+        // Verify we're in the interval [15 minutes, 60 minutes]. Lower values may adversely
+        // impact battery life and higher values can decrease the probability of detecting
+        // network changes.
+        final int lowerBoundSec = 15 * 60;
+        final int upperBoundSec = 60 * 60;
+        assertTrue(lowerBoundSec <= interval);
+        assertTrue(interval <= upperBoundSec);
+    }
 }
diff --git a/tests/tests/net/src/android/net/cts/IpSecManagerTest.java b/tests/tests/net/src/android/net/cts/IpSecManagerTest.java
index 93b5c44..39d683d 100644
--- a/tests/tests/net/src/android/net/cts/IpSecManagerTest.java
+++ b/tests/tests/net/src/android/net/cts/IpSecManagerTest.java
@@ -85,8 +85,7 @@
             randomSpi =
                     mISM.reserveSecurityParameterIndex(
                             IpSecTransform.DIRECTION_OUT,
-                            addr,
-                            IpSecManager.INVALID_SECURITY_PARAMETER_INDEX);
+                            addr);
             assertTrue(randomSpi.getSpi() != IpSecManager.INVALID_SECURITY_PARAMETER_INDEX);
 
             droidSpi =
@@ -121,8 +120,7 @@
         IpSecManager.SecurityParameterIndex outSpi =
                 mISM.reserveSecurityParameterIndex(
                         IpSecTransform.DIRECTION_OUT,
-                        local,
-                        IpSecManager.INVALID_SECURITY_PARAMETER_INDEX);
+                        local);
 
         IpSecManager.SecurityParameterIndex inSpi =
                 mISM.reserveSecurityParameterIndex(
@@ -133,21 +131,21 @@
                         .setSpi(IpSecTransform.DIRECTION_OUT, outSpi)
                         .setEncryption(
                                 IpSecTransform.DIRECTION_OUT,
-                                new IpSecAlgorithm(IpSecAlgorithm.ALGO_CRYPT_AES_CBC, CRYPT_KEY))
+                                new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY))
                         .setAuthentication(
                                 IpSecTransform.DIRECTION_OUT,
                                 new IpSecAlgorithm(
-                                        IpSecAlgorithm.ALGO_AUTH_HMAC_SHA256,
+                                        IpSecAlgorithm.AUTH_HMAC_SHA256,
                                         AUTH_KEY,
                                         AUTH_KEY.length * 8))
                         .setSpi(IpSecTransform.DIRECTION_IN, inSpi)
                         .setEncryption(
                                 IpSecTransform.DIRECTION_IN,
-                                new IpSecAlgorithm(IpSecAlgorithm.ALGO_CRYPT_AES_CBC, CRYPT_KEY))
+                                new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY))
                         .setAuthentication(
                                 IpSecTransform.DIRECTION_IN,
                                 new IpSecAlgorithm(
-                                        IpSecAlgorithm.ALGO_AUTH_HMAC_SHA256,
+                                        IpSecAlgorithm.AUTH_HMAC_SHA256,
                                         AUTH_KEY,
                                         CRYPT_KEY.length * 8))
                         .buildTransportModeTransform(local);
diff --git a/tests/tests/os/src/android/os/cts/AbiTest.java b/tests/tests/os/src/android/os/cts/AbiTest.java
index 49ff8aa..1765ae7 100644
--- a/tests/tests/os/src/android/os/cts/AbiTest.java
+++ b/tests/tests/os/src/android/os/cts/AbiTest.java
@@ -16,11 +16,14 @@
 
 package android.os.cts;
 
+import android.system.OsConstants;
+import android.system.ErrnoException;
 import android.util.ArraySet;
 
 import com.android.compatibility.common.util.ReadElf;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.Arrays;
 
 import junit.framework.TestCase;
@@ -74,6 +77,14 @@
                     elf = ReadElf.read(f);
                 } catch (IllegalArgumentException ignored) {
                     // If it's not actually an ELF file, we don't care.
+                } catch (IOException ex) {
+                    Throwable cause = ex.getCause();
+                    if (cause instanceof ErrnoException) {
+                        // if we are denied access to the file, ignore.
+                        if (((ErrnoException) cause).errno != OsConstants.EACCES) {
+                            throw ex;
+                        }
+                    }
                 } finally {
                     if (elf != null) {
                         elf.close();
diff --git a/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java b/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java
index 1db2d72..736e0f3 100644
--- a/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java
+++ b/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java
@@ -53,6 +53,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.SynchronousQueue;
 import junit.framework.AssertionFailedError;
@@ -256,6 +257,32 @@
         assertStorageVolumesEquals(primary, childVolume);
     }
 
+    private void assertNoUuid(File file) {
+        try {
+            final UUID uuid = mStorageManager.getUuidForPath(file);
+            fail("Unexpected UUID " + uuid + " for " + file);
+        } catch (IOException expected) {
+        }
+    }
+
+    public void testGetUuidForPath() throws Exception {
+        assertEquals(StorageManager.UUID_DEFAULT,
+                mStorageManager.getUuidForPath(Environment.getDataDirectory()));
+        assertEquals(StorageManager.UUID_DEFAULT,
+                mStorageManager.getUuidForPath(mContext.getDataDir()));
+
+        final UUID extUuid = mStorageManager
+                .getUuidForPath(Environment.getExternalStorageDirectory());
+        if (Environment.isExternalStorageEmulated()) {
+            assertEquals(StorageManager.UUID_DEFAULT, extUuid);
+        }
+
+        assertEquals(extUuid, mStorageManager.getUuidForPath(mContext.getExternalCacheDir()));
+
+        assertNoUuid(new File("/"));
+        assertNoUuid(new File("/proc/"));
+    }
+
     private static class TestProxyFileDescriptorCallback extends ProxyFileDescriptorCallback {
         final byte[] bytes;
         int fsyncCount;
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index 4e6b9ea..949e2c1 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -1511,6 +1511,16 @@
     <permission android:name="android.permission.DVB_DEVICE"
         android:protectionLevel="signature|privileged" />
 
+    <!-- @SystemApi Allows reading and enabling/disabling the OEM unlock allowed by carrier state
+         @hide <p>Not for use by third-party applications. -->
+    <permission android:name="android.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE"
+        android:protectionLevel="signature|privileged" />
+
+    <!-- @SystemApi Allows reading and enabling/disabling the OEM unlock allowed by user state
+         @hide <p>Not for use by third-party applications. -->
+    <permission android:name="android.permission.MANAGE_USER_OEM_UNLOCK_STATE"
+        android:protectionLevel="signature|privileged" />
+
     <!-- @SystemApi Allows reading the OEM unlock state
          @hide <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.READ_OEM_UNLOCK_STATE"
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStoreUiTest.java b/tests/tests/provider/src/android/provider/cts/MediaStoreUiTest.java
index e40f2ed..d8a80d2 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStoreUiTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStoreUiTest.java
@@ -131,6 +131,14 @@
         }
     }
 
+    private void maybeClick(UiSelector sel) {
+        try { mDevice.findObject(sel).click(); } catch (Throwable ignored) { }
+    }
+
+    private void maybeClick(BySelector sel) {
+        try { mDevice.findObject(sel).click(); } catch (Throwable ignored) { }
+    }
+
     /**
      * Verify that whoever handles {@link MediaStore#ACTION_IMAGE_CAPTURE} can
      * correctly write the contents into a passed {@code content://} Uri.
@@ -164,7 +172,7 @@
                 + pkg + " " + android.Manifest.permission.ACCESS_COARSE_LOCATION);
         getInstrumentation().getUiAutomation().executeShellCommand("pm grant "
                 + pkg + " " + android.Manifest.permission.ACCESS_FINE_LOCATION);
-        Thread.sleep(1000);
+        SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
 
         mActivity.startActivityForResult(intent, REQUEST_CODE);
         mDevice.waitForIdle();
@@ -184,15 +192,27 @@
         // Hrm, that didn't work; let's try an alternative approach of digging
         // around for a shutter button
         if (result == null) {
-            mDevice.findObject(new UiSelector().resourceId(pkg + ":id/shutter_button")).click();
+            maybeClick(new UiSelector().resourceId(pkg + ":id/shutter_button"));
             mDevice.waitForIdle();
             SystemClock.sleep(5 * DateUtils.SECOND_IN_MILLIS);
-            mDevice.findObject(new UiSelector().resourceId(pkg + ":id/shutter_button")).click();
+            maybeClick(new UiSelector().resourceId(pkg + ":id/shutter_button"));
             mDevice.waitForIdle();
+
+            result = mActivity.getResult(15, TimeUnit.SECONDS);
+            Log.d(TAG, "Second pass result was " + result);
         }
 
-        result = mActivity.getResult(15, TimeUnit.SECONDS);
-        Log.d(TAG, "Second pass result was " + result);
+        // Grr, let's try hunting around even more
+        if (result == null) {
+            maybeClick(By.pkg(pkg).descContains("Capture"));
+            mDevice.waitForIdle();
+            SystemClock.sleep(5 * DateUtils.SECOND_IN_MILLIS);
+            maybeClick(By.pkg(pkg).descContains("Done"));
+            mDevice.waitForIdle();
+
+            result = mActivity.getResult(15, TimeUnit.SECONDS);
+            Log.d(TAG, "Third pass result was " + result);
+        }
 
         assertNotNull("Expected to get a IMAGE_CAPTURE result; your camera app should "
                 + "respond to the CAMERA and DPAD_CENTER keycodes", result);
diff --git a/tests/tests/security/src/android/security/cts/SeccompTest.java b/tests/tests/security/src/android/security/cts/SeccompTest.java
index 44185bd..745aa87 100644
--- a/tests/tests/security/src/android/security/cts/SeccompTest.java
+++ b/tests/tests/security/src/android/security/cts/SeccompTest.java
@@ -67,6 +67,30 @@
         }
     }
 
+    public void testCTSSwapOnOffBlocked() {
+        if (CpuFeatures.isArm64Cpu()) {
+            testBlocked(224); // __NR_swapon
+            testBlocked(225); // __NR_swapoff
+        } else if (CpuFeatures.isArmCpu()) {
+            testBlocked(87);  // __NR_swapon
+            testBlocked(115); // __NR_swapoff
+        } else if (CpuFeatures.isX86_64Cpu()) {
+            testBlocked(167); // __NR_swapon
+            testBlocked(168); // __NR_swapoff
+        } else if (CpuFeatures.isX86Cpu()) {
+            testBlocked(87);  // __NR_swapon
+            testBlocked(115); // __NR_swapoff
+        } else if (CpuFeatures.isMips64Cpu()) {
+            testBlocked(5162); // __NR_swapon
+            testBlocked(5163); // __NR_swapoff
+        } else if (CpuFeatures.isMipsCpu()) {
+            testBlocked(4087); // __NR_swapon
+            testBlocked(4115); // __NR_swapoff
+        } else {
+            fail("Unsupported OS");
+        }
+    }
+
     private void testBlocked(int nr) {
         assertTrue("Syscall " + nr + " allowed", testSyscallBlocked(nr));
     }
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index 199c63b..c458ffd 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -617,6 +617,7 @@
                     codec.release();
                 }
             }
+            ex.unselectTrack(t);
         }
         ex.release();
         String cve = rname.replace("_", "-").toUpperCase();
diff --git a/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
index 420bba1..c01a173 100644
--- a/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
@@ -555,7 +555,47 @@
             fail("Expected SecurityException. App does not have carrier privileges or is not the "
                     + "default dialer app");
         } catch (SecurityException expected) {
+        }
+    }
 
+    /**
+     * Tests that the device properly reports the contents of EF_FPLMN or null
+     */
+    @Test
+    public void testGetForbiddenPlmns() {
+        if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+            return;
+        }
+        String[] plmns = mTelephonyManager.getForbiddenPlmns();
+
+        int phoneType = mTelephonyManager.getPhoneType();
+        switch (phoneType) {
+            case TelephonyManager.PHONE_TYPE_GSM:
+                assertNotNull("Forbidden PLMNs must be valid or an empty list!", plmns);
+            case TelephonyManager.PHONE_TYPE_CDMA:
+            case TelephonyManager.PHONE_TYPE_NONE:
+                if (plmns == null) {
+                    return;
+                }
+        }
+
+        for(String plmn : plmns) {
+            if (plmn.length() > 6 || plmn.length() < 5) {
+                fail("Invalid Length for PLMN-ID, must be 5 or 6: " + plmn);
+            }
+
+            // A record which is written in the SIM but empty will
+            // be all f's
+            if(android.text.TextUtils.isDigitsOnly(plmn)) {
+                assertTrue(
+                        "PLMNs must be strings of digits 0-9,F! " + plmn,
+                        android.text.TextUtils.isDigitsOnly(plmn));
+            } else {
+                for (char c : plmn.toUpperCase().toCharArray()) {
+                    assertTrue("PLMNs must be strings of digits 0-9,F! " + plmn,
+                            Character.toUpperCase(c) == 'F');
+                }
+            }
         }
     }
 
diff --git a/tests/tests/telephony/src/android/telephony/cts/VisualVoicemailServiceTest.java b/tests/tests/telephony/src/android/telephony/cts/VisualVoicemailServiceTest.java
index ae8ab8d..1e766ba 100644
--- a/tests/tests/telephony/src/android/telephony/cts/VisualVoicemailServiceTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/VisualVoicemailServiceTest.java
@@ -348,6 +348,10 @@
     }
 
     public void testFilter_originatingNumber_match_filtered() {
+        if (!hasTelephony(mContext)) {
+            Log.d(TAG, "skipping test that requires telephony feature");
+            return;
+        }
         VisualVoicemailSmsFilterSettings settings = new VisualVoicemailSmsFilterSettings.Builder()
                 .setClientPrefix("//CTSVVM")
                 .setOriginatingNumbers(Arrays.asList(mPhoneNumber))
@@ -357,6 +361,10 @@
     }
 
     public void testFilter_originatingNumber_mismatch_notFiltered() {
+        if (!hasTelephony(mContext)) {
+            Log.d(TAG, "skipping test that requires telephony feature");
+            return;
+        }
         VisualVoicemailSmsFilterSettings settings = new VisualVoicemailSmsFilterSettings.Builder()
                 .setClientPrefix("//CTSVVM")
                 .setOriginatingNumbers(Arrays.asList("1"))
diff --git a/tests/tests/text/src/android/text/cts/StaticLayoutTest.java b/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
index 9dca58f..308e750 100644
--- a/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
+++ b/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
@@ -1196,8 +1196,8 @@
         assertEquals(0, layout.getLineForOffset(lineBreakOffset - 1));
 
         assertEquals(0, layout.getOffsetForHorizontal(0, 0.0f));
-        assertEquals(lineBreakOffset, layout.getOffsetForHorizontal(0, width));
-        assertEquals(lineBreakOffset, layout.getOffsetForHorizontal(0, width * 2));
+        assertEquals(lineBreakOffset - 2, layout.getOffsetForHorizontal(0, width));
+        assertEquals(lineBreakOffset - 2, layout.getOffsetForHorizontal(0, width * 2));
 
         final int lineCount = layout.getLineCount();
         assertEquals(testString.length(), layout.getOffsetForHorizontal(lineCount - 1, width));
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java b/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java
index 0b28d05..578591c 100644
--- a/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java
@@ -426,7 +426,6 @@
         ContentValues baseValues = createDummyChannelValues(mInputId, false);
         Uri channelUri = mContentResolver.insert(mChannelsUri, baseValues);
 
-        final String COLUMN_SYSTEM_APPROVED = "system_approved";
 
         // Test: insert
         ContentValues values = new ContentValues(baseValues);
@@ -438,14 +437,6 @@
             // Expected.
         }
         values = new ContentValues(baseValues);
-        values.put(COLUMN_SYSTEM_APPROVED, 1);
-        try {
-            mContentResolver.insert(mChannelsUri, values);
-            fail("'" + COLUMN_SYSTEM_APPROVED + "' should be read-only.");
-        } catch (Exception e) {
-            // Expected.
-        }
-        values = new ContentValues(baseValues);
         values.put(Channels.COLUMN_LOCKED, 1);
         try {
             mContentResolver.insert(mChannelsUri, values);
@@ -464,14 +455,6 @@
             // Expected.
         }
         values = new ContentValues(baseValues);
-        values.put(COLUMN_SYSTEM_APPROVED, 1);
-        try {
-            mContentResolver.update(channelUri, values, null, null);
-            fail("'" + COLUMN_SYSTEM_APPROVED + "' should be read-only.");
-        } catch (Exception e) {
-            // Expected.
-        }
-        values = new ContentValues(baseValues);
         values.put(Channels.COLUMN_LOCKED, 1);
         try {
             mContentResolver.update(channelUri, values, null, null);
@@ -716,6 +699,14 @@
         Uri programUri = TvContract.buildPreviewProgramUri(programId);
         verifyPreviewProgram(programUri, values, programId);
 
+        values.remove(PreviewPrograms.COLUMN_TYPE);
+        try {
+            mContentResolver.insert(previewProgramsUri, values);
+            fail("Type should be a required column.");
+        } catch (IllegalArgumentException e) {
+            // Expected.
+        }
+
         // Test: update
         values.put(PreviewPrograms.COLUMN_EPISODE_TITLE, "Sample title");
         values.put(PreviewPrograms.COLUMN_SHORT_DESCRIPTION, "Short description");
@@ -743,6 +734,14 @@
         Uri programUri = TvContract.buildWatchNextProgramUri(programId);
         verifyWatchNextProgram(programUri, values, programId);
 
+        values.remove(WatchNextPrograms.COLUMN_TYPE);
+        try {
+            mContentResolver.insert(watchNextProgramsUri, values);
+            fail("Type should be a required column.");
+        } catch (IllegalArgumentException e) {
+            // Expected.
+        }
+
         // Test: update
         values.put(WatchNextPrograms.COLUMN_EPISODE_TITLE, "Sample title");
         values.put(WatchNextPrograms.COLUMN_SHORT_DESCRIPTION, "Short description");
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/AutofillHighlightTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/AutofillHighlightTests.java
index e3d56ba..95c222c3 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/AutofillHighlightTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/AutofillHighlightTests.java
@@ -20,14 +20,17 @@
 import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
 import android.uirendering.cts.R;
 import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
 import android.uirendering.cts.bitmapverifiers.GoldenImageVerifier;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 @MediumTest
+@RunWith(AndroidJUnit4.class)
 public class AutofillHighlightTests extends ActivityTestBase {
     @Test
     public void testHighlightedFrameLayout() {
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 77ff8f2..d705c7e 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapFilterTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapFilterTests.java
@@ -20,6 +20,7 @@
 import android.graphics.Paint;
 import android.graphics.PaintFlagsDrawFilter;
 import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
 import android.uirendering.cts.bitmapverifiers.BitmapVerifier;
 import android.uirendering.cts.bitmapverifiers.ColorVerifier;
 import android.uirendering.cts.bitmapverifiers.PerPixelBitmapVerifier;
@@ -27,8 +28,10 @@
 import android.uirendering.cts.testinfrastructure.CanvasClient;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 @MediumTest
+@RunWith(AndroidJUnit4.class)
 public class BitmapFilterTests extends ActivityTestBase {
     private static final int WHITE_WEIGHT = 255 * 3;
     private enum FilterEnum {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapTests.java
index d9b8d7f..789d8d5 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapTests.java
@@ -24,6 +24,7 @@
 import android.graphics.Color;
 import android.graphics.Rect;
 import android.os.Handler;
+import android.support.test.filters.LargeTest;
 import android.support.test.filters.MediumTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.uirendering.cts.R;
@@ -41,7 +42,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-@MediumTest
+@LargeTest
 @RunWith(AndroidJUnit4.class)
 public class BitmapTests extends ActivityTestBase {
     class BitmapView extends View {
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 d9eec30..16f98f6 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/CanvasStateTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/CanvasStateTests.java
@@ -26,11 +26,13 @@
 import android.graphics.RectF;
 import android.graphics.Region;
 import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
 import android.uirendering.cts.bitmapverifiers.ColorVerifier;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
 import android.util.DisplayMetrics;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 /**
  * Tests of state query-able from canvas at draw time.
@@ -39,6 +41,7 @@
  * capability to test the hardware accelerated Canvas in the way that it is used by Views.
  */
 @MediumTest
+@RunWith(AndroidJUnit4.class)
 public class CanvasStateTests extends ActivityTestBase {
     @Test
     public void testClipRectReturnValues() {
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 bbc50df..5d875ab 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ColorFilterAlphaTest.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ColorFilterAlphaTest.java
@@ -22,17 +22,19 @@
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
 import android.graphics.PorterDuffXfermode;
-import android.support.test.filters.LargeTest;
+import android.support.test.filters.MediumTest;
 import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
 import android.uirendering.cts.testinfrastructure.CanvasClient;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
 
 import java.util.List;
 
-@LargeTest // large while non-parameterized
-//@RunWith(Parameterized.class) // TODO: Reenable when CTS supports parameterized tests
+@MediumTest
+@RunWith(Parameterized.class)
 public class ColorFilterAlphaTest extends ActivityTestBase {
     // We care about one point in each of the four rectangles of different alpha values, as well as
     // the area outside the rectangles
@@ -85,12 +87,16 @@
                 0xFFC21A1A, 0xFFC93333, 0xFFD04D4D, 0xFFD66666, 0xFFBB0000 } },
     };
 
-    //@Parameterized.Parameters(name = "{0}")
+    @Parameterized.Parameters(name = "{0}")
     public static List<XfermodeTest.Config> configs() {
         return XfermodeTest.configs(MODES_AND_EXPECTED_COLORS);
     }
 
-    private XfermodeTest.Config mConfig;
+    private final XfermodeTest.Config mConfig;
+
+    public ColorFilterAlphaTest(XfermodeTest.Config config) {
+        mConfig = config;
+    }
 
     private static final int[] BLOCK_COLORS = new int[] {
             0x33808080,
@@ -127,12 +133,9 @@
 
     @Test
     public void test() {
-        for (XfermodeTest.Config config : configs()) {
-            mConfig = config;
-            createTest()
-                    .addCanvasClient(mCanvasClient, mConfig.hardwareAccelerated)
-                    .runWithVerifier(new SamplePointVerifier(TEST_POINTS, mConfig.expectedColors));
-        }
+        createTest()
+                .addCanvasClient(mCanvasClient, mConfig.hardwareAccelerated)
+                .runWithVerifier(new SamplePointVerifier(TEST_POINTS, mConfig.expectedColors));
     }
 }
 
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ColorSpaceTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ColorSpaceTests.java
index c5aa1b3..13c8e91 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ColorSpaceTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ColorSpaceTests.java
@@ -31,16 +31,19 @@
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
 import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
 
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.io.IOException;
 import java.io.InputStream;
 
 @MediumTest
+@RunWith(AndroidJUnit4.class)
 public class ColorSpaceTests extends ActivityTestBase {
     private Bitmap mMask;
 
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 444af9f..304303a 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
@@ -25,6 +25,7 @@
 import android.graphics.Rect;
 import android.graphics.drawable.NinePatchDrawable;
 import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
 import android.uirendering.cts.R;
 import android.uirendering.cts.bitmapcomparers.BitmapComparer;
 import android.uirendering.cts.bitmapcomparers.ExactComparer;
@@ -35,8 +36,10 @@
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 @MediumTest
+@RunWith(AndroidJUnit4.class)
 public class ExactCanvasTests extends ActivityTestBase {
     private final BitmapComparer mExactComparer = new ExactComparer();
 
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 2a2ec51..ea7403b 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/FontRenderingTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/FontRenderingTests.java
@@ -22,6 +22,7 @@
 import android.graphics.Paint;
 import android.graphics.Typeface;
 import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
 import android.uirendering.cts.R;
 import android.uirendering.cts.bitmapcomparers.BitmapComparer;
 import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
@@ -29,8 +30,10 @@
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 @MediumTest
+@RunWith(AndroidJUnit4.class)
 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;
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/GradientTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/GradientTests.java
index e808296..4b8b6b2 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/GradientTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/GradientTests.java
@@ -22,11 +22,14 @@
 import android.graphics.Point;
 import android.graphics.Shader;
 import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
 import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 @MediumTest
+@RunWith(AndroidJUnit4.class)
 public class GradientTests extends ActivityTestBase {
     @Test
     public void testAlphaPreMultiplication() {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/HardwareBitmapTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/HardwareBitmapTests.java
index 00b61e9..c62e134 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/HardwareBitmapTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/HardwareBitmapTests.java
@@ -28,6 +28,7 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.NinePatchDrawable;
+import android.support.test.runner.AndroidJUnit4;
 import android.uirendering.cts.R;
 
 import android.graphics.Bitmap;
@@ -41,11 +42,13 @@
 
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.io.IOException;
 import java.io.InputStream;
 
 @MediumTest
+@RunWith(AndroidJUnit4.class)
 public class HardwareBitmapTests extends ActivityTestBase {
 
     private Resources mRes;
@@ -82,7 +85,7 @@
                     HARDWARE_OPTIONS);
             canvas.drawBitmap(hardwareBitmap, 0, 0, new Paint());
         }, true).runWithVerifier(new GoldenImageVerifier(getActivity(),
-                R.drawable.golden_headless_robot, new ExactComparer()));
+                R.drawable.golden_headless_robot, new MSSIMComparer(0.95)));
     }
 
     @Test
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 f952bc2..ee46601 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java
@@ -18,7 +18,9 @@
 import android.graphics.Color;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.support.test.filters.LargeTest;
 import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
 import android.uirendering.cts.R;
 import android.uirendering.cts.bitmapcomparers.BitmapComparer;
 import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
@@ -28,8 +30,10 @@
 import android.uirendering.cts.testinfrastructure.ViewInitializer;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 @MediumTest
+@RunWith(AndroidJUnit4.class)
 public class InfrastructureTests extends ActivityTestBase {
 
     @Test
@@ -45,6 +49,7 @@
      * by verifying that two paths that should render differently *do* render
      * differently.
      */
+    @LargeTest
     @Test
     public void testRenderSpecIsolation() {
         CanvasClient canvasClient = (canvas, width, height) -> {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java
index f7661a5..ed0110a 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java
@@ -32,6 +32,7 @@
 import android.graphics.Rect;
 import android.graphics.Region.Op;
 import android.support.annotation.ColorInt;
+import android.support.test.filters.LargeTest;
 import android.support.test.filters.MediumTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.uirendering.cts.R;
@@ -140,6 +141,7 @@
                 .runWithVerifier(new ColorVerifier(expectedColor));
     }
 
+    @LargeTest
     @Test
     public void testLayerClear() {
         ViewInitializer initializer = 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 c0323b6..3d1c10e 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayoutTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayoutTests.java
@@ -18,14 +18,17 @@
 import android.graphics.Color;
 import android.graphics.Rect;
 import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
 import android.uirendering.cts.R;
 import android.uirendering.cts.bitmapverifiers.ColorVerifier;
 import android.uirendering.cts.bitmapverifiers.RectVerifier;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 @MediumTest
+@RunWith(AndroidJUnit4.class)
 public class LayoutTests extends ActivityTestBase {
     @Test
     public void testSimpleRedLayout() {
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 6eaba8f..ae4fee1 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java
@@ -24,7 +24,9 @@
 import android.graphics.Path;
 import android.graphics.Point;
 import android.graphics.Typeface;
+import android.support.test.filters.LargeTest;
 import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
 import android.uirendering.cts.R;
 import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
 import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
@@ -38,10 +40,12 @@
 import android.webkit.WebView;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.concurrent.CountDownLatch;
 
 @MediumTest
+@RunWith(AndroidJUnit4.class)
 public class PathClippingTests extends ActivityTestBase {
     // draw circle with hole in it, with stroked circle
     static final CanvasClient sTorusDrawCanvasClient = (canvas, width, height) -> {
@@ -173,6 +177,7 @@
         };
     }
 
+    @LargeTest
     @Test
     public void testWebViewClipWithCircle() {
         if (!getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_WEBVIEW)) {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathTests.java
index 5abe831..2d5acaa 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathTests.java
@@ -5,14 +5,17 @@
 import android.graphics.Path;
 import android.graphics.Typeface;
 import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
 import android.uirendering.cts.R;
 import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
 import android.uirendering.cts.bitmapverifiers.GoldenImageVerifier;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 @MediumTest
+@RunWith(AndroidJUnit4.class)
 public class PathTests extends ActivityTestBase {
 
     private static final double REGULAR_THRESHOLD = 0.92;
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 c1e10d3..454eb2c0 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PictureTest.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PictureTest.java
@@ -22,13 +22,16 @@
 import android.graphics.Picture;
 import android.graphics.Rect;
 import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
 import android.uirendering.cts.bitmapverifiers.ColorVerifier;
 import android.uirendering.cts.bitmapverifiers.RectVerifier;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 @MediumTest
+@RunWith(AndroidJUnit4.class)
 public class PictureTest extends ActivityTestBase {
 
     private static final Rect sRect = new Rect(0, 0, 40, 40);
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/Rgba16fTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/Rgba16fTests.java
index 44831bf..d9ec2b5 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/Rgba16fTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/Rgba16fTests.java
@@ -25,16 +25,19 @@
 import android.graphics.Point;
 import android.graphics.Shader;
 import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
 import android.uirendering.cts.R;
 import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.io.IOException;
 import java.io.InputStream;
 
 @MediumTest
+@RunWith(AndroidJUnit4.class)
 public class Rgba16fTests extends ActivityTestBase {
     @Test
     public void testTransferFunctions() {
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 2c9df73..252874d 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShaderTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShaderTests.java
@@ -27,14 +27,17 @@
 import android.graphics.RadialGradient;
 import android.graphics.Shader;
 import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
 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 org.junit.Test;
+import org.junit.runner.RunWith;
 
 @MediumTest
+@RunWith(AndroidJUnit4.class)
 public class ShaderTests extends ActivityTestBase {
     @Test
     public void testSinglePixelBitmapShader() {
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 e9b9bd4..e4f9809 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShadowTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShadowTests.java
@@ -18,14 +18,17 @@
 import android.graphics.Color;
 import android.graphics.Point;
 import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
 import android.uirendering.cts.R;
 import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
 import android.uirendering.cts.util.CompareUtils;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 @MediumTest
+@RunWith(AndroidJUnit4.class)
 public class ShadowTests extends ActivityTestBase {
 
     private class GrayScaleVerifier extends SamplePointVerifier {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShapeTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShapeTests.java
index 9aad23d..0b708d4 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShapeTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShapeTests.java
@@ -17,14 +17,17 @@
 package android.uirendering.cts.testclasses;
 
 import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
 import android.uirendering.cts.R;
 import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
 import android.uirendering.cts.bitmapverifiers.GoldenImageVerifier;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 @MediumTest
+@RunWith(AndroidJUnit4.class)
 public class ShapeTests extends ActivityTestBase {
     @Test
     public void testDashedOval() {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SurfaceViewTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SurfaceViewTests.java
index 52b87cc..741c35c 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SurfaceViewTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SurfaceViewTests.java
@@ -24,7 +24,9 @@
 import android.graphics.Color;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.support.test.filters.LargeTest;
 import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
 import android.uirendering.cts.R;
 import android.uirendering.cts.bitmapverifiers.ColorVerifier;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
@@ -40,10 +42,12 @@
 
 import org.junit.Assert;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.concurrent.CountDownLatch;
 
-@MediumTest
+@LargeTest
+@RunWith(AndroidJUnit4.class)
 public class SurfaceViewTests extends ActivityTestBase {
 
     static final CanvasCallback sGreenCanvasCallback =
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SweepTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SweepTests.java
index c374dd7e..ff0e9a7 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SweepTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SweepTests.java
@@ -22,7 +22,9 @@
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.Shader;
+import android.support.test.filters.LargeTest;
 import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
 import android.uirendering.cts.bitmapcomparers.BitmapComparer;
 import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
@@ -31,11 +33,13 @@
 import android.uirendering.cts.testinfrastructure.ResourceModifier;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 /**
  * Test cases of all combination of resource modifications.
  */
-@MediumTest
+@LargeTest
+@RunWith(AndroidJUnit4.class)
 public class SweepTests extends ActivityTestBase {
     private final static DisplayModifier COLOR_FILTER_GRADIENT_MODIFIER = new DisplayModifier() {
         private final Rect mBounds = new Rect(30, 30, 150, 150);
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/TextureViewTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/TextureViewTests.java
index f220bfb..abbec36 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/TextureViewTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/TextureViewTests.java
@@ -27,6 +27,7 @@
 import android.graphics.SurfaceTexture;
 import android.support.annotation.ColorInt;
 import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
 import android.uirendering.cts.R;
 import android.uirendering.cts.bitmapverifiers.ColorVerifier;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
@@ -42,10 +43,12 @@
 import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.concurrent.CountDownLatch;
 
 @MediumTest
+@RunWith(AndroidJUnit4.class)
 public class TextureViewTests extends ActivityTestBase {
 
     private static SurfaceTexture sRedTexture;
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/VectorDrawableTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/VectorDrawableTests.java
index 2a64ac4..ffb263d 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/VectorDrawableTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/VectorDrawableTests.java
@@ -26,8 +26,10 @@
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 @MediumTest
+@RunWith(AndroidJUnit4.class)
 public class VectorDrawableTests extends ActivityTestBase {
     @Test
     public void testScaleDown() {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewAnimationUtilsTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewAnimationUtilsTests.java
index d74dcb7..88aa265 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewAnimationUtilsTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewAnimationUtilsTests.java
@@ -17,6 +17,7 @@
 package android.uirendering.cts.testclasses;
 
 import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
 import android.uirendering.cts.R;
 import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
 import android.uirendering.cts.bitmapverifiers.GoldenImageVerifier;
@@ -25,8 +26,10 @@
 import android.view.ViewAnimationUtils;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 @MediumTest
+@RunWith(AndroidJUnit4.class)
 public class ViewAnimationUtilsTests extends ActivityTestBase {
     @Test
     public void testCreateCircularReveal() {
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 47f9f4d..d1f0ee5 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewClippingTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewClippingTests.java
@@ -7,6 +7,7 @@
 import android.graphics.Path;
 import android.graphics.Rect;
 import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
 import android.uirendering.cts.R;
 import android.uirendering.cts.bitmapverifiers.BitmapVerifier;
 import android.uirendering.cts.bitmapverifiers.RectVerifier;
@@ -18,6 +19,7 @@
 import android.view.ViewOutlineProvider;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 /**
  * This tests view clipping by modifying properties of blue_padded_layout, and validating
@@ -26,6 +28,7 @@
  * Since the layout is blue on a white background, this is always done with a RectVerifier.
  */
 @MediumTest
+@RunWith(AndroidJUnit4.class)
 public class ViewClippingTests extends ActivityTestBase {
     static final Rect FULL_RECT = new Rect(0, 0, 90, 90);
     static final Rect BOUNDS_RECT = new Rect(0, 0, 80, 80);
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 04e1dfd..38a4d40 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/XfermodeTest.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/XfermodeTest.java
@@ -22,18 +22,20 @@
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.RectF;
-import android.support.test.filters.LargeTest;
+import android.support.test.filters.MediumTest;
 import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
 import android.uirendering.cts.testinfrastructure.CanvasClient;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
 
 import java.util.ArrayList;
 import java.util.List;
 
-@LargeTest // large while non-parameterized
-//@RunWith(Parameterized.class) // TODO: Reenable when CTS supports parameterized tests
+@MediumTest
+@RunWith(Parameterized.class)
 public class XfermodeTest extends ActivityTestBase {
     /**
      * There are 4 locations we care about in testing each filter:
@@ -124,12 +126,16 @@
                 BG_COLOR, DST_COLOR, SCREEN_COLOR, SRC_COLOR } },
     };
 
-    //@Parameterized.Parameters(name = "{0}")
+    @Parameterized.Parameters(name = "{0}")
     public static List<Config> configs() {
         return configs(MODES_AND_EXPECTED_COLORS);
     }
 
-    private Config mConfig;
+    private final Config mConfig;
+
+    public XfermodeTest(Config config) {
+        mConfig = config;
+    }
 
     private CanvasClient mCanvasClient = new CanvasClient() {
         final Paint mPaint = new Paint();
@@ -170,11 +176,8 @@
 
     @Test
     public void test() {
-        for (XfermodeTest.Config config : configs()) {
-            mConfig = config;
-            createTest()
-                    .addCanvasClient(mCanvasClient, mConfig.hardwareAccelerated)
-                    .runWithVerifier(new SamplePointVerifier(TEST_POINTS, mConfig.expectedColors));
-        }
+        createTest()
+                .addCanvasClient(mCanvasClient, mConfig.hardwareAccelerated)
+                .runWithVerifier(new SamplePointVerifier(TEST_POINTS, mConfig.expectedColors));
     }
 }
diff --git a/tests/tests/view/AndroidManifest.xml b/tests/tests/view/AndroidManifest.xml
index 8afec2c..5f50e9c 100644
--- a/tests/tests/view/AndroidManifest.xml
+++ b/tests/tests/view/AndroidManifest.xml
@@ -331,6 +331,13 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+
+        <activity android:name="android.view.cts.DefaultFocusHighlightCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
     </application>
 
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/view/res/drawable/scrollbar_no_size.xml b/tests/tests/view/res/drawable/scrollbar_no_size.xml
deleted file mode 100644
index 88a59f0..0000000
--- a/tests/tests/view/res/drawable/scrollbar_no_size.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-       android:shape="rectangle">
-    <solid android:color="@android:color/white" />
-</shape>
diff --git a/tests/tests/view/res/drawable/scrollbar_thumb.xml b/tests/tests/view/res/drawable/scrollbar_thumb.xml
deleted file mode 100644
index d7612ac..0000000
--- a/tests/tests/view/res/drawable/scrollbar_thumb.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-       android:shape="rectangle">
-    <solid android:color="@android:color/white" />
-    <size
-        android:width="@dimen/scrollbar_thumb_width"
-        android:height="@dimen/scrollbar_thumb_height"/>
-</shape>
diff --git a/tests/tests/view/res/drawable/scrollbar_track.xml b/tests/tests/view/res/drawable/scrollbar_track.xml
deleted file mode 100644
index a184569..0000000
--- a/tests/tests/view/res/drawable/scrollbar_track.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-       android:shape="rectangle">
-    <solid android:color="@android:color/white" />
-    <size
-        android:width="@dimen/scrollbar_track_width"
-        android:height="@dimen/scrollbar_track_height"/>
-</shape>
diff --git a/tests/tests/view/res/layout/default_focus_highlight_layout.xml b/tests/tests/view/res/layout/default_focus_highlight_layout.xml
new file mode 100644
index 0000000..827de43
--- /dev/null
+++ b/tests/tests/view/res/layout/default_focus_highlight_layout.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <View
+        android:id="@+id/view"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/id_ok"/>
+
+    <ListView
+        android:id="@+id/listview"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/id_ok"/>
+
+    <EditText
+        android:id="@+id/edittext"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/id_ok"
+        android:inputType="text"/>
+
+    <Button
+        android:id="@+id/button"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/id_ok"/>
+
+    <LinearLayout
+        android:id="@+id/linearlayout"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+    </LinearLayout>
+
+    <View
+        android:id="@+id/view_to_inflate"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:defaultFocusHighlightEnabled="false"
+        android:text="@string/id_ok"/>
+
+    <ListView
+        android:id="@+id/listview_to_inflate"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:defaultFocusHighlightEnabled="true"
+        android:text="@string/id_ok"/>
+
+    <EditText
+        android:id="@+id/edittext_to_inflate"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/id_ok"
+        android:defaultFocusHighlightEnabled="true"
+        android:inputType="text"/>
+
+    <Button
+        android:id="@+id/button_to_inflate"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:defaultFocusHighlightEnabled="false"
+        android:text="@string/id_ok"/>
+
+    <LinearLayout
+        android:id="@+id/linearlayout_to_inflate"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:defaultFocusHighlightEnabled="false"
+        android:orientation="vertical">
+    </LinearLayout>
+
+</LinearLayout>
+
diff --git a/tests/tests/view/res/layout/focus_finder_layout.xml b/tests/tests/view/res/layout/focus_finder_layout.xml
index 610ffc8..1dea684 100644
--- a/tests/tests/view/res/layout/focus_finder_layout.xml
+++ b/tests/tests/view/res/layout/focus_finder_layout.xml
@@ -19,7 +19,7 @@
     <TableLayout android:id="@+id/layout"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_centerInParent="true">
+            android:layout_alignParentTop="true">
         <TableRow>
             <android.view.cts.TestButton android:id="@+id/top_left_button"
                     android:layout_width="60dp"
@@ -41,5 +41,12 @@
                     android:text="BR" />
         </TableRow>  
     </TableLayout>
+    <LinearLayout android:id="@+id/inflate_layout"
+            android:orientation="horizontal"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@id/layout">
+
+    </LinearLayout>
 </RelativeLayout>
 
diff --git a/tests/tests/view/res/layout/focus_finder_sublayout.xml b/tests/tests/view/res/layout/focus_finder_sublayout.xml
new file mode 100644
index 0000000..c9a4c3b
--- /dev/null
+++ b/tests/tests/view/res/layout/focus_finder_sublayout.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="vertical"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content">
+    <FrameLayout
+        android:focusableInTouchMode="true"
+        android:id="@+id/itembox"
+        android:layout_width="200px"
+        android:layout_height="200px">
+        <Button
+            android:id="@+id/itembutton"
+            android:focusableInTouchMode="true"
+            android:nextFocusForward="@id/itembox"
+            android:layout_gravity="bottom|right"
+            android:layout_marginRight="10px"
+            android:layout_marginBottom="10px"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"/>
+    </FrameLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/tests/view/res/layout/view_layout.xml b/tests/tests/view/res/layout/view_layout.xml
index 3cfaafa..920da83 100644
--- a/tests/tests/view/res/layout/view_layout.xml
+++ b/tests/tests/view/res/layout/view_layout.xml
@@ -46,42 +46,6 @@
         android:requiresFadingEdge="horizontal|vertical"
         android:fadingEdgeLength="20px"/>
 
-    <android.view.cts.MockView
-        android:id="@+id/scroll_view_3"
-        android:layout_width="100px"
-        android:layout_height="200px"
-        android:scrollbars="horizontal|vertical"
-        android:scrollbarThumbVertical="@drawable/scrollbar_no_size"
-        android:scrollbarThumbHorizontal="@drawable/scrollbar_no_size"/>
-
-    <android.view.cts.MockView
-        android:id="@+id/scroll_view_4"
-        android:layout_width="100px"
-        android:layout_height="200px"
-        android:scrollbars="horizontal|vertical"
-        android:scrollbarThumbVertical="@drawable/scrollbar_thumb"
-        android:scrollbarThumbHorizontal="@drawable/scrollbar_thumb"/>
-
-    <android.view.cts.MockView
-        android:id="@+id/scroll_view_5"
-        android:layout_width="100px"
-        android:layout_height="200px"
-        android:scrollbars="horizontal|vertical"
-        android:scrollbarThumbVertical="@drawable/scrollbar_thumb"
-        android:scrollbarTrackVertical="@drawable/scrollbar_track"
-        android:scrollbarThumbHorizontal="@drawable/scrollbar_thumb"
-        android:scrollbarTrackHorizontal="@drawable/scrollbar_track"/>
-
-    <android.view.cts.MockView
-        android:id="@+id/scroll_view_6"
-        android:layout_width="100px"
-        android:layout_height="200px"
-        android:scrollbars="horizontal|vertical"
-        android:scrollbarThumbVertical="@drawable/scrollbar_thumb"
-        android:scrollbarTrackVertical="@drawable/scrollbar_no_size"
-        android:scrollbarThumbHorizontal="@drawable/scrollbar_thumb"
-        android:scrollbarTrackHorizontal="@drawable/scrollbar_no_size"/>
-
     <View
         android:id="@+id/fit_windows"
         android:fitsSystemWindows="true"
diff --git a/tests/tests/view/res/values/dimens.xml b/tests/tests/view/res/values/dimens.xml
index a1d66f9..59369a7 100644
--- a/tests/tests/view/res/values/dimens.xml
+++ b/tests/tests/view/res/values/dimens.xml
@@ -30,8 +30,4 @@
     <dimen name="hover_target_margin">4dp</dimen>
     <dimen name="hover_target_size">8dp</dimen>
     <dimen name="hover_target_size_double">16dp</dimen>
-    <dimen name="scrollbar_thumb_width">11dp</dimen>
-    <dimen name="scrollbar_thumb_height">12dp</dimen>
-    <dimen name="scrollbar_track_width">13dp</dimen>
-    <dimen name="scrollbar_track_height">14dp</dimen>
 </resources>
\ No newline at end of file
diff --git a/tests/tests/view/src/android/view/cts/DefaultFocusHighlightCtsActivity.java b/tests/tests/view/src/android/view/cts/DefaultFocusHighlightCtsActivity.java
new file mode 100644
index 0000000..5211938
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/DefaultFocusHighlightCtsActivity.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * A simple activity to test "Default Focus Highlight"
+ */
+public class DefaultFocusHighlightCtsActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.default_focus_highlight_layout);
+    }
+}
diff --git a/tests/tests/view/src/android/view/cts/FocusFinderTest.java b/tests/tests/view/src/android/view/cts/FocusFinderTest.java
index 22fb6e0..8d56087 100644
--- a/tests/tests/view/src/android/view/cts/FocusFinderTest.java
+++ b/tests/tests/view/src/android/view/cts/FocusFinderTest.java
@@ -21,13 +21,16 @@
 import static org.junit.Assert.assertTrue;
 
 import android.graphics.Rect;
+import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
 import android.view.FocusFinder;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Button;
+import android.widget.FrameLayout;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -340,4 +343,75 @@
                 View.FOCUS_BACKWARD);
         assertTrue(nextFocus == mBottomRight || nextFocus == mBottomLeft);
     }
+
+    @Test
+    public void testDuplicateId() throws Throwable {
+        LayoutInflater inflater = mActivityRule.getActivity().getLayoutInflater();
+        mLayout = (ViewGroup) mActivityRule.getActivity().findViewById(R.id.inflate_layout);
+        View[] buttons = new View[3];
+        View[] boxes = new View[3];
+        mActivityRule.runOnUiThread(() -> {
+            for (int i = 0; i < 3; ++i) {
+                View item = inflater.inflate(R.layout.focus_finder_sublayout, mLayout, false);
+                buttons[i] = item.findViewById(R.id.itembutton);
+                boxes[i] = item.findViewById(R.id.itembox);
+                mLayout.addView(item);
+            }
+        });
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+        verifyNextFocus(buttons[0], View.FOCUS_FORWARD, boxes[0]);
+        verifyNextFocus(boxes[0], View.FOCUS_FORWARD, buttons[1]);
+        verifyNextFocus(buttons[1], View.FOCUS_FORWARD, boxes[1]);
+        verifyNextFocus(boxes[1], View.FOCUS_FORWARD, buttons[2]);
+    }
+
+    @Test
+    public void testBasicFocusOrder() {
+        // Sanity check to make sure sorter is behaving
+        FrameLayout layout = new FrameLayout(mLayout.getContext());
+        Button button1 = new Button(mLayout.getContext());
+        Button button2 = new Button(mLayout.getContext());
+        button1.setLeftTopRightBottom(0, 0, 10, 10);
+        button2.setLeftTopRightBottom(0, 0, 10, 10);
+        layout.addView(button1);
+        layout.addView(button2);
+        View[] views = new View[]{button2, button1};
+        // empty shouldn't crash or anything
+        FocusFinder.sort(views, 0, 0, layout, false);
+        // one view should work
+        FocusFinder.sort(views, 0, 1, layout, false);
+        assertEquals(button2, views[0]);
+        // exactly overlapping views should remain in original order
+        FocusFinder.sort(views, 0, 2, layout, false);
+        assertEquals(button2, views[0]);
+        assertEquals(button1, views[1]);
+        // make sure it will actually mutate input array.
+        button2.setLeftTopRightBottom(20, 0, 30, 10);
+        FocusFinder.sort(views, 0, 2, layout, false);
+        assertEquals(button1, views[0]);
+        assertEquals(button2, views[1]);
+
+        // While we don't want to test details, we should at least verify basic correctness
+        // like "left-to-right" ordering in well-behaved layouts
+        assertEquals(mLayout.findFocus(), mTopLeft);
+        verifyNextFocus(mTopLeft, View.FOCUS_FORWARD, mTopRight);
+        verifyNextFocus(mTopRight, View.FOCUS_FORWARD, mBottomLeft);
+        verifyNextFocus(mBottomLeft, View.FOCUS_FORWARD, mBottomRight);
+
+        // Should still work intuitively even if some views are slightly shorter.
+        mBottomLeft.setBottom(mBottomLeft.getBottom() - 3);
+        mBottomLeft.offsetTopAndBottom(3);
+        verifyNextFocus(mTopLeft, View.FOCUS_FORWARD, mTopRight);
+        verifyNextFocus(mTopRight, View.FOCUS_FORWARD, mBottomLeft);
+        verifyNextFocus(mBottomLeft, View.FOCUS_FORWARD, mBottomRight);
+
+        // RTL layout should work right-to-left
+        mActivityRule.getActivity().runOnUiThread(
+                () -> mLayout.setLayoutDirection(View.LAYOUT_DIRECTION_RTL));
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+        verifyNextFocus(mTopLeft, View.FOCUS_FORWARD, mTopRight);
+        verifyNextFocus(mTopRight, View.FOCUS_FORWARD, mBottomLeft);
+        verifyNextFocus(mBottomLeft, View.FOCUS_FORWARD, mBottomRight);
+    }
 }
diff --git a/tests/tests/view/src/android/view/cts/ViewGroupTest.java b/tests/tests/view/src/android/view/cts/ViewGroupTest.java
index 17c6843..95b8491 100644
--- a/tests/tests/view/src/android/view/cts/ViewGroupTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewGroupTest.java
@@ -208,6 +208,19 @@
         mMockViewGroup.setVisibility(View.GONE);
         parent.addKeyboardNavigationClusters(list, 0);
         assertEquals(0, list.size());
+        list.clear();
+
+        // Nested clusters are ignored
+        TestClusterHier h = new TestClusterHier();
+        h.nestedGroup.setKeyboardNavigationCluster(true);
+        h.cluster2.setKeyboardNavigationCluster(false);
+        h.top.addKeyboardNavigationClusters(list, View.FOCUS_FORWARD);
+        assertTrue(list.contains(h.nestedGroup));
+        list.clear();
+        h.cluster2.setKeyboardNavigationCluster(true);
+        h.top.addKeyboardNavigationClusters(list, View.FOCUS_FORWARD);
+        assertFalse(list.contains(h.nestedGroup));
+        list.clear();
     }
 
     @UiThreadTest
@@ -1562,6 +1575,14 @@
         h.c2view1.setVisibility(View.INVISIBLE);
         h.cluster2.restoreFocusInCluster(View.FOCUS_DOWN);
         assertSame(h.c2view2, h.top.findFocus());
+
+        // Nested clusters should be ignored.
+        h = new TestClusterHier();
+        h.c1view1.setFocusedInCluster();
+        h.nestedGroup.setKeyboardNavigationCluster(true);
+        h.c2view2.setFocusedInCluster();
+        h.cluster2.restoreFocusInCluster(View.FOCUS_DOWN);
+        assertSame(h.c2view2, h.top.findFocus());
     }
 
     @UiThreadTest
@@ -1781,6 +1802,7 @@
         // can normal-navigate around once inside
         h.top.addFocusables(views, View.FOCUS_DOWN);
         assertTrue(views.contains(h.c1view1));
+        views.clear();
         h.c1view1.requestFocus();
         assertSame(h.c1view1, h.top.findFocus());
         // focus loops within cluster (doesn't leave)
@@ -1791,6 +1813,17 @@
         h.c2view2.requestFocus();
         h.c1view1.requestFocus();
         assertSame(h.c2view2, h.top.findFocus());
+
+        h = new TestClusterHier(false);
+        h.c1view1.requestFocus();
+        h.nestedGroup.setKeyboardNavigationCluster(true);
+        h.nestedGroup.setTouchscreenBlocksFocus(true);
+        // since cluster is nested, it should ignore its touchscreenBlocksFocus behavior.
+        h.c2view2.requestFocus();
+        assertSame(h.c2view2, h.top.findFocus());
+        h.top.addFocusables(views, View.FOCUS_DOWN);
+        assertTrue(views.contains(h.c2view2));
+        views.clear();
     }
 
     @UiThreadTest
diff --git a/tests/tests/view/src/android/view/cts/ViewTest.java b/tests/tests/view/src/android/view/cts/ViewTest.java
index ca39aab..2550915 100644
--- a/tests/tests/view/src/android/view/cts/ViewTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewTest.java
@@ -3661,67 +3661,6 @@
     }
 
     @Test
-    public void testScrollbarSize() {
-        final int configScrollbarSize = ViewConfiguration.get(mActivity).getScaledScrollBarSize();
-        final int customScrollbarSize = configScrollbarSize * 2;
-
-        // No explicit scrollbarSize or custom drawables, ViewConfiguration applies.
-        final MockView view = (MockView) mActivity.findViewById(R.id.scroll_view);
-        assertEquals(configScrollbarSize, view.getScrollBarSize());
-        assertEquals(configScrollbarSize, view.getVerticalScrollbarWidth());
-        assertEquals(configScrollbarSize, view.getHorizontalScrollbarHeight());
-
-        // No custom drawables, explicit scrollbarSize takes precedence.
-        final MockView view2 = (MockView) mActivity.findViewById(R.id.scroll_view_2);
-        view2.setScrollBarSize(customScrollbarSize);
-        assertEquals(customScrollbarSize, view2.getScrollBarSize());
-        assertEquals(customScrollbarSize, view2.getVerticalScrollbarWidth());
-        assertEquals(customScrollbarSize, view2.getHorizontalScrollbarHeight());
-
-        // Custom drawables with no intrinsic size, ViewConfiguration applies.
-        final MockView view3 = (MockView) mActivity.findViewById(R.id.scroll_view_3);
-        assertEquals(configScrollbarSize, view3.getVerticalScrollbarWidth());
-        assertEquals(configScrollbarSize, view3.getHorizontalScrollbarHeight());
-        // Explicit scrollbarSize takes precedence.
-        view3.setScrollBarSize(customScrollbarSize);
-        assertEquals(view3.getScrollBarSize(), view3.getVerticalScrollbarWidth());
-        assertEquals(view3.getScrollBarSize(), view3.getHorizontalScrollbarHeight());
-
-        // Custom thumb drawables with intrinsic sizes define the scrollbars' dimensions.
-        final MockView view4 = (MockView) mActivity.findViewById(R.id.scroll_view_4);
-        final Resources res = mActivity.getResources();
-        final int thumbWidth = res.getDimensionPixelOffset(R.dimen.scrollbar_thumb_width);
-        final int thumbHeight = res.getDimensionPixelOffset(R.dimen.scrollbar_thumb_height);
-        assertEquals(thumbWidth, view4.getVerticalScrollbarWidth());
-        assertEquals(thumbHeight, view4.getHorizontalScrollbarHeight());
-        // Explicit scrollbarSize has no effect.
-        view4.setScrollBarSize(customScrollbarSize);
-        assertEquals(thumbWidth, view4.getVerticalScrollbarWidth());
-        assertEquals(thumbHeight, view4.getHorizontalScrollbarHeight());
-
-        // Custom thumb and track drawables with intrinsic sizes. Track size take precedence.
-        final MockView view5 = (MockView) mActivity.findViewById(R.id.scroll_view_5);
-        final int trackWidth = res.getDimensionPixelOffset(R.dimen.scrollbar_track_width);
-        final int trackHeight = res.getDimensionPixelOffset(R.dimen.scrollbar_track_height);
-        assertEquals(trackWidth, view5.getVerticalScrollbarWidth());
-        assertEquals(trackHeight, view5.getHorizontalScrollbarHeight());
-        // Explicit scrollbarSize has no effect.
-        view5.setScrollBarSize(customScrollbarSize);
-        assertEquals(trackWidth, view5.getVerticalScrollbarWidth());
-        assertEquals(trackHeight, view5.getHorizontalScrollbarHeight());
-
-        // Custom thumb and track, track with no intrinsic size, ViewConfiguration applies
-        // regardless of the thumb drawable dimensions.
-        final MockView view6 = (MockView) mActivity.findViewById(R.id.scroll_view_6);
-        assertEquals(configScrollbarSize, view6.getVerticalScrollbarWidth());
-        assertEquals(configScrollbarSize, view6.getHorizontalScrollbarHeight());
-        // Explicit scrollbarSize takes precedence.
-        view6.setScrollBarSize(customScrollbarSize);
-        assertEquals(customScrollbarSize, view6.getVerticalScrollbarWidth());
-        assertEquals(customScrollbarSize, view6.getHorizontalScrollbarHeight());
-    }
-
-    @Test
     public void testOnStartAndFinishTemporaryDetach() throws Throwable {
         final AtomicBoolean exitedDispatchStartTemporaryDetach = new AtomicBoolean(false);
         final AtomicBoolean exitedDispatchFinishTemporaryDetach = new AtomicBoolean(false);
diff --git a/tests/tests/view/src/android/view/cts/View_DefaultFocusHighlightTest.java b/tests/tests/view/src/android/view/cts/View_DefaultFocusHighlightTest.java
new file mode 100644
index 0000000..5e362cf
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/View_DefaultFocusHighlightTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.cts;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.app.Activity;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.MediumTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class View_DefaultFocusHighlightTest {
+
+    @Rule
+    public ActivityTestRule<DefaultFocusHighlightCtsActivity> mActivityRule =
+            new ActivityTestRule<>(DefaultFocusHighlightCtsActivity.class);
+
+    @UiThreadTest
+    @Test
+    public void testSettersAndGetters() {
+        Activity activity = mActivityRule.getActivity();
+
+        View view = activity.findViewById(R.id.view);
+        ListView listView = (ListView) activity.findViewById(R.id.listview);
+        EditText editText = (EditText) activity.findViewById(R.id.edittext);
+        Button button = (Button) activity.findViewById(R.id.button);
+        LinearLayout linearLayout = (LinearLayout) activity.findViewById(R.id.linearlayout);
+
+        assertTrue(view.getDefaultFocusHighlightEnabled());
+        assertFalse(listView.getDefaultFocusHighlightEnabled());
+        assertFalse(editText.getDefaultFocusHighlightEnabled());
+        assertTrue(button.getDefaultFocusHighlightEnabled());
+        assertTrue(linearLayout.getDefaultFocusHighlightEnabled());
+
+        view.setDefaultFocusHighlightEnabled(false);
+        listView.setDefaultFocusHighlightEnabled(true);
+        editText.setDefaultFocusHighlightEnabled(true);
+        button.setDefaultFocusHighlightEnabled(false);
+        linearLayout.setDefaultFocusHighlightEnabled(false);
+
+        assertFalse(view.getDefaultFocusHighlightEnabled());
+        assertTrue(listView.getDefaultFocusHighlightEnabled());
+        assertTrue(editText.getDefaultFocusHighlightEnabled());
+        assertFalse(button.getDefaultFocusHighlightEnabled());
+        assertFalse(linearLayout.getDefaultFocusHighlightEnabled());
+    }
+
+    @UiThreadTest
+    @Test
+    public void testInflating() {
+        Activity activity = mActivityRule.getActivity();
+
+        View view = activity.findViewById(R.id.view_to_inflate);
+        ListView listView = (ListView) activity.findViewById(R.id.listview_to_inflate);
+        EditText editText = (EditText) activity.findViewById(R.id.edittext_to_inflate);
+        Button button = (Button) activity.findViewById(R.id.button_to_inflate);
+        LinearLayout linearLayout = (LinearLayout) activity.findViewById(
+                R.id.linearlayout_to_inflate);
+
+        assertFalse(view.getDefaultFocusHighlightEnabled());
+        assertTrue(listView.getDefaultFocusHighlightEnabled());
+        assertTrue(editText.getDefaultFocusHighlightEnabled());
+        assertFalse(button.getDefaultFocusHighlightEnabled());
+        assertFalse(linearLayout.getDefaultFocusHighlightEnabled());
+    }
+}
diff --git a/tests/tests/view/src/android/view/cts/surfacevalidator/SurfacePixelValidator.java b/tests/tests/view/src/android/view/cts/surfacevalidator/SurfacePixelValidator.java
index 3d9f66b..60ef12e 100644
--- a/tests/tests/view/src/android/view/cts/surfacevalidator/SurfacePixelValidator.java
+++ b/tests/tests/view/src/android/view/cts/surfacevalidator/SurfacePixelValidator.java
@@ -36,7 +36,7 @@
      * Observed that first few frames have errors with SurfaceView placement, so we skip for now.
      * b/29603849 tracking that issue.
      */
-    private static final int NUM_FIRST_FRAMES_SKIPPED = 8;
+    private static final int NUM_FIRST_FRAMES_SKIPPED = 25;
 
     // If no channel is greater than this value, pixel will be considered 'blackish'.
     private static final short PIXEL_CHANNEL_THRESHOLD = 4;
@@ -78,6 +78,7 @@
             synchronized (mResultLock) {
                 if (numSkipped < NUM_FIRST_FRAMES_SKIPPED) {
                     numSkipped++;
+                    Log.d(TAG, "skipped fram nr " + numSkipped + ", success = " + success);
                 } else {
                     if (success) {
                         mResultSuccessFrames++;
diff --git a/tests/tests/view/src/android/view/textclassifier/cts/TextClassificationManagerTest.java b/tests/tests/view/src/android/view/textclassifier/cts/TextClassificationManagerTest.java
index b16d473..a840116 100644
--- a/tests/tests/view/src/android/view/textclassifier/cts/TextClassificationManagerTest.java
+++ b/tests/tests/view/src/android/view/textclassifier/cts/TextClassificationManagerTest.java
@@ -17,7 +17,6 @@
 package android.view.textclassifier.cts;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
 import static org.mockito.Mockito.mock;
 
 import android.os.LocaleList;
@@ -25,21 +24,12 @@
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.view.textclassifier.TextClassificationManager;
-import android.view.textclassifier.TextClassificationResult;
 import android.view.textclassifier.TextClassifier;
-import android.view.textclassifier.TextLanguage;
-import android.view.textclassifier.TextSelection;
 
-import org.hamcrest.BaseMatcher;
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.util.List;
-import java.util.Locale;
-
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class TextClassificationManagerTest {
@@ -53,78 +43,23 @@
     public void setup() {
         mTcm = InstrumentationRegistry.getTargetContext()
                 .getSystemService(TextClassificationManager.class);
-        mTcm.setTextClassifier(null);
+        mTcm.setTextClassifier(null); // Resets the classifier.
         mClassifier = mTcm.getTextClassifier();
     }
 
     @Test
-    public void testSmartSelection() {
-        if (isTextClassifierDisabled()) return;
-
-        String text = "Contact me at droid@android.com";
-        String selected = "droid";
-        String suggested = "droid@android.com";
-        int startIndex = text.indexOf(selected);
-        int endIndex = startIndex + selected.length();
-        int smartStartIndex = text.indexOf(suggested);
-        int smartEndIndex = smartStartIndex + suggested.length();
-
-        assertThat(mClassifier.suggestSelection(text, startIndex, endIndex, LOCALES),
-                isTextSelection(smartStartIndex, smartEndIndex, TextClassifier.TYPE_EMAIL));
+    public void testSmartSelectionDoesNotThrowException() {
+        mClassifier.suggestSelection("text", 2, 3, LOCALES);
     }
 
     @Test
-    public void testSmartSelection_url() {
-        if (isTextClassifierDisabled()) return;
-
-        String text = "Visit http://www.android.com for more information";
-        String selected = "http";
-        String suggested = "http://www.android.com";
-        int startIndex = text.indexOf(selected);
-        int endIndex = startIndex + selected.length();
-        int smartStartIndex = text.indexOf(suggested);
-        int smartEndIndex = smartStartIndex + suggested.length();
-
-        assertThat(mClassifier.suggestSelection(text, startIndex, endIndex, LOCALES),
-                isTextSelection(smartStartIndex, smartEndIndex, TextClassifier.TYPE_URL));
+    public void testTextClassificationResultDoesNotThrowException() {
+        mClassifier.getTextClassificationResult("text", 2, 3, LOCALES);
     }
 
     @Test
-    public void testTextClassificationResult() {
-        if (isTextClassifierDisabled()) return;
-
-        String text = "Contact me at droid@android.com";
-        String classifiedText = "droid@android.com";
-        int startIndex = text.indexOf(classifiedText);
-        int endIndex = startIndex + classifiedText.length();
-        assertThat(mClassifier.getTextClassificationResult(text, startIndex, endIndex, LOCALES),
-                isTextClassificationResult(classifiedText, TextClassifier.TYPE_EMAIL));
-    }
-
-    @Test
-    public void testTextClassificationResult_url() {
-        if (isTextClassifierDisabled()) return;
-
-        String text = "Visit http://www.android.com for more information";
-        String classifiedText = "http://www.android.com";
-        int startIndex = text.indexOf(classifiedText);
-        int endIndex = startIndex + classifiedText.length();
-        assertThat(mClassifier.getTextClassificationResult(text, startIndex, endIndex, LOCALES),
-                isTextClassificationResult(classifiedText, TextClassifier.TYPE_URL));
-    }
-
-    @Test
-    public void testLanguageDetection() {
-        if (isTextClassifierDisabled()) return;
-
-        String text = "This is english text";
-        assertThat(mTcm.detectLanguages(text), isDetectedLanguage("en"));
-
-        text = "Das ist deutscher text";
-        assertThat(mTcm.detectLanguages(text), isDetectedLanguage("de"));
-
-        text = "これは日本語テキストです";
-        assertThat(mTcm.detectLanguages(text), isDetectedLanguage("ja"));
+    public void testLanguageDetectionDoesNotThrowException() {
+        mTcm.detectLanguages("text");
     }
 
     @Test
@@ -133,80 +68,4 @@
         mTcm.setTextClassifier(classifier);
         assertEquals(classifier, mTcm.getTextClassifier());
     }
-
-    private boolean isTextClassifierDisabled() {
-        return mClassifier == TextClassifier.NO_OP;
-    }
-
-    private static Matcher<TextSelection> isTextSelection(
-            final int startIndex, final int endIndex, final String type) {
-        return new BaseMatcher<TextSelection>() {
-            @Override
-            public boolean matches(Object o) {
-                if (o instanceof TextSelection) {
-                    TextSelection selection = (TextSelection) o;
-                    return startIndex == selection.getSelectionStartIndex()
-                            && endIndex == selection.getSelectionEndIndex()
-                            && selection.getEntityCount() > 0
-                            && type.equals(selection.getEntity(0));
-                }
-                return false;
-            }
-
-            @Override
-            public void describeTo(Description description) {
-                description.appendValue(
-                        String.format("%d, %d, %s", startIndex, endIndex, type));
-            }
-        };
-    }
-
-    private static Matcher<TextClassificationResult> isTextClassificationResult(
-            final String text, final String type) {
-        return new BaseMatcher<TextClassificationResult>() {
-            @Override
-            public boolean matches(Object o) {
-                if (o instanceof TextClassificationResult) {
-                    TextClassificationResult result = (TextClassificationResult) o;
-                    return text.equals(result.getText())
-                            && result.getEntityCount() > 0
-                            && type.equals(result.getEntity(0));
-                    // TODO: Include other properties.
-                }
-                return false;
-            }
-
-            @Override
-            public void describeTo(Description description) {
-                description.appendText("text=").appendValue(text)
-                        .appendText(", type=").appendValue(type);
-            }
-        };
-    }
-
-    private static Matcher<List<TextLanguage>> isDetectedLanguage(final String language) {
-        return new BaseMatcher<List<TextLanguage>>() {
-            @Override
-            public boolean matches(Object o) {
-                if (o instanceof List) {
-                    List languages = (List) o;
-                    if (!languages.isEmpty()) {
-                        Object o1 = languages.get(0);
-                        if (o1 instanceof TextLanguage) {
-                            TextLanguage lang = (TextLanguage) o1;
-                            return lang.getLanguageCount() > 0
-                                    && new Locale(language).getLanguage()
-                                            .equals(lang.getLanguage(0).getLanguage());
-                        }
-                    }
-                }
-                return false;
-            }
-
-            @Override
-            public void describeTo(Description description) {
-                description.appendValue(String.format("%s", language));
-            }
-        };
-    }
 }
diff --git a/tests/tests/widget/res/layout/textview_imeoptions.xml b/tests/tests/widget/res/layout/textview_imeoptions.xml
new file mode 100644
index 0000000..82b1d26
--- /dev/null
+++ b/tests/tests/widget/res/layout/textview_imeoptions.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+
+    <!-- Test EditorInfo.IME_NULL -->
+    <TextView
+        android:id="@+id/textview_imeoption_normal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:imeOptions="normal" />
+
+    <!-- Test EditorInfo.IME_ACTION_* -->
+    <TextView
+        android:id="@+id/textview_imeoption_action_unspecified"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:imeOptions="actionUnspecified" />
+    <TextView
+        android:id="@+id/textview_imeoption_action_none"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:imeOptions="actionNone" />
+    <TextView
+        android:id="@+id/textview_imeoption_action_go"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:imeOptions="actionGo" />
+    <TextView
+        android:id="@+id/textview_imeoption_action_search"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:imeOptions="actionSearch" />
+    <TextView
+        android:id="@+id/textview_imeoption_action_send"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:imeOptions="actionSend" />
+    <TextView
+        android:id="@+id/textview_imeoption_action_next"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:imeOptions="actionNext" />
+    <TextView
+        android:id="@+id/textview_imeoption_action_done"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:imeOptions="actionDone" />
+    <TextView
+        android:id="@+id/textview_imeoption_action_previous"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:imeOptions="actionPrevious" />
+
+    <!-- Test EditorInfo.IME_FLAG_* -->
+    <TextView
+        android:id="@+id/textview_imeoption_no_personalized_learning"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:imeOptions="flagNoPersonalizedLearning" />
+    <TextView
+        android:id="@+id/textview_imeoption_no_fullscreen"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:imeOptions="flagNoFullscreen" />
+    <TextView
+        android:id="@+id/textview_imeoption_navigation_previous"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:imeOptions="flagNavigatePrevious" />
+    <TextView
+        android:id="@+id/textview_imeoption_navigation_next"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:imeOptions="flagNavigateNext" />
+    <TextView
+        android:id="@+id/textview_imeoption_no_extract_ui"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:imeOptions="flagNoExtractUi" />
+    <TextView
+        android:id="@+id/textview_imeoption_no_accessory_action"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:imeOptions="flagNoAccessoryAction" />
+    <TextView
+        android:id="@+id/textview_imeoption_no_enter_action"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:imeOptions="flagNoEnterAction" />
+    <TextView
+        android:id="@+id/textview_imeoption_force_ascii"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:imeOptions="flagForceAscii" />
+
+    <!-- test an action with multiple flags -->
+    <TextView
+        android:id="@+id/textview_imeoption_action_go_nagivate_next_no_extract_ui_force_ascii"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:imeOptions="actionGo|flagNavigateNext|flagNoExtractUi|flagForceAscii" />
+
+</LinearLayout>
diff --git a/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java b/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java
index 4e33156..b2fd35c 100644
--- a/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java
@@ -362,6 +362,11 @@
         assertTrue(mAdapterView.isFocusable());
         assertTrue(mAdapterView.isFocusableInTouchMode());
 
+        // FOCUSABLE_AUTO should also work with children added (AbsListView is clickable)
+        mAdapterView.setFocusable(View.FOCUSABLE_AUTO);
+        assertTrue(mAdapterView.isFocusable());
+        assertTrue(mAdapterView.isFocusableInTouchMode());
+
         mAdapterView.setFocusable(false);
         assertFalse(mAdapterView.isFocusable());
         assertFalse(mAdapterView.isFocusableInTouchMode());
diff --git a/tests/tests/widget/src/android/widget/cts/ImageViewTest.java b/tests/tests/widget/src/android/widget/cts/ImageViewTest.java
index 2b55ed5..5476b22 100644
--- a/tests/tests/widget/src/android/widget/cts/ImageViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ImageViewTest.java
@@ -510,7 +510,6 @@
         Drawable backgroundDrawable = new ColorDrawable(0xFF0000FF);
         mockImageView.setBackgroundDrawable(backgroundDrawable);
 
-        assertFalse(mockImageView.verifyDrawable(null));
         assertFalse(mockImageView.verifyDrawable(new ColorDrawable(0xFF00FF00)));
         assertTrue(mockImageView.verifyDrawable(drawable));
         assertTrue(mockImageView.verifyDrawable(backgroundDrawable));
diff --git a/tests/tests/widget/src/android/widget/cts/ProgressBarTest.java b/tests/tests/widget/src/android/widget/cts/ProgressBarTest.java
index 4ced4fb..5a68273 100644
--- a/tests/tests/widget/src/android/widget/cts/ProgressBarTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ProgressBarTest.java
@@ -514,26 +514,22 @@
     public void testVerifyDrawable() {
         MockProgressBar mockProgressBar =
                 (MockProgressBar) mActivity.findViewById(R.id.progress_custom);
-        assertTrue(mockProgressBar.verifyDrawable(null));
 
         Drawable d1 = mActivity.getDrawable(R.drawable.blue);
         Drawable d2 = mActivity.getDrawable(R.drawable.red);
         Drawable d3 = mActivity.getDrawable(R.drawable.yellow);
 
         mockProgressBar.setBackgroundDrawable(d1);
-        assertTrue(mockProgressBar.verifyDrawable(null));
         assertTrue(mockProgressBar.verifyDrawable(d1));
         assertFalse(mockProgressBar.verifyDrawable(d2));
         assertFalse(mockProgressBar.verifyDrawable(d3));
 
         mockProgressBar.setIndeterminateDrawable(d2);
-        assertTrue(mockProgressBar.verifyDrawable(null));
         assertTrue(mockProgressBar.verifyDrawable(d1));
         assertTrue(mockProgressBar.verifyDrawable(d2));
         assertFalse(mockProgressBar.verifyDrawable(d3));
 
         mockProgressBar.setProgressDrawable(d3);
-        assertFalse(mockProgressBar.verifyDrawable(null));
         assertTrue(mockProgressBar.verifyDrawable(d1));
         assertTrue(mockProgressBar.verifyDrawable(d2));
         assertTrue(mockProgressBar.verifyDrawable(d3));
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index 3da2cb4..a7cde1a 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -42,6 +42,9 @@
 import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.annotation.IntDef;
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.app.Instrumentation.ActivityMonitor;
@@ -158,6 +161,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
+import java.lang.annotation.Retention;
 import java.util.Arrays;
 import java.util.Locale;
 
@@ -411,6 +415,108 @@
         assertEquals(-1, mTextView.getGravity());
     }
 
+    @Retention(SOURCE)
+    @IntDef({EditorInfo.IME_ACTION_UNSPECIFIED, EditorInfo.IME_ACTION_NONE,
+            EditorInfo.IME_ACTION_GO, EditorInfo.IME_ACTION_SEARCH, EditorInfo.IME_ACTION_SEND,
+            EditorInfo.IME_ACTION_NEXT, EditorInfo.IME_ACTION_DONE, EditorInfo.IME_ACTION_PREVIOUS})
+    private @interface ImeOptionAction {}
+
+    @Retention(SOURCE)
+    @IntDef(flag = true,
+            value = {EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING,
+                    EditorInfo.IME_FLAG_NO_FULLSCREEN, EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS,
+                    EditorInfo.IME_FLAG_NAVIGATE_NEXT, EditorInfo.IME_FLAG_NO_EXTRACT_UI,
+                    EditorInfo.IME_FLAG_NO_ACCESSORY_ACTION, EditorInfo.IME_FLAG_NO_ENTER_ACTION,
+                    EditorInfo.IME_FLAG_FORCE_ASCII})
+    private @interface ImeOptionFlags {}
+
+    private static void assertImeOptions(TextView textView,
+            @ImeOptionAction int expectedImeOptionAction,
+            @ImeOptionFlags int expectedImeOptionFlags) {
+        final int actualAction = textView.getImeOptions() & EditorInfo.IME_MASK_ACTION;
+        final int actualFlags = textView.getImeOptions() & ~EditorInfo.IME_MASK_ACTION;
+        assertEquals(expectedImeOptionAction, actualAction);
+        assertEquals(expectedImeOptionFlags, actualFlags);
+    }
+
+    @UiThreadTest
+    @Test
+    public void testImeOptions() {
+        mActivity.setContentView(R.layout.textview_imeoptions);
+
+        // Test "normal" to be a synonym EditorInfo.IME_NULL
+        assertEquals(EditorInfo.IME_NULL,
+                mActivity.<TextView>findViewById(R.id.textview_imeoption_normal).getImeOptions());
+
+        // Test EditorInfo.IME_ACTION_*
+        assertImeOptions(
+                mActivity.findViewById(R.id.textview_imeoption_action_unspecified),
+                EditorInfo.IME_ACTION_UNSPECIFIED, 0);
+        assertImeOptions(
+                mActivity.findViewById(R.id.textview_imeoption_action_none),
+                EditorInfo.IME_ACTION_NONE, 0);
+        assertImeOptions(
+                mActivity.findViewById(R.id.textview_imeoption_action_go),
+                EditorInfo.IME_ACTION_GO, 0);
+        assertImeOptions(
+                mActivity.findViewById(R.id.textview_imeoption_action_search),
+                EditorInfo.IME_ACTION_SEARCH, 0);
+        assertImeOptions(
+                mActivity.findViewById(R.id.textview_imeoption_action_send),
+                EditorInfo.IME_ACTION_SEND, 0);
+        assertImeOptions(
+                mActivity.findViewById(R.id.textview_imeoption_action_next),
+                EditorInfo.IME_ACTION_NEXT, 0);
+        assertImeOptions(
+                mActivity.findViewById(R.id.textview_imeoption_action_done),
+                EditorInfo.IME_ACTION_DONE, 0);
+        assertImeOptions(
+                mActivity.findViewById(R.id.textview_imeoption_action_previous),
+                EditorInfo.IME_ACTION_PREVIOUS, 0);
+
+        // Test EditorInfo.IME_FLAG_*
+        assertImeOptions(
+                mActivity.findViewById(R.id.textview_imeoption_no_personalized_learning),
+                EditorInfo.IME_ACTION_UNSPECIFIED,
+                EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING);
+        assertImeOptions(
+                mActivity.findViewById(R.id.textview_imeoption_no_fullscreen),
+                EditorInfo.IME_ACTION_UNSPECIFIED,
+                EditorInfo.IME_FLAG_NO_FULLSCREEN);
+        assertImeOptions(
+                mActivity.findViewById(R.id.textview_imeoption_navigation_previous),
+                EditorInfo.IME_ACTION_UNSPECIFIED,
+                EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS);
+        assertImeOptions(
+                mActivity.findViewById(R.id.textview_imeoption_navigation_next),
+                EditorInfo.IME_ACTION_UNSPECIFIED,
+                EditorInfo.IME_FLAG_NAVIGATE_NEXT);
+        assertImeOptions(
+                mActivity.findViewById(R.id.textview_imeoption_no_extract_ui),
+                EditorInfo.IME_ACTION_UNSPECIFIED,
+                EditorInfo.IME_FLAG_NO_EXTRACT_UI);
+        assertImeOptions(
+                mActivity.findViewById(R.id.textview_imeoption_no_accessory_action),
+                EditorInfo.IME_ACTION_UNSPECIFIED,
+                EditorInfo.IME_FLAG_NO_ACCESSORY_ACTION);
+        assertImeOptions(
+                mActivity.findViewById(R.id.textview_imeoption_no_enter_action),
+                EditorInfo.IME_ACTION_UNSPECIFIED,
+                EditorInfo.IME_FLAG_NO_ENTER_ACTION);
+        assertImeOptions(
+                mActivity.findViewById(R.id.textview_imeoption_force_ascii),
+                EditorInfo.IME_ACTION_UNSPECIFIED,
+                EditorInfo.IME_FLAG_FORCE_ASCII);
+
+        // test action + multiple flags
+        assertImeOptions(
+                mActivity.findViewById(
+                        R.id.textview_imeoption_action_go_nagivate_next_no_extract_ui_force_ascii),
+                EditorInfo.IME_ACTION_GO,
+                EditorInfo.IME_FLAG_NAVIGATE_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI
+                        | EditorInfo.IME_FLAG_FORCE_ASCII);
+    }
+
     @Test
     public void testAccessAutoLinkMask() throws Throwable {
         mTextView = findTextView(R.id.textview_text);
@@ -4546,7 +4652,7 @@
                 | InputType.TYPE_NUMBER_FLAG_DECIMAL
                 | InputType.TYPE_NUMBER_FLAG_SIGNED, mTextView.getInputType());
         assertSame(mTextView.getKeyListener(),
-                DigitsKeyListener.getInstance(mTextView.getTextLocale(), true, true));
+                DigitsKeyListener.getInstance(null, true, true));
 
         mTextView.setInputType(InputType.TYPE_CLASS_PHONE);
         assertEquals(InputType.TYPE_CLASS_PHONE, mTextView.getInputType());
@@ -4762,6 +4868,59 @@
 
     @UiThreadTest
     @Test
+    public void testSetImeHintLocalesChangesInputType() {
+        final TextView textView = new TextView(mActivity);
+        textView.setText("", BufferType.EDITABLE);
+
+        textView.setInputType(InputType.TYPE_CLASS_NUMBER);
+        assertEquals(InputType.TYPE_CLASS_NUMBER, textView.getInputType());
+
+        final LocaleList localeList = LocaleList.forLanguageTags("fa-IR");
+        textView.setImeHintLocales(localeList);
+        final int textType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL;
+        // Setting IME hint locales to Persian must change the input type to a full text IME,
+        // since the typical number input IME may not have localized digits.
+        assertEquals(textType, textView.getInputType());
+
+        // Changing the input type to datetime should keep the full text IME, since the IME hint
+        // is still set to Persian, which needs advanced input.
+        final int dateType = InputType.TYPE_CLASS_DATETIME | InputType.TYPE_DATETIME_VARIATION_DATE;
+        textView.setInputType(dateType);
+        assertEquals(textType, textView.getInputType());
+
+        // Changing the input type to number password should keep the full text IME, since the IME
+        // hint is still set to Persian, which needs advanced input. But it also needs to set the
+        // text password flag.
+        final int numberPasswordType = InputType.TYPE_CLASS_NUMBER
+                | InputType.TYPE_NUMBER_VARIATION_PASSWORD;
+        final int textPasswordType = InputType.TYPE_CLASS_TEXT
+                | InputType.TYPE_TEXT_VARIATION_PASSWORD;
+        textView.setInputType(numberPasswordType);
+        assertEquals(textPasswordType, textView.getInputType());
+
+        // Setting the IME hint locales to null should reset the type to number password, since we
+        // no longer need internationalized input.
+        textView.setImeHintLocales(null);
+        assertEquals(numberPasswordType, textView.getInputType());
+    }
+
+    @UiThreadTest
+    @Test
+    public void testSetImeHintLocalesDoesntLoseInputType() {
+        final TextView textView = new TextView(mActivity);
+        textView.setText("", BufferType.EDITABLE);
+        final int inputType = InputType.TYPE_CLASS_TEXT
+                | InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT
+                | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS
+                | InputType.TYPE_TEXT_FLAG_MULTI_LINE
+                | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
+        textView.setInputType(inputType);
+        textView.setImeHintLocales(new LocaleList(Locale.US));
+        assertEquals(inputType, textView.getInputType());
+    }
+
+    @UiThreadTest
+    @Test
     public void testSetExtractedText() {
         mTextView = findTextView(R.id.textview_text);
         assertEquals(mActivity.getResources().getString(R.string.text_view_hello),
@@ -6630,19 +6789,17 @@
     public void testAutoSizeCallers_setHorizontallyScrolling() throws Throwable {
         final TextView autoSizeTextView = prepareAndRetrieveAutoSizeTestData(
                 R.id.textview_autosize_uniform, false);
+        // Verify that we do not have horizontal scrolling turned on.
+        assertTrue(!autoSizeTextView.getHorizontallyScrolling());
+
         final float initialTextSize = autoSizeTextView.getTextSize();
-        mActivityRule.runOnUiThread(() -> autoSizeTextView.setHorizontallyScrolling(
-                !autoSizeTextView.getHorizontallyScrolling()));
+        mActivityRule.runOnUiThread(() -> autoSizeTextView.setHorizontallyScrolling(true));
         mInstrumentation.waitForIdleSync();
-        final float changedTextSize = autoSizeTextView.getTextSize();
+        assertTrue(autoSizeTextView.getTextSize() > initialTextSize);
 
-        assertTrue(changedTextSize < initialTextSize);
-
-        mActivityRule.runOnUiThread(() -> autoSizeTextView.setHorizontallyScrolling(
-                autoSizeTextView.getHorizontallyScrolling()));
+        mActivityRule.runOnUiThread(() -> autoSizeTextView.setHorizontallyScrolling(false));
         mInstrumentation.waitForIdleSync();
-
-        assertEquals(changedTextSize, autoSizeTextView.getTextSize(), 0f);
+        assertEquals(initialTextSize, autoSizeTextView.getTextSize(), 0f);
     }
 
     @Test
@@ -7346,8 +7503,8 @@
         }
 
         private void calculatePositions() {
-            int xStart = (int) mParent.getLayout().getPrimaryHorizontal(mStartCharPos, true, true);
-            int xEnd = (int) mParent.getLayout().getPrimaryHorizontal(mEndCharPos, true, true);
+            int xStart = (int) mParent.getLayout().getPrimaryHorizontal(mStartCharPos, true);
+            int xEnd = (int) mParent.getLayout().getPrimaryHorizontal(mEndCharPos, true);
             int line = mParent.getLayout().getLineForOffset(mEndCharPos);
             int yTop = mParent.getLayout().getLineTop(line);
             int yBottom = mParent.getLayout().getLineBottom(line);
@@ -7487,8 +7644,8 @@
      */
     private static Point getCenterPositionOfTextAt(
             TextView textView, int startIndex, int endIndex) {
-        int xStart = (int) textView.getLayout().getPrimaryHorizontal(startIndex, true, true);
-        int xEnd = (int) textView.getLayout().getPrimaryHorizontal(endIndex, true, true);
+        int xStart = (int) textView.getLayout().getPrimaryHorizontal(startIndex, true);
+        int xEnd = (int) textView.getLayout().getPrimaryHorizontal(endIndex, true);
         int line = textView.getLayout().getLineForOffset(endIndex);
         int yTop = textView.getLayout().getLineTop(line);
         int yBottom = textView.getLayout().getLineBottom(line);
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index 769336d..f694daa 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -175,20 +175,16 @@
     <!-- b/31803630 -->
     <option name="compatibility:exclude-filter" value="CtsSecurityTestCases android.security.cts.ListeningPortsTest" />
 
-    <!-- b/36812770 -->
-    <option name="compatibility:exclude-filter" value="CtsSensorTestCases android.hardware.cts.SensorDirectReportTest#testAccelerometerHardwareBufferNormal" />
-    <option name="compatibility:exclude-filter" value="CtsSensorTestCases android.hardware.cts.SensorDirectReportTest#testGyroscopeHardwareBufferNormal" />
-    <option name="compatibility:exclude-filter" value="CtsSensorTestCases android.hardware.cts.SensorDirectReportTest#testMagneticFieldHardwareBufferNormal" />
-    <option name="compatibility:exclude-filter" value="CtsSensorTestCases android.hardware.cts.SensorDirectReportTest#testAccelerometerHardwareBufferFast" />
-    <option name="compatibility:exclude-filter" value="CtsSensorTestCases android.hardware.cts.SensorDirectReportTest#testGyroscopeHardwareBufferFast" />
-    <option name="compatibility:exclude-filter" value="CtsSensorTestCases android.hardware.cts.SensorDirectReportTest#testMagneticFieldHardwareBufferFast" />
-    <option name="compatibility:exclude-filter" value="CtsSensorTestCases android.hardware.cts.SensorDirectReportTest#testAccelerometerHardwareBufferVeryFast" />
-    <option name="compatibility:exclude-filter" value="CtsSensorTestCases android.hardware.cts.SensorDirectReportTest#testGyroscopeHardwareBufferVeryFast" />
-    <option name="compatibility:exclude-filter" value="CtsSensorTestCases android.hardware.cts.SensorDirectReportTest#testMagneticFieldHardwareBufferVeryFast" />
+    <!-- b/36686383 -->
+    <option name="compatibility:exclude-filter" value="CtsIncidentHostTestCases com.android.server.cts.ErrorsTest#testANR" />
 
-    <!-- b/37216168 -->
-    <option name="compatibility:exclude-filter" value="CtsNativeHardwareTestCases AHardwareBufferTest#AHardwareBuffer_SendAndRecv_Succeeds" />
+    <!-- b/33090965 -->
+    <option name="compatibility:exclude-filter" value="CtsVideoTestCases android.video.cts.VideoEncoderDecoderTest#testVp9Goog0Perf0320x0180" />
+    <option name="compatibility:exclude-filter" value="CtsVideoTestCases android.video.cts.VideoEncoderDecoderTest#testVp9Goog0Perf0640x0360" />
+    <option name="compatibility:exclude-filter" value="CtsVideoTestCases android.video.cts.VideoEncoderDecoderTest#testVp9Goog0Perf1280x0720" />
+    <option name="compatibility:exclude-filter" value="CtsVideoTestCases android.video.cts.VideoEncoderDecoderTest#testVp9Goog0Perf1920x1080" />
 
-    <!-- b/37108688 -->
-    <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.HardwareBufferTest#testCreate" />
+    <!-- b/37105075 -->
+    <option name="compatibility:exclude-filter" value="CtsIncidentHostTestCases com.android.server.cts.BatteryStatsValidationTest#testWifiUpload" />
+
 </configuration>
diff --git a/tools/cts-tradefed/res/config/cts-vendor-interface.xml b/tools/cts-tradefed/res/config/cts-vendor-interface.xml
index 582cebf..6785dd8 100644
--- a/tools/cts-tradefed/res/config/cts-vendor-interface.xml
+++ b/tools/cts-tradefed/res/config/cts-vendor-interface.xml
@@ -44,6 +44,7 @@
     <option name="compatibility:include-filter" value="CtsMonkeyTestCases" />
     <option name="compatibility:include-filter" value="CtsNetTestCases" />
     <option name="compatibility:include-filter" value="CtsOsTestCases" />
+    <option name="compatibility:include-filter" value="CtsPdfTestCases" />
     <option name="compatibility:include-filter" value="CtsPreference2TestCases" />
     <option name="compatibility:include-filter" value="CtsPrintTestCases" />
     <option name="compatibility:include-filter" value="CtsProviderTestCases" />
diff --git a/tools/cts-tradefed/res/config/cts.xml b/tools/cts-tradefed/res/config/cts.xml
index 28a5c27..0e31afb 100644
--- a/tools/cts-tradefed/res/config/cts.xml
+++ b/tools/cts-tradefed/res/config/cts.xml
@@ -24,6 +24,10 @@
     <option name="test-tag" value="cts" />
 
     <option name="enable-root" value="false" />
+    <!-- retain 200MB of host log -->
+    <option name="max-log-size" value="200" />
+    <!--  retain 200MB of logcat -->
+    <option name="max-tmp-logcat-file" value="209715200" />
 
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.PropertyCheck">
         <option name="property-name" value="ro.build.type" />