Merge \\\"Add test to detect some rendering inaccuracy.\\\" into nyc-dev am: f6df828780 am: 8350d5a913
am: 5b57a34915

Change-Id: Icadbfc82af5dd9a38c6f770286455ed255c7f939
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java
index d7fa7a7..98a63c2 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java
@@ -151,7 +151,7 @@
         helpBuilder.append("  help: show this message.\n");
         helpBuilder.append("  help all: show the complete tradefed help.\n");
         helpBuilder.append("  version: show the version.\n");
-        helpBuilder.append("  exit: gracefully exit the compatibiltiy console, waiting until all ");
+        helpBuilder.append("  exit: gracefully exit the compatibility console, waiting until all ");
         helpBuilder.append("invocations have completed.\n");
         helpBuilder.append("Run:\n");
         final String runPrompt = "  run <plan> ";
diff --git a/hostsidetests/compilation/src/android/cts/compilation/AdbRootDependentCompilationTest.java b/hostsidetests/compilation/src/android/cts/compilation/AdbRootDependentCompilationTest.java
index ab7dc43..24fad97 100644
--- a/hostsidetests/compilation/src/android/cts/compilation/AdbRootDependentCompilationTest.java
+++ b/hostsidetests/compilation/src/android/cts/compilation/AdbRootDependentCompilationTest.java
@@ -36,9 +36,17 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
 /**
- * Tests that profile guided compilation succeeds regardless of whether a runtime
- * profile of the target application is present on the device.
+ * Various integration tests for dex to oat compilation, with or without profiles.
+ * When changing this test, make sure it still passes in each of the following
+ * configurations:
+ * <ul>
+ *     <li>On a 'user' build</li>
+ *     <li>On a 'userdebug' build with system property 'dalvik.vm.usejitprofiles' set to false</li>
+ *     <li>On a 'userdebug' build with system property 'dalvik.vm.usejitprofiles' set to true</li>
+ * </ul>
  */
 public class AdbRootDependentCompilationTest extends DeviceTestCase {
     private static final String TAG = AdbRootDependentCompilationTest.class.getSimpleName();
@@ -66,8 +74,6 @@
     private ITestDevice mDevice;
     private byte[] profileBytes;
     private File localProfileFile;
-    private String odexFilePath;
-    private byte[] initialOdexFileContents;
     private File apkFile;
     private boolean mIsRoot;
     private boolean mNewlyObtainedRoot;
@@ -101,20 +107,6 @@
         localProfileFile = File.createTempFile("compilationtest", "prof");
         Files.write(profileBytes, localProfileFile);
         assertTrue("empty profile", profileBytes.length > 0); // sanity check
-
-        if (mIsRoot) {
-            // ensure no profiles initially present
-            for (ProfileLocation profileLocation : ProfileLocation.values()) {
-                String clientPath = profileLocation.getPath();
-                if (mDevice.doesFileExist(clientPath)) {
-                    executeAdbCommand(0, "shell", "rm", clientPath);
-                }
-            }
-            executeCompile(/* force */ true);
-            this.odexFilePath = getOdexFilePath();
-            this.initialOdexFileContents = readFileOnClient(odexFilePath);
-            assertTrue("empty odex file", initialOdexFileContents.length > 0); // sanity check
-        }
     }
 
     @Override
@@ -128,6 +120,29 @@
         super.tearDown();
     }
 
+    /**
+     * Tests compilation using {@code -r bg-dexopt -f}.
+     */
+    public void testCompile_bgDexopt() throws Exception {
+        if (!canRunTest(EnumSet.noneOf(ProfileLocation.class))) {
+            return;
+        }
+        // Usually "interpret-only"
+        String expectedInstallFilter = checkNotNull(mDevice.getProperty("pm.dexopt.install"));
+        // Usually "speed-profile"
+        String expectedBgDexoptFilter = checkNotNull(mDevice.getProperty("pm.dexopt.bg-dexopt"));
+
+        String odexPath = getOdexFilePath();
+        assertEquals(expectedInstallFilter, getCompilerFilter(odexPath));
+
+        // Without -f, the compiler would only run if it judged the bg-dexopt filter to
+        // be "better" than the install filter. However manufacturers can change those
+        // values so we don't want to depend here on the resulting filter being better.
+        executeCompile("-r", "bg-dexopt", "-f");
+
+        assertEquals(expectedBgDexoptFilter, getCompilerFilter(odexPath));
+    }
+
     /*
      The tests below test the remaining combinations of the "ref" (reference) and
      "cur" (current) profile being available. The "cur" profile gets moved/merged
@@ -140,53 +155,31 @@
      profile_assistant, it may only be available in "ref".
      */
 
-    public void testForceCompile_noProfile() throws Exception {
-        Set<ProfileLocation> profileLocations = EnumSet.noneOf(ProfileLocation.class);
-        if (!canRunTest(profileLocations)) {
-            return;
-        }
-        compileWithProfilesAndCheckFilter(profileLocations);
-        byte[] odexFileContents = readFileOnClient(odexFilePath);
-        assertBytesEqual(initialOdexFileContents, odexFileContents);
+    public void testCompile_noProfile() throws Exception {
+        compileWithProfilesAndCheckFilter(false /* expectOdexChange */,
+                EnumSet.noneOf(ProfileLocation.class));
     }
 
-    public void testForceCompile_curProfile() throws Exception {
-        Set<ProfileLocation> profileLocations = EnumSet.of(ProfileLocation.CUR);
-        if (!canRunTest(profileLocations)) {
-            return;
+    public void testCompile_curProfile() throws Exception {
+        boolean didRun = compileWithProfilesAndCheckFilter(true  /* expectOdexChange */,
+                 EnumSet.of(ProfileLocation.CUR));
+        if (didRun) {
+            assertTrue("ref profile should have been created by the compiler",
+                    mDevice.doesFileExist(ProfileLocation.REF.getPath()));
         }
-        compileWithProfilesAndCheckFilter(profileLocations);
-        assertTrue("ref profile should have been created by the compiler",
-                mDevice.doesFileExist(ProfileLocation.REF.getPath()));
-        assertFalse("odex compiled with cur profile should differ from the initial one without",
-                Arrays.equals(initialOdexFileContents, readFileOnClient(odexFilePath)));
     }
 
-    public void testForceCompile_refProfile() throws Exception {
-        Set<ProfileLocation> profileLocations = EnumSet.of(ProfileLocation.REF);
-        if (!canRunTest(profileLocations)) {
-            return;
-        }
-        compileWithProfilesAndCheckFilter(profileLocations);
+    public void testCompile_refProfile() throws Exception {
+        compileWithProfilesAndCheckFilter(false /* expectOdexChange */,
+                 EnumSet.of(ProfileLocation.REF));
         // We assume that the compiler isn't smart enough to realize that the
         // previous odex was compiled before the ref profile was in place, even
         // though theoretically it could be.
-        byte[] odexFileContents = readFileOnClient(odexFilePath);
-        assertBytesEqual(initialOdexFileContents, odexFileContents);
     }
 
-    public void testForceCompile_curAndRefProfile() throws Exception {
-        Set<ProfileLocation> profileLocations = EnumSet.of(
-                ProfileLocation.CUR, ProfileLocation.REF);
-        if (!canRunTest(profileLocations)) {
-            return;
-        }
-        compileWithProfilesAndCheckFilter(profileLocations);
-        // We assume that the compiler isn't smart enough to realize that the
-        // previous odex was compiled before the ref profile was in place, even
-        // though theoretically it could be.
-        byte[] odexFileContents = readFileOnClient(odexFilePath);
-        assertBytesEqual(initialOdexFileContents, odexFileContents);
+    public void testCompile_curAndRefProfile() throws Exception {
+        compileWithProfilesAndCheckFilter(false /* expectOdexChange */,
+                EnumSet.of(ProfileLocation.CUR, ProfileLocation.REF));
     }
 
     private byte[] readFileOnClient(String clientPath) throws Exception {
@@ -204,29 +197,58 @@
     /**
      * Places {@link #profileBytes} in the specified locations, recompiles (without -f)
      * and checks the compiler-filter in the odex file.
+     *
+     * @return whether the test ran (as opposed to early exit)
      */
-    private void compileWithProfilesAndCheckFilter(Set<ProfileLocation> profileLocations)
+    private boolean compileWithProfilesAndCheckFilter(boolean expectOdexChange,
+            Set<ProfileLocation> profileLocations)
             throws Exception {
+        if (!canRunTest(profileLocations)) {
+            return false;
+        }
+        // ensure no profiles initially present
+        for (ProfileLocation profileLocation : ProfileLocation.values()) {
+            String clientPath = profileLocation.getPath();
+            if (mDevice.doesFileExist(clientPath)) {
+                executeAdbCommand(0, "shell", "rm", clientPath);
+            }
+        }
+        executeCompile("-m", "speed-profile", "-f");
+        String odexFilePath = getOdexFilePath();
+        byte[] initialOdexFileContents = readFileOnClient(odexFilePath);
+        assertTrue("empty odex file", initialOdexFileContents.length > 0); // sanity check
+
         for (ProfileLocation profileLocation : profileLocations) {
             writeProfile(profileLocation);
         }
-        executeCompile(/* force */ false);
+        executeCompile("-m", "speed-profile");
 
         // Confirm the compiler-filter used in creating the odex file
         String compilerFilter = getCompilerFilter(odexFilePath);
 
         assertEquals("compiler-filter", "speed-profile", compilerFilter);
+
+        byte[] odexFileContents = readFileOnClient(odexFilePath);
+        boolean odexChanged = !(Arrays.equals(initialOdexFileContents, odexFileContents));
+        if (odexChanged && !expectOdexChange) {
+            String msg = String.format(Locale.US, "Odex file without filters (%d bytes) "
+                    + "unexpectedly different from odex file (%d bytes) compiled with filters: %s",
+                    initialOdexFileContents.length, odexFileContents.length, profileLocations);
+            fail(msg);
+        } else if (!odexChanged && expectOdexChange) {
+            fail("odex file should have changed when recompiling with " + profileLocations);
+        }
+        return true;
     }
 
     /**
      * Invokes the dex2oat compiler on the client.
+     *
+     * @param compileOptions extra options to pass to the compiler on the command line
      */
-    private void executeCompile(boolean force) throws Exception {
-        List<String> command = new ArrayList<>(Arrays.asList("shell", "cmd", "package", "compile",
-                "-m", "speed-profile"));
-        if (force) {
-            command.add("-f");
-        }
+    private void executeCompile(String... compileOptions) throws Exception {
+        List<String> command = new ArrayList<>(Arrays.asList("shell", "cmd", "package", "compile"));
+        command.addAll(Arrays.asList(compileOptions));
         command.add(APPLICATION_PACKAGE);
         String[] commandArray = command.toArray(new String[0]);
         assertEquals("Success", executeAdbCommand(1, commandArray)[0]);
@@ -292,8 +314,8 @@
     }
 
     /**
-     * Returns whether a test can run in the current device configuration
-     * and for the given profileLocations. This allows tests to exit early.
+     * Returns whether a test that uses the given profileLocations can run
+     * in the current device configuration. This allows tests to exit early.
      *
      * <p>Ideally we'd like tests to be marked as skipped/ignored or similar
      * rather than passing if they can't run on the current device, but that
@@ -332,10 +354,4 @@
         String[] lines = output.equals("") ? new String[0] : output.split("\n");
         return lines;
     }
-
-    private static void assertBytesEqual(byte[] expected, byte[] actual) {
-        String msg = String.format("Expected %d bytes differ from actual %d bytes",
-                expected.length, actual.length);
-        assertTrue(msg, Arrays.equals(expected, actual));
-    }
 }
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/api23/Android.mk b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/api23/Android.mk
index b1c35aac..5d32955 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/api23/Android.mk
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/api23/Android.mk
@@ -26,7 +26,7 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 ctsdeviceutil ctstestrunner ub-uiautomator
 
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := test_current
 
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/../res
 
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/Android.mk b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/Android.mk
index 7d08bc3..884bb0b 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/Android.mk
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/Android.mk
@@ -26,7 +26,7 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 ctsdeviceutil ctstestrunner ub-uiautomator
 
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := test_current
 
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/../res
 
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/AndroidManifest.xml b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/AndroidManifest.xml
index 744db8f..1c9d24d 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/AndroidManifest.xml
@@ -25,7 +25,8 @@
     <uses-permission android:name="android.permission.SET_WALLPAPER" />
     <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
 
-    <application
+    <!-- Add a network security config that trusts user added CAs for tests -->
+    <application android:networkSecurityConfig="@xml/network_security_config"
         android:testOnly="true">
 
         <uses-library android:name="android.test.runner" />
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/res/xml/network_security_config.xml b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/xml/network_security_config.xml
similarity index 100%
rename from hostsidetests/devicepolicy/app/DeviceOwner/res/xml/network_security_config.xml
rename to hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/xml/network_security_config.xml
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AlwaysOnVpnTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AlwaysOnVpnTest.java
index 34566a1..01a5a3a 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AlwaysOnVpnTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AlwaysOnVpnTest.java
@@ -17,6 +17,7 @@
 package com.android.cts.deviceandprofileowner;
 
 import android.os.Bundle;
+import android.os.UserManager;
 
 import com.android.cts.deviceandprofileowner.vpn.VpnTestHelper;
 
@@ -63,6 +64,18 @@
         VpnTestHelper.checkPing(TEST_ADDRESS);
     }
 
+    public void testDisallowConfigVpn() throws Exception {
+        mDevicePolicyManager.addUserRestriction(
+                ADMIN_RECEIVER_COMPONENT, UserManager.DISALLOW_CONFIG_VPN);
+        try {
+            testAlwaysOnVpn();
+        } finally {
+            // clear the user restriction
+            mDevicePolicyManager.clearUserRestriction(ADMIN_RECEIVER_COMPONENT,
+                    UserManager.DISALLOW_CONFIG_VPN);
+        }
+    }
+
     public void testAllowedApps() throws Exception {
         final Bundle restrictions = new Bundle();
         restrictions.putStringArray(RESTRICTION_ALLOWED, new String[] {mPackageName});
@@ -97,4 +110,3 @@
         assertNull(mDevicePolicyManager.getAlwaysOnVpnPackage(ADMIN_RECEIVER_COMPONENT));
     }
 }
-
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CaCertManagementTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/CaCertManagementTest.java
similarity index 84%
rename from hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CaCertManagementTest.java
rename to hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/CaCertManagementTest.java
index 3e692c3..feb4a9b 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CaCertManagementTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/CaCertManagementTest.java
@@ -13,8 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.cts.deviceowner;
+package com.android.cts.deviceandprofileowner;
 
+import android.content.ComponentName;
 import android.net.http.X509TrustManagerExtensions;
 import android.security.NetworkSecurityPolicy;
 
@@ -32,17 +33,19 @@
 import javax.net.ssl.TrustManagerFactory;
 import javax.net.ssl.X509TrustManager;
 
-import static com.android.cts.deviceowner.FakeKeys.FAKE_DSA_1;
-import static com.android.cts.deviceowner.FakeKeys.FAKE_RSA_1;
+import static android.cts.util.FakeKeys.FAKE_DSA_1;
+import static android.cts.util.FakeKeys.FAKE_RSA_1;
 
-public class CaCertManagementTest extends BaseDeviceOwnerTest {
+public class CaCertManagementTest extends BaseDeviceAdminTest {
+    private final ComponentName mAdmin = ADMIN_RECEIVER_COMPONENT;
+
     /**
      * Test: device admins should be able to list all installed certs.
      *
      * <p>The list of certificates must never be {@code null}.
      */
     public void testCanRetrieveListOfInstalledCaCerts() {
-        List<byte[]> caCerts = mDevicePolicyManager.getInstalledCaCerts(getWho());
+        List<byte[]> caCerts = mDevicePolicyManager.getInstalledCaCerts(mAdmin);
         assertNotNull(caCerts);
     }
 
@@ -54,11 +57,11 @@
         assertUninstalled(FAKE_RSA_1.caCertificate);
         assertUninstalled(FAKE_DSA_1.caCertificate);
 
-        assertTrue(mDevicePolicyManager.installCaCert(getWho(), FAKE_RSA_1.caCertificate));
+        assertTrue(mDevicePolicyManager.installCaCert(mAdmin, FAKE_RSA_1.caCertificate));
         assertInstalled(FAKE_RSA_1.caCertificate);
         assertUninstalled(FAKE_DSA_1.caCertificate);
 
-        mDevicePolicyManager.uninstallCaCert(getWho(), FAKE_RSA_1.caCertificate);
+        mDevicePolicyManager.uninstallCaCert(mAdmin, FAKE_RSA_1.caCertificate);
         assertUninstalled(FAKE_RSA_1.caCertificate);
         assertUninstalled(FAKE_DSA_1.caCertificate);
     }
@@ -68,14 +71,14 @@
      */
     public void testUninstallationIsSelective()
             throws CertificateException, GeneralSecurityException {
-        assertTrue(mDevicePolicyManager.installCaCert(getWho(), FAKE_RSA_1.caCertificate));
-        assertTrue(mDevicePolicyManager.installCaCert(getWho(), FAKE_DSA_1.caCertificate));
+        assertTrue(mDevicePolicyManager.installCaCert(mAdmin, FAKE_RSA_1.caCertificate));
+        assertTrue(mDevicePolicyManager.installCaCert(mAdmin, FAKE_DSA_1.caCertificate));
 
-        mDevicePolicyManager.uninstallCaCert(getWho(), FAKE_DSA_1.caCertificate);
+        mDevicePolicyManager.uninstallCaCert(mAdmin, FAKE_DSA_1.caCertificate);
         assertInstalled(FAKE_RSA_1.caCertificate);
         assertUninstalled(FAKE_DSA_1.caCertificate);
 
-        mDevicePolicyManager.uninstallCaCert(getWho(), FAKE_RSA_1.caCertificate);
+        mDevicePolicyManager.uninstallCaCert(mAdmin, FAKE_RSA_1.caCertificate);
     }
 
     /**
@@ -84,10 +87,10 @@
      */
     public void testCanUninstallAllUserCaCerts()
             throws CertificateException, GeneralSecurityException {
-        assertTrue(mDevicePolicyManager.installCaCert(getWho(), FAKE_RSA_1.caCertificate));
-        assertTrue(mDevicePolicyManager.installCaCert(getWho(), FAKE_DSA_1.caCertificate));
+        assertTrue(mDevicePolicyManager.installCaCert(mAdmin, FAKE_RSA_1.caCertificate));
+        assertTrue(mDevicePolicyManager.installCaCert(mAdmin, FAKE_DSA_1.caCertificate));
 
-        mDevicePolicyManager.uninstallAllUserCaCerts(getWho());
+        mDevicePolicyManager.uninstallAllUserCaCerts(mAdmin);
         assertUninstalled(FAKE_RSA_1.caCertificate);
         assertUninstalled(FAKE_DSA_1.caCertificate);
     }
@@ -131,10 +134,10 @@
      */
     private boolean isCaCertInstalledAndTrusted(Certificate caCert)
             throws GeneralSecurityException, CertificateException {
-        boolean installed = mDevicePolicyManager.hasCaCertInstalled(getWho(), caCert.getEncoded());
+        boolean installed = mDevicePolicyManager.hasCaCertInstalled(mAdmin, caCert.getEncoded());
 
         boolean listed = false;
-        for (byte[] certBuffer : mDevicePolicyManager.getInstalledCaCerts(getWho())) {
+        for (byte[] certBuffer : mDevicePolicyManager.getInstalledCaCerts(mAdmin)) {
             if (caCert.equals(readCertificate(certBuffer))) {
                 listed = true;
             }
@@ -153,7 +156,7 @@
         boolean userAddedCertificate = xtm.isUserAddedCertificate((X509Certificate) caCert);
 
         // All three responses should match - if an installed certificate isn't trusted or (worse)
-        // a trusted certificate isn't even installed we should 
+        // a trusted certificate isn't even installed we should fail now, loudly.
         assertEquals(installed, listed);
         assertEquals(installed, trusted);
         assertEquals(installed, userAddedCertificate);
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/vpn/VpnTestHelper.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/vpn/VpnTestHelper.java
index 3072251..41bb626 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/vpn/VpnTestHelper.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/vpn/VpnTestHelper.java
@@ -65,7 +65,6 @@
     private static final int ICMP_ECHO_REQUEST = 0x08;
     private static final int ICMP_ECHO_REPLY = 0x00;
     private static final int NETWORK_TIMEOUT_MS = 5000;
-    private static final int NETWORK_SETTLE_GRACE_MS = 100;
     private static final ComponentName ADMIN_RECEIVER_COMPONENT =
             BaseDeviceAdminTest.ADMIN_RECEIVER_COMPONENT;
 
@@ -93,8 +92,6 @@
             if (!vpnLatch.await(NETWORK_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                 fail("Took too long waiting to establish a VPN-backed connection");
             }
-            // Give the VPN a moment to start transmitting data.
-            Thread.sleep(NETWORK_SETTLE_GRACE_MS);
         } catch (InterruptedException | PackageManager.NameNotFoundException e) {
             fail("Failed to send ping: " + e);
         } finally {
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk b/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk
index 18d1b8b..197f5a7 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk
@@ -26,7 +26,7 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner cts-junit
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner compatibility-device-util
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner ctsdeviceutil compatibility-device-util
 
 LOCAL_SDK_VERSION := test_current
 
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml b/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml
index 64d4079..07d006c 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml
@@ -25,8 +25,7 @@
     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
 
-    <!-- Add a network security config that trusts user added CAs for tests -->
-    <application android:networkSecurityConfig="@xml/network_security_config"
+    <application
         android:testOnly="true">
 
         <uses-library android:name="android.test.runner" />
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/KeyManagementTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/KeyManagementTest.java
index 219dfc2..cc4a8b0 100755
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/KeyManagementTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/KeyManagementTest.java
@@ -15,8 +15,8 @@
  */
 package com.android.cts.deviceowner;
 
+import static android.cts.util.FakeKeys.FAKE_RSA_1;
 import static com.android.cts.deviceowner.BaseDeviceOwnerTest.getWho;
-import static com.android.cts.deviceowner.FakeKeys.FAKE_RSA_1;
 
 import android.app.Activity;
 import android.app.admin.DevicePolicyManager;
diff --git a/hostsidetests/devicepolicy/app/LauncherTests/Android.mk b/hostsidetests/devicepolicy/app/LauncherTests/Android.mk
index eb4a091..19fd3bd 100644
--- a/hostsidetests/devicepolicy/app/LauncherTests/Android.mk
+++ b/hostsidetests/devicepolicy/app/LauncherTests/Android.mk
@@ -26,7 +26,7 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner cts-junit
 
-LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 ctstestrunner android-support-test
 
 LOCAL_SDK_VERSION := current
 
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk b/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk
index 85c74f9..7003012 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk
@@ -27,7 +27,7 @@
 LOCAL_JAVA_LIBRARIES := android.test.runner cts-junit
 
 LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 ctstestrunner compatibility-device-util \
-	ub-uiautomator
+	ub-uiautomator android-support-test
 
 LOCAL_SDK_VERSION := current
 
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
index 7b40ff1..c2a9bc1 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
@@ -110,6 +110,13 @@
         super.tearDown();
     }
 
+    public void testCaCertManagement() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        executeDeviceTestClass(".CaCertManagementTest");
+    }
+
     public void testResetPassword() throws Exception {
         if (!mHasFeature) {
             return;
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index 4748b35..a877525 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -84,10 +84,6 @@
         super.tearDown();
     }
 
-    public void testCaCertManagement() throws Exception {
-        executeDeviceOwnerTest("CaCertManagementTest");
-    }
-
     public void testDeviceOwnerSetup() throws Exception {
         executeDeviceOwnerTest("DeviceOwnerSetupTest");
     }
diff --git a/hostsidetests/net/aidl/Android.mk b/hostsidetests/net/aidl/Android.mk
index a7ec6ef..4aa55b6 100644
--- a/hostsidetests/net/aidl/Android.mk
+++ b/hostsidetests/net/aidl/Android.mk
@@ -19,4 +19,4 @@
 LOCAL_SDK_VERSION := current
 LOCAL_SRC_FILES := com/android/cts/net/hostside/IRemoteSocketFactory.aidl
 LOCAL_MODULE := CtsHostsideNetworkTestsAidl
-include $(BUILD_JAVA_LIBRARY)
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/hostsidetests/numberblocking/app/Android.mk b/hostsidetests/numberblocking/app/Android.mk
index 492a2ec..5755f84 100644
--- a/hostsidetests/numberblocking/app/Android.mk
+++ b/hostsidetests/numberblocking/app/Android.mk
@@ -27,7 +27,7 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
 
 # tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/FakeKeys.java b/libs/deviceutil/src/android/cts/util/FakeKeys.java
similarity index 99%
rename from hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/FakeKeys.java
rename to libs/deviceutil/src/android/cts/util/FakeKeys.java
index 11df8e5..f3814a4 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/FakeKeys.java
+++ b/libs/deviceutil/src/android/cts/util/FakeKeys.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.cts.deviceowner;
+package android.cts.util;
 
 // Copied from cts/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java
 
diff --git a/libs/deviceutil/src/android/cts/util/PollingCheck.java b/libs/deviceutil/src/android/cts/util/PollingCheck.java
index 3a08c7e..0e255a1 100644
--- a/libs/deviceutil/src/android/cts/util/PollingCheck.java
+++ b/libs/deviceutil/src/android/cts/util/PollingCheck.java
@@ -82,4 +82,13 @@
             }
         }.run();
     }
+
+    public static void waitFor(long timeout, final PollingCheckCondition condition) {
+        new PollingCheck(timeout) {
+            @Override
+            protected boolean check() {
+                return condition.canProceed();
+            }
+        }.run();
+    }
 }
diff --git a/libs/deviceutil/src/android/cts/util/WidgetTestUtils.java b/libs/deviceutil/src/android/cts/util/WidgetTestUtils.java
index 813672e..740513e 100644
--- a/libs/deviceutil/src/android/cts/util/WidgetTestUtils.java
+++ b/libs/deviceutil/src/android/cts/util/WidgetTestUtils.java
@@ -33,10 +33,11 @@
  */
 public class WidgetTestUtils {
     /**
-     * Assert that two bitmaps are equal.
+     * Assert that two bitmaps have identical content (same dimensions, same configuration,
+     * same pixel content).
      *
-     * @param Bitmap b1 the first bitmap which needs to compare.
-     * @param Bitmap b2 the second bitmap which needs to compare.
+     * @param b1 the first bitmap which needs to compare.
+     * @param b2 the second bitmap which needs to compare.
      */
     public static void assertEquals(Bitmap b1, Bitmap b2) {
         if (b1 == b2) {
diff --git a/tests/app/Android.mk b/tests/app/Android.mk
index 775e679..6ce0148 100644
--- a/tests/app/Android.mk
+++ b/tests/app/Android.mk
@@ -23,7 +23,7 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common voip-common org.apache.http.legacy
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner ctstestserver mockito-target
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner ctstestserver mockito-target android-support-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/app/app/AndroidManifest.xml b/tests/app/app/AndroidManifest.xml
index 10a6792..2ac5dbb 100644
--- a/tests/app/app/AndroidManifest.xml
+++ b/tests/app/app/AndroidManifest.xml
@@ -196,7 +196,7 @@
             </intent-filter>
         </activity>
 
-        <activity android:name="android.app.stubs.ChildTabActivity" android:label="ChildTabActivity" />
+        <activity android:name="android.app.stubs.FragmentResultActivity" android:label="FragmentResultActivity" />
 
         <activity android:name="android.app.stubs.LauncherActivityStub"
                   android:label="LauncherActivityStub" >
diff --git a/tests/app/app/src/android/app/stubs/FragmentResultActivity.java b/tests/app/app/src/android/app/stubs/FragmentResultActivity.java
new file mode 100644
index 0000000..364d093
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/FragmentResultActivity.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app.stubs;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+/**
+ * A simple Activity used to return a result.
+ */
+public class FragmentResultActivity extends Activity {
+    public static final String EXTRA_RESULT_CODE = "result";
+    public static final String EXTRA_RESULT_CONTENT = "result_content";
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        int resultCode = getIntent().getIntExtra(EXTRA_RESULT_CODE, Activity.RESULT_OK);
+        String result = getIntent().getStringExtra(EXTRA_RESULT_CONTENT);
+        Intent intent = new Intent();
+        intent.putExtra(EXTRA_RESULT_CONTENT, result);
+        setResult(resultCode, intent);
+        finish();
+    }
+}
diff --git a/tests/app/app/src/android/app/stubs/FragmentTestActivity.java b/tests/app/app/src/android/app/stubs/FragmentTestActivity.java
index a421895..a5f54bc 100644
--- a/tests/app/app/src/android/app/stubs/FragmentTestActivity.java
+++ b/tests/app/app/src/android/app/stubs/FragmentTestActivity.java
@@ -19,6 +19,7 @@
 import android.app.Activity;
 import android.app.Fragment;
 import android.content.Context;
+import android.content.Intent;
 import android.os.Bundle;
 import android.transition.Transition;
 import android.transition.Transition.TransitionListener;
diff --git a/tests/app/app/src/android/app/stubs/MockTabActivity.java b/tests/app/app/src/android/app/stubs/MockTabActivity.java
index 247cfe0..722ac69 100644
--- a/tests/app/app/src/android/app/stubs/MockTabActivity.java
+++ b/tests/app/app/src/android/app/stubs/MockTabActivity.java
@@ -40,7 +40,7 @@
         final TabHost tabHost = getTabHost();
 
         tabHost.addTab(tabHost.newTabSpec(TAB1).setIndicator(TAB1)
-                .setContent(new Intent(this, ChildTabActivity.class)));
+                .setContent(new Intent(this, MockActivity.class)));
 
         tabHost.addTab(tabHost.newTabSpec(TAB2).setIndicator(TAB2)
                 .setContent(new Intent(this, MockActivity.class)));
diff --git a/tests/app/src/android/app/cts/ActivityActionModeTest.java b/tests/app/src/android/app/cts/ActivityActionModeTest.java
new file mode 100644
index 0000000..b74e737
--- /dev/null
+++ b/tests/app/src/android/app/cts/ActivityActionModeTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app.cts;
+
+import static org.mockito.Mockito.*;
+
+import android.app.stubs.MockActivity;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.ActionMode;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ActivityActionModeTest {
+
+    private ActionMode.Callback mCallback;
+
+    @Rule
+    public ActivityTestRule<MockActivity> mActivityRule =
+            new ActivityTestRule<>(MockActivity.class);
+
+    @Before
+    public void setUp() {
+        mCallback = mock(ActionMode.Callback.class);
+        when(mCallback.onCreateActionMode(any(), any())).thenReturn(true);
+        when(mCallback.onPrepareActionMode(any(), any())).thenReturn(true);
+    }
+
+    @Test
+    @UiThreadTest
+    public void testStartPrimaryActionMode() {
+        final ActionMode mode = mActivityRule.getActivity().startActionMode(
+                mCallback, ActionMode.TYPE_PRIMARY);
+
+        assertNotNull(mode);
+        assertEquals(ActionMode.TYPE_PRIMARY, mode.getType());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testStartFloatingActionMode() {
+        final ActionMode mode = mActivityRule.getActivity().startActionMode(
+                mCallback, ActionMode.TYPE_FLOATING);
+
+        assertNotNull(mode);
+        assertEquals(ActionMode.TYPE_FLOATING, mode.getType());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testStartTypelessActionMode() {
+        final ActionMode mode = mActivityRule.getActivity().startActionMode(mCallback);
+
+        assertNotNull(mode);
+        assertEquals(ActionMode.TYPE_PRIMARY, mode.getType());
+    }
+}
diff --git a/tests/app/src/android/app/cts/FragmentReceiveResultTest.java b/tests/app/src/android/app/cts/FragmentReceiveResultTest.java
new file mode 100644
index 0000000..b22ab6c
--- /dev/null
+++ b/tests/app/src/android/app/cts/FragmentReceiveResultTest.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app.cts;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertTrue;
+import static junit.framework.TestCase.fail;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.Instrumentation;
+import android.app.PendingIntent;
+import android.app.stubs.FragmentResultActivity;
+import android.app.stubs.FragmentTestActivity;
+import android.app.stubs.R;
+import android.content.Intent;
+import android.content.IntentSender;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Tests Fragment's startActivityForResult and startIntentSenderForResult.
+ */
+public class FragmentReceiveResultTest extends
+        ActivityInstrumentationTestCase2<FragmentTestActivity> {
+
+    private FragmentTestActivity mActivity;
+    private TestFragment mFragment;
+
+    public FragmentReceiveResultTest() {
+        super(FragmentTestActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+        mFragment = attachTestFragment();
+    }
+
+    @SmallTest
+    public void testStartActivityForResultOk() {
+        startActivityForResult(10, Activity.RESULT_OK, "content 10");
+
+        assertTrue("Fragment should receive result", mFragment.mHasResult);
+        assertEquals(10, mFragment.mRequestCode);
+        assertEquals(Activity.RESULT_OK, mFragment.mResultCode);
+        assertEquals("content 10", mFragment.mResultContent);
+    }
+
+    @SmallTest
+    public void testStartActivityForResultCanceled() {
+        startActivityForResult(20, Activity.RESULT_CANCELED, "content 20");
+
+        assertTrue("Fragment should receive result", mFragment.mHasResult);
+        assertEquals(20, mFragment.mRequestCode);
+        assertEquals(Activity.RESULT_CANCELED, mFragment.mResultCode);
+        assertEquals("content 20", mFragment.mResultContent);
+    }
+
+    @SmallTest
+    public void testStartIntentSenderForResultOk() {
+        startIntentSenderForResult(30, Activity.RESULT_OK, "content 30");
+
+        assertTrue("Fragment should receive result", mFragment.mHasResult);
+        assertEquals(30, mFragment.mRequestCode);
+        assertEquals(Activity.RESULT_OK, mFragment.mResultCode);
+        assertEquals("content 30", mFragment.mResultContent);
+    }
+
+    @SmallTest
+    public void testStartIntentSenderForResultCanceled() {
+        startIntentSenderForResult(40, Activity.RESULT_CANCELED, "content 40");
+
+        assertTrue("Fragment should receive result", mFragment.mHasResult);
+        assertEquals(40, mFragment.mRequestCode);
+        assertEquals(Activity.RESULT_CANCELED, mFragment.mResultCode);
+        assertEquals("content 40", mFragment.mResultContent);
+    }
+
+    private TestFragment attachTestFragment() {
+        final TestFragment fragment = new TestFragment();
+        getInstrumentation().waitForIdleSync();
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                mActivity.getFragmentManager().beginTransaction()
+                        .add(R.id.content, fragment)
+                        .addToBackStack(null)
+                        .commitAllowingStateLoss();
+                mActivity.getFragmentManager().executePendingTransactions();
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+        return fragment;
+    }
+
+    private void startActivityForResult(final int requestCode, final int resultCode,
+            final String content) {
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                Intent intent = new Intent(mActivity, FragmentResultActivity.class);
+                intent.putExtra(FragmentResultActivity.EXTRA_RESULT_CODE, resultCode);
+                intent.putExtra(FragmentResultActivity.EXTRA_RESULT_CONTENT, content);
+
+                mFragment.startActivityForResult(intent, requestCode);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+    }
+
+    private void startIntentSenderForResult(final int requestCode, final int resultCode,
+            final String content) {
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                Intent intent = new Intent(mActivity, FragmentResultActivity.class);
+                intent.putExtra(FragmentResultActivity.EXTRA_RESULT_CODE, resultCode);
+                intent.putExtra(FragmentResultActivity.EXTRA_RESULT_CONTENT, content);
+
+                PendingIntent pendingIntent = PendingIntent.getActivity(mActivity,
+                        requestCode, intent, 0);
+
+                try {
+                    mFragment.startIntentSenderForResult(pendingIntent.getIntentSender(),
+                            requestCode, null, 0, 0, 0, null);
+                } catch (IntentSender.SendIntentException e) {
+                    fail("IntentSender failed");
+                }
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+    }
+
+    public static class TestFragment extends Fragment {
+        boolean mHasResult = false;
+        int mRequestCode = -1;
+        int mResultCode = 100;
+        String mResultContent;
+
+        @Override
+        public void onActivityResult(int requestCode, int resultCode, Intent data) {
+            mHasResult = true;
+            mRequestCode = requestCode;
+            mResultCode = resultCode;
+            mResultContent = data.getStringExtra(FragmentResultActivity.EXTRA_RESULT_CONTENT);
+        }
+    }
+
+}
diff --git a/tests/app/src/android/app/cts/FragmentTransactionTest.java b/tests/app/src/android/app/cts/FragmentTransactionTest.java
new file mode 100644
index 0000000..2ff69a7
--- /dev/null
+++ b/tests/app/src/android/app/cts/FragmentTransactionTest.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app.cts;
+
+import android.app.Fragment;
+import android.app.stubs.FragmentTestActivity;
+import android.app.stubs.R;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static junit.framework.TestCase.*;
+
+/**
+ * Tests usage of the {@link android.app.FragmentTransaction} class.
+ */
+@RunWith(AndroidJUnit4.class)
+public class FragmentTransactionTest {
+
+    @Rule
+    public ActivityTestRule<FragmentTestActivity> mActivityRule =
+            new ActivityTestRule<>(FragmentTestActivity.class);
+
+    private FragmentTestActivity mActivity;
+
+    @Before
+    public void setUp() {
+        mActivity = mActivityRule.getActivity();
+    }
+
+    @Test
+    public void testAddTransactionWithValidFragment() {
+        final Fragment fragment = new CorrectFragment();
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                mActivity.getFragmentManager().beginTransaction()
+                        .add(R.id.content, fragment)
+                        .addToBackStack(null)
+                        .commit();
+                mActivity.getFragmentManager().executePendingTransactions();
+            }
+        });
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+        assertTrue(fragment.isAdded());
+    }
+
+    @Test
+    public void testAddTransactionWithPrivateFragment() {
+        final Fragment fragment = new PrivateFragment();
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                boolean exceptionThrown = false;
+                try {
+                    mActivity.getFragmentManager().beginTransaction()
+                            .add(R.id.content, fragment)
+                            .addToBackStack(null)
+                            .commit();
+                    mActivity.getFragmentManager().executePendingTransactions();
+                } catch (IllegalStateException e) {
+                    exceptionThrown = true;
+                } finally {
+                    assertTrue("Exception should be thrown", exceptionThrown);
+                    assertFalse("Fragment shouldn't be added", fragment.isAdded());
+                }
+            }
+        });
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+    }
+
+    @Test
+    public void testAddTransactionWithPackagePrivateFragment() {
+        final Fragment fragment = new PackagePrivateFragment();
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                boolean exceptionThrown = false;
+                try {
+                    mActivity.getFragmentManager().beginTransaction()
+                            .add(R.id.content, fragment)
+                            .addToBackStack(null)
+                            .commit();
+                    mActivity.getFragmentManager().executePendingTransactions();
+                } catch (IllegalStateException e) {
+                    exceptionThrown = true;
+                } finally {
+                    assertTrue("Exception should be thrown", exceptionThrown);
+                    assertFalse("Fragment shouldn't be added", fragment.isAdded());
+                }
+            }
+        });
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+    }
+
+    @Test
+    public void testAddTransactionWithAnonymousFragment() {
+        final Fragment fragment = new Fragment() {};
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                boolean exceptionThrown = false;
+                try {
+                    mActivity.getFragmentManager().beginTransaction()
+                            .add(R.id.content, fragment)
+                            .addToBackStack(null)
+                            .commit();
+                    mActivity.getFragmentManager().executePendingTransactions();
+                } catch (IllegalStateException e) {
+                    exceptionThrown = true;
+                } finally {
+                    assertTrue("Exception should be thrown", exceptionThrown);
+                    assertFalse("Fragment shouldn't be added", fragment.isAdded());
+                }
+            }
+        });
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+    }
+
+    @Test
+    public void testAddTransactionWithNonStaticFragment() {
+        final Fragment fragment = new NonStaticFragment();
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                boolean exceptionThrown = false;
+                try {
+                    mActivity.getFragmentManager().beginTransaction()
+                            .add(R.id.content, fragment)
+                            .addToBackStack(null)
+                            .commit();
+                    mActivity.getFragmentManager().executePendingTransactions();
+                } catch (IllegalStateException e) {
+                    exceptionThrown = true;
+                } finally {
+                    assertTrue("Exception should be thrown", exceptionThrown);
+                    assertFalse("Fragment shouldn't be added", fragment.isAdded());
+                }
+            }
+        });
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+    }
+
+    public static class CorrectFragment extends Fragment {}
+
+    private static class PrivateFragment extends Fragment {}
+
+    private static class PackagePrivateFragment extends Fragment {}
+
+    private class NonStaticFragment extends Fragment {}
+}
diff --git a/tests/aslr/src/AslrMallocTest.cpp b/tests/aslr/src/AslrMallocTest.cpp
index 6e773cb..91a36e2 100644
--- a/tests/aslr/src/AslrMallocTest.cpp
+++ b/tests/aslr/src/AslrMallocTest.cpp
@@ -157,7 +157,9 @@
             return EXIT_FAILURE;
         }
 
-        printf("%p", malloc(size));
+        void* p = malloc(size);
+        printf("%p", p);
+        free(p);
         return EXIT_SUCCESS;
     }
 #endif
diff --git a/tests/camera/libctscamera2jni/native-camera-jni.cpp b/tests/camera/libctscamera2jni/native-camera-jni.cpp
index db687bf..4a3620e 100644
--- a/tests/camera/libctscamera2jni/native-camera-jni.cpp
+++ b/tests/camera/libctscamera2jni/native-camera-jni.cpp
@@ -345,7 +345,7 @@
 
 class StaticInfo {
   public:
-    StaticInfo(ACameraMetadata* chars) : mChars(chars) {}
+    explicit StaticInfo(ACameraMetadata* chars) : mChars(chars) {}
 
     bool isColorOutputSupported() {
         return isCapabilitySupported(ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index 5ea4322..86839eb 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -244,19 +244,6 @@
   bug: 23779168
 },
 {
-  description: "New assist tests that do not yet have a track record.",
-  names: [
-    "android.assist.cts.AssistantContentViewTest",
-    "android.assist.cts.ExtraAssistDataTest",
-    "android.assist.cts.FocusChangeTest",
-    "android.assist.cts.LargeViewHierarchyTest",
-    "android.assist.cts.ScreenshotTest",
-    "android.assist.cts.TextViewTest",
-    "android.assist.cts.WebViewTest"
-  ],
-  bug: 21668302
-},
-{
   description: "ConnectivityConstraintTest job scheduler not working.",
   names: [
      "android.jobscheduler.cts.ConnectivityConstraintTest#testConnectivityConstraintExecutes_withWifi",
diff --git a/tests/tests/animation/Android.mk b/tests/tests/animation/Android.mk
index 205adda..ed42d74 100644
--- a/tests/tests/animation/Android.mk
+++ b/tests/tests/animation/Android.mk
@@ -24,13 +24,19 @@
 # When built, explicitly put it in the data partition.
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES += \
+    android-support-test \
+    mockito-target \
+    android-common \
+    ctsdeviceutil \
+    ctstestrunner \
+    platform-test-annotations
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
 
-LOCAL_SDK_VERSION := current
-
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/animation/src/android/animation/cts/AnimatorListenerAdapterTest.java b/tests/tests/animation/src/android/animation/cts/AnimatorListenerAdapterTest.java
new file mode 100644
index 0000000..c6c0bc4
--- /dev/null
+++ b/tests/tests/animation/src/android/animation/cts/AnimatorListenerAdapterTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.animation.cts;
+
+import android.animation.AnimatorListenerAdapter;
+import android.support.test.filters.SmallTest;
+
+import org.junit.Test;
+
+@SmallTest
+public class AnimatorListenerAdapterTest {
+    /**
+     * AnimatorListenerAdapter has a noop implementation of the AnimatorListener interface.
+     * It should do nothing, including when nulls are passed to it.
+     * <p>
+     * Mostly this test pokes the implementation so that it is counted as tested. There isn't
+     * much to test here since it has no implementation.
+     */
+    @Test
+    public void testNullOk() throws Throwable {
+        AnimatorListenerAdapter adapter = new MyAdapter();
+        adapter.onAnimationStart(null);
+        adapter.onAnimationEnd(null);
+        adapter.onAnimationRepeat(null);
+        adapter.onAnimationCancel(null);
+        adapter.onAnimationPause(null);
+        adapter.onAnimationResume(null);
+    }
+
+    private static class MyAdapter extends AnimatorListenerAdapter {
+    }
+}
diff --git a/tests/tests/animation/src/android/animation/cts/AnimatorSetTest.java b/tests/tests/animation/src/android/animation/cts/AnimatorSetTest.java
index 3bf86de..77b1583 100644
--- a/tests/tests/animation/src/android/animation/cts/AnimatorSetTest.java
+++ b/tests/tests/animation/src/android/animation/cts/AnimatorSetTest.java
@@ -438,6 +438,82 @@
         assertSame(animator2.getInterpolator(), clone2.getInterpolator());
     }
 
+    public void testSetSynchronized() throws Throwable {
+        final TargetObj obj1 = new TargetObj();
+        final TargetObj obj2 = new TargetObj();
+        ObjectAnimator anim1 = ObjectAnimator.ofFloat(obj1, "val", 0, 1);
+        ObjectAnimator anim2 = ObjectAnimator.ofFloat(obj1, "val", 0, 1);
+        ObjectAnimator anim3 = ObjectAnimator.ofFloat(obj1, "val", 0, 1);
+        anim1.setStartDelay(100);
+        anim2.setStartDelay(400);
+        anim3.setStartDelay(700);
+        final AnimatorSet combined1 = new AnimatorSet();
+        combined1.playTogether(anim1, anim2, anim3);
+
+        ObjectAnimator anim4 = ObjectAnimator.ofFloat(obj2, "val", 0, 1);
+        ObjectAnimator anim5 = ObjectAnimator.ofFloat(obj2, "val", 0, 1);
+        ObjectAnimator anim6 = ObjectAnimator.ofFloat(obj2, "val", 0, 1);
+        final AnimatorSet combined2 = new AnimatorSet();
+        combined2.playSequentially(anim4, anim5, anim6);
+        combined2.setStartDelay(100);
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                combined1.start();
+                combined2.start();
+            }
+        });
+
+        while (combined1.isRunning()) {
+            runTestOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    assertEquals(obj1.value, obj2.value);
+                }
+            });
+        }
+    }
+
+    public void testNotifiesAfterEnd() throws Throwable {
+        final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
+        Animator.AnimatorListener listener = new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                assertTrue(animation.isStarted());
+                assertTrue(animation.isRunning());
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                assertFalse(animation.isRunning());
+                assertFalse(animation.isStarted());
+                super.onAnimationEnd(animation);
+            }
+        };
+        animator.addListener(listener);
+        final AnimatorSet animatorSet = new AnimatorSet();
+        animatorSet.playTogether(animator);
+        animatorSet.addListener(listener);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                animatorSet.start();
+                animator.end();
+                assertFalse(animator.isStarted());
+                assertFalse(animatorSet.isStarted());
+            }
+        });
+    }
+
+    static class TargetObj {
+        public float value = 0;
+
+        public void setVal(float value) {
+            this.value = value;
+        }
+    }
+
     class AnimateObject {
         int x = 1;
         int y = 2;
diff --git a/tests/tests/animation/src/android/animation/cts/EvaluatorTest.java b/tests/tests/animation/src/android/animation/cts/EvaluatorTest.java
index 0812351..9c90f40 100644
--- a/tests/tests/animation/src/android/animation/cts/EvaluatorTest.java
+++ b/tests/tests/animation/src/android/animation/cts/EvaluatorTest.java
@@ -27,10 +27,12 @@
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
 
 /**
  * Tests for the various Evaluator classes in android.animation
  */
+@SmallTest
 public class EvaluatorTest extends InstrumentationTestCase {
 
     public void testFloatEvaluator() {
@@ -50,10 +52,18 @@
     }
 
     public void testFloatArrayEvaluator() {
+        FloatArrayEvaluator evaluator = new FloatArrayEvaluator();
+        floatArrayEvaluatorTestImpl(evaluator, null);
+
+        float[] reusableArray = new float[2];
+        FloatArrayEvaluator evaluator2 = new FloatArrayEvaluator(reusableArray);
+        floatArrayEvaluatorTestImpl(evaluator2, reusableArray);
+    }
+
+    private void floatArrayEvaluatorTestImpl(FloatArrayEvaluator evaluator, float[] reusedArray) {
         float[] start = {0f, 0f};
         float[] end = {.8f, 1.0f};
         float fraction = 0.5f;
-        FloatArrayEvaluator evaluator = new FloatArrayEvaluator();
 
         float[] result = evaluator.evaluate(0, start, end);
         assertEquals(start[0], result[0], .001f);
@@ -66,51 +76,63 @@
         result = evaluator.evaluate(1, start, end);
         assertEquals(end[0], result[0], .001f);
         assertEquals(end[1], result[1], .001f);
+
+        if (reusedArray != null) {
+            assertEquals(reusedArray, result);
+        }
     }
 
     public void testArgbEvaluator() throws Throwable {
-        final int RED =  0xffFF8080;
-        final int BLUE = 0xff8080FF;
-        int aRED = Color.alpha(RED);
-        int rRED = Color.red(RED);
-        int gRED = Color.green(RED);
-        int bRED = Color.blue(RED);
-        int aBLUE = Color.alpha(BLUE);
-        int rBLUE = Color.red(BLUE);
-        int gBLUE = Color.green(BLUE);
-        int bBLUE = Color.blue(BLUE);
+        final int START =  0xffFF8080;
+        final int END = 0xff8080FF;
+        int aSTART = Color.alpha(START);
+        int rSTART = Color.red(START);
+        int gSTART = Color.green(START);
+        int bSTART = Color.blue(START);
+        int aEND = Color.alpha(END);
+        int rEND = Color.red(END);
+        int gEND = Color.green(END);
+        int bEND = Color.blue(END);
 
         final ArgbEvaluator evaluator = new ArgbEvaluator();
 
-        int result = (Integer) evaluator.evaluate(0, RED, BLUE);
+        int result = (Integer) evaluator.evaluate(0, START, END);
         int aResult = Color.alpha(result);
         int rResult = Color.red(result);
         int gResult = Color.green(result);
         int bResult = Color.blue(result);
-        assertEquals(aRED, aResult);
-        assertEquals(rRED, rResult);
-        assertEquals(gRED, gResult);
-        assertEquals(bRED, bResult);
+        assertEquals(aSTART, aResult);
+        assertEquals(rSTART, rResult);
+        assertEquals(gSTART, gResult);
+        assertEquals(bSTART, bResult);
 
-        result = (Integer) evaluator.evaluate(.5f, RED, BLUE);
+        result = (Integer) evaluator.evaluate(.5f, START, END);
         aResult = Color.alpha(result);
         rResult = Color.red(result);
         gResult = Color.green(result);
         bResult = Color.blue(result);
         assertEquals(0xff, aResult);
-        assertEquals(rRED + (int)(.5f * (rBLUE - rRED)), rResult);
-        assertEquals(gRED + (int)(.5f * (gBLUE - gRED)), gResult);
-        assertEquals(bRED + (int)(.5f * (bBLUE - bRED)), bResult);
+        assertEquals(0x80, gResult);
+        if (rSTART < rEND) {
+            assertTrue(rResult > rSTART && rResult < rEND);
+        } else {
+            assertTrue(rResult < rSTART && rResult > rEND);
+        }
+        if (bSTART < bEND) {
+            assertTrue(bResult > bSTART && bResult < bEND);
+        } else {
+            assertTrue(bResult < bSTART && bResult > bEND);
+        }
 
-        result = (Integer) evaluator.evaluate(1, RED, BLUE);
+        result = (Integer) evaluator.evaluate(1, START, END);
         aResult = Color.alpha(result);
         rResult = Color.red(result);
         gResult = Color.green(result);
         bResult = Color.blue(result);
-        assertEquals(aBLUE, aResult);
-        assertEquals(rBLUE, rResult);
-        assertEquals(gBLUE, gResult);
-        assertEquals(bBLUE, bResult);
+        assertEquals(aEND, aResult);
+        assertEquals(rEND, rResult);
+        assertEquals(gEND, gResult);
+        assertEquals(bEND, bResult);
     }
 
     public void testIntEvaluator() throws Throwable {
@@ -130,10 +152,18 @@
     }
 
     public void testIntArrayEvaluator() {
+        IntArrayEvaluator evaluator = new IntArrayEvaluator();
+        intArrayEvaluatorTestImpl(evaluator, null);
+
+        int[] reusableArray = new int[2];
+        IntArrayEvaluator evaluator2 = new IntArrayEvaluator(reusableArray);
+        intArrayEvaluatorTestImpl(evaluator2, reusableArray);
+    }
+
+    private void intArrayEvaluatorTestImpl(IntArrayEvaluator evaluator, int[] reusedArray) {
         int[] start = {0, 0};
         int[] end = {80, 100};
         float fraction = 0.5f;
-        IntArrayEvaluator evaluator = new IntArrayEvaluator();
 
         int[] result = evaluator.evaluate(0, start, end);
         assertEquals(start[0], result[0]);
@@ -146,10 +176,22 @@
         result = evaluator.evaluate(1, start, end);
         assertEquals(end[0], result[0]);
         assertEquals(end[1], result[1]);
+
+        if (reusedArray != null) {
+            assertEquals(reusedArray, result);
+        }
     }
 
     public void testRectEvaluator() throws Throwable {
         final RectEvaluator evaluator = new RectEvaluator();
+        rectEvaluatorTestImpl(evaluator, null);
+
+        Rect reusableRect = new Rect();
+        final RectEvaluator evaluator2 = new RectEvaluator(reusableRect);
+        rectEvaluatorTestImpl(evaluator2, reusableRect);
+    }
+
+    private void rectEvaluatorTestImpl(RectEvaluator evaluator, Rect reusedRect) {
         final Rect start = new Rect(0, 0, 0, 0);
         final Rect end = new Rect(100, 200, 300, 400);
         final float fraction = 0.5f;
@@ -171,10 +213,22 @@
         assertEquals(end.top, result.top, .001f);
         assertEquals(end.right, result.right, .001f);
         assertEquals(end.bottom, result.bottom, .001f);
+
+        if (reusedRect != null) {
+            assertEquals(reusedRect, result);
+        }
     }
 
     public void testPointFEvaluator() throws Throwable {
         final PointFEvaluator evaluator = new PointFEvaluator();
+        pointFEvaluatorTestImpl(evaluator, null);
+
+        PointF reusablePoint = new PointF();
+        final PointFEvaluator evaluator2 = new PointFEvaluator(reusablePoint);
+        pointFEvaluatorTestImpl(evaluator2, reusablePoint);
+    }
+
+    private void pointFEvaluatorTestImpl(PointFEvaluator evaluator, PointF reusedPoint) {
         final PointF start = new PointF(0, 0);
         final PointF end = new PointF(100, 200);
         final float fraction = 0.5f;
@@ -190,6 +244,10 @@
         result = evaluator.evaluate(1, start, end);
         assertEquals(end.x, result.x, .001f);
         assertEquals(end.y, result.y, .001f);
+
+        if (reusedPoint != null) {
+            assertEquals(reusedPoint, result);
+        }
     }
 
     /**
diff --git a/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java b/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java
index 6ff1cf9..a96b8c9 100644
--- a/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java
+++ b/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java
@@ -16,17 +16,39 @@
 
 package android.animation.cts;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.ArgbEvaluator;
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
+import android.animation.TypeConverter;
 import android.animation.ValueAnimator;
+import android.graphics.Color;
+import android.graphics.Path;
+import android.graphics.PointF;
 import android.test.ActivityInstrumentationTestCase2;
 import android.util.Property;
+import android.view.View;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.Interpolator;
 
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
 public class ObjectAnimatorTest extends
         ActivityInstrumentationTestCase2<AnimationActivity> {
+    private static final float LINE1_START = -32f;
+    private static final float LINE1_END = -2f;
+    private static final float LINE1_Y = 0f;
+    private static final float LINE2_START = 2f;
+    private static final float LINE2_END = 12f;
+    private static final float QUADRATIC_CTRL_PT1_X = 0f;
+    private static final float QUADRATIC_CTRL_PT1_Y = 0f;
+    private static final float QUADRATIC_CTRL_PT2_X = 50f;
+    private static final float QUADRATIC_CTRL_PT2_Y = 20f;
+    private static final float QUADRATIC_CTRL_PT3_X = 100f;
+    private static final float QUADRATIC_CTRL_PT3_Y = 0f;
+
     private AnimationActivity mActivity;
     private ObjectAnimator mObjectAnimator;
     private long mDuration = 1000;
@@ -162,6 +184,59 @@
         assertTrue(endColor <= i.intValue());
     }
 
+    public void testOfArgb() throws Throwable {
+        Object object = mActivity.view;
+        String property = "backgroundColor";
+        int start = 0xffff0000;
+        int end = 0xff0000ff;
+        int[] values = {start, end};
+        int startRed = Color.red(start);
+        int startBlue = Color.blue(start);
+        int endRed = Color.red(end);
+        int endBlue = Color.blue(end);
+        final ObjectAnimator animator = ObjectAnimator.ofArgb(object, property, start, end);
+        animator.setDuration(mDuration);
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                if (animation.getAnimatedFraction() > .05f) {
+                    latch.countDown();
+                }
+            }
+        });
+
+        this.runTestOnUiThread(new Runnable(){
+            public void run() {
+                animator.start();
+            }
+        });
+        boolean isRunning = animator.isRunning();
+        assertTrue(isRunning);
+
+        assertTrue(latch.await(500, TimeUnit.MILLISECONDS));
+
+        Integer animatedValue = (Integer) animator.getAnimatedValue();
+        int alpha = Color.alpha(animatedValue);
+        int red = Color.red(animatedValue);
+        int green = Color.green(animatedValue);
+        int blue = Color.blue(animatedValue);
+        assertTrue(red < startRed);
+        assertTrue(red > endRed);
+        assertTrue(blue > startBlue);
+        assertTrue(blue < endBlue);
+        assertEquals(255, alpha);
+        assertEquals(0, green);
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                animator.cancel();
+            }
+        });
+    }
+
     public void testGetPropertyName() throws Throwable {
         Object object = mActivity.view.newBall;
         String propertyName = "backgroundColor";
@@ -230,6 +305,473 @@
         assertEquals(interpolator, cloneAnimator.getInterpolator());
     }
 
+    public void testOfFloat_Path() throws Throwable {
+        // Test for ObjectAnimator.ofFloat(Object, String, String, Path)
+        // Create a path that contains two disconnected line segments. Check that the animated
+        // property x and property y always stay on the line segments.
+        Path path = new Path();
+        path.moveTo(LINE1_START, LINE1_Y);
+        path.lineTo(LINE1_END, LINE1_Y);
+        path.moveTo(LINE2_START, LINE2_START);
+        path.lineTo(LINE2_END, LINE2_END);
+        final double totalLength = (LINE1_END - LINE1_START) + Math.sqrt(
+                (LINE2_END - LINE2_START) * (LINE2_END - LINE2_START) +
+                (LINE2_END - LINE2_START) * (LINE2_END - LINE2_START));
+        final double firstSegEndFraction = (LINE1_END - LINE1_START) / totalLength;
+        final float delta = 0.01f;
+
+        Object target = new Object() {
+            public void setX(float x) {
+            }
+
+            public void setY(float y) {
+            }
+        };
+        final CountDownLatch endLatch = new CountDownLatch(1);
+
+        final ObjectAnimator anim = ObjectAnimator.ofFloat(target, "x", "y", path);
+        anim.setDuration(200);
+        // Linear interpolator
+        anim.setInterpolator(null);
+        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                float fraction = animation.getAnimatedFraction();
+                float x = (Float) animation.getAnimatedValue("x");
+                float y = (Float) animation.getAnimatedValue("y");
+
+                // Check that the point is on the path.
+                if (x <= 0) {
+                    // First line segment is a horizontal line.
+                    assertTrue(x >= LINE1_START);
+                    assertTrue(x <= LINE1_END);
+                    assertEquals(LINE1_Y, y);
+
+                    // Check that the time animation stays on the first segment is proportional to
+                    // the length of the first line segment.
+                    assertTrue(fraction < firstSegEndFraction + delta);
+                } else {
+                    assertTrue(x >= LINE2_START);
+                    assertTrue(x <= LINE2_END);
+                    assertEquals(x, y);
+
+                    // Check that the time animation stays on the second segment is proportional to
+                    // the length of the second line segment.
+                    assertTrue(fraction > firstSegEndFraction - delta);
+                }
+            }
+        });
+        anim.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                endLatch.countDown();
+            }
+        });
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                anim.start();
+            }
+        });
+        assertTrue(endLatch.await(400, TimeUnit.MILLISECONDS));
+    }
+
+    public void testOfInt_Path() throws Throwable {
+        // Test for ObjectAnimator.ofInt(Object, String, String, Path)
+        // Create a path that contains two disconnected line segments. Check that the animated
+        // property x and property y always stay on the line segments.
+        Path path = new Path();
+        path.moveTo(LINE1_START, -LINE1_START);
+        path.lineTo(LINE1_END, -LINE1_END);
+        path.moveTo(LINE2_START, LINE2_START);
+        path.lineTo(LINE2_END, LINE2_END);
+
+        Object target = new Object() {
+            public void setX(float x) {
+            }
+
+            public void setY(float y) {
+            }
+        };
+        final CountDownLatch endLatch = new CountDownLatch(1);
+        final ObjectAnimator anim = ObjectAnimator.ofInt(target, "x", "y", path);
+        anim.setDuration(200);
+
+        // Linear interpolator
+        anim.setInterpolator(null);
+        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                float fraction = animation.getAnimatedFraction();
+                int x = (Integer) animation.getAnimatedValue("x");
+                int y = (Integer) animation.getAnimatedValue("y");
+
+                // Check that the point is on the path.
+                if (x <= 0) {
+                    // Check that the time animation stays on the first segment is proportional to
+                    // the length of the first line segment.
+                    assertTrue(x >= LINE1_START);
+                    assertTrue(x <= LINE1_END);
+                    assertEquals(x, -y);
+
+                    // First line segment is 3 times as long as the second line segment, so the
+                    // 3/4 of the animation duration will be spent on the first line segment.
+                    assertTrue(fraction <= 0.75f);
+                } else {
+                    // Check that the time animation stays on the second segment is proportional to
+                    // the length of the second line segment.
+                    assertTrue(x >= LINE2_START);
+                    assertTrue(x <= LINE2_END);
+                    assertEquals(x, y);
+
+                    assertTrue(fraction >= 0.75f);
+                }
+            }
+        });
+        anim.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                endLatch.countDown();
+            }
+        });
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                anim.start();
+            }
+        });
+        assertTrue(endLatch.await(400, TimeUnit.MILLISECONDS));
+
+    }
+
+    public void testOfMultiFloat_Path() throws Throwable {
+        // Test for ObjectAnimator.ofMultiFloat(Object, String, Path);
+        // Create a quadratic bezier curve that are symmetric about the vertical line (x = 50).
+        // Expect when fraction < 0.5, x < 50, otherwise, x >= 50.
+        Path path = new Path();
+        path.moveTo(QUADRATIC_CTRL_PT1_X, QUADRATIC_CTRL_PT1_Y);
+        path.quadTo(QUADRATIC_CTRL_PT2_X, QUADRATIC_CTRL_PT2_Y,
+                QUADRATIC_CTRL_PT3_X, QUADRATIC_CTRL_PT3_Y);
+
+        Object target = new Object() {
+            public void setPosition(float x, float y) {
+            }
+        };
+
+        final CountDownLatch endLatch = new CountDownLatch(1);
+        final ObjectAnimator anim = ObjectAnimator.ofMultiFloat(target, "position", path);
+        // Linear interpolator
+        anim.setInterpolator(null);
+        anim.setDuration(200);
+
+        anim.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                endLatch.countDown();
+            }
+        });
+
+        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            float lastFraction = 0;
+            float lastX = 0;
+            float lastY = 0;
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                float[] values = (float[]) animation.getAnimatedValue();
+                assertEquals(2, values.length);
+                float x = values[0];
+                float y = values[1];
+                float fraction = animation.getAnimatedFraction();
+                // Given that the curve is symmetric about the line (x = 50), x should be less than
+                // 50 for half of the animation duration.
+                if (fraction < 0.5) {
+                    assertTrue(x < QUADRATIC_CTRL_PT2_X);
+                } else {
+                    assertTrue(x >= QUADRATIC_CTRL_PT2_X);
+                }
+
+                if (lastFraction > 0.5) {
+                    // x should be increasing, y should be decreasing
+                    assertTrue(x >= lastX);
+                    assertTrue(y <= lastY);
+                } else if (fraction <= 0.5) {
+                    // when fraction <= 0.5, both x, y should be increasing
+                    assertTrue(x >= lastX);
+                    assertTrue(y >= lastY);
+                }
+                lastX = x;
+                lastY = y;
+                lastFraction = fraction;
+            }
+        });
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                anim.start();
+            }
+        });
+        assertTrue(endLatch.await(400, TimeUnit.MILLISECONDS));
+    }
+
+    public void testOfMultiFloat() throws Throwable {
+        // Test for ObjectAnimator.ofMultiFloat(Object, String, float[][]);
+        final float[][] data = new float[10][];
+        for (int i = 0; i < data.length; i++) {
+            data[i] = new float[3];
+            data[i][0] = i;
+            data[i][1] = i * 2;
+            data[i][2] = 0f;
+        }
+
+        Object target = new Object() {
+            public void setPosition(float x, float y, float z) {
+            }
+        };
+        final CountDownLatch endLatch = new CountDownLatch(1);
+        final ObjectAnimator anim = ObjectAnimator.ofMultiFloat(target, "position", data);
+        anim.setInterpolator(null);
+        anim.setDuration(60);
+        anim.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                endLatch.countDown();
+            }
+        });
+
+        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                float fraction = animation.getAnimatedFraction();
+                float[] values = (float[]) animation.getAnimatedValue();
+                assertEquals(3, values.length);
+
+                float expectedX = fraction * (data.length - 1);
+
+                assertEquals(expectedX, values[0]);
+                assertEquals(expectedX * 2, values[1]);
+                assertEquals(0f, values[2]);
+            }
+        });
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                anim.start();
+            }
+        });
+        assertTrue(endLatch.await(200, TimeUnit.MILLISECONDS));
+    }
+
+    public void testOfMultiInt_Path() throws Throwable {
+        // Test for ObjectAnimator.ofMultiInt(Object, String, Path);
+        // Create a quadratic bezier curve that are symmetric about the vertical line (x = 50).
+        // Expect when fraction < 0.5, x < 50, otherwise, x >= 50.
+        Path path = new Path();
+        path.moveTo(QUADRATIC_CTRL_PT1_X, QUADRATIC_CTRL_PT1_Y);
+        path.quadTo(QUADRATIC_CTRL_PT2_X, QUADRATIC_CTRL_PT2_Y,
+                QUADRATIC_CTRL_PT3_X, QUADRATIC_CTRL_PT3_Y);
+
+        Object target = new Object() {
+            public void setPosition(int x, int y) {
+            }
+        };
+
+        final CountDownLatch endLatch = new CountDownLatch(1);
+        final ObjectAnimator anim = ObjectAnimator.ofMultiInt(target, "position", path);
+        // Linear interpolator
+        anim.setInterpolator(null);
+        anim.setDuration(200);
+
+        anim.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                endLatch.countDown();
+            }
+        });
+
+        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            float lastFraction = 0;
+            int lastX = 0;
+            int lastY = 0;
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                int[] values = (int[]) animation.getAnimatedValue();
+                assertEquals(2, values.length);
+                int x = values[0];
+                int y = values[1];
+                float fraction = animation.getAnimatedFraction();
+                // Given that the curve is symmetric about the line (x = 50), x should be less than
+                // 50 for half of the animation duration.
+                if (fraction < 0.5) {
+                    assertTrue(x < QUADRATIC_CTRL_PT2_X);
+                } else {
+                    assertTrue(x >= QUADRATIC_CTRL_PT2_X);
+                }
+
+                if (lastFraction > 0.5) {
+                    // x should be increasing, y should be decreasing
+                    assertTrue(x >= lastX);
+                    assertTrue(y <= lastY);
+                } else if (fraction <= 0.5) {
+                    // when fraction <= 0.5, both x, y should be increasing
+                    assertTrue(x >= lastX);
+                    assertTrue(y >= lastY);
+                }
+                lastX = x;
+                lastY = y;
+                lastFraction = fraction;
+            }
+        });
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                anim.start();
+            }
+        });
+        assertTrue(endLatch.await(400, TimeUnit.MILLISECONDS));
+    }
+
+    public void testOfMultiInt() throws Throwable {
+        // Test for ObjectAnimator.ofMultiFloat(Object, String, int[][]);
+        final int[][] data = new int[10][];
+        for (int i = 0; i < data.length; i++) {
+            data[i] = new int[3];
+            data[i][0] = i;
+            data[i][1] = i * 2;
+            data[i][2] = 0;
+        }
+
+        Object target = new Object() {
+            public void setPosition(int x, int y, int z) {
+            }
+        };
+        final CountDownLatch endLatch = new CountDownLatch(1);
+        final ObjectAnimator anim = ObjectAnimator.ofMultiInt(target, "position", data);
+        anim.setInterpolator(null);
+        anim.setDuration(60);
+        anim.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                endLatch.countDown();
+            }
+        });
+
+        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                float fraction = animation.getAnimatedFraction();
+                int[] values = (int[]) animation.getAnimatedValue();
+                assertEquals(3, values.length);
+
+                int expectedX = Math.round(fraction * (data.length - 1));
+                int expectedY = Math.round(fraction * (data.length - 1) * 2);
+
+                // Allow a delta of 1 for rounding errors.
+                assertEquals(expectedX, values[0], 1);
+                assertEquals(expectedY, values[1], 1);
+                assertEquals(0, values[2]);
+            }
+        });
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                anim.start();
+            }
+        });
+        assertTrue(endLatch.await(200, TimeUnit.MILLISECONDS));
+    }
+
+    public void testOfObject_Converter() throws Throwable {
+        // Test for ObjectAnimator.ofObject(Object, String, TypeConverter<T, V>, Path)
+        // Create a path that contains two disconnected line segments. Check that the animated
+        // property x and property y always stay on the line segments.
+        Path path = new Path();
+        path.moveTo(LINE1_START, -LINE1_START);
+        path.lineTo(LINE1_END, -LINE1_END);
+        path.moveTo(LINE2_START, LINE2_START);
+        path.lineTo(LINE2_END, LINE2_END);
+
+        Object target1 = new Object() {
+            public void setDistance(float distance) {
+            }
+        };
+        Object target2 = new Object() {
+            public void setPosition(PointF pos) {
+            }
+        };
+        TypeConverter<PointF, Float> converter = new TypeConverter<PointF, Float>(
+                PointF.class, Float.class) {
+            @Override
+            public Float convert(PointF value) {
+                return (float) Math.sqrt(value.x * value.x + value.y * value.y);
+            }
+        };
+        final CountDownLatch endLatch = new CountDownLatch(2);
+
+        // Create two animators. One use a converter that converts the point to distance to origin.
+        // The other one does not have a type converter.
+        final ObjectAnimator anim1 = ObjectAnimator.ofObject(target1, "distance", converter, path);
+        anim1.setDuration(100);
+        anim1.setInterpolator(null);
+        anim1.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                endLatch.countDown();
+            }
+        });
+
+        final ObjectAnimator anim2 = ObjectAnimator.ofObject(target2, "position", null, path);
+        anim2.setDuration(100);
+        anim2.setInterpolator(null);
+        anim2.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                endLatch.countDown();
+            }
+        });
+        anim2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            // Set the initial value of the distance to the distance between the first point on
+            // the path to the origin.
+            float mLastDistance = (float) (32 * Math.sqrt(2));
+            float mLastFraction = 0f;
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                float fraction = anim1.getAnimatedFraction();
+                assertEquals(fraction, anim2.getAnimatedFraction());
+                float distance = (Float) anim1.getAnimatedValue();
+                PointF position = (PointF) anim2.getAnimatedValue();
+
+                // Manually calculate the distance for the animator that doesn't have a
+                // TypeConverter, and expect the result to be the same as the animation value from
+                // the type converter.
+                float distanceFromPosition = (float) Math.sqrt(
+                        position.x * position.x + position.y * position.y);
+                assertEquals(distance, distanceFromPosition, 0.0001f);
+
+                if (mLastFraction > 0.75) {
+                    // In the 2nd line segment of the path, distance to origin should be increasing.
+                    assertTrue(distance >= mLastDistance);
+                } else if (fraction < 0.75) {
+                    assertTrue(distance <= mLastDistance);
+                }
+                mLastDistance = distance;
+                mLastFraction = fraction;
+            }
+        });
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                anim1.start();
+                anim2.start();
+            }
+        });
+
+        // Wait until both of the animations finish
+        assertTrue(endLatch.await(200, TimeUnit.MILLISECONDS));
+    }
+
     public void testIsStarted() throws Throwable {
         Object object = mActivity.view.newBall;
         String property = "y";
@@ -308,6 +850,46 @@
         });
     }
 
+    public void testCachedValues() throws Throwable {
+        final AnimTarget target = new AnimTarget();
+        final ObjectAnimator anim = ObjectAnimator.ofFloat(target, "testValue", 100);
+        anim.setDuration(200);
+        final CountDownLatch twoFramesLatch = new CountDownLatch(2);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                anim.start();
+                final View decor = getActivity().getWindow().getDecorView();
+                decor.postOnAnimation(new Runnable() {
+                    @Override
+                    public void run() {
+                        if (twoFramesLatch.getCount() > 0) {
+                            twoFramesLatch.countDown();
+                            decor.postOnAnimation(this);
+                        }
+                    }
+                });
+            }
+        });
+
+        assertTrue("Animation didn't start in a reasonable time",
+                twoFramesLatch.await(100, TimeUnit.MILLISECONDS));
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertTrue("Start value should readjust to current position",
+                        target.getTestValue() != 0);
+                anim.cancel();
+                anim.setupStartValues();
+                anim.start();
+                assertTrue("Start value should readjust to current position",
+                        target.getTestValue() != 0);
+                anim.cancel();
+            }
+        });
+    }
+
     static class AnimTarget {
         private float mTestValue = 0;
 
diff --git a/tests/tests/animation/src/android/animation/cts/PropertyValuesHolderTest.java b/tests/tests/animation/src/android/animation/cts/PropertyValuesHolderTest.java
index 200ebce..5e23b29 100644
--- a/tests/tests/animation/src/android/animation/cts/PropertyValuesHolderTest.java
+++ b/tests/tests/animation/src/android/animation/cts/PropertyValuesHolderTest.java
@@ -21,9 +21,14 @@
 import android.animation.Keyframe;
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
+import android.animation.TypeConverter;
 import android.animation.ValueAnimator;
+import android.graphics.Color;
+import android.graphics.Path;
+import android.graphics.PointF;
 import android.graphics.drawable.ShapeDrawable;
 import android.test.ActivityInstrumentationTestCase2;
+import android.util.FloatProperty;
 import android.util.Property;
 import android.view.View;
 import android.view.animation.AccelerateInterpolator;
@@ -33,6 +38,18 @@
 
 public class PropertyValuesHolderTest extends
         ActivityInstrumentationTestCase2<AnimationActivity> {
+    private static final float LINE1_START = -32f;
+    private static final float LINE1_END = -2f;
+    private static final float LINE1_Y = 0f;
+    private static final float LINE2_START = 2f;
+    private static final float LINE2_END = 12f;
+    private static final float QUADRATIC_CTRL_PT1_X = 0f;
+    private static final float QUADRATIC_CTRL_PT1_Y = 0f;
+    private static final float QUADRATIC_CTRL_PT2_X = 50f;
+    private static final float QUADRATIC_CTRL_PT2_Y = 20f;
+    private static final float QUADRATIC_CTRL_PT3_X = 100f;
+    private static final float QUADRATIC_CTRL_PT3_Y = 0f;
+
     private AnimationActivity mActivity;
     private Animator mAnimator;
     private long mDuration = 1000;
@@ -199,7 +216,7 @@
         assertEquals("Animation should run as expected", 100f, mActivity.view.newBall.getY());
     }
 
-    public void testOffloat() throws Throwable {
+    public void testOfFloat() throws Throwable {
         float[] values = {mStartY, mEndY};
         PropertyValuesHolder pVHolder = PropertyValuesHolder.ofFloat(mProperty, values);
         assertNotNull(pVHolder);
@@ -272,10 +289,425 @@
             mDuration);
         startAnimation(objectAnimator, colorAnimator);
         Thread.sleep(1000);
-        Integer i = (Integer) colorAnimator.getAnimatedValue();
-        //We are going from less negative value to a more negative value
-        assertTrue(i.intValue() <= startColor);
-        assertTrue(endColor <= i.intValue());
+        Integer animatedValue = (Integer) colorAnimator.getAnimatedValue();
+        int redMin = Math.min(Color.red(startColor), Color.red(endColor));
+        int redMax = Math.max(Color.red(startColor), Color.red(endColor));
+        int blueMin = Math.min(Color.blue(startColor), Color.blue(endColor));
+        int blueMax = Math.max(Color.blue(startColor), Color.blue(endColor));
+        assertTrue(Color.red(animatedValue) >= redMin);
+        assertTrue(Color.red(animatedValue) <= redMax);
+        assertTrue(Color.blue(animatedValue) >= blueMin);
+        assertTrue(Color.blue(animatedValue) <= blueMax);
+    }
+
+    public void testOfMultiFloat_Path() throws Throwable {
+        // Test for PropertyValuesHolder.ofMultiFloat(String, Path);
+        // Create a quadratic bezier curve that are symmetric about the vertical line (x = 50).
+        // Expect when fraction < 0.5, x < 50, otherwise, x >= 50.
+        Path path = new Path();
+        path.moveTo(QUADRATIC_CTRL_PT1_X, QUADRATIC_CTRL_PT1_Y);
+        path.quadTo(QUADRATIC_CTRL_PT2_X, QUADRATIC_CTRL_PT2_Y,
+                QUADRATIC_CTRL_PT3_X, QUADRATIC_CTRL_PT3_Y);
+
+        PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiFloat("position", path);
+        final ValueAnimator anim = ValueAnimator.ofPropertyValuesHolder(pvh);
+
+        final CountDownLatch endLatch = new CountDownLatch(1);
+        // Linear interpolator
+        anim.setInterpolator(null);
+        anim.setDuration(200);
+
+        anim.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                endLatch.countDown();
+            }
+        });
+
+        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            float lastFraction = 0;
+            float lastX = 0;
+            float lastY = 0;
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                float[] values = (float[]) animation.getAnimatedValue();
+                assertEquals(2, values.length);
+                float x = values[0];
+                float y = values[1];
+                float fraction = animation.getAnimatedFraction();
+                // Given that the curve is symmetric about the line (x = 50), x should be less than
+                // 50 for half of the animation duration.
+                if (fraction < 0.5) {
+                    assertTrue(x < QUADRATIC_CTRL_PT2_X);
+                } else {
+                    assertTrue(x >= QUADRATIC_CTRL_PT2_X);
+                }
+
+                if (lastFraction > 0.5) {
+                    // x should be increasing, y should be decreasing
+                    assertTrue(x >= lastX);
+                    assertTrue(y <= lastY);
+                } else if (fraction <= 0.5) {
+                    // when fraction <= 0.5, both x, y should be increasing
+                    assertTrue(x >= lastX);
+                    assertTrue(y >= lastY);
+                }
+                lastX = x;
+                lastY = y;
+                lastFraction = fraction;
+            }
+        });
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                anim.start();
+            }
+        });
+        assertTrue(endLatch.await(400, TimeUnit.MILLISECONDS));
+    }
+
+    public void testOfMultiFloat_Array() throws Throwable {
+        // Test for PropertyValuesHolder.ofMultiFloat(String, float[][]);
+        final float[][] data = new float[10][];
+        for (int i = 0; i < data.length; i++) {
+            data[i] = new float[3];
+            data[i][0] = i;
+            data[i][1] = i * 2;
+            data[i][2] = 0f;
+        }
+        final CountDownLatch endLatch = new CountDownLatch(1);
+        final PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiFloat("position", data);
+
+        final ValueAnimator anim = ValueAnimator.ofPropertyValuesHolder(pvh);
+        anim.setInterpolator(null);
+        anim.setDuration(60);
+        anim.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                endLatch.countDown();
+            }
+        });
+
+        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                float fraction = animation.getAnimatedFraction();
+                float[] values = (float[]) animation.getAnimatedValue();
+                assertEquals(3, values.length);
+
+                float expectedX = fraction * (data.length - 1);
+
+                assertEquals(expectedX, values[0]);
+                assertEquals(expectedX * 2, values[1]);
+                assertEquals(0f, values[2]);
+            }
+        });
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                anim.start();
+            }
+        });
+        assertTrue(endLatch.await(200, TimeUnit.MILLISECONDS));
+    }
+
+    public void testOfMultiInt_Path() throws Throwable {
+        // Test for PropertyValuesHolder.ofMultiInt(String, Path);
+        // Create a quadratic bezier curve that are symmetric about the vertical line (x = 50).
+        // Expect when fraction < 0.5, x < 50, otherwise, x >= 50.
+        Path path = new Path();
+        path.moveTo(QUADRATIC_CTRL_PT1_X, QUADRATIC_CTRL_PT1_Y);
+        path.quadTo(QUADRATIC_CTRL_PT2_X, QUADRATIC_CTRL_PT2_Y,
+                QUADRATIC_CTRL_PT3_X, QUADRATIC_CTRL_PT3_Y);
+
+        final CountDownLatch endLatch = new CountDownLatch(1);
+        final PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiInt("position", path);
+        final ValueAnimator anim = ValueAnimator.ofPropertyValuesHolder(pvh);
+        // Linear interpolator
+        anim.setInterpolator(null);
+        anim.setDuration(200);
+
+        anim.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                endLatch.countDown();
+            }
+        });
+
+        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            float lastFraction = 0;
+            int lastX = 0;
+            int lastY = 0;
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                int[] values = (int[]) animation.getAnimatedValue();
+                assertEquals(2, values.length);
+                int x = values[0];
+                int y = values[1];
+                float fraction = animation.getAnimatedFraction();
+                // Given that the curve is symmetric about the line (x = 50), x should be less than
+                // 50 for half of the animation duration.
+                if (fraction < 0.5) {
+                    assertTrue(x < QUADRATIC_CTRL_PT2_X);
+                } else {
+                    assertTrue(x >= QUADRATIC_CTRL_PT2_X);
+                }
+
+                if (lastFraction > 0.5) {
+                    // x should be increasing, y should be decreasing
+                    assertTrue(x >= lastX);
+                    assertTrue(y <= lastY);
+                } else if (fraction <= 0.5) {
+                    // when fraction <= 0.5, both x, y should be increasing
+                    assertTrue(x >= lastX);
+                    assertTrue(y >= lastY);
+                }
+                lastX = x;
+                lastY = y;
+                lastFraction = fraction;
+            }
+        });
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                anim.start();
+            }
+        });
+        assertTrue(endLatch.await(400, TimeUnit.MILLISECONDS));
+    }
+
+    public void testOfMultiInt_Array() throws Throwable {
+        // Test for PropertyValuesHolder.ofMultiFloat(String, int[][]);
+        final int[][] data = new int[10][];
+        for (int i = 0; i < data.length; i++) {
+            data[i] = new int[3];
+            data[i][0] = i;
+            data[i][1] = i * 2;
+            data[i][2] = 0;
+        }
+
+        final CountDownLatch endLatch = new CountDownLatch(1);
+        final PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiInt("position", data);
+        final ValueAnimator anim = ValueAnimator.ofPropertyValuesHolder(pvh);
+        anim.setInterpolator(null);
+        anim.setDuration(60);
+        anim.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                endLatch.countDown();
+            }
+        });
+
+        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                float fraction = animation.getAnimatedFraction();
+                int[] values = (int[]) animation.getAnimatedValue();
+                assertEquals(3, values.length);
+
+                int expectedX = Math.round(fraction * (data.length - 1));
+                int expectedY = Math.round(fraction * (data.length - 1) * 2);
+
+                // Allow a delta of 1 for rounding errors.
+                assertEquals(expectedX, values[0], 1);
+                assertEquals(expectedY, values[1], 1);
+                assertEquals(0, values[2]);
+            }
+        });
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                anim.start();
+            }
+        });
+        assertTrue(endLatch.await(200, TimeUnit.MILLISECONDS));
+    }
+
+    public void testOfObject_Converter() throws Throwable {
+        // Test for PropertyValuesHolder.ofObject(String, TypeConverter<T, V>, Path)
+        // and for PropertyValuesHolder.ofObject(Property, TypeConverter<T, V>, Path)
+        // Create a path that contains two disconnected line segments. Check that the animated
+        // property x and property y always stay on the line segments.
+        Path path = new Path();
+        path.moveTo(LINE1_START, -LINE1_START);
+        path.lineTo(LINE1_END, -LINE1_END);
+        path.moveTo(LINE2_START, LINE2_START);
+        path.lineTo(LINE2_END, LINE2_END);
+        TypeConverter<PointF, Float> converter = new TypeConverter<PointF, Float>(
+                PointF.class, Float.class) {
+            @Override
+            public Float convert(PointF value) {
+                return (float) Math.sqrt(value.x * value.x + value.y * value.y);
+            }
+        };
+        final CountDownLatch endLatch = new CountDownLatch(3);
+
+        // Create three animators. The first one use a converter that converts the point to distance
+        // to  origin. The second one does not have a type converter. The third animator uses a
+        // converter to changes sign of the x, y value of the input pointF.
+        FloatProperty property = new FloatProperty("distance") {
+            @Override
+            public void setValue(Object object, float value) {
+            }
+
+            @Override
+            public Object get(Object object) {
+                return null;
+            }
+        };
+        final PropertyValuesHolder pvh1 =
+                PropertyValuesHolder.ofObject(property, converter, path);
+        final ValueAnimator anim1 = ValueAnimator.ofPropertyValuesHolder(pvh1);
+        anim1.setDuration(100);
+        anim1.setInterpolator(null);
+        anim1.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                endLatch.countDown();
+            }
+        });
+
+        final PropertyValuesHolder pvh2 =
+                PropertyValuesHolder.ofObject("position", null, path);
+        final ValueAnimator anim2 = ValueAnimator.ofPropertyValuesHolder(pvh2);
+        anim2.setDuration(100);
+        anim2.setInterpolator(null);
+        anim2.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                endLatch.countDown();
+            }
+        });
+
+        TypeConverter<PointF, PointF> converter3 = new TypeConverter<PointF, PointF>(
+                PointF.class, PointF.class) {
+            PointF mValue = new PointF();
+            @Override
+            public PointF convert(PointF value) {
+                mValue.x = -value.x;
+                mValue.y = -value.y;
+                return mValue;
+            }
+        };
+        final PropertyValuesHolder pvh3 =
+                PropertyValuesHolder.ofObject("position", converter3, path);
+        final ValueAnimator anim3 = ValueAnimator.ofPropertyValuesHolder(pvh3);
+        anim3.setDuration(100);
+        anim3.setInterpolator(null);
+        anim3.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                endLatch.countDown();
+            }
+        });
+
+        anim3.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            // Set the initial value of the distance to the distance between the first point on
+            // the path to the origin.
+            float mLastDistance = (float) (32 * Math.sqrt(2));
+            float mLastFraction = 0f;
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                float fraction = anim1.getAnimatedFraction();
+                assertEquals(fraction, anim2.getAnimatedFraction());
+                assertEquals(fraction, anim3.getAnimatedFraction());
+                float distance = (Float) anim1.getAnimatedValue();
+                PointF position = (PointF) anim2.getAnimatedValue();
+                PointF positionReverseSign = (PointF) anim3.getAnimatedValue();
+                assertEquals(position.x, -positionReverseSign.x);
+                assertEquals(position.y, -positionReverseSign.y);
+
+                // Manually calculate the distance for the animator that doesn't have a
+                // TypeConverter, and expect the result to be the same as the animation value from
+                // the type converter.
+                float distanceFromPosition = (float) Math.sqrt(
+                        position.x * position.x + position.y * position.y);
+                assertEquals(distance, distanceFromPosition, 0.0001f);
+
+                if (mLastFraction > 0.75) {
+                    // In the 2nd line segment of the path, distance to origin should be increasing.
+                    assertTrue(distance >= mLastDistance);
+                } else if (fraction < 0.75) {
+                    assertTrue(distance <= mLastDistance);
+                }
+                mLastDistance = distance;
+                mLastFraction = fraction;
+            }
+        });
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                anim1.start();
+                anim2.start();
+                anim3.start();
+            }
+        });
+
+        // Wait until both of the animations finish
+        assertTrue(endLatch.await(200, TimeUnit.MILLISECONDS));
+    }
+
+    public void testSetConverter() throws Throwable {
+        // Test for PropertyValuesHolder.setConverter()
+        PropertyValuesHolder pvh = PropertyValuesHolder.ofObject("", null, 0f, 1f);
+        // Reverse the sign of the float in the converter, and use that value as the new type
+        // PointF's x value.
+        pvh.setConverter(new TypeConverter<Float, PointF>(Float.class, PointF.class) {
+            PointF mValue = new PointF();
+            @Override
+            public PointF convert(Float value) {
+                mValue.x = value * (-1f);
+                mValue.y = 0f;
+                return mValue;
+            }
+        });
+        final CountDownLatch endLatch = new CountDownLatch(2);
+
+        final ValueAnimator anim1 = ValueAnimator.ofPropertyValuesHolder(pvh);
+        anim1.setInterpolator(null);
+        anim1.setDuration(100);
+        anim1.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                endLatch.countDown();
+            }
+        });
+
+        final ValueAnimator anim2 = ValueAnimator.ofFloat(0f, 1f);
+        anim2.setInterpolator(null);
+        anim2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                assertEquals(anim1.getAnimatedFraction(), anim2.getAnimatedFraction());
+                // Check that the pvh with type converter did reverse the sign of float, and set
+                // the x value of the PointF with it.
+                PointF value1 = (PointF) anim1.getAnimatedValue();
+                float value2 = (Float) anim2.getAnimatedValue();
+                assertEquals(value2, -value1.x);
+                assertEquals(0f, value1.y);
+            }
+        });
+        anim2.setDuration(100);
+        anim2.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                endLatch.countDown();
+            }
+        });
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                anim1.start();
+                anim2.start();
+            }
+        });
+
+        // Wait until both of the animations finish
+        assertTrue(endLatch.await(200, TimeUnit.MILLISECONDS));
     }
 
     public void testSetProperty() throws Throwable {
diff --git a/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java b/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java
index b778530..b43cc3a 100644
--- a/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java
+++ b/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java
@@ -19,6 +19,7 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
+import android.graphics.Color;
 import android.test.ActivityInstrumentationTestCase2;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.LinearInterpolator;
@@ -393,6 +394,57 @@
         assertTrue(animatedValue <= end);
     }
 
+    public void testOfArgb() throws Throwable {
+        int start = 0xffff0000;
+        int end = 0xff0000ff;
+        int[] values = {start, end};
+        int startRed = Color.red(start);
+        int startBlue = Color.blue(start);
+        int endRed = Color.red(end);
+        int endBlue = Color.blue(end);
+        final ValueAnimator valueAnimatorLocal = ValueAnimator.ofArgb(values);
+        valueAnimatorLocal.setDuration(mDuration);
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        valueAnimatorLocal.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                if (animation.getAnimatedFraction() > .05f) {
+                    latch.countDown();
+                }
+            }
+        });
+
+        this.runTestOnUiThread(new Runnable(){
+            public void run() {
+                valueAnimatorLocal.start();
+            }
+        });
+        boolean isRunning = valueAnimatorLocal.isRunning();
+        assertTrue(isRunning);
+
+        assertTrue(latch.await(500, TimeUnit.MILLISECONDS));
+
+        Integer animatedValue = (Integer) valueAnimatorLocal.getAnimatedValue();
+        int alpha = Color.alpha(animatedValue);
+        int red = Color.red(animatedValue);
+        int green = Color.green(animatedValue);
+        int blue = Color.blue(animatedValue);
+        assertTrue(red < startRed);
+        assertTrue(red > endRed);
+        assertTrue(blue > startBlue);
+        assertTrue(blue < endBlue);
+        assertEquals(255, alpha);
+        assertEquals(0, green);
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                valueAnimatorLocal.cancel();
+            }
+        });
+    }
+
     public void testNoDelayOnSeekAnimation() throws Throwable {
         ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
         animator.setInterpolator(new LinearInterpolator());
@@ -418,6 +470,31 @@
         });
     }
 
+    public void testNotifiesAfterEnd() throws Throwable {
+        final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
+        animator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                assertTrue(animation.isStarted());
+                assertTrue(animation.isRunning());
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                assertFalse(animation.isRunning());
+                assertFalse(animation.isStarted());
+                super.onAnimationEnd(animation);
+            }
+        });
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                animator.start();
+                animator.end();
+            }
+        });
+    }
+
     private ValueAnimator getAnimator() {
         Object object = mActivity.view.newBall;
         String property = "y";
diff --git a/tests/tests/app.usage/Android.mk b/tests/tests/app.usage/Android.mk
index 4cc3606..0303dbd 100644
--- a/tests/tests/app.usage/Android.mk
+++ b/tests/tests/app.usage/Android.mk
@@ -26,7 +26,7 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java b/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java
index bd96d76..2c3c2ad 100644
--- a/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java
+++ b/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java
@@ -26,6 +26,9 @@
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
 import android.net.NetworkRequest;
+import android.net.TrafficStats;
+import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.RemoteException;
@@ -53,6 +56,12 @@
     private static final long MINUTE = 1000 * 60;
     private static final int TIMEOUT_MILLIS = 15000;
 
+    private static final String CHECK_CONNECTIVITY_URL = "http://www.265.com/";
+    private static final String CHECK_CALLBACK_URL = CHECK_CONNECTIVITY_URL;
+
+    private static final int NETWORK_TAG = 0xf00d;
+    private static final long THRESHOLD_BYTES = 2 * 1024 * 1024;  // 2 MB
+
     private interface NetworkInterfaceToTest {
         int getNetworkType();
         int getTransportType();
@@ -119,7 +128,7 @@
     private String mWriteSettingsMode;
     private String mUsageStatsMode;
 
-    private void exerciseRemoteHost(Network network) throws Exception {
+    private void exerciseRemoteHost(Network network, URL url) throws Exception {
         NetworkInfo networkInfo = mCm.getNetworkInfo(network);
         if (networkInfo == null) {
             Log.w(LOG_TAG, "Network info is null");
@@ -131,8 +140,8 @@
         String originalKeepAlive = System.getProperty("http.keepAlive");
         System.setProperty("http.keepAlive", "false");
         try {
-            urlc = (HttpURLConnection) network.openConnection(new URL(
-                    "http://www.265.com/"));
+            TrafficStats.setThreadStatsTag(NETWORK_TAG);
+            urlc = (HttpURLConnection) network.openConnection(url);
             urlc.setConnectTimeout(TIMEOUT_MILLIS);
             urlc.setUseCaches(false);
             urlc.connect();
@@ -147,6 +156,7 @@
         } catch (Exception e) {
             Log.i(LOG_TAG, "Badness during exercising remote server: " + e);
         } finally {
+            TrafficStats.clearThreadStatsTag();
             if (in != null) {
                 try {
                     in.close();
@@ -229,10 +239,12 @@
 
     private class NetworkCallback extends ConnectivityManager.NetworkCallback {
         private long mTolerance;
+        private URL mUrl;
         public boolean success;
 
-        NetworkCallback(long tolerance) {
+        NetworkCallback(long tolerance, URL url) {
             mTolerance = tolerance;
+            mUrl = url;
             success = false;
         }
 
@@ -240,7 +252,7 @@
         public void onAvailable(Network network) {
             try {
                 mStartTime = System.currentTimeMillis() - mTolerance;
-                exerciseRemoteHost(network);
+                exerciseRemoteHost(network, mUrl);
                 mEndTime = System.currentTimeMillis() + mTolerance;
                 success = true;
                 synchronized(NetworkUsageStatsTest.this) {
@@ -260,7 +272,7 @@
         if (!hasFeature) {
             return false;
         }
-        NetworkCallback callback = new NetworkCallback(tolerance);
+        NetworkCallback callback = new NetworkCallback(tolerance, new URL(CHECK_CONNECTIVITY_URL));
         mCm.requestNetwork(new NetworkRequest.Builder()
                 .addTransportType(sNetworkInterfacesToTest[networkTypeIndex].getTransportType())
                 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
@@ -520,10 +532,99 @@
         }
     }
 
+    public void testTagDetails() throws Exception {
+        for (int i = 0; i < sNetworkInterfacesToTest.length; ++i) {
+            // Relatively large tolerance to accommodate for history bucket size.
+            if (!shouldTestThisNetworkType(i, MINUTE * 120)) {
+                continue;
+            }
+            setAppOpsMode(AppOpsManager.OPSTR_GET_USAGE_STATS, "allow");
+            NetworkStats result = null;
+            try {
+                result = mNsm.queryDetailsForUidTag(
+                        sNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
+                        mStartTime, mEndTime, Process.myUid(), NETWORK_TAG);
+                assertTrue(result != null);
+                NetworkStats.Bucket bucket = new NetworkStats.Bucket();
+                long totalTxPackets = 0;
+                long totalRxPackets = 0;
+                long totalTxBytes = 0;
+                long totalRxBytes = 0;
+                while (result.hasNextBucket()) {
+                    assertTrue(result.getNextBucket(bucket));
+                    assertTimestamps(bucket);
+                    assertEquals(bucket.getState(), NetworkStats.Bucket.STATE_ALL);
+                    assertEquals(bucket.getUid(), Process.myUid());
+                    if (bucket.getTag() == NETWORK_TAG) {
+                        totalTxPackets += bucket.getTxPackets();
+                        totalRxPackets += bucket.getRxPackets();
+                        totalTxBytes += bucket.getTxBytes();
+                        totalRxBytes += bucket.getRxBytes();
+                    }
+                }
+                assertTrue("No Rx bytes tagged with 0x" + Integer.toHexString(NETWORK_TAG)
+                        + " for uid " + Process.myUid(), totalRxBytes > 0);
+                assertTrue("No Rx packets tagged with " + Integer.toHexString(NETWORK_TAG)
+                        + " for uid " + Process.myUid(), totalRxPackets > 0);
+                assertTrue("No Tx bytes tagged with 0x" + Integer.toHexString(NETWORK_TAG)
+                        + " for uid " + Process.myUid(), totalTxBytes > 0);
+                assertTrue("No Tx packets tagged with 0x" + Integer.toHexString(NETWORK_TAG)
+                        + " for uid " + Process.myUid(), totalTxPackets > 0);
+            } catch (SecurityException e) {
+                fail("testUidDetails fails with exception: " + e.toString());
+            } finally {
+                if (result != null) {
+                    result.close();
+                }
+            }
+            setAppOpsMode(AppOpsManager.OPSTR_GET_USAGE_STATS, "deny");
+            try {
+                result = mNsm.queryDetailsForUidTag(
+                        sNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
+                        mStartTime, mEndTime, Process.myUid(), NETWORK_TAG);
+                fail("negative testUidDetails fails: no exception thrown.");
+            } catch (SecurityException e) {
+                // expected outcome
+            }
+        }
+    }
+
+    public void testCallback() throws Exception {
+        for (int i = 0; i < sNetworkInterfacesToTest.length; ++i) {
+            // Relatively large tolerance to accommodate for history bucket size.
+            if (!shouldTestThisNetworkType(i, MINUTE/2)) {
+                continue;
+            }
+            setAppOpsMode(AppOpsManager.OPSTR_GET_USAGE_STATS, "allow");
+
+            TestUsageCallback usageCallback = new TestUsageCallback();
+            HandlerThread thread = new HandlerThread("callback-thread");
+            thread.start();
+            Handler handler = new Handler(thread.getLooper());
+            mNsm.registerUsageCallback(sNetworkInterfacesToTest[i].getNetworkType(),
+                    getSubscriberId(i), THRESHOLD_BYTES, usageCallback, handler);
+
+            // TODO: Force traffic and check whether the callback is invoked.
+            // Right now the test only covers whether the callback can be registered, but not
+            // whether it is invoked upon data usage since we don't have a scalable way of
+            // storing files of >2MB in CTS.
+
+            mNsm.unregisterUsageCallback(usageCallback);
+        }
+    }
+
     private void assertTimestamps(final NetworkStats.Bucket bucket) {
         assertTrue("Start timestamp " + bucket.getStartTimeStamp() + " is less than " +
                 mStartTime, bucket.getStartTimeStamp() >= mStartTime);
         assertTrue("End timestamp " + bucket.getEndTimeStamp() + " is greater than " +
                 mEndTime, bucket.getEndTimeStamp() <= mEndTime);
     }
+
+    private static class TestUsageCallback extends NetworkStatsManager.UsageCallback {
+        @Override
+        public void onThresholdReached(int networkType, String subscriberId) {
+            Log.v(LOG_TAG, "Called onThresholdReached for networkType=" + networkType
+                    + " subscriberId=" + subscriberId);
+        }
+    }
 }
diff --git a/tests/tests/app/Android.mk b/tests/tests/app/Android.mk
index 08201a6..cf76aa0b 100644
--- a/tests/tests/app/Android.mk
+++ b/tests/tests/app/Android.mk
@@ -26,7 +26,7 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java b/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
index be6a759..e192a0c 100644
--- a/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
+++ b/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
@@ -107,4 +107,27 @@
         }
     }
 
+    public void testGetIccAuthentication() {
+        // EAP-SIM rand is 16 bytes.
+        String base64Challenge = "ECcTqwuo6OfY8ddFRboD9WM=";
+        String base64Challenge2 = "EMNxjsFrPCpm+KcgCmQGnwQ=";
+        if (!hasCellular) return;
+        try {
+            assertNull("getIccAuthentication should return null for empty data.",
+                    mTelephonyManager.getIccAuthentication(TelephonyManager.APPTYPE_USIM,
+                    TelephonyManager.AUTHTYPE_EAP_AKA, ""));
+            String response = mTelephonyManager.getIccAuthentication(TelephonyManager.APPTYPE_USIM,
+                    TelephonyManager.AUTHTYPE_EAP_SIM, base64Challenge);
+            assertTrue("Response to EAP-SIM Challenge must not be Null.", response != null);
+            // response is base64 encoded. After decoding, the value should be:
+            // 1 length byte + SRES(4 bytes) + 1 length byte + Kc(8 bytes)
+            byte[] result = android.util.Base64.decode(response, android.util.Base64.DEFAULT);
+            assertTrue("Result length must be 14 bytes.", 14 == result.length);
+            String response2 = mTelephonyManager.getIccAuthentication(TelephonyManager.APPTYPE_USIM,
+                    TelephonyManager.AUTHTYPE_EAP_SIM, base64Challenge2);
+            assertTrue("Two responses must be different.", !response.equals(response2));
+        } catch (SecurityException e) {
+            failMessage();
+        }
+    }
 }
diff --git a/tests/tests/content/Android.mk b/tests/tests/content/Android.mk
index a22d539..73191c3 100644
--- a/tests/tests/content/Android.mk
+++ b/tests/tests/content/Android.mk
@@ -26,9 +26,16 @@
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 ctsdeviceutil ctstestrunner services.core
 
 # Resource unit tests use a private locale and some densities
-LOCAL_AAPT_FLAGS = -c xx_YY -c cs -c small -c normal -c large -c xlarge \
+LOCAL_AAPT_FLAGS = -c small -c normal -c large -c xlarge \
         -c 320dpi -c 240dpi -c 160dpi -c 32dpi \
-        -c kok,kok_IN,kok_419,kok_419_VARIANT,kok_Knda_419,kok_Knda_419_VARIANT,kok_VARIANT,kok_Knda,tgl,tgl_PH
+        -c cs \
+        -c fil,fil_SA \
+        -c iw,iw_IL \
+        -c kok,kok_IN,kok_419,kok_419_VARIANT,kok_Knda_419,kok_Knda_419_VARIANT,kok_VARIANT,kok_Knda \
+        -c mk,mk_MK \
+        -c tgl,tgl_PH \
+        -c tlh \
+        -c xx_YY
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/content/res/values-b+fil+SA/configVarying.xml b/tests/tests/content/res/values-b+fil+SA/configVarying.xml
new file mode 100644
index 0000000..ba3c653
--- /dev/null
+++ b/tests/tests/content/res/values-b+fil+SA/configVarying.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag fil SA</item>
+    </bag>
+</resources>
diff --git a/tests/tests/content/res/values-b+fil/configVarying.xml b/tests/tests/content/res/values-b+fil/configVarying.xml
new file mode 100644
index 0000000..2fa8f9f
--- /dev/null
+++ b/tests/tests/content/res/values-b+fil/configVarying.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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>
+    <item type="configVarying" name="simple">simple fil</item>
+</resources>
diff --git a/tests/tests/content/res/values-b+tlh/configVarying.xml b/tests/tests/content/res/values-b+tlh/configVarying.xml
new file mode 100644
index 0000000..48730f3
--- /dev/null
+++ b/tests/tests/content/res/values-b+tlh/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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>
+    <item type="configVarying" name="simple">simple tlh</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag tlh</item>
+    </bag>
+</resources>
diff --git a/tests/tests/content/res/values-iw-rIL/configVarying.xml b/tests/tests/content/res/values-iw-rIL/configVarying.xml
new file mode 100644
index 0000000..a42f026
--- /dev/null
+++ b/tests/tests/content/res/values-iw-rIL/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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>
+    <item type="configVarying" name="simple">simple iw IL</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag iw IL</item>
+    </bag>
+</resources>
diff --git a/tests/tests/content/res/values-iw/configVarying.xml b/tests/tests/content/res/values-iw/configVarying.xml
new file mode 100644
index 0000000..8eabd93
--- /dev/null
+++ b/tests/tests/content/res/values-iw/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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>
+    <item type="configVarying" name="simple">simple iw</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag iw</item>
+    </bag>
+</resources>
diff --git a/tests/tests/content/res/values-mk-rMK/configVarying.xml b/tests/tests/content/res/values-mk-rMK/configVarying.xml
new file mode 100644
index 0000000..14265ef
--- /dev/null
+++ b/tests/tests/content/res/values-mk-rMK/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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>
+    <item type="configVarying" name="simple">simple mk MK</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag mk MK</item>
+    </bag>
+</resources>
diff --git a/tests/tests/content/res/values-mk/configVarying.xml b/tests/tests/content/res/values-mk/configVarying.xml
new file mode 100644
index 0000000..edd1099
--- /dev/null
+++ b/tests/tests/content/res/values-mk/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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>
+    <item type="configVarying" name="simple">simple mk</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag mk</item>
+    </bag>
+</resources>
diff --git a/tests/tests/content/res/values/resources_test.xml b/tests/tests/content/res/values/resources_test.xml
index 91c2c4a..78385186 100644
--- a/tests/tests/content/res/values/resources_test.xml
+++ b/tests/tests/content/res/values/resources_test.xml
@@ -22,6 +22,10 @@
           will be displayed in the app launcher and elsewhere. -->
      <dimen name="app_icon_size">48px</dimen>
      <dimen name="toast_y_offset">64dip</dimen>
+    <dimen name="pos_dimen_149">1.49px</dimen>
+    <dimen name="pos_dimen_151">1.51px</dimen>
+    <dimen name="neg_dimen_149">-1.49px</dimen>
+    <dimen name="neg_dimen_151">-1.51px</dimen>
      <plurals name="plurals_test">
         <item quantity="one">A dog</item>
         <item quantity="other">Some dogs</item>
diff --git a/tests/tests/content/src/android/content/res/cts/AssetManagerTest.java b/tests/tests/content/src/android/content/res/cts/AssetManagerTest.java
index 4893ec1..1387be0 100644
--- a/tests/tests/content/src/android/content/res/cts/AssetManagerTest.java
+++ b/tests/tests/content/src/android/content/res/cts/AssetManagerTest.java
@@ -139,13 +139,16 @@
     public void testGetNonSystemLocales() {
         // This is the list of locales built into this test package. It is basically the locales
         // specified in the Android.mk files (assuming they have corresponding resources), plus the
-        // special case for Filipino.
+        // special cases for Filipino.
         final String KNOWN_LOCALES[] = {
             "cs",
             "fil",
             "fil-PH",
+            "fil-SA",
             "fr",
             "fr-FR",
+            "iw",
+            "iw-IL",
             "kok",
             "kok-419",
             "kok-419-variant",
@@ -154,8 +157,11 @@
             "kok-Knda-419",
             "kok-Knda-419-variant",
             "kok-variant",
+            "mk",
+            "mk-MK",
             "tgl",
             "tgl-PH",
+            "tlh",
             "xx",
             "xx-YY"
         };
diff --git a/tests/tests/content/src/android/content/res/cts/ConfigTest.java b/tests/tests/content/src/android/content/res/cts/ConfigTest.java
index 2390146..912de38 100644
--- a/tests/tests/content/src/android/content/res/cts/ConfigTest.java
+++ b/tests/tests/content/src/android/content/res/cts/ConfigTest.java
@@ -1153,6 +1153,42 @@
     }
 
     @MediumTest
+    public void testNormalLocales() {
+        Resources res;
+        TotalConfig config = makeClassicConfig();
+        // Hebrew
+        config.setProperty(Properties.LANGUAGE, "iw");
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple iw");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag iw"});
+
+        // Hebrew for Israel
+        config.setProperty(Properties.LANGUAGE, "iw");
+        config.setProperty(Properties.COUNTRY, "IL");
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple iw IL");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag iw IL"});
+
+        config = makeClassicConfig();
+        // Macedonian
+        config.setProperty(Properties.LANGUAGE, "mk");
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple mk");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag mk"});
+
+        // Macedonian for Macedonia
+        config.setProperty(Properties.LANGUAGE, "mk");
+        config.setProperty(Properties.COUNTRY, "MK");
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple mk MK");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag mk MK"});
+    }
+
+    @MediumTest
     public void testExtendedLocales() {
         TotalConfig config = makeClassicConfig();
         // BCP 47 Locale kok
@@ -1225,9 +1261,9 @@
         config.setProperty(Properties.LANGUAGE, "fil");
         config.setProperty(Properties.COUNTRY, "US");
         Resources res = config.getResources();
-        checkValue(res, R.configVarying.simple, "simple tl");
+        checkValue(res, R.configVarying.simple, "simple fil");  // We have this resource in 'fil'
         checkValue(res, R.configVarying.bag,
-                R.styleable.TestConfig, new String[] { "bag tl" });
+                R.styleable.TestConfig, new String[] { "bag tl" });  // But this comes from 'tl'
 
         // Ensure that "fil-PH" is mapped to "tl-PH" correctly.
         config = makeClassicConfig();
@@ -1238,6 +1274,24 @@
         checkValue(res, R.configVarying.bag,
                 R.styleable.TestConfig, new String[] { "bag tl PH" });
 
+        // Ensure that "fil-SA" works with no "tl" version.
+        config = makeClassicConfig();
+        config.setProperty(Properties.LANGUAGE, "fil");
+        config.setProperty(Properties.COUNTRY, "SA");
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple fil");  // This comes from 'fil'
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[] { "bag fil SA" });  // And this from 'fil-SA'
+
+        // Ensure that "tlh" is not mistakenly treated as a "tl" variant.
+        config = makeClassicConfig();
+        config.setProperty(Properties.LANGUAGE, "tlh");
+        config.setProperty(Properties.COUNTRY, "US");
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple tlh");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[] { "bag tlh" });
+
         config = makeClassicConfig();
         config.setProperty(Properties.LANGUAGE, "tgl");
         res = config.getResources();
@@ -1276,8 +1330,9 @@
         }
 
         assertEquals(0, tlLocales.size());
-        assertEquals(2, filLocales.size());
+        assertEquals(3, filLocales.size());
         assertTrue(filLocales.contains("fil"));
         assertTrue(filLocales.contains("fil-PH"));
+        assertTrue(filLocales.contains("fil-SA"));
     }
 }
diff --git a/tests/tests/content/src/android/content/res/cts/ResourcesTest.java b/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
index 0f40ebd..0c51099 100644
--- a/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
+++ b/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
@@ -288,6 +288,10 @@
         // app_icon_size is 48px, as defined in cts/tests/res/values/resources_test.xml
         final int size = mResources.getDimensionPixelSize(R.dimen.app_icon_size);
         assertEquals(48, size);
+        assertEquals(1, mResources.getDimensionPixelSize(R.dimen.pos_dimen_149));
+        assertEquals(2, mResources.getDimensionPixelSize(R.dimen.pos_dimen_151));
+        assertEquals(-1, mResources.getDimensionPixelSize(R.dimen.neg_dimen_149));
+        assertEquals(-2, mResources.getDimensionPixelSize(R.dimen.neg_dimen_151));
     }
 
     public void testGetDrawable() {
diff --git a/tests/tests/graphics/Android.mk b/tests/tests/graphics/Android.mk
index 7e26e07..40beee6 100644
--- a/tests/tests/graphics/Android.mk
+++ b/tests/tests/graphics/Android.mk
@@ -22,7 +22,7 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := mockito-target ctsdeviceutil ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-annotations android-support-test mockito-target ctsdeviceutil ctstestrunner
 LOCAL_JNI_SHARED_LIBRARIES := libctsgraphics_jni
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/graphics/res/drawable/avd_empty_animator.xml b/tests/tests/graphics/res/drawable/avd_empty_animator.xml
new file mode 100644
index 0000000..cf6dd9a
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/avd_empty_animator.xml
@@ -0,0 +1,44 @@
+<?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.
+-->
+<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
+                 xmlns:android="http://schemas.android.com/apk/res/android">
+    <aapt:attr name="android:drawable">
+        <vector
+                android:width="32dp"
+                android:viewportWidth="32"
+                android:height="32dp"
+                android:viewportHeight="32">
+            <group
+                    android:name="btn_radio_to_off_mtrl_0"
+                    android:translateX="16"
+                    android:translateY="16">
+                <group
+                        android:name="ring_outer">
+                    <path
+                            android:name="ring_outer_path"
+                            android:fillColor="#FF000000"
+                            android:pathData="M 0.0,-9.0 c 4.9705627482,0.0 9.0,4.0294372518 9.0,9.0 c 0.0,4.9705627482 -4.0294372518,9.0 -9.0,9.0 c -4.9705627482,0.0 -9.0,-4.0294372518 -9.0,-9.0 c 0.0,-4.9705627482 4.0294372518,-9.0 9.0,-9.0 Z"/>
+                </group>
+            </group>
+        </vector>
+    </aapt:attr>
+    <target android:name="ring_outer_path">
+        <aapt:attr name="android:animation">
+            <!-- Empty animator set -->
+            <set/>
+        </aapt:attr>
+    </target>
+</animated-vector>
diff --git a/tests/tests/graphics/res/raw/a4_portrait_rgbb.pdf b/tests/tests/graphics/res/raw/a4_portrait_rgbb.pdf
new file mode 100644
index 0000000..ed373b7
--- /dev/null
+++ b/tests/tests/graphics/res/raw/a4_portrait_rgbb.pdf
Binary files differ
diff --git a/tests/tests/graphics/res/raw/a5_portrait_rgbb.pdf b/tests/tests/graphics/res/raw/a5_portrait_rgbb.pdf
new file mode 100644
index 0000000..44e5a7a
--- /dev/null
+++ b/tests/tests/graphics/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/tests/graphics/res/raw/a5_portrait_rgbb_1_6_printscaling_default.pdf
new file mode 100644
index 0000000..1f4ec0b
--- /dev/null
+++ b/tests/tests/graphics/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/tests/graphics/res/raw/a5_portrait_rgbb_1_6_printscaling_none.pdf
new file mode 100644
index 0000000..4d7a0f4
--- /dev/null
+++ b/tests/tests/graphics/res/raw/a5_portrait_rgbb_1_6_printscaling_none.pdf
Binary files differ
diff --git a/tests/tests/graphics/res/raw/two_pages.pdf b/tests/tests/graphics/res/raw/two_pages.pdf
new file mode 100644
index 0000000..ee73ae6
--- /dev/null
+++ b/tests/tests/graphics/res/raw/two_pages.pdf
Binary files differ
diff --git a/tests/tests/graphics/src/android/graphics/cts/CameraTest.java b/tests/tests/graphics/src/android/graphics/cts/CameraTest.java
index a28d6ff..4fbe88b 100644
--- a/tests/tests/graphics/src/android/graphics/cts/CameraTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/CameraTest.java
@@ -18,8 +18,10 @@
 import android.graphics.Camera;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
+import android.support.test.filters.SmallTest;
 import android.test.AndroidTestCase;
 
+@SmallTest
 public class CameraTest extends AndroidTestCase {
     private Camera mCamera;
 
@@ -127,6 +129,35 @@
         assertEquals(1.0f, f[8]);
     }
 
+    public void testRotate() {
+        Matrix m1 = new Matrix();
+        preCompare(m1);
+
+        mCamera.rotate(15.0f, 30.0f, 45.0f);
+        Matrix m2 = new Matrix();
+        mCamera.getMatrix(m2);
+        assertFalse(m1.equals(m2));
+
+        float[] f = new float[9];
+        m2.getValues(f);
+        assertEquals(0.6123724f, f[0]);
+        assertEquals(0.6123724f, f[1]);
+        assertEquals(0.0f, f[2]);
+        assertEquals(-0.5915063f, f[3]);
+        assertEquals(0.774519f, f[4]);
+        assertEquals(0.0f, f[5]);
+        assertEquals(0.0009106233f, f[6]);
+        assertEquals(0.00027516257f, f[7]);
+        assertEquals(1.0f, f[8]);
+    }
+
+    public void testLocationAccessors() {
+        mCamera.setLocation(10.0f, 20.0f, 30.0f);
+        assertEquals(10.0f, mCamera.getLocationX());
+        assertEquals(20.0f, mCamera.getLocationY());
+        assertEquals(30.0f, mCamera.getLocationZ());
+    }
+
     public void testApplyToCanvas() {
         Canvas c1 = new Canvas();
         mCamera.applyToCanvas(c1);
diff --git a/tests/tests/graphics/src/android/graphics/cts/ColorTest.java b/tests/tests/graphics/src/android/graphics/cts/ColorTest.java
index 760e3f9..c180906 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ColorTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ColorTest.java
@@ -16,31 +16,43 @@
 package android.graphics.cts;
 
 import android.graphics.Color;
-import android.test.AndroidTestCase;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
 
-public class ColorTest extends AndroidTestCase {
+import static org.junit.Assert.*;
 
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ColorTest {
+    @Test
     public void testAlpha(){
         assertEquals(0xff, Color.alpha(Color.RED));
         assertEquals(0xff, Color.alpha(Color.YELLOW));
         new Color();
     }
 
+    @Test
     public void testArgb(){
         assertEquals(Color.RED, Color.argb(0xff, 0xff, 0x00, 0x00));
         assertEquals(Color.YELLOW, Color.argb(0xff, 0xff, 0xff, 0x00));
     }
 
+    @Test
     public void testBlue(){
         assertEquals(0x00, Color.blue(Color.RED));
         assertEquals(0x00, Color.blue(Color.YELLOW));
     }
 
+    @Test
     public void testGreen(){
         assertEquals(0x00, Color.green(Color.RED));
         assertEquals(0xff, Color.green(Color.GREEN));
     }
 
+    @Test
     public void testHSVToColor1(){
         //abnormal case: hsv length less than 3
         try{
@@ -56,6 +68,7 @@
         assertEquals(Color.RED, Color.HSVToColor(hsv));
     }
 
+    @Test
     public void testHSVToColor2(){
         //abnormal case: hsv length less than 3
         try{
@@ -71,6 +84,7 @@
         assertEquals(Color.RED, Color.HSVToColor(0xff, hsv));
     }
 
+    @Test
     public void testParseColor(){
         //abnormal case: colorString starts with '#' but length is neither 7 nor 9
         try{
@@ -104,16 +118,19 @@
         assertEquals(Color.MAGENTA, Color.parseColor("magenta"));
     }
 
+    @Test
     public void testRed(){
         assertEquals(0xff, Color.red(Color.RED));
         assertEquals(0xff, Color.red(Color.YELLOW));
     }
 
+    @Test
     public void testRgb(){
         assertEquals(Color.RED, Color.rgb(0xff, 0x00, 0x00));
         assertEquals(Color.YELLOW, Color.rgb(0xff, 0xff, 0x00));
     }
 
+    @Test
     public void testRGBToHSV(){
         //abnormal case: hsv length less than 3
         try{
@@ -128,4 +145,14 @@
         Color.RGBToHSV(0xff, 0x00, 0x00, hsv);
         assertEquals(Color.RED, Color.HSVToColor(hsv));
     }
+
+    @Test
+    public void testLuminance() {
+        assertEquals(0, Color.luminance(Color.BLACK), 0);
+        float eps = 0.000001f;
+        assertEquals(0.0722, Color.luminance(Color.BLUE), eps);
+        assertEquals(0.2126, Color.luminance(Color.RED), eps);
+        assertEquals(0.7152, Color.luminance(Color.GREEN), eps);
+        assertEquals(1, Color.luminance(Color.WHITE), 0);
+    }
 }
diff --git a/tests/tests/graphics/src/android/graphics/cts/MatrixTest.java b/tests/tests/graphics/src/android/graphics/cts/MatrixTest.java
index 29e4f5f..5b600f6 100644
--- a/tests/tests/graphics/src/android/graphics/cts/MatrixTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/MatrixTest.java
@@ -15,39 +15,68 @@
  */
 package android.graphics.cts;
 
+import android.graphics.Camera;
 import android.graphics.Matrix;
 import android.graphics.RectF;
 import android.graphics.Matrix.ScaleToFit;
-import android.test.AndroidTestCase;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
-public class MatrixTest extends AndroidTestCase {
+import static org.junit.Assert.*;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class MatrixTest {
     private Matrix mMatrix;
     private float[] mValues;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @Before
+    public void setUp() {
         mMatrix = new Matrix();
         mValues = new float[9];
     }
 
-    public void testConstractor() {
-        new Matrix();
-        new Matrix(mMatrix);
+    @Test
+    public void testConstructor() {
+        assertTrue(new Matrix().isIdentity());
+        assertTrue(new Matrix(mMatrix).isIdentity());
     }
 
+    @Test
     public void testIsIdentity() {
         assertTrue(mMatrix.isIdentity());
         mMatrix.setScale(0f, 0f);
         assertFalse(mMatrix.isIdentity());
     }
 
+    @Test
     public void testRectStaysRect() {
         assertTrue(mMatrix.rectStaysRect());
         mMatrix.postRotate(80);
         assertFalse(mMatrix.rectStaysRect());
     }
 
+    @Test
+    public void testIsAffine() {
+        assertTrue(mMatrix.isAffine());
+
+        // translate/scale/rotateZ don't affect whether matrix is affine
+        mMatrix.postTranslate(50, 50);
+        mMatrix.postScale(20, 4);
+        mMatrix.postRotate(80);
+        assertTrue(mMatrix.isAffine());
+
+        Camera camera = new Camera();
+        camera.setLocation(0, 0, 100);
+        camera.rotateX(20);
+        camera.getMatrix(mMatrix);
+        assertFalse(mMatrix.isAffine());
+    }
+
+    @Test
     public void testSet() {
         mValues[0] = 1000;
         mMatrix.getValues(mValues);
@@ -56,9 +85,10 @@
         mValues = new float[9];
         mValues[0] = 2000;
         matrix.getValues(mValues);
-        assertEquals(1f, mValues[0]);
+        assertEquals(1f, mValues[0], 0f);
     }
 
+    @Test
     public void testEquals() {
         mMatrix.setScale(1f, 2f);
         Matrix matrix = new Matrix();
@@ -68,6 +98,7 @@
         assertTrue(mMatrix.equals(matrix));
     }
 
+    @Test
     public void testReset() {
         mMatrix.setScale(1f, 2f, 3f, 4f);
         String expect = "[1.0, 0.0, 0.0][0.0, 2.0, -4.0][0.0, 0.0, 1.0]";
@@ -77,6 +108,7 @@
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testSetScale() {
         String expect = "[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]";
         assertEquals(expect, mMatrix.toShortString());
@@ -85,6 +117,7 @@
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testSetScale2() {
         String expect = "[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]";
         assertEquals(expect, mMatrix.toShortString());
@@ -94,6 +127,7 @@
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testSetRotate() {
         mMatrix.setRotate(1f);
         String expect = "[0.9998477, -0.017452406, 0.0]"
@@ -101,6 +135,7 @@
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testSetRotate2() {
         mMatrix.setRotate(1f, 2f, 3f);
         String expect = "[0.9998477, -0.017452406, 0.0526618]"
@@ -108,30 +143,35 @@
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testSetSinCos() {
         mMatrix.setSinCos(1f, 2f);
         String expect = "[2.0, -1.0, 0.0][1.0, 2.0, 0.0][0.0, 0.0, 1.0]";
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testSetSinCos2() {
         mMatrix.setSinCos(1f, 2f, 3f, 4f);
         String expect = "[2.0, -1.0, 1.0][1.0, 2.0, -7.0][0.0, 0.0, 1.0]";
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testSetSkew() {
         mMatrix.setSkew(1f, 2f);
         String expect = "[1.0, 1.0, 0.0][2.0, 1.0, 0.0][0.0, 0.0, 1.0]";
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testSetSkew2() {
         mMatrix.setSkew(1f, 2f, 3f, 4f);
         String expect = "[1.0, 1.0, -4.0][2.0, 1.0, -6.0][0.0, 0.0, 1.0]";
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testSetConcat() {
         Matrix a = new Matrix();
         Matrix b = new Matrix();
@@ -151,24 +191,28 @@
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testPreTranslate() {
         assertTrue(mMatrix.preTranslate(1f, 2f));
         String expect = "[1.0, 0.0, 1.0][0.0, 1.0, 2.0][0.0, 0.0, 1.0]";
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testPreScale() {
         assertTrue(mMatrix.preScale(1f, 2f));
         String expect = "[1.0, 0.0, 0.0][0.0, 2.0, 0.0][0.0, 0.0, 1.0]";
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testPreScale2() {
         assertTrue(mMatrix.preScale(1f, 2f, 3f, 4f));
         String expect = "[1.0, 0.0, 0.0][0.0, 2.0, -4.0][0.0, 0.0, 1.0]";
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testPreRotate() {
         assertTrue(mMatrix.preRotate(1f));
         String expect = "[0.9998477, -0.017452406, 0.0][0.017452406, 0.9998477, "
@@ -176,6 +220,7 @@
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testPreRotate2() {
         assertTrue(mMatrix.preRotate(1f, 2f, 3f));
         float[] values = new float[9];
@@ -185,18 +230,21 @@
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testPreSkew() {
         assertTrue(mMatrix.preSkew(1f, 2f));
         String expect = "[1.0, 1.0, 0.0][2.0, 1.0, 0.0][0.0, 0.0, 1.0]";
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testPreSkew2() {
         assertTrue(mMatrix.preSkew(1f, 2f, 3f, 4f));
         String expect = "[1.0, 1.0, -4.0][2.0, 1.0, -6.0][0.0, 0.0, 1.0]";
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testPreConcat() {
         float[] values = new float[9];
         values[0] = 1000;
@@ -207,24 +255,28 @@
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testPostTranslate() {
         assertTrue(mMatrix.postTranslate(1f, 2f));
         String expect = "[1.0, 0.0, 1.0][0.0, 1.0, 2.0][0.0, 0.0, 1.0]";
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testPostScale() {
         assertTrue(mMatrix.postScale(1f, 2f));
         String expect = "[1.0, 0.0, 0.0][0.0, 2.0, 0.0][0.0, 0.0, 1.0]";
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testPostScale2() {
         assertTrue(mMatrix.postScale(1f, 2f, 3f, 4f));
         String expect = "[1.0, 0.0, 0.0][0.0, 2.0, -4.0][0.0, 0.0, 1.0]";
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testPostRotate() {
         assertTrue(mMatrix.postRotate(1f));
         String expect = "[0.9998477, -0.017452406, 0.0]" +
@@ -232,6 +284,7 @@
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testPostRotate2() {
         assertTrue(mMatrix.postRotate(1f, 2f, 3f));
         String expect = "[0.9998477, -0.017452406, 0.0526618]" +
@@ -239,18 +292,21 @@
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testPostSkew() {
         assertTrue(mMatrix.postSkew(1f, 2f));
         String expect = "[1.0, 1.0, 0.0][2.0, 1.0, 0.0][0.0, 0.0, 1.0]";
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testPostSkew2() {
         assertTrue(mMatrix.postSkew(1f, 2f, 3f, 4f));
         String expect = "[1.0, 1.0, -4.0][2.0, 1.0, -6.0][0.0, 0.0, 1.0]";
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testPostConcat() {
         Matrix matrix = new Matrix();
         float[] values = new float[9];
@@ -262,6 +318,7 @@
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testSetRectToRect() {
         RectF r1 = new RectF();
         r1.set(1f, 2f, 3f, 3f);
@@ -292,10 +349,11 @@
         try {
             mMatrix.setRectToRect(null, null, ScaleToFit.CENTER);
             fail("should throw exception");
-        } catch (Exception e) {
+        } catch (Exception ignored) {
         }
     }
 
+    @Test
     public void testInvert() {
         Matrix matrix = new Matrix();
         float[] values = new float[9];
@@ -310,11 +368,12 @@
         try {
             result = mMatrix.invert(null);
             fail("should throw exception");
-        } catch (Exception e) {
+        } catch (Exception ignored) {
         }
         assertFalse(result);
     }
 
+    @Test
     public void testSetPolyToPoly() {
         float[] src = new float[9];
         src[0] = 100f;
@@ -327,138 +386,147 @@
         try {
             mMatrix.setPolyToPoly(src, 0, dst, 0, 5);
             fail("should throw exception");
-        } catch (Exception e) {
+        } catch (Exception ignored) {
         }
     }
 
+    @Test
     public void testMapPoints() {
         float[] value = new float[9];
         value[0] = 100f;
         mMatrix.mapPoints(value);
-        assertEquals(value[0], 100f);
+        assertEquals(value[0], 100f, 0f);
         try {
             mMatrix.mapPoints(null);
             fail("should throw exception");
-        } catch (Exception e) {
+        } catch (Exception ignored) {
         }
     }
 
+    @Test
     public void testMapPoints2() {
         float[] dst = new float[9];
         dst[0] = 100f;
         float[] src = new float[9];
         src[0] = 200f;
         mMatrix.mapPoints(dst, src);
-        assertEquals(dst[0], 200f);
+        assertEquals(dst[0], 200f, 0f);
         try {
             mMatrix.mapPoints(new float[8], new float[9]);
             fail("should throw exception");
-        } catch (Exception e) {
+        } catch (Exception ignored) {
         }
     }
 
+    @Test
     public void testMapPoints3() {
         float[] dst = new float[9];
         dst[0] = 100f;
         float[] src = new float[9];
         src[0] = 200f;
         mMatrix.mapPoints(dst, 0, src, 0, 9 >> 1);
-        assertEquals(dst[0], 200f);
+        assertEquals(dst[0], 200f, 0f);
         try {
             mMatrix.mapPoints(null, 0, new float[9], 0, 1);
             fail("should throw exception");
-        } catch (Exception e) {
+        } catch (Exception ignored) {
         }
     }
 
+    @Test
     public void testMapVectors() {
         float[] values = new float[9];
-        values = new float[9];
         values[0] = 100f;
         mMatrix.mapVectors(values);
-        assertEquals(values[0], 100f);
+        assertEquals(values[0], 100f, 0f);
         try {
             mMatrix.mapVectors(null);
             fail("should throw exception");
-        } catch (Exception e) {
+        } catch (Exception ignored) {
         }
     }
 
+    @Test
     public void testMapVectors2() {
         float[] src = new float[9];
         src[0] = 100f;
         float[] dst = new float[9];
         dst[0] = 200f;
         mMatrix.mapVectors(dst, src);
-        assertEquals(dst[0], 100f);
+        assertEquals(dst[0], 100f, 0f);
 
         try {
             mMatrix.mapVectors(new float[9], new float[8]);
             fail("should throw exception");
-        } catch (Exception e) {
+        } catch (Exception ignored) {
         }
     }
 
+    @Test
     public void testMapVectors3() {
         float[] src = new float[9];
         src[0] = 100f;
         float[] dst = new float[9];
         dst[0] = 200f;
         mMatrix.mapVectors(dst, 0, src, 0, 1);
-        assertEquals(dst[0], 100f);
+        assertEquals(dst[0], 100f, 0f);
         try {
             mMatrix.mapVectors(dst, 0, src, 0, 10);
             fail("should throw exception");
-        } catch (Exception e) {
+        } catch (Exception ignored) {
         }
     }
 
+    @Test
     public void testMapRadius() {
-        assertEquals(mMatrix.mapRadius(100f), 100f);
+        assertEquals(mMatrix.mapRadius(100f), 100f, 0f);
         assertEquals(mMatrix.mapRadius(Float.MAX_VALUE),
-                Float.POSITIVE_INFINITY);
-        assertEquals(mMatrix.mapRadius(Float.MIN_VALUE), 0f);
+                Float.POSITIVE_INFINITY, 0f);
+        assertEquals(mMatrix.mapRadius(Float.MIN_VALUE), 0f, 0f);
     }
 
+    @Test
     public void testMapRect() {
         RectF r = new RectF();
         r.set(1f, 2f, 3f, 4f);
         assertTrue(mMatrix.mapRect(r));
-        assertEquals(1f, r.left);
-        assertEquals(2f, r.top);
-        assertEquals(3f, r.right);
-        assertEquals(4f, r.bottom);
+        assertEquals(1f, r.left, 0f);
+        assertEquals(2f, r.top, 0f);
+        assertEquals(3f, r.right, 0f);
+        assertEquals(4f, r.bottom, 0f);
 
         try {
             mMatrix.mapRect(null);
             fail("should throw exception");
-        } catch (Exception e) {
+        } catch (Exception ignored) {
         }
     }
 
+    @Test
     public void testMapRect2() {
         RectF dst = new RectF();
         dst.set(100f, 100f, 200f, 200f);
         RectF src = new RectF();
         dst.set(10f, 10f, 20f, 20f);
         assertTrue(mMatrix.mapRect(dst, src));
-        assertEquals(0f, dst.left);
-        assertEquals(0f, dst.top);
-        assertEquals(0f, dst.right);
-        assertEquals(0f, dst.bottom);
+        assertEquals(0f, dst.left, 0f);
+        assertEquals(0f, dst.top, 0f);
+        assertEquals(0f, dst.right, 0f);
+        assertEquals(0f, dst.bottom, 0f);
 
-        assertEquals(0f, src.left);
-        assertEquals(0f, src.top);
-        assertEquals(0f, src.right);
-        assertEquals(0f, src.bottom);
+        assertEquals(0f, src.left, 0f);
+        assertEquals(0f, src.top, 0f);
+        assertEquals(0f, src.right, 0f);
+        assertEquals(0f, src.bottom, 0f);
 
         try {
             mMatrix.mapRect(null, null);
             fail("should throw exception");
-        } catch (Exception e) {
+        } catch (Exception ignored) {
         }
     }
 
+    @Test
     public void testAccessValues() {
         Matrix matrix = new Matrix();
         mMatrix.invert(matrix);
@@ -478,15 +546,18 @@
                 + values[6] + ", " + values[7] + ", " + values[8] + "]";
     }
 
+    @Test
     public void testToString() {
         assertNotNull(mMatrix.toString());
     }
 
+    @Test
     public void testToShortString() {
         String expect = "[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]";
         assertEquals(expect, mMatrix.toShortString());
     }
 
+    @Test
     public void testSetTranslate() {
         mMatrix.setTranslate(2f, 3f);
         String expect = "[1.0, 0.0, 2.0][0.0, 1.0, 3.0][0.0, 0.0, 1.0]";
diff --git a/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java b/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java
index 8b73380..8dcd32d 100644
--- a/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java
@@ -16,9 +16,6 @@
 
 package android.graphics.cts;
 
-import android.graphics.cts.R;
-
-
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -29,8 +26,10 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.Region;
+import android.support.test.filters.SmallTest;
 import android.test.AndroidTestCase;
 
+@SmallTest
 public class NinePatchTest extends AndroidTestCase {
     private static int ALPHA_OPAQUE = 0xFF;
 
@@ -57,13 +56,37 @@
     }
 
     public void testConstructor() {
-        mNinePatch = null;
+        try {
+            mNinePatch = new NinePatch(mBitmap, new byte[2]);
+            fail("should throw exception");
+        } catch (Exception e) {
+        }
+
         try {
             mNinePatch = new NinePatch(mBitmap, new byte[2], NAME);
             fail("should throw exception");
         } catch (Exception e) {
         }
+
+        mNinePatch = new NinePatch(mBitmap, mChunk);
+        assertEquals(mBitmap, mNinePatch.getBitmap());
+        assertEquals(null, mNinePatch.getName());
+
         mNinePatch = new NinePatch(mBitmap, mChunk, NAME);
+        assertEquals(mBitmap, mNinePatch.getBitmap());
+        assertEquals(NAME, mNinePatch.getName());
+    }
+
+    public void testPaintAccessors() {
+        Paint p = new Paint();
+        mNinePatch = new NinePatch(mBitmap, mChunk, NAME);
+        assertNull(mNinePatch.getPaint());
+
+        mNinePatch.setPaint(p);
+        assertEquals(p, mNinePatch.getPaint());
+
+        mNinePatch.setPaint(null);
+        assertNull(mNinePatch.getPaint());
     }
 
     public void testIsNinePatchChunk() {
@@ -71,7 +94,6 @@
         Bitmap bitmap = Bitmap.createBitmap(COLOR, 10, 10, Bitmap.Config.ARGB_4444);
         assertFalse(NinePatch.isNinePatchChunk(bitmap.getNinePatchChunk()));
         assertFalse(NinePatch.isNinePatchChunk(null));
-
     }
 
     public void testDraw() {
diff --git a/tests/tests/graphics/src/android/graphics/cts/OutlineTest.java b/tests/tests/graphics/src/android/graphics/cts/OutlineTest.java
index 4b01916..57a20ee 100644
--- a/tests/tests/graphics/src/android/graphics/cts/OutlineTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/OutlineTest.java
@@ -19,14 +19,15 @@
 import android.graphics.Outline;
 import android.graphics.Path;
 import android.graphics.Rect;
+import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
 
 @SmallTest
+@RunWith(AndroidJUnit4.class)
 public class OutlineTest {
     @Test
     public void testDefaults() {
@@ -40,6 +41,20 @@
     }
 
     @Test
+    public void testCopyConstructor() {
+        Outline orig = new Outline();
+        orig.setAlpha(0.5f);
+        orig.setRect(10, 10, 20, 20);
+
+        Outline copy = new Outline(orig);
+        assertEquals(0.5f, copy.getAlpha(), 0.0f);
+
+        Rect copyRect = new Rect();
+        copy.getRect(copyRect);
+        assertEquals(new Rect(10, 10, 20, 20), copyRect);
+    }
+
+    @Test
     public void testGetSetAlpha() {
         Outline outline = new Outline();
 
@@ -60,6 +75,21 @@
     }
 
     @Test
+    public void testSet() {
+        Outline orig = new Outline();
+        orig.setAlpha(0.5f);
+        orig.setRect(10, 10, 20, 20);
+
+        Outline copy = new Outline();
+        copy.set(orig);
+        assertEquals(0.5f, copy.getAlpha(), 0.0f);
+
+        Rect copyRect = new Rect();
+        copy.getRect(copyRect);
+        assertEquals(new Rect(10, 10, 20, 20), copyRect);
+    }
+
+    @Test
     public void testSetRect() {
         Outline outline = new Outline();
         Rect outRect = new Rect();
@@ -135,6 +165,11 @@
         assertTrue(outline.getRect(outRect)); // is round rect, so works
         assertTrue(outline.canClip()); // is round rect, so works
         assertFalse(outline.isEmpty());
+
+        outline.setOval(new Rect(0, 0, 50, 50)); // same x & y radii, so round rect
+        assertTrue(outline.getRect(outRect)); // is round rect, so works
+        assertTrue(outline.canClip()); // is round rect, so works
+        assertFalse(outline.isEmpty());
     }
 
     @Test
diff --git a/tests/tests/graphics/src/android/graphics/cts/PathTest.java b/tests/tests/graphics/src/android/graphics/cts/PathTest.java
index 6e93400..6aef2cf 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PathTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PathTest.java
@@ -16,8 +16,6 @@
 
 package android.graphics.cts;
 
-import junit.framework.TestCase;
-
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
@@ -25,8 +23,16 @@
 import android.graphics.Paint;
 import android.graphics.Path;
 import android.graphics.RectF;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
-public class PathTest extends TestCase {
+import static org.junit.Assert.*;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class PathTest {
 
     // Test constants
     private static final float LEFT = 10.0f;
@@ -36,6 +42,7 @@
     private static final float XCOORD = 40.0f;
     private static final float YCOORD = 40.0f;
 
+    @Test
     public void testConstructor() {
         // new the Path instance
         new Path();
@@ -44,9 +51,8 @@
         new Path(new Path());
     }
 
+    @Test
     public void testAddRect1() {
-
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
         RectF rect = new RectF(LEFT, TOP, RIGHT, BOTTOM);
@@ -54,34 +60,34 @@
         assertFalse(path.isEmpty());
     }
 
+    @Test
     public void testAddRect2() {
-
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
         path.addRect(LEFT, TOP, RIGHT, BOTTOM, Path.Direction.CW);
         assertFalse(path.isEmpty());
     }
 
+    @Test
     public void testMoveTo() {
-        // new the Path instance
         Path path = new Path();
         path.moveTo(10.0f, 10.0f);
     }
 
+    @Test
     public void testSet() {
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
         Path path1 = new Path();
-        setPath(path1);
+        addRectToPath(path1);
         path.set(path1);
         assertPathsAreEquivalent(path, path1);
     }
 
+    @Test
     public void testSetCleanOld() {
         Path path = new Path();
-        setPath(path);
+        addRectToPath(path);
         path.addRect(new RectF(0, 0, 10, 10), Path.Direction.CW);
         Path path1 = new Path();
         path1.addRect(new RectF(10, 10, 20, 20), Path.Direction.CW);
@@ -89,15 +95,16 @@
         assertPathsAreEquivalent(path, path1);
     }
 
+    @Test
     public void testSetEmptyPath() {
-        // new the Path instance
         Path path = new Path();
-        setPath(path);
+        addRectToPath(path);
         Path path1 = new Path();
         path.set(path1);
         assertPathsAreEquivalent(path, path1);
     }
 
+    @Test
     public void testAccessFillType() {
         // set the expected value
         Path.FillType expected1 = Path.FillType.EVEN_ODD;
@@ -118,52 +125,49 @@
         assertEquals(expected4, path.getFillType());
     }
 
+    @Test
     public void testRQuadTo() {
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
         path.rQuadTo(5.0f, 5.0f, 10.0f, 10.0f);
         assertFalse(path.isEmpty());
     }
 
+    @Test
     public void testTransform1() {
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
         Path dst = new Path();
-        setPath(path);
+        addRectToPath(path);
         path.transform(new Matrix(), dst);
         assertFalse(dst.isEmpty());
     }
 
-    public void testTransform2() {
-
-    }
-
+    @Test
     public void testLineTo() {
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
         path.lineTo(XCOORD, YCOORD);
         assertFalse(path.isEmpty());
     }
 
+    @Test
     public void testClose() {
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
-        setPath(path);
+        addRectToPath(path);
         path.close();
     }
 
+    @Test
     public void testQuadTo() {
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
         path.quadTo(20.0f, 20.0f, 40.0f, 40.0f);
         assertFalse(path.isEmpty());
     }
 
+    @Test
     public void testAddCircle() {
         // new the Path instance
         Path path = new Path();
@@ -172,8 +176,8 @@
         assertFalse(path.isEmpty());
     }
 
+    @Test
     public void testArcTo1() {
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
         RectF oval = new RectF(LEFT, TOP, RIGHT, BOTTOM);
@@ -181,8 +185,8 @@
         assertFalse(path.isEmpty());
     }
 
+    @Test
     public void testArcTo2() {
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
         RectF oval = new RectF(LEFT, TOP, RIGHT, BOTTOM);
@@ -190,81 +194,77 @@
         assertFalse(path.isEmpty());
     }
 
+    @Test
     public void testComputeBounds1() {
-
         RectF expected = new RectF(0.0f, 0.0f, 0.0f, 0.0f);
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
         RectF bounds = new RectF();
         path.computeBounds(bounds, true);
-        assertEquals(expected.width(), bounds.width());
-        assertEquals(expected.height(), bounds.height());
+        assertEquals(expected.width(), bounds.width(), 0.0f);
+        assertEquals(expected.height(), bounds.height(), 0.0f);
         path.computeBounds(bounds, false);
-        assertEquals(expected.width(), bounds.width());
-        assertEquals(expected.height(), bounds.height());
+        assertEquals(expected.width(), bounds.width(), 0.0f);
+        assertEquals(expected.height(), bounds.height(), 0.0f);
     }
 
+    @Test
     public void testComputeBounds2() {
-
         RectF expected = new RectF(LEFT, TOP, RIGHT, BOTTOM);
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
         RectF bounds = new RectF(LEFT, TOP, RIGHT, BOTTOM);
         path.addRect(bounds, Path.Direction.CW);
         path.computeBounds(bounds, true);
-        assertEquals(expected.width(), bounds.width());
-        assertEquals(expected.height(), bounds.height());
+        assertEquals(expected.width(), bounds.width(), 0.0f);
+        assertEquals(expected.height(), bounds.height(), 0.0f);
         path.computeBounds(bounds, false);
-        assertEquals(expected.width(), bounds.width());
-        assertEquals(expected.height(), bounds.height());
+        assertEquals(expected.width(), bounds.width(), 0.0f);
+        assertEquals(expected.height(), bounds.height(), 0.0f);
     }
 
+    @Test
     public void testRMoveTo() {
-        // new the Path instance
     }
 
+    @Test
     public void testSetLastPoint() {
-        // new the Path instance
         Path path = new Path();
         path.setLastPoint(10.0f, 10.0f);
     }
 
+    @Test
     public void testRLineTo() {
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
         path.rLineTo(10.0f, 10.0f);
         assertFalse(path.isEmpty());
     }
 
+    @Test
     public void testIsEmpty() {
 
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
-        setPath(path);
+        addRectToPath(path);
         assertFalse(path.isEmpty());
     }
 
+    @Test
     public void testRewind() {
-
-        // set the expected value
         Path.FillType expected = Path.FillType.EVEN_ODD;
 
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
-        setPath(path);
+        addRectToPath(path);
         path.rewind();
         path.setFillType(Path.FillType.EVEN_ODD);
         assertTrue(path.isEmpty());
         assertEquals(expected, path.getFillType());
     }
 
+    @Test
     public void testAddOval() {
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
         RectF oval = new RectF(LEFT, TOP, RIGHT, BOTTOM);
@@ -272,50 +272,46 @@
         assertFalse(path.isEmpty());
     }
 
+    @Test
     public void testIsRect() {
-
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
-        setPath(path);
+        addRectToPath(path);
     }
 
-    public void testIncReserve() {
-    }
-
+    @Test
     public void testAddPath1() {
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
         Path src = new Path();
-        setPath(src);
+        addRectToPath(src);
         path.addPath(src, 10.0f, 10.0f);
         assertFalse(path.isEmpty());
     }
 
+    @Test
     public void testAddPath2() {
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
         Path src = new Path();
-        setPath(src);
+        addRectToPath(src);
         path.addPath(src);
         assertFalse(path.isEmpty());
     }
 
+    @Test
     public void testAddPath3() {
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
         Path src = new Path();
-        setPath(src);
+        addRectToPath(src);
         Matrix matrix = new Matrix();
         path.addPath(src, matrix);
         assertFalse(path.isEmpty());
     }
 
+    @Test
     public void testAddRoundRect1() {
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
         RectF rect = new RectF(LEFT, TOP, RIGHT, BOTTOM);
@@ -323,8 +319,8 @@
         assertFalse(path.isEmpty());
     }
 
+    @Test
     public void testAddRoundRect2() {
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
         RectF rect = new RectF(LEFT, TOP, RIGHT, BOTTOM);
@@ -336,59 +332,84 @@
         assertFalse(path.isEmpty());
     }
 
-    public void testIsInverseFillType() {
+    @Test
+    public void testIsConvex1() {
+        Path path = new Path();
+        path.addRect(0, 0, 100, 10, Path.Direction.CW);
+        assertTrue(path.isConvex());
 
-        // new the Path instance
+        path.addRect(0, 0, 10, 100, Path.Direction.CW);
+        assertFalse(path.isConvex()); // path is concave
+    }
+
+    @Test
+    public void testIsConvex2() {
+        Path path = new Path();
+        path.addRect(0, 0, 40, 40, Path.Direction.CW);
+        assertTrue(path.isConvex());
+
+        path.addRect(10, 10, 30, 30, Path.Direction.CCW);
+        assertFalse(path.isConvex()); // path has hole, isn't convex
+    }
+
+    @Test
+    public void testIsConvex3() {
+        Path path = new Path();
+        path.addRect(0, 0, 10, 10, Path.Direction.CW);
+        assertTrue(path.isConvex());
+
+        path.addRect(0, 20, 10, 10, Path.Direction.CW);
+        assertFalse(path.isConvex()); // path isn't one convex shape
+    }
+
+    @Test
+    public void testIsInverseFillType() {
         Path path = new Path();
         assertFalse(path.isInverseFillType());
         path.setFillType(Path.FillType.INVERSE_EVEN_ODD);
         assertTrue(path.isInverseFillType());
     }
 
+    @Test
     public void testOffset1() {
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
-        setPath(path);
+        addRectToPath(path);
         Path dst = new Path();
         path.offset(XCOORD, YCOORD, dst);
         assertFalse(dst.isEmpty());
     }
 
-    public void testOffset2() {
-        // new the Path instance
-    }
-
+    @Test
     public void testCubicTo() {
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
         path.cubicTo(10.0f, 10.0f, 20.0f, 20.0f, 30.0f, 30.0f);
         assertFalse(path.isEmpty());
     }
 
+    @Test
     public void testReset() {
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
         Path path1 = new Path();
-        setPath(path1);
+        addRectToPath(path1);
         path.set(path1);
         assertFalse(path.isEmpty());
         path.reset();
         assertTrue(path.isEmpty());
     }
 
+    @Test
     public void testToggleInverseFillType() {
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
         path.toggleInverseFillType();
         assertTrue(path.isInverseFillType());
     }
 
+    @Test
     public void testAddArc() {
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
         RectF oval = new RectF(LEFT, TOP, RIGHT, BOTTOM);
@@ -396,8 +417,8 @@
         assertFalse(path.isEmpty());
     }
 
+    @Test
     public void testRCubicTo() {
-        // new the Path instance
         Path path = new Path();
         assertTrue(path.isEmpty());
         path.rCubicTo(10.0f, 10.0f, 11.0f, 11.0f, 12.0f, 12.0f);
@@ -423,7 +444,7 @@
         return bitmap;
     }
 
-    private void setPath(Path path) {
+    private void addRectToPath(Path path) {
         RectF rect = new RectF(LEFT, TOP, RIGHT, BOTTOM);
         path.addRect(rect, Path.Direction.CW);
     }
diff --git a/tests/tests/graphics/src/android/graphics/cts/PointFTest.java b/tests/tests/graphics/src/android/graphics/cts/PointFTest.java
index 77b72d4..0bef3e7 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PointFTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PointFTest.java
@@ -18,33 +18,21 @@
 
 import android.graphics.Point;
 import android.graphics.PointF;
+import android.os.Parcel;
+import android.support.test.filters.SmallTest;
 import android.test.AndroidTestCase;
 
+@SmallTest
 public class PointFTest extends AndroidTestCase {
 
     private PointF mPointF;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mPointF = null;
-    }
-
     public void testConstructor() {
-
-        mPointF = null;
-        // new the PointF instance
         mPointF = new PointF();
-
-        mPointF = null;
-        // new the PointF instance
         mPointF = new PointF(10.0f, 10.0f);
 
-        mPointF = null;
         Point point = new Point(10, 10);
-        // new the PointF instance
         mPointF = new PointF(point);
-
     }
 
     public void testNegate() {
@@ -91,4 +79,20 @@
         assertEquals(11.1f, mPointF.y);
     }
 
+    public void testDescribeContents() {
+        mPointF = new PointF(10.0f, 20.0f);
+        assertEquals(0, mPointF.describeContents());
+    }
+
+    public void testParceling() {
+        mPointF = new PointF(10.0f, 20.0f);
+        Parcel p = Parcel.obtain();
+        mPointF.writeToParcel(p, 0);
+        p.setDataPosition(0);
+
+        mPointF = new PointF();
+        mPointF.readFromParcel(p);
+        assertEquals(10.0f, mPointF.x);
+        assertEquals(20.0f, mPointF.y);
+    }
 }
diff --git a/tests/tests/graphics/src/android/graphics/cts/PointTest.java b/tests/tests/graphics/src/android/graphics/cts/PointTest.java
index e4ede58..bee4034 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PointTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PointTest.java
@@ -17,30 +17,21 @@
 package android.graphics.cts;
 
 import android.graphics.Point;
+import android.os.Parcel;
+import android.support.test.filters.SmallTest;
 import android.test.AndroidTestCase;
 
+@SmallTest
 public class PointTest extends AndroidTestCase {
 
     private Point mPoint;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mPoint = null;
-    }
-
     public void testConstructor() {
-
-        // new the Point instance
         mPoint = new Point();
-
-        // new the Point instance
         mPoint = new Point(10, 10);
 
         Point point = new Point(10, 10);
-        // new the Point instance
         mPoint = new Point(point);
-
     }
 
     public void testSet() {
@@ -89,4 +80,20 @@
         assertEquals(-10, mPoint.y);
     }
 
+    public void testDescribeContents() {
+        mPoint = new Point(10, 20);
+        assertEquals(0, mPoint.describeContents());
+    }
+
+    public void testParceling() {
+        mPoint = new Point(10, 20);
+        Parcel p = Parcel.obtain();
+        mPoint.writeToParcel(p, 0);
+        p.setDataPosition(0);
+
+        mPoint = new Point();
+        mPoint.readFromParcel(p);
+        assertEquals(10, mPoint.x);
+        assertEquals(20, mPoint.y);
+    }
 }
diff --git a/tests/tests/graphics/src/android/graphics/cts/RectFTest.java b/tests/tests/graphics/src/android/graphics/cts/RectFTest.java
index f5788af..0240690 100644
--- a/tests/tests/graphics/src/android/graphics/cts/RectFTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/RectFTest.java
@@ -16,46 +16,28 @@
 
 package android.graphics.cts;
 
-
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.os.Parcel;
+import android.support.test.filters.SmallTest;
 import android.test.AndroidTestCase;
 
+@SmallTest
 public class RectFTest extends AndroidTestCase {
-
     private RectF mRectF;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mRectF = null;
-    }
-
     public void testConstructor() {
-
-        mRectF = null;
-        // new the RectF instance
         mRectF = new RectF();
-
-        mRectF = null;
-        // new the RectF instance
         mRectF = new RectF(1.5f, 2.5f, 20.3f, 40.9f);
 
-        mRectF = null;
         RectF rectF = new RectF(1.5f, 2.5f, 20.3f, 40.9f);
-        // new the RectF instance
         mRectF = new RectF(rectF);
 
-        mRectF = null;
         Rect rect = new Rect(0, 0, 10, 10);
-        // new the RectF instance
         mRectF = new RectF(rect);
-
     }
 
     public void testSort() {
-
         mRectF = new RectF(10, 10, 5, 5);
         assertEquals(10.0f, mRectF.left);
         assertEquals(10.0f, mRectF.top);
@@ -67,22 +49,18 @@
         assertEquals(5.0f, mRectF.top);
         assertEquals(10.0f, mRectF.right);
         assertEquals(10.0f, mRectF.bottom);
-
     }
 
     public void testSet1() {
-
         mRectF = new RectF();
         mRectF.set(1.0f, 2.0f, 3.0f, 4.0f);
         assertEquals(1.0f, mRectF.left);
         assertEquals(2.0f, mRectF.top);
         assertEquals(3.0f, mRectF.right);
         assertEquals(4.0f, mRectF.bottom);
-
     }
 
     public void testSet2() {
-
         RectF rectF = new RectF(1.0f, 2.0f, 3.0f, 4.0f);
         mRectF = new RectF();
         mRectF.set(rectF);
@@ -90,11 +68,9 @@
         assertEquals(2.0f, mRectF.top);
         assertEquals(3.0f, mRectF.right);
         assertEquals(4.0f, mRectF.bottom);
-
     }
 
     public void testSet3() {
-
         Rect rect = new Rect(1, 2, 3, 4);
         mRectF = new RectF();
         mRectF.set(rect);
@@ -102,11 +78,9 @@
         assertEquals(2.0f, mRectF.top);
         assertEquals(3.0f, mRectF.right);
         assertEquals(4.0f, mRectF.bottom);
-
     }
 
     public void testIntersects1() {
-
         mRectF = new RectF(0, 0, 10, 10);
         assertTrue(mRectF.intersects(5, 5, 15, 15));
         assertEquals(0.0f, mRectF.left);
@@ -120,11 +94,9 @@
         assertEquals(0.0f, mRectF.top);
         assertEquals(10.0f, mRectF.right);
         assertEquals(10.0f, mRectF.bottom);
-
     }
 
     public void testIntersects2() {
-
         RectF rectF1;
         RectF rectF2;
 
@@ -135,11 +107,9 @@
         rectF1 = new RectF(0, 0, 10, 10);
         rectF2 = new RectF(15, 15, 25, 25);
         assertFalse(RectF.intersects(rectF1, rectF2));
-
     }
 
     public void testIntersect1() {
-
         mRectF = new RectF(0, 0, 10, 10);
         assertTrue(mRectF.intersect(5, 5, 15, 15));
         assertEquals(5.0f, mRectF.left);
@@ -153,11 +123,9 @@
         assertEquals(0.0f, mRectF.top);
         assertEquals(10.0f, mRectF.right);
         assertEquals(10.0f, mRectF.bottom);
-
     }
 
     public void testIntersect2() {
-
         RectF rectF;
 
         mRectF = new RectF(0, 0, 10, 10);
@@ -175,11 +143,9 @@
         assertEquals(0.0f, mRectF.top);
         assertEquals(10.0f, mRectF.right);
         assertEquals(10.0f, mRectF.bottom);
-
     }
 
     public void testUnion1() {
-
         // Both rect1 and rect2 are not empty.
         // 1. left < right, top < bottom
         // this.left < this.right, this.top < this.bottom
@@ -225,11 +191,9 @@
         assertEquals(0.0f, mRectF.left);
         assertEquals(1.0f, mRectF.right);
         assertEquals(1.0f, mRectF.bottom);
-
     }
 
     public void testUnion2() {
-
         RectF rectF;
 
         // Both rect1 and rect2 are not empty.
@@ -282,11 +246,9 @@
         assertEquals(0.0f, mRectF.left);
         assertEquals(1.0f, mRectF.right);
         assertEquals(1.0f, mRectF.bottom);
-
     }
 
     public void testUnion3() {
-
         // rect1 is not empty (x > right, y > bottom).
         mRectF = new RectF(0.0f, 0.0f, 1.0f, 1.0f);
         mRectF.union(2.0f, 2.0f);
@@ -318,21 +280,17 @@
         assertEquals(0.0f, mRectF.left);
         assertEquals(2.0f, mRectF.right);
         assertEquals(2.0f, mRectF.bottom);
-
     }
 
     public void testContains1() {
-
         mRectF = new RectF(1.0f, 1.0f, 20.0f, 20.0f);
         assertFalse(mRectF.contains(0.9f, 0.9f));
         assertTrue(mRectF.contains(1.0f, 1.0f));
         assertTrue(mRectF.contains(19.9f, 19.9f));
         assertFalse(mRectF.contains(20.0f, 20.0f));
-
     }
 
     public void testContains2() {
-
         mRectF = new RectF(1.0f, 1.0f, 20.0f, 20.0f);
         assertTrue(mRectF.contains(1.0f, 1.0f, 20.0f, 20.0f));
         assertTrue(mRectF.contains(2.0f, 2.0f, 19.0f, 19.0f));
@@ -341,7 +299,6 @@
     }
 
     public void testContains3() {
-
         RectF rectF;
         mRectF = new RectF(1.0f, 1.0f, 20.0f, 20.0f);
         rectF = new RectF(1.0f, 1.0f, 20.0f, 20.0f);
@@ -352,22 +309,18 @@
         assertFalse(mRectF.contains(rectF));
         rectF = new RectF(0.0f, 0.0f, 19.0f, 19.0f);
         assertFalse(mRectF.contains(rectF));
-
     }
 
     public void testOffset() {
-
        mRectF = new RectF(5, 5, 10, 10);
        mRectF.offset(1.0f, 1.0f);
        assertEquals(6.0f, mRectF.left);
        assertEquals(6.0f, mRectF.top);
        assertEquals(11.0f, mRectF.right);
        assertEquals(11.0f, mRectF.bottom);
-
     }
 
     public void testInset() {
-
         mRectF = new RectF(5.0f, 5.0f, 10.0f, 10.0f);
         mRectF.inset(1.0f, 1.0f);
         assertEquals(6.0f, mRectF.left);
@@ -381,7 +334,6 @@
         assertEquals(4.0f, mRectF.top);
         assertEquals(11.0f, mRectF.right);
         assertEquals(11.0f, mRectF.bottom);
-
     }
 
     public void testHeight() {
@@ -395,18 +347,15 @@
     }
 
     public void testOffsetTo() {
-
         mRectF = new RectF(5, 5, 10, 10);
         mRectF.offsetTo(1.0f, 1.0f);
         assertEquals(1.0f, mRectF.left);
         assertEquals(1.0f, mRectF.top);
         assertEquals(6.0f, mRectF.right);
         assertEquals(6.0f, mRectF.bottom);
-
     }
 
     public void testSetEmpty() {
-
         // Before setEmpty()
         mRectF = new RectF(1, 2, 3, 4);
         assertEquals(1.0f, mRectF.left);
@@ -420,11 +369,9 @@
         assertEquals(0.0f, mRectF.top);
         assertEquals(0.0f, mRectF.right);
         assertEquals(0.0f, mRectF.bottom);
-
     }
 
     public void testIsEmpty() {
-
         mRectF = new RectF();
         assertTrue(mRectF.isEmpty());
         mRectF = new RectF(1.0f, 1.0f, 1.0f, 1.0f);
@@ -433,22 +380,18 @@
         assertTrue(mRectF.isEmpty());
         mRectF = new RectF(1.0f, 1.0f, 20.0f, 20.0f);
         assertFalse(mRectF.isEmpty());
-
     }
 
     public void testCenterX() {
-
         mRectF = new RectF(10.0f, 10.0f, 20.0f, 20.0f);
         assertEquals(15.0f, mRectF.centerX());
         mRectF = new RectF(10.5f, 10.0f, 20.0f, 20.0f);
         assertEquals(15.25f, mRectF.centerX());
         mRectF = new RectF(10.4f, 10.0f, 20.0f, 20.0f);
         assertEquals(15.2f, mRectF.centerX());
-
     }
 
     public void testCenterY() {
-
         mRectF = new RectF(10.0f, 10.0f, 20.0f, 20.0f);
         assertEquals(15.0f, mRectF.centerY());
         mRectF = new RectF(10.0f, 10.5f, 20.0f, 20.0f);
@@ -458,12 +401,16 @@
     }
 
     public void testToString() {
-        mRectF = new RectF();
-        assertNotNull(mRectF.toString());
+        mRectF = new RectF(10.0f, 20.0f, 30.0f, 40.0f);
+        assertEquals("RectF(10.0, 20.0, 30.0, 40.0)", mRectF.toString());
+    }
+
+    public void testToShortString() {
+        mRectF = new RectF(10.0f, 20.0f, 30.0f, 40.0f);
+        assertEquals("[10.0,20.0][30.0,40.0]", mRectF.toShortString());
     }
 
     public void testSetIntersect() {
-
         RectF rectF1 = new RectF(0, 0, 10, 10);
         RectF rectF2 = new RectF(5, 5, 15, 15);
 
@@ -482,11 +429,9 @@
         assertEquals(5.0f, mRectF.top);
         assertEquals(10.0f, mRectF.right);
         assertEquals(10.0f, mRectF.bottom);
-
     }
 
     public void testRoundOut() {
-
         Rect rect = new Rect();
         mRectF = new RectF(1.2f, 1.8f, 5.2f, 5.8f);
         mRectF.roundOut(rect);
@@ -494,11 +439,9 @@
         assertEquals(1, rect.top);
         assertEquals(6, rect.right);
         assertEquals(6, rect.bottom);
-
     }
 
     public void testRound() {
-
         Rect rect = new Rect();
         mRectF = new RectF(1.2f, 1.8f, 5.2f, 5.8f);
         mRectF.round(rect);
@@ -506,7 +449,6 @@
         assertEquals(2, rect.top);
         assertEquals(5, rect.right);
         assertEquals(6, rect.bottom);
-
     }
 
     public void testWriteReadParcel() {
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/Animatable2_AnimationCallbackTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/Animatable2_AnimationCallbackTest.java
new file mode 100644
index 0000000..deb0e87
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/Animatable2_AnimationCallbackTest.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.drawable.cts;
+
+import junit.framework.TestCase;
+
+import android.graphics.drawable.Animatable2.AnimationCallback;
+import android.support.test.filters.SmallTest;
+
+@SmallTest
+public class Animatable2_AnimationCallbackTest extends TestCase {
+
+    public void testCallback() {
+        // These are no-op methods. Just make sure they don't crash.
+        AnimationCallback callback = new AnimationCallback() {};
+        callback.onAnimationStart(null);
+        callback.onAnimationEnd(null);
+    }
+}
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 5dabdfd..4e6c357 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
@@ -169,6 +169,28 @@
     }
 
     @SmallTest
+    public void testEmptyAnimatorSet() throws InterruptedException {
+        int resId = R.drawable.avd_empty_animator;
+        final MyCallback callback = new MyCallback();
+        final AnimatedVectorDrawable d1 =
+                (AnimatedVectorDrawable) mResources.getDrawable(resId);
+        d1.registerAnimationCallback(callback);
+        mActivity.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mActivity.setContentView(mLayoutId);
+                ImageView imageView = (ImageView) mActivity.findViewById(mImageViewId);
+                imageView.setImageDrawable(d1);
+                d1.start();
+            }
+        });
+
+        getInstrumentation().waitForIdleSync();
+        // Check that the AVD with empty AnimatorSet has finished
+        assertTrue(callback.mEnd);
+    }
+
+    @SmallTest
     public void testGetChangingConfigurations() {
         AnimatedVectorDrawable avd = new AnimatedVectorDrawable();
         ConstantState constantState = avd.getConstantState();
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerStateTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerStateTest.java
index 8cbecab..726466c 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerStateTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerStateTest.java
@@ -16,6 +16,7 @@
 
 package android.graphics.drawable.cts;
 
+import junit.framework.TestCase;
 
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
@@ -23,12 +24,12 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.DrawableContainer;
-import android.graphics.drawable.LevelListDrawable;
 import android.graphics.drawable.DrawableContainer.DrawableContainerState;
+import android.graphics.drawable.LevelListDrawable;
+import android.support.test.filters.SmallTest;
 
-import junit.framework.TestCase;
-
-public class DrawableContainerStateTest extends TestCase{
+@SmallTest
+public class DrawableContainerStateTest extends TestCase {
     private DrawableContainerState mDrawableContainerState;
 
     private DrawableContainer mDrawableContainer;
@@ -36,6 +37,7 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+
         // DrawableContainerState has no public constructor. Obtain an instance through
         // LevelListDrawable.getConstants(). This is fine for testing the final methods of
         // DrawableContainerState.
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTest.java
index bc452f3..81d9386 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTest.java
@@ -16,14 +16,30 @@
 
 package android.graphics.drawable.cts;
 
-import android.content.res.Resources.Theme;
-import android.graphics.drawable.Drawable.Callback;
-import android.view.View;
-import android.graphics.cts.R;
-
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
+import android.content.ContentResolver;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.graphics.cts.R;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Drawable.Callback;
+import android.net.Uri;
+import android.support.test.filters.SmallTest;
+import android.test.AndroidTestCase;
+import android.util.AttributeSet;
+import android.util.StateSet;
+import android.util.TypedValue;
+import android.util.Xml;
+import android.view.View;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -32,24 +48,11 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 
-import android.content.ContentResolver;
-import android.content.res.Resources;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.PixelFormat;
-import android.graphics.PorterDuff;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.test.AndroidTestCase;
-import android.util.AttributeSet;
-import android.util.StateSet;
-import android.util.TypedValue;
-import android.util.Xml;
-
+import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
 
+@SmallTest
 public class DrawableTest extends AndroidTestCase {
     Resources mResources;
 
@@ -546,13 +549,22 @@
     }
 
     public void testScheduleSelf() {
-        MockDrawable mockDrawable = new MockDrawable();
-        MockCallback mockCallback = new MockCallback();
-        mockDrawable.setCallback(mockCallback);
+        Drawable mockDrawable = new MockDrawable();
         mockDrawable.scheduleSelf(null, 1000L);
-        assertEquals(mockDrawable, mockCallback.getScheduleDrawable());
-        assertNull(mockCallback.getRunnable());
-        assertEquals(1000L, mockCallback.getWhen());
+
+        Runnable runnable = mock(Runnable.class);
+        mockDrawable.scheduleSelf(runnable, 1000L);
+
+        Callback mockCallback = mock(Callback.class);
+        mockDrawable.setCallback(mockCallback);
+        mockDrawable.scheduleSelf(runnable, 1000L);
+        verify(mockCallback).scheduleDrawable(eq(mockDrawable), eq(runnable), eq(1000L));
+
+        mockDrawable.scheduleSelf(runnable, 0L);
+        verify(mockCallback).scheduleDrawable(eq(mockDrawable), eq(runnable), eq(0L));
+
+        mockDrawable.scheduleSelf(runnable, -1000L);
+        verify(mockCallback).scheduleDrawable(eq(mockDrawable), eq(runnable), eq(-1000L));
     }
 
     public void testAccessCallback() {
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 713f61a..b062073 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/GradientDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/GradientDrawableTest.java
@@ -16,9 +16,13 @@
 
 package android.graphics.drawable.cts;
 
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
+import android.app.Activity;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
@@ -28,11 +32,14 @@
 import android.graphics.ColorFilter;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
+import android.graphics.cts.MockActivity;
 import android.graphics.cts.R;
 import android.graphics.drawable.Drawable.ConstantState;
 import android.graphics.drawable.GradientDrawable;
 import android.graphics.drawable.GradientDrawable.Orientation;
-import android.test.AndroidTestCase;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+
 import android.test.suitebuilder.annotation.MediumTest;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.AttributeSet;
@@ -42,9 +49,21 @@
 import java.util.Arrays;
 
 import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
-public class GradientDrawableTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class GradientDrawableTest {
+
+    @Rule
+    public ActivityTestRule<MockActivity> mActivityRule
+            = new ActivityTestRule<>(MockActivity.class);
+
     @SmallTest
+    @Test
     public void testConstructor() {
         int[] color = new int[] {1, 2, 3};
 
@@ -54,6 +73,7 @@
     }
 
     @SmallTest
+    @Test
     public void testGetOpacity() {
         GradientDrawable gradientDrawable = new GradientDrawable();
         assertEquals("Default opacity is TRANSLUCENT",
@@ -87,6 +107,7 @@
     }
 
     @SmallTest
+    @Test
     public void testSetOrientation() {
         GradientDrawable gradientDrawable = new GradientDrawable();
         Orientation orientation;
@@ -98,6 +119,7 @@
     }
 
     @SmallTest
+    @Test
     public void testSetCornerRadii() {
         float[] radii = new float[] {1.0f, 2.0f, 3.0f};
 
@@ -116,6 +138,7 @@
     }
 
     @SmallTest
+    @Test
     public void testSetCornerRadius() {
         GradientDrawable gradientDrawable = new GradientDrawable();
 
@@ -124,6 +147,22 @@
     }
 
     @SmallTest
+    @Test
+    public void testGetCornerRadius() {
+        GradientDrawable gradientDrawable = new GradientDrawable();
+        gradientDrawable.setCornerRadius(5.5f);
+        assertEquals(gradientDrawable.getCornerRadius(), 5.5f, 0);
+        float[] radii = new float[] {1.0f, 2.0f, 3.0f};
+        gradientDrawable.setCornerRadii(radii);
+        assertEquals(5.5f, gradientDrawable.getCornerRadius(), 0);
+        gradientDrawable.setShape(GradientDrawable.OVAL);
+        assertEquals(5.5f, gradientDrawable.getCornerRadius(), 0);
+        gradientDrawable.setCornerRadii(null);
+        assertEquals(0, gradientDrawable.getCornerRadius(), 0);
+    }
+
+    @SmallTest
+    @Test
     public void testSetStroke() {
         helpTestSetStroke(2, Color.RED);
         helpTestSetStroke(-2, Color.TRANSPARENT);
@@ -137,6 +176,7 @@
     }
 
     @SmallTest
+    @Test
     public void testSetStroke_WidthGap() {
         helpTestSetStroke_WidthGap(2, Color.RED, 3.4f, 5.5f);
         helpTestSetStroke_WidthGap(-2, Color.TRANSPARENT, -3.4f, -5.5f);
@@ -151,6 +191,7 @@
     }
 
     @SmallTest
+    @Test
     public void testSetStrokeList() {
         helpTestSetStrokeList(2, ColorStateList.valueOf(Color.RED));
         helpTestSetStrokeList(-2, ColorStateList.valueOf(Color.TRANSPARENT));
@@ -165,6 +206,7 @@
     }
 
     @SmallTest
+    @Test
     public void testSetStrokeList_WidthGap() {
         helpTestSetStrokeList_WidthGap(2, ColorStateList.valueOf(Color.RED), 3.4f, 5.5f);
         helpTestSetStrokeList_WidthGap(-2, ColorStateList.valueOf(Color.TRANSPARENT), -3.4f, -5.5f);
@@ -179,6 +221,7 @@
     }
 
     @SmallTest
+    @Test
     public void testSetSize() {
         helpTestSetSize(6, 4);
         helpTestSetSize(-30, -40);
@@ -194,6 +237,7 @@
     }
 
     @SmallTest
+    @Test
     public void testSetShape() {
         GradientDrawable gradientDrawable = new GradientDrawable();
         int shape;
@@ -210,6 +254,7 @@
     }
 
     @SmallTest
+    @Test
     public void testSetGradientType() {
         GradientDrawable gradientDrawable = new GradientDrawable();
         int gradientType;
@@ -226,6 +271,7 @@
     }
 
     @SmallTest
+    @Test
     public void testSetGradientCenter() {
         GradientDrawable gradientDrawable = new GradientDrawable();
         float centerX;
@@ -245,11 +291,12 @@
         centerX = 0.0f;
         centerY = 0.0f;
         gradientDrawable.setGradientCenter(centerX, centerY);
-        assertEquals(centerX, gradientDrawable.getGradientCenterX());
-        assertEquals(centerY, gradientDrawable.getGradientCenterY());
+        assertEquals(centerX, gradientDrawable.getGradientCenterX(), 0.01f);
+        assertEquals(centerY, gradientDrawable.getGradientCenterY(), 0.01f);
     }
 
     @SmallTest
+    @Test
     public void testSetGradientRadius() {
         GradientDrawable gradientDrawable = new GradientDrawable();
 
@@ -258,6 +305,7 @@
     }
 
     @SmallTest
+    @Test
     public void testSetUseLevel() {
         GradientDrawable gradientDrawable = new GradientDrawable();
         boolean useLevel;
@@ -276,6 +324,7 @@
     }
 
     @SmallTest
+    @Test
     public void testDraw() {
         GradientDrawable gradientDrawable = new GradientDrawable();
         Canvas c = new Canvas();
@@ -286,6 +335,7 @@
     }
 
     @SmallTest
+    @Test
     public void testSetColor() {
         GradientDrawable gradientDrawable = new GradientDrawable();
         int color;
@@ -302,6 +352,7 @@
     }
 
     @SmallTest
+    @Test
     public void testSetColors() {
         GradientDrawable gradientDrawable = new GradientDrawable();
         int[] colors;
@@ -318,6 +369,7 @@
     }
 
     @SmallTest
+    @Test
     public void testSetColorList() {
         GradientDrawable gradientDrawable = new GradientDrawable();
         ColorStateList color;
@@ -332,6 +384,7 @@
     }
 
     @SmallTest
+    @Test
     public void testGetChangingConfigurations() {
         GradientDrawable gradientDrawable = new GradientDrawable();
         assertEquals(0, gradientDrawable.getChangingConfigurations());
@@ -344,6 +397,7 @@
     }
 
     @SmallTest
+    @Test
     public void testSetAlpha() {
         GradientDrawable gradientDrawable = new GradientDrawable();
 
@@ -352,6 +406,7 @@
     }
 
     @SmallTest
+    @Test
     public void testSetDither() {
         GradientDrawable gradientDrawable = new GradientDrawable();
 
@@ -360,6 +415,7 @@
     }
 
     @SmallTest
+    @Test
     public void testSetColorFilter() {
         GradientDrawable gradientDrawable = new GradientDrawable();
         ColorFilter cf = new ColorFilter();
@@ -370,6 +426,7 @@
     }
 
     @SmallTest
+    @Test
     public void testInflate() throws XmlPullParserException, IOException {
         GradientDrawable gradientDrawable = new GradientDrawable();
         Rect rect = new Rect();
@@ -379,7 +436,7 @@
         assertEquals(0, rect.right);
         assertEquals(0, rect.bottom);
 
-        Resources resources = mContext.getResources();
+        Resources resources = mActivityRule.getActivity().getResources();
         XmlPullParser parser = resources.getXml(R.drawable.gradientdrawable);
         AttributeSet attrs = Xml.asAttributeSet(parser);
 
@@ -415,9 +472,10 @@
     }
 
     @SmallTest
+    @Test
     public void testInflateGradientRadius() throws XmlPullParserException, IOException {
         Rect parentBounds = new Rect(0, 0, 100, 100);
-        Resources resources = mContext.getResources();
+        Resources resources = mActivityRule.getActivity().getResources();
 
         GradientDrawable gradientDrawable;
         float radius;
@@ -436,6 +494,7 @@
     }
 
     @SmallTest
+    @Test
     public void testGetIntrinsicWidth() {
         GradientDrawable gradientDrawable = new GradientDrawable();
         gradientDrawable.setSize(6, 4);
@@ -446,6 +505,7 @@
     }
 
     @SmallTest
+    @Test
     public void testGetIntrinsicHeight() {
         GradientDrawable gradientDrawable = new GradientDrawable();
         gradientDrawable.setSize(5, 3);
@@ -456,14 +516,16 @@
     }
 
     @SmallTest
+    @Test
     public void testGetConstantState() {
         GradientDrawable gradientDrawable = new GradientDrawable();
         assertNotNull(gradientDrawable.getConstantState());
     }
 
     @SmallTest
+    @Test
     public void testMutate() {
-        Resources resources = mContext.getResources();
+        Resources resources = mActivityRule.getActivity().getResources();
         GradientDrawable d1 = (GradientDrawable) resources.getDrawable(R.drawable.gradientdrawable);
         GradientDrawable d2 = (GradientDrawable) resources.getDrawable(R.drawable.gradientdrawable);
         GradientDrawable d3 = (GradientDrawable) resources.getDrawable(R.drawable.gradientdrawable);
@@ -495,8 +557,9 @@
     }
 
     @MediumTest
+    @Test
     public void testPreloadDensity() throws XmlPullParserException, IOException {
-        final Resources res = getContext().getResources();
+        final Resources res = mActivityRule.getActivity().getResources();
         final int densityDpi = res.getConfiguration().densityDpi;
         try {
             testPreloadDensityInner(res, densityDpi);
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/ShapeDrawable_ShaderFactoryTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/ShapeDrawable_ShaderFactoryTest.java
index b736519..0447fb2 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/ShapeDrawable_ShaderFactoryTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/ShapeDrawable_ShaderFactoryTest.java
@@ -17,10 +17,26 @@
 package android.graphics.drawable.cts;
 
 import junit.framework.TestCase;
-import android.graphics.drawable.ShapeDrawable;
 
+import android.graphics.Shader;
+import android.graphics.drawable.ShapeDrawable.ShaderFactory;
+import android.support.test.filters.SmallTest;
+
+@SmallTest
 public class ShapeDrawable_ShaderFactoryTest extends TestCase {
+
     public void testResize() {
-        // resize is an abstract function.
+        // This is an abstract function, but coverage
+        // complains if we don't call it.
+        ShaderFactory impl = new ShaderFactoryImpl();
+        assertNull(impl.resize(0, 0));
+    }
+
+    private class ShaderFactoryImpl extends ShaderFactory {
+
+        @Override
+        public Shader resize(int width, int height) {
+            return null;
+        }
     }
 }
diff --git a/tests/tests/graphics/src/android/graphics/pdf/cts/PdfRendererTest.java b/tests/tests/graphics/src/android/graphics/pdf/cts/PdfRendererTest.java
new file mode 100644
index 0000000..a1c32ab
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/pdf/cts/PdfRendererTest.java
@@ -0,0 +1,394 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.pdf.cts;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.cts.R;
+import android.graphics.pdf.PdfRenderer;
+import android.graphics.pdf.PdfRenderer.Page;
+import android.os.ParcelFileDescriptor;
+import android.support.annotation.NonNull;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Log;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * All test for {@link PdfRenderer} beside the valid transformation parameter tests of {@link
+ * PdfRenderer.Page#render}.
+ */
+@RunWith(AndroidJUnit4.class)
+public class PdfRendererTest {
+    private static final String LOG_TAG = "PdfRendererTest";
+
+    private static final int A5_PORTRAIT_PRINTSCALING_DEFAULT =
+            R.raw.a5_portrait_rgbb_1_6_printscaling_default;
+    private static final int A5_PORTRAIT_PRINTSCALING_NONE =
+            R.raw.a5_portrait_rgbb_1_6_printscaling_none;
+    private static final int TWO_PAGES = R.raw.two_pages;
+
+    private Context mContext;
+
+    /**
+     * Run a runnable and expect and exception of a certain type.
+     *
+     * @param r             The {@link Invokable} to run
+     * @param expectedClass The expected exception type
+     */
+    private void assertException(@NonNull Invokable r,
+            @NonNull Class<? extends Exception> expectedClass) {
+        try {
+            r.run();
+        } catch (Exception e) {
+            if (e.getClass().isAssignableFrom(expectedClass)) {
+                return;
+            } else {
+                Log.e(LOG_TAG, "Incorrect exception", e);
+                throw new AssertionError("Expected: " + expectedClass.getName() + ", got: "
+                        + e.getClass().getName());
+            }
+        }
+
+        throw new AssertionError("No exception thrown");
+    }
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+    }
+
+    @Test
+    public void constructRendererNull() throws Exception {
+        assertException(() -> new PdfRenderer(null), NullPointerException.class);
+    }
+
+    @Test
+    @Ignore("Makes all subsequent tests fail")
+    public void constructRendererFromNonPDF() throws Exception {
+        // Open jpg as if it was a PDF
+        ParcelFileDescriptor fd = mContext.getResources().openRawResourceFd(R.raw.testimage)
+                .getParcelFileDescriptor();
+        assertException(() -> new PdfRenderer(fd), IOException.class);
+    }
+
+    @Test
+    public void useRendererAfterClose() throws Exception {
+        PdfRenderer renderer = Utils.createRenderer(Utils.A4_PORTRAIT, mContext);
+        renderer.close();
+
+        assertException(() -> renderer.close(), IllegalStateException.class);
+        assertException(() -> renderer.getPageCount(), IllegalStateException.class);
+        assertException(() -> renderer.shouldScaleForPrinting(), IllegalStateException.class);
+        assertException(() -> renderer.openPage(0), IllegalStateException.class);
+    }
+
+    @Test
+    public void usePageAfterClose() throws Exception {
+        PdfRenderer renderer = Utils.createRenderer(Utils.A4_PORTRAIT, mContext);
+        Page page = renderer.openPage(0);
+        page.close();
+
+        // Legacy behavior: The properties are cached, hence they are still available after the page
+        //                  is closed
+        page.getHeight();
+        page.getWidth();
+        page.getIndex();
+        assertException(() -> page.close(), IllegalStateException.class);
+
+        // Legacy support. An IllegalStateException would be nice by unfortunately the legacy
+        // implementation returned NullPointerException
+        assertException(() -> page.render(null, null, null, Page.RENDER_MODE_FOR_DISPLAY),
+                NullPointerException.class);
+
+        renderer.close();
+    }
+
+    @Test
+    public void closeWithOpenPage() throws Exception {
+        PdfRenderer renderer = Utils.createRenderer(Utils.A4_PORTRAIT, mContext);
+        Page page = renderer.openPage(0);
+
+        assertException(() -> renderer.close(), IllegalStateException.class);
+
+        page.close();
+        renderer.close();
+    }
+
+    @Test
+    public void openTwoPages() throws Exception {
+        try (PdfRenderer renderer = Utils.createRenderer(TWO_PAGES, mContext)) {
+            // Cannot open two pages at once
+            Page page = renderer.openPage(0);
+            assertException(() -> renderer.openPage(1), IllegalStateException.class);
+
+            page.close();
+        }
+    }
+
+    @Test
+    public void testPageCount() throws Exception {
+        try (PdfRenderer renderer = Utils.createRenderer(TWO_PAGES, mContext)) {
+            assertEquals(2, renderer.getPageCount());
+        }
+    }
+
+    @Test
+    public void testOpenPage() throws Exception {
+        try (PdfRenderer renderer = Utils.createRenderer(TWO_PAGES, mContext)) {
+            assertException(() -> renderer.openPage(-1), IllegalArgumentException.class);
+            Page page0 = renderer.openPage(0);
+            page0.close();
+            Page page1 = renderer.openPage(1);
+            page1.close();
+            assertException(() -> renderer.openPage(2), IllegalArgumentException.class);
+        }
+    }
+
+    @Test
+    public void testPageSize() throws Exception {
+        try (PdfRenderer renderer = Utils.createRenderer(Utils.A4_PORTRAIT, mContext)) {
+            try (Page page = renderer.openPage(0)) {
+                assertEquals(Utils.A4_HEIGHT_PTS, page.getHeight());
+                assertEquals(Utils.A4_WIDTH_PTS, page.getWidth());
+            }
+        }
+    }
+
+    @Test
+    public void testPrintScaleDefault() throws Exception {
+        try (PdfRenderer renderer = Utils.createRenderer(Utils.A5_PORTRAIT, mContext)) {
+            assertTrue(renderer.shouldScaleForPrinting());
+        }
+    }
+
+    @Test
+    public void testPrintScalePDF16Default() throws Exception {
+        try (PdfRenderer renderer = Utils
+                .createRenderer(A5_PORTRAIT_PRINTSCALING_DEFAULT, mContext)) {
+            assertTrue(renderer.shouldScaleForPrinting());
+        }
+    }
+
+    @Test
+    public void testPrintScalePDF16None() throws Exception {
+        try (PdfRenderer renderer = Utils.createRenderer(A5_PORTRAIT_PRINTSCALING_NONE, mContext)) {
+            assertFalse(renderer.shouldScaleForPrinting());
+        }
+    }
+
+    /**
+     * Take 16 color probes in the middle of the 16 segments of the page in the following pattern:
+     * <pre>
+     * +----+----+----+----+
+     * |  0 :  1 :  2 :  3 |
+     * +....:....:....:....+
+     * |  4 :  5 :  6 :  7 |
+     * +....:....:....:....+
+     * |  8 :  9 : 10 : 11 |
+     * +....:....:....:....+
+     * | 12 : 13 : 14 : 15 |
+     * +----+----+----+----+
+     * </pre>
+     *
+     * @param bm The bitmap to probe
+     *
+     * @return The color at the probes
+     */
+    private @NonNull int[] getColorProbes(@NonNull Bitmap bm) {
+        int[] probes = new int[16];
+
+        for (int row = 0; row < 4; row++) {
+            for (int column = 0; column < 4; column++) {
+                probes[row * 4 + column] = bm.getPixel((int) (bm.getWidth() * (column + 0.5) / 4),
+                        (int) (bm.getHeight() * (row + 0.5) / 4));
+            }
+        }
+
+        return probes;
+    }
+
+    /**
+     * Implementation for {@link #renderNoTransformationAndComparePointsForScreen} and {@link
+     * #renderNoTransformationAndComparePointsForPrint}.
+     *
+     * @param renderMode The render mode to use
+     *
+     * @throws Exception If anything was unexpected
+     */
+    private void renderNoTransformationAndComparePoints(int renderMode) throws Exception {
+        Bitmap bm = Utils.renderWithTransform(Utils.A4_WIDTH_PTS, Utils.A4_HEIGHT_PTS,
+                Utils.A4_PORTRAIT, null, null, renderMode, mContext);
+        int[] probes = getColorProbes(bm);
+
+        // Compare rendering to expected result. This ensures that all other tests in this class do
+        // not accidentally all compare empty bitmaps.
+        assertEquals(Color.RED, probes[0]);
+        assertEquals(Color.RED, probes[1]);
+        assertEquals(Color.GREEN, probes[2]);
+        assertEquals(Color.GREEN, probes[3]);
+        assertEquals(Color.RED, probes[4]);
+        assertEquals(Color.RED, probes[5]);
+        assertEquals(Color.GREEN, probes[6]);
+        assertEquals(Color.GREEN, probes[7]);
+        assertEquals(Color.BLUE, probes[8]);
+        assertEquals(Color.BLUE, probes[9]);
+        assertEquals(Color.BLACK, probes[10]);
+        assertEquals(Color.BLACK, probes[11]);
+        assertEquals(Color.BLUE, probes[12]);
+        assertEquals(Color.BLUE, probes[13]);
+        assertEquals(Color.BLACK, probes[14]);
+        assertEquals(Color.BLACK, probes[15]);
+    }
+
+    @Test
+    public void renderNoTransformationAndComparePointsForScreen() throws Exception {
+        renderNoTransformationAndComparePoints(Page.RENDER_MODE_FOR_DISPLAY);
+    }
+
+    @Test
+    public void renderNoTransformationAndComparePointsForPrint() throws Exception {
+        renderNoTransformationAndComparePoints(Page.RENDER_MODE_FOR_PRINT);
+    }
+
+    @Test
+    public void renderPerspective() throws Exception {
+        Matrix transform = new Matrix();
+
+        transform.setValues(new float[] { 1, 1, 1, 1, 1, 1, 1, 1, 1 });
+
+        assertException(() -> Utils
+                        .renderWithTransform(Utils.A4_WIDTH_PTS, Utils.A4_HEIGHT_PTS,
+                                Utils.A4_PORTRAIT, null, transform, Page.RENDER_MODE_FOR_DISPLAY,
+                                mContext), IllegalArgumentException.class);
+    }
+
+    @Test
+    public void render45degreeRotationTranslationAndScaleAndClip() throws Exception {
+        Matrix transform = new Matrix();
+        // Rotate on top left corner
+        transform.postRotate(45);
+        // Move
+        transform.postTranslate(Utils.A4_WIDTH_PTS / 4, Utils.A4_HEIGHT_PTS / 4);
+        // Scale to 75%
+        transform.postScale(0.75f, 0.75f);
+        // Clip
+        Rect clip = new Rect(20, 20, Utils.A4_WIDTH_PTS - 20, Utils.A4_HEIGHT_PTS - 20);
+
+        Utils.renderAndCompare(Utils.A4_WIDTH_PTS, Utils.A4_HEIGHT_PTS, Utils.A4_PORTRAIT, clip,
+                transform, Page.RENDER_MODE_FOR_DISPLAY, mContext);
+    }
+
+    @Test
+    public void renderStreched() throws Exception {
+        Utils.renderAndCompare(Utils.A4_WIDTH_PTS * 4 / 3, Utils.A4_HEIGHT_PTS * 3 / 4,
+                Utils.A4_PORTRAIT, null, null, Page.RENDER_MODE_FOR_DISPLAY, mContext);
+    }
+
+    @Test
+    public void renderWithClip() throws Exception {
+        Rect clip = new Rect(20, 20, Utils.A4_WIDTH_PTS - 50, Utils.A4_HEIGHT_PTS - 50);
+        Utils.renderAndCompare(Utils.A4_WIDTH_PTS, Utils.A4_HEIGHT_PTS,
+                Utils.A4_PORTRAIT, clip, null, Page.RENDER_MODE_FOR_DISPLAY, mContext);
+    }
+
+    @Test
+    public void renderWithAllClipped() throws Exception {
+        Rect clip = new Rect(Utils.A4_WIDTH_PTS / 2, Utils.A4_HEIGHT_PTS / 2,
+                Utils.A4_WIDTH_PTS / 2, Utils.A4_HEIGHT_PTS / 2);
+        Utils.renderAndCompare(Utils.A4_WIDTH_PTS, Utils.A4_HEIGHT_PTS, Utils.A4_PORTRAIT, clip,
+                null, Page.RENDER_MODE_FOR_DISPLAY, mContext);
+    }
+
+    @Test
+    public void renderWithBadLowerCornerOfClip() throws Exception {
+        Rect clip = new Rect(0, 0, Utils.A4_WIDTH_PTS + 20, Utils.A4_HEIGHT_PTS + 20);
+        assertException(() -> Utils
+                        .renderWithTransform(Utils.A4_WIDTH_PTS, Utils.A4_HEIGHT_PTS,
+                                Utils.A4_PORTRAIT, clip, null, Page.RENDER_MODE_FOR_DISPLAY,
+                                mContext),
+                IllegalArgumentException.class);
+    }
+
+    @Test
+    public void renderWithBadUpperCornerOfClip() throws Exception {
+        Rect clip = new Rect(-20, -20, Utils.A4_WIDTH_PTS, Utils.A4_HEIGHT_PTS);
+        assertException(() -> Utils
+                        .renderWithTransform(Utils.A4_WIDTH_PTS, Utils.A4_HEIGHT_PTS,
+                                Utils.A4_PORTRAIT, clip, null, Page.RENDER_MODE_FOR_DISPLAY,
+                                mContext),
+                IllegalArgumentException.class);
+    }
+
+    @Test
+    public void renderTwoModes() throws Exception {
+        assertException(() -> Utils
+                .renderWithTransform(Utils.A4_WIDTH_PTS, Utils.A4_HEIGHT_PTS, Utils.A4_PORTRAIT,
+                        null, null, Page.RENDER_MODE_FOR_DISPLAY | Page.RENDER_MODE_FOR_PRINT,
+                        mContext), IllegalArgumentException.class);
+    }
+
+    @Test
+    public void renderBadMode() throws Exception {
+        assertException(() -> Utils
+                .renderWithTransform(Utils.A4_WIDTH_PTS, Utils.A4_HEIGHT_PTS, Utils.A4_PORTRAIT,
+                        null, null, 1 << 30, mContext), IllegalArgumentException.class);
+    }
+
+    @Test
+    public void renderAllModes() throws Exception {
+        assertException(() -> Utils
+                .renderWithTransform(Utils.A4_WIDTH_PTS, Utils.A4_HEIGHT_PTS, Utils.A4_PORTRAIT,
+                        null, null, -1, mContext), IllegalArgumentException.class);
+    }
+
+    @Test
+    public void renderNoMode() throws Exception {
+        assertException(() -> Utils
+                .renderWithTransform(Utils.A4_WIDTH_PTS, Utils.A4_HEIGHT_PTS, Utils.A4_PORTRAIT,
+                        null, null, 0, mContext), IllegalArgumentException.class);
+    }
+
+    @Test
+    public void renderOnNullBitmap() throws Exception {
+        try (PdfRenderer renderer = Utils.createRenderer(Utils.A4_PORTRAIT, mContext)) {
+            try (Page page = renderer.openPage(0)) {
+                assertException(() -> page.render(null, null, null, Page.RENDER_MODE_FOR_DISPLAY),
+                        NullPointerException.class);
+            }
+        }
+    }
+
+    /**
+     * A runnable that can throw an exception.
+     */
+    private interface Invokable {
+        void run() throws Exception;
+    }
+}
diff --git a/tests/tests/graphics/src/android/graphics/pdf/cts/PdfRendererTransformTest.java b/tests/tests/graphics/src/android/graphics/pdf/cts/PdfRendererTransformTest.java
new file mode 100644
index 0000000..facbd4e
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/pdf/cts/PdfRendererTransformTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.pdf.cts;
+
+import android.content.Context;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.pdf.PdfRenderer;
+import android.graphics.pdf.PdfRenderer.Page;
+import android.support.annotation.Nullable;
+import android.support.annotation.RawRes;
+import android.support.test.InstrumentationRegistry;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * Test for the {@link PdfRenderer}
+ */
+@RunWith(Parameterized.class)
+public class PdfRendererTransformTest {
+    private Context mContext;
+    private int mWidth;
+    private int mHeight;
+    private int mDocRes;
+    private @Nullable Rect mClipping;
+    private @Nullable Matrix mTransformation;
+    private int mRenderMode;
+
+    public PdfRendererTransformTest(int width, int height, @RawRes int docRes,
+            @Nullable Rect clipping, @Nullable Matrix transformation, int renderMode) {
+        mWidth = width;
+        mHeight = height;
+        mDocRes = docRes;
+        mClipping = clipping;
+        mTransformation = transformation;
+        mRenderMode = renderMode;
+    }
+
+    @Parameterized.Parameters
+    public static Collection<Object[]> getParameters() {
+        int[] widths = new int[] { Utils.A4_WIDTH_PTS * 3 / 4, Utils.A4_WIDTH_PTS,
+                Utils.A4_WIDTH_PTS * 4 / 3
+        };
+        int[] heights = new int[] { Utils.A4_HEIGHT_PTS * 3 / 4, Utils.A4_HEIGHT_PTS,
+                Utils.A4_HEIGHT_PTS * 4 / 3
+        };
+        int[] rotations = new int[] { 0, 15, 90, 180 };
+        int[] translations = new int[] { -Utils.A4_HEIGHT_PTS / 2, 0, Utils.A4_HEIGHT_PTS / 2 };
+        float[] scales = { -0.5f, 0, 1, 1.5f };
+
+        Collection<Object[]> params = new ArrayList<>();
+
+        for (int rotation : rotations) {
+            for (float scaleX : scales) {
+                for (float scaleY : scales) {
+                    for (int translateX : translations) {
+                        for (int translateY : translations) {
+                            Matrix transformation = new Matrix();
+                            if (rotation != 0 || translateX != 0 || translateY != 0
+                                    || scaleX != 0 || scaleY != 0) {
+                                if (rotation != 0) {
+                                    transformation.postRotate(rotation);
+                                }
+
+                                if (scaleX != 0 || scaleY != 0) {
+                                    transformation.postScale(scaleX, scaleY);
+                                }
+
+                                if (translateX != 0 || translateY != 0) {
+                                    transformation.postTranslate(translateX,
+                                            translateY);
+                                }
+                            }
+
+                            for (int width : widths) {
+                                for (int height : heights) {
+                                    params.add(
+                                            new Object[] { width, height, Utils.A4_PORTRAIT, null,
+                                                    transformation, Page.RENDER_MODE_FOR_DISPLAY
+                                            });
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return params;
+    }
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+    }
+
+    @Test
+    public void test() throws Exception {
+        Utils.renderAndCompare(mWidth, mHeight, mDocRes, mClipping, mTransformation, mRenderMode,
+                mContext);
+    }
+}
diff --git a/tests/tests/graphics/src/android/graphics/pdf/cts/Utils.java b/tests/tests/graphics/src/android/graphics/pdf/cts/Utils.java
new file mode 100644
index 0000000..402a99f
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/pdf/cts/Utils.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.pdf.cts;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.pdf.PdfRenderer;
+import android.os.ParcelFileDescriptor;
+import android.support.annotation.FloatRange;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.RawRes;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Map;
+
+import static org.junit.Assert.fail;
+
+/**
+ * Utilities for this package
+ */
+class Utils {
+    private static final String LOG_TAG = "Utils";
+
+    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;
+
+    private static Map<Integer, File> sFiles = new ArrayMap<>();
+    private static Map<Integer, Bitmap> sRenderedBitmaps = new ArrayMap<>();
+
+    /**
+     * Create a {@link PdfRenderer} pointing to a file copied from a resource.
+     *
+     * @param docRes  The resource to load
+     * @param context The context to use for creating the renderer
+     *
+     * @return the renderer
+     *
+     * @throws IOException If anything went wrong
+     */
+    static @NonNull PdfRenderer createRenderer(@RawRes int docRes, @NonNull Context context)
+            throws IOException {
+        File pdfFile = sFiles.get(docRes);
+
+        if (pdfFile == null) {
+            pdfFile = File.createTempFile("pdf", null, context.getCacheDir());
+
+            // Copy resource to file so that we can open it as a ParcelFileDescriptor
+            try (OutputStream os = new BufferedOutputStream(new FileOutputStream(pdfFile))) {
+                try (InputStream is = new BufferedInputStream(
+                        context.getResources().openRawResource(docRes))) {
+                    byte buffer[] = new byte[1024];
+
+                    while (true) {
+                        int numRead = is.read(buffer, 0, buffer.length);
+
+                        if (numRead == -1) {
+                            break;
+                        }
+
+                        os.write(Arrays.copyOf(buffer, numRead));
+                    }
+
+                    os.flush();
+                }
+            }
+
+            sFiles.put(docRes, pdfFile);
+        }
+
+        return new PdfRenderer(
+                ParcelFileDescriptor.open(pdfFile, ParcelFileDescriptor.MODE_READ_ONLY));
+    }
+
+    /**
+     * Render a pdf onto a bitmap <u>while</u> applying the transformation <u>in the</u>
+     * PDFRenderer. Hence use PdfRenderer.*'s translation and clipping methods.
+     *
+     * @param bmWidth        The width of the destination bitmap
+     * @param bmHeight       The height of the destination bitmap
+     * @param docRes         The resolution of the doc
+     * @param clipping       The clipping for the PDF document
+     * @param transformation The transformation of the PDF
+     * @param renderMode     The render mode to use to render the PDF
+     * @param context        The context to use for creating the renderer
+     *
+     * @return The rendered bitmap
+     */
+    static @NonNull Bitmap renderWithTransform(int bmWidth, int bmHeight, @RawRes int docRes,
+            @Nullable Rect clipping, @Nullable Matrix transformation, int renderMode,
+            @NonNull Context context)
+            throws IOException {
+        try (PdfRenderer renderer = createRenderer(docRes, context)) {
+            try (PdfRenderer.Page page = renderer.openPage(0)) {
+                Bitmap bm = Bitmap.createBitmap(bmWidth, bmHeight, Bitmap.Config.ARGB_8888);
+
+                page.render(bm, clipping, transformation, renderMode);
+
+                return bm;
+            }
+        }
+    }
+
+    /**
+     * Render a pdf onto a bitmap <u>and then</u> apply then render the resulting bitmap onto
+     * another bitmap while applying the transformation. Hence use canvas' translation and clipping
+     * methods.
+     *
+     * @param bmWidth        The width of the destination bitmap
+     * @param bmHeight       The height of the destination bitmap
+     * @param docRes         The resolution of the doc
+     * @param clipping       The clipping for the PDF document
+     * @param transformation The transformation of the PDF
+     * @param renderMode     The render mode to use to render the PDF
+     * @param context        The context to use for creating the renderer
+     *
+     * @return The rendered bitmap
+     */
+    private static @NonNull Bitmap renderAndThenTransform(int bmWidth, int bmHeight,
+            @RawRes int docRes, @Nullable Rect clipping, @Nullable Matrix transformation,
+            int renderMode, @NonNull Context context) throws IOException {
+        Bitmap renderedBm;
+
+        renderedBm = sRenderedBitmaps.get(docRes);
+
+        if (renderedBm == null) {
+            try (PdfRenderer renderer = Utils.createRenderer(docRes, context)) {
+                try (PdfRenderer.Page page = renderer.openPage(0)) {
+                    renderedBm = Bitmap.createBitmap(page.getWidth(), page.getHeight(),
+                            Bitmap.Config.ARGB_8888);
+                    page.render(renderedBm, null, null, renderMode);
+                }
+            }
+            sRenderedBitmaps.put(docRes, renderedBm);
+        }
+
+        if (transformation == null) {
+            // According to PdfRenderer.page#render transformation == null means that the bitmap
+            // should be stretched to clipping (if provided) or otherwise destination size
+            transformation = new Matrix();
+
+            if (clipping != null) {
+                transformation.postScale((float) clipping.width() / renderedBm.getWidth(),
+                        (float) clipping.height() / renderedBm.getHeight());
+                transformation.postTranslate(clipping.left, clipping.top);
+            } else {
+                transformation.postScale((float) bmWidth / renderedBm.getWidth(),
+                        (float) bmHeight / renderedBm.getHeight());
+            }
+        }
+
+        Bitmap transformedBm = Bitmap.createBitmap(bmWidth, bmHeight, Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(transformedBm);
+        canvas.drawBitmap(renderedBm, transformation, null);
+
+        Bitmap clippedBm;
+        if (clipping != null) {
+            clippedBm = Bitmap.createBitmap(bmWidth, bmHeight, Bitmap.Config.ARGB_8888);
+            canvas = new Canvas(clippedBm);
+            canvas.drawBitmap(transformedBm, clipping, clipping, null);
+            transformedBm.recycle();
+        } else {
+            clippedBm = transformedBm;
+        }
+
+        return clippedBm;
+    }
+
+    /**
+     * Get the fraction of non-matching pixels of two bitmaps. 1 == no pixels match, 0 == all pixels
+     * match.
+     *
+     * @param a The first bitmap
+     * @param b The second bitmap
+     *
+     * @return The fraction of non-matching pixels.
+     */
+    private static @FloatRange(from = 0, to = 1) float getNonMatching(@NonNull Bitmap a,
+            @NonNull Bitmap b) {
+        if (a.getWidth() != b.getWidth() || a.getHeight() != b.getHeight()) {
+            return 1;
+        }
+
+        int[] aPx = new int[a.getWidth() * a.getHeight()];
+        int[] bPx = new int[b.getWidth() * b.getHeight()];
+        a.getPixels(aPx, 0, a.getWidth(), 0, 0, a.getWidth(), a.getHeight());
+        b.getPixels(bPx, 0, b.getWidth(), 0, 0, b.getWidth(), b.getHeight());
+
+        int badPixels = 0;
+        for (int i = 0; i < a.getWidth() * a.getHeight(); i++) {
+            if (aPx[i] != bPx[i]) {
+                badPixels++;
+            }
+        }
+
+        return ((float) badPixels) / (a.getWidth() * a.getHeight());
+    }
+
+    /**
+     * Render the PDF two times. Once with applying the transformation and clipping in the {@link
+     * PdfRenderer}. The other time render the PDF onto a bitmap and then clip and transform that
+     * image. The result should be the same beside some minor aliasing.
+     *
+     * @param width          The width of the resulting bitmap
+     * @param height         The height of the resulting bitmap
+     * @param docRes         The resource of the PDF document
+     * @param clipping       The clipping to apply
+     * @param transformation The transformation to apply
+     * @param renderMode     The render mode to use
+     * @param context        The context to use for creating the renderer
+     *
+     * @throws IOException
+     */
+    static void renderAndCompare(int width, int height, @RawRes int docRes,
+            @Nullable Rect clipping, @Nullable Matrix transformation, int renderMode,
+            @NonNull Context context) throws IOException {
+        Bitmap a = renderWithTransform(width, height, docRes, clipping, transformation,
+                renderMode, context);
+        Bitmap b = renderAndThenTransform(width, height, docRes, clipping, transformation,
+                renderMode, context);
+
+        try {
+            // We allow 1% aliasing error
+            float nonMatching = getNonMatching(a, b);
+
+            if (nonMatching == 0) {
+                Log.d(LOG_TAG, "bitmaps match");
+            } else if (nonMatching > 0.01) {
+                fail("Testing width:" + width + ", height:" + height + ", docRes:" + docRes +
+                        ", clipping:" + clipping + ", transform:" + transformation + ". Bitmaps " +
+                        "differ by " + Math.ceil(nonMatching * 10000) / 100 +
+                        "%. That is too much.");
+            } else {
+                Log.d(LOG_TAG, "bitmaps differ by " + Math.ceil(nonMatching * 10000) / 100 + "%");
+            }
+        } finally {
+            a.recycle();
+            b.recycle();
+        }
+    }
+}
diff --git a/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionTest.java b/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionTest.java
index 77c6da1..5a76816 100644
--- a/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionTest.java
+++ b/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionTest.java
@@ -25,6 +25,7 @@
 import android.test.ActivityInstrumentationTestCase2;
 import android.util.Log;
 
+import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import javax.microedition.khronos.egl.EGL10;
@@ -61,20 +62,16 @@
         int detectedMajorVersion = getDetectedMajorVersion();
         int reportedVersion = getVersionFromActivityManager(mActivity);
 
-        assertEquals("Detected OpenGL ES major version " + detectedMajorVersion
-                + " but Activity Manager is reporting " +  getMajorVersion(reportedVersion)
-                + " (Check ro.opengles.version)",
-                detectedMajorVersion, getMajorVersion(reportedVersion));
         assertEquals("Reported OpenGL ES version from ActivityManager differs from PackageManager",
                 reportedVersion, getVersionFromPackageManager(mActivity));
 
-        assertGlVersionString(1);
+        assertGlVersionString(1, 1);
         if (detectedMajorVersion == 2) {
             restartActivityWithClientVersion(2);
-            assertGlVersionString(2);
+            assertGlVersionString(2, getMinorVersion(reportedVersion));
         } else if (detectedMajorVersion == 3) {
             restartActivityWithClientVersion(3);
-            assertGlVersionString(3);
+            assertGlVersionString(3, getMinorVersion(reportedVersion));
         }
     }
 
@@ -123,14 +120,11 @@
         restartActivityWithClientVersion(3);
 
         String extensions = mActivity.getExtensionsString();
-        if (!hasExtension(extensions, "ANDROID_extension_pack_es31a")) {
-            assertFalse("FEATURE_OPENGLES_EXTENSION_PACK is available but ANDROID_extension_pack_es31a isn't in the extension list",
-                    hasAepFeature);
-            return;
-        }
-
-        assertTrue("ANDROID_extension_pack_es31a is present, but support is incomplete",
-                mActivity.getAepEs31Support());
+        boolean hasAepExtension = hasExtension(extensions, "GL_ANDROID_extension_pack_es31a");
+        assertEquals("System feature FEATURE_OPENGLES_EXTENSION_PACK is "
+            + (hasAepFeature ? "" : "not ") + "available, but extension GL_ANDROID_extension_pack_es31a is "
+            + (hasAepExtension ? "" : "not ") + "in the OpenGL ES extension list.",
+            hasAepFeature, hasAepExtension);
     }
 
     public void testOpenGlEsVersionForVrHighPerformance() throws InterruptedException {
@@ -288,15 +282,21 @@
     }
 
     /**
-     * Check that the version string has some form of "Open GL ES X.Y" in it where X is the major
-     * version and Y must be some digit.
+     * Check that the version string has the form "OpenGL ES(-CM)? (\d+)\.(\d+)", where the two
+     * numbers match the major and minor parameters.
      */
-    private void assertGlVersionString(int majorVersion) throws InterruptedException {
-        String versionString = "" + majorVersion;
-        String message = "OpenGL version string '" + mActivity.getVersionString()
-                + "' is not " + majorVersion + ".0+.";
-        assertTrue(message, Pattern.matches(".*OpenGL.*ES.*" + versionString + "\\.\\d.*",
-                mActivity.getVersionString()));
+    private void assertGlVersionString(int major, int minor) throws InterruptedException {
+        Matcher matcher = Pattern.compile("OpenGL ES(?:-CM)? (\\d+)\\.(\\d+).*")
+                                 .matcher(mActivity.getVersionString());
+        assertTrue("OpenGL ES version string is not of the required form "
+            + "'OpenGL ES(-CM)? (\\d+)\\.(\\d+).*'",
+            matcher.matches());
+        int stringMajor = Integer.parseInt(matcher.group(1));
+        int stringMinor = Integer.parseInt(matcher.group(2));
+        assertEquals("GL_VERSION string doesn't match ActivityManager major version (check ro.opengles.version property)",
+            major, stringMajor);
+        assertEquals("GL_VERSION string doesn't match ActivityManager minor version (check ro.opengles.version property)",
+            minor, stringMinor);
     }
 
     /** Restart {@link GLSurfaceViewCtsActivity} with a specific client version. */
diff --git a/tests/tests/icu/Android.mk b/tests/tests/icu/Android.mk
index 6f183d5..39d1285 100644
--- a/tests/tests/icu/Android.mk
+++ b/tests/tests/icu/Android.mk
@@ -30,9 +30,12 @@
 
 # The aim of this package is to run tests against the implementation in use by
 # the current android system.
+LOCAL_JAVA_LIBRARIES := cts-core-test-runner
+
 LOCAL_STATIC_JAVA_LIBRARIES := \
-	cts-core-test-runner \
-	android-icu4j-tests
+	android-icu4j-tests \
+	ctstestrunner \
+	android-support-test
 
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
diff --git a/tests/tests/jni/Android.mk b/tests/tests/jni/Android.mk
index 7a9504d..4a81a85 100644
--- a/tests/tests/jni/Android.mk
+++ b/tests/tests/jni/Android.mk
@@ -30,7 +30,7 @@
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
 
 LOCAL_JNI_SHARED_LIBRARIES := libjnitest libnativehelper_compat_libc++
 
diff --git a/tests/tests/jni/libjnitest/helper.c b/tests/tests/jni/libjnitest/helper.c
index 8f7f2f8..2281795 100644
--- a/tests/tests/jni/libjnitest/helper.c
+++ b/tests/tests/jni/libjnitest/helper.c
@@ -70,6 +70,7 @@
             free(result);
             if (newResult == NULL) {
                 // Shouldn't happen, but deal as gracefully as possible.
+                va_end(args);
                 return NULL;
             }
             result = newResult;
diff --git a/tests/tests/jni/libjnitest/macroized_tests.c b/tests/tests/jni/libjnitest/macroized_tests.c
index 76b5481..130b378 100644
--- a/tests/tests/jni/libjnitest/macroized_tests.c
+++ b/tests/tests/jni/libjnitest/macroized_tests.c
@@ -192,6 +192,7 @@
             "returnBoolean", "()Z");
 
     if (method == NULL) {
+        va_end(args);
         return msg;
     }
 
@@ -240,6 +241,7 @@
             break;
         }
         default: {
+            va_end(args);
             return failure("shouldn't happen");
         }
     }
@@ -295,6 +297,7 @@
             "returnByte", "()B");
 
     if (method == NULL) {
+        va_end(args);
         return msg;
     }
 
@@ -343,6 +346,7 @@
             break;
         }
         default: {
+            va_end(args);
             return failure("shouldn't happen");
         }
     }
@@ -398,6 +402,7 @@
             "returnShort", "()S");
 
     if (method == NULL) {
+        va_end(args);
         return msg;
     }
 
@@ -446,6 +451,7 @@
             break;
         }
         default: {
+            va_end(args);
             return failure("shouldn't happen");
         }
     }
@@ -501,6 +507,7 @@
             "returnChar", "()C");
 
     if (method == NULL) {
+        va_end(args);
         return msg;
     }
 
@@ -549,6 +556,7 @@
             break;
         }
         default: {
+            va_end(args);
             return failure("shouldn't happen");
         }
     }
@@ -604,6 +612,7 @@
             "returnInt", "()I");
 
     if (method == NULL) {
+        va_end(args);
         return msg;
     }
 
@@ -652,6 +661,7 @@
             break;
         }
         default: {
+            va_end(args);
             return failure("shouldn't happen");
         }
     }
@@ -707,6 +717,7 @@
             "returnLong", "()J");
 
     if (method == NULL) {
+        va_end(args);
         return msg;
     }
 
@@ -755,6 +766,7 @@
             break;
         }
         default: {
+            va_end(args);
             return failure("shouldn't happen");
         }
     }
@@ -810,6 +822,7 @@
             "returnFloat", "()F");
 
     if (method == NULL) {
+        va_end(args);
         return msg;
     }
 
@@ -858,6 +871,7 @@
             break;
         }
         default: {
+            va_end(args);
             return failure("shouldn't happen");
         }
     }
@@ -913,6 +927,7 @@
             "returnDouble", "()D");
 
     if (method == NULL) {
+        va_end(args);
         return msg;
     }
 
@@ -961,6 +976,7 @@
             break;
         }
         default: {
+            va_end(args);
             return failure("shouldn't happen");
         }
     }
@@ -1016,6 +1032,7 @@
             "nop", "()V");
 
     if (method == NULL) {
+        va_end(args);
         return msg;
     }
 
@@ -1064,6 +1081,7 @@
             break;
         }
         default: {
+            va_end(args);
             return failure("shouldn't happen");
         }
     }
@@ -1119,6 +1137,7 @@
             "returnString", "()Ljava/lang/String;");
 
     if (method == NULL) {
+        va_end(args);
         return msg;
     }
 
@@ -1171,6 +1190,7 @@
             break;
         }
         default: {
+            va_end(args);
             return failure("shouldn't happen");
         }
     }
@@ -1240,6 +1260,7 @@
             "takeOneOfEach", "(DFJICSBZLjava/lang/String;)Z");
 
     if (method == NULL) {
+        va_end(args);
         return msg;
     }
 
@@ -1299,6 +1320,7 @@
             break;
         }
         default: {
+            va_end(args);
             return failure("shouldn't happen");
         }
     }
@@ -1361,6 +1383,7 @@
             "(IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII)Z");
 
     if (method == NULL) {
+        va_end(args);
         return msg;
     }
 
@@ -1441,6 +1464,7 @@
             break;
         }
         default: {
+            va_end(args);
             return failure("shouldn't happen");
         }
     }
diff --git a/tests/tests/keystore/Android.mk b/tests/tests/keystore/Android.mk
index 4688846..8fe7a3b 100644
--- a/tests/tests/keystore/Android.mk
+++ b/tests/tests/keystore/Android.mk
@@ -26,6 +26,7 @@
 LOCAL_JAVA_LIBRARIES := bouncycastle
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
+        android-support-test \
         core-tests-support \
         ctsdeviceutil \
         ctstestrunner \
diff --git a/tests/tests/media/Android.mk b/tests/tests/media/Android.mk
index eda78e8..d61556d 100644
--- a/tests/tests/media/Android.mk
+++ b/tests/tests/media/Android.mk
@@ -44,7 +44,7 @@
 # include both the 32 and 64 bit versions
 LOCAL_MULTILIB := both
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctsmediautil ctsdeviceutil compatibility-device-util ctstestserver ctstestrunner ndkaudio
+LOCAL_STATIC_JAVA_LIBRARIES := ctsmediautil ctsdeviceutil compatibility-device-util ctstestserver ctstestrunner ndkaudio android-support-test
 
 LOCAL_JNI_SHARED_LIBRARIES := libctsmediacodec_jni libaudio_jni libnativehelper_compat_libc++ libndkaudioLib
 
diff --git a/tests/tests/media/src/android/media/cts/IvfWriter.java b/tests/tests/media/src/android/media/cts/IvfWriter.java
index 075f73c..36fb679 100644
--- a/tests/tests/media/src/android/media/cts/IvfWriter.java
+++ b/tests/tests/media/src/android/media/cts/IvfWriter.java
@@ -16,6 +16,8 @@
 
 package android.media.cts;
 
+import android.media.MediaFormat;
+
 import java.io.IOException;
 import java.io.RandomAccessFile;
 
@@ -34,6 +36,7 @@
     private int mScale;
     private int mRate;
     private int mFrameCount;
+    private String mMimeType;
 
     /**
      * Initializes the IVF file writer.
@@ -43,15 +46,17 @@
      * with this timebase value.
      *
      * @param filename   name of the IVF file
+     * @param mimeType   mime type of the codec
      * @param width      frame width
      * @param height     frame height
      * @param scale      timebase scale (or numerator of the timebase fraction)
      * @param rate       timebase rate (or denominator of the timebase fraction)
      */
-    public IvfWriter(String filename,
-                     int width, int height,
-                     int scale, int rate) throws IOException {
+    public IvfWriter(
+            String filename, String mimeType, int width, int height, int scale,
+            int rate) throws IOException {
         mOutputFile = new RandomAccessFile(filename, "rw");
+        mMimeType = mimeType;
         mWidth = width;
         mHeight = height;
         mScale = scale;
@@ -67,11 +72,12 @@
      * Microsecond timebase is default for OMX thus stagefright.
      *
      * @param filename   name of the IVF file
+     * @param mimeType   mime type of the codec
      * @param width      frame width
      * @param height     frame height
      */
-    public IvfWriter(String filename, int width, int height) throws IOException {
-        this(filename, width, height, 1, 1000000);
+    public IvfWriter(String filename, String mimeType, int width, int height) throws IOException {
+        this(filename, mimeType, width, height, 1, 1000000);
     }
 
     /**
@@ -80,7 +86,7 @@
     public void close() throws IOException{
         // Write header now
         mOutputFile.seek(0);
-        mOutputFile.write(makeIvfHeader(mFrameCount, mWidth, mHeight, mScale, mRate));
+        mOutputFile.write(makeIvfHeader(mFrameCount, mWidth, mHeight, mScale, mRate, mMimeType));
         mOutputFile.close();
     }
 
@@ -107,7 +113,8 @@
      * @param scale      timebase scale (or numerator of the timebase fraction)
      * @param rate       timebase rate (or denominator of the timebase fraction)
      */
-    private static byte[] makeIvfHeader(int frameCount, int width, int height, int scale, int rate){
+    private static byte[] makeIvfHeader(
+            int frameCount, int width, int height, int scale, int rate, String mimeType) {
         byte[] ivfHeader = new byte[32];
         ivfHeader[0] = 'D';
         ivfHeader[1] = 'K';
@@ -117,7 +124,7 @@
         lay16Bits(ivfHeader, 6, 32);  // header size
         ivfHeader[8] = 'V';  // fourcc
         ivfHeader[9] = 'P';
-        ivfHeader[10] = '8';
+        ivfHeader[10] = (byte) (MediaFormat.MIMETYPE_VIDEO_VP8.equals(mimeType) ? '8' : '9');
         ivfHeader[11] = '0';
         lay16Bits(ivfHeader, 12, width);
         lay16Bits(ivfHeader, 14, height);
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java b/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
index 5b2936b..b579c6d 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
@@ -52,12 +52,8 @@
     private static final int TIMEOUT_US = 1000000;  // 1 sec
     private static final int IFRAME_INTERVAL = 10;          // 10 seconds between I-frames
 
-    private final MediaCodecList mRegularCodecs =
-            new MediaCodecList(MediaCodecList.REGULAR_CODECS);
     private final MediaCodecList mAllCodecs =
             new MediaCodecList(MediaCodecList.ALL_CODECS);
-    private final MediaCodecInfo[] mRegularInfos =
-            mRegularCodecs.getCodecInfos();
     private final MediaCodecInfo[] mAllInfos =
             mAllCodecs.getCodecInfos();
 
@@ -391,7 +387,7 @@
         // check if there is an adaptive decoder for each
         for (String mime : supportedFormats) {
             skipped = false;
-            // implicit assumption that QVGA video is always valid.
+            // implicit assumption that QCIF video is always valid.
             MediaFormat format = MediaFormat.createVideoFormat(mime, 176, 144);
             format.setFeatureEnabled(CodecCapabilities.FEATURE_AdaptivePlayback, true);
             String codec = mAllCodecs.findDecoderForFormat(format);
@@ -501,7 +497,7 @@
                 MediaFormat format = null;
                 try {
                     codec = MediaCodec.createByCodecName(info.getName());
-                    // implicit assumption that QVGA video is always valid.
+                    // implicit assumption that QCIF video is always valid.
                     format = createReasonableVideoFormat(caps, mime, isEncoder, 176, 144);
                     format.setInteger(
                             MediaFormat.KEY_COLOR_FORMAT,
diff --git a/tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java b/tests/tests/media/src/android/media/cts/VpxCodecTestBase.java
similarity index 96%
rename from tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java
rename to tests/tests/media/src/android/media/cts/VpxCodecTestBase.java
index 0395ec7..ea72225 100644
--- a/tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java
+++ b/tests/tests/media/src/android/media/cts/VpxCodecTestBase.java
@@ -43,17 +43,18 @@
 import java.util.concurrent.CountDownLatch;
 
 /**
- * Verification test for vp8 encoder and decoder.
+ * Verification test for vpx encoder and decoder.
  *
  * A raw yv12 stream is encoded at various settings and written to an IVF
  * file. Encoded stream bitrate and key frame interval are checked against target values.
- * The stream is later decoded by vp8 decoder to verify frames are decodable and to
+ * The stream is later decoded by the decoder to verify frames are decodable and to
  * calculate PSNR values for various bitrates.
  */
-public class Vp8CodecTestBase extends AndroidTestCase {
+public class VpxCodecTestBase extends AndroidTestCase {
 
-    protected static final String TAG = "VP8CodecTestBase";
+    protected static final String TAG = "VPxCodecTestBase";
     protected static final String VP8_MIME = MediaFormat.MIMETYPE_VIDEO_VP8;
+    protected static final String VP9_MIME = MediaFormat.MIMETYPE_VIDEO_VP9;
     private static final String GOOGLE_CODEC_PREFIX = "omx.google.";
     protected static final String SDCARD_DIR =
             Environment.getExternalStorageDirectory().getAbsolutePath();
@@ -91,7 +92,7 @@
     }
 
     /**
-     *  VP8 codec properties generated by getVp8CodecProperties() function.
+     *  VPx codec properties generated by getVpxCodecProperties() function.
      */
     private class CodecProperties {
         CodecProperties(String codecName, int colorFormat) {
@@ -102,12 +103,12 @@
             return codecName.toLowerCase().startsWith(GOOGLE_CODEC_PREFIX);
         }
 
-        public final String codecName; // OpenMax component name for VP8 codec.
+        public final String codecName; // OpenMax component name for VPx codec.
         public final int colorFormat;  // Color format supported by codec.
     }
 
     /**
-     * Function to find VP8 codec.
+     * Function to find VPx codec.
      *
      * Iterates through the list of available codecs and tries to find
      * VPX codec, which can support either YUV420 planar or NV12 color formats.
@@ -197,7 +198,9 @@
         int inputResourceId;
         // Name of the IVF file to write encoded bitsream
         public String outputIvfFilename;
-        // Force to use Google VP8 encoder.
+        // Mime Type of the Encoded content.
+        public String codecMimeType;
+        // Force to use Google VPx encoder.
         boolean forceGoogleEncoder;
         // Number of frames to encode.
         int frameCount;
@@ -236,6 +239,7 @@
     protected ArrayList<EncoderOutputStreamParameters> getDefaultEncodingParameterList(
             String inputYuvName,
             String outputIvfBaseName,
+            String codecMimeType,
             int encodeSeconds,
             int[] resolutionScales,
             int frameWidth,
@@ -258,8 +262,10 @@
             params.scaledYuvFilename = SDCARD_DIR + File.separator +
                     outputIvfBaseName + resolutionScales[i]+ ".yuv";
             params.inputResourceId = R.raw.football_qvga;
+            params.codecMimeType = codecMimeType;
+            String codecSuffix = VP8_MIME.equals(codecMimeType) ? "vp8" : "vp9";
             params.outputIvfFilename = SDCARD_DIR + File.separator +
-                    outputIvfBaseName + resolutionScales[i] + ".ivf";
+                    outputIvfBaseName + resolutionScales[i] + "_" + codecSuffix + ".ivf";
             params.forceGoogleEncoder = false;
             params.frameCount = encodeSeconds * frameRate;
             params.frameRate = frameRate;
@@ -286,6 +292,7 @@
     protected EncoderOutputStreamParameters getDefaultEncodingParameters(
             String inputYuvName,
             String outputIvfBaseName,
+            String codecMimeType,
             int encodeSeconds,
             int frameWidth,
             int frameHeight,
@@ -298,6 +305,7 @@
         return getDefaultEncodingParameterList(
                 inputYuvName,
                 outputIvfBaseName,
+                codecMimeType,
                 encodeSeconds,
                 scaleValues,
                 frameWidth,
@@ -500,17 +508,18 @@
      * md5 sum comparison wouldn't work.)
      *
      * Indeed, MediaCodec will raise an IllegalStateException
-     * whenever vp8 decoder fails to decode a frame, and
+     * whenever vpx decoder fails to decode a frame, and
      * this test uses that fact to verify the bitstream.
      *
      * @param inputIvfFilename  The name of the IVF file containing encoded bitsream.
      * @param outputYuvFilename The name of the output YUV file (optional).
      * @param frameRate         Frame rate of input file in frames per second
-     * @param forceGoogleDecoder    Force to use Google VP8 decoder.
+     * @param forceGoogleDecoder    Force to use Google VPx decoder.
      */
     protected ArrayList<MediaCodec.BufferInfo> decode(
             String inputIvfFilename,
             String outputYuvFilename,
+            String codecMimeType,
             int frameRate,
             boolean forceGoogleDecoder) throws Exception {
         ArrayList<MediaCodec.BufferInfo> bufferInfos = new ArrayList<MediaCodec.BufferInfo>();
@@ -528,7 +537,7 @@
 
         // Create decoder.
         MediaFormat format = MediaFormat.createVideoFormat(
-                VP8_MIME, ivf.getWidth(), ivf.getHeight());
+                codecMimeType, ivf.getWidth(), ivf.getHeight());
         CodecProperties properties = getVpxCodecProperties(
                 false /* encoder */, format, forceGoogleDecoder);
         if (properties == null) {
@@ -1243,13 +1252,13 @@
     }
 
     /**
-     * Vp8 encoding loop supporting encoding single streams with an option
+     * Vpx encoding loop supporting encoding single streams with an option
      * to run in a looper thread and use buffer ready notification callbacks.
      *
      * Output stream is described by encodingParams parameters.
      *
      * MediaCodec will raise an IllegalStateException
-     * whenever vp8 encoder fails to encode a frame.
+     * whenever vpx encoder fails to encode a frame.
      *
      * Color format of input file should be YUV420, and frameWidth,
      * frameHeight should be supplied correctly as raw input file doesn't
@@ -1268,7 +1277,8 @@
 
         // Create minimal media format signifying desired output.
         MediaFormat format = MediaFormat.createVideoFormat(
-                VP8_MIME, streamParams.frameWidth, streamParams.frameHeight);
+                streamParams.codecMimeType, streamParams.frameWidth,
+                streamParams.frameHeight);
         format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
         CodecProperties properties = getVpxCodecProperties(
                 true, format, streamParams.forceGoogleEncoder);
@@ -1280,7 +1290,8 @@
         InputStream yuvStream = OpenFileOrResourceId(
                 streamParams.inputYuvFilename, streamParams.inputResourceId);
         IvfWriter ivf = new IvfWriter(
-                streamParams.outputIvfFilename, streamParams.frameWidth, streamParams.frameHeight);
+                streamParams.outputIvfFilename, streamParams.codecMimeType,
+                streamParams.frameWidth, streamParams.frameHeight);
 
         // Create a media format signifying desired output.
         if (streamParams.bitrateType == VIDEO_ControlRateConstant) {
@@ -1416,12 +1427,12 @@
     }
 
     /**
-     * Vp8 encoding run in a looper thread and use buffer ready callbacks.
+     * Vpx encoding run in a looper thread and use buffer ready callbacks.
      *
      * Output stream is described by encodingParams parameters.
      *
      * MediaCodec will raise an IllegalStateException
-     * whenever vp8 encoder fails to encode a frame.
+     * whenever vpx encoder fails to encode a frame.
      *
      * Color format of input file should be YUV420, and frameWidth,
      * frameHeight should be supplied correctly as raw input file doesn't
@@ -1443,7 +1454,8 @@
 
         // Create minimal media format signifying desired output.
         MediaFormat format = MediaFormat.createVideoFormat(
-                VP8_MIME, streamParams.frameWidth, streamParams.frameHeight);
+                streamParams.codecMimeType, streamParams.frameWidth,
+                streamParams.frameHeight);
         format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
         CodecProperties properties = getVpxCodecProperties(
                 true, format, streamParams.forceGoogleEncoder);
@@ -1453,7 +1465,8 @@
 
         // Open input/output
         IvfWriter ivf = new IvfWriter(
-                streamParams.outputIvfFilename, streamParams.frameWidth, streamParams.frameHeight);
+                streamParams.outputIvfFilename, streamParams.codecMimeType,
+                streamParams.frameWidth, streamParams.frameHeight);
 
         // Create a media format signifying desired output.
         if (streamParams.bitrateType == VIDEO_ControlRateConstant) {
@@ -1495,13 +1508,13 @@
     }
 
     /**
-     * Vp8 encoding loop supporting encoding multiple streams at a time.
+     * Vpx encoding loop supporting encoding multiple streams at a time.
      * Each output stream is described by encodingParams parameters allowing
      * simultaneous encoding of various resolutions, bitrates with an option to
      * control key frame and dynamic bitrate for each output stream indepandently.
      *
      * MediaCodec will raise an IllegalStateException
-     * whenever vp8 encoder fails to encode a frame.
+     * whenever vpx encoder fails to encode a frame.
      *
      * Color format of input file should be YUV420, and frameWidth,
      * frameHeight should be supplied correctly as raw input file doesn't
@@ -1546,8 +1559,9 @@
             int bitrate = params.bitrateSet[0];
 
             // Create minimal media format signifying desired output.
-            format[i] = MediaFormat.createVideoFormat(VP8_MIME,
-                    params.frameWidth, params.frameHeight);
+            format[i] = MediaFormat.createVideoFormat(
+                    params.codecMimeType, params.frameWidth,
+                    params.frameHeight);
             format[i].setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
             CodecProperties properties = getVpxCodecProperties(
                     true, format[i], params.forceGoogleEncoder);
@@ -1572,7 +1586,9 @@
             yuvStream[i] = new FileInputStream(params.scaledYuvFilename);
 
             // Create IVF writer
-            ivf[i] = new IvfWriter(params.outputIvfFilename, params.frameWidth, params.frameHeight);
+            ivf[i] = new IvfWriter(
+                    params.outputIvfFilename, params.codecMimeType,
+                    params.frameWidth, params.frameHeight);
 
             // Frame buffer
             int frameSize = params.frameWidth * params.frameHeight * 3 / 2;
@@ -1731,8 +1747,8 @@
     /**
      * Some encoding statistics.
      */
-    protected class Vp8EncodingStatistics {
-        Vp8EncodingStatistics() {
+    protected class VpxEncodingStatistics {
+        VpxEncodingStatistics() {
             mBitrates = new ArrayList<Integer>();
             mFrames = new ArrayList<Integer>();
             mKeyFrames = new ArrayList<Integer>();
@@ -1756,9 +1772,9 @@
      * mKeyFrames array will contain the position of key frames in the encoded stream and
      * mKeyFrameInterval - average key frame interval.
      */
-    protected Vp8EncodingStatistics computeEncodingStatistics(int encoderId,
+    protected VpxEncodingStatistics computeEncodingStatistics(int encoderId,
             ArrayList<MediaCodec.BufferInfo> bufferInfos ) {
-        Vp8EncodingStatistics statistics = new Vp8EncodingStatistics();
+        VpxEncodingStatistics statistics = new VpxEncodingStatistics();
 
         int totalSize = 0;
         int frames = 0;
@@ -1838,18 +1854,18 @@
         return statistics;
     }
 
-    protected Vp8EncodingStatistics computeEncodingStatistics(
+    protected VpxEncodingStatistics computeEncodingStatistics(
             ArrayList<MediaCodec.BufferInfo> bufferInfos ) {
         return computeEncodingStatistics(0, bufferInfos);
     }
 
-    protected ArrayList<Vp8EncodingStatistics> computeSimulcastEncodingStatistics(
+    protected ArrayList<VpxEncodingStatistics> computeSimulcastEncodingStatistics(
             ArrayList<ArrayList<MediaCodec.BufferInfo>> bufferInfos) {
         int numCodecs = bufferInfos.size();
-        ArrayList<Vp8EncodingStatistics> statistics = new ArrayList<Vp8EncodingStatistics>();
+        ArrayList<VpxEncodingStatistics> statistics = new ArrayList<VpxEncodingStatistics>();
 
         for (int i = 0; i < numCodecs; i++) {
-            Vp8EncodingStatistics currentStatistics =
+            VpxEncodingStatistics currentStatistics =
                     computeEncodingStatistics(i, bufferInfos.get(i));
             statistics.add(currentStatistics);
         }
@@ -1872,8 +1888,8 @@
     /**
      * Decoding PSNR statistics.
      */
-    protected class Vp8DecodingStatistics {
-        Vp8DecodingStatistics() {
+    protected class VpxDecodingStatistics {
+        VpxDecodingStatistics() {
             mMinimumPSNR = Integer.MAX_VALUE;
         }
         public double mAveragePSNR;
@@ -1901,13 +1917,13 @@
      * set of reference and decoded video frames.
      * Runs PSNR calculation for the full duration of the decoded data.
      */
-    protected Vp8DecodingStatistics computeDecodingStatistics(
+    protected VpxDecodingStatistics computeDecodingStatistics(
             String referenceYuvFilename,
             int referenceYuvRawId,
             String decodedYuvFilename,
             int width,
             int height) throws Exception {
-        Vp8DecodingStatistics statistics = new Vp8DecodingStatistics();
+        VpxDecodingStatistics statistics = new VpxDecodingStatistics();
         InputStream referenceStream =
                 OpenFileOrResourceId(referenceYuvFilename, referenceYuvRawId);
         InputStream decodedStream = new FileInputStream(decodedYuvFilename);
diff --git a/tests/tests/media/src/android/media/cts/Vp8EncoderTest.java b/tests/tests/media/src/android/media/cts/VpxEncoderTest.java
similarity index 85%
rename from tests/tests/media/src/android/media/cts/Vp8EncoderTest.java
rename to tests/tests/media/src/android/media/cts/VpxEncoderTest.java
index 5552f6c..0e9c940 100644
--- a/tests/tests/media/src/android/media/cts/Vp8EncoderTest.java
+++ b/tests/tests/media/src/android/media/cts/VpxEncoderTest.java
@@ -28,14 +28,14 @@
 import java.util.Arrays;
 
 /**
- * Verification test for vp8 encoder and decoder.
+ * Verification test for vp8/vp9 encoder and decoder.
  *
  * A raw yv12 stream is encoded at various settings and written to an IVF
  * file. Encoded stream bitrate and key frame interval are checked against target values.
- * The stream is later decoded by vp8 decoder to verify frames are decodable and to
+ * The stream is later decoded by vp8/vp9 decoder to verify frames are decodable and to
  * calculate PSNR values for various bitrates.
  */
-public class Vp8EncoderTest extends Vp8CodecTestBase {
+public class VpxEncoderTest extends VpxCodecTestBase {
 
     private static final String ENCODED_IVF_BASE = "football";
     private static final String INPUT_YUV = null;
@@ -54,9 +54,9 @@
     private static final int[] TEST_BITRATES_SET = { 300000, 500000, 700000, 900000 };
     // Maximum allowed bitrate variation from the target value.
     private static final double MAX_BITRATE_VARIATION = 0.2;
-    // Average PSNR values for reference Google VP8 codec for the above bitrates.
+    // Average PSNR values for reference Google VPx codec for the above bitrates.
     private static final double[] REFERENCE_AVERAGE_PSNR = { 33.1, 35.2, 36.6, 37.8 };
-    // Minimum PSNR values for reference Google VP8 codec for the above bitrates.
+    // Minimum PSNR values for reference Google VPx codec for the above bitrates.
     private static final double[] REFERENCE_MINIMUM_PSNR = { 25.9, 27.5, 28.4, 30.3 };
     // Maximum allowed average PSNR difference of encoder comparing to reference Google encoder.
     private static final double MAX_AVERAGE_PSNR_DIFFERENCE = 2;
@@ -75,13 +75,13 @@
     private static final int MAX_KEYFRAME_INTERVAL_VARIATION = 3;
 
     /**
-     * A basic test for VP8 encoder.
+     * A basic test for VPx encoder.
      *
      * Encodes 9 seconds of raw stream with default configuration options,
      * and then decodes it to verify the bitstream.
      * Also checks the average bitrate is within MAX_BITRATE_VARIATION of the target value.
      */
-    public void testBasic() throws Exception {
+    private void internalTestBasic(String codecMimeType) throws Exception {
         int encodeSeconds = 9;
         boolean skipped = true;
 
@@ -89,6 +89,7 @@
             EncoderOutputStreamParameters params = getDefaultEncodingParameters(
                     INPUT_YUV,
                     ENCODED_IVF_BASE,
+                    codecMimeType,
                     encodeSeconds,
                     WIDTH,
                     HEIGHT,
@@ -102,14 +103,14 @@
             }
             skipped = false;
 
-            Vp8EncodingStatistics statistics = computeEncodingStatistics(bufInfo);
+            VpxEncodingStatistics statistics = computeEncodingStatistics(bufInfo);
 
             assertEquals("Stream bitrate " + statistics.mAverageBitrate +
                     " is different from the target " + targetBitrate,
                     targetBitrate, statistics.mAverageBitrate,
                     MAX_BITRATE_VARIATION * targetBitrate);
 
-            decode(params.outputIvfFilename, null, FPS, params.forceGoogleEncoder);
+            decode(params.outputIvfFilename, null, codecMimeType, FPS, params.forceGoogleEncoder);
         }
 
         if (skipped) {
@@ -118,13 +119,13 @@
     }
 
     /**
-     * Asynchronous encoding test for VP8 encoder.
+     * Asynchronous encoding test for VPx encoder.
      *
      * Encodes 9 seconds of raw stream using synchronous and asynchronous calls.
      * Checks the PSNR difference between the encoded and decoded output and reference yuv input
      * does not change much for two different ways of the encoder call.
      */
-    public void testAsyncEncoding() throws Exception {
+    private void internalTestAsyncEncoding(String codecMimeType) throws Exception {
         int encodeSeconds = 9;
 
         // First test the encoder running in a looper thread with buffer callbacks enabled.
@@ -132,6 +133,7 @@
         EncoderOutputStreamParameters params = getDefaultEncodingParameters(
                 INPUT_YUV,
                 ENCODED_IVF_BASE,
+                codecMimeType,
                 encodeSeconds,
                 WIDTH,
                 HEIGHT,
@@ -145,8 +147,8 @@
             return;
         }
         computeEncodingStatistics(bufInfos);
-        decode(params.outputIvfFilename, OUTPUT_YUV, FPS, params.forceGoogleEncoder);
-        Vp8DecodingStatistics statisticsAsync = computeDecodingStatistics(
+        decode(params.outputIvfFilename, OUTPUT_YUV, codecMimeType, FPS, params.forceGoogleEncoder);
+        VpxDecodingStatistics statisticsAsync = computeDecodingStatistics(
                 params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
                 params.frameWidth, params.frameHeight);
 
@@ -156,6 +158,7 @@
         params = getDefaultEncodingParameters(
                 INPUT_YUV,
                 ENCODED_IVF_BASE,
+                codecMimeType,
                 encodeSeconds,
                 WIDTH,
                 HEIGHT,
@@ -169,8 +172,8 @@
             return;
         }
         computeEncodingStatistics(bufInfos);
-        decode(params.outputIvfFilename, OUTPUT_YUV, FPS, params.forceGoogleEncoder);
-        Vp8DecodingStatistics statisticsSync = computeDecodingStatistics(
+        decode(params.outputIvfFilename, OUTPUT_YUV, codecMimeType, FPS, params.forceGoogleEncoder);
+        VpxDecodingStatistics statisticsSync = computeDecodingStatistics(
                 params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
                 params.frameWidth, params.frameHeight);
 
@@ -193,12 +196,13 @@
      * Encodes 9 seconds of raw stream and requests a sync frame every second (30 frames).
      * The test does not verify the output stream.
      */
-    public void testSyncFrame() throws Exception {
+    private void internalTestSyncFrame(String codecMimeType) throws Exception {
         int encodeSeconds = 9;
 
         EncoderOutputStreamParameters params = getDefaultEncodingParameters(
                 INPUT_YUV,
                 ENCODED_IVF_BASE,
+                codecMimeType,
                 encodeSeconds,
                 WIDTH,
                 HEIGHT,
@@ -214,7 +218,7 @@
             return;
         }
 
-        Vp8EncodingStatistics statistics = computeEncodingStatistics(bufInfo);
+        VpxEncodingStatistics statistics = computeEncodingStatistics(bufInfo);
 
         // First check if we got expected number of key frames.
         int actualKeyFrames = statistics.mKeyFrames.size();
@@ -242,13 +246,14 @@
      * Run the the encoder for 12 seconds. Request changes to the
      * bitrate after 6 seconds and ensure the encoder responds.
      */
-    public void testDynamicBitrateChange() throws Exception {
+    private void internalTestDynamicBitrateChange(String codecMimeType) throws Exception {
         int encodeSeconds = 12;    // Encoding sequence duration in seconds.
         int[] bitrateTargetValues = { 400000, 800000 };  // List of bitrates to test.
 
         EncoderOutputStreamParameters params = getDefaultEncodingParameters(
                 INPUT_YUV,
                 ENCODED_IVF_BASE,
+                codecMimeType,
                 encodeSeconds,
                 WIDTH,
                 HEIGHT,
@@ -274,7 +279,7 @@
             return;
         }
 
-        Vp8EncodingStatistics statistics = computeEncodingStatistics(bufInfo);
+        VpxEncodingStatistics statistics = computeEncodingStatistics(bufInfo);
 
         // Calculate actual average bitrates  for every [stepSeconds] second.
         int[] bitrateActualValues = new int[bitrateTargetValues.length];
@@ -309,11 +314,11 @@
       * and then run parallel encoding and decoding of the same streams.
       * Compares average bitrate and PSNR for sequential and parallel runs.
       */
-     public void testParallelEncodingAndDecoding() throws Exception {
+     private void internalTestParallelEncodingAndDecoding(String codecMimeType) throws Exception {
          // check for encoder up front, as by the time we detect lack of
          // encoder support, we may have already started decoding.
          MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
-         MediaFormat format = MediaFormat.createVideoFormat(VP8_MIME, WIDTH, HEIGHT);
+         MediaFormat format = MediaFormat.createVideoFormat(codecMimeType, WIDTH, HEIGHT);
          if (mcl.findEncoderForFormat(format) == null) {
              Log.i(TAG, "SKIPPING testParallelEncodingAndDecoding(): no suitable encoder found");
              return;
@@ -327,6 +332,7 @@
          final EncoderOutputStreamParameters params = getDefaultEncodingParameters(
                  INPUT_YUV,
                  ENCODED_IVF_BASE,
+                 codecMimeType,
                  encodeSeconds,
                  WIDTH,
                  HEIGHT,
@@ -340,7 +346,7 @@
              public void run() {
                  try {
                      ArrayList<MediaCodec.BufferInfo> bufInfo = encode(params);
-                     Vp8EncodingStatistics statistics = computeEncodingStatistics(bufInfo);
+                     VpxEncodingStatistics statistics = computeEncodingStatistics(bufInfo);
                      bitrate[0] = statistics.mAverageBitrate;
                  } catch (Exception e) {
                      Log.e(TAG, "Encoder error: " + e.toString());
@@ -351,8 +357,8 @@
          Runnable runDecoder = new Runnable() {
              public void run() {
                  try {
-                     decode(inputIvfFilename, OUTPUT_YUV, FPS, params.forceGoogleEncoder);
-                     Vp8DecodingStatistics statistics = computeDecodingStatistics(
+                     decode(inputIvfFilename, OUTPUT_YUV, codecMimeType, FPS, params.forceGoogleEncoder);
+                     VpxDecodingStatistics statistics = computeDecodingStatistics(
                             params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
                             params.frameWidth, params.frameHeight);
                      psnr[0] = statistics.mAveragePSNR;
@@ -410,7 +416,7 @@
      * Video streams with higher bitrates should have higher PSNRs.
      * Also compares average and minimum PSNR of codec with PSNR values of reference Google codec.
      */
-    public void testEncoderQuality() throws Exception {
+    private void internalTestEncoderQuality(String codecMimeType) throws Exception {
         int encodeSeconds = 9;      // Encoding sequence duration in seconds for each bitrate.
         double[] psnrPlatformCodecAverage = new double[TEST_BITRATES_SET.length];
         double[] psnrPlatformCodecMin = new double[TEST_BITRATES_SET.length];
@@ -423,6 +429,7 @@
             EncoderOutputStreamParameters params = getDefaultEncodingParameters(
                     INPUT_YUV,
                     ENCODED_IVF_BASE,
+                    codecMimeType,
                     encodeSeconds,
                     WIDTH,
                     HEIGHT,
@@ -438,8 +445,8 @@
             completed[i] = true;
             skipped = false;
 
-            decode(params.outputIvfFilename, OUTPUT_YUV, FPS, params.forceGoogleEncoder);
-            Vp8DecodingStatistics statistics = computeDecodingStatistics(
+            decode(params.outputIvfFilename, OUTPUT_YUV, codecMimeType, FPS, params.forceGoogleEncoder);
+            VpxDecodingStatistics statistics = computeDecodingStatistics(
                     params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
                     params.frameWidth, params.frameHeight);
             psnrPlatformCodecAverage[i] = statistics.mAveragePSNR;
@@ -500,5 +507,32 @@
             }
         }
     }
+
+    public void testBasicVP8() throws Exception { internalTestBasic(VP8_MIME); }
+    public void testBasicVP9() throws Exception { internalTestBasic(VP9_MIME); }
+
+    public void testAsyncEncodingVP8() throws Exception { internalTestAsyncEncoding(VP8_MIME); }
+    public void testAsyncEncodingVP9() throws Exception { internalTestAsyncEncoding(VP9_MIME); }
+
+    public void testSyncFrameVP8() throws Exception { internalTestSyncFrame(VP8_MIME); }
+    public void testSyncFrameVP9() throws Exception { internalTestSyncFrame(VP9_MIME); }
+
+    public void testDynamicBitrateChangeVP8() throws Exception {
+        internalTestDynamicBitrateChange(VP8_MIME);
+    }
+    public void testDynamicBitrateChangeVP9() throws Exception {
+        internalTestDynamicBitrateChange(VP9_MIME);
+    }
+
+    public void testParallelEncodingAndDecodingVP8() throws Exception {
+        internalTestParallelEncodingAndDecoding(VP8_MIME);
+    }
+    public void testParallelEncodingAndDecodingVP9() throws Exception {
+        internalTestParallelEncodingAndDecoding(VP9_MIME);
+    }
+
+    public void testEncoderQualityVP8() throws Exception { internalTestEncoderQuality(VP8_MIME); }
+    public void testEncoderQualityVP9() throws Exception { internalTestEncoderQuality(VP9_MIME); }
+
 }
 
diff --git a/tests/tests/os/Android.mk b/tests/tests/os/Android.mk
index 5397fc6a..abbad8f 100644
--- a/tests/tests/os/Android.mk
+++ b/tests/tests/os/Android.mk
@@ -25,7 +25,7 @@
 LOCAL_MULTILIB := both
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
-    ctsdeviceutil ctstestrunner guava
+    android-support-test ctsdeviceutil ctstestrunner guava platform-test-annotations
 
 LOCAL_JNI_SHARED_LIBRARIES := libcts_jni libctsos_jni libnativehelper_compat_libc++
 
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index 4ebe527..3d8ab32 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -18,8 +18,8 @@
 */
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="android" coreApp="true" android:sharedUserId="android.uid.system"
-          android:sharedUserLabel="@string/android_system_label">
+    package="android" coreApp="true" android:sharedUserId="android.uid.system"
+    android:sharedUserLabel="@string/android_system_label">
 
     <!-- ================================================ -->
     <!-- Special broadcasts that only the system can send -->
@@ -138,49 +138,46 @@
     <protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_REPLY" />
     <protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_CANCEL" />
     <protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST" />
-    <protected-broadcast android:name="android.bluetooth.device.action.SDP_RECORD" />
     <protected-broadcast android:name="android.bluetooth.devicepicker.action.LAUNCH" />
     <protected-broadcast android:name="android.bluetooth.devicepicker.action.DEVICE_SELECTED" />
     <protected-broadcast
-            android:name="android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED" />
+        android:name="android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
-            android:name="android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED" />
+        android:name="android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED" />
     <protected-broadcast
-            android:name="android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT" />
+        android:name="android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT" />
     <protected-broadcast
-            android:name="android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED" />
+        android:name="android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
-            android:name="android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED" />
+        android:name="android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED" />
     <protected-broadcast
-            android:name="android.bluetooth.headsetclient.profile.action.AG_EVENT" />
+        android:name="android.bluetooth.headsetclient.profile.action.AG_EVENT" />
     <protected-broadcast
-            android:name="android.bluetooth.headsetclient.profile.action.AG_CALL_CHANGED" />
+        android:name="android.bluetooth.headsetclient.profile.action.AG_CALL_CHANGED" />
     <protected-broadcast
-            android:name="android.bluetooth.headsetclient.profile.action.RESULT" />
+        android:name="android.bluetooth.headsetclient.profile.action.RESULT" />
     <protected-broadcast
-            android:name="android.bluetooth.headsetclient.profile.action.LAST_VTAG" />
+        android:name="android.bluetooth.headsetclient.profile.action.LAST_VTAG" />
     <protected-broadcast
-            android:name="android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED" />
+        android:name="android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
-            android:name="android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED" />
+        android:name="android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED" />
     <protected-broadcast
-            android:name="android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED" />
+        android:name="android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
-            android:name="android.bluetooth.a2dp-sink.profile.action.PLAYING_STATE_CHANGED" />
+        android:name="android.bluetooth.a2dp-sink.profile.action.PLAYING_STATE_CHANGED" />
     <protected-broadcast
-            android:name="android.bluetooth.a2dp-sink.profile.action.AUDIO_CONFIG_CHANGED" />
+        android:name="android.bluetooth.a2dp-sink.profile.action.AUDIO_CONFIG_CHANGED" />
     <protected-broadcast
-            android:name="android.bluetooth.avrcp-controller.profile.action.CONNECTION_STATE_CHANGED" />
+        android:name="android.bluetooth.avrcp-controller.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
-            android:name="android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED" />
+        android:name="android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
-            android:name="android.bluetooth.input.profile.action.PROTOCOL_MODE_CHANGED" />
+        android:name="android.bluetooth.input.profile.action.PROTOCOL_MODE_CHANGED" />
     <protected-broadcast
-            android:name="android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS" />
+        android:name="android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS" />
     <protected-broadcast
-            android:name="android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED" />
-    <protected-broadcast
-            android:name="android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED" />
+        android:name="android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast android:name="android.bluetooth.pbap.intent.action.PBAP_STATE_CHANGED" />
     <protected-broadcast android:name="android.btopp.intent.action.INCOMING_FILE_NOTIFICATION" />
     <protected-broadcast android:name="android.btopp.intent.action.USER_CONFIRMATION_TIMEOUT" />
@@ -192,7 +189,6 @@
     <protected-broadcast android:name="android.btopp.intent.action.RETRY" />
     <protected-broadcast android:name="android.btopp.intent.action.OPEN" />
     <protected-broadcast android:name="android.btopp.intent.action.OPEN_INBOUND" />
-    <protected-broadcast android:name="android.btopp.intent.action.TRANSFER_COMPLETE" />
     <protected-broadcast android:name="com.android.bluetooth.pbap.authchall" />
     <protected-broadcast android:name="com.android.bluetooth.pbap.userconfirmtimeout" />
     <protected-broadcast android:name="com.android.bluetooth.pbap.authresponse" />
@@ -310,7 +306,7 @@
     <protected-broadcast android:name="android.intent.action.ACTION_IDLE_MAINTENANCE_START" />
     <protected-broadcast android:name="android.intent.action.ACTION_IDLE_MAINTENANCE_END" />
 
-    <protected-broadcast android:name="com.android.server.ACTION_TRIGGER_IDLE" />
+    <protected-broadcast android:name="com.android.server.task.controllers.IdleController.ACTION_TRIGGER_IDLE" />
 
     <protected-broadcast android:name="android.intent.action.HDMI_PLUGGED" />
 
@@ -330,11 +326,11 @@
     <protected-broadcast android:name="android.provider.Telephony.MMS_DOWNLOADED" />
 
     <protected-broadcast
-            android:name="com.android.server.connectivityservice.CONNECTED_TO_PROVISIONING_NETWORK_ACTION" />
+        android:name="com.android.server.connectivityservice.CONNECTED_TO_PROVISIONING_NETWORK_ACTION" />
 
     <!-- Defined in RestrictionsManager -->
     <protected-broadcast
-            android:name="android.intent.action.PERMISSION_RESPONSE_RECEIVED" />
+        android:name="android.intent.action.PERMISSION_RESPONSE_RECEIVED" />
     <!-- Defined in RestrictionsManager -->
 
     <protected-broadcast android:name="android.intent.action.REQUEST_PERMISSION" />
@@ -496,28 +492,28 @@
     <!-- Used for runtime permissions related to contacts and profiles on this
         device. -->
     <permission-group android:name="android.permission-group.CONTACTS"
-                      android:icon="@drawable/perm_group_contacts"
-                      android:label="@string/permgrouplab_contacts"
-                      android:description="@string/permgroupdesc_contacts"
-                      android:priority="100" />
+        android:icon="@drawable/perm_group_contacts"
+        android:label="@string/permgrouplab_contacts"
+        android:description="@string/permgroupdesc_contacts"
+        android:priority="100" />
 
     <!-- Allows an application to read the user's contacts data.
         <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.READ_CONTACTS"
-                android:permissionGroup="android.permission-group.CONTACTS"
-                android:label="@string/permlab_readContacts"
-                android:description="@string/permdesc_readContacts"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.CONTACTS"
+        android:label="@string/permlab_readContacts"
+        android:description="@string/permdesc_readContacts"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an application to write the user's contacts data.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.WRITE_CONTACTS"
-                android:permissionGroup="android.permission-group.CONTACTS"
-                android:label="@string/permlab_writeContacts"
-                android:description="@string/permdesc_writeContacts"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.CONTACTS"
+        android:label="@string/permlab_writeContacts"
+        android:description="@string/permdesc_writeContacts"
+        android:protectionLevel="dangerous" />
 
     <!-- ====================================================================== -->
     <!-- Permissions for accessing user's calendar                              -->
@@ -526,28 +522,28 @@
 
     <!-- Used for runtime permissions related to user's calendar. -->
     <permission-group android:name="android.permission-group.CALENDAR"
-                      android:icon="@drawable/perm_group_calendar"
-                      android:label="@string/permgrouplab_calendar"
-                      android:description="@string/permgroupdesc_calendar"
-                      android:priority="200" />
+        android:icon="@drawable/perm_group_calendar"
+        android:label="@string/permgrouplab_calendar"
+        android:description="@string/permgroupdesc_calendar"
+        android:priority="200" />
 
     <!-- Allows an application to read the user's calendar data.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.READ_CALENDAR"
-                android:permissionGroup="android.permission-group.CALENDAR"
-                android:label="@string/permlab_readCalendar"
-                android:description="@string/permdesc_readCalendar"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.CALENDAR"
+        android:label="@string/permlab_readCalendar"
+        android:description="@string/permdesc_readCalendar"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an application to write the user's calendar data.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.WRITE_CALENDAR"
-                android:permissionGroup="android.permission-group.CALENDAR"
-                android:label="@string/permlab_writeCalendar"
-                android:description="@string/permdesc_writeCalendar"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.CALENDAR"
+        android:label="@string/permlab_writeCalendar"
+        android:description="@string/permdesc_writeCalendar"
+        android:protectionLevel="dangerous" />
 
     <!-- ====================================================================== -->
     <!-- Permissions for accessing and modifying user's SMS messages            -->
@@ -556,56 +552,56 @@
 
     <!-- Used for runtime permissions related to user's SMS messages. -->
     <permission-group android:name="android.permission-group.SMS"
-                      android:icon="@drawable/perm_group_sms"
-                      android:label="@string/permgrouplab_sms"
-                      android:description="@string/permgroupdesc_sms"
-                      android:priority="300" />
+        android:icon="@drawable/perm_group_sms"
+        android:label="@string/permgrouplab_sms"
+        android:description="@string/permgroupdesc_sms"
+        android:priority="300" />
 
     <!-- Allows an application to send SMS messages.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.SEND_SMS"
-                android:permissionGroup="android.permission-group.SMS"
-                android:label="@string/permlab_sendSms"
-                android:description="@string/permdesc_sendSms"
-                android:permissionFlags="costsMoney"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.SMS"
+        android:label="@string/permlab_sendSms"
+        android:description="@string/permdesc_sendSms"
+        android:permissionFlags="costsMoney"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an application to receive SMS messages.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.RECEIVE_SMS"
-                android:permissionGroup="android.permission-group.SMS"
-                android:label="@string/permlab_receiveSms"
-                android:description="@string/permdesc_receiveSms"
-                android:protectionLevel="dangerous"/>
+        android:permissionGroup="android.permission-group.SMS"
+        android:label="@string/permlab_receiveSms"
+        android:description="@string/permdesc_receiveSms"
+        android:protectionLevel="dangerous"/>
 
     <!-- Allows an application to read SMS messages.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.READ_SMS"
-                android:permissionGroup="android.permission-group.SMS"
-                android:label="@string/permlab_readSms"
-                android:description="@string/permdesc_readSms"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.SMS"
+        android:label="@string/permlab_readSms"
+        android:description="@string/permdesc_readSms"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an application to receive WAP push messages.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.RECEIVE_WAP_PUSH"
-                android:permissionGroup="android.permission-group.SMS"
-                android:label="@string/permlab_receiveWapPush"
-                android:description="@string/permdesc_receiveWapPush"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.SMS"
+        android:label="@string/permlab_receiveWapPush"
+        android:description="@string/permdesc_receiveWapPush"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an application to monitor incoming MMS messages.
         <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.RECEIVE_MMS"
-                android:permissionGroup="android.permission-group.SMS"
-                android:label="@string/permlab_receiveMms"
-                android:description="@string/permdesc_receiveMms"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.SMS"
+        android:label="@string/permlab_receiveMms"
+        android:description="@string/permdesc_receiveMms"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an application to read previously received cell broadcast
          messages and to register a content observer to get notifications when
@@ -620,10 +616,10 @@
          <p>Protection level: dangerous
          @hide Pending API council approval -->
     <permission android:name="android.permission.READ_CELL_BROADCASTS"
-                android:permissionGroup="android.permission-group.SMS"
-                android:label="@string/permlab_readCellBroadcasts"
-                android:description="@string/permdesc_readCellBroadcasts"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.SMS"
+        android:label="@string/permlab_readCellBroadcasts"
+        android:description="@string/permdesc_readCellBroadcasts"
+        android:protectionLevel="dangerous" />
 
     <!-- ====================================================================== -->
     <!-- Permissions for accessing external storage                             -->
@@ -632,10 +628,10 @@
 
     <!-- Used for runtime permissions related to the shared external storage. -->
     <permission-group android:name="android.permission-group.STORAGE"
-                      android:icon="@drawable/perm_group_storage"
-                      android:label="@string/permgrouplab_storage"
-                      android:description="@string/permgroupdesc_storage"
-                      android:priority="900" />
+        android:icon="@drawable/perm_group_storage"
+        android:label="@string/permgrouplab_storage"
+        android:description="@string/permgroupdesc_storage"
+        android:priority="900" />
 
     <!-- Allows an application to read from external storage.
      <p>Any app that declares the {@link #WRITE_EXTERNAL_STORAGE} permission is implicitly
@@ -660,10 +656,10 @@
      <p>Protection level: dangerous
      -->
     <permission android:name="android.permission.READ_EXTERNAL_STORAGE"
-                android:permissionGroup="android.permission-group.STORAGE"
-                android:label="@string/permlab_sdcardRead"
-                android:description="@string/permdesc_sdcardRead"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.STORAGE"
+        android:label="@string/permlab_sdcardRead"
+        android:description="@string/permdesc_sdcardRead"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an application to write to external storage.
          <p class="note"><strong>Note:</strong> If <em>both</em> your <a
@@ -681,10 +677,10 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
-                android:permissionGroup="android.permission-group.STORAGE"
-                android:label="@string/permlab_sdcardWrite"
-                android:description="@string/permdesc_sdcardWrite"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.STORAGE"
+        android:label="@string/permlab_sdcardWrite"
+        android:description="@string/permdesc_sdcardWrite"
+        android:protectionLevel="dangerous" />
 
     <!-- ====================================================================== -->
     <!-- Permissions for accessing the device location                          -->
@@ -693,28 +689,28 @@
 
     <!-- Used for permissions that allow accessing the device location. -->
     <permission-group android:name="android.permission-group.LOCATION"
-                      android:icon="@drawable/perm_group_location"
-                      android:label="@string/permgrouplab_location"
-                      android:description="@string/permgroupdesc_location"
-                      android:priority="400" />
+        android:icon="@drawable/perm_group_location"
+        android:label="@string/permgrouplab_location"
+        android:description="@string/permgroupdesc_location"
+        android:priority="400" />
 
     <!-- Allows an app to access precise location.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.ACCESS_FINE_LOCATION"
-                android:permissionGroup="android.permission-group.LOCATION"
-                android:label="@string/permlab_accessFineLocation"
-                android:description="@string/permdesc_accessFineLocation"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.LOCATION"
+        android:label="@string/permlab_accessFineLocation"
+        android:description="@string/permdesc_accessFineLocation"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an app to access approximate location.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.ACCESS_COARSE_LOCATION"
-                android:permissionGroup="android.permission-group.LOCATION"
-                android:label="@string/permlab_accessCoarseLocation"
-                android:description="@string/permdesc_accessCoarseLocation"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.LOCATION"
+        android:label="@string/permlab_accessCoarseLocation"
+        android:description="@string/permdesc_accessCoarseLocation"
+        android:protectionLevel="dangerous" />
 
     <!-- ====================================================================== -->
     <!-- Permissions for accessing the device telephony                         -->
@@ -723,10 +719,10 @@
 
     <!-- Used for permissions that are associated telephony features. -->
     <permission-group android:name="android.permission-group.PHONE"
-                      android:icon="@drawable/perm_group_phone_calls"
-                      android:label="@string/permgrouplab_phone"
-                      android:description="@string/permgroupdesc_phone"
-                      android:priority="500" />
+        android:icon="@drawable/perm_group_phone_calls"
+        android:label="@string/permgrouplab_phone"
+        android:description="@string/permgroupdesc_phone"
+        android:priority="500" />
 
     <!-- Allows read only access to phone state, including the phone number of the device,
          current cellular network information, the status of any ongoing calls, and a list of any
@@ -742,21 +738,21 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.READ_PHONE_STATE"
-                android:permissionGroup="android.permission-group.PHONE"
-                android:label="@string/permlab_readPhoneState"
-                android:description="@string/permdesc_readPhoneState"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.PHONE"
+        android:label="@string/permlab_readPhoneState"
+        android:description="@string/permdesc_readPhoneState"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an application to initiate a phone call without going through
         the Dialer user interface for the user to confirm the call.
         <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.CALL_PHONE"
-                android:permissionGroup="android.permission-group.PHONE"
-                android:permissionFlags="costsMoney"
-                android:label="@string/permlab_callPhone"
-                android:description="@string/permdesc_callPhone"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.PHONE"
+        android:permissionFlags="costsMoney"
+        android:label="@string/permlab_callPhone"
+        android:description="@string/permdesc_callPhone"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an application to access the IMS call service: making and
          modifying a call
@@ -764,10 +760,10 @@
         @hide
     -->
     <permission android:name="android.permission.ACCESS_IMS_CALL_SERVICE"
-                android:permissionGroup="android.permission-group.PHONE"
-                android:label="@string/permlab_accessImsCallService"
-                android:description="@string/permdesc_accessImsCallService"
-                android:protectionLevel="signature|privileged" />
+        android:permissionGroup="android.permission-group.PHONE"
+        android:label="@string/permlab_accessImsCallService"
+        android:description="@string/permdesc_accessImsCallService"
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to read the user's call log.
          <p class="note"><strong>Note:</strong> If your app uses the
@@ -782,10 +778,10 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.READ_CALL_LOG"
-                android:permissionGroup="android.permission-group.PHONE"
-                android:label="@string/permlab_readCallLog"
-                android:description="@string/permdesc_readCallLog"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.PHONE"
+        android:label="@string/permlab_readCallLog"
+        android:description="@string/permdesc_readCallLog"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an application to write (but not read) the user's
          call log data.
@@ -801,28 +797,28 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.WRITE_CALL_LOG"
-                android:permissionGroup="android.permission-group.PHONE"
-                android:label="@string/permlab_writeCallLog"
-                android:description="@string/permdesc_writeCallLog"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.PHONE"
+        android:label="@string/permlab_writeCallLog"
+        android:description="@string/permdesc_writeCallLog"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an application to add voicemails into the system.
          <p>Protection level: dangerous
     -->
     <permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL"
-                android:permissionGroup="android.permission-group.PHONE"
-                android:label="@string/permlab_addVoicemail"
-                android:description="@string/permdesc_addVoicemail"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.PHONE"
+        android:label="@string/permlab_addVoicemail"
+        android:description="@string/permdesc_addVoicemail"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an application to use SIP service.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.USE_SIP"
-                android:permissionGroup="android.permission-group.PHONE"
-                android:description="@string/permdesc_use_sip"
-                android:label="@string/permlab_use_sip"
-                android:protectionLevel="dangerous"/>
+        android:permissionGroup="android.permission-group.PHONE"
+        android:description="@string/permdesc_use_sip"
+        android:label="@string/permlab_use_sip"
+        android:protectionLevel="dangerous"/>
 
     <!-- Allows an application to see the number being dialed during an outgoing
          call with the option to redirect the call to a different number or
@@ -830,10 +826,10 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.PROCESS_OUTGOING_CALLS"
-                android:permissionGroup="android.permission-group.PHONE"
-                android:label="@string/permlab_processOutgoingCalls"
-                android:description="@string/permdesc_processOutgoingCalls"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.PHONE"
+        android:label="@string/permlab_processOutgoingCalls"
+        android:description="@string/permdesc_processOutgoingCalls"
+        android:protectionLevel="dangerous" />
 
     <!-- ====================================================================== -->
     <!-- Permissions for accessing the device microphone                        -->
@@ -844,19 +840,19 @@
          microphone audio from the device. Note that phone calls also capture audio
          but are in a separate (more visible) permission group. -->
     <permission-group android:name="android.permission-group.MICROPHONE"
-                      android:icon="@drawable/perm_group_microphone"
-                      android:label="@string/permgrouplab_microphone"
-                      android:description="@string/permgroupdesc_microphone"
-                      android:priority="600" />
+        android:icon="@drawable/perm_group_microphone"
+        android:label="@string/permgrouplab_microphone"
+        android:description="@string/permgroupdesc_microphone"
+        android:priority="600" />
 
     <!-- Allows an application to record audio.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.RECORD_AUDIO"
-                android:permissionGroup="android.permission-group.MICROPHONE"
-                android:label="@string/permlab_recordAudio"
-                android:description="@string/permdesc_recordAudio"
-                android:protectionLevel="dangerous"/>
+        android:permissionGroup="android.permission-group.MICROPHONE"
+        android:label="@string/permlab_recordAudio"
+        android:description="@string/permdesc_recordAudio"
+        android:protectionLevel="dangerous"/>
 
     <!-- ====================================================================== -->
     <!-- Permissions for accessing the UCE Service                              -->
@@ -866,15 +862,15 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.ACCESS_UCE_PRESENCE_SERVICE"
-                android:permissionGroup="android.permission-group.PHONE"
-                android:protectionLevel="signatureOrSystem"/>
+        android:permissionGroup="android.permission-group.PHONE"
+        android:protectionLevel="signatureOrSystem"/>
 
     <!-- @hide Allows an application to Access UCE-OPTIONS.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.ACCESS_UCE_OPTIONS_SERVICE"
-                android:permissionGroup="android.permission-group.PHONE"
-                android:protectionLevel="signatureOrSystem"/>
+        android:permissionGroup="android.permission-group.PHONE"
+        android:protectionLevel="signatureOrSystem"/>
 
 
 
@@ -886,10 +882,10 @@
     <!-- Used for permissions that are associated with accessing
      camera or capturing images/video from the device. -->
     <permission-group android:name="android.permission-group.CAMERA"
-                      android:icon="@drawable/perm_group_camera"
-                      android:label="@string/permgrouplab_camera"
-                      android:description="@string/permgroupdesc_camera"
-                      android:priority="700" />
+        android:icon="@drawable/perm_group_camera"
+        android:label="@string/permgrouplab_camera"
+        android:description="@string/permgroupdesc_camera"
+        android:priority="700" />
 
     <!-- Required to be able to access the camera device.
          <p>This will automatically enforce the <a
@@ -901,10 +897,10 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.CAMERA"
-                android:permissionGroup="android.permission-group.CAMERA"
-                android:label="@string/permlab_camera"
-                android:description="@string/permdesc_camera"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.CAMERA"
+        android:label="@string/permlab_camera"
+        android:description="@string/permdesc_camera"
+        android:protectionLevel="dangerous" />
 
 
     <!-- ====================================================================== -->
@@ -915,28 +911,28 @@
     <!-- Used for permissions that are associated with accessing
          camera or capturing images/video from the device. -->
     <permission-group android:name="android.permission-group.SENSORS"
-                      android:icon="@drawable/perm_group_sensors"
-                      android:label="@string/permgrouplab_sensors"
-                      android:description="@string/permgroupdesc_sensors"
-                      android:priority="800" />
+        android:icon="@drawable/perm_group_sensors"
+        android:label="@string/permgrouplab_sensors"
+        android:description="@string/permgroupdesc_sensors"
+        android:priority="800" />
 
     <!-- Allows an application to access data from sensors that the user uses to
          measure what is happening inside his/her body, such as heart rate.
          <p>Protection level: dangerous -->
     <permission android:name="android.permission.BODY_SENSORS"
-                android:permissionGroup="android.permission-group.SENSORS"
-                android:label="@string/permlab_bodySensors"
-                android:description="@string/permdesc_bodySensors"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.SENSORS"
+        android:label="@string/permlab_bodySensors"
+        android:description="@string/permdesc_bodySensors"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an app to use fingerprint hardware.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.USE_FINGERPRINT"
-                android:permissionGroup="android.permission-group.SENSORS"
-                android:label="@string/permlab_useFingerprint"
-                android:description="@string/permdesc_useFingerprint"
-                android:protectionLevel="normal" />
+        android:permissionGroup="android.permission-group.SENSORS"
+        android:label="@string/permlab_useFingerprint"
+        android:description="@string/permdesc_useFingerprint"
+        android:protectionLevel="normal" />
 
     <!-- ====================================================================== -->
     <!-- REMOVED PERMISSIONS                                                    -->
@@ -944,78 +940,78 @@
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.READ_PROFILE"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.WRITE_PROFILE"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.READ_SOCIAL_STREAM"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.WRITE_SOCIAL_STREAM"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.READ_USER_DICTIONARY"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.WRITE_USER_DICTIONARY"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.WRITE_SMS"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="com.android.browser.permission.WRITE_HISTORY_BOOKMARKS"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.MANAGE_ACCOUNTS"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.USE_CREDENTIALS"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.SUBSCRIBED_FEEDS_READ"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.SUBSCRIBED_FEEDS_WRITE"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.FLASHLIGHT"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- ====================================================================== -->
     <!-- INSTALL PERMISSIONS                                                    -->
@@ -1030,37 +1026,35 @@
          to handle the respond-via-message action during incoming calls.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.SEND_RESPOND_VIA_MESSAGE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to send SMS to premium shortcodes without user permission.
-         <p>Not for use by third-party applications.
-         @hide -->
+         <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.SEND_SMS_NO_CONFIRMATION"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to filter carrier specific sms.
          @hide -->
     <permission android:name="android.permission.CARRIER_FILTER_SMS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to receive emergency cell broadcast messages,
          to record or display them to the user.
-         <p>Not for use by third-party applications.
-         @hide -->
+         <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.RECEIVE_EMERGENCY_BROADCAST"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to monitor incoming Bluetooth MAP messages, to record
          or perform processing on them. -->
     <!-- @hide -->
     <permission android:name="android.permission.RECEIVE_BLUETOOTH_MAP"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allows an application to execute contacts directory search.
          This should only be used by ContactsProvider.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.BIND_DIRECTORY_SEARCH"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allows an application to modify cell broadcasts through the content provider.
          <p>Not for use by third-party applications. -->
@@ -1076,9 +1070,9 @@
          <p>Protection level: normal
     -->
     <permission android:name="com.android.alarm.permission.SET_ALARM"
-                android:label="@string/permlab_setAlarm"
-                android:description="@string/permdesc_setAlarm"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_setAlarm"
+        android:description="@string/permdesc_setAlarm"
+        android:protectionLevel="normal" />
 
     <!-- =============================================================== -->
     <!-- Permissions for accessing the user voicemail                    -->
@@ -1089,13 +1083,13 @@
         <p>Protection level: signature|privileged
     -->
     <permission android:name="com.android.voicemail.permission.WRITE_VOICEMAIL"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to read voicemails in the system.
          <p>Protection level: signature|privileged
     -->
     <permission android:name="com.android.voicemail.permission.READ_VOICEMAIL"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- ======================================= -->
     <!-- Permissions for accessing location info -->
@@ -1106,26 +1100,26 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"
-                android:label="@string/permlab_accessLocationExtraCommands"
-                android:description="@string/permdesc_accessLocationExtraCommands"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_accessLocationExtraCommands"
+        android:description="@string/permdesc_accessLocationExtraCommands"
+        android:protectionLevel="normal" />
 
     <!-- @SystemApi Allows an application to install a location provider into the Location Manager.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.INSTALL_LOCATION_PROVIDER"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allows HDMI-CEC service to access device and configuration files.
          This should only be used by HDMI-CEC service.
     -->
     <permission android:name="android.permission.HDMI_CEC"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to use location features in hardware,
          such as the geofencing api.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.LOCATION_HARDWARE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
     <uses-permission android:name="android.permission.LOCATION_HARDWARE"/>
 
     <!-- @SystemApi Allows an application to create mock location providers for testing.
@@ -1133,7 +1127,7 @@
          @hide
     -->
     <permission android:name="android.permission.ACCESS_MOCK_LOCATION"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- ======================================= -->
     <!-- Permissions for accessing networks -->
@@ -1144,73 +1138,73 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.INTERNET"
-                android:description="@string/permdesc_createNetworkSockets"
-                android:label="@string/permlab_createNetworkSockets"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_createNetworkSockets"
+        android:label="@string/permlab_createNetworkSockets"
+        android:protectionLevel="normal" />
 
     <!-- Allows applications to access information about networks.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.ACCESS_NETWORK_STATE"
-                android:description="@string/permdesc_accessNetworkState"
-                android:label="@string/permlab_accessNetworkState"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_accessNetworkState"
+        android:label="@string/permlab_accessNetworkState"
+        android:protectionLevel="normal" />
 
     <!-- Allows applications to access information about Wi-Fi networks.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.ACCESS_WIFI_STATE"
-                android:description="@string/permdesc_accessWifiState"
-                android:label="@string/permlab_accessWifiState"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_accessWifiState"
+        android:label="@string/permlab_accessWifiState"
+        android:protectionLevel="normal" />
 
     <!-- Allows applications to change Wi-Fi connectivity state.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.CHANGE_WIFI_STATE"
-                android:description="@string/permdesc_changeWifiState"
-                android:label="@string/permlab_changeWifiState"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_changeWifiState"
+        android:label="@string/permlab_changeWifiState"
+        android:protectionLevel="normal" />
 
     <!-- @SystemApi @hide Allows applications to read Wi-Fi credential.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.READ_WIFI_CREDENTIAL"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allows applications to change tether state and run
          tether carrier provisioning.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.TETHER_PRIVILEGED"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allow system apps to receive broadcast
          when a wifi network credential is changed.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allows an application to modify any wifi configuration, even if created
      by another application. Once reconfigured the original creator cannot make any further
      modifications.
      <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.OVERRIDE_WIFI_CONFIG"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @hide -->
     <permission android:name="android.permission.ACCESS_WIMAX_STATE"
-                android:description="@string/permdesc_accessWimaxState"
-                android:label="@string/permlab_accessWimaxState"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_accessWimaxState"
+        android:label="@string/permlab_accessWimaxState"
+        android:protectionLevel="normal" />
 
     <!-- @hide -->
     <permission android:name="android.permission.CHANGE_WIMAX_STATE"
-                android:description="@string/permdesc_changeWimaxState"
-                android:label="@string/permlab_changeWimaxState"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_changeWimaxState"
+        android:label="@string/permlab_changeWimaxState"
+        android:protectionLevel="normal" />
 
     <!-- Allows applications to act as network scorers. @hide @SystemApi-->
     <permission android:name="android.permission.SCORE_NETWORKS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- ======================================= -->
     <!-- Permissions for short range, peripheral networks -->
@@ -1221,68 +1215,68 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.BLUETOOTH"
-                android:description="@string/permdesc_bluetooth"
-                android:label="@string/permlab_bluetooth"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_bluetooth"
+        android:label="@string/permlab_bluetooth"
+        android:protectionLevel="normal" />
 
     <!-- Allows applications to discover and pair bluetooth devices.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.BLUETOOTH_ADMIN"
-                android:description="@string/permdesc_bluetoothAdmin"
-                android:label="@string/permlab_bluetoothAdmin"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_bluetoothAdmin"
+        android:label="@string/permlab_bluetoothAdmin"
+        android:protectionLevel="normal" />
 
     <!-- @SystemApi Allows applications to pair bluetooth devices without user interaction, and to
          allow or disallow phonebook access or message access.
          This is not available to third party applications. -->
     <permission android:name="android.permission.BLUETOOTH_PRIVILEGED"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Control access to email providers exclusively for Bluetooth
          @hide
     -->
     <permission android:name="android.permission.BLUETOOTH_MAP"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows bluetooth stack to access files
          @hide This should only be used by Bluetooth apk.
     -->
     <permission android:name="android.permission.BLUETOOTH_STACK"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows applications to perform I/O operations over NFC.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.NFC"
-                android:description="@string/permdesc_nfc"
-                android:label="@string/permlab_nfc"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_nfc"
+        android:label="@string/permlab_nfc"
+        android:protectionLevel="normal" />
 
     <!-- @SystemApi Allows an internal user to use privileged ConnectivityManager APIs.
          @hide -->
     <permission android:name="android.permission.CONNECTIVITY_INTERNAL"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows a system application to access hardware packet offload capabilities.
          @hide -->
     <permission android:name="android.permission.PACKET_KEEPALIVE_OFFLOAD"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi
          @hide -->
     <permission android:name="android.permission.RECEIVE_DATA_ACTIVITY_CHANGE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows access to the loop radio (Android@Home mesh network) device.
          @hide -->
     <permission android:name="android.permission.LOOP_RADIO"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows sending and receiving handover transfer status from Wifi and Bluetooth
          @hide -->
     <permission android:name="android.permission.NFC_HANDOVER_STATUS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- ================================== -->
     <!-- Permissions for accessing accounts -->
@@ -1301,15 +1295,15 @@
     <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.GET_ACCOUNTS"
-                android:permissionGroup="android.permission-group.CONTACTS"
-                android:protectionLevel="dangerous"
-                android:description="@string/permdesc_getAccounts"
-                android:label="@string/permlab_getAccounts" />
+        android:permissionGroup="android.permission-group.CONTACTS"
+        android:protectionLevel="dangerous"
+        android:description="@string/permdesc_getAccounts"
+        android:label="@string/permlab_getAccounts" />
 
     <!-- @SystemApi Allows applications to call into AccountAuthenticators.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.ACCOUNT_MANAGER"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- ================================== -->
     <!-- Permissions for accessing hardware that may effect battery life-->
@@ -1320,34 +1314,34 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"
-                android:description="@string/permdesc_changeWifiMulticastState"
-                android:label="@string/permlab_changeWifiMulticastState"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_changeWifiMulticastState"
+        android:label="@string/permlab_changeWifiMulticastState"
+        android:protectionLevel="normal" />
 
     <!-- Allows access to the vibrator.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.VIBRATE"
-                android:label="@string/permlab_vibrate"
-                android:description="@string/permdesc_vibrate"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_vibrate"
+        android:description="@string/permdesc_vibrate"
+        android:protectionLevel="normal" />
 
     <!-- Allows using PowerManager WakeLocks to keep processor from sleeping or screen
          from dimming.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.WAKE_LOCK"
-                android:label="@string/permlab_wakeLock"
-                android:description="@string/permdesc_wakeLock"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_wakeLock"
+        android:description="@string/permdesc_wakeLock"
+        android:protectionLevel="normal" />
 
     <!-- Allows using the device's IR transmitter, if available.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.TRANSMIT_IR"
-                android:label="@string/permlab_transmitIr"
-                android:description="@string/permdesc_transmitIr"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_transmitIr"
+        android:description="@string/permdesc_transmitIr"
+        android:protectionLevel="normal" />
 
     <!-- ==================================================== -->
     <!-- Permissions related to changing audio settings   -->
@@ -1358,9 +1352,9 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"
-                android:label="@string/permlab_modifyAudioSettings"
-                android:description="@string/permdesc_modifyAudioSettings"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_modifyAudioSettings"
+        android:description="@string/permdesc_modifyAudioSettings"
+        android:protectionLevel="normal" />
 
     <!-- ================================== -->
     <!-- Permissions for accessing hardware -->
@@ -1370,53 +1364,53 @@
     <!-- @SystemApi Allows an application to manage preferences and permissions for USB devices
          @hide -->
     <permission android:name="android.permission.MANAGE_USB"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to access the MTP USB kernel driver.
          For use only by the device side MTP implementation.
          @hide -->
     <permission android:name="android.permission.ACCESS_MTP"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows access to hardware peripherals.  Intended only for hardware testing.
          <p>Not for use by third-party applications.
          @hide
     -->
     <permission android:name="android.permission.HARDWARE_TEST"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows access to FM
          @hide This is not a third-party API (intended for system apps).-->
     <permission android:name="android.permission.ACCESS_FM_RADIO"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows access to configure network interfaces, configure/use IPSec, etc.
          @hide -->
     <permission android:name="android.permission.NET_ADMIN"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows registration for remote audio playback. @hide -->
     <permission android:name="android.permission.REMOTE_AUDIO_PLAYBACK"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows TvInputService to access underlying TV input hardware such as
          built-in tuners and HDMI-in's.
          @hide This should only be used by OEM's TvInputService's.
     -->
     <permission android:name="android.permission.TV_INPUT_HARDWARE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows to capture a frame of TV input hardware such as
          built-in tuners and HDMI-in's.
          @hide <p>Not for use by third-party applications.
     -->
     <permission android:name="android.permission.CAPTURE_TV_INPUT"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @hide Allows TvInputService to access DVB device.
    <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.DVB_DEVICE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows reading the OEM unlock state
          @hide <p>Not for use by third-party applications. -->
@@ -1426,17 +1420,17 @@
     <!-- @hide Allows enabling/disabling OEM unlock
    <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.OEM_UNLOCK_STATE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @hide Allows querying state of PersistentDataBlock
    <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.ACCESS_PDB_STATE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @hide Allows system update service to notify device owner about pending updates.
    <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.NOTIFY_PENDING_SYSTEM_UPDATE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- =========================================== -->
     <!-- Permissions associated with camera and image capture -->
@@ -1447,12 +1441,12 @@
          a camera is in use by an application.
          @hide -->
     <permission android:name="android.permission.CAMERA_DISABLE_TRANSMIT_LED"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows sending the camera service notifications about system-wide events.
         @hide -->
     <permission android:name="android.permission.CAMERA_SEND_SYSTEM_EVENTS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- =========================================== -->
     <!-- Permissions associated with telephony state -->
@@ -1463,50 +1457,50 @@
          Does not include placing calls.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.MODIFY_PHONE_STATE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows read only access to precise phone state.
          @hide Pending API council approval -->
     <permission android:name="android.permission.READ_PRECISE_PHONE_STATE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows read access to privileged phone state.
          @hide Used internally. -->
     <permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Protects the ability to register any PhoneAccount with
          PhoneAccount#CAPABILITY_SIM_SUBSCRIPTION. This capability indicates that the PhoneAccount
          corresponds to a device SIM.
          @hide -->
     <permission android:name="android.permission.REGISTER_SIM_SUBSCRIPTION"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Protects the ability to register any PhoneAccount with
          PhoneAccount#CAPABILITY_CALL_PROVIDER.
          @hide -->
     <permission android:name="android.permission.REGISTER_CALL_PROVIDER"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Protects the ability to register any PhoneAccount with
          PhoneAccount#CAPABILITY_CONNECTION_MANAGER
          @hide -->
     <permission android:name="android.permission.REGISTER_CONNECTION_MANAGER"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by a {@link android.telecom.InCallService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature|privileged
     -->
     <permission android:name="android.permission.BIND_INCALL_SERVICE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by a {@link android.telecom.CallScreeningService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature|privileged
     -->
     <permission android:name="android.permission.BIND_SCREENING_SERVICE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by a {@link android.telecom.ConnectionService},
          to ensure that only the system can bind to it.
@@ -1515,24 +1509,24 @@
          @SystemApi
          @hide -->
     <permission android:name="android.permission.BIND_CONNECTION_SERVICE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by a {@link android.telecom.ConnectionService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature|privileged
     -->
     <permission android:name="android.permission.BIND_TELECOM_CONNECTION_SERVICE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to control the in-call experience.
          @hide -->
     <permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to receive STK related commands.
          @hide -->
     <permission android:name="android.permission.RECEIVE_STK_COMMANDS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- ================================== -->
     <!-- Permissions for sdcard interaction -->
@@ -1542,7 +1536,7 @@
     <!-- @SystemApi Allows an application to write to internal media storage
          @hide  -->
     <permission android:name="android.permission.WRITE_MEDIA_STORAGE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to manage access to documents, usually as part
          of a document picker.
@@ -1552,14 +1546,14 @@
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.MANAGE_DOCUMENTS"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @hide Allows an application to cache content.
          <p>Not for use by third-party applications.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.CACHE_CONTENT"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- ================================== -->
     <!-- Permissions for screenlock         -->
@@ -1570,9 +1564,9 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.DISABLE_KEYGUARD"
-                android:description="@string/permdesc_disableKeyguard"
-                android:label="@string/permlab_disableKeyguard"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_disableKeyguard"
+        android:label="@string/permlab_disableKeyguard"
+        android:protectionLevel="normal" />
 
     <!-- ================================== -->
     <!-- Permissions to access other installed applications  -->
@@ -1581,9 +1575,9 @@
 
     <!-- @deprecated No longer enforced. -->
     <permission android:name="android.permission.GET_TASKS"
-                android:label="@string/permlab_getTasks"
-                android:description="@string/permdesc_getTasks"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_getTasks"
+        android:description="@string/permdesc_getTasks"
+        android:protectionLevel="normal" />
 
     <!-- New version of GET_TASKS that apps can request, since GET_TASKS doesn't really
          give access to task information.  We need this new one because there are
@@ -1596,32 +1590,32 @@
          @hide
          @SystemApi -->
     <permission android:name="android.permission.REAL_GET_TASKS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to start a task from a ActivityManager#RecentTaskInfo.
          @hide -->
     <permission android:name="android.permission.START_TASKS_FROM_RECENTS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allows an application to call APIs that allow it to do interactions
          across the users on the device, using singleton services and
          user-targeted broadcasts.  This permission is not available to
          third party applications. -->
     <permission android:name="android.permission.INTERACT_ACROSS_USERS"
-                android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Fuller form of {@link android.Manifest.permission#INTERACT_ACROSS_USERS}
          that removes restrictions on where broadcasts can be sent and allows other
          types of interactions
          @hide -->
     <permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"
-                android:protectionLevel="signature|installer" />
+        android:protectionLevel="signature|installer" />
 
     <!-- @SystemApi @hide Allows an application to call APIs that allow it to query and manage
          users on the device. This permission is not available to
          third party applications. -->
     <permission android:name="android.permission.MANAGE_USERS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @hide Allows an application to create, remove users and get the list of
          users on the device. Applications holding this permission can only create restricted,
@@ -1634,69 +1628,69 @@
     <!-- @hide Allows an application to set the profile owners and the device owner.
          This permission is not available to third party applications.-->
     <permission android:name="android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS"
-                android:protectionLevel="signature"
-                android:label="@string/permlab_manageProfileAndDeviceOwners"
-                android:description="@string/permdesc_manageProfileAndDeviceOwners" />
+        android:protectionLevel="signature"
+        android:label="@string/permlab_manageProfileAndDeviceOwners"
+        android:description="@string/permdesc_manageProfileAndDeviceOwners" />
 
     <!-- Allows an application to get full detailed information about
          recently running tasks, with full fidelity to the real state.
          @hide -->
     <permission android:name="android.permission.GET_DETAILED_TASKS"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to change the Z-order of tasks.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.REORDER_TASKS"
-                android:label="@string/permlab_reorderTasks"
-                android:description="@string/permdesc_reorderTasks"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_reorderTasks"
+        android:description="@string/permdesc_reorderTasks"
+        android:protectionLevel="normal" />
 
     <!-- @hide Allows an application to change to remove/kill tasks -->
     <permission android:name="android.permission.REMOVE_TASKS"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi @hide Allows an application to create/manage/remove stacks -->
     <permission android:name="android.permission.MANAGE_ACTIVITY_STACKS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to start any activity, regardless of permission
          protection or exported state.
          @hide -->
     <permission android:name="android.permission.START_ANY_ACTIVITY"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @deprecated The {@link android.app.ActivityManager#restartPackage}
         API is no longer supported. -->
     <permission android:name="android.permission.RESTART_PACKAGES"
-                android:label="@string/permlab_killBackgroundProcesses"
-                android:description="@string/permdesc_killBackgroundProcesses"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_killBackgroundProcesses"
+        android:description="@string/permdesc_killBackgroundProcesses"
+        android:protectionLevel="normal" />
 
     <!-- Allows an application to call
         {@link android.app.ActivityManager#killBackgroundProcesses}.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"
-                android:label="@string/permlab_killBackgroundProcesses"
-                android:description="@string/permdesc_killBackgroundProcesses"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_killBackgroundProcesses"
+        android:description="@string/permdesc_killBackgroundProcesses"
+        android:protectionLevel="normal" />
 
     <!-- @SystemApi @hide Allows an application to query process states and current
          OOM adjustment scores.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.GET_PROCESS_STATE_AND_OOM_SCORE"
-                android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi @hide Allows an application to retrieve a package's importance.
          This permission is not available to third party applications. -->
     <permission android:name="android.permission.GET_PACKAGE_IMPORTANCE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows use of PendingIntent.getIntent().
          @hide -->
     <permission android:name="android.permission.GET_INTENT_SENDER_INTENT"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- ================================== -->
     <!-- Permissions affecting the display of other applications  -->
@@ -1719,9 +1713,9 @@
          Settings.canDrawOverlays()}.
          <p>Protection level: signature -->
     <permission android:name="android.permission.SYSTEM_ALERT_WINDOW"
-                android:label="@string/permlab_systemAlertWindow"
-                android:description="@string/permdesc_systemAlertWindow"
-                android:protectionLevel="signature|preinstalled|appop|pre23|development" />
+        android:label="@string/permlab_systemAlertWindow"
+        android:description="@string/permdesc_systemAlertWindow"
+        android:protectionLevel="signature|preinstalled|appop|pre23|development" />
 
     <!-- ================================== -->
     <!-- Permissions affecting the system wallpaper -->
@@ -1732,17 +1726,17 @@
          <p>Protection level: normal
      -->
     <permission android:name="android.permission.SET_WALLPAPER"
-                android:label="@string/permlab_setWallpaper"
-                android:description="@string/permdesc_setWallpaper"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_setWallpaper"
+        android:description="@string/permdesc_setWallpaper"
+        android:protectionLevel="normal" />
 
     <!-- Allows applications to set the wallpaper hints.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.SET_WALLPAPER_HINTS"
-                android:label="@string/permlab_setWallpaperHints"
-                android:description="@string/permdesc_setWallpaperHints"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_setWallpaperHints"
+        android:description="@string/permdesc_setWallpaperHints"
+        android:protectionLevel="normal" />
 
     <!-- ============================================ -->
     <!-- Permissions for changing the system clock -->
@@ -1752,15 +1746,15 @@
     <!-- @SystemApi Allows applications to set the system time.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.SET_TIME"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows applications to set the system time zone.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.SET_TIME_ZONE"
-                android:label="@string/permlab_setTimeZone"
-                android:description="@string/permdesc_setTimeZone"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_setTimeZone"
+        android:description="@string/permdesc_setTimeZone"
+        android:protectionLevel="normal" />
 
     <!-- ==================================================== -->
     <!-- Permissions related to changing status bar   -->
@@ -1771,9 +1765,9 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.EXPAND_STATUS_BAR"
-                android:label="@string/permlab_expandStatusBar"
-                android:description="@string/permdesc_expandStatusBar"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_expandStatusBar"
+        android:description="@string/permdesc_expandStatusBar"
+        android:protectionLevel="normal" />
 
     <!-- ============================================================== -->
     <!-- Permissions related to adding/removing shortcuts from Launcher -->
@@ -1784,17 +1778,17 @@
          <p>Protection level: normal
     -->
     <permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"
-                android:label="@string/permlab_install_shortcut"
-                android:description="@string/permdesc_install_shortcut"
-                android:protectionLevel="normal"/>
+        android:label="@string/permlab_install_shortcut"
+        android:description="@string/permdesc_install_shortcut"
+        android:protectionLevel="normal"/>
 
     <!-- Allows an application to uninstall a shortcut in Launcher.
          <p>Protection level: normal
     -->
     <permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"
-                android:label="@string/permlab_uninstall_shortcut"
-                android:description="@string/permdesc_uninstall_shortcut"
-                android:protectionLevel="normal"/>
+        android:label="@string/permlab_uninstall_shortcut"
+        android:description="@string/permdesc_uninstall_shortcut"
+        android:protectionLevel="normal"/>
 
     <!-- ==================================================== -->
     <!-- Permissions related to accessing sync settings   -->
@@ -1805,25 +1799,25 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.READ_SYNC_SETTINGS"
-                android:description="@string/permdesc_readSyncSettings"
-                android:label="@string/permlab_readSyncSettings"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_readSyncSettings"
+        android:label="@string/permlab_readSyncSettings"
+        android:protectionLevel="normal" />
 
     <!-- Allows applications to write the sync settings.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.WRITE_SYNC_SETTINGS"
-                android:description="@string/permdesc_writeSyncSettings"
-                android:label="@string/permlab_writeSyncSettings"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_writeSyncSettings"
+        android:label="@string/permlab_writeSyncSettings"
+        android:protectionLevel="normal" />
 
     <!-- Allows applications to read the sync stats.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.READ_SYNC_STATS"
-                android:description="@string/permdesc_readSyncStats"
-                android:label="@string/permlab_readSyncStats"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_readSyncStats"
+        android:label="@string/permlab_readSyncStats"
+        android:protectionLevel="normal" />
 
     <!-- ============================================ -->
     <!-- Permissions for low-level system interaction -->
@@ -1832,12 +1826,12 @@
 
     <!-- @SystemApi @hide Change the screen compatibility mode of applications -->
     <permission android:name="android.permission.SET_SCREEN_COMPATIBILITY"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to modify the current configuration, such
          as locale. -->
     <permission android:name="android.permission.CHANGE_CONFIGURATION"
-                android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged|development" />
 
     <!-- Allows an application to read or write the system settings.
 
@@ -1852,51 +1846,51 @@
         <p>Protection level: signature
     -->
     <permission android:name="android.permission.WRITE_SETTINGS"
-                android:label="@string/permlab_writeSettings"
-                android:description="@string/permdesc_writeSettings"
-                android:protectionLevel="signature|preinstalled|appop|pre23" />
+        android:label="@string/permlab_writeSettings"
+        android:description="@string/permdesc_writeSettings"
+        android:protectionLevel="signature|preinstalled|appop|pre23" />
 
     <!-- @SystemApi Allows an application to modify the Google service map.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.WRITE_GSERVICES"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to call
         {@link android.app.ActivityManager#forceStopPackage}.
         @hide -->
     <permission android:name="android.permission.FORCE_STOP_PACKAGES"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allows an application to retrieve the content of the active window
          An active window is the window that has fired an accessibility event. -->
     <permission android:name="android.permission.RETRIEVE_WINDOW_CONTENT"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Modify the global animation scaling factor.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.SET_ANIMATION_SCALE"
-                android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged|development" />
 
     <!-- @deprecated This functionality will be removed in the future; please do
          not use. Allow an application to make its activities persistent. -->
     <permission android:name="android.permission.PERSISTENT_ACTIVITY"
-                android:label="@string/permlab_persistentActivity"
-                android:description="@string/permdesc_persistentActivity"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_persistentActivity"
+        android:description="@string/permdesc_persistentActivity"
+        android:protectionLevel="normal" />
 
     <!-- Allows an application to find out the space used by any package.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.GET_PACKAGE_SIZE"
-                android:label="@string/permlab_getPackageSize"
-                android:description="@string/permdesc_getPackageSize"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_getPackageSize"
+        android:description="@string/permdesc_getPackageSize"
+        android:protectionLevel="normal" />
 
     <!-- @deprecated No longer useful, see
          {@link android.content.pm.PackageManager#addPackageToPreferred}
          for details. -->
     <permission android:name="android.permission.SET_PREFERRED_APPLICATIONS"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to receive the
          {@link android.content.Intent#ACTION_BOOT_COMPLETED} that is
@@ -1912,9 +1906,9 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"
-                android:label="@string/permlab_receiveBootCompleted"
-                android:description="@string/permdesc_receiveBootCompleted"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_receiveBootCompleted"
+        android:description="@string/permdesc_receiveBootCompleted"
+        android:protectionLevel="normal" />
 
     <!-- Allows an application to broadcast sticky intents.  These are
          broadcasts whose data is held by the system after being finished,
@@ -1923,90 +1917,90 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.BROADCAST_STICKY"
-                android:label="@string/permlab_broadcastSticky"
-                android:description="@string/permdesc_broadcastSticky"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_broadcastSticky"
+        android:description="@string/permdesc_broadcastSticky"
+        android:protectionLevel="normal" />
 
     <!-- @SystemApi Allows mounting and unmounting file systems for removable storage.
     <p>Not for use by third-party applications.-->
     <permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows formatting file systems for removable storage.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.MOUNT_FORMAT_FILESYSTEMS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @hide -->
     <permission android:name="android.permission.STORAGE_INTERNAL"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows access to ASEC non-destructive API calls
          @hide  -->
     <permission android:name="android.permission.ASEC_ACCESS"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows creation of ASEC volumes
          @hide  -->
     <permission android:name="android.permission.ASEC_CREATE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows destruction of ASEC volumes
          @hide  -->
     <permission android:name="android.permission.ASEC_DESTROY"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows mount / unmount of ASEC volumes
          @hide  -->
     <permission android:name="android.permission.ASEC_MOUNT_UNMOUNT"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows rename of ASEC volumes
          @hide  -->
     <permission android:name="android.permission.ASEC_RENAME"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows applications to write the apn settings.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.WRITE_APN_SETTINGS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows applications to change network connectivity state.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.CHANGE_NETWORK_STATE"
-                android:description="@string/permdesc_changeNetworkState"
-                android:label="@string/permlab_changeNetworkState"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_changeNetworkState"
+        android:label="@string/permlab_changeNetworkState"
+        android:protectionLevel="normal" />
 
     <!-- Allows an application to clear the caches of all installed
          applications on the device.
          <p>Protection level: system|signature
     -->
     <permission android:name="android.permission.CLEAR_APP_CACHE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to use any media decoder when decoding for playback
          @hide -->
     <permission android:name="android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to install and/or uninstall CA certificates on
          behalf of the user.
          @hide -->
     <permission android:name="android.permission.MANAGE_CA_CERTIFICATES"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to do certain operations needed for
          interacting with the recovery (system update) system.
          @hide -->
     <permission android:name="android.permission.RECOVERY"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows the system to bind to an application's task services
          @hide -->
     <permission android:name="android.permission.BIND_JOB_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
     <uses-permission android:name="android.permission.BIND_JOB_SERVICE"/>
 
     <!-- Allows an application to initiate configuration updates
@@ -2015,12 +2009,7 @@
          it off to the various individual installer components
          @hide -->
     <permission android:name="android.permission.UPDATE_CONFIG"
-                android:protectionLevel="signature|privileged" />
-
-    <!-- Allows the system to reset throttling in shortcut manager.
-         @hide -->
-    <permission android:name="android.permission.RESET_SHORTCUT_MANAGER_THROTTLING"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- ========================================= -->
     <!-- Permissions for special development tools -->
@@ -2030,40 +2019,40 @@
     <!-- @SystemApi Allows an application to read or write the secure system settings.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.WRITE_SECURE_SETTINGS"
-                android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Allows an application to retrieve state dump information from system services.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.DUMP"
-                android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Allows an application to read the low-level system log files.
     <p>Not for use by third-party applications, because
     Log entries can contain the user's private information. -->
     <permission android:name="android.permission.READ_LOGS"
-                android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Configure an application for debugging.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.SET_DEBUG_APP"
-                android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Allows an application to set the maximum number of (not needed)
          application processes that can be running.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.SET_PROCESS_LIMIT"
-                android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Allows an application to control whether activities are immediately
          finished when put in the background.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.SET_ALWAYS_FINISH"
-                android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Allow an application to request that a signal be sent to all persistent processes.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.SIGNAL_PERSISTENT_PROCESSES"
-                android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged|development" />
 
     <!-- ==================================== -->
     <!-- Private permissions                  -->
@@ -2072,34 +2061,34 @@
 
     <!-- @SystemApi Allows access to the list of accounts in the Accounts Service. -->
     <permission android:name="android.permission.GET_ACCOUNTS_PRIVILEGED"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows but does not guarantee access to user passwords at the conclusion of add account
     @hide -->
     <permission android:name="android.permission.GET_PASSWORD"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows applications to RW to diagnostic resources.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.DIAGNOSTIC"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to open, close, or disable the status bar
          and its icons.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.STATUS_BAR"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to be the status bar.  Currently used only by SystemUI.apk
     @hide -->
     <permission android:name="android.permission.STATUS_BAR_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to bind to third party quick settings tiles.
          <p>Should only be requested by the System, should be required by
          TileService declarations.-->
     <permission android:name="android.permission.BIND_QUICK_SETTINGS_TILE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to force a BACK operation on whatever is the
          top activity.
@@ -2107,28 +2096,28 @@
          @hide
     -->
     <permission android:name="android.permission.FORCE_BACK"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to update device statistics.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.UPDATE_DEVICE_STATS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allows an application to collect battery statistics -->
     <permission android:name="android.permission.GET_APP_OPS_STATS"
-                android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Allows an application to update application operation statistics. Not for
          use by third party apps.
          @hide -->
     <permission android:name="android.permission.UPDATE_APP_OPS_STATS"
-                android:protectionLevel="signature|privileged|installer" />
+        android:protectionLevel="signature|privileged|installer" />
 
     <!-- @SystemApi Allows an application to update the user app op restrictions.
          Not for use by third party apps.
          @hide -->
     <permission android:name="android.permission.MANAGE_APP_OPS_RESTRICTIONS"
-                android:protectionLevel="signature|installer" />
+        android:protectionLevel="signature|installer" />
 
     <!-- @SystemApi Allows an application to open windows that are for use by parts
          of the system user interface.
@@ -2136,7 +2125,7 @@
          @hide
     -->
     <permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to manage (create, destroy,
          Z-order) application tokens in the window manager.
@@ -2144,17 +2133,17 @@
          @hide
     -->
     <permission android:name="android.permission.MANAGE_APP_TOKENS"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows System UI to register listeners for events from Window Manager.
          @hide -->
     <permission android:name="android.permission.REGISTER_WINDOW_MANAGER_LISTENERS"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @hide Allows the application to temporarily freeze the screen for a
          full-screen transition. -->
     <permission android:name="android.permission.FREEZE_SCREEN"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to inject user events (keys, touch, trackball)
          into the event stream and deliver them to ANY window.  Without this
@@ -2163,24 +2152,24 @@
          @hide
     -->
     <permission android:name="android.permission.INJECT_EVENTS"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @hide Allows an application to register an input filter which filters the stream
          of user events (keys, touch, trackball) before they are dispatched to any window. -->
     <permission android:name="android.permission.FILTER_EVENTS"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @hide Allows an application to retrieve the window token from the accessibility manager. -->
     <permission android:name="android.permission.RETRIEVE_WINDOW_TOKEN"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @hide Allows an application to collect frame statistics -->
     <permission android:name="android.permission.FRAME_STATS"
-                android:protectionLevel="signature" />
+         android:protectionLevel="signature" />
 
     <!-- @hide Allows an application to temporary enable accessibility on the device. -->
     <permission android:name="android.permission.TEMPORARY_ENABLE_ACCESSIBILITY"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to watch and control how activities are
          started globally in the system.  Only for is in debugging
@@ -2189,13 +2178,13 @@
          @hide
     -->
     <permission android:name="android.permission.SET_ACTIVITY_WATCHER"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to call the activity manager shutdown() API
          to put the higher-level system there into a shutdown state.
          @hide -->
     <permission android:name="android.permission.SHUTDOWN"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to tell the activity manager to temporarily
          stop application switches, putting it into a special mode that
@@ -2203,7 +2192,7 @@
          critical UI such as the home screen.
          @hide -->
     <permission android:name="android.permission.STOP_APP_SWITCHES"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to retrieve private information about
          the current top activity, such as any assist context it can provide.
@@ -2211,42 +2200,42 @@
          @hide
     -->
     <permission android:name="android.permission.GET_TOP_ACTIVITY_INFO"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to retrieve the current state of keys and
          switches.
          <p>Not for use by third-party applications.
          @deprecated The API that used this permission has been removed. -->
     <permission android:name="android.permission.READ_INPUT_STATE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by an {@link android.inputmethodservice.InputMethodService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_INPUT_METHOD"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by an {@link android.media.midi.MidiDeviceService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_MIDI_DEVICE_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by an {@link android.accessibilityservice.AccessibilityService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link android.printservice.PrintService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_PRINT_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link android.printservice.recommendation.RecommendationService},
      to ensure that only the system can bind to it.
@@ -2255,7 +2244,7 @@
      <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_PRINT_RECOMMENDATION_SERVICE"
-                android:protectionLevel="signature" />
+            android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link android.nfc.cardemulation.HostApduService}
          or {@link android.nfc.cardemulation.OffHostApduService} to ensure that only
@@ -2263,65 +2252,65 @@
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_NFC_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by the PrintSpooler to ensure that only the system can bind to it.
          @hide -->
     <permission android:name="android.permission.BIND_PRINT_SPOOLER_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Must be required by the RuntimePermissionPresenterService to ensure
          that only the system can bind to it.
          @hide -->
     <permission android:name="android.permission.BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by a TextService (e.g. SpellCheckerService)
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_TEXT_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link android.net.VpnService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_VPN_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link android.service.wallpaper.WallpaperService},
          to ensure that only the system can bind to it.
          <p>Protection level: system|signature
     -->
     <permission android:name="android.permission.BIND_WALLPAPER"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by a {@link android.service.voice.VoiceInteractionService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_VOICE_INTERACTION"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by hotword enrollment application,
          to ensure that only the system can interact with it.
          @hide <p>Not for use by third-party applications.</p> -->
     <permission android:name="android.permission.MANAGE_VOICE_KEYPHRASES"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by a {@link com.android.media.remotedisplay.RemoteDisplayProvider},
          to ensure that only the system can bind to it.
          @hide -->
     <permission android:name="android.permission.BIND_REMOTE_DISPLAY"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link android.media.tv.TvInputService}
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_TV_INPUT"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi
          Must be required by a {@link com.android.media.tv.remoteprovider.TvRemoteProvider}
@@ -2330,7 +2319,7 @@
          <p>Not for use by third-party applications. </p>
          @hide  -->
     <permission android:name="android.permission.BIND_TV_REMOTE_SERVICE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi
          Must be required for a virtual remote controller for TV.
@@ -2338,32 +2327,32 @@
          <p>Not for use by third-party applications. </p>
          @hide  -->
     <permission android:name="android.permission.TV_VIRTUAL_REMOTE_CONTROLLER"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to modify parental controls
          <p>Not for use by third-party applications.
          @hide -->
     <permission android:name="android.permission.MODIFY_PARENTAL_CONTROLS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by a {@link android.media.routing.MediaRouteService}
          to ensure that only the system can interact with it.
          @hide -->
     <permission android:name="android.permission.BIND_ROUTE_PROVIDER"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by device administration receiver, to ensure that only the
          system can interact with it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_DEVICE_ADMIN"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Required to add or remove another application as a device admin.
          <p>Not for use by third-party applications.
          @hide -->
     <permission android:name="android.permission.MANAGE_DEVICE_ADMINS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows low-level access to setting the orientation (actually
          rotation) of the screen.
@@ -2371,33 +2360,33 @@
          @hide
     -->
     <permission android:name="android.permission.SET_ORIENTATION"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows low-level access to setting the pointer speed.
          <p>Not for use by third-party applications.
          @hide
     -->
     <permission android:name="android.permission.SET_POINTER_SPEED"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows low-level access to setting input device calibration.
          <p>Not for use by normal applications.
          @hide -->
     <permission android:name="android.permission.SET_INPUT_CALIBRATION"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows low-level access to setting the keyboard layout.
          <p>Not for use by third-party applications.
          @hide -->
     <permission android:name="android.permission.SET_KEYBOARD_LAYOUT"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to query tablet mode state and monitor changes
          in it.
          <p>Not for use by third-party applications.
          @hide -->
     <permission android:name="android.permission.TABLET_MODE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to request installing packages. Apps
          targeting APIs greater than 22 must hold this permission in
@@ -2405,41 +2394,41 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"
-                android:label="@string/permlab_requestInstallPackages"
-                android:description="@string/permdesc_requestInstallPackages"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_requestInstallPackages"
+        android:description="@string/permdesc_requestInstallPackages"
+        android:protectionLevel="normal" />
 
     <!-- @SystemApi Allows an application to install packages.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.INSTALL_PACKAGES"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to clear user data.
          <p>Not for use by third-party applications
          @hide
     -->
     <permission android:name="android.permission.CLEAR_APP_USER_DATA"
-                android:protectionLevel="signature|installer" />
+        android:protectionLevel="signature|installer" />
 
     <!-- @hide Allows an application to get the URI permissions
          granted to another application.
          <p>Not for use by third-party applications
     -->
     <permission android:name="android.permission.GET_APP_GRANTED_URI_PERMISSIONS"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @hide Allows an application to clear the URI permissions
          granted to another application.
          <p>Not for use by third-party applications
     -->
     <permission
-            android:name="android.permission.CLEAR_APP_GRANTED_URI_PERMISSIONS"
-            android:protectionLevel="signature" />
+        android:name="android.permission.CLEAR_APP_GRANTED_URI_PERMISSIONS"
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to delete cache files.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.DELETE_CACHE_FILES"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to delete packages.
          <p>Not for use by third-party applications.
@@ -2447,251 +2436,251 @@
          when the application deleting the package is not the same application that installed the
          package. -->
     <permission android:name="android.permission.DELETE_PACKAGES"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to move location of installed package.
          @hide -->
     <permission android:name="android.permission.MOVE_PACKAGE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to change whether an application component (other than its own) is
          enabled or not.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to grant specific permissions.
          @hide -->
     <permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS"
-                android:protectionLevel="signature|installer|verifier" />
+        android:protectionLevel="signature|installer|verifier" />
 
     <!-- @SystemApi Allows an app that has this permission and the permissions to install packages
          to request certain runtime permissions to be granted at installation.
          @hide -->
     <permission android:name="android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS"
-                android:protectionLevel="signature|installer|verifier" />
+        android:protectionLevel="signature|installer|verifier" />
 
     <!-- @SystemApi Allows an application to revoke specific permissions.
         @hide -->
     <permission android:name="android.permission.REVOKE_RUNTIME_PERMISSIONS"
-                android:protectionLevel="signature|installer|verifier" />
+         android:protectionLevel="signature|installer|verifier" />
 
     <!-- @hide Allows an application to observe permission changes. -->
     <permission android:name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to use SurfaceFlinger's low level features.
          <p>Not for use by third-party applications.
          @hide
     -->
     <permission android:name="android.permission.ACCESS_SURFACE_FLINGER"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to take screen shots and more generally
          get access to the frame buffer data.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.READ_FRAME_BUFFER"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to use InputFlinger's low level features.
          @hide -->
     <permission android:name="android.permission.ACCESS_INPUT_FLINGER"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to configure and connect to Wifi displays
          @hide -->
     <permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to control low-level features of Wifi displays
          such as opening an RTSP socket.  This permission should only be used
          by the display manager.
          @hide -->
     <permission android:name="android.permission.CONTROL_WIFI_DISPLAY"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to control the color transforms applied to
          displays system-wide.
          <p>Not for use by third-party applications.</p>
          @hide -->
     <permission android:name="android.permission.CONFIGURE_DISPLAY_COLOR_TRANSFORM"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to control VPN.
          <p>Not for use by third-party applications.</p>
          @hide -->
     <permission android:name="android.permission.CONTROL_VPN"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
     <uses-permission android:name="android.permission.CONTROL_VPN" />
 
     <!-- @SystemApi Allows an application to capture audio output.
          <p>Not for use by third-party applications.</p> -->
     <permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to capture audio for hotword detection.
          <p>Not for use by third-party applications.</p>
          @hide -->
     <permission android:name="android.permission.CAPTURE_AUDIO_HOTWORD"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to modify audio routing and override policy decisions.
          <p>Not for use by third-party applications.</p>
          @hide -->
     <permission android:name="android.permission.MODIFY_AUDIO_ROUTING"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to capture video output.
          <p>Not for use by third-party applications.</p> -->
     <permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to capture secure video output.
          <p>Not for use by third-party applications.</p> -->
     <permission android:name="android.permission.CAPTURE_SECURE_VIDEO_OUTPUT"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to know what content is playing and control its playback.
          <p>Not for use by third-party applications due to privacy of media consumption</p>  -->
     <permission android:name="android.permission.MEDIA_CONTENT_CONTROL"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Required to be able to disable the device (very dangerous!).
          <p>Not for use by third-party applications.
          @hide
     -->
     <permission android:name="android.permission.BRICK"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Required to be able to reboot the device.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.REBOOT"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
-    <!-- @SystemApi Allows low-level access to power management.
-         <p>Not for use by third-party applications.
-         @hide
-     -->
-    <permission android:name="android.permission.DEVICE_POWER"
-                android:protectionLevel="signature" />
+   <!-- @SystemApi Allows low-level access to power management.
+        <p>Not for use by third-party applications.
+        @hide
+    -->
+   <permission android:name="android.permission.DEVICE_POWER"
+        android:protectionLevel="signature" />
 
-    <!-- Allows access to the PowerManager.userActivity function.
-    <p>Not for use by third-party applications. @hide @SystemApi -->
+   <!-- Allows access to the PowerManager.userActivity function.
+   <p>Not for use by third-party applications. @hide @SystemApi -->
     <permission android:name="android.permission.USER_ACTIVITY"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
-    <!-- @hide Allows low-level access to tun tap driver -->
+   <!-- @hide Allows low-level access to tun tap driver -->
     <permission android:name="android.permission.NET_TUNNELING"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Run as a manufacturer test application, running as the root user.
          Only available when the device is running in manufacturer test mode.
          <p>Not for use by third-party applications.
     -->
     <permission android:name="android.permission.FACTORY_TEST"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to broadcast a notification that an application
          package has been removed.
          <p>Not for use by third-party applications.
     -->
     <permission android:name="android.permission.BROADCAST_PACKAGE_REMOVED"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to broadcast an SMS receipt notification.
          <p>Not for use by third-party applications.
     -->
     <permission android:name="android.permission.BROADCAST_SMS"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to broadcast a WAP PUSH receipt notification.
          <p>Not for use by third-party applications.
     -->
     <permission android:name="android.permission.BROADCAST_WAP_PUSH"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to broadcast privileged networking requests.
          <p>Not for use by third-party applications. @hide -->
     <permission android:name="android.permission.BROADCAST_NETWORK_PRIVILEGED"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Not for use by third-party applications. -->
     <permission android:name="android.permission.MASTER_CLEAR"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to call any phone number, including emergency
          numbers, without going through the Dialer user interface for the user
          to confirm the call being placed.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.CALL_PRIVILEGED"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to perform CDMA OTA provisioning @hide -->
     <permission android:name="android.permission.PERFORM_CDMA_PROVISIONING"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to perform SIM Activation @hide -->
     <permission android:name="android.permission.PERFORM_SIM_ACTIVATION"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows enabling/disabling location update notifications from
          the radio.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.CONTROL_LOCATION_UPDATES"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows read/write access to the "properties" table in the checkin
          database, to change values that get uploaded.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.ACCESS_CHECKIN_PROPERTIES"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to collect component usage
          statistics
          <p>Declaring the permission implies intention to use the API and the user of the
          device can grant permission through the Settings application. -->
     <permission android:name="android.permission.PACKAGE_USAGE_STATS"
-                android:protectionLevel="signature|privileged|development|appop" />
+        android:protectionLevel="signature|privileged|development|appop" />
     <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
 
     <!-- @hide Allows an application to change the app idle state of an app.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.CHANGE_APP_IDLE_STATE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @hide @SystemApi Allows an application to temporarily whitelist an inactive app to
          access the network and acquire wakelocks.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Permission an application must hold in order to use
          {@link android.provider.Settings#ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS}.
          This is a normal permission: an app requesting it will always be granted the
          permission, without the user needing to approve or see it. -->
     <permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"
-                android:protectionLevel="normal" />
+        android:protectionLevel="normal" />
 
     <!-- @SystemApi Allows an application to collect battery statistics -->
     <permission android:name="android.permission.BATTERY_STATS"
-                android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Allows an application to control the backup and restore process.
     <p>Not for use by third-party applications.
          @hide pending API council -->
     <permission android:name="android.permission.BACKUP"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows a package to launch the secure full-backup confirmation UI.
          ONLY the system process may hold this permission.
          @hide -->
     <permission android:name="android.permission.CONFIRM_FULL_BACKUP"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Must be required by a {@link android.widget.RemoteViewsService},
          to ensure that only the system can bind to it. -->
     <permission android:name="android.permission.BIND_REMOTEVIEWS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to tell the AppWidget service which application
          can access AppWidget's data.  The normal user flow is that a user
@@ -2700,25 +2689,25 @@
          An application that has this permission should honor that contract.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.BIND_APPWIDGET"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Private permission, to restrict who can bring up a dialog to add a new
          keyguard widget
          @hide -->
     <permission android:name="android.permission.BIND_KEYGUARD_APPWIDGET"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Internal permission allowing an application to query/set which
          applications can bind AppWidgets.
          @hide -->
     <permission android:name="android.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows applications to change the background data setting.
     <p>Not for use by third-party applications.
          @hide pending API council -->
     <permission android:name="android.permission.CHANGE_BACKGROUND_DATA_SETTING"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi This permission can be used on content providers to allow the global
          search system to access their data.  Typically it used when the
@@ -2729,7 +2718,7 @@
          it is used by applications to protect themselves from everyone else
          besides global search. -->
     <permission android:name="android.permission.GLOBAL_SEARCH"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Internal permission protecting access to the global search
          system: ensures that only the system can access the provider
@@ -2739,33 +2728,33 @@
          ranking).
          @hide -->
     <permission android:name="android.permission.GLOBAL_SEARCH_CONTROL"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Internal permission to allows an application to read indexable data.
         @hide -->
     <permission android:name="android.permission.READ_SEARCH_INDEXABLES"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows applications to set a live wallpaper.
          @hide XXX Change to signature once the picker is moved to its
          own apk as Ghod Intended. -->
     <permission android:name="android.permission.SET_WALLPAPER_COMPONENT"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows applications to read dream settings and dream state.
          @hide -->
     <permission android:name="android.permission.READ_DREAM_STATE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows applications to write dream settings, and start or stop dreaming.
          @hide -->
     <permission android:name="android.permission.WRITE_DREAM_STATE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allow an application to read and write the cache partition.
          @hide -->
     <permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by default container service so that only
          the system can bind to it and use it to copy
@@ -2773,67 +2762,67 @@
          accessible to the system.
          @hide -->
     <permission android:name="android.permission.COPY_PROTECTED_DATA"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Internal permission protecting access to the encryption methods
         @hide
     -->
     <permission android:name="android.permission.CRYPT_KEEPER"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to read historical network usage for
          specific networks and applications. @hide -->
     <permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to manage network policies (such as warning and disable
          limits) and to define application-specific rules. @hide -->
     <permission android:name="android.permission.MANAGE_NETWORK_POLICY"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to account its network traffic against other UIDs. Used
          by system services like download manager and media server. Not for use by
          third party apps. @hide -->
     <permission android:name="android.permission.MODIFY_NETWORK_ACCOUNTING"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- C2DM permission.
          @hide Used internally.
      -->
     <permission android:name="android.intent.category.MASTER_CLEAR.permission.C2D_MESSAGE"
-                android:protectionLevel="signature" />
+          android:protectionLevel="signature" />
     <uses-permission android:name="android.intent.category.MASTER_CLEAR.permission.C2D_MESSAGE"/>
 
     <!-- @SystemApi @hide Package verifier needs to have this permission before the PackageManager will
          trust it to verify packages.
     -->
     <permission android:name="android.permission.PACKAGE_VERIFICATION_AGENT"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by package verifier receiver, to ensure that only the
          system can interact with it.
          @hide
     -->
     <permission android:name="android.permission.BIND_PACKAGE_VERIFIER"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi @hide Intent filter verifier needs to have this permission before the
          PackageManager will trust it to verify intent filters.
     -->
     <permission android:name="android.permission.INTENT_FILTER_VERIFICATION_AGENT"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by intent filter verifier receiver, to ensure that only the
          system can interact with it.
          @hide
     -->
     <permission android:name="android.permission.BIND_INTENT_FILTER_VERIFIER"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows applications to access serial ports via the SerialManager.
          @hide -->
     <permission android:name="android.permission.SERIAL_PORT"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows the holder to access content providers from outside an ApplicationThread.
          This permission is enforced by the ActivityManagerService on the corresponding APIs,
@@ -2842,27 +2831,27 @@
          @hide
     -->
     <permission android:name="android.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to hold an UpdateLock, recommending that a headless
          OTA reboot *not* occur while the lock is held.
          @hide -->
     <permission android:name="android.permission.UPDATE_LOCK"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to read the current set of notifications, including
          any metadata and intents attached.
          @hide -->
     <permission android:name="android.permission.ACCESS_NOTIFICATIONS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Marker permission for applications that wish to access notification policy.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY"
-                android:description="@string/permdesc_access_notification_policy"
-                android:label="@string/permlab_access_notification_policy"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_access_notification_policy"
+        android:label="@string/permlab_access_notification_policy"
+        android:protectionLevel="normal" />
 
     <!-- Allows modification of do not disturb rules and policies. Only allowed for system
         processes.
@@ -2873,42 +2862,42 @@
     <!-- Allows access to keyguard secure storage.  Only allowed for system processes.
         @hide -->
     <permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows managing (adding, removing) fingerprint templates. Reserved for the system. @hide -->
     <permission android:name="android.permission.MANAGE_FINGERPRINT"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an app to reset fingerprint attempt counter. Reserved for the system. @hide -->
     <permission android:name="android.permission.RESET_FINGERPRINT_LOCKOUT"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to control keyguard.  Only allowed for system processes.
         @hide -->
     <permission android:name="android.permission.CONTROL_KEYGUARD"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to listen to trust changes.  Only allowed for system processes.
         @hide -->
     <permission android:name="android.permission.TRUST_LISTENER"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to provide a trust agent.
          @hide For security reasons, this is a platform-only permission. -->
     <permission android:name="android.permission.PROVIDE_TRUST_AGENT"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to launch the trust agent settings activity.
         @hide -->
     <permission android:name="android.permission.LAUNCH_TRUST_AGENT_SETTINGS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Must be required by an {@link
         android.service.trust.TrustAgentService},
         to ensure that only the system can bind to it.
         @hide -->
     <permission android:name="android.permission.BIND_TRUST_AGENT"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by an {@link
          android.service.notification.NotificationListenerService},
@@ -2916,7 +2905,7 @@
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by an {@link
          android.service.notification.NotificationRankerService         to ensure that only the system can bind to it.
@@ -2924,7 +2913,7 @@
          @hide This is not a third-party API (intended for system apps). -->
     -->
     <permission android:name="android.permission.BIND_NOTIFICATION_RANKER_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link
          android.service.chooser.ChooserTargetService}, to ensure that
@@ -2932,7 +2921,7 @@
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_CHOOSER_TARGET_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link
          android.service.notification.ConditionProviderService},
@@ -2940,57 +2929,57 @@
          <p>Protection level: signature
          -->
     <permission android:name="android.permission.BIND_CONDITION_PROVIDER_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by an {@link android.service.dreams.DreamService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_DREAM_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to call into a carrier setup flow. It is up to the
          carrier setup application to enforce that this permission is required
          @hide This is not a third-party API (intended for OEMs and system apps). -->
     <permission android:name="android.permission.INVOKE_CARRIER_SETUP"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to listen for network condition observations.
          @hide This is not a third-party API (intended for system apps). -->
     <permission android:name="android.permission.ACCESS_NETWORK_CONDITIONS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to provision and access DRM certificates
          @hide This is not a third-party API (intended for system apps). -->
     <permission android:name="android.permission.ACCESS_DRM_CERTIFICATES"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Api Allows an application to manage media projection sessions.
          @hide This is not a third-party API (intended for system apps). -->
     <permission android:name="android.permission.MANAGE_MEDIA_PROJECTION"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to read install sessions
          @hide This is not a third-party API (intended for system apps). -->
     <permission android:name="android.permission.READ_INSTALL_SESSIONS"
-                android:label="@string/permlab_readInstallSessions"
-                android:description="@string/permdesc_readInstallSessions"
-                android:protectionLevel="normal"/>
+        android:label="@string/permlab_readInstallSessions"
+        android:description="@string/permdesc_readInstallSessions"
+        android:protectionLevel="normal"/>
 
     <!-- @SystemApi Allows an application to remove DRM certificates
          @hide This is not a third-party API (intended for system apps). -->
     <permission android:name="android.permission.REMOVE_DRM_CERTIFICATES"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @deprecated Use {@link android.Manifest.permission#BIND_CARRIER_SERVICES} instead -->
     <permission android:name="android.permission.BIND_CARRIER_MESSAGING_SERVICE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to interact with the currently active
          {@link android.service.voice.VoiceInteractionService}.
          @hide -->
     <permission android:name="android.permission.ACCESS_VOICE_INTERACTION_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- The system process that is allowed to bind to services in carrier apps will
          have this permission. Carrier apps should use this permission to protect
@@ -2998,9 +2987,9 @@
          <p>Protection level: system|signature
     -->
     <permission android:name="android.permission.BIND_CARRIER_SERVICES"
-                android:label="@string/permlab_bindCarrierServices"
-                android:description="@string/permdesc_bindCarrierServices"
-                android:protectionLevel="signature|privileged" />
+        android:label="@string/permlab_bindCarrierServices"
+        android:description="@string/permdesc_bindCarrierServices"
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to query whether DO_NOT_ASK_CREDENTIALS_ON_BOOT
          flag is set.
@@ -3046,7 +3035,7 @@
     <!-- Allows the holder to access the ephemeral applications on the device.
     @hide -->
     <permission android:name="android.permission.ACCESS_EPHEMERAL_APPS"
-                android:protectionLevel="signature" />
+            android:protectionLevel="signature" />
 
     <!-- Allows receiving the usage of media resource e.g. video/audio codec and
          graphic memory.
@@ -3058,7 +3047,7 @@
          APIs given by {@link SoundTriggerManager}.
          @hide <p>Not for use by third-party applications.</p> -->
     <permission android:name="android.permission.MANAGE_SOUND_TRIGGER"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows trusted applications to dispatch managed provisioning message to Managed
          Provisioning app. If requesting app does not have permission, it will be ignored.
@@ -3082,17 +3071,17 @@
          the system can bind to it.
          <p>Protection level: signature -->
     <permission android:name="android.permission.BIND_VR_LISTENER_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Required to make calls to {@link android.service.vr.IVrManager}.
          @hide -->
     <permission android:name="android.permission.ACCESS_VR_MANAGER"
-                android:protectionLevel="signature" />
+            android:protectionLevel="signature" />
 
     <!-- Allows an application to whitelist tasks during lock task mode
          @hide <p>Not for use by third-party applications.</p> -->
     <permission android:name="android.permission.UPDATE_LOCK_TASK_PACKAGES"
-                android:protectionLevel="signature|setup" />
+        android:protectionLevel="signature|setup" />
 
     <!-- @SystemApi Allows an application to replace the app name displayed alongside notifications
          in the N-release and later.
@@ -3113,13 +3102,12 @@
                  android:defaultToDeviceProtectedStorage="true"
                  android:directBootAware="true">
         <activity android:name="com.android.internal.app.ChooserActivity"
-                  android:theme="@style/Theme.DeviceDefault.Resolver"
-                  android:finishOnCloseSystemDialogs="true"
-                  android:excludeFromRecents="true"
-                  android:documentLaunchMode="never"
-                  android:relinquishTaskIdentity="true"
-                  android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
-                  android:process=":ui">
+                android:theme="@style/Theme.DeviceDefault.Resolver"
+                android:finishOnCloseSystemDialogs="true"
+                android:excludeFromRecents="true"
+                android:documentLaunchMode="never"
+                android:relinquishTaskIdentity="true"
+                android:process=":ui">
             <intent-filter>
                 <action android:name="android.intent.action.CHOOSER" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -3127,102 +3115,102 @@
             </intent-filter>
         </activity>
         <activity android:name="com.android.internal.app.IntentForwarderActivity"
-                  android:finishOnCloseSystemDialogs="true"
-                  android:theme="@style/Theme.NoDisplay"
-                  android:excludeFromRecents="true"
-                  android:label="@string/user_owner_label"
-                  android:exported="true"
-        >
+                android:finishOnCloseSystemDialogs="true"
+                android:theme="@style/Theme.NoDisplay"
+                android:excludeFromRecents="true"
+                android:label="@string/user_owner_label"
+                android:exported="true"
+                >
         </activity>
         <activity-alias android:name="com.android.internal.app.ForwardIntentToParent"
-                        android:targetActivity="com.android.internal.app.IntentForwarderActivity"
-                        android:exported="true"
-                        android:label="@string/user_owner_label">
+                android:targetActivity="com.android.internal.app.IntentForwarderActivity"
+                android:exported="true"
+                android:label="@string/user_owner_label">
         </activity-alias>
         <activity-alias android:name="com.android.internal.app.ForwardIntentToManagedProfile"
-                        android:targetActivity="com.android.internal.app.IntentForwarderActivity"
-                        android:icon="@drawable/ic_corp_icon"
-                        android:exported="true"
-                        android:label="@string/managed_profile_label">
+                android:targetActivity="com.android.internal.app.IntentForwarderActivity"
+                android:icon="@drawable/ic_corp_icon"
+                android:exported="true"
+                android:label="@string/managed_profile_label">
         </activity-alias>
         <activity android:name="com.android.internal.app.HeavyWeightSwitcherActivity"
-                  android:theme="@style/Theme.Material.Light.Dialog"
-                  android:label="@string/heavy_weight_switcher_title"
-                  android:finishOnCloseSystemDialogs="true"
-                  android:excludeFromRecents="true"
-                  android:process=":ui">
+                android:theme="@style/Theme.Material.Light.Dialog"
+                android:label="@string/heavy_weight_switcher_title"
+                android:finishOnCloseSystemDialogs="true"
+                android:excludeFromRecents="true"
+                android:process=":ui">
         </activity>
         <activity android:name="com.android.internal.app.PlatLogoActivity"
-                  android:theme="@style/Theme.Wallpaper.NoTitleBar.Fullscreen"
-                  android:configChanges="orientation|keyboardHidden"
-                  android:process=":ui">
+                android:theme="@style/Theme.Wallpaper.NoTitleBar.Fullscreen"
+                android:configChanges="orientation|keyboardHidden"
+                android:process=":ui">
         </activity>
         <activity android:name="com.android.internal.app.DisableCarModeActivity"
-                  android:theme="@style/Theme.NoDisplay"
-                  android:excludeFromRecents="true"
-                  android:process=":ui">
+                android:theme="@style/Theme.NoDisplay"
+                android:excludeFromRecents="true"
+                android:process=":ui">
         </activity>
         <activity android:name="com.android.internal.app.DumpHeapActivity"
-                  android:theme="@style/Theme.Translucent.NoTitleBar"
-                  android:label="@string/dump_heap_title"
-                  android:finishOnCloseSystemDialogs="true"
-                  android:noHistory="true"
-                  android:excludeFromRecents="true"
-                  android:process=":ui">
+                android:theme="@style/Theme.Translucent.NoTitleBar"
+                android:label="@string/dump_heap_title"
+                android:finishOnCloseSystemDialogs="true"
+                android:noHistory="true"
+                android:excludeFromRecents="true"
+                android:process=":ui">
         </activity>
         <provider android:name="com.android.server.am.DumpHeapProvider"
-                  android:authorities="com.android.server.heapdump"
-                  android:grantUriPermissions="true"
-                  android:multiprocess="false"
-                  android:singleUser="true" />
+                android:authorities="com.android.server.heapdump"
+                android:grantUriPermissions="true"
+                android:multiprocess="false"
+                android:singleUser="true" />
 
         <activity android:name="android.accounts.ChooseAccountActivity"
-                  android:excludeFromRecents="true"
-                  android:exported="true"
-                  android:theme="@style/Theme.Material.Light.Dialog"
-                  android:label="@string/choose_account_label"
-                  android:process=":ui">
+                android:excludeFromRecents="true"
+                android:exported="true"
+                android:theme="@style/Theme.Material.Light.Dialog"
+                android:label="@string/choose_account_label"
+                android:process=":ui">
         </activity>
 
         <activity android:name="android.accounts.ChooseTypeAndAccountActivity"
-                  android:excludeFromRecents="true"
-                  android:exported="true"
-                  android:theme="@style/Theme.Material.Light.Dialog"
-                  android:label="@string/choose_account_label"
-                  android:process=":ui">
+                android:excludeFromRecents="true"
+                android:exported="true"
+                android:theme="@style/Theme.Material.Light.Dialog"
+                android:label="@string/choose_account_label"
+                android:process=":ui">
         </activity>
 
         <activity android:name="android.accounts.ChooseAccountTypeActivity"
-                  android:excludeFromRecents="true"
-                  android:theme="@style/Theme.Material.Light.Dialog"
-                  android:label="@string/choose_account_label"
-                  android:process=":ui">
+                android:excludeFromRecents="true"
+                android:theme="@style/Theme.Material.Light.Dialog"
+                android:label="@string/choose_account_label"
+                android:process=":ui">
         </activity>
 
         <activity android:name="android.accounts.CantAddAccountActivity"
-                  android:excludeFromRecents="true"
-                  android:exported="true"
-                  android:theme="@style/Theme.Material.Light.Dialog.NoActionBar"
-                  android:process=":ui">
+                android:excludeFromRecents="true"
+                android:exported="true"
+                android:theme="@style/Theme.Material.Light.Dialog.NoActionBar"
+                android:process=":ui">
         </activity>
 
         <activity android:name="android.accounts.GrantCredentialsPermissionActivity"
-                  android:excludeFromRecents="true"
-                  android:exported="true"
-                  android:theme="@style/Theme.Material.Light.DialogWhenLarge"
-                  android:process=":ui">
+                android:excludeFromRecents="true"
+                android:exported="true"
+                android:theme="@style/Theme.Material.Light.DialogWhenLarge"
+                android:process=":ui">
         </activity>
 
         <activity android:name="android.content.SyncActivityTooManyDeletes"
-                  android:theme="@style/Theme.Material.Light.Dialog"
-                  android:label="@string/sync_too_many_deletes"
-                  android:process=":ui">
+               android:theme="@style/Theme.Material.Light.Dialog"
+               android:label="@string/sync_too_many_deletes"
+               android:process=":ui">
         </activity>
 
         <activity android:name="com.android.internal.app.ShutdownActivity"
-                  android:permission="android.permission.SHUTDOWN"
-                  android:theme="@style/Theme.NoDisplay"
-                  android:excludeFromRecents="true">
+            android:permission="android.permission.SHUTDOWN"
+            android:theme="@style/Theme.NoDisplay"
+            android:excludeFromRecents="true">
             <intent-filter>
                 <action android:name="android.intent.action.ACTION_REQUEST_SHUTDOWN" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -3234,9 +3222,9 @@
         </activity>
 
         <activity android:name="com.android.internal.app.NetInitiatedActivity"
-                  android:theme="@style/Theme.Material.Light.Dialog.Alert"
-                  android:excludeFromRecents="true"
-                  android:process=":ui">
+                android:theme="@style/Theme.Material.Light.Dialog.Alert"
+                android:excludeFromRecents="true"
+                android:process=":ui">
         </activity>
 
         <activity android:name="com.android.internal.app.SystemUserHomeActivity"
@@ -3253,9 +3241,9 @@
         <!-- Activity to prompt user if it's ok to create a new user sandbox for a
              specified account. -->
         <activity android:name="com.android.internal.app.ConfirmUserCreationActivity"
-                  android:excludeFromRecents="true"
-                  android:process=":ui"
-                  android:theme="@style/Theme.Material.Light.Dialog.Alert">
+                android:excludeFromRecents="true"
+                android:process=":ui"
+                android:theme="@style/Theme.Material.Light.Dialog.Alert">
             <intent-filter android:priority="1000">
                 <action android:name="android.os.action.CREATE_USER" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -3263,20 +3251,20 @@
         </activity>
 
         <activity android:name="com.android.internal.app.UnlaunchableAppActivity"
-                  android:theme="@style/Theme.Material.Light.Dialog.Alert"
-                  android:excludeFromRecents="true"
-                  android:process=":ui">
+                android:theme="@style/Theme.Material.Light.Dialog.Alert"
+                android:excludeFromRecents="true"
+                android:process=":ui">
         </activity>
 
         <receiver android:name="com.android.server.BootReceiver"
-                  android:systemUserOnly="true">
+                android:systemUserOnly="true">
             <intent-filter android:priority="1000">
                 <action android:name="android.intent.action.BOOT_COMPLETED" />
             </intent-filter>
         </receiver>
 
         <receiver android:name="com.android.server.updates.CertPinInstallReceiver"
-                  android:permission="android.permission.UPDATE_CONFIG">
+                android:permission="android.permission.UPDATE_CONFIG">
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_PINS" />
                 <data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3284,7 +3272,7 @@
         </receiver>
 
         <receiver android:name="com.android.server.updates.IntentFirewallInstallReceiver"
-                  android:permission="android.permission.UPDATE_CONFIG">
+                android:permission="android.permission.UPDATE_CONFIG">
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_INTENT_FIREWALL" />
                 <data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3292,7 +3280,7 @@
         </receiver>
 
         <receiver android:name="com.android.server.updates.SmsShortCodesInstallReceiver"
-                  android:permission="android.permission.UPDATE_CONFIG">
+                android:permission="android.permission.UPDATE_CONFIG">
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_SMS_SHORT_CODES" />
                 <data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3300,7 +3288,7 @@
         </receiver>
 
         <receiver android:name="com.android.server.updates.ApnDbInstallReceiver"
-                  android:permission="android.permission.UPDATE_CONFIG">
+                android:permission="android.permission.UPDATE_CONFIG">
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_APN_DB" />
                 <data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3308,7 +3296,7 @@
         </receiver>
 
         <receiver android:name="com.android.server.updates.CarrierProvisioningUrlsInstallReceiver"
-                  android:permission="android.permission.UPDATE_CONFIG">
+                android:permission="android.permission.UPDATE_CONFIG">
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_CARRIER_PROVISIONING_URLS" />
                 <data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3316,23 +3304,15 @@
         </receiver>
 
         <receiver android:name="com.android.server.updates.TzDataInstallReceiver"
-                  android:permission="android.permission.UPDATE_CONFIG">
+                android:permission="android.permission.UPDATE_CONFIG">
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_TZDATA" />
                 <data android:scheme="content" android:host="*" android:mimeType="*/*" />
             </intent-filter>
         </receiver>
 
-        <receiver android:name="com.android.server.updates.SELinuxPolicyInstallReceiver"
-                  android:permission="android.permission.UPDATE_CONFIG">
-            <intent-filter>
-                <action android:name="android.intent.action.UPDATE_SEPOLICY" />
-                <data android:scheme="content" android:host="*" android:mimeType="*/*" />
-            </intent-filter>
-        </receiver>
-
         <receiver android:name="com.android.server.MasterClearReceiver"
-                  android:permission="android.permission.MASTER_CLEAR">
+            android:permission="android.permission.MASTER_CLEAR">
             <intent-filter
                     android:priority="100" >
                 <!-- For Checkin, Settings, etc.: action=MASTER_CLEAR -->
@@ -3345,12 +3325,12 @@
         </receiver>
 
         <service android:name="android.hardware.location.GeofenceHardwareService"
-                 android:permission="android.permission.LOCATION_HARDWARE"
-                 android:exported="false" />
+            android:permission="android.permission.LOCATION_HARDWARE"
+            android:exported="false" />
 
         <service android:name="com.android.internal.backup.LocalTransportService"
-                 android:permission="android.permission.CONFIRM_FULL_BACKUP"
-                 android:exported="false">
+                android:permission="android.permission.CONFIRM_FULL_BACKUP"
+                android:exported="false">
             <intent-filter>
                 <action android:name="android.backup.TRANSPORT_HOST" />
             </intent-filter>
@@ -3375,9 +3355,9 @@
         </service>
 
         <service
-                android:name="com.android.server.pm.BackgroundDexOptService"
-                android:exported="true"
-                android:permission="android.permission.BIND_JOB_SERVICE">
+            android:name="com.android.server.pm.BackgroundDexOptService"
+            android:exported="true"
+            android:permission="android.permission.BIND_JOB_SERVICE">
         </service>
 
     </application>
diff --git a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
index e8de02d..7406645 100644
--- a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
+++ b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
@@ -106,7 +106,7 @@
 
         // OEMs cannot define permissions in the platform namespace
         for (String permission : declaredPermissionsMap.keySet()) {
-            assertFalse("Cannot define permission " + permission + " in android namespace",
+            assertFalse("Cannot define permission in android namespace",
                     permission.startsWith(PLATFORM_ROOT_NAMESPACE));
         }
 
diff --git a/tests/tests/print/Android.mk b/tests/tests/print/Android.mk
index bceaacc..d0c1a81 100644
--- a/tests/tests/print/Android.mk
+++ b/tests/tests/print/Android.mk
@@ -27,7 +27,7 @@
 
 LOCAL_PACKAGE_NAME := CtsPrintTestCases
 
-LOCAL_STATIC_JAVA_LIBRARIES := mockito-target ctstestrunner ub-uiautomator ctsdeviceutil
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target ctstestrunner ub-uiautomator ctsdeviceutil android-support-test
 
 LOCAL_SDK_VERSION := test_current
 
diff --git a/tests/tests/print/src/android/print/cts/AppPrintInterfaceTest.java b/tests/tests/print/src/android/print/cts/AppPrintInterfaceTest.java
new file mode 100644
index 0000000..98434bb
--- /dev/null
+++ b/tests/tests/print/src/android/print/cts/AppPrintInterfaceTest.java
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.print.cts;
+
+import android.content.Context;
+import android.os.ParcelFileDescriptor;
+import android.print.PageRange;
+import android.print.PrintAttributes;
+import android.print.PrintDocumentAdapter;
+import android.print.PrintDocumentInfo;
+import android.print.PrintJob;
+import android.print.PrintJobInfo;
+import android.print.PrintManager;
+import android.print.PrinterCapabilitiesInfo;
+import android.print.PrinterId;
+import android.print.PrinterInfo;
+import android.print.cts.services.FirstPrintService;
+import android.print.cts.services.PrintServiceCallbacks;
+import android.print.cts.services.PrinterDiscoverySessionCallbacks;
+import android.print.cts.services.SecondPrintService;
+import android.print.cts.services.StubbablePrinterDiscoverySession;
+import android.support.annotation.NonNull;
+
+import java.util.ArrayList;
+
+/**
+ * Test interface from the application to the print service.
+ */
+public class AppPrintInterfaceTest extends BasePrintTest {
+    private static final String TEST_PRINTER = "Test printer";
+
+    private static final PrintAttributes.Resolution TWO_HUNDRED_DPI = new PrintAttributes.Resolution(
+            "200x200", "200dpi", 200,
+            200);
+
+    /**
+     * @return The print manager
+     */
+    private @NonNull PrintManager getPrintManager() {
+        return (PrintManager) getActivity().getSystemService(Context.PRINT_SERVICE);
+    }
+
+    /**
+     * Start printing
+     *
+     * @param adapter      Adapter supplying data to print
+     * @param printJobName The name of the print job
+     */
+    protected void print(@NonNull PrintDocumentAdapter adapter, @NonNull String printJobName) {
+        // Initiate printing as if coming from the app.
+        getInstrumentation()
+                .runOnMainSync(() -> getPrintManager().print(printJobName, adapter, null));
+    }
+
+    /**
+     * Create a mock {@link PrintDocumentAdapter} that provides one empty page.
+     *
+     * @return The mock adapter
+     */
+    private @NonNull PrintDocumentAdapter createMockPrintDocumentAdapter() {
+        final PrintAttributes[] printAttributes = new PrintAttributes[1];
+
+        return createMockPrintDocumentAdapter(
+                invocation -> {
+                    printAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
+                    PrintDocumentAdapter.LayoutResultCallback callback =
+                            (PrintDocumentAdapter.LayoutResultCallback) invocation
+                                    .getArguments()[3];
+
+                    callback.onLayoutFinished(new PrintDocumentInfo.Builder("doc")
+                            .setPageCount(1).build(), false);
+
+                    onLayoutCalled();
+                    return null;
+                }, invocation -> {
+                    Object[] args = invocation.getArguments();
+                    PageRange[] pages = (PageRange[]) args[0];
+                    ParcelFileDescriptor fd = (ParcelFileDescriptor) args[1];
+                    PrintDocumentAdapter.WriteResultCallback callback = (PrintDocumentAdapter.WriteResultCallback) args[3];
+
+                    writeBlankPages(printAttributes[0], fd, pages[0].getStart(), pages[0].getEnd());
+                    fd.close();
+                    callback.onWriteFinished(pages);
+                    return null;
+                }, invocation -> null);
+    }
+
+    /**
+     * Create a mock {@link PrinterDiscoverySessionCallbacks} that discovers a simple test printer.
+     *
+     * @return The mock session callbacks
+     */
+    private @NonNull PrinterDiscoverySessionCallbacks createFirstMockPrinterDiscoverySessionCallbacks() {
+        return createMockPrinterDiscoverySessionCallbacks(invocation -> {
+            StubbablePrinterDiscoverySession session = ((PrinterDiscoverySessionCallbacks) invocation
+                    .getMock()).getSession();
+
+            if (session.getPrinters().isEmpty()) {
+                PrinterId printerId = session.getService().generatePrinterId(TEST_PRINTER);
+                PrinterInfo.Builder printer = new PrinterInfo.Builder(
+                        session.getService().generatePrinterId(TEST_PRINTER), TEST_PRINTER,
+                        PrinterInfo.STATUS_IDLE);
+
+                printer.setCapabilities(new PrinterCapabilitiesInfo.Builder(printerId)
+                        .addMediaSize(PrintAttributes.MediaSize.ISO_A5, true)
+                        .addResolution(TWO_HUNDRED_DPI, true)
+                        .setColorModes(PrintAttributes.COLOR_MODE_MONOCHROME,
+                                PrintAttributes.COLOR_MODE_MONOCHROME)
+                        .setMinMargins(new PrintAttributes.Margins(0, 0, 0, 0)).build());
+
+                ArrayList<PrinterInfo> printers = new ArrayList<>(1);
+                printers.add(printer.build());
+
+                session.addPrinters(printers);
+            }
+            return null;
+        }, null, null, invocation -> null, null, null, invocation -> {
+            // Take a note onDestroy was called.
+            onPrinterDiscoverySessionDestroyCalled();
+            return null;
+        });
+    }
+
+    /**
+     * Create mock service callback for a session. Once the job is queued the test function is
+     * called.
+     *
+     * @param sessionCallbacks The callbacks of the session
+     * @param blockAfterState  The state the print services should progress to
+     */
+    private @NonNull PrintServiceCallbacks createFirstMockPrinterServiceCallbacks(
+            final @NonNull PrinterDiscoverySessionCallbacks sessionCallbacks, int blockAfterState) {
+        return createMockPrintServiceCallbacks(
+                invocation -> sessionCallbacks, invocation -> {
+                    android.printservice.PrintJob job = (android.printservice.PrintJob) invocation
+                            .getArguments()[0];
+
+                    switch (blockAfterState) {
+                        case PrintJobInfo.STATE_CREATED:
+                            assertEquals(PrintJobInfo.STATE_CREATED, job.getInfo().getState());
+                            break;
+                        case PrintJobInfo.STATE_STARTED:
+                            job.start();
+                            break;
+                        case PrintJobInfo.STATE_QUEUED:
+                            assertEquals(PrintJobInfo.STATE_QUEUED, job.getInfo().getState());
+                            break;
+                        case PrintJobInfo.STATE_BLOCKED:
+                            job.start();
+                            job.block("test block");
+                            break;
+                        case PrintJobInfo.STATE_FAILED:
+                            job.start();
+                            job.fail("test fail");
+                            break;
+                        case PrintJobInfo.STATE_COMPLETED:
+                            job.start();
+                            job.complete();
+                            break;
+                        default:
+                            throw new Exception("Should not be reached");
+                    }
+
+                    return null;
+                }, invocation -> {
+                    android.printservice.PrintJob job = (android.printservice.PrintJob) invocation
+                            .getArguments()[0];
+
+                    job.cancel();
+
+                    return null;
+                });
+    }
+
+    /**
+     * Setup mock print subsystem
+     *
+     * @param blockAfterState Tell the print service to block all print jobs at this state
+     *
+     * @return The print document adapter to be used for printing
+     */
+    private @NonNull PrintDocumentAdapter setupPrint(int blockAfterState) {
+        // Create the session of the printers that we will be checking.
+        PrinterDiscoverySessionCallbacks sessionCallbacks = createFirstMockPrinterDiscoverySessionCallbacks();
+
+        // Create the service callbacks for the first print service.
+        PrintServiceCallbacks serviceCallbacks = createFirstMockPrinterServiceCallbacks(
+                sessionCallbacks, blockAfterState);
+
+        // Configure the print services.
+        FirstPrintService.setCallbacks(serviceCallbacks);
+
+        // We don't use the second service, but we have to still configure it
+        SecondPrintService.setCallbacks(createMockPrintServiceCallbacks(null, null, null));
+
+        return createMockPrintDocumentAdapter();
+    }
+
+    /**
+     * @param name Name of print job
+     *
+     * @return The print job for the name
+     *
+     * @throws Exception If print job could not be found
+     */
+    private @NonNull PrintJob getPrintJob(@NonNull String name) throws Exception {
+        for (PrintJob job : getPrintManager().getPrintJobs()) {
+            if (job.getInfo().getLabel().equals(name)) {
+                return job;
+            }
+        }
+
+        throw new Exception(
+                "Print job " + name + " not found in " + getPrintManager().getPrintJobs());
+    }
+
+    /**
+     * Base test for all cancel print job tests
+     *
+     * @param cancelAfterState The print job state state to progress to canceling
+     * @param printJobName     The print job name to use
+     *
+     * @throws Exception If anything is unexpected
+     */
+    private void cancelPrintJobBaseTest(int cancelAfterState, @NonNull String printJobName)
+            throws Exception {
+        PrintDocumentAdapter adapter = setupPrint(cancelAfterState);
+
+        print(adapter, printJobName);
+        selectPrinter(TEST_PRINTER);
+
+        clickPrintButton();
+        answerPrintServicesWarning(true);
+
+        PrintJob job = getPrintJob(printJobName);
+
+        eventually(() -> assertEquals(cancelAfterState, job.getInfo().getState()));
+
+        job.cancel();
+
+        eventually(() -> assertEquals(PrintJobInfo.STATE_CANCELED, job.getInfo().getState()));
+
+        waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
+    }
+
+    public void testAttemptCancelCreatedPrintJob() throws Exception {
+        PrintDocumentAdapter adapter = setupPrint(PrintJobInfo.STATE_STARTED);
+
+        print(adapter, "testAttemptCancelCreatedPrintJob");
+        selectPrinter(TEST_PRINTER);
+
+        waitForLayoutAdapterCallbackCount(1);
+
+        PrintJob job = getPrintJob("testAttemptCancelCreatedPrintJob");
+
+        // Cancel does not have an effect on created jobs
+        job.cancel();
+
+        eventually(() -> assertEquals(PrintJobInfo.STATE_CREATED, job.getInfo().getState()));
+
+        // Cancel printing by exiting print activity
+        getUiDevice().pressBack();
+
+        eventually(() -> assertEquals(PrintJobInfo.STATE_CANCELED, job.getInfo().getState()));
+
+        waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
+    }
+
+    public void testCancelStartedPrintJob() throws Exception {
+        cancelPrintJobBaseTest(PrintJobInfo.STATE_STARTED, "testCancelStartedPrintJob");
+    }
+
+    public void testCancelBlockedPrintJob() throws Exception {
+        cancelPrintJobBaseTest(PrintJobInfo.STATE_BLOCKED, "testCancelBlockedPrintJob");
+    }
+
+    public void testCancelFailedPrintJob() throws Exception {
+        cancelPrintJobBaseTest(PrintJobInfo.STATE_FAILED, "testCancelFailedPrintJob");
+    }
+
+    public void testRestartFailedPrintJob() throws Exception {
+        PrintDocumentAdapter adapter = setupPrint(PrintJobInfo.STATE_FAILED);
+
+        print(adapter, "testRestartFailedPrintJob");
+        selectPrinter(TEST_PRINTER);
+
+        clickPrintButton();
+        answerPrintServicesWarning(true);
+
+        PrintJob job = getPrintJob("testRestartFailedPrintJob");
+
+        eventually(() -> assertEquals(PrintJobInfo.STATE_FAILED, job.getInfo().getState()));
+
+        // Restart goes from failed right to queued, so stop the print job at "queued" now
+        setupPrint(PrintJobInfo.STATE_QUEUED);
+
+        job.restart();
+        eventually(() -> assertEquals(PrintJobInfo.STATE_QUEUED, job.getInfo().getState()));
+
+        job.cancel();
+        eventually(() -> assertEquals(PrintJobInfo.STATE_CANCELED, job.getInfo().getState()));
+
+        waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
+    }
+
+    public void testGetTwoPrintJobStates() throws Exception {
+        PrintDocumentAdapter adapter = setupPrint(PrintJobInfo.STATE_BLOCKED);
+        print(adapter, "testGetTwoPrintJobStates-block");
+        selectPrinter(TEST_PRINTER);
+        clickPrintButton();
+        answerPrintServicesWarning(true);
+
+        PrintJob job1 = getPrintJob("testGetTwoPrintJobStates-block");
+        eventually(() -> assertEquals(PrintJobInfo.STATE_BLOCKED, job1.getInfo().getState()));
+
+        adapter = setupPrint(PrintJobInfo.STATE_COMPLETED);
+        print(adapter, "testGetTwoPrintJobStates-complete");
+        clickPrintButton();
+
+        PrintJob job2 = getPrintJob("testGetTwoPrintJobStates-complete");
+        eventually(() -> assertEquals(PrintJobInfo.STATE_COMPLETED, job2.getInfo().getState()));
+
+        // First print job should still be there
+        PrintJob job1again = getPrintJob("testGetTwoPrintJobStates-block");
+        assertEquals(PrintJobInfo.STATE_BLOCKED, job1again.getInfo().getState());
+
+        // Check attributes that should have been applied
+        assertEquals(PrintAttributes.MediaSize.ISO_A5,
+                job1again.getInfo().getAttributes().getMediaSize());
+        assertEquals(PrintAttributes.COLOR_MODE_MONOCHROME,
+                job1again.getInfo().getAttributes().getColorMode());
+        assertEquals(TWO_HUNDRED_DPI, job1again.getInfo().getAttributes().getResolution());
+
+        waitForPrinterDiscoverySessionDestroyCallbackCalled(2);
+    }
+}
diff --git a/tests/tests/print/src/android/print/cts/BasePrintTest.java b/tests/tests/print/src/android/print/cts/BasePrintTest.java
index 7f0ae5d..8f2949e 100644
--- a/tests/tests/print/src/android/print/cts/BasePrintTest.java
+++ b/tests/tests/print/src/android/print/cts/BasePrintTest.java
@@ -55,7 +55,6 @@
 import android.support.test.uiautomator.UiObjectNotFoundException;
 import android.support.test.uiautomator.UiSelector;
 import android.test.InstrumentationTestCase;
-import android.util.DisplayMetrics;
 import android.util.Log;
 
 import org.hamcrest.BaseMatcher;
@@ -71,7 +70,6 @@
 import java.io.InputStreamReader;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Locale;
 import java.util.concurrent.TimeoutException;
 /**
  * This is the base class for print tests.
@@ -87,11 +85,41 @@
     private static final String COMMAND_PREFIX_ENABLE_IME = "ime enable ";
     private static final String COMMAND_PREFIX_DISABLE_IME = "ime disable ";
     private static final int CURRENT_USER_ID = -2; // Mirrors UserHandle.USER_CURRENT
+    private static final String PRINTSPOOLER_PACKAGE = "com.android.printspooler";
 
     private static PrintDocumentActivity sActivity;
     private UiDevice mUiDevice;
 
     /**
+     * Make sure that a runnable eventually finishes without throwing a exception.
+     *
+     * @param r The runnable to run.
+     */
+    protected static void eventually(Runnable r) {
+        final long TIMEOUT_MILLS = 5000;
+        long start = System.currentTimeMillis();
+
+        while (true) {
+            try {
+                r.run();
+                break;
+            } catch (Throwable e) {
+                if (System.currentTimeMillis() - start < TIMEOUT_MILLS) {
+                    Log.e(LOG_TAG, "Ignoring exception", e);
+
+                    try {
+                        Thread.sleep(100);
+                    } catch (InterruptedException e1) {
+                        Log.e(LOG_TAG, "Interrupted", e);
+                    }
+                } else {
+                    throw e;
+                }
+            }
+        }
+    }
+
+    /**
      * Return the UI device
      *
      * @return the UI device
@@ -100,8 +128,6 @@
         return mUiDevice;
     }
 
-    private LocaleList mOldLocale;
-
     private CallCounter mCancelOperationCounter;
     private CallCounter mLayoutCallCounter;
     private CallCounter mWriteCallCounter;
@@ -180,18 +206,6 @@
         System.setProperty("dexmaker.dexcache", getInstrumentation()
                 .getTargetContext().getCacheDir().getPath());
 
-        // Set to US locale.
-        Log.d(LOG_TAG, "set locale");
-        Resources resources = getInstrumentation().getTargetContext().getResources();
-        Configuration oldConfiguration = resources.getConfiguration();
-        if (!oldConfiguration.getLocales().get(0).equals(Locale.US)) {
-            mOldLocale = oldConfiguration.getLocales();
-            DisplayMetrics displayMetrics = resources.getDisplayMetrics();
-            Configuration newConfiguration = new Configuration(oldConfiguration);
-            newConfiguration.setLocale(Locale.US);
-            resources.updateConfiguration(newConfiguration, displayMetrics);
-        }
-
         // Initialize the latches.
         Log.d(LOG_TAG, "init counters");
         mCancelOperationCounter = new CallCounter();
@@ -226,17 +240,6 @@
         Log.d(LOG_TAG, "enableImes()");
         enableImes();
 
-        // Restore the locale if needed.
-        Log.d(LOG_TAG, "restore locale");
-        if (mOldLocale != null) {
-            Resources resources = getInstrumentation().getTargetContext().getResources();
-            DisplayMetrics displayMetrics = resources.getDisplayMetrics();
-            Configuration newConfiguration = new Configuration(resources.getConfiguration());
-            newConfiguration.setLocales(mOldLocale);
-            mOldLocale = null;
-            resources.updateConfiguration(newConfiguration, displayMetrics);
-        }
-
         // Make sure the spooler is cleaned, this also un-approves all services
         Log.d(LOG_TAG, "clearPrintSpoolerData()");
         clearPrintSpoolerData();
@@ -439,12 +442,11 @@
     }
 
     protected void answerPrintServicesWarning(boolean confirm) throws UiObjectNotFoundException {
-        UiDevice uiDevice = UiDevice.getInstance(getInstrumentation());
         UiObject button;
         if (confirm) {
-            button = uiDevice.findObject(new UiSelector().resourceId("android:id/button1"));
+            button = mUiDevice.findObject(new UiSelector().resourceId("android:id/button1"));
         } else {
-            button = uiDevice.findObject(new UiSelector().resourceId("android:id/button2"));
+            button = mUiDevice.findObject(new UiSelector().resourceId("android:id/button2"));
         }
         button.click();
     }
@@ -568,6 +570,17 @@
         }
     }
 
+    protected void clickRetryButton() throws UiObjectNotFoundException, IOException {
+        try {
+            UiObject retryButton = mUiDevice.findObject(new UiSelector().resourceId(
+                    "com.android.printspooler:id/action_button"));
+            retryButton.click();
+        } catch (UiObjectNotFoundException e) {
+            dumpWindowHierarchy();
+            throw e;
+        }
+    }
+
     protected void dumpWindowHierarchy() throws IOException {
         ByteArrayOutputStream os = new ByteArrayOutputStream();
         mUiDevice.dumpWindowHierarchy(os);
@@ -807,4 +820,76 @@
         return getInstrumentation().getContext().getPackageManager()
                 .hasSystemFeature(PackageManager.FEATURE_PRINTING);
     }
+
+    /**
+     * Get a string array from the print spooler's resources.
+     *
+     * @param resourceName The name of the array resource
+     * @return The localized string array
+     *
+     * @throws Exception If anything is unexpected
+     */
+    protected String[] getPrintSpoolerStringArray(String resourceName) throws Exception {
+        PackageManager pm = getActivity().getPackageManager();
+        Resources printSpoolerRes = pm.getResourcesForApplication(PRINTSPOOLER_PACKAGE);
+        int id = printSpoolerRes.getIdentifier(resourceName, "array", PRINTSPOOLER_PACKAGE);
+        return printSpoolerRes.getStringArray(id);
+    }
+
+    /**
+     * Get a string from the print spooler's resources.
+     *
+     * @param resource_name The name of the string resource
+     * @return The localized string
+     *
+     * @throws Exception If anything is unexpected
+     */
+    protected String getPrintSpoolerString(String resourceName) throws Exception {
+        PackageManager pm = getActivity().getPackageManager();
+        Resources printSpoolerRes = pm.getResourcesForApplication(PRINTSPOOLER_PACKAGE);
+        int id = printSpoolerRes.getIdentifier(resourceName, "string", PRINTSPOOLER_PACKAGE);
+        return printSpoolerRes.getString(id);
+    }
+
+    /**
+     * Get a string with one parameter from the print spooler's resources.
+     *
+     * @param resource_name The name of the string resource
+     * @return The localized string
+     *
+     * @throws Exception If anything is unexpected
+     */
+    protected String getPrintSpoolerStringOneParam(String resourceName, Object p)
+            throws Exception {
+        PackageManager pm = getActivity().getPackageManager();
+        Resources printSpoolerRes = pm.getResourcesForApplication(PRINTSPOOLER_PACKAGE);
+        int id = printSpoolerRes.getIdentifier(resourceName, "string", PRINTSPOOLER_PACKAGE);
+        return printSpoolerRes.getString(id, p);
+    }
+
+    /**
+     * Get the default media size for the current locale.
+     *
+     * @return The default media size for the current locale
+     *
+     * @throws Exception If anything is unexpected
+     */
+    protected PrintAttributes.MediaSize getDefaultMediaSize() throws Exception {
+        PackageManager pm = getActivity().getPackageManager();
+        Resources printSpoolerRes = pm.getResourcesForApplication(PRINTSPOOLER_PACKAGE);
+        int defaultMediaSizeResId = printSpoolerRes.getIdentifier("mediasize_default", "string",
+                PRINTSPOOLER_PACKAGE);
+        String defaultMediaSizeName = printSpoolerRes.getString(defaultMediaSizeResId);
+
+        switch (defaultMediaSizeName) {
+            case "NA_LETTER":
+                return PrintAttributes.MediaSize.NA_LETTER;
+            case "JIS_B5":
+                return PrintAttributes.MediaSize.JIS_B5;
+            case "ISO_A4":
+                return PrintAttributes.MediaSize.ISO_A4;
+            default:
+                throw new Exception("Unknown default media size " + defaultMediaSizeName);
+        }
+    }
 }
diff --git a/tests/tests/print/src/android/print/cts/CustomPrintOptionsTest.java b/tests/tests/print/src/android/print/cts/CustomPrintOptionsTest.java
index 54b4d23..68f6201 100644
--- a/tests/tests/print/src/android/print/cts/CustomPrintOptionsTest.java
+++ b/tests/tests/print/src/android/print/cts/CustomPrintOptionsTest.java
@@ -87,7 +87,8 @@
      * @throws Exception If something was unexpected
      */
     private PageRange[] getPages() throws Exception {
-        if (getUiDevice().hasObject(By.text("All 3"))) {
+        if (getUiDevice().hasObject(By.text(getPrintSpoolerStringOneParam("template_all_pages",
+                3)))) {
             return PAGESS[2];
         }
 
diff --git a/tests/tests/print/src/android/print/cts/PageRangeAdjustmentTest.java b/tests/tests/print/src/android/print/cts/PageRangeAdjustmentTest.java
index df142b9..dae2976 100644
--- a/tests/tests/print/src/android/print/cts/PageRangeAdjustmentTest.java
+++ b/tests/tests/print/src/android/print/cts/PageRangeAdjustmentTest.java
@@ -258,7 +258,7 @@
         waitForLayoutAdapterCallbackCount(2);
 
         // Select only the second page.
-        selectPages("2");
+        selectPages("2", PAGE_COUNT);
 
         // Click the print button.
         clickPrintButton();
@@ -392,7 +392,7 @@
         waitForLayoutAdapterCallbackCount(2);
 
         // Select a page not written for preview.
-        selectPages(Integer.valueOf(REQUESTED_PAGE).toString());
+        selectPages(Integer.valueOf(REQUESTED_PAGE).toString(), PAGE_COUNT);
 
         // Click the print button.
         clickPrintButton();
@@ -607,7 +607,7 @@
         waitForLayoutAdapterCallbackCount(2);
 
         // Select a page not written for preview.
-        selectPages("3");
+        selectPages("3", PAGE_COUNT);
 
         // Click the print button.
         clickPrintButton();
@@ -633,12 +633,13 @@
                 any(PrintJob.class));
     }
 
-    private void selectPages(String pages) throws UiObjectNotFoundException {
+    private void selectPages(String pages, int totalPages) throws Exception {
         UiObject pagesSpinner = getUiDevice().findObject(new UiSelector().resourceId(
                 "com.android.printspooler:id/range_options_spinner"));
         pagesSpinner.click();
 
-        UiObject rangeOption = getUiDevice().findObject(new UiSelector().textContains("Range"));
+        UiObject rangeOption = getUiDevice().findObject(new UiSelector().textContains(
+                getPrintSpoolerStringOneParam("template_page_range", totalPages)));
         rangeOption.click();
 
         UiObject pagesEditText = getUiDevice().findObject(new UiSelector().resourceId(
diff --git a/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java b/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java
index f171884..fd656ce 100644
--- a/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java
+++ b/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java
@@ -43,6 +43,7 @@
 import android.print.cts.services.StubbablePrinterDiscoverySession;
 import android.printservice.PrintJob;
 import android.printservice.PrintService;
+import android.util.Log;
 
 import org.mockito.InOrder;
 import org.mockito.invocation.InvocationOnMock;
@@ -58,6 +59,8 @@
  */
 public class PrintDocumentAdapterContractTest extends BasePrintTest {
 
+    private static final String LOG_TAG = "PrintDocumentAdapterContractTest";
+
     public void testNoPrintOptionsOrPrinterChange() throws Exception {
         if (!supportsPrinting()) {
             return;
@@ -141,7 +144,7 @@
         // there are other printers but none of them was used.
         PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
         PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
-                .setMediaSize(MediaSize.NA_LETTER)
+                .setMediaSize(getDefaultMediaSize())
                 .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
                 .setMinMargins(Margins.NO_MARGINS)
                 .setColorMode(PrintAttributes.COLOR_MODE_COLOR)
@@ -256,7 +259,7 @@
         // there are other printers but none of them was used.
         PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
         PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
-                .setMediaSize(MediaSize.NA_LETTER)
+                .setMediaSize(getDefaultMediaSize())
                 .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
                 .setMinMargins(Margins.NO_MARGINS)
                 .setColorMode(PrintAttributes.COLOR_MODE_COLOR)
@@ -342,25 +345,25 @@
         waitForLayoutAdapterCallbackCount(2);
 
         // Change the orientation.
-        changeOrientation("Landscape");
+        changeOrientation(getPrintSpoolerStringArray("orientation_labels")[1]);
 
         // Wait for layout.
         waitForLayoutAdapterCallbackCount(3);
 
         // Change the media size.
-        changeMediaSize("ISO A4");
+        changeMediaSize(MediaSize.ISO_A0.getLabel(getActivity().getPackageManager()));
 
         // Wait for layout.
         waitForLayoutAdapterCallbackCount(4);
 
         // Change the color.
-        changeColor("Black & White");
+        changeColor(getPrintSpoolerStringArray("color_mode_labels")[0]);
 
         // Wait for layout.
         waitForLayoutAdapterCallbackCount(5);
 
         // Change the duplex.
-        changeDuplex("Short edge");
+        changeDuplex(getPrintSpoolerStringArray("duplex_mode_labels")[2]);
 
         // Wait for layout.
         waitForLayoutAdapterCallbackCount(6);
@@ -387,7 +390,7 @@
         // there are other printers but none of them was used.
         PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
         PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
-                .setMediaSize(MediaSize.NA_LETTER)
+                .setMediaSize(getDefaultMediaSize())
                 .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
                 .setMinMargins(Margins.NO_MARGINS)
                 .setColorMode(PrintAttributes.COLOR_MODE_COLOR)
@@ -432,7 +435,7 @@
         // there shouldn't be a next call to write.
         PrintAttributes fourthOldAttributes = thirdNewAttributes;
         PrintAttributes fourthNewAttributes = new PrintAttributes.Builder()
-                .setMediaSize(MediaSize.ISO_A4.asLandscape())
+                .setMediaSize(MediaSize.ISO_A0.asLandscape())
                 .setResolution(new Resolution("300x300", "300x300", 300, 300))
                 .setMinMargins(Margins.NO_MARGINS)
                 .setColorMode(PrintAttributes.COLOR_MODE_COLOR)
@@ -445,7 +448,7 @@
         // there shouldn't be a next call to write.
         PrintAttributes fifthOldAttributes = fourthNewAttributes;
         PrintAttributes fifthNewAttributes = new PrintAttributes.Builder()
-                .setMediaSize(MediaSize.ISO_A4.asLandscape())
+                .setMediaSize(MediaSize.ISO_A0.asLandscape())
                 .setResolution(new Resolution("300x300", "300x300", 300, 300))
                 .setMinMargins(Margins.NO_MARGINS)
                 .setColorMode(PrintAttributes.COLOR_MODE_MONOCHROME)
@@ -458,7 +461,7 @@
         // there shouldn't be a next call to write.
         PrintAttributes sixthOldAttributes = fifthNewAttributes;
         PrintAttributes sixthNewAttributes = new PrintAttributes.Builder()
-                .setMediaSize(MediaSize.ISO_A4.asLandscape())
+                .setMediaSize(MediaSize.ISO_A0.asLandscape())
                 .setResolution(new Resolution("300x300", "300x300", 300, 300))
                 .setMinMargins(Margins.NO_MARGINS)
                 .setColorMode(PrintAttributes.COLOR_MODE_MONOCHROME)
@@ -546,7 +549,7 @@
         waitForLayoutAdapterCallbackCount(2);
 
         // Change the color.
-        changeColor("Black & White");
+        changeColor(getPrintSpoolerStringArray("color_mode_labels")[0]);
 
         // Wait for layout.
         waitForLayoutAdapterCallbackCount(3);
@@ -580,7 +583,7 @@
         // there are other printers but none of them was used.
         PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
         PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
-                .setMediaSize(MediaSize.NA_LETTER)
+                .setMediaSize(getDefaultMediaSize())
                 .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
                 .setMinMargins(Margins.NO_MARGINS)
                 .setColorMode(PrintAttributes.COLOR_MODE_COLOR)
@@ -622,7 +625,7 @@
         // new printer which results in a layout pass. Same for color.
         PrintAttributes fourthOldAttributes = thirdNewAttributes;
         PrintAttributes fourthNewAttributes = new PrintAttributes.Builder()
-                .setMediaSize(MediaSize.ISO_A4)
+                .setMediaSize(MediaSize.ISO_A0)
                 .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
                 .setMinMargins(new Margins(200, 200, 200, 200))
                 .setColorMode(PrintAttributes.COLOR_MODE_COLOR)
@@ -732,7 +735,7 @@
         // there are other printers but none of them was used.
         PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
         PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
-                .setMediaSize(MediaSize.NA_LETTER)
+                .setMediaSize(getDefaultMediaSize())
                 .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
                 .setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
                 .setDuplexMode(PrintAttributes.DUPLEX_MODE_NONE)
@@ -860,7 +863,7 @@
         // there are other printers but none of them was used.
         PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
         PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
-                .setMediaSize(MediaSize.NA_LETTER)
+                .setMediaSize(getDefaultMediaSize())
                 .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
                 .setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
                 .setDuplexMode(PrintAttributes.DUPLEX_MODE_NONE)
@@ -973,7 +976,7 @@
         // there are other printers but none of them was used.
         PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
         PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
-                .setMediaSize(MediaSize.NA_LETTER)
+                .setMediaSize(getDefaultMediaSize())
                 .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
                 .setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
                 .setDuplexMode(PrintAttributes.DUPLEX_MODE_NONE)
@@ -1081,7 +1084,7 @@
         // there are other printers but none of them was used.
         PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
         PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
-                .setMediaSize(MediaSize.NA_LETTER)
+                .setMediaSize(getDefaultMediaSize())
                 .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
                 .setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
                 .setDuplexMode(PrintAttributes.DUPLEX_MODE_NONE)
@@ -1176,7 +1179,7 @@
         // there are other printers but none of them was used.
         PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
         PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
-                .setMediaSize(MediaSize.NA_LETTER)
+                .setMediaSize(getDefaultMediaSize())
                 .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
                 .setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
                 .setDuplexMode(PrintAttributes.DUPLEX_MODE_NONE)
@@ -1249,7 +1252,7 @@
         // there are other printers but none of them was used.
         PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
         PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
-                .setMediaSize(MediaSize.NA_LETTER)
+                .setMediaSize(getDefaultMediaSize())
                 .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
                 .setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
                 .setDuplexMode(PrintAttributes.DUPLEX_MODE_NONE)
@@ -1332,7 +1335,7 @@
         // there are other printers but none of them was used.
         PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
         PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
-                .setMediaSize(MediaSize.NA_LETTER)
+                .setMediaSize(getDefaultMediaSize())
                 .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
                 .setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
                 .setDuplexMode(PrintAttributes.DUPLEX_MODE_NONE)
@@ -1351,6 +1354,168 @@
         verifyNoMoreInteractions(adapter);
     }
 
+    public void testUnexpectedLayoutCancel() throws Exception {
+        if (!supportsPrinting()) {
+            return;
+        }
+        // Configure the print services.
+        FirstPrintService.setCallbacks(createFirstMockPrintServiceCallbacks());
+        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+        final PrintAttributes[] printAttributes = new PrintAttributes[1];
+        final int[] numLayoutCalls = new int[1];
+
+        // Create a mock print adapter.
+        final PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(
+                new Answer<Void>() {
+                    @Override
+                    public Void answer(InvocationOnMock invocation) throws Throwable {
+                        printAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
+                        LayoutResultCallback callback = (LayoutResultCallback) invocation.getArguments()[3];
+
+                        // Returned cancelled for the second layout call which is unexpected
+                        if (numLayoutCalls[0] == 1) {
+                            callback.onLayoutCancelled();
+                        } else {
+                            callback.onLayoutFinished(
+                                    (new PrintDocumentInfo.Builder(PRINT_JOB_NAME)).build(), false);
+                        }
+                        numLayoutCalls[0]++;
+                        // Mark layout was called.
+                        onLayoutCalled();
+                        return null;
+                    }
+                }, new Answer<Void>() {
+                    @Override
+                    public Void answer(InvocationOnMock invocation) throws Throwable {
+                        Object[] args = invocation.getArguments();
+                        PageRange[] pages = (PageRange[]) args[0];
+                        ParcelFileDescriptor fd = (ParcelFileDescriptor) args[1];
+                        WriteResultCallback callback = (WriteResultCallback) args[3];
+                        writeBlankPages(printAttributes[0], fd, 0, 1);
+                        fd.close();
+                        callback.onWriteFinished(pages);
+                        // Mark write was called.
+                        onWriteCalled();
+                        return null;
+                    }
+                }, new Answer<Void>() {
+                    @Override
+                    public Void answer(InvocationOnMock invocation) throws Throwable {
+                        // Mark finish was called.
+                        onFinishCalled();
+                        return null;
+                    }
+                });
+
+        // Start printing.
+        print(adapter);
+
+        // Wait for layout.
+        waitForLayoutAdapterCallbackCount(1);
+
+        // Select the second printer.
+        selectPrinter("Second printer");
+
+        // Wait for layout.
+        waitForLayoutAdapterCallbackCount(2);
+
+        // Retry layout (which should succeed) as the layout call will stop canceling after the
+        // second time
+        clickRetryButton();
+
+        // Click the print button.
+        clickPrintButton();
+
+        // Answer the dialog for the print service cloud warning
+        answerPrintServicesWarning(true);
+
+        // Wait for the session to be destroyed to isolate tests.
+        waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
+    }
+
+    public void testUnexpectedWriteCancel() throws Exception {
+        if (!supportsPrinting()) {
+            return;
+        }
+        // Configure the print services.
+        FirstPrintService.setCallbacks(createFirstMockPrintServiceCallbacks());
+        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+        final PrintAttributes[] printAttributes = new PrintAttributes[1];
+        final int[] numWriteCalls = new int[1];
+
+        // Create a mock print adapter.
+        final PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(
+                new Answer<Void>() {
+                    @Override
+                    public Void answer(InvocationOnMock invocation) throws Throwable {
+                        printAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
+                        LayoutResultCallback callback = (LayoutResultCallback) invocation.getArguments()[3];
+
+                        callback.onLayoutFinished(
+                                    (new PrintDocumentInfo.Builder(PRINT_JOB_NAME)).build(), true);
+
+                        // Mark layout was called.
+                        onLayoutCalled();
+                        return null;
+                    }
+                }, new Answer<Void>() {
+                    @Override
+                    public Void answer(InvocationOnMock invocation) throws Throwable {
+                        Object[] args = invocation.getArguments();
+                        WriteResultCallback callback = (WriteResultCallback) args[3];
+
+                        // Returned cancelled for the second write call which is unexpected
+                        if (numWriteCalls[0] == 1) {
+                            callback.onWriteCancelled();
+                        } else {
+                            PageRange[] pages = (PageRange[]) args[0];
+                            ParcelFileDescriptor fd = (ParcelFileDescriptor) args[1];
+                            writeBlankPages(printAttributes[0], fd, 0, 1);
+                            fd.close();
+                            callback.onWriteFinished(pages);
+                        }
+                        numWriteCalls[0]++;
+
+                        // Mark write was called.
+                        onWriteCalled();
+                        return null;
+                    }
+                }, new Answer<Void>() {
+                    @Override
+                    public Void answer(InvocationOnMock invocation) throws Throwable {
+                        // Mark finish was called.
+                        onFinishCalled();
+                        return null;
+                    }
+                });
+
+        // Start printing.
+        print(adapter);
+
+        waitForWriteAdapterCallback(1);
+
+        // Select the second printer.
+        selectPrinter("Second printer");
+
+        // Wait for layout.
+        waitForWriteAdapterCallback(2);
+
+        // Retry write (which should succeed) as the write call will stop canceling after the
+        // second time
+        clickRetryButton();
+
+        // Click the print button.
+        clickPrintButton();
+
+        // Answer the dialog for the print service cloud warning
+        answerPrintServicesWarning(true);
+
+        // Wait for the session to be destroyed to isolate tests.
+        waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
+    }
+
     public void testRequestedPagesNotWritten() throws Exception {
         if (!supportsPrinting()) {
             return;
@@ -1424,7 +1589,7 @@
         // there are other printers but none of them was used.
         PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
         PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
-                .setMediaSize(MediaSize.NA_LETTER)
+                .setMediaSize(getDefaultMediaSize())
                 .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
                 .setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
                 .setDuplexMode(PrintAttributes.DUPLEX_MODE_NONE)
@@ -1496,7 +1661,7 @@
         // there are other printers but none of them was used.
         PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
         PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
-                .setMediaSize(MediaSize.NA_LETTER)
+                .setMediaSize(getDefaultMediaSize())
                 .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
                 .setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
                 .setDuplexMode(PrintAttributes.DUPLEX_MODE_NONE)
@@ -1576,7 +1741,7 @@
         // there are other printers but none of them was used.
         PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
         PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
-                .setMediaSize(MediaSize.NA_LETTER)
+                .setMediaSize(getDefaultMediaSize())
                 .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
                 .setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
                 .setDuplexMode(PrintAttributes.DUPLEX_MODE_NONE)
@@ -1595,6 +1760,189 @@
         verifyNoMoreInteractions(adapter);
     }
 
+    public void testLayoutCallbackCalledTwice() throws Exception {
+        if (!supportsPrinting()) {
+            return;
+        }
+        // Configure the print services.
+        FirstPrintService.setCallbacks(createFirstMockPrintServiceCallbacks());
+        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+        // Create a mock print adapter.
+        final PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(
+                new Answer<Void>() {
+                    @Override
+                    public Void answer(InvocationOnMock invocation) throws Throwable {
+                        PrintDocumentInfo info = new PrintDocumentInfo.Builder(PRINT_JOB_NAME)
+                                .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
+                                .setPageCount(1)
+                                .build();
+                        LayoutResultCallback callback = (LayoutResultCallback) invocation
+                                .getArguments()[3];
+
+                        // Break the contract and call the callback twice.
+                        callback.onLayoutFinished(info, true);
+                        callback.onLayoutFinished(info, true);
+
+                        // Mark layout called.
+                        onLayoutCalled();
+                        return null;
+                    }
+                }, null, new Answer<Void>() {
+                    @Override
+                    public Void answer(InvocationOnMock invocation) throws Throwable {
+                        // Mark finish was called.
+                        onFinishCalled();
+                        return null;
+                    }
+                });
+
+        // Start printing.
+        print(adapter);
+
+        // Wait for layout.
+        waitForLayoutAdapterCallbackCount(1);
+
+        // Cancel printing.
+        getUiDevice().pressBack(); // wakes up the device.
+        getUiDevice().pressBack();
+
+        // Wait for a finish.
+        waitForAdapterFinishCallbackCalled();
+
+        // Wait for the session to be destroyed to isolate tests.
+        waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
+
+        // Verify the expected calls.
+        InOrder inOrder = inOrder(adapter);
+
+        // Start is always called first.
+        inOrder.verify(adapter).onStart();
+
+        // Start is always followed by a layout. The PDF printer is selected if
+        // there are other printers but none of them was used.
+        PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
+        PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
+                .setMediaSize(getDefaultMediaSize())
+                .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
+                .setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+                .setDuplexMode(PrintAttributes.DUPLEX_MODE_NONE)
+                .build();
+        verifyLayoutCall(inOrder, adapter, firstOldAttributes, firstNewAttributes, true);
+
+        PageRange[] firstPage = new PageRange[] {new PageRange(0, 0)};
+        inOrder.verify(adapter).onWrite(eq(firstPage), any(ParcelFileDescriptor.class),
+                any(CancellationSignal.class), any(WriteResultCallback.class));
+
+        // Finish is always called last.
+        inOrder.verify(adapter).onFinish();
+
+        // No other call are expected.
+        verifyNoMoreInteractions(adapter);
+    }
+
+    public void testWriteCallbackCalledTwice() throws Exception {
+        if (!supportsPrinting()) {
+            return;
+        }
+        // Configure the print services.
+        FirstPrintService.setCallbacks(createFirstMockPrintServiceCallbacks());
+        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+        final PrintAttributes[] printAttributes = new PrintAttributes[1];
+
+        // Create a mock print adapter.
+        final PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(
+                new Answer<Void>() {
+                    @Override
+                    public Void answer(InvocationOnMock invocation) throws Throwable {
+                        printAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
+                        PrintDocumentInfo info = new PrintDocumentInfo.Builder(PRINT_JOB_NAME)
+                                .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
+                                .setPageCount(1)
+                                .build();
+                        LayoutResultCallback callback = (LayoutResultCallback) invocation
+                                .getArguments()[3];
+
+                        callback.onLayoutFinished(info, true);
+
+                        // Mark layout called.
+                        onLayoutCalled();
+                        return null;
+                    }
+                }, new Answer<Void>() {
+                    @Override
+                    public Void answer(InvocationOnMock invocation) throws Throwable {
+                        Object[] args = invocation.getArguments();
+                        PageRange[] pages = (PageRange[]) args[0];
+                        ParcelFileDescriptor fd = (ParcelFileDescriptor) args[1];
+                        WriteResultCallback callback = (WriteResultCallback) args[3];
+
+                        // Write only one pages
+                        writeBlankPages(printAttributes[0], fd, 0, 0);
+                        fd.close();
+
+                        // Break the contract and call callback twice
+                        callback.onWriteFinished(pages);
+                        callback.onWriteFinished(pages);
+
+                        // Mark write called
+                        onWriteCalled();
+                        return null;
+                    }
+                }, new Answer<Void>() {
+                    @Override
+                    public Void answer(InvocationOnMock invocation) throws Throwable {
+                        // Mark finish was called.
+                        onFinishCalled();
+                        return null;
+                    }
+                });
+
+        // Start printing.
+        print(adapter);
+
+        // Wait for layout.
+        waitForLayoutAdapterCallbackCount(1);
+
+        // Cancel printing.
+        getUiDevice().pressBack(); // wakes up the device.
+        getUiDevice().pressBack();
+
+        // Wait for a finish.
+        waitForAdapterFinishCallbackCalled();
+
+        // Wait for the session to be destroyed to isolate tests.
+        waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
+
+        // Verify the expected calls.
+        InOrder inOrder = inOrder(adapter);
+
+        // Start is always called first.
+        inOrder.verify(adapter).onStart();
+
+        // Start is always followed by a layout. The PDF printer is selected if
+        // there are other printers but none of them was used.
+        PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
+        PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
+                .setMediaSize(getDefaultMediaSize())
+                .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
+                .setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+                .setDuplexMode(PrintAttributes.DUPLEX_MODE_NONE)
+                .build();
+        verifyLayoutCall(inOrder, adapter, firstOldAttributes, firstNewAttributes, true);
+
+        PageRange[] firstPage = new PageRange[] {new PageRange(0, 0)};
+        inOrder.verify(adapter).onWrite(eq(firstPage), any(ParcelFileDescriptor.class),
+                any(CancellationSignal.class), any(WriteResultCallback.class));
+
+        // Finish is always called last.
+        inOrder.verify(adapter).onFinish();
+
+        // No other call are expected.
+        verifyNoMoreInteractions(adapter);
+    }
+
     /**
      * Pretend to have written two pages, but only actually write one page
      *
@@ -1832,7 +2180,7 @@
                     PrinterCapabilitiesInfo firstCapabilities =
                             new PrinterCapabilitiesInfo.Builder(firstPrinterId)
                         .setMinMargins(new Margins(200, 200, 200, 200))
-                        .addMediaSize(MediaSize.ISO_A4, true)
+                        .addMediaSize(MediaSize.ISO_A0, true)
                         .addMediaSize(MediaSize.ISO_A5, false)
                         .addResolution(new Resolution("300x300", "300x300", 300, 300), true)
                         .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
@@ -1849,7 +2197,7 @@
                     PrinterCapabilitiesInfo secondCapabilities =
                             new PrinterCapabilitiesInfo.Builder(secondPrinterId)
                         .addMediaSize(MediaSize.ISO_A3, true)
-                        .addMediaSize(MediaSize.ISO_A4, false)
+                        .addMediaSize(MediaSize.ISO_A0, false)
                         .addResolution(new Resolution("200x200", "200x200", 200, 200), true)
                         .addResolution(new Resolution("300x300", "300x300", 300, 300), false)
                         .setColorModes(PrintAttributes.COLOR_MODE_COLOR
@@ -1870,12 +2218,17 @@
                     // Add the third printer.
                     PrinterId thirdPrinterId = service.generatePrinterId("third_printer");
                     PrinterCapabilitiesInfo thirdCapabilities =
-                            new PrinterCapabilitiesInfo.Builder(thirdPrinterId)
-                        .addMediaSize(MediaSize.NA_LETTER, true)
-                        .addResolution(new Resolution("300x300", "300x300", 300, 300), true)
-                        .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
-                                PrintAttributes.COLOR_MODE_COLOR)
-                        .build();
+                            null;
+                    try {
+                        thirdCapabilities = new PrinterCapabilitiesInfo.Builder(thirdPrinterId)
+                                .addMediaSize(getDefaultMediaSize(), true)
+                                .addResolution(new Resolution("300x300", "300x300", 300, 300), true)
+                                .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
+                                        PrintAttributes.COLOR_MODE_COLOR)
+                                .build();
+                    } catch (Exception e) {
+                        Log.e(LOG_TAG, "Cannot create third printer", e);
+                    }
                     PrinterInfo thirdPrinter = new PrinterInfo.Builder(thirdPrinterId,
                             "Third printer", PrinterInfo.STATUS_IDLE)
                         .setCapabilities(thirdCapabilities)
diff --git a/tests/tests/print/src/android/print/cts/PrintJobTest.java b/tests/tests/print/src/android/print/cts/PrintJobTest.java
index b0f3742e..fc099ce 100644
--- a/tests/tests/print/src/android/print/cts/PrintJobTest.java
+++ b/tests/tests/print/src/android/print/cts/PrintJobTest.java
@@ -37,8 +37,6 @@
 import android.print.cts.services.SecondPrintService;
 import android.print.cts.services.StubbablePrinterDiscoverySession;
 import android.printservice.PrintJob;
-import android.support.test.uiautomator.UiObject;
-import android.support.test.uiautomator.UiSelector;
 import android.util.Log;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
@@ -208,35 +206,6 @@
     }
 
     /**
-     * Make sure that a runnable eventually finishes without throwing a exception.
-     *
-     * @param r The runnable to run.
-     */
-    private static void eventually(Runnable r) {
-        final long TIMEOUT_MILLS = 5000;
-        long start = System.currentTimeMillis();
-
-        while (true) {
-            try {
-                r.run();
-                break;
-            } catch (Exception e) {
-                if (System.currentTimeMillis() - start < TIMEOUT_MILLS) {
-                    Log.e(LOG_TAG, "Ignoring exception as we know that the print spooler does " +
-                            "not guarantee to process commands in order", e);
-                    try {
-                        Thread.sleep(100);
-                    } catch (InterruptedException e1) {
-                        Log.e(LOG_TAG, "Interrupted", e);
-                    }
-                } else {
-                    throw e;
-                }
-            }
-        }
-    }
-
-    /**
      * Base test for the print job tests. Starts a print job and executes a testFn once the job is
      * queued.
      *
diff --git a/tests/tests/print/src/android/print/cts/PrinterCapabilitiesTest.java b/tests/tests/print/src/android/print/cts/PrinterCapabilitiesTest.java
index 8e3f984..91f9610 100644
--- a/tests/tests/print/src/android/print/cts/PrinterCapabilitiesTest.java
+++ b/tests/tests/print/src/android/print/cts/PrinterCapabilitiesTest.java
@@ -149,7 +149,8 @@
      * @throws Exception If anything was unexpected.
      */
     private void waitForPrinterUnavailable() throws Exception {
-        final String PRINTER_UNAVAILABLE_MSG = "This printer isn't available right now.";
+        final String PRINTER_UNAVAILABLE_MSG =
+                getPrintSpoolerString("print_error_printer_unavailable");
 
         UiObject message = getUiDevice().findObject(new UiSelector().resourceId(
                 "com.android.printspooler:id/message"));
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_ContactsTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_ContactsTest.java
index f8f610a..0c6f411 100644
--- a/tests/tests/provider/src/android/provider/cts/ContactsContract_ContactsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_ContactsTest.java
@@ -29,6 +29,7 @@
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
 import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Directory;
 import android.provider.cts.ContactsContract_TestDataBuilder.TestContact;
 import android.provider.cts.ContactsContract_TestDataBuilder.TestRawContact;
 import android.provider.cts.contacts.ContactUtil;
@@ -228,6 +229,15 @@
                 new long[]{contact.getId()}
         );
 
+        // Contacts.CONTENT_FILTER_URI
+        DatabaseAsserts.checkProjection(mResolver,
+                Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon().appendEncodedPath("xxx")
+                        .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+                                String.valueOf(Directory.DEFAULT)).build(),
+                PROJECTION,
+                new long[]{contact.getId()}
+        );
+
         // Contacts.CONTENT_LOOKUP_URI
         DatabaseAsserts.checkProjection(mResolver,
                 Contacts.getLookupUri(contactId, lookupKey),
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_DataTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_DataTest.java
index 33d3a28..62c6fdd 100644
--- a/tests/tests/provider/src/android/provider/cts/ContactsContract_DataTest.java
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_DataTest.java
@@ -36,6 +36,7 @@
 import android.provider.ContactsContract.Contacts;
 import android.provider.ContactsContract.Contacts.Entity;
 import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.Directory;
 import android.provider.ContactsContract.RawContacts;
 import android.provider.ContactsContract.RawContactsEntity;
 import android.provider.cts.ContactsContract_TestDataBuilder.TestContact;
@@ -533,6 +534,37 @@
         assertCursorStoredValuesWithRawContactsFilter(uri, ids, sContentValues[6]);
     }
 
+    public void testEnterpriseCallableFilterByNameOrOrganization_returnsCorrectDataRows()
+            throws Exception {
+        long[] ids = setupContactablesTestData();
+        Uri uri = Uri.withAppendedPath(Callable.ENTERPRISE_CONTENT_FILTER_URI, "doe").buildUpon()
+                .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+                        String.valueOf(Directory.DEFAULT))
+                .build();
+        // Only callables belonging to John Doe (name) and Cold Tamago (organization) are returned.
+        assertCursorStoredValuesWithRawContactsFilter(uri, ids, sContentValues[5],
+                sContentValues[6]);
+    }
+
+    public void testEnterpriseCallableFilterByNumber_returnsCorrectDataRows() throws Exception {
+        long[] ids = setupContactablesTestData();
+        Uri uri = Uri.withAppendedPath(Callable.ENTERPRISE_CONTENT_FILTER_URI, "510").buildUpon()
+                .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+                        String.valueOf(Directory.DEFAULT))
+                .build();
+        assertCursorStoredValuesWithRawContactsFilter(uri, ids, sContentValues[1]);
+    }
+
+    public void testEnterpriseCallableFilterBySipAddress_returnsCorrectDataRows()
+            throws Exception {
+        long[] ids = setupContactablesTestData();
+        Uri uri = Uri.withAppendedPath(Callable.ENTERPRISE_CONTENT_FILTER_URI, "mysip").buildUpon()
+                .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+                        String.valueOf(Directory.DEFAULT))
+                .build();
+        assertCursorStoredValuesWithRawContactsFilter(uri, ids, sContentValues[6]);
+    }
+
     public void testDataInsert_updatesContactLastUpdatedTimestamp() {
         DatabaseAsserts.ContactIdPair ids = DatabaseAsserts.assertAndCreateContact(mResolver);
         long baseTime = ContactUtil.queryContactLastUpdatedTimestamp(mResolver, ids.mContactId);
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_SearchSnippetsTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_SearchSnippetsTest.java
index 847e357..b049996 100644
--- a/tests/tests/provider/src/android/provider/cts/ContactsContract_SearchSnippetsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_SearchSnippetsTest.java
@@ -28,6 +28,7 @@
 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
 import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
 import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Directory;
 import android.provider.ContactsContract.RawContacts;
 import android.provider.ContactsContract.SearchSnippets;
 import android.provider.cts.ContactsContract_TestDataBuilder.TestContact;
@@ -85,6 +86,15 @@
         assertCursorStoredValuesWithContactsFilter(uri, ids);
     }
 
+    public void testEnterpriseSearchSnippets_NoMatch() throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+                .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+                        String.valueOf(Directory.DEFAULT)).appendPath("nomatch").build();
+
+        assertCursorStoredValuesWithContactsFilter(uri, ids);
+    }
+
     public void testSearchSnippets_MatchEmailAddressCorrectSnippet() throws Exception {
         long[] ids = setupTestData();
         final Uri uri = ContactsContract.Contacts.CONTENT_FILTER_URI.buildUpon()
@@ -96,6 +106,18 @@
         assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
     }
 
+    public void testEnterpriseSearchSnippets_MatchEmailAddressCorrectSnippet() throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+                .appendPath("farm").appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+                        String.valueOf(Directory.DEFAULT)).build();
+
+        final ContentValues expected = new ContentValues();
+        expected.put(Contacts._ID, ids[1]);
+        expected.put(SearchSnippets.SNIPPET, "eggs@[farmers].org");
+        assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+    }
+
     public void testSearchSnippets_MatchPhoneNumberCorrectSnippet() throws Exception {
         long[] ids = setupTestData();
         final Uri uri = ContactsContract.Contacts.CONTENT_FILTER_URI.buildUpon()
@@ -107,6 +129,18 @@
         assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
     }
 
+    public void testEnterpriseSearchSnippets_MatchPhoneNumberCorrectSnippet() throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+                .appendPath("510").appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+                        String.valueOf(Directory.DEFAULT)).build();
+
+        final ContentValues expected = new ContentValues();
+        expected.put(Contacts._ID, ids[0]);
+        expected.put(SearchSnippets.SNIPPET, "[510-123-5769]");
+        assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+    }
+
     public void testSearchSnippets_MatchPostalAddressCorrectSnippet() throws Exception {
         long[] ids = setupTestData();
         final Uri uri = ContactsContract.Contacts.CONTENT_FILTER_URI.buildUpon()
@@ -118,6 +152,18 @@
         assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
     }
 
+    public void testEnterpriseSearchSnippets_MatchPostalAddressCorrectSnippet() throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+                .appendPath("street").appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+                        String.valueOf(Directory.DEFAULT)).build();
+
+        final ContentValues expected = new ContentValues();
+        expected.put(Contacts._ID, ids[2]);
+        expected.put(SearchSnippets.SNIPPET, "123 Main [Street] Unit 3113\u2026");
+        assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+    }
+
     public void testSearchSnippets_LongMatchTruncation() throws Exception {
         long[] ids = setupTestData();
         final Uri uri = ContactsContract.Contacts.CONTENT_FILTER_URI.buildUpon()
@@ -129,6 +175,18 @@
         assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
     }
 
+    public void testEnterpriseSearchSnippets_LongMatchTruncation() throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+                .appendPath("over").appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+                        String.valueOf(Directory.DEFAULT)).build();
+
+        final ContentValues expected = new ContentValues();
+        expected.put(Contacts._ID, ids[2]);
+        expected.put(SearchSnippets.SNIPPET, "\u2026dog jumps [over] the quick\u2026");
+        assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+    }
+
     public void testSearchSnippets_MultipleMatchesCorrectSnippet() throws Exception {
         long[] ids = setupTestData();
         final Uri uri = ContactsContract.Contacts.CONTENT_FILTER_URI.buildUpon()
@@ -145,6 +203,23 @@
         assertCursorStoredValuesWithContactsFilter(uri, ids, expected, expected2);
     }
 
+    public void testEnterpriseSearchSnippets_MultipleMatchesCorrectSnippet() throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+                .appendPath("123").appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+                        String.valueOf(Directory.DEFAULT)).build();
+
+        final ContentValues expected = new ContentValues();
+        expected.put(Contacts._ID, ids[1]);
+        expected.put(SearchSnippets.SNIPPET, "[123-456-7890]");
+
+        final ContentValues expected2 = new ContentValues();
+        expected2.put(Contacts._ID, ids[2]);
+        expected2.put(SearchSnippets.SNIPPET, "[123] Main Street Unit 3113\u2026");
+
+        assertCursorStoredValuesWithContactsFilter(uri, ids, expected, expected2);
+    }
+
     /**
      * Tests that if deferred snippeting is indicated, the provider will not perform formatting
      * of the snippet for a single word query.
@@ -163,6 +238,25 @@
     }
 
     /**
+     * Tests that if deferred snippeting is indicated, the provider will not perform formatting
+     * of the snippet for a single word query.
+     */
+    public void testEnterpriseSearchSnippets_DeferredSnippetingSingleWordQuerySnippetDeferred()
+            throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+                .appendQueryParameter(SearchSnippets.DEFERRED_SNIPPETING_KEY, "1")
+                .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+                        String.valueOf(Directory.DEFAULT))
+                .appendPath("510").build();
+
+        final ContentValues expected = new ContentValues();
+        expected.put(Contacts._ID, ids[0]);
+        expected.put(SearchSnippets.SNIPPET, "510-123-5769");
+        assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+    }
+
+    /**
      * Tests that even if deferred snippeting is indicated, a multi-word query will have formatting
      * of the snippet done by the provider using SQLite
      */
@@ -180,6 +274,25 @@
     }
 
     /**
+     * Tests that even if deferred snippeting is indicated, a multi-word query will have formatting
+     * of the snippet done by the provider using SQLite
+     */
+    public void testEnterpriseSearchSnippets_DeferredSnippetingMultiWordQuerySnippetNotDeferred()
+            throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+                .appendQueryParameter(SearchSnippets.DEFERRED_SNIPPETING_KEY, "1")
+                .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+                        String.valueOf(Directory.DEFAULT))
+                .appendPath("jumps over").build();
+
+        final ContentValues expected = new ContentValues();
+        expected.put(Contacts._ID, ids[2]);
+        expected.put(SearchSnippets.SNIPPET, "\u2026lazy dog [jumps] [over] the\u2026");
+        assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+    }
+
+    /**
      * Given a uri, performs a query on the contacts provider for that uri and asserts that the
      * cursor returned from the query matches the expected results.
      *
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/reduce.rs b/tests/tests/renderscript/src/android/renderscript/cts/reduce.rs
index d731561..173c3ea 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/reduce.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/reduce.rs
@@ -428,8 +428,32 @@
 /////////////////////////////////////////////////////////////////////////
 
 // Test out-of-range result.
+
+// When a result is ulong, it can take on values not representable on
+// the Java side, where there are no unsigned integral types and long
+// is the largest integral type -- i.e., all values in the range
+// (MAX_LONG, MAX_ULONG] are not representable in Java.  The reflected
+// result_*.get() methods throw an exception if the result value is
+// out of range.  The globals and reduction kernels below allow a test
+// case on the Java side to describe what kind of result we should
+// produce -- in particular, what to use for an in-range value and an
+// out-of-range value, and where (if anywhere) to put an out-of-range
+// value within the result (which might be scalar, vector, array of
+// scalar, or array of vector).
+
 // We don't care about the input at all.
 // We use these globals to configure the generation of the result.
+// A kernel puts 2*oorrBadResultHalf in the position (if any) of the result
+// given by oorrBadResult, and oorrGoodResult everywhere else.
+// The oorrBadPos encoding is as follows:
+// - For scalar result, 0 = scalar; anything else = nowhere
+// - For vector result, 0..length(vector)-1 = corresponding vector component
+//     (0 = x, 1 = y, 2 = z, 3 = w); anything else = nowhere
+// - For array of scalar result, 0..length(array)-1 = corresponding array element;
+//     anything else = nowhere
+// - For array of vector result, 0..length(vector)*length(array)-1 = corresponding
+//     vector component C of corresponding array element E; anything else = nowhere
+//     (encoding is C + length(vector)*E)
 ulong oorrGoodResult;     // the value of a good result
 ulong oorrBadResultHalf;  // half the value of a bad result
                           //   ("half" because Java can only set the global from long not from ulong)
diff --git a/tests/tests/security/AndroidManifest.xml b/tests/tests/security/AndroidManifest.xml
index 7a67b08..1423aca 100644
--- a/tests/tests/security/AndroidManifest.xml
+++ b/tests/tests/security/AndroidManifest.xml
@@ -37,6 +37,14 @@
 
         <service android:name="android.security.cts.activity.SecureRandomService"
                  android:process=":secureRandom"/>
+        <activity
+            android:name="android.security.cts.DisplayDriverActivity"
+            android:label="Test qhwc::MDPCompLowRes::allocLayerPipes (Qualcomm)">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
+            </intent-filter>
+        </activity>
     </application>
 
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/security/res/layout/activity_displaydriver.xml b/tests/tests/security/res/layout/activity_displaydriver.xml
new file mode 100755
index 0000000..9009dbf
--- /dev/null
+++ b/tests/tests/security/res/layout/activity_displaydriver.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>

+<!--

+ * Copyright (C) 2016 The Android Open Source Project

+ *

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ -->

+<LinearLayout

+    xmlns:android="http://schemas.android.com/apk/res/android"

+    android:layout_width="fill_parent"

+    android:layout_height="fill_parent"

+    android:gravity="center"

+    android:orientation="vertical">

+

+    <VideoView

+        android:id="@+id/videoview"

+        android:layout_width="300dp"

+        android:layout_height="250dp"

+        android:layout_gravity="center"/>

+

+</LinearLayout>

+

+

+

+

diff --git a/tests/tests/security/res/raw/fuzz.webm b/tests/tests/security/res/raw/fuzz.webm
new file mode 100755
index 0000000..e5d95ce
--- /dev/null
+++ b/tests/tests/security/res/raw/fuzz.webm
Binary files differ
diff --git a/tests/app/app/src/android/app/stubs/ChildTabActivity.java b/tests/tests/security/src/android/security/cts/DisplayDriverActivity.java
old mode 100644
new mode 100755
similarity index 61%
rename from tests/app/app/src/android/app/stubs/ChildTabActivity.java
rename to tests/tests/security/src/android/security/cts/DisplayDriverActivity.java
index 1f0fb37..ca6c898
--- a/tests/app/app/src/android/app/stubs/ChildTabActivity.java
+++ b/tests/tests/security/src/android/security/cts/DisplayDriverActivity.java
@@ -1,25 +1,30 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.stubs;
-
-import android.app.Activity;
-
-/**
- * An empty activity for the TabActivity test
- */
-public class ChildTabActivity extends Activity {
-}
+/*

+ * Copyright (C) 2016 The Android Open Source Project

+ *

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+

+package android.security.cts;

+

+import android.security.cts.R;

+

+import android.app.Activity;

+import android.os.Bundle;

+

+public class DisplayDriverActivity extends Activity {

+    @Override

+    protected void onCreate(Bundle savedInstanceState) {

+        super.onCreate(savedInstanceState);

+        setContentView(R.layout.activity_displaydriver);

+    }

+}

diff --git a/tests/tests/security/src/android/security/cts/DisplayDriverTest.java b/tests/tests/security/src/android/security/cts/DisplayDriverTest.java
new file mode 100755
index 0000000..7f3a0d4
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/DisplayDriverTest.java
@@ -0,0 +1,115 @@
+/*

+ * Copyright (C) 2016 The Android Open Source Project

+ *

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+

+package android.security.cts;

+

+import android.security.cts.R;

+

+import android.app.Activity;

+import android.media.MediaPlayer;

+import android.media.MediaPlayer.OnErrorListener;

+import android.net.Uri;

+import android.os.SystemClock;

+import android.test.ActivityInstrumentationTestCase2;

+import android.widget.MediaController;

+import android.widget.VideoView;

+

+public class DisplayDriverTest extends

+        ActivityInstrumentationTestCase2<DisplayDriverActivity> {

+    /**

+     * The maximum time to wait for an operation.

+     */

+    private static final int TIMEOUT_ASYNC_PROCESSING = 3000;

+    private Activity mActivity;

+

+    public DisplayDriverTest() {

+        super(DisplayDriverActivity.class);

+    }

+

+    /**

+     * Checks whether video crashed or not

+     * 1. Initializes mTriggered to false

+     * 2. sets mTriggered to true if onError() occurred while playing video

+     */

+    private static class MockListener {

+        private boolean mTriggered;

+

+        MockListener() {

+            mTriggered = false;

+        }

+

+        public boolean isTriggered() {

+            return mTriggered;

+        }

+

+        protected void onEvent() {

+            mTriggered = true;

+        }

+    }

+

+    private static class MockOnErrorListener extends MockListener implements

+            OnErrorListener {

+        public boolean onError(MediaPlayer mp, int what, int extra) {

+            super.onEvent();

+            return false;

+        }

+    }

+

+    @Override

+    protected void setUp() throws Exception {

+        super.setUp();

+        mActivity = getActivity();

+        assertNotNull("Failed to get the activity instance", mActivity);

+    }

+

+    /**

+     * 1. Runs the vulnerable video by registering OnErrorListener for VideoView

+     * 2. Wait for max time taken by video to crash and hit OnErrorListener

+     * 3. if video crashed - Pass the test case otherwise Fail the test case

+     */

+    public void testDisplayDriver_cve_2015_6634() {

+        final MockOnErrorListener listener = new MockOnErrorListener();

+        mActivity.runOnUiThread(new Runnable() {

+            @Override

+            public void run() {

+                try {

+                    MediaController mMediaControls =

+                            new MediaController(mActivity);

+                    VideoView mVideoView =

+                            (VideoView) mActivity.findViewById(R.id.videoview);

+                    mVideoView.setMediaController(mMediaControls);

+                    mVideoView.setOnErrorListener(listener);

+                    mVideoView.setVideoURI(Uri.parse("android.resource://" +

+                            mActivity.getPackageName() + "/" + R.raw.fuzz));

+                    mVideoView.start();

+                } catch (Exception e) {

+                    listener.onError(null, 0, 0);

+                }

+            }

+        });

+        SystemClock.sleep(TIMEOUT_ASYNC_PROCESSING);

+        assertTrue("Test case failed due to vulnerability in the video: " +

+                        "Device is vulenrable to CVE-2015-6634", listener.isTriggered());

+    }

+

+    @Override

+    protected void tearDown() throws Exception {

+        if (mActivity != null) {

+            mActivity.finish();

+        }

+        super.tearDown();

+    }

+}

diff --git a/tests/tests/speech/Android.mk b/tests/tests/speech/Android.mk
index 3d95053..68e0cba 100755
--- a/tests/tests/speech/Android.mk
+++ b/tests/tests/speech/Android.mk
@@ -21,7 +21,7 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/systemui/Android.mk b/tests/tests/systemui/Android.mk
index 536d2a8..c31d825 100644
--- a/tests/tests/systemui/Android.mk
+++ b/tests/tests/systemui/Android.mk
@@ -26,7 +26,7 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/telecom/Android.mk b/tests/tests/telecom/Android.mk
index 5a8922e..27947af 100644
--- a/tests/tests/telecom/Android.mk
+++ b/tests/tests/telecom/Android.mk
@@ -24,7 +24,7 @@
 # When built, explicitly put it in the data partition.
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/telephony/src/android/telephony/cts/SimRestrictedApisTest.java b/tests/tests/telephony/src/android/telephony/cts/SimRestrictedApisTest.java
index 0f09314..b15a4e8 100644
--- a/tests/tests/telephony/src/android/telephony/cts/SimRestrictedApisTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/SimRestrictedApisTest.java
@@ -265,4 +265,20 @@
         } catch (SecurityException expected) {
         }
     }
+
+    /**
+     * Tests the TelephonyManager.getIccAuthentication() API. This makes a call to
+     * getIccAuthentication() API and expects a SecurityException since the test apk is not
+     * signed by certificate on the SIM.
+     */
+    public void testGetIccAuthentication() {
+        try {
+            if (isSimCardPresent()) {
+                TelephonyManager.getDefault().getIccAuthentication(TelephonyManager.APPTYPE_USIM,
+                        TelephonyManager.AUTHTYPE_EAP_AKA, "");
+                fail("Expected SecurityException. App doesn't have carrier privileges.");
+            }
+        } catch (SecurityException expected) {
+        }
+    }
 }
diff --git a/tests/tests/text/Android.mk b/tests/tests/text/Android.mk
index 65a93fb..731fa9b 100644
--- a/tests/tests/text/Android.mk
+++ b/tests/tests/text/Android.mk
@@ -23,7 +23,7 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctsdeviceutillegacy ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctsdeviceutillegacy ctstestrunner android-support-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/text/AndroidManifest.xml b/tests/tests/text/AndroidManifest.xml
index fea237f..40a0b50 100644
--- a/tests/tests/text/AndroidManifest.xml
+++ b/tests/tests/text/AndroidManifest.xml
@@ -68,7 +68,7 @@
                 <category android:name="android.intent.category.DEFAULT" />
                 <category android:name="android.intent.category.BROWSABLE" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-                <data android:scheme="ctstest" />
+                <data android:scheme="ctstesttext" />
             </intent-filter>
         </activity>
 
diff --git a/tests/tests/text/res/values/strings.xml b/tests/tests/text/res/values/strings.xml
index c167278..b3db2a6 100644
--- a/tests/tests/text/res/values/strings.xml
+++ b/tests/tests/text/res/values/strings.xml
@@ -165,7 +165,7 @@
    <string name="themes_prompt">Select a Theme:</string>
    <string name="sample_text">Sample text goes here. I wanted something creative and whimsical
 but then I just got bored...</string>
-    <string name="long_text">This is a really long string which exceeds the width of the view.
+   <string name="long_text">This is a really long string which exceeds the width of the view.
 New devices have a much larger screen which actually enables long strings to be displayed
 with no fading. I have made this string longer to fix this case. If you are correcting this
 text, I would love to see the kind of devices you guys now use! Guys, maybe some devices need longer string!
@@ -176,4 +176,8 @@
 text, I would love to see the kind of devices you guys now use! Guys, maybe some devices need longer string!
 I think so, so how about double this string, like copy and paste! </string>
     <string name="rectangle200">"M 0,0 l 200,0 l 0, 200 l -200, 0 z"</string>
+    <plurals name="list_ellipsize_test">
+        <item quantity="one">one more</item>
+        <item quantity="other"><xliff:g id="number">%d</xliff:g> more</item>
+    </plurals>
 </resources>
diff --git a/tests/tests/text/src/android/text/cts/BidiFormatterTest.java b/tests/tests/text/src/android/text/cts/BidiFormatterTest.java
index 3e5db4d..b7aec1b 100644
--- a/tests/tests/text/src/android/text/cts/BidiFormatterTest.java
+++ b/tests/tests/text/src/android/text/cts/BidiFormatterTest.java
@@ -16,9 +16,13 @@
 
 package android.text.cts;
 
+import android.icu.util.ULocale;
 import android.test.AndroidTestCase;
 import android.text.BidiFormatter;
+import android.text.SpannableString;
+import android.text.Spanned;
 import android.text.TextDirectionHeuristics;
+import android.text.style.RelativeSizeSpan;
 
 import java.util.Locale;
 
@@ -233,4 +237,83 @@
                 LRE + HE + EN + HE + PDF,
                 RTL_FMT_EXIT_RESET.unicodeWrap(HE + EN + HE, TextDirectionHeuristics.LTR, false));
     }
+
+    public void testGetStereoReset() {
+        assertTrue(LTR_FMT.getStereoReset());
+        assertTrue(RTL_FMT.getStereoReset());
+        assertFalse(LTR_FMT_EXIT_RESET.getStereoReset());
+        assertFalse(RTL_FMT_EXIT_RESET.getStereoReset());
+    }
+
+    public void testBuilder_construction() {
+        final BidiFormatter defaultFmt = new BidiFormatter.Builder().build();
+        // Test that the default locale and the BidiFormatter's locale have the same direction.
+        assertEquals(ULocale.getDefault().isRightToLeft(), defaultFmt.isRtlContext());
+
+        final BidiFormatter ltrFmt = new BidiFormatter.Builder(false).build();
+        assertFalse(ltrFmt.isRtlContext());
+
+        final BidiFormatter rtlFmt = new BidiFormatter.Builder(true).build();
+        assertTrue(rtlFmt.isRtlContext());
+
+        final BidiFormatter englishFmt = new BidiFormatter.Builder(Locale.ENGLISH).build();
+        assertFalse(englishFmt.isRtlContext());
+
+        final BidiFormatter arabicFmt =
+                new BidiFormatter.Builder(Locale.forLanguageTag("ar")).build();
+        assertTrue(arabicFmt.isRtlContext());
+    }
+
+    public void testBuilder_setTextDirectionHeuristic() {
+        final BidiFormatter defaultFmt = new BidiFormatter.Builder().build();
+        assertFalse(defaultFmt.isRtl(EN + HE + EN));
+
+        final BidiFormatter modifiedFmt = new BidiFormatter.Builder().setTextDirectionHeuristic(
+                TextDirectionHeuristics.ANYRTL_LTR).build();
+        assertTrue(modifiedFmt.isRtl(EN + HE + EN));
+    }
+
+    public void testCharSequenceApis() {
+        final CharSequence CS_HE = new SpannableString(HE);
+        assertEquals(true, BidiFormatter.getInstance(true).isRtl(CS_HE));
+
+        final SpannableString CS_EN_HE = new SpannableString(EN + HE);
+        final Object RELATIVE_SIZE_SPAN = new RelativeSizeSpan(1.2f);
+        CS_EN_HE.setSpan(RELATIVE_SIZE_SPAN, 0, EN.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+
+        Spanned wrapped;
+        Object[] spans;
+
+        wrapped = (Spanned) LTR_FMT.unicodeWrap(CS_EN_HE);
+        assertEquals(EN + HE + LRM, wrapped.toString());
+        spans = wrapped.getSpans(0, wrapped.length(), Object.class);
+        assertEquals(1, spans.length);
+        assertEquals(RELATIVE_SIZE_SPAN, spans[0]);
+        assertEquals(0, wrapped.getSpanStart(RELATIVE_SIZE_SPAN));
+        assertEquals(EN.length(), wrapped.getSpanEnd(RELATIVE_SIZE_SPAN));
+
+        wrapped = (Spanned) LTR_FMT.unicodeWrap(CS_EN_HE, TextDirectionHeuristics.LTR);
+        assertEquals(EN + HE + LRM, wrapped.toString());
+        spans = wrapped.getSpans(0, wrapped.length(), Object.class);
+        assertEquals(1, spans.length);
+        assertEquals(RELATIVE_SIZE_SPAN, spans[0]);
+        assertEquals(0, wrapped.getSpanStart(RELATIVE_SIZE_SPAN));
+        assertEquals(EN.length(), wrapped.getSpanEnd(RELATIVE_SIZE_SPAN));
+
+        wrapped = (Spanned) LTR_FMT.unicodeWrap(CS_EN_HE, false);
+        assertEquals(EN + HE, wrapped.toString());
+        spans = wrapped.getSpans(0, wrapped.length(), Object.class);
+        assertEquals(1, spans.length);
+        assertEquals(RELATIVE_SIZE_SPAN, spans[0]);
+        assertEquals(0, wrapped.getSpanStart(RELATIVE_SIZE_SPAN));
+        assertEquals(EN.length(), wrapped.getSpanEnd(RELATIVE_SIZE_SPAN));
+
+        wrapped = (Spanned) LTR_FMT.unicodeWrap(CS_EN_HE, TextDirectionHeuristics.LTR, false);
+        assertEquals(EN + HE, wrapped.toString());
+        spans = wrapped.getSpans(0, wrapped.length(), Object.class);
+        assertEquals(1, spans.length);
+        assertEquals(RELATIVE_SIZE_SPAN, spans[0]);
+        assertEquals(0, wrapped.getSpanStart(RELATIVE_SIZE_SPAN));
+        assertEquals(EN.length(), wrapped.getSpanEnd(RELATIVE_SIZE_SPAN));
+    }
 }
diff --git a/tests/tests/text/src/android/text/cts/SpannableStringBuilderTest.java b/tests/tests/text/src/android/text/cts/SpannableStringBuilderTest.java
index 6dee5e9..09b5dbf 100644
--- a/tests/tests/text/src/android/text/cts/SpannableStringBuilderTest.java
+++ b/tests/tests/text/src/android/text/cts/SpannableStringBuilderTest.java
@@ -21,19 +21,20 @@
 import android.test.suitebuilder.annotation.SmallTest;
 import android.text.Editable;
 import android.text.InputFilter;
+import android.text.Selection;
 import android.text.SpannableString;
 import android.text.SpannableStringBuilder;
 import android.text.Spanned;
 import android.text.TextWatcher;
 import android.text.style.BulletSpan;
-import android.text.style.ParagraphStyle;
 import android.text.style.QuoteSpan;
-import android.text.style.RelativeSizeSpan;
 import android.text.style.StrikethroughSpan;
 import android.text.style.SubscriptSpan;
 import android.text.style.TabStopSpan;
 import android.text.style.UnderlineSpan;
 
+import java.util.Arrays;
+
 /**
  * Test {@link SpannableStringBuilder}.
  */
@@ -377,6 +378,28 @@
         }
     }
 
+    @SmallTest
+    public void testAppend_textWithSpan() {
+        final QuoteSpan span = new QuoteSpan();
+        final SpannableStringBuilder builder = new SpannableStringBuilder("hello ");
+        final int spanStart = builder.length();
+        builder.append("planet", span, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        final int spanEnd = builder.length();
+        builder.append(" earth");
+
+        assertEquals("SpannableStringBuilder.append should append text to existing whole text",
+                "hello planet earth", builder.toString());
+
+        final Object[] spans = builder.getSpans(0, builder.length(), Object.class);
+        assertNotNull("Appended text included a Quote span", spans);
+        assertEquals("Appended text included a Quote span", 1, spans.length);
+        assertSame("Should be the same span instance", span, spans[0]);
+        assertEquals("Appended span should start at appended text start",
+                spanStart, builder.getSpanStart(spans[0]));
+        assertEquals("Appended span should end at appended text end",
+                spanEnd, builder.getSpanEnd(spans[0]));
+    }
+
     public void testClearSpans() {
         SpannableStringBuilder builder = new SpannableStringBuilder("hello, world");
 
@@ -688,6 +711,19 @@
         assertEquals(0, builder.length());
     }
 
+    public void testReplace_shouldNotThrowIndexOutOfBoundsExceptionForLongText() {
+        final char[] charArray = new char[75000];
+        Arrays.fill(charArray, 'a');
+        final String text = new String(charArray, 0, 50000);
+        final String copiedText = new String(charArray);
+        final SpannableStringBuilder spannable = new SpannableStringBuilder(text);
+        Selection.setSelection(spannable, text.length());
+
+        spannable.replace(0, text.length(), copiedText);
+
+        assertEquals(copiedText.length(), spannable.length());
+    }
+
     public void testDelete() {
         SpannableStringBuilder builder = new SpannableStringBuilder("hello,world");
         assertEquals("hello,world", builder.toString());
diff --git a/tests/tests/text/src/android/text/cts/StaticLayoutTest.java b/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
index ed3f1ea..f66f4c0 100644
--- a/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
+++ b/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
@@ -100,8 +100,6 @@
                 maxLines);
     }
 
-
-
     /**
      * Constructor test
      */
@@ -523,37 +521,53 @@
                     TextUtils.TruncateAt.MARQUEE, 1);
             assertTrue(layout.getEllipsisCount(0) == 0);
         }
+        {
+            final String text = "\u3042" // HIRAGANA LETTER A
+                    + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
+            final float textWidth = mDefaultPaint.measureText(text);
+            final int halfWidth = (int)(textWidth / 2.0f);
+            {
+                StaticLayout layout = new StaticLayout(text, 0, text.length(), mDefaultPaint,
+                        halfWidth, DEFAULT_ALIGN, TextDirectionHeuristics.FIRSTSTRONG_LTR,
+                        SPACE_MULTI, SPACE_ADD, false, TextUtils.TruncateAt.END, halfWidth, 1);
+                assertTrue(layout.getEllipsisCount(0) > 0);
+                assertTrue(layout.getEllipsisStart(0) > 0);
+            }
+            {
+                StaticLayout layout = new StaticLayout(text, 0, text.length(), mDefaultPaint,
+                        halfWidth, DEFAULT_ALIGN, TextDirectionHeuristics.FIRSTSTRONG_LTR,
+                        SPACE_MULTI, SPACE_ADD, false, TextUtils.TruncateAt.START, halfWidth, 1);
+                assertTrue(layout.getEllipsisCount(0) > 0);
+                assertEquals(0, mDefaultLayout.getEllipsisStart(0));
+            }
+            {
+                StaticLayout layout = new StaticLayout(text, 0, text.length(), mDefaultPaint,
+                        halfWidth, DEFAULT_ALIGN, TextDirectionHeuristics.FIRSTSTRONG_LTR,
+                        SPACE_MULTI, SPACE_ADD, false, TextUtils.TruncateAt.MIDDLE, halfWidth, 1);
+                assertTrue(layout.getEllipsisCount(0) > 0);
+                assertTrue(layout.getEllipsisStart(0) > 0);
+            }
+            {
+                StaticLayout layout = new StaticLayout(text, 0, text.length(), mDefaultPaint,
+                        halfWidth, DEFAULT_ALIGN, TextDirectionHeuristics.FIRSTSTRONG_LTR,
+                        SPACE_MULTI, SPACE_ADD, false, TextUtils.TruncateAt.MARQUEE, halfWidth, 1);
+                assertEquals(0, layout.getEllipsisCount(0));
+            }
+        }
 
-        final String text = "\u3042" // HIRAGANA LETTER A
-                + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
-        final float textWidth = mDefaultPaint.measureText(text);
-        final int halfWidth = (int)(textWidth / 2.0f);
         {
-            StaticLayout layout = new StaticLayout(text, 0, text.length(), mDefaultPaint,
-                    halfWidth, DEFAULT_ALIGN, TextDirectionHeuristics.FIRSTSTRONG_LTR,
-                    SPACE_MULTI, SPACE_ADD, false, TextUtils.TruncateAt.END, halfWidth, 1);
-            assertTrue(layout.getEllipsisCount(0) > 0);
-            assertTrue(layout.getEllipsisStart(0) > 0);
-        }
-        {
-            StaticLayout layout = new StaticLayout(text, 0, text.length(), mDefaultPaint,
-                    halfWidth, DEFAULT_ALIGN, TextDirectionHeuristics.FIRSTSTRONG_LTR,
-                    SPACE_MULTI, SPACE_ADD, false, TextUtils.TruncateAt.START, halfWidth, 1);
-            assertTrue(layout.getEllipsisCount(0) > 0);
-            assertEquals(0, mDefaultLayout.getEllipsisStart(0));
-        }
-        {
-            StaticLayout layout = new StaticLayout(text, 0, text.length(), mDefaultPaint,
-                    halfWidth, DEFAULT_ALIGN, TextDirectionHeuristics.FIRSTSTRONG_LTR,
-                    SPACE_MULTI, SPACE_ADD, false, TextUtils.TruncateAt.MIDDLE, halfWidth, 1);
-            assertTrue(layout.getEllipsisCount(0) > 0);
-            assertTrue(layout.getEllipsisStart(0) > 0);
-        }
-        {
-            StaticLayout layout = new StaticLayout(text, 0, text.length(), mDefaultPaint,
-                    halfWidth, DEFAULT_ALIGN, TextDirectionHeuristics.FIRSTSTRONG_LTR,
-                    SPACE_MULTI, SPACE_ADD, false, TextUtils.TruncateAt.MARQUEE, halfWidth, 1);
-            assertEquals(0, layout.getEllipsisCount(0));
+            // The white spaces in this text will be trailing if maxLines is larger than 1, but
+            // width of the trailing white spaces must not be ignored if ellipsis is applied.
+            final String text = "abc                                             def";
+            final float textWidth = mDefaultPaint.measureText(text);
+            final int halfWidth = (int)(textWidth / 2.0f);
+            {
+                StaticLayout layout = new StaticLayout(text, 0, text.length(), mDefaultPaint,
+                        halfWidth, DEFAULT_ALIGN, TextDirectionHeuristics.FIRSTSTRONG_LTR,
+                        SPACE_MULTI, SPACE_ADD, false, TextUtils.TruncateAt.END, halfWidth, 1);
+                assertTrue(layout.getEllipsisCount(0) > 0);
+                assertTrue(layout.getEllipsisStart(0) > 0);
+            }
         }
     }
 
diff --git a/tests/tests/text/src/android/text/cts/TextUtilsTest.java b/tests/tests/text/src/android/text/cts/TextUtilsTest.java
index 0da1eb4..1b97c95 100644
--- a/tests/tests/text/src/android/text/cts/TextUtilsTest.java
+++ b/tests/tests/text/src/android/text/cts/TextUtilsTest.java
@@ -20,12 +20,16 @@
 import static android.view.View.LAYOUT_DIRECTION_LTR;
 import static android.view.View.LAYOUT_DIRECTION_RTL;
 
+import android.content.Context;
 import android.content.res.ColorStateList;
+import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Paint.FontMetricsInt;
 import android.graphics.Typeface;
+import android.os.LocaleList;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.test.AndroidTestCase;
@@ -45,6 +49,8 @@
 import android.util.StringBuilderPrinter;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 import java.util.Locale;
 import java.util.regex.Pattern;
 
@@ -80,6 +86,109 @@
         return re.substring(0, re.indexOf("x"));
     }
 
+    /**
+     * @return the number of times the code unit appears in the CharSequence.
+     */
+    private int countChars(CharSequence s, char c) {
+        int count = 0;
+        for (int i = 0; i < s.length(); i++) {
+            if (s.charAt(i) == c) {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    public void testListEllipsize() {
+        final Context context = getContext();
+        final TextPaint paint = new TextPaint();
+        final int moreId = R.plurals.list_ellipsize_test;  // "one more" for 1, "%d more" for other
+
+        final List fullList = Arrays.asList("A", "B", "C", "D", "E", "F", "G", "H", "I", "J");
+        final String separator = ", ";
+        final String fullString = TextUtils.join(separator, fullList);
+        final float fullWidth = paint.measureText(fullString);
+        assertEquals("",
+            TextUtils.listEllipsize(context, null, separator, paint, fullWidth, moreId));
+
+        final List<CharSequence> emptyList = new ArrayList<CharSequence>();
+        assertEquals("",
+            TextUtils.listEllipsize(context, emptyList, separator, paint, fullWidth, moreId));
+
+        // Null context should cause ellipsis to be used at the end.
+        final String ellipsizedWithNull = TextUtils.listEllipsize(
+                null, fullList, separator, paint, fullWidth / 2, 0).toString();
+        assertTrue(ellipsizedWithNull.endsWith(getEllipsis()));
+
+        // Test that the empty string gets returned if there's no space.
+        assertEquals("",
+                TextUtils.listEllipsize(context, fullList, separator, paint, 1.0f, moreId));
+
+        // Test that the full string itself can get returned if there's enough space.
+        assertEquals(fullString,
+                TextUtils.listEllipsize(context, fullList, separator, paint, fullWidth, moreId)
+                        .toString());
+        assertEquals(fullString,
+                TextUtils.listEllipsize(context, fullList, separator, paint, fullWidth * 2,
+                        moreId).toString());
+
+        final float epsilon = fullWidth / 20;
+        for (float width = epsilon; width < fullWidth - epsilon / 2; width += epsilon) {
+            final String ellipsized = TextUtils.listEllipsize(
+                    context, fullList, separator, paint, width, moreId).toString();
+            // Since we don't have the full space, test that we are not getting the full string.
+            assertFalse(fullString.equals(ellipsized));
+
+            if (!ellipsized.isEmpty()) {
+                assertTrue(ellipsized.endsWith(" more"));
+                // Test that the number of separators (which equals the number of output elements),
+                // plus the number output before more always equals the number of original elements.
+                final int lastSpace = ellipsized.lastIndexOf(' ');
+                final int penultimateSpace = ellipsized.lastIndexOf(' ', lastSpace - 1);
+                assertEquals(',', ellipsized.charAt(penultimateSpace - 1));
+                final String moreCountString = ellipsized.substring(
+                        penultimateSpace + 1, lastSpace);
+                final int moreCount = (moreCountString.equals("one"))
+                        ? 1 : Integer.parseInt(moreCountString);
+                final int commaCount = countChars(ellipsized, ',');
+                assertEquals(fullList.size(), commaCount + moreCount);
+            }
+        }
+}
+
+    public void testListEllipsize_rtl() {
+        final Context context = getContext();
+        final Resources res = context.getResources();
+        final Configuration newConfig = new Configuration(res.getConfiguration());
+
+        // save the locales and set them to just Arabic
+        final LocaleList previousLocales = newConfig.getLocales();
+        newConfig.setLocales(LocaleList.forLanguageTags("ar"));
+        res.updateConfiguration(newConfig, null);
+
+        try {
+            final TextPaint paint = new TextPaint();
+            final int moreId = R.plurals.list_ellipsize_test;  // "one more" for 1, else "%d more"
+            final String RLM = "\u200F";
+            final String LRE = "\u202A";
+            final String PDF = "\u202C";
+
+            final List fullList = Arrays.asList("A", "B");
+            final String separator = ", ";
+            final String expectedString =
+                    RLM + LRE + "A" + PDF + RLM + ", " + RLM + LRE + "B" + PDF + RLM;
+            final float enoughWidth = paint.measureText(expectedString);
+
+            assertEquals(expectedString,
+                    TextUtils.listEllipsize(context, fullList, separator, paint, enoughWidth,
+                                            moreId).toString());
+        } finally {
+            // Restore the original locales
+            newConfig.setLocales(previousLocales);
+            res.updateConfiguration(newConfig, null);
+        }
+    }
+
     public void testCommaEllipsize() {
         TextPaint p = new TextPaint();
         String text = "long, string, to, truncate";
diff --git a/tests/tests/text/src/android/text/format/cts/FormatterTest.java b/tests/tests/text/src/android/text/format/cts/FormatterTest.java
index 6acfb84..5ae19e7 100644
--- a/tests/tests/text/src/android/text/format/cts/FormatterTest.java
+++ b/tests/tests/text/src/android/text/format/cts/FormatterTest.java
@@ -20,16 +20,18 @@
 import java.math.MathContext;
 
 import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.text.format.Formatter;
 
 public class FormatterTest extends AndroidTestCase {
 
+    @SmallTest
     public void testFormatFileSize() {
         // test null Context
         assertEquals("", Formatter.formatFileSize(null, 0));
 
         MathContext mc = MathContext.DECIMAL64;
-        BigDecimal bd = new BigDecimal((long) 1024, mc);
+        BigDecimal bd = new BigDecimal((long) 1000, mc);
 
         // test different long values with various length
         assertEquals("0 B", Formatter.formatFileSize(mContext, 0));
@@ -39,9 +41,9 @@
         assertEquals("99 B", Formatter.formatFileSize(mContext, 99));
         assertEquals("100 B", Formatter.formatFileSize(mContext, 100));
         assertEquals("900 B", Formatter.formatFileSize(mContext, 900));
-        assertEquals("0.88 KB", Formatter.formatFileSize(mContext, 901));
+        assertEquals("0.90 kB", Formatter.formatFileSize(mContext, 901));
 
-        assertEquals("1.00 KB", Formatter.formatFileSize(mContext, bd.pow(1).longValue()));
+        assertEquals("1.00 kB", Formatter.formatFileSize(mContext, bd.pow(1).longValue()));
 
         assertEquals("1.00 MB", Formatter.formatFileSize(mContext, bd.pow(2).longValue()));
 
@@ -51,12 +53,13 @@
 
         assertEquals("1.00 PB", Formatter.formatFileSize(mContext, bd.pow(5).longValue()));
 
-        assertEquals("1024 PB", Formatter.formatFileSize(mContext, bd.pow(6).longValue()));
+        assertEquals("1000 PB", Formatter.formatFileSize(mContext, bd.pow(6).longValue()));
 
         // test Negative value
         assertEquals("-1 B", Formatter.formatFileSize(mContext, -1));
     }
 
+    @SmallTest
     public void testFormatIpAddress() {
         assertEquals("1.0.168.192", Formatter.formatIpAddress(0xC0A80001));
         assertEquals("1.0.0.127", Formatter.formatIpAddress(0x7F000001));
diff --git a/tests/tests/text/src/android/text/method/cts/BackspaceTest.java b/tests/tests/text/src/android/text/method/cts/BackspaceTest.java
index 1705326..212d4eb 100644
--- a/tests/tests/text/src/android/text/method/cts/BackspaceTest.java
+++ b/tests/tests/text/src/android/text/method/cts/BackspaceTest.java
@@ -59,6 +59,31 @@
     }
 
     @SmallTest
+    public void testCRLF() {
+        EditorState state = new EditorState();
+
+        // U+000A is LINE FEED.
+        state.setByString("U+000A |");
+        backspace(state, 0);
+        state.assertEquals("|");
+
+        // U+000D is CARRIAGE RETURN.
+        state.setByString("U+000D |");
+        backspace(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("U+000D U+000A |");
+        backspace(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("U+000A U+000D |");
+        backspace(state, 0);
+        state.assertEquals("U+000A |");
+        backspace(state, 0);
+        state.assertEquals("|");
+    }
+
+    @SmallTest
     public void testSurrogatePairs() {
         EditorState state = new EditorState();
 
diff --git a/tests/tests/text/src/android/text/method/cts/ForwardDeleteTest.java b/tests/tests/text/src/android/text/method/cts/ForwardDeleteTest.java
index 40ed593..3b226fb 100644
--- a/tests/tests/text/src/android/text/method/cts/ForwardDeleteTest.java
+++ b/tests/tests/text/src/android/text/method/cts/ForwardDeleteTest.java
@@ -59,6 +59,30 @@
     }
 
     @SmallTest
+    public void testCRLF() {
+        EditorState state = new EditorState();
+
+        // U+000A is LINE FEED.
+        state.setByString("| U+000A");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // U+000D is CARRIAGE RETURN.
+        state.setByString("| U+000D");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("| U+000D U+000A");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("| U+000A U+000D");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+000D");
+        forwardDelete(state, 0);
+    }
+
+    @SmallTest
     public void testSurrogatePairs() {
         EditorState state = new EditorState();
 
diff --git a/tests/tests/text/src/android/text/style/cts/SuggestionSpanTest.java b/tests/tests/text/src/android/text/style/cts/SuggestionSpanTest.java
index ff5167c..ef883b1 100644
--- a/tests/tests/text/src/android/text/style/cts/SuggestionSpanTest.java
+++ b/tests/tests/text/src/android/text/style/cts/SuggestionSpanTest.java
@@ -21,12 +21,111 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Parcel;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.text.style.SuggestionSpan;
 
 import java.util.Locale;
 
+import static org.junit.Assert.assertArrayEquals;
+
 public class SuggestionSpanTest extends TestCase {
 
+    @SmallTest
+    public void testGetSuggestionSpans() {
+        final String[] suggestions = new String[]{"suggestion1", "suggestion2"};
+        final SuggestionSpan span = new SuggestionSpan(Locale.forLanguageTag("en"), suggestions,
+                SuggestionSpan.FLAG_AUTO_CORRECTION);
+        assertArrayEquals("Should return the correct suggestions array",
+                suggestions, span.getSuggestions());
+
+        final SuggestionSpan clonedSpan = cloneViaParcel(span);
+        assertArrayEquals("Should (de)serialize suggestions",
+                suggestions, clonedSpan.getSuggestions());
+    }
+
+    @SmallTest
+    public void testGetSuggestionSpans_emptySuggestions() {
+        final String[] suggestions = new String[0];
+        final SuggestionSpan span = new SuggestionSpan(Locale.forLanguageTag("en"), suggestions,
+                SuggestionSpan.FLAG_AUTO_CORRECTION);
+        assertArrayEquals("Span should return empty suggestion array",
+                suggestions, span.getSuggestions());
+
+        // also test parceling
+        final SuggestionSpan clonedSpan = cloneViaParcel(span);
+        assertArrayEquals("Should (de)serialize empty suggestions array",
+                suggestions, clonedSpan.getSuggestions());
+    }
+
+    @SmallTest
+    public void testGetSuggestionSpans_suggestionsWithNullValue() {
+        final String[] suggestions = new String[]{"suggestion", null};
+        final SuggestionSpan span = new SuggestionSpan(Locale.forLanguageTag("en"), suggestions,
+                SuggestionSpan.FLAG_AUTO_CORRECTION);
+        assertArrayEquals("Should accept and return null suggestions",
+                suggestions, span.getSuggestions());
+
+        final SuggestionSpan clonedSpan = cloneViaParcel(span);
+        assertArrayEquals("Should (de)serialize null in suggestions array",
+                suggestions, clonedSpan.getSuggestions());
+    }
+
+    @SmallTest
+    public void testGetFlags() {
+        final String[] anySuggestions = new String[0];
+        final int flag = SuggestionSpan.FLAG_AUTO_CORRECTION;
+        SuggestionSpan span = new SuggestionSpan(Locale.forLanguageTag("en"), anySuggestions, flag);
+
+        assertEquals("Should return the flag passed in constructor",
+                flag, span.getFlags());
+
+        final SuggestionSpan clonedSpan = cloneViaParcel(span);
+        assertEquals("Should (de)serialize flags", flag, clonedSpan.getFlags());
+    }
+
+    @SmallTest
+    public void testEquals_returnsTrueForDeserializedInstances() {
+        final SuggestionSpan span1 = new SuggestionSpan(null, Locale.forLanguageTag("en"),
+                new String[0], SuggestionSpan.FLAG_AUTO_CORRECTION, SuggestionSpan.class);
+        final SuggestionSpan span2 = cloneViaParcel(span1);
+
+        assertTrue("(De)serialized instances should be equal", span1.equals(span2));
+    }
+
+    @SmallTest
+    public void testEquals_returnsTrueIfTheFlagsAreDifferent() {
+        final SuggestionSpan span1 = new SuggestionSpan(null, Locale.forLanguageTag("en"),
+                new String[0], SuggestionSpan.FLAG_AUTO_CORRECTION, SuggestionSpan.class);
+        final SuggestionSpan span2 = cloneViaParcel(span1);
+        span2.setFlags(SuggestionSpan.FLAG_EASY_CORRECT);
+
+        assertEquals("Should return the flag passed in set function",
+                SuggestionSpan.FLAG_EASY_CORRECT, span2.getFlags());
+
+        assertTrue("Instances with different flags should be equal", span1.equals(span2));
+    }
+
+    @SmallTest
+    public void testEquals_returnsFalseIfCreationTimeIsNotSame() {
+        final Locale anyLocale = Locale.forLanguageTag("en");
+        final String[] anySuggestions = new String[0];
+        final int anyFlags = SuggestionSpan.FLAG_AUTO_CORRECTION;
+        final Class anyClass = SuggestionSpan.class;
+
+        final SuggestionSpan span1 = new SuggestionSpan(null, anyLocale, anySuggestions, anyFlags,
+                anyClass);
+        try {
+            // let some time pass before constructing the other span
+            Thread.sleep(2);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+        final SuggestionSpan span2 = new SuggestionSpan(null, anyLocale, anySuggestions, anyFlags,
+                anyClass);
+
+        assertFalse("Instances created at different time should not be equal", span2.equals(span1));
+    }
+
     /**
      * @param locale a {@link Locale} object.
      * @return A well-formed BCP 47 language tag representation.
@@ -62,6 +161,7 @@
         assertEquals(getNonNullLocaleString(locale), cloned.getLocale());
     }
 
+    @SmallTest
     public void testGetLocaleObject() {
         checkGetLocaleObject(Locale.forLanguageTag("en"));
         checkGetLocaleObject(Locale.forLanguageTag("en-GB"));
diff --git a/tests/tests/text/src/android/text/style/cts/URLSpanTest.java b/tests/tests/text/src/android/text/style/cts/URLSpanTest.java
index 330db77..e5ccf59 100644
--- a/tests/tests/text/src/android/text/style/cts/URLSpanTest.java
+++ b/tests/tests/text/src/android/text/style/cts/URLSpanTest.java
@@ -28,8 +28,8 @@
 import android.widget.TextView;
 
 public class URLSpanTest extends ActivityInstrumentationTestCase2<URLSpanCtsActivity> {
-    // The scheme of TEST_URL must be "ctstest" to launch MockURLSpanTestActivity
-    private static final String TEST_URL = "ctstest://urlSpan/test";
+    // The scheme of TEST_URL must be "ctstesttext" to launch MockURLSpanTestActivity
+    private static final String TEST_URL = "ctstesttext://urlSpan/test";
     private Activity mActivity;
 
     public URLSpanTest() {
diff --git a/tests/tests/text/src/android/text/util/cts/LinkifyTest.java b/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
index a159da9..431c754 100644
--- a/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
+++ b/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
@@ -592,13 +592,6 @@
     }
 
     @SmallTest
-    public void testAddLinks_partiallyMatchesUrlWithInvalidRequestParameter() throws Exception {
-        String url = "http://android.com?p=value";
-        assertAddLinksWithWebUrlPartiallyMatches("Should partially match URL with invalid " +
-                "request parameter", "http://android.com", url);
-    }
-
-    @SmallTest
     public void testAddLinks_matchesValidUrlWithEmoji() throws Exception {
         String url = "Thank\u263A.com";
         assertAddLinksWithWebUrlSucceeds("Should match URL with emoji", url);
@@ -669,6 +662,48 @@
         }
     }
 
+    @SmallTest
+    public void testAddLinks_matchesDomainNameWithDash() throws Exception {
+        String url = "http://a-nd.r-oid.com";
+        assertAddLinksWithWebUrlSucceeds("Should match domain name with '-'", url);
+
+        url = "a-nd.r-oid.com";
+        assertAddLinksWithWebUrlSucceeds("Should match domain name with '-'", url);
+    }
+
+    @SmallTest
+    public void testAddLinks_matchesDomainNameWithUnderscore() throws Exception {
+        String url = "http://a_nd.r_oid.com";
+        assertAddLinksWithWebUrlSucceeds("Should match domain name with '_'", url);
+
+        url = "a_nd.r_oid.com";
+        assertAddLinksWithWebUrlSucceeds("Should match domain name with '_'", url);
+    }
+
+    @SmallTest
+    public void testAddLinks_matchesPathAndQueryWithDollarSign() throws Exception {
+        String url = "http://android.com/path$?v=$val";
+        assertAddLinksWithWebUrlSucceeds("Should match path and query with '$'", url);
+
+        url = "android.com/path$?v=$val";
+        assertAddLinksWithWebUrlSucceeds("Should match path and query with '$'", url);
+    }
+
+    @SmallTest
+    public void testAddLinks_matchesEmptyPathWithQueryParams() throws Exception {
+        String url = "http://android.com?q=v";
+        assertAddLinksWithWebUrlSucceeds("Should match empty path with query params", url);
+
+        url = "android.com?q=v";
+        assertAddLinksWithWebUrlSucceeds("Should match empty path with query params", url);
+
+        url = "http://android.com/?q=v";
+        assertAddLinksWithWebUrlSucceeds("Should match empty path with query params", url);
+
+        url = "android.com/?q=v";
+        assertAddLinksWithWebUrlSucceeds("Should match empty path with query params", url);
+    }
+
     // EMAIL_ADDRESSES Related Tests
 
     public void testAddLinks_email_matchesShortValidEmail() throws Exception {
diff --git a/tests/tests/text/src/android/text/util/cts/Rfc822TokenizerTest.java b/tests/tests/text/src/android/text/util/cts/Rfc822TokenizerTest.java
index 4d145f1..b3aa714 100644
--- a/tests/tests/text/src/android/text/util/cts/Rfc822TokenizerTest.java
+++ b/tests/tests/text/src/android/text/util/cts/Rfc822TokenizerTest.java
@@ -18,17 +18,24 @@
 
 
 import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.text.util.Rfc822Token;
 import android.text.util.Rfc822Tokenizer;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Test {@link Rfc822Tokenizer}.
  */
 public class Rfc822TokenizerTest extends AndroidTestCase {
+
+    @SmallTest
     public void testConstructor() {
         new Rfc822Tokenizer();
     }
 
+    @SmallTest
     public void testFindTokenStart() {
         Rfc822Tokenizer rfc822Tokenizer = new Rfc822Tokenizer();
 
@@ -61,6 +68,7 @@
         }
     }
 
+    @SmallTest
     public void testFindTokenEnd() {
         Rfc822Tokenizer rfc822Tokenizer = new Rfc822Tokenizer();
 
@@ -96,6 +104,7 @@
         }
     }
 
+    @SmallTest
     public void testTerminateToken() {
         Rfc822Tokenizer rfc822Tokenizer = new Rfc822Tokenizer();
 
@@ -110,21 +119,22 @@
         assertEquals(text + comma + space, rfc822Tokenizer.terminateToken(null));
     }
 
+    @SmallTest
     public void testTokenize() {
         Rfc822Token[] tokens = Rfc822Tokenizer.tokenize("");
         assertEquals(0, tokens.length);
 
-        String text = "\"Berg\" (home) <berg\\@google.com>, tom\\@google.com (work)";
+        String text = "\"Berg\" (home) <berg\\@example.com>, tom\\@example.com (work)";
         tokens = Rfc822Tokenizer.tokenize(text);
         assertEquals(2, tokens.length);
-        localAssertEquals(tokens[0], "Berg", "berg\\@google.com", "home");
-        localAssertEquals(tokens[1], null, "tom\\@google.com", "work");
+        localAssertEquals(tokens[0], "Berg", "berg\\@example.com", "home");
+        localAssertEquals(tokens[1], null, "tom\\@example.com", "work");
 
-        text = "Foo Bar (something) <foo\\@google.com>, blah\\@google.com (something)";
+        text = "Foo Bar (something) <foo\\@example.com>, blah\\@example.com (something)";
         tokens = Rfc822Tokenizer.tokenize(text);
         assertEquals(2, tokens.length);
-        localAssertEquals(tokens[0], "Foo Bar", "foo\\@google.com", "something");
-        localAssertEquals(tokens[1], null, "blah\\@google.com", "something");
+        localAssertEquals(tokens[0], "Foo Bar", "foo\\@example.com", "something");
+        localAssertEquals(tokens[1], null, "blah\\@example.com", "something");
 
         try {
             Rfc822Tokenizer.tokenize(null);
@@ -134,6 +144,32 @@
         }
     }
 
+    @SmallTest
+    public void testTokenize_withListParam() {
+        final List<Rfc822Token> list = new ArrayList<>();
+        Rfc822Tokenizer.tokenize("", list);
+        assertEquals(0, list.size());
+
+        String text = "\"Berg\" (home) <berg\\@example.com>, tom\\@example.com (work)";
+        Rfc822Tokenizer.tokenize(text, list);
+        assertEquals(2, list.size());
+        localAssertEquals(list.get(0), "Berg", "berg\\@example.com", "home");
+        localAssertEquals(list.get(1), null, "tom\\@example.com", "work");
+
+        text = "Foo Bar (something) <foo\\@example.com>, blah\\@example.com (something)";
+        list.clear();
+        Rfc822Tokenizer.tokenize(text, list);
+        assertEquals(2, list.size());
+        localAssertEquals(list.get(0), "Foo Bar", "foo\\@example.com", "something");
+        localAssertEquals(list.get(1), null, "blah\\@example.com", "something");
+
+        try {
+            Rfc822Tokenizer.tokenize(null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+        }
+    }
+
     /**
      * Assert the specified token's name, address and comment all equal specified ones.
      * @param token the Rfc822Token to be asserted.
diff --git a/tests/tests/transition/Android.mk b/tests/tests/transition/Android.mk
index af8b4eb..5370d4f 100644
--- a/tests/tests/transition/Android.mk
+++ b/tests/tests/transition/Android.mk
@@ -24,13 +24,19 @@
 # When built, explicitly put it in the data partition.
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES += \
+    android-support-test \
+    mockito-target \
+    android-common \
+    ctsdeviceutil \
+    ctstestrunner \
+    platform-test-annotations
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
 
-LOCAL_SDK_VERSION := current
-
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/transition/res/layout/scene11.xml b/tests/tests/transition/res/layout/scene11.xml
new file mode 100644
index 0000000..8ecad8d
--- /dev/null
+++ b/tests/tests/transition/res/layout/scene11.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:transitionName="holder"
+                android:id="@+id/holder">
+    <ImageView
+        android:id="@+id/redSquare"
+        android:src="#F00"
+        android:layout_width="10dp"
+        android:layout_height="10dp"/>
+</RelativeLayout>
diff --git a/tests/tests/transition/res/transition/arc_motion.xml b/tests/tests/transition/res/transition/arc_motion.xml
new file mode 100644
index 0000000..264f074
--- /dev/null
+++ b/tests/tests/transition/res/transition/arc_motion.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<changeBounds xmlns:android="http://schemas.android.com/apk/res/android">
+    <arcMotion android:minimumVerticalAngle="1"
+               android:minimumHorizontalAngle="2"
+               android:maximumAngle="53"/>
+</changeBounds>
\ No newline at end of file
diff --git a/tests/tests/transition/res/transition/auto_transition.xml b/tests/tests/transition/res/transition/auto_transition.xml
new file mode 100644
index 0000000..e285105
--- /dev/null
+++ b/tests/tests/transition/res/transition/auto_transition.xml
@@ -0,0 +1,16 @@
+<?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.
+-->
+<autoTransition/>
\ No newline at end of file
diff --git a/tests/tests/transition/res/transition/change_bounds.xml b/tests/tests/transition/res/transition/change_bounds.xml
new file mode 100644
index 0000000..162372c
--- /dev/null
+++ b/tests/tests/transition/res/transition/change_bounds.xml
@@ -0,0 +1,17 @@
+<?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.
+-->
+<changeBounds xmlns:android="http://schemas.android.com/apk/res/android"
+      android:resizeClip="true"/>
diff --git a/tests/tests/transition/res/transition/change_clip_bounds.xml b/tests/tests/transition/res/transition/change_clip_bounds.xml
new file mode 100644
index 0000000..70a7dc6
--- /dev/null
+++ b/tests/tests/transition/res/transition/change_clip_bounds.xml
@@ -0,0 +1,16 @@
+<?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.
+-->
+<changeClipBounds/>
diff --git a/tests/tests/transition/res/transition/change_image_transform.xml b/tests/tests/transition/res/transition/change_image_transform.xml
new file mode 100644
index 0000000..b37ab04
--- /dev/null
+++ b/tests/tests/transition/res/transition/change_image_transform.xml
@@ -0,0 +1,16 @@
+<?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.
+-->
+<changeImageTransform/>
diff --git a/tests/tests/transition/res/transition/change_scroll.xml b/tests/tests/transition/res/transition/change_scroll.xml
new file mode 100644
index 0000000..9054686
--- /dev/null
+++ b/tests/tests/transition/res/transition/change_scroll.xml
@@ -0,0 +1,16 @@
+<?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.
+-->
+<changeScroll/>
\ No newline at end of file
diff --git a/tests/tests/transition/res/transition/change_transform.xml b/tests/tests/transition/res/transition/change_transform.xml
new file mode 100644
index 0000000..c87c549
--- /dev/null
+++ b/tests/tests/transition/res/transition/change_transform.xml
@@ -0,0 +1,17 @@
+<?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.
+-->
+<changeTransform xmlns:android="http://schemas.android.com/apk/res/android"
+    android:reparent="false" android:reparentWithOverlay="false"/>
diff --git a/tests/tests/transition/res/transition/custom_path_motion.xml b/tests/tests/transition/res/transition/custom_path_motion.xml
new file mode 100644
index 0000000..1704419
--- /dev/null
+++ b/tests/tests/transition/res/transition/custom_path_motion.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<changeBounds xmlns:android="http://schemas.android.com/apk/res/android">
+    <pathMotion class="android.transition.cts.TransitionInflaterTest$CustomPathMotion"/>
+</changeBounds>
\ No newline at end of file
diff --git a/tests/tests/transition/res/transition/custom_transition.xml b/tests/tests/transition/res/transition/custom_transition.xml
new file mode 100644
index 0000000..35ee285
--- /dev/null
+++ b/tests/tests/transition/res/transition/custom_transition.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<transition class="android.transition.cts.TransitionInflaterTest$CustomTransition"/>
\ No newline at end of file
diff --git a/tests/tests/transition/res/transition/explode.xml b/tests/tests/transition/res/transition/explode.xml
new file mode 100644
index 0000000..a038d8b
--- /dev/null
+++ b/tests/tests/transition/res/transition/explode.xml
@@ -0,0 +1,17 @@
+<?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.
+-->
+<explode xmlns:android="http://schemas.android.com/apk/res/android"
+    android:transitionVisibilityMode="mode_in"/>
diff --git a/tests/tests/transition/res/transition/fade.xml b/tests/tests/transition/res/transition/fade.xml
new file mode 100644
index 0000000..2057014
--- /dev/null
+++ b/tests/tests/transition/res/transition/fade.xml
@@ -0,0 +1,17 @@
+<?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.
+-->
+<fade xmlns:android="http://schemas.android.com/apk/res/android"
+      android:fadingMode="fade_out"/>
diff --git a/tests/tests/transition/res/transition/pattern_path_motion.xml b/tests/tests/transition/res/transition/pattern_path_motion.xml
new file mode 100644
index 0000000..f794447
--- /dev/null
+++ b/tests/tests/transition/res/transition/pattern_path_motion.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<changeBounds xmlns:android="http://schemas.android.com/apk/res/android">
+    <patternPathMotion android:patternPathData="M0 0 L0 100 L100 100"/>
+</changeBounds>
\ No newline at end of file
diff --git a/tests/tests/transition/res/transition/slide.xml b/tests/tests/transition/res/transition/slide.xml
new file mode 100644
index 0000000..9fde010
--- /dev/null
+++ b/tests/tests/transition/res/transition/slide.xml
@@ -0,0 +1,17 @@
+<?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.
+-->
+<slide xmlns:android="http://schemas.android.com/apk/res/android"
+    android:slideEdge="top"/>
diff --git a/tests/tests/transition/res/transition/target_classes.xml b/tests/tests/transition/res/transition/target_classes.xml
new file mode 100644
index 0000000..01d1e2d
--- /dev/null
+++ b/tests/tests/transition/res/transition/target_classes.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<changeBounds xmlns:android="http://schemas.android.com/apk/res/android">
+    <targets>
+        <target android:targetClass="android.widget.TextView"/>
+        <target android:targetClass="android.widget.ImageView"/>
+    </targets>
+</changeBounds>
\ No newline at end of file
diff --git a/tests/tests/transition/res/transition/target_ids.xml b/tests/tests/transition/res/transition/target_ids.xml
new file mode 100644
index 0000000..2340e46
--- /dev/null
+++ b/tests/tests/transition/res/transition/target_ids.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<changeBounds xmlns:android="http://schemas.android.com/apk/res/android">
+    <targets>
+        <target android:targetId="@+id/hello"/>
+        <target android:targetId="@+id/world"/>
+    </targets>
+</changeBounds>
\ No newline at end of file
diff --git a/tests/tests/transition/res/transition/target_names.xml b/tests/tests/transition/res/transition/target_names.xml
new file mode 100644
index 0000000..b90cf19
--- /dev/null
+++ b/tests/tests/transition/res/transition/target_names.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<changeBounds xmlns:android="http://schemas.android.com/apk/res/android">
+    <targets>
+        <target android:targetName="hello"/>
+        <target android:targetName="world"/>
+    </targets>
+</changeBounds>
\ No newline at end of file
diff --git a/tests/tests/transition/res/transition/transition_constructors.xml b/tests/tests/transition/res/transition/transition_constructors.xml
new file mode 100644
index 0000000..e442187
--- /dev/null
+++ b/tests/tests/transition/res/transition/transition_constructors.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
+    <transition class="android.transition.cts.TransitionInflaterTest$InflationFade"/>
+    <transition class="android.transition.cts.TransitionInflaterTest$InflationChangeBounds"/>
+    <transition class="android.transition.cts.TransitionInflaterTest$InflationChangeImageTransform"/>
+    <transition class="android.transition.cts.TransitionInflaterTest$InflationChangeTransform"/>
+    <transition class="android.transition.cts.TransitionInflaterTest$InflationAutoTransition"/>
+    <transition class="android.transition.cts.TransitionInflaterTest$InflationChangeClipBounds"/>
+    <transition class="android.transition.cts.TransitionInflaterTest$InflationChangeScroll"/>
+    <transition class="android.transition.cts.TransitionInflaterTest$InflationExplode"/>
+    <transition class="android.transition.cts.TransitionInflaterTest$InflationSlide"/>
+    <transition class="android.transition.cts.TransitionInflaterTest$InflationTransitionSet"/>
+</transitionSet>
\ No newline at end of file
diff --git a/tests/tests/transition/res/transition/transition_manager.xml b/tests/tests/transition/res/transition/transition_manager.xml
new file mode 100644
index 0000000..8d3186c
--- /dev/null
+++ b/tests/tests/transition/res/transition/transition_manager.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<transitionManager xmlns:android="http://schemas.android.com/apk/res/android">
+    <transition android:toScene="@layout/scene1"
+                android:transition="@transition/fade"/>
+    <transition android:fromScene="@layout/scene1" android:toScene="@layout/scene2"
+                android:transition="@transition/change_bounds"/>
+</transitionManager>
\ No newline at end of file
diff --git a/tests/tests/transition/res/transition/transition_set.xml b/tests/tests/transition/res/transition/transition_set.xml
new file mode 100644
index 0000000..3b1ff3c
--- /dev/null
+++ b/tests/tests/transition/res/transition/transition_set.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
+    android:transitionOrdering="sequential">
+    <changeBounds/>
+    <fade/>
+</transitionSet>
diff --git a/tests/tests/transition/src/android/transition/cts/BaseTransitionTest.java b/tests/tests/transition/src/android/transition/cts/BaseTransitionTest.java
index 944ff91..a5da03e 100644
--- a/tests/tests/transition/src/android/transition/cts/BaseTransitionTest.java
+++ b/tests/tests/transition/src/android/transition/cts/BaseTransitionTest.java
@@ -89,7 +89,7 @@
     }
 
     protected Scene loadScene(final View layout) throws Throwable {
-        Scene[] scene = new Scene[1];
+        final Scene[] scene = new Scene[1];
         runTestOnUiThread(new Runnable() {
             @Override
             public void run() {
@@ -101,7 +101,7 @@
     }
 
     protected Scene loadScene(final int layoutId) throws Throwable {
-        Scene scene[] = new Scene[1];
+        final Scene scene[] = new Scene[1];
         runTestOnUiThread(new Runnable() {
             @Override
             public void run() {
diff --git a/tests/tests/transition/src/android/transition/cts/CaptureValuesTest.java b/tests/tests/transition/src/android/transition/cts/CaptureValuesTest.java
new file mode 100644
index 0000000..84b154a
--- /dev/null
+++ b/tests/tests/transition/src/android/transition/cts/CaptureValuesTest.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.transition.cts;
+
+import android.support.test.filters.MediumTest;
+import android.support.test.filters.SmallTest;
+import android.transition.AutoTransition;
+import android.transition.ChangeBounds;
+import android.transition.ChangeClipBounds;
+import android.transition.ChangeImageTransform;
+import android.transition.ChangeScroll;
+import android.transition.ChangeTransform;
+import android.transition.Explode;
+import android.transition.Fade;
+import android.transition.Slide;
+import android.transition.Transition;
+import android.transition.TransitionManager;
+import android.transition.TransitionSet;
+import android.transition.TransitionValues;
+import android.util.ArrayMap;
+
+@MediumTest
+public class CaptureValuesTest extends BaseTransitionTest {
+    private ArrayMap<Class<?>, Boolean> mStartCaptured = new ArrayMap<>();
+    private ArrayMap<Class<?>, Boolean> mEndCaptured = new ArrayMap<>();
+
+    /**
+     * Ensures captureValues is called on all Transitions and the proper values are captured.
+     */
+    public void testCaptureValues() throws Throwable {
+        final TransitionSetCaptureValues set = new TransitionSetCaptureValues();
+        set.addTransition(new FadeCaptureValues());
+        set.addTransition(new ChangeBoundsCaptureValues());
+        set.addTransition(new ChangeImageTransformCaptureValues());
+        set.addTransition(new ChangeTransformCaptureValues());
+        set.addTransition(new AutoTransitionCaptureValues());
+        set.addTransition(new ChangeClipBoundsCaptureValues());
+        set.addTransition(new ChangeScrollCaptureValues());
+        set.addTransition(new ExplodeCaptureValues());
+        set.addTransition(new SlideCaptureValues());
+
+        enterScene(R.layout.scene11);
+        set.addTarget(getActivity().findViewById(R.id.redSquare));
+        mTransition = set;
+        resetListener();
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                TransitionManager.beginDelayedTransition(mSceneRoot, set);
+                mSceneRoot.invalidate();
+            }
+        });
+        waitForStart();
+        // no transition needs to run, but they should have all captured values.
+
+        for (int i = 0; i < set.getTransitionCount(); i++) {
+            Transition transition = set.getTransitionAt(i);
+            String className = transition.getClass().getSuperclass().getSimpleName().toString();
+            assertNotNull("captureStartValues not called for " + className,
+                    mStartCaptured.get(transition.getClass()));
+            assertNotNull("captureEndValues not called for " + className,
+                    mEndCaptured.get(transition.getClass()));
+        }
+        assertNotNull(mStartCaptured.get(set.getClass()));
+        assertNotNull(mEndCaptured.get(set.getClass()));
+    }
+
+    private void testCapturedValues(Transition transition, TransitionValues values,
+            boolean isStart) {
+        String[] properties = transition.getTransitionProperties();
+        if (transition instanceof TransitionSet) {
+            assertNull(properties);
+        } else {
+            String className = transition.getClass().getSuperclass().getSimpleName().toString();
+            assertNotNull(className + " should have non-null transition properties", properties);
+            assertTrue(properties.length > 0);
+
+            for (String property : properties) {
+                assertTrue(className + " should have written to property " + property,
+                        values.values.keySet().contains(property));
+            }
+        }
+        if (isStart) {
+            mStartCaptured.put(transition.getClass(), true);
+        } else {
+            mEndCaptured.put(transition.getClass(), true);
+        }
+    }
+
+    public class FadeCaptureValues extends Fade {
+        @Override
+        public void captureStartValues(TransitionValues transitionValues) {
+            super.captureStartValues(transitionValues);
+            testCapturedValues(this, transitionValues, true);
+        }
+
+        @Override
+        public void captureEndValues(TransitionValues transitionValues) {
+            super.captureEndValues(transitionValues);
+            testCapturedValues(this, transitionValues, false);
+        }
+    }
+
+    public class ChangeBoundsCaptureValues extends ChangeBounds {
+        public ChangeBoundsCaptureValues() {
+            super();
+            setResizeClip(true);
+            setReparent(true);
+        }
+        @Override
+        public void captureStartValues(TransitionValues transitionValues) {
+            super.captureStartValues(transitionValues);
+            testCapturedValues(this, transitionValues, true);
+        }
+
+        @Override
+        public void captureEndValues(TransitionValues transitionValues) {
+            super.captureEndValues(transitionValues);
+            testCapturedValues(this, transitionValues, false);
+        }
+    }
+
+    public class ChangeImageTransformCaptureValues extends ChangeImageTransform {
+        @Override
+        public void captureStartValues(TransitionValues transitionValues) {
+            super.captureStartValues(transitionValues);
+            testCapturedValues(this, transitionValues, true);
+        }
+
+        @Override
+        public void captureEndValues(TransitionValues transitionValues) {
+            super.captureEndValues(transitionValues);
+            testCapturedValues(this, transitionValues, false);
+        }
+    }
+
+    public class ChangeTransformCaptureValues extends ChangeTransform {
+        @Override
+        public void captureStartValues(TransitionValues transitionValues) {
+            super.captureStartValues(transitionValues);
+            testCapturedValues(this, transitionValues, true);
+        }
+
+        @Override
+        public void captureEndValues(TransitionValues transitionValues) {
+            super.captureEndValues(transitionValues);
+            testCapturedValues(this, transitionValues, false);
+        }
+    }
+
+    public class AutoTransitionCaptureValues extends AutoTransition {
+        @Override
+        public void captureStartValues(TransitionValues transitionValues) {
+            super.captureStartValues(transitionValues);
+            testCapturedValues(this, transitionValues, true);
+        }
+
+        @Override
+        public void captureEndValues(TransitionValues transitionValues) {
+            super.captureEndValues(transitionValues);
+            testCapturedValues(this, transitionValues, false);
+        }
+    }
+
+    public class ChangeClipBoundsCaptureValues extends ChangeClipBounds {
+        @Override
+        public void captureStartValues(TransitionValues transitionValues) {
+            super.captureStartValues(transitionValues);
+            testCapturedValues(this, transitionValues, true);
+        }
+
+        @Override
+        public void captureEndValues(TransitionValues transitionValues) {
+            super.captureEndValues(transitionValues);
+            testCapturedValues(this, transitionValues, false);
+        }
+    }
+
+    public class ChangeScrollCaptureValues extends ChangeScroll {
+        @Override
+        public void captureStartValues(TransitionValues transitionValues) {
+            super.captureStartValues(transitionValues);
+            testCapturedValues(this, transitionValues, true);
+        }
+
+        @Override
+        public void captureEndValues(TransitionValues transitionValues) {
+            super.captureEndValues(transitionValues);
+            testCapturedValues(this, transitionValues, false);
+        }
+    }
+
+    public class ExplodeCaptureValues extends Explode {
+        @Override
+        public void captureStartValues(TransitionValues transitionValues) {
+            super.captureStartValues(transitionValues);
+            testCapturedValues(this, transitionValues, true);
+        }
+
+        @Override
+        public void captureEndValues(TransitionValues transitionValues) {
+            super.captureEndValues(transitionValues);
+            testCapturedValues(this, transitionValues, false);
+        }
+    }
+
+    public class SlideCaptureValues extends Slide {
+        @Override
+        public void captureStartValues(TransitionValues transitionValues) {
+            super.captureStartValues(transitionValues);
+            testCapturedValues(this, transitionValues, true);
+        }
+
+        @Override
+        public void captureEndValues(TransitionValues transitionValues) {
+            super.captureEndValues(transitionValues);
+            testCapturedValues(this, transitionValues, false);
+        }
+    }
+    public class TransitionSetCaptureValues extends TransitionSet {
+        @Override
+        public void captureStartValues(TransitionValues transitionValues) {
+            super.captureStartValues(transitionValues);
+            testCapturedValues(this, transitionValues, true);
+        }
+
+        @Override
+        public void captureEndValues(TransitionValues transitionValues) {
+            super.captureEndValues(transitionValues);
+            testCapturedValues(this, transitionValues, false);
+        }
+    }
+}
diff --git a/tests/tests/transition/src/android/transition/cts/PatternPathMotionTest.java b/tests/tests/transition/src/android/transition/cts/PatternPathMotionTest.java
index 5485b4a..6655213 100644
--- a/tests/tests/transition/src/android/transition/cts/PatternPathMotionTest.java
+++ b/tests/tests/transition/src/android/transition/cts/PatternPathMotionTest.java
@@ -47,5 +47,14 @@
 
         assertPathMatches(expected, pathMotion.getPath(0, 0, 0, 100));
     }
+
+    public void testSetPatternPath() throws Throwable {
+        Path pattern = new Path();
+        pattern.addArc(0, 0, 100, 100, 0, 180);
+
+        PatternPathMotion patternPathMotion = new PatternPathMotion();
+        patternPathMotion.setPatternPath(pattern);
+        assertSame(pattern, patternPathMotion.getPatternPath());
+    }
 }
 
diff --git a/tests/tests/transition/src/android/transition/cts/PropagationTest.java b/tests/tests/transition/src/android/transition/cts/PropagationTest.java
new file mode 100644
index 0000000..7b49c15
--- /dev/null
+++ b/tests/tests/transition/src/android/transition/cts/PropagationTest.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.transition.cts;
+
+import android.graphics.Rect;
+import android.transition.CircularPropagation;
+import android.transition.SidePropagation;
+import android.transition.Transition;
+import android.transition.TransitionValues;
+import android.view.Gravity;
+import android.view.View;
+
+public class PropagationTest extends BaseTransitionTest {
+    public void testCircularPropagation() throws Throwable {
+        enterScene(R.layout.scene10);
+        CircularPropagation propagation = new CircularPropagation();
+        mTransition.setPropagation(propagation);
+        final TransitionValues redValues = new TransitionValues();
+        redValues.view = getActivity().findViewById(R.id.redSquare);
+        propagation.captureValues(redValues);
+
+        // Only the reported propagation properties are set
+        for (String prop : propagation.getPropagationProperties()) {
+            assertTrue(redValues.values.keySet().contains(prop));
+        }
+        assertEquals(propagation.getPropagationProperties().length, redValues.values.size());
+
+        // check the visibility
+        assertEquals(View.VISIBLE, propagation.getViewVisibility(redValues));
+        assertEquals(View.GONE, propagation.getViewVisibility(null));
+
+        // Check the positions
+        int[] pos = new int[2];
+        redValues.view.getLocationOnScreen(pos);
+        pos[0] += redValues.view.getWidth() / 2;
+        pos[1] += redValues.view.getHeight() / 2;
+        assertEquals(pos[0], propagation.getViewX(redValues));
+        assertEquals(pos[1], propagation.getViewY(redValues));
+
+        mTransition.setEpicenterCallback(new Transition.EpicenterCallback() {
+            @Override
+            public Rect onGetEpicenter(Transition transition) {
+                return new Rect(0, 0, redValues.view.getWidth(), redValues.view.getHeight());
+            }
+        });
+
+        long redDelay = getDelay(R.id.redSquare);
+        // red square's delay should be roughly 0 since it is at the epicenter
+        assertEquals(0f, redDelay, 30f);
+
+        // The green square is on the upper-right
+        long greenDelay = getDelay(R.id.greenSquare);
+        assertTrue(greenDelay < redDelay);
+
+        // The blue square is on the lower-right
+        long blueDelay = getDelay(R.id.blueSquare);
+        assertTrue(blueDelay < greenDelay);
+
+        // Test propagation speed
+        propagation.setPropagationSpeed(1000000000f);
+        assertEquals(0, getDelay(R.id.blueSquare));
+    }
+
+    public void testSidePropagationBottom() throws Throwable {
+        SidePropagation propagation = new SidePropagation();
+        propagation.setSide(Gravity.BOTTOM);
+        mTransition.setEpicenterCallback(new Transition.EpicenterCallback() {
+            @Override
+            public Rect onGetEpicenter(Transition transition) {
+                return new Rect(0, 0, 1, 1);
+            }
+        });
+        mTransition.setPropagation(propagation);
+
+        enterScene(R.layout.scene10);
+
+        // The red square is on the upper-left
+        long redDelay = getDelay(R.id.redSquare);
+
+        // The green square is on the upper-right
+        long greenDelay = getDelay(R.id.greenSquare);
+
+        // The blue square is on the lower-right
+        long blueDelay = getDelay(R.id.blueSquare);
+
+        // The yellow square is on the lower-left
+        long yellowDelay = getDelay(R.id.yellowSquare);
+
+        assertTrue(redDelay > greenDelay);
+        assertTrue(redDelay > yellowDelay);
+        assertTrue(greenDelay > blueDelay);
+        assertTrue(yellowDelay > blueDelay);
+
+        // Test propagation speed
+        propagation.setPropagationSpeed(1000000000f);
+        assertEquals(0, getDelay(R.id.blueSquare));
+    }
+
+    public void testSidePropagationTop() throws Throwable {
+        SidePropagation propagation = new SidePropagation();
+        propagation.setSide(Gravity.TOP);
+        mTransition.setEpicenterCallback(new Transition.EpicenterCallback() {
+            @Override
+            public Rect onGetEpicenter(Transition transition) {
+                return new Rect(0, 0, 1, 1);
+            }
+        });
+        mTransition.setPropagation(propagation);
+
+        enterScene(R.layout.scene10);
+
+        // The red square is on the upper-left
+        long redDelay = getDelay(R.id.redSquare);
+
+        // The green square is on the upper-right
+        long greenDelay = getDelay(R.id.greenSquare);
+
+        // The blue square is on the lower-right
+        long blueDelay = getDelay(R.id.blueSquare);
+
+        // The yellow square is on the lower-left
+        long yellowDelay = getDelay(R.id.yellowSquare);
+
+        assertTrue(yellowDelay > redDelay);
+        assertTrue(yellowDelay > blueDelay);
+        assertTrue(redDelay > greenDelay);
+        assertTrue(blueDelay > greenDelay);
+    }
+
+    public void testSidePropagationRight() throws Throwable {
+        SidePropagation propagation = new SidePropagation();
+        propagation.setSide(Gravity.RIGHT);
+        mTransition.setEpicenterCallback(new Transition.EpicenterCallback() {
+            @Override
+            public Rect onGetEpicenter(Transition transition) {
+                return new Rect(0, 0, 1, 1);
+            }
+        });
+        mTransition.setPropagation(propagation);
+
+        enterScene(R.layout.scene10);
+
+        // The red square is on the upper-left
+        long redDelay = getDelay(R.id.redSquare);
+
+        // The green square is on the upper-right
+        long greenDelay = getDelay(R.id.greenSquare);
+
+        // The blue square is on the lower-right
+        long blueDelay = getDelay(R.id.blueSquare);
+
+        // The yellow square is on the lower-left
+        long yellowDelay = getDelay(R.id.yellowSquare);
+
+        assertTrue(redDelay > greenDelay);
+        assertTrue(redDelay > yellowDelay);
+        assertTrue(yellowDelay > blueDelay);
+        assertTrue(greenDelay > blueDelay);
+    }
+
+    public void testSidePropagationLeft() throws Throwable {
+        SidePropagation propagation = new SidePropagation();
+        propagation.setSide(Gravity.LEFT);
+        mTransition.setEpicenterCallback(new Transition.EpicenterCallback() {
+            @Override
+            public Rect onGetEpicenter(Transition transition) {
+                return new Rect(0, 0, 1, 1);
+            }
+        });
+        mTransition.setPropagation(propagation);
+
+        enterScene(R.layout.scene10);
+
+        // The red square is on the upper-left
+        long redDelay = getDelay(R.id.redSquare);
+
+        // The green square is on the upper-right
+        long greenDelay = getDelay(R.id.greenSquare);
+
+        // The blue square is on the lower-right
+        long blueDelay = getDelay(R.id.blueSquare);
+
+        // The yellow square is on the lower-left
+        long yellowDelay = getDelay(R.id.yellowSquare);
+
+        assertTrue(greenDelay > redDelay);
+        assertTrue(greenDelay > blueDelay);
+        assertTrue(redDelay > yellowDelay);
+        assertTrue(blueDelay > yellowDelay);
+    }
+
+    private TransitionValues capturePropagationValues(int viewId) {
+        TransitionValues transitionValues = new TransitionValues();
+        transitionValues.view = mSceneRoot.findViewById(viewId);
+        mTransition.getPropagation().captureValues(transitionValues);
+        return transitionValues;
+    }
+
+    private long getDelay(int viewId) {
+        TransitionValues transitionValues = capturePropagationValues(viewId);
+        return mTransition.getPropagation().
+                getStartDelay(mSceneRoot, mTransition, transitionValues, null);
+    }
+}
diff --git a/tests/tests/transition/src/android/transition/cts/SceneTest.java b/tests/tests/transition/src/android/transition/cts/SceneTest.java
index 2785714..48fb6c1 100644
--- a/tests/tests/transition/src/android/transition/cts/SceneTest.java
+++ b/tests/tests/transition/src/android/transition/cts/SceneTest.java
@@ -17,12 +17,12 @@
 
 import android.transition.Scene;
 import android.view.View;
+import android.view.ViewGroup;
 
 public class SceneTest extends BaseTransitionTest {
-
-    public SceneTest() {
-    }
-
+    /**
+     * Test Scene(ViewGroup) with enterAction and exitAction
+     */
     public void testDynamicConstructor() throws Throwable {
         Scene scene = new Scene(mSceneRoot);
         assertEquals(mSceneRoot, scene.getSceneRoot());
@@ -52,32 +52,34 @@
         assertNull(mSceneRoot.findViewById(R.id.redSquare));
     }
 
+    /**
+     * Test Scene(ViewGroup, View)
+     */
     public void testViewConstructor() throws Throwable {
         View view = loadLayout(R.layout.scene1);
-        Scene scene = new Scene(mSceneRoot, view);
-        assertEquals(mSceneRoot, scene.getSceneRoot());
-        CallCheck enterCheck = new CallCheck();
-        scene.setEnterAction(enterCheck);
-        CallCheck exitCheck = new CallCheck();
-        scene.setExitAction(exitCheck);
-        enterScene(scene);
-
-        assertTrue(enterCheck.wasRun);
-        assertFalse(exitCheck.wasRun);
-
-        View redSquare = mActivity.findViewById(R.id.redSquare);
-        assertNotNull(redSquare);
-
-        exitScene(scene);
-        assertNotNull(mSceneRoot.findViewById(R.id.redSquare));
-        assertTrue(exitCheck.wasRun);
-
-        enterScene(R.layout.scene4);
-        assertNull(mSceneRoot.findViewById(R.id.redSquare));
+        constructorTest(new Scene(mSceneRoot, view));
     }
 
+    /**
+     * Test Scene(ViewGroup, ViewGroup)
+     */
+    public void testDeprecatedConstructor() throws Throwable {
+        View view = loadLayout(R.layout.scene1);
+        constructorTest(new Scene(mSceneRoot, (ViewGroup) view));
+    }
+
+    /**
+     * Test Scene.getSceneForLayout
+     */
     public void testFactory() throws Throwable {
         Scene scene = loadScene(R.layout.scene1);
+        constructorTest(scene);
+    }
+
+    /**
+     * Tests that the Scene was constructed properly from a scene1
+     */
+    private void constructorTest(Scene scene) throws Throwable {
         assertEquals(mSceneRoot, scene.getSceneRoot());
         CallCheck enterCheck = new CallCheck();
         scene.setEnterAction(enterCheck);
@@ -94,8 +96,6 @@
         exitScene(scene);
         assertNotNull(mSceneRoot.findViewById(R.id.redSquare));
         assertTrue(exitCheck.wasRun);
-        enterScene(R.layout.scene4);
-        assertNull(mSceneRoot.findViewById(R.id.redSquare));
     }
 
     private static class CallCheck implements Runnable {
diff --git a/tests/tests/transition/src/android/transition/cts/TransitionInflaterTest.java b/tests/tests/transition/src/android/transition/cts/TransitionInflaterTest.java
new file mode 100644
index 0000000..22c0616
--- /dev/null
+++ b/tests/tests/transition/src/android/transition/cts/TransitionInflaterTest.java
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.transition.cts;
+
+import android.content.Context;
+import android.graphics.Path;
+import android.graphics.PathMeasure;
+import android.support.test.filters.MediumTest;
+import android.transition.ArcMotion;
+import android.transition.AutoTransition;
+import android.transition.ChangeBounds;
+import android.transition.ChangeClipBounds;
+import android.transition.ChangeImageTransform;
+import android.transition.ChangeScroll;
+import android.transition.ChangeTransform;
+import android.transition.Explode;
+import android.transition.Fade;
+import android.transition.PathMotion;
+import android.transition.PatternPathMotion;
+import android.transition.Scene;
+import android.transition.Slide;
+import android.transition.Transition;
+import android.transition.TransitionInflater;
+import android.transition.TransitionManager;
+import android.transition.TransitionSet;
+import android.transition.TransitionValues;
+import android.transition.Visibility;
+import android.transition.cts.R;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.util.List;
+
+@MediumTest
+public class TransitionInflaterTest extends BaseTransitionTest {
+    public void testInflationConstructors() throws Throwable {
+        TransitionInflater inflater = TransitionInflater.from(mActivity);
+        Transition transition = inflater.inflateTransition(R.transition.transition_constructors);
+        assertTrue(transition instanceof TransitionSet);
+        TransitionSet set = (TransitionSet) transition;
+        assertEquals(10, set.getTransitionCount());
+    }
+
+    public void testInflation() {
+        TransitionInflater inflater = TransitionInflater.from(mActivity);
+        assureFadeProperties(inflater.inflateTransition(R.transition.fade));
+        assureChangeBoundsProperties(inflater.inflateTransition(R.transition.change_bounds));
+        assureSlideProperties(inflater.inflateTransition(R.transition.slide));
+        assureExplodeProperties(inflater.inflateTransition(R.transition.explode));
+        assureChangeImageTransformProperties(
+                inflater.inflateTransition(R.transition.change_image_transform));
+        assureChangeTransformProperties(inflater.inflateTransition(R.transition.change_transform));
+        assureChangeClipBoundsProperties(
+                inflater.inflateTransition(R.transition.change_clip_bounds));
+        assureAutoTransitionProperties(inflater.inflateTransition(R.transition.auto_transition));
+        assureChangeScrollProperties(inflater.inflateTransition(R.transition.change_scroll));
+        assureTransitionSetProperties(inflater.inflateTransition(R.transition.transition_set));
+        assureCustomTransitionProperties(
+                inflater.inflateTransition(R.transition.custom_transition));
+        testTargetIds(inflater.inflateTransition(R.transition.target_ids));
+        testTargetNames(inflater.inflateTransition(R.transition.target_names));
+        testTargetClass(inflater.inflateTransition(R.transition.target_classes));
+        testArcMotion(inflater.inflateTransition(R.transition.arc_motion));
+        testCustomPathMotion(inflater.inflateTransition(R.transition.custom_path_motion));
+        testPatternPathMotion(inflater.inflateTransition(R.transition.pattern_path_motion));
+    }
+
+    public void testInflateTransitionManager() throws Throwable {
+        TransitionInflater inflater = TransitionInflater.from(mActivity);
+        TransitionManager transitionManager =
+                inflater.inflateTransitionManager(R.transition.transition_manager, mSceneRoot);
+        assertNotNull(transitionManager);
+
+        Scene scene1 = Scene.getSceneForLayout(mSceneRoot, R.layout.scene1, mActivity);
+        Transition transition = transitionManager.getTransition(scene1);
+        assertNotNull(transition);
+        assertTrue(transition instanceof Fade);
+        enterScene(scene1);
+
+        Scene scene2 = Scene.getSceneForLayout(mSceneRoot, R.layout.scene2, mActivity);
+        transition = transitionManager.getTransition(scene2);
+        assertNotNull(transition);
+        assertTrue(transition instanceof ChangeBounds);
+    }
+
+    private void assureFadeProperties(Transition transition) {
+        assertTrue(transition instanceof Fade);
+        Fade fade = (Fade) transition;
+        assertEquals(Fade.OUT, fade.getMode());
+    }
+
+    private void assureChangeBoundsProperties(Transition transition) {
+        assertTrue(transition instanceof ChangeBounds);
+        ChangeBounds changeBounds = (ChangeBounds) transition;
+        assertTrue(changeBounds.getResizeClip());
+    }
+
+    private void assureSlideProperties(Transition transition) {
+        assertTrue(transition instanceof Slide);
+        Slide slide = (Slide) transition;
+        assertEquals(Gravity.TOP, slide.getSlideEdge());
+    }
+
+    private void assureExplodeProperties(Transition transition) {
+        assertTrue(transition instanceof Explode);
+        Visibility visibility = (Visibility) transition;
+        assertEquals(Visibility.MODE_IN, visibility.getMode());
+    }
+
+    private void assureChangeImageTransformProperties(Transition transition) {
+        assertTrue(transition instanceof ChangeImageTransform);
+    }
+
+    private void assureChangeTransformProperties(Transition transition) {
+        assertTrue(transition instanceof ChangeTransform);
+        ChangeTransform changeTransform = (ChangeTransform) transition;
+        assertFalse(changeTransform.getReparent());
+        assertFalse(changeTransform.getReparentWithOverlay());
+    }
+
+    private void assureChangeClipBoundsProperties(Transition transition) {
+        assertTrue(transition instanceof ChangeClipBounds);
+    }
+
+    private void assureAutoTransitionProperties(Transition transition) {
+        assertTrue(transition instanceof AutoTransition);
+    }
+
+    private void assureChangeScrollProperties(Transition transition) {
+        assertTrue(transition instanceof ChangeScroll);
+    }
+
+    private void assureTransitionSetProperties(Transition transition) {
+        assertTrue(transition instanceof TransitionSet);
+        TransitionSet set = (TransitionSet) transition;
+        assertEquals(TransitionSet.ORDERING_SEQUENTIAL, set.getOrdering());
+        assertEquals(2, set.getTransitionCount());
+        assertTrue(set.getTransitionAt(0) instanceof ChangeBounds);
+        assertTrue(set.getTransitionAt(1) instanceof Fade);
+    }
+
+    private void assureCustomTransitionProperties(Transition transition) {
+        assertTrue(transition instanceof CustomTransition);
+    }
+
+    private void testTargetIds(Transition transition) {
+        List<Integer> targets = transition.getTargetIds();
+        assertNotNull(targets);
+        assertEquals(2, targets.size());
+        assertEquals(R.id.hello, (int) targets.get(0));
+        assertEquals(R.id.world, (int) targets.get(1));
+    }
+
+    private void testTargetNames(Transition transition) {
+        List<String> targets = transition.getTargetNames();
+        assertNotNull(targets);
+        assertEquals(2, targets.size());
+        assertEquals("hello", targets.get(0));
+        assertEquals("world", targets.get(1));
+    }
+
+    private void testTargetClass(Transition transition) {
+        List<Class> targets = transition.getTargetTypes();
+        assertNotNull(targets);
+        assertEquals(2, targets.size());
+        assertEquals(TextView.class, targets.get(0));
+        assertEquals(ImageView.class, targets.get(1));
+    }
+
+    private void testArcMotion(Transition transition) {
+        assertNotNull(transition);
+        PathMotion motion = transition.getPathMotion();
+        assertNotNull(motion);
+        assertTrue(motion instanceof ArcMotion);
+        ArcMotion arcMotion = (ArcMotion) motion;
+        assertEquals(1f, arcMotion.getMinimumVerticalAngle(), 0.01f);
+        assertEquals(2f, arcMotion.getMinimumHorizontalAngle(), 0.01f);
+        assertEquals(53f, arcMotion.getMaximumAngle(), 0.01f);
+    }
+
+    private void testCustomPathMotion(Transition transition) {
+        assertNotNull(transition);
+        PathMotion motion = transition.getPathMotion();
+        assertNotNull(motion);
+        assertTrue(motion instanceof CustomPathMotion);
+    }
+
+    private void testPatternPathMotion(Transition transition) {
+        assertNotNull(transition);
+        PathMotion motion = transition.getPathMotion();
+        assertNotNull(motion);
+        assertTrue(motion instanceof PatternPathMotion);
+        PatternPathMotion pattern = (PatternPathMotion) motion;
+        Path path = pattern.getPatternPath();
+        PathMeasure measure = new PathMeasure(path, false);
+        assertEquals(200f, measure.getLength(), 0.1f);
+    }
+
+    public static class CustomTransition extends Transition {
+        public CustomTransition() {
+            fail("Default constructor was not expected");
+        }
+
+        public CustomTransition(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+
+        @Override
+        public void captureStartValues(TransitionValues transitionValues) {
+
+        }
+
+        @Override
+        public void captureEndValues(TransitionValues transitionValues) {
+
+        }
+    }
+
+    public static class CustomPathMotion extends PathMotion {
+        public CustomPathMotion() {
+            fail("default constructor shouldn't be called.");
+        }
+
+        public CustomPathMotion(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+
+        @Override
+        public Path getPath(float startX, float startY, float endX, float endY) {
+            return null;
+        }
+    }
+
+    public static class InflationFade extends Fade {
+        public InflationFade(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+    }
+
+    public static class InflationChangeBounds extends ChangeBounds {
+        public InflationChangeBounds(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+    }
+
+    public static class InflationSlide extends Slide {
+        public InflationSlide(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+    }
+
+    public static class InflationTransitionSet extends TransitionSet {
+        public InflationTransitionSet(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+    }
+
+    public static class InflationChangeImageTransform extends ChangeImageTransform {
+        public InflationChangeImageTransform(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+    }
+
+    public static class InflationChangeTransform extends ChangeTransform {
+        public InflationChangeTransform(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+    }
+
+    public static class InflationAutoTransition extends AutoTransition {
+        public InflationAutoTransition(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+    }
+
+    public static class InflationChangeClipBounds extends ChangeClipBounds {
+        public InflationChangeClipBounds(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+    }
+
+    public static class InflationChangeScroll extends ChangeScroll {
+        public InflationChangeScroll(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+    }
+
+    public static class InflationExplode extends Explode {
+        public InflationExplode(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+    }
+}
diff --git a/tests/tests/transition/src/android/transition/cts/TransitionManagerTest.java b/tests/tests/transition/src/android/transition/cts/TransitionManagerTest.java
index 9eacd1b..a8a653d 100644
--- a/tests/tests/transition/src/android/transition/cts/TransitionManagerTest.java
+++ b/tests/tests/transition/src/android/transition/cts/TransitionManagerTest.java
@@ -15,11 +15,13 @@
  */
 package android.transition.cts;
 
+import android.graphics.Rect;
 import android.transition.cts.R;
 
 import android.transition.Scene;
 import android.transition.TransitionManager;
 import android.view.View;
+import android.view.ViewTreeObserver;
 
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -57,6 +59,49 @@
         });
     }
 
+    public void testDefaultBeginDelayedTransition() throws Throwable {
+        enterScene(R.layout.scene1);
+        final CountDownLatch startLatch = new CountDownLatch(1);
+        mSceneRoot.getViewTreeObserver().addOnPreDrawListener(
+                new ViewTreeObserver.OnPreDrawListener() {
+                    @Override
+                    public boolean onPreDraw() {
+                        mSceneRoot.getViewTreeObserver().removeOnPreDrawListener(this);
+                        startLatch.countDown();
+                        return true;
+                    }
+                });
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                TransitionManager.beginDelayedTransition(mSceneRoot);
+            }
+        });
+        enterScene(R.layout.scene6);
+        assertTrue(startLatch.await(500, TimeUnit.MILLISECONDS));
+        ensureRedSquareIsMoving();
+        endTransition();
+    }
+
+    private void ensureRedSquareIsMoving() throws InterruptedException {
+        final View view = getActivity().findViewById(R.id.redSquare);
+        assertNotNull(view);
+        // We should see a ChangeBounds on redSquare
+        final Rect position = new Rect(view.getLeft(), view.getTop(), view.getRight(),
+                view.getBottom());
+        final CountDownLatch latch = new CountDownLatch(1);
+        view.postOnAnimationDelayed(new Runnable() {
+            @Override
+            public void run() {
+                Rect next = new Rect(view.getLeft(), view.getTop(), view.getRight(),
+                        view.getBottom());
+                assertTrue(!next.equals(position));
+                latch.countDown();
+            }
+        }, 20);
+        assertTrue(latch.await(500, TimeUnit.MILLISECONDS));
+    }
+
     public void testGo() throws Throwable {
         startTransition(R.layout.scene1);
         waitForStart();
@@ -77,6 +122,30 @@
         });
     }
 
+    public void testDefaultGo() throws Throwable {
+        enterScene(R.layout.scene1);
+        final CountDownLatch startLatch = new CountDownLatch(1);
+        mSceneRoot.getViewTreeObserver().addOnPreDrawListener(
+                new ViewTreeObserver.OnPreDrawListener() {
+                    @Override
+                    public boolean onPreDraw() {
+                        mSceneRoot.getViewTreeObserver().removeOnPreDrawListener(this);
+                        startLatch.countDown();
+                        return true;
+                    }
+                });
+        final Scene scene6 = loadScene(R.layout.scene6);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                TransitionManager.go(scene6);
+            }
+        });
+        assertTrue(startLatch.await(500, TimeUnit.MILLISECONDS));
+        ensureRedSquareIsMoving();
+        endTransition();
+    }
+
     public void testSetTransition1() throws Throwable {
         final TransitionManager transitionManager = new TransitionManager();
 
diff --git a/tests/tests/transition/src/android/transition/cts/TransitionTest.java b/tests/tests/transition/src/android/transition/cts/TransitionTest.java
index 9ae568a..71b22fe 100644
--- a/tests/tests/transition/src/android/transition/cts/TransitionTest.java
+++ b/tests/tests/transition/src/android/transition/cts/TransitionTest.java
@@ -23,6 +23,7 @@
 import android.transition.ArcMotion;
 import android.transition.AutoTransition;
 import android.transition.ChangeBounds;
+import android.transition.CircularPropagation;
 import android.transition.PathMotion;
 import android.transition.Scene;
 import android.transition.Transition;
@@ -240,6 +241,7 @@
     public void testIsTransitionRequired() throws Throwable {
         enterScene(R.layout.scene1);
         mTransition = new NotRequiredTransition();
+        assertFalse(mTransition.isTransitionRequired(null, null));
         resetListener();
         runTestOnUiThread(new Runnable() {
             @Override
@@ -315,6 +317,19 @@
         endTransition();
     }
 
+    public void testExcludeChildrenClass() throws Throwable {
+        enterScene(R.layout.scene1);
+        mTransition.excludeChildren(RelativeLayout.class, true);
+        startTransition(R.layout.scene2);
+        waitForEnd(0); // Should already be ended, since no children are transitioning
+
+        resetListener();
+        mTransition.excludeChildren(RelativeLayout.class, false); // remove it
+        startTransition(R.layout.scene1);
+        assertEquals(1, mListener.endLatch.getCount()); // It is running
+        endTransition();
+    }
+
     public void testExcludeTargetView() throws Throwable {
         View layout1 = loadLayout(R.layout.scene1);
         Scene scene1 = loadScene(layout1);
@@ -383,6 +398,7 @@
     }
 
     public void testEpicenter() throws Throwable {
+        assertNull(mTransition.getEpicenter());
         EpicenterCallback callback = new EpicenterCallback() {
             @Override
             public Rect onGetEpicenter(Transition transition) {
@@ -390,7 +406,8 @@
             }
         };
         mTransition.setEpicenterCallback(callback);
-        assertEquals(callback, mTransition.getEpicenterCallback());
+        assertSame(callback, mTransition.getEpicenterCallback());
+        assertEquals(new Rect(0, 0, 1, 1), mTransition.getEpicenter());
     }
 
     public void testInterpolator() throws Throwable {
@@ -467,6 +484,14 @@
         endTransition();
     }
 
+    public void testSetPropagation() throws Throwable {
+        Transition transition = new ChangeBounds();
+        assertNull(transition.getPropagation());
+        TransitionPropagation propagation = new CircularPropagation();
+        transition.setPropagation(propagation);
+        assertSame(propagation, transition.getPropagation());
+    }
+
     public void testStartDelay() throws Throwable {
         CaptureAnimatorTransition transition = new CaptureAnimatorTransition();
         mTransition = transition;
@@ -489,10 +514,13 @@
 
     public void testTransitionValues() throws Throwable {
         enterScene(R.layout.scene1);
-        mTransition = new CheckTransitionValuesTransition();
+        CheckTransitionValuesTransition transition = new CheckTransitionValuesTransition();
+        mTransition = transition;
         mTransition.setDuration(10);
         resetListener();
-        startTransition(R.layout.scene4);
+        startTransition(R.layout.scene2);
+        assertTrue(transition.onDisappearCalled.await(500, TimeUnit.MILLISECONDS));
+        assertTrue(transition.onAppearCalled.await(500, TimeUnit.MILLISECONDS));
         // The transition has all the asserts in it, so we can just end it now.
         endTransition();
     }
@@ -515,6 +543,29 @@
         waitForEnd(400);
     }
 
+    public void testGetTransitionProperties() throws Throwable {
+        enterScene(R.layout.scene1);
+        // Make the transition make changes to properties in getTransitionProperties.
+        TransitionPropertiesTransition transition = new TransitionPropertiesTransition(false);
+        mTransition = transition;
+        resetListener();
+        startTransition(R.layout.scene2);
+        assertTrue(transition.latch.await(500, TimeUnit.MILLISECONDS));
+        endTransition();
+
+        // Now make the transition only make changes to unimportant properties.
+        transition = new TransitionPropertiesTransition(true);
+        mTransition = transition;
+        resetListener();
+        startTransition(R.layout.scene1);
+        assertTrue(mListener.endLatch.await(500, TimeUnit.MILLISECONDS));
+        // createAnimator shouldn't have been called.
+        assertEquals(1, transition.latch.getCount());
+
+        assertNotNull(transition.getTransitionProperties());
+        assertEquals(1, transition.getTransitionProperties().length);
+    }
+
     private class NotRequiredTransition extends TestTransition {
         @Override
         public boolean isTransitionRequired(TransitionValues startValues,
@@ -551,9 +602,12 @@
     }
 
     private class CheckTransitionValuesTransition extends TestTransition {
+        public CountDownLatch onAppearCalled = new CountDownLatch(1);
+        public CountDownLatch onDisappearCalled = new CountDownLatch(1);
         @Override
         public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues,
                 TransitionValues endValues) {
+            onAppearCalled.countDown();
             assertNull(getTransitionValues(endValues.view, true));
             assertEquals(endValues, getTransitionValues(endValues.view, false));
             return super.onAppear(sceneRoot, view, startValues, endValues);
@@ -562,6 +616,7 @@
         @Override
         public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues,
                 TransitionValues endValues) {
+            onDisappearCalled.countDown();
             assertNull(getTransitionValues(startValues.view, false));
             assertEquals(startValues, getTransitionValues(startValues.view, true));
             return super.onDisappear(sceneRoot, view, startValues, endValues);
@@ -576,5 +631,48 @@
             startLatch.countDown();
         }
     }
+
+    private static class TransitionPropertiesTransition extends Transition {
+        private static final String SIDE_PROP = "prop1";
+        private static final String IMPORTANT_PROP = "prop2";
+        private static final String[] PROPERTIES = {
+                IMPORTANT_PROP
+        };
+
+        private boolean mOnlyUnimportant;
+        public CountDownLatch latch = new CountDownLatch(1);
+
+        public TransitionPropertiesTransition(boolean onlyUnimportant) {
+            mOnlyUnimportant = onlyUnimportant;
+        }
+
+        @Override
+        public String[] getTransitionProperties() {
+            return PROPERTIES;
+        }
+
+        @Override
+        public void captureStartValues(TransitionValues transitionValues) {
+            transitionValues.values.put(SIDE_PROP, 1);
+            transitionValues.values.put(IMPORTANT_PROP, 1);
+        }
+
+        @Override
+        public void captureEndValues(TransitionValues transitionValues) {
+            transitionValues.values.put(SIDE_PROP, 2);
+            int val = mOnlyUnimportant ? 1 : 2;
+            transitionValues.values.put(IMPORTANT_PROP, val);
+        }
+
+        @Override
+        public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
+                TransitionValues endValues) {
+            if (startValues != null && endValues != null) {
+                latch.countDown();
+            }
+
+            return null;
+        }
+    }
 }
 
diff --git a/tests/tests/transition/src/android/transition/cts/VisibilityTest.java b/tests/tests/transition/src/android/transition/cts/VisibilityTest.java
index 9b91a36..81977a4 100644
--- a/tests/tests/transition/src/android/transition/cts/VisibilityTest.java
+++ b/tests/tests/transition/src/android/transition/cts/VisibilityTest.java
@@ -15,9 +15,15 @@
  */
 package android.transition.cts;
 
+import android.animation.Animator;
+import android.transition.TransitionManager;
 import android.transition.TransitionValues;
 import android.transition.Visibility;
 import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 public class VisibilityTest extends BaseTransitionTest {
     Visibility mVisibilityTransition;
@@ -104,5 +110,102 @@
         mTransition.captureStartValues(goneValues);
         assertFalse(mVisibilityTransition.isVisible(goneValues));
     }
+
+    public void testOnAppear() throws Throwable {
+        enterScene(R.layout.scene4);
+        AppearTransition transition = new AppearTransition();
+        mTransition = transition;
+        resetListener();
+        startTransition(R.layout.scene5);
+        assertTrue(transition.onAppearCalled.await(500, TimeUnit.MILLISECONDS));
+        // No need to end the transition since AppearTransition doesn't create
+        // any animators.
+    }
+
+    public void testOnDisppear() throws Throwable {
+        // First, test with overlay
+        enterScene(R.layout.scene5);
+        DisappearTransition transition = new DisappearTransition(true);
+        mTransition = transition;
+        resetListener();
+        startTransition(R.layout.scene4);
+        assertTrue(transition.onDisppearCalled.await(500, TimeUnit.MILLISECONDS));
+        // No need to end the transition since DisappearTransition doesn't create
+        // any animators.
+
+        // Next test without overlay
+        enterScene(R.layout.scene5);
+        transition = new DisappearTransition(false);
+        mTransition = transition;
+        resetListener();
+        final View text = getActivity().findViewById(R.id.text);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                TransitionManager.beginDelayedTransition(mSceneRoot, mTransition);
+                text.setVisibility(View.GONE);
+            }
+        });
+        assertTrue(transition.onDisppearCalled.await(500, TimeUnit.MILLISECONDS));
+        // No need to end the transition since DisappearTransition doesn't create
+        // any animators.
+    }
+
+    static class AppearTransition extends Visibility {
+        private View mExpectedView;
+        public CountDownLatch onAppearCalled = new CountDownLatch(1);
+        @Override
+        public Animator onAppear(ViewGroup sceneRoot, TransitionValues startValues,
+                int startVisibility, TransitionValues endValues, int endVisibility) {
+            assertNotNull(endValues);
+            mExpectedView = endValues.view;
+            return super.onAppear(sceneRoot, startValues, startVisibility, endValues,
+                    endVisibility);
+        }
+
+        @Override
+        public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues,
+                TransitionValues endValues) {
+            assertSame(mExpectedView, view);
+            onAppearCalled.countDown();
+            return null;
+        }
+    }
+
+    static class DisappearTransition extends Visibility {
+        private View mExpectedView;
+        private final boolean mExpectingOverlay;
+        public CountDownLatch onDisppearCalled = new CountDownLatch(1);
+
+        public DisappearTransition(boolean expectingOverlay) {
+            mExpectingOverlay = expectingOverlay;
+        }
+
+        @Override
+        public Animator onDisappear(ViewGroup sceneRoot, TransitionValues startValues,
+                int startVisibility, TransitionValues endValues, int endVisibility) {
+            assertNotNull(startValues);
+            if (mExpectingOverlay) {
+                assertNull(endValues);
+                mExpectedView = null;
+            } else {
+                assertNotNull(endValues);
+                mExpectedView = endValues.view;
+            }
+            return super.onDisappear(sceneRoot, startValues, startVisibility, endValues,
+                    endVisibility);
+        }
+
+        @Override
+        public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues,
+                TransitionValues endValues) {
+            assertNotNull(view);
+            if (mExpectedView != null) {
+                assertSame(mExpectedView, view);
+            }
+            onDisppearCalled.countDown();
+            return null;
+        }
+    }
 }
 
diff --git a/tests/tests/uirendering/Android.mk b/tests/tests/uirendering/Android.mk
index fd01e10..a2e54d0 100644
--- a/tests/tests/uirendering/Android.mk
+++ b/tests/tests/uirendering/Android.mk
@@ -26,7 +26,7 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/tests/uirendering/res/drawable-nodpi/golden_blue_circle.png b/tests/tests/uirendering/res/drawable-nodpi/golden_blue_circle.png
new file mode 100644
index 0000000..f587fb7
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable-nodpi/golden_blue_circle.png
Binary files differ
diff --git a/tests/tests/uirendering/res/drawable-nodpi/golden_dashed_oval.png b/tests/tests/uirendering/res/drawable-nodpi/golden_dashed_oval.png
new file mode 100644
index 0000000..c95568a
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable-nodpi/golden_dashed_oval.png
Binary files differ
diff --git a/tests/tests/uirendering/res/drawable/dashed_oval.xml b/tests/tests/uirendering/res/drawable/dashed_oval.xml
new file mode 100644
index 0000000..904b016
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable/dashed_oval.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+       Licensed under the Apache License, Version 2.0 (the "License");
+       you may not use this file except in compliance with the License.
+       You may obtain a copy of the License at
+
+            http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+       See the License for the specific language governing permissions and
+       limitations under the License.
+  -->
+<shape
+    android:shape="oval"
+    xmlns:android="http://schemas.android.com/apk/res/android">
+    <stroke
+        android:width="2px"
+        android:dashGap="6px"
+        android:dashWidth="2px"
+        android:color="@android:color/black"
+        />
+</shape>
diff --git a/tests/tests/uirendering/res/layout/frame_layout.xml b/tests/tests/uirendering/res/layout/frame_layout.xml
index 0eb1f9b..4ceac5d 100644
--- a/tests/tests/uirendering/res/layout/frame_layout.xml
+++ b/tests/tests/uirendering/res/layout/frame_layout.xml
@@ -17,4 +17,3 @@
     android:id="@+id/frame_layout"
     android:layout_width="@dimen/test_width"
     android:layout_height="@dimen/test_height"/>
-
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/GoldenImageVerifier.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/GoldenImageVerifier.java
index 42e8960..b9816db 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/GoldenImageVerifier.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/GoldenImageVerifier.java
@@ -15,7 +15,9 @@
  */
 package android.uirendering.cts.bitmapverifiers;
 
+import android.content.Context;
 import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.uirendering.cts.bitmapcomparers.BitmapComparer;
 import android.uirendering.cts.differencevisualizers.PassFailVisualizer;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
@@ -31,6 +33,10 @@
         mBitmapComparer = bitmapComparer;
     }
 
+    public GoldenImageVerifier(Context context, int goldenResId, BitmapComparer bitmapComparer) {
+        this(BitmapFactory.decodeResource(context.getResources(), goldenResId), bitmapComparer);
+    }
+
     @Override
     public boolean verify(int[] bitmap, int offset, int stride, int width, int height) {
         boolean success = mBitmapComparer.verifySame(mGoldenBitmapArray, bitmap, offset, stride,
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 1e7a832..8360948 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/CanvasStateTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/CanvasStateTests.java
@@ -16,12 +16,18 @@
 
 package android.uirendering.cts.testclasses;
 
+import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
 import android.graphics.Path;
 import android.graphics.RectF;
 import android.graphics.Region;
 import android.test.suitebuilder.annotation.MediumTest;
+import android.uirendering.cts.bitmapverifiers.ColorVerifier;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
+import android.util.DisplayMetrics;
+
 import org.junit.Test;
 
 import static org.junit.Assert.assertFalse;
@@ -114,4 +120,68 @@
                 })
                 .runWithoutVerification();
     }
+
+    private void testFailureOnBitmapDraw(Bitmap bitmap) {
+        createTest()
+                .addCanvasClient((canvas, width, height) -> {
+                    boolean sawException = false;
+                    try {
+                        canvas.drawBitmap(bitmap, 0, 0, null);
+                    } catch (RuntimeException e) {
+                        sawException = true;
+                    }
+                    assertTrue(sawException);
+                })
+                .runWithoutVerification();
+    }
+
+    @Test
+    public void testFailureOnDrawRecycledBitmap() {
+        Bitmap recycledBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
+        recycledBitmap.recycle();
+        testFailureOnBitmapDraw(recycledBitmap);
+    }
+
+    @Test
+    public void testFailureOnNonPremultipliedBitmap() {
+        Bitmap nonPremultipliedBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
+        nonPremultipliedBitmap.setPremultiplied(false);
+        nonPremultipliedBitmap.setHasAlpha(true);
+        testFailureOnBitmapDraw(nonPremultipliedBitmap);
+    }
+
+    @Test
+    public void testDrawScreenWideBitmap() {
+        createTest()
+                .addCanvasClient((canvas, width, height) -> {
+                    DisplayMetrics displayMetrics =
+                            getActivity().getResources().getDisplayMetrics();
+                    assertTrue(displayMetrics.widthPixels <= canvas.getMaximumBitmapWidth());
+                    assertTrue(displayMetrics.heightPixels <= canvas.getMaximumBitmapHeight());
+                    Bitmap bitmap = Bitmap.createBitmap(displayMetrics.widthPixels,
+                            displayMetrics.heightPixels, Bitmap.Config.ARGB_8888);
+                    bitmap.eraseColor(Color.RED);
+                    canvas.drawBitmap(bitmap, 0, 0, null);
+                })
+                .runWithVerifier(new ColorVerifier(Color.RED, 0));
+    }
+
+    @Test
+    public void testDrawLargeBitmap() {
+        // verify that HW and SW pipelines can both draw screen-and-a-half sized bitmap
+        createTest()
+                .addCanvasClient((canvas, width, height) -> {
+                    DisplayMetrics displayMetrics =
+                            getActivity().getResources().getDisplayMetrics();
+
+                    int bWidth = displayMetrics.widthPixels * 3 / 2;
+                    int bHeight = displayMetrics.heightPixels * 3 / 2;
+                    bWidth = Math.min(bWidth, canvas.getMaximumBitmapWidth());
+                    bHeight = Math.min(bHeight, canvas.getMaximumBitmapHeight());
+                    Bitmap bitmap = Bitmap.createBitmap(bWidth, bHeight, Bitmap.Config.ARGB_8888);
+                    bitmap.eraseColor(Color.RED);
+                    canvas.drawBitmap(bitmap, 0, 0, null);
+                })
+                .runWithVerifier(new ColorVerifier(Color.RED, 0));
+    }
 }
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShapeTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShapeTests.java
new file mode 100644
index 0000000..18fd2bc
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShapeTests.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.uirendering.cts.testclasses;
+
+import android.graphics.*;
+import android.test.suitebuilder.annotation.MediumTest;
+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;
+
+@MediumTest
+public class ShapeTests extends ActivityTestBase {
+    @Test
+    public void testDashedOval() {
+        createTest()
+                .addLayout(R.layout.frame_layout,
+                        view -> view.setBackgroundResource(R.drawable.dashed_oval))
+                .runWithVerifier(new GoldenImageVerifier(getActivity(),
+                        R.drawable.golden_dashed_oval, new MSSIMComparer(0.99)));
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewAnimationUtilsTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewAnimationUtilsTests.java
new file mode 100644
index 0000000..4a3e7cf
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewAnimationUtilsTests.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.uirendering.cts.testclasses;
+
+import android.test.suitebuilder.annotation.MediumTest;
+import android.uirendering.cts.R;
+import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
+import android.uirendering.cts.bitmapverifiers.GoldenImageVerifier;
+import android.uirendering.cts.testinfrastructure.ActivityTestBase;
+import android.uirendering.cts.testinfrastructure.ViewInitializer;
+import android.view.ViewAnimationUtils;
+import org.junit.Test;
+
+@MediumTest
+public class ViewAnimationUtilsTests extends ActivityTestBase {
+    @Test
+    public void testCreateCircularReveal() {
+        createTest()
+                .addLayout(R.layout.blue_padded_layout, (ViewInitializer) view -> {
+                    ViewAnimationUtils.createCircularReveal(view, 45, 45, 45, 45)
+                            .setDuration(10000) // 10 sec, longer than animation
+                            .start();
+                }, true)
+                .runWithVerifier(new GoldenImageVerifier(getActivity(),
+                        R.drawable.golden_blue_circle, new MSSIMComparer(0.99)));
+    }
+}
diff --git a/tests/tests/util/Android.mk b/tests/tests/util/Android.mk
index cb1c70a..866e566 100644
--- a/tests/tests/util/Android.mk
+++ b/tests/tests/util/Android.mk
@@ -24,7 +24,7 @@
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-annotations android-support-test ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/util/src/android/util/cts/MutableTest.java b/tests/tests/util/src/android/util/cts/MutableTest.java
new file mode 100644
index 0000000..e4f6fd9
--- /dev/null
+++ b/tests/tests/util/src/android/util/cts/MutableTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util.cts;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class MutableTest {
+    @Test
+    public void testMutableBoolean() {
+        MutableBoolean mut = new MutableBoolean(false);
+        assertFalse(mut.value);
+        mut = new MutableBoolean(true);
+        assertTrue(mut.value);
+    }
+
+    @Test
+    public void testMutableByte() {
+        MutableByte mut = new MutableByte((byte) 127);
+        assertEquals(127, mut.value);
+        mut = new MutableByte((byte) -128);
+        assertEquals(-128, mut.value);
+    }
+
+    @Test
+    public void testMutableChar() {
+        MutableChar mut = new MutableChar('a');
+        assertEquals('a', mut.value);
+        mut = new MutableChar('b');
+        assertEquals('b', mut.value);
+    }
+
+    @Test
+    public void testMutableDouble() {
+        MutableDouble mut = new MutableDouble(0);
+        assertEquals(0, mut.value, 0);
+        mut = new MutableDouble(Double.MAX_VALUE);
+        assertEquals(Double.MAX_VALUE, mut.value, 0);
+    }
+
+    @Test
+    public void testMutableFloat() {
+        MutableFloat mut = new MutableFloat(0f);
+        assertEquals(0f, mut.value, 0);
+        mut = new MutableFloat(Float.MAX_VALUE);
+        assertEquals(Float.MAX_VALUE, mut.value, 0);
+    }
+
+    @Test
+    public void testMutableShort() {
+        MutableShort mut = new MutableShort((short) 0);
+        assertEquals(0, mut.value);
+        mut = new MutableShort(Short.MAX_VALUE);
+        assertEquals(Short.MAX_VALUE, mut.value);
+    }
+}
diff --git a/tests/tests/util/src/android/util/cts/PropertyTest.java b/tests/tests/util/src/android/util/cts/PropertyTest.java
index 22ad2c4..3d76e36 100644
--- a/tests/tests/util/src/android/util/cts/PropertyTest.java
+++ b/tests/tests/util/src/android/util/cts/PropertyTest.java
@@ -17,51 +17,62 @@
 package android.util.cts;
 
 import android.graphics.Point;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
 import android.util.FloatProperty;
 import android.util.IntProperty;
 import android.util.Property;
-import junit.framework.TestCase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
-public class PropertyTest extends TestCase {
+import static org.junit.Assert.*;
 
-    float mFloatValue = -1;
-    int mIntValue = -2;
-    Point mPointValue = new Point(-3, -4);
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class PropertyTest {
+    private float mFloatValue = -1;
+    private int mIntValue = -2;
+    private Point mPointValue = new Point(-3, -4);
 
+    @Test
     public void testProperty() throws Exception {
         float testFloatValue = 5;
         Point testPointValue = new Point(10, 20);
 
         assertFalse(getFloatProp() == testFloatValue);
         assertFalse(getPointProp().equals(testPointValue));
-        assertEquals(RAW_FLOAT_PROP.get(this), getFloatProp());
-        assertEquals(RAW_POINT_PROP.get(this), getPointProp());
+        assertEquals(getFloatProp(), RAW_FLOAT_PROP.get(this), 0f);
+        assertEquals(getPointProp(), RAW_POINT_PROP.get(this));
 
         RAW_FLOAT_PROP.set(this, testFloatValue);
-        assertEquals(RAW_FLOAT_PROP.get(this), mFloatValue);
+        assertEquals(mFloatValue, RAW_FLOAT_PROP.get(this), 0f);
 
         RAW_POINT_PROP.set(this, testPointValue);
-        assertEquals(RAW_POINT_PROP.get(this), testPointValue);
+        assertEquals(testPointValue, RAW_POINT_PROP.get(this));
     }
 
+    @Test
     public void testFloatProperty() throws Exception {
-        float testFloatValue = 5;
+        assertFalse(getFloatProp() == 5);
+        assertEquals(getFloatProp(), FLOAT_PROP.get(this), 0f);
 
-        assertFalse(getFloatProp() == testFloatValue);
-        assertEquals(FLOAT_PROP.get(this), getFloatProp());
+        FLOAT_PROP.set(this, 5f);
+        assertEquals(5f, FLOAT_PROP.get(this), 0f);
 
-        FLOAT_PROP.set(this, testFloatValue);
-        assertEquals(FLOAT_PROP.get(this), testFloatValue);
+        FLOAT_PROP.setValue(this, 10);
+        assertEquals(10f, FLOAT_PROP.get(this), 0f);
     }
 
+    @Test
     public void testIntProperty() throws Exception {
-        int testIntValue = 5;
+        assertFalse(getIntProp() == 5);
+        assertEquals(getIntProp(), INT_PROP.get(this).intValue());
 
-        assertFalse(getIntProp() == testIntValue);
-        assertEquals(INT_PROP.get(this).intValue(), getIntProp());
+        INT_PROP.set(this, 5);
+        assertEquals(5, INT_PROP.get(this).intValue());
 
-        INT_PROP.set(this, testIntValue);
-        assertEquals(INT_PROP.get(this).intValue(), testIntValue);
+        INT_PROP.setValue(this, 10);
+        assertEquals(10, INT_PROP.get(this).intValue());
     }
 
     // Utility methods to get/set instance values. Used by Property classes below.
@@ -91,9 +102,9 @@
     }
 
     // Properties. RAW subclass from the generic Property class, the others subclass from
-    // the primtive-friendly IntProperty and FloatProperty subclasses.
+    // the primitive-friendly IntProperty and FloatProperty subclasses.
 
-    public static final Property<PropertyTest, Point> RAW_POINT_PROP =
+    private static final Property<PropertyTest, Point> RAW_POINT_PROP =
             new Property<PropertyTest, Point>(Point.class, "rawPoint") {
                 @Override
                 public void set(PropertyTest object, Point value) {
@@ -106,7 +117,7 @@
                 }
             };
 
-    public static final Property<PropertyTest, Float> RAW_FLOAT_PROP =
+    private static final Property<PropertyTest, Float> RAW_FLOAT_PROP =
             new Property<PropertyTest, Float>(Float.class, "rawFloat") {
                 @Override
                 public void set(PropertyTest object, Float value) {
@@ -119,7 +130,7 @@
                 }
             };
 
-    public static final Property<PropertyTest, Float> FLOAT_PROP =
+    private static final FloatProperty<PropertyTest> FLOAT_PROP =
             new FloatProperty<PropertyTest>("float") {
 
                 @Override
@@ -133,7 +144,7 @@
                 }
             };
 
-    public static final Property<PropertyTest, Integer> INT_PROP =
+    private static final IntProperty<PropertyTest> INT_PROP =
             new IntProperty<PropertyTest>("int") {
 
                 @Override
diff --git a/tests/tests/util/src/android/util/cts/RationalTest.java b/tests/tests/util/src/android/util/cts/RationalTest.java
index ab5c063..dabb29d 100644
--- a/tests/tests/util/src/android/util/cts/RationalTest.java
+++ b/tests/tests/util/src/android/util/cts/RationalTest.java
@@ -369,6 +369,34 @@
         }
     }
 
+    @SmallTest
+    public void testParseRational() {
+        assertEquals(new Rational(1, 2), Rational.parseRational("3:+6"));
+        assertEquals(new Rational(1, 2), Rational.parseRational("-3:-6"));
+        assertEquals(Rational.NaN, Rational.parseRational("NaN"));
+        assertEquals(Rational.POSITIVE_INFINITY, Rational.parseRational("Infinity"));
+        assertEquals(Rational.NEGATIVE_INFINITY, Rational.parseRational("-Infinity"));
+        assertEquals(Rational.ZERO, Rational.parseRational("0/261"));
+        assertEquals(Rational.NaN, Rational.parseRational("0/-0"));
+        assertEquals(Rational.POSITIVE_INFINITY, Rational.parseRational("1000/+0"));
+        assertEquals(Rational.NEGATIVE_INFINITY, Rational.parseRational("-1000/-0"));
+
+        try {
+            fail("Parsing " + Rational.parseRational("1.5") + " should not have succeeded");
+        } catch (NumberFormatException exception) {
+            // OK
+        }
+
+        try {
+            fail("Parsing " + Rational.parseRational("239") + " should not have succeeded");
+        } catch (NumberFormatException exception) {
+            // OK
+        }
+
+        Rational r = new Rational(10, 15);
+        assertEquals(r, Rational.parseRational(r.toString()));
+    }
+
     private static void assertValueEquals(Rational object, float expected) {
         assertEquals("Checking floatValue() for " + object + ";",
                 expected, object.floatValue());
diff --git a/tests/tests/util/src/android/util/cts/SizeTest.java b/tests/tests/util/src/android/util/cts/SizeTest.java
new file mode 100644
index 0000000..b0cc89b
--- /dev/null
+++ b/tests/tests/util/src/android/util/cts/SizeTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util.cts;
+
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Size;
+import android.util.SizeF;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SizeTest {
+    @Test
+    public void testConstructors() {
+        Size size = new Size(100, 200);
+        assertEquals(100, size.getWidth());
+        assertEquals(200, size.getHeight());
+
+        SizeF sizeF = new SizeF(100, 200);
+        assertEquals(100, sizeF.getWidth(), 0f);
+        assertEquals(200, sizeF.getHeight(), 0f);
+    }
+
+    @Test
+    public void testParseSize() {
+        try {
+            Size.parseSize("2by4");
+            fail("Should not be able to parse");
+        } catch (NumberFormatException ignored) {
+        }
+
+        assertEquals(new Size(100, 200), Size.parseSize("100*200"));
+        assertEquals(new Size(10, 20), Size.parseSize("10x20"));
+        assertEquals(new SizeF(9999, 9999), SizeF.parseSizeF("9999x9999"));
+    }
+
+    @Test
+    public void testParseSizeF() {
+        try {
+            SizeF.parseSizeF("2by4");
+            fail("Should not be able to parse");
+        } catch (NumberFormatException ignored) {
+        }
+
+        assertEquals(new SizeF(100f, 200f), SizeF.parseSizeF("100*200"));
+        assertEquals(new SizeF(10f, 20f), SizeF.parseSizeF("10x20"));
+        assertEquals(new SizeF(1000000f, 2.4f), SizeF.parseSizeF("1e6x2.4"));
+    }
+}
diff --git a/tests/tests/util/src/android/util/cts/TypedValueTest.java b/tests/tests/util/src/android/util/cts/TypedValueTest.java
index 2ab91d9..735074f 100644
--- a/tests/tests/util/src/android/util/cts/TypedValueTest.java
+++ b/tests/tests/util/src/android/util/cts/TypedValueTest.java
@@ -205,4 +205,24 @@
 
         assertEquals(TypedValue.complexToDimension(10, dm), tv.getDimension(dm));
     }
+
+    public void testGetComplexUnit() {
+        TypedValue tv = new TypedValue();
+        tv.data = 256;
+        assertEquals(TypedValue.COMPLEX_UNIT_PX, tv.getComplexUnit());
+        tv.data = 257;
+        assertEquals(TypedValue.COMPLEX_UNIT_DIP, tv.getComplexUnit());
+        tv.data = 258;
+        assertEquals(TypedValue.COMPLEX_UNIT_SP, tv.getComplexUnit());
+        tv.data = 259;
+        assertEquals(TypedValue.COMPLEX_UNIT_PT, tv.getComplexUnit());
+        tv.data = 260;
+        assertEquals(TypedValue.COMPLEX_UNIT_IN, tv.getComplexUnit());
+        tv.data = 261;
+        assertEquals(TypedValue.COMPLEX_UNIT_MM, tv.getComplexUnit());
+        tv.data = 21474864;
+        assertEquals(TypedValue.COMPLEX_UNIT_FRACTION, tv.getComplexUnit());
+        tv.data = 21474865;
+        assertEquals(TypedValue.COMPLEX_UNIT_FRACTION_PARENT, tv.getComplexUnit());
+    }
 }
diff --git a/tests/tests/view/Android.mk b/tests/tests/view/Android.mk
index ba4be93..d6100c8 100644
--- a/tests/tests/view/Android.mk
+++ b/tests/tests/view/Android.mk
@@ -29,11 +29,12 @@
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-test \
     ctsdeviceutil \
     ctstestrunner \
     mockito-target \
-    ub-uiautomator \
-    android-support-test
+    platform-test-annotations \
+    ub-uiautomator
 
 LOCAL_JNI_SHARED_LIBRARIES := libctsview_jni libnativehelper_compat_libc++
 
diff --git a/tests/tests/view/jni/Android.mk b/tests/tests/view/jni/Android.mk
index ac7b844..288e250 100644
--- a/tests/tests/view/jni/Android.mk
+++ b/tests/tests/view/jni/Android.mk
@@ -18,6 +18,8 @@
 
 LOCAL_MODULE := libctsview_jni
 
+LOCAL_CFLAGS += -Werror
+
 LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := \
diff --git a/tests/tests/view/jni/CtsViewJniOnLoad.cpp b/tests/tests/view/jni/CtsViewJniOnLoad.cpp
index 2c1e643..1a7ef3c 100644
--- a/tests/tests/view/jni/CtsViewJniOnLoad.cpp
+++ b/tests/tests/view/jni/CtsViewJniOnLoad.cpp
@@ -16,8 +16,8 @@
  */
 #include <jni.h>
 
-#include <utils/Log.h>
 #define LOG_TAG "CtsViewJniOnLoad"
+#include <utils/Log.h>
 
 extern int register_android_view_cts_ChoreographerNativeTest(JNIEnv* env);
 
diff --git a/tests/tests/view/src/android/view/cts/AbsSavedStateTest.java b/tests/tests/view/src/android/view/cts/AbsSavedStateTest.java
index 3662e2c..e4165bb 100644
--- a/tests/tests/view/src/android/view/cts/AbsSavedStateTest.java
+++ b/tests/tests/view/src/android/view/cts/AbsSavedStateTest.java
@@ -18,83 +18,128 @@
 
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.support.test.filters.SmallTest;
 import android.test.InstrumentationTestCase;
 import android.view.AbsSavedState;
 
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+@SmallTest
 public class AbsSavedStateTest extends InstrumentationTestCase {
 
-    // constant for test of writeToParcel
-    public static final int TEST_NUMBER = 1;
-
     public void testConstructor() {
-        MockParcelable superState = new MockParcelable();
-        assertNotNull(superState);
-        new MockAbsSavedState(superState);
+        try {
+            new AbsSavedStateImpl((Parcelable) null);
+            fail("Expected NullPointerException");
+        } catch (IllegalArgumentException e) {
+            // Expected.
+        }
+
+        try {
+            new AbsSavedStateImpl((Parcel) null);
+            fail("Expected NullPointerException");
+        } catch (NullPointerException e) {
+            // Expected.
+        }
+
+        try {
+            new AbsSavedStateImpl(null, null);
+            fail("Expected NullPointerException");
+        } catch (NullPointerException e) {
+            // Expected.
+        }
+
+        AbsSavedState superState = new AbsSavedStateImpl(Parcel.obtain());
+        assertNull(superState.getSuperState());
+
+        AbsSavedState s = new AbsSavedStateImpl(superState);
+        assertSame(superState, s.getSuperState());
 
         Parcel source = Parcel.obtain();
-        new MockAbsSavedState(source);
+        source.writeParcelable(superState, 0);
+        source.setDataPosition(0);
+        s = new AbsSavedStateImpl(source);
+        assertTrue(s.getSuperState() instanceof AbsSavedState);
 
-        MockAbsSavedState savedState = new MockAbsSavedState(source);
-        assertEquals(0, savedState.describeContents());
+        source = Parcel.obtain();
+        s = new AbsSavedStateImpl(source);
+        assertSame(AbsSavedState.EMPTY_STATE, s.getSuperState());
+
+        ClassLoader loader = AbsSavedState.class.getClassLoader();
+        source = Parcel.obtain();
+        source.writeParcelable(superState, 0);
+        source.setDataPosition(0);
+        s = new AbsSavedStateImpl(source, loader);
+        assertTrue(s.getSuperState() instanceof AbsSavedState);
+
+        source = Parcel.obtain();
+        s = new AbsSavedStateImpl(source, loader);
+        assertSame(AbsSavedState.EMPTY_STATE, s.getSuperState());
     }
 
-    public void testGetSuperState() {
-        MockParcelable superState = new MockParcelable();
-        assertNotNull(superState);
-        MockAbsSavedState savedState = new MockAbsSavedState(superState);
+    public void testCreator() {
+        int size = 10;
+        AbsSavedState[] array = AbsSavedState.CREATOR.newArray(size);
+        assertNotNull(array);
+        assertEquals(size, array.length);
+        for (AbsSavedState state : array) {
+            assertNull(state);
+        }
 
-        assertSame(superState, savedState.getSuperState());
+        AbsSavedState state = new AbsSavedStateImpl(AbsSavedState.EMPTY_STATE);
+        Parcel parcel = Parcel.obtain();
+        state.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+        AbsSavedState unparceled = AbsSavedState.CREATOR.createFromParcel(parcel);
+        assertNotNull(unparceled);
+        assertEquals(AbsSavedState.EMPTY_STATE, unparceled.getSuperState());
+
+        AbsSavedState stateWithSuper = new AbsSavedStateImpl(state);
+        parcel = Parcel.obtain();
+        stateWithSuper.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+        try {
+            AbsSavedState.CREATOR.createFromParcel(parcel);
+            fail("Expected IllegalStateException");
+        } catch (IllegalStateException e) {
+            // Expected.
+        }
     }
 
     public void testWriteToParcel() {
-        MockParcelable superState = new MockParcelable();
-        assertNotNull(superState);
-        MockAbsSavedState savedState = new MockAbsSavedState(superState);
-
+        Parcelable superState = mock(Parcelable.class);
+        AbsSavedState savedState = new AbsSavedStateImpl(superState);
         Parcel dest = Parcel.obtain();
         int flags = 2;
         savedState.writeToParcel(dest, flags);
-
-        // we instantiate the writeToParcel of Parcalable
-        // and give a return for test
-        assertEquals(TEST_NUMBER, superState.writeToParcelRunSymbol());
-        assertEquals(flags, superState.getFlags());
+        verify(superState).writeToParcel(eq(dest), eq(flags));
     }
 
-    static class MockAbsSavedState extends AbsSavedState {
-
-        public MockAbsSavedState(Parcelable superState) {
+    private static class AbsSavedStateImpl extends AbsSavedState {
+        AbsSavedStateImpl(Parcelable superState) {
             super(superState);
         }
 
-        public MockAbsSavedState(Parcel source) {
+        AbsSavedStateImpl(Parcel source) {
             super(source);
         }
-    }
 
-    static class MockParcelable implements Parcelable {
-
-        // Test for writeToParcel
-        private int mTest;
-        private int mFlags;
-
-        public int describeContents() {
-            return 0;
+        AbsSavedStateImpl(Parcel source, ClassLoader loader) {
+            super(source, loader);
         }
 
-        // Instantiate writeToParcel
-        public void writeToParcel(Parcel dest, int flags) {
-            mTest = TEST_NUMBER;
-            mFlags = flags;
-        }
+        public static final Creator<AbsSavedStateImpl> CREATOR = new Creator<AbsSavedStateImpl>() {
+            @Override
+            public AbsSavedStateImpl createFromParcel(Parcel source) {
+                return new AbsSavedStateImpl(source);
+            }
 
-        // For test of writeToParcel
-        public int writeToParcelRunSymbol() {
-            return mTest;
-        }
-
-        public int getFlags() {
-            return mFlags;
-        }
+            @Override
+            public AbsSavedStateImpl[] newArray(int size) {
+                return new AbsSavedStateImpl[size];
+            }
+        };
     }
 }
diff --git a/tests/tests/view/src/android/view/cts/NumberPickerTest.java b/tests/tests/view/src/android/view/cts/NumberPickerTest.java
deleted file mode 100644
index 2e2733e..0000000
--- a/tests/tests/view/src/android/view/cts/NumberPickerTest.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-package android.view.cts;
-
-import android.test.AndroidTestCase;
-import android.widget.NumberPicker;
-
-public class NumberPickerTest extends AndroidTestCase {
-
-    public void testSetDisplayedValues1() throws Exception {
-        NumberPicker numberPicker = new NumberPicker(getContext());
-        numberPicker.setMinValue(10);
-        numberPicker.setMaxValue(12);
-        numberPicker.setDisplayedValues(new String[]{"One", "Two", "Three"});
-    }
-
-    public void testSetDisplayedValues2() throws Exception {
-        NumberPicker numberPicker = new NumberPicker(getContext());
-        numberPicker.setMinValue(10);
-        numberPicker.setMaxValue(14);
-        try {
-            numberPicker.setDisplayedValues(new String[]{"One", "Two", "Three"});
-            fail("The size of the displayed values array must be equal to the selectable numbers!");
-        } catch (Exception e) {
-            /* expected */
-        }
-    }
-}
diff --git a/tests/tests/view/src/android/view/cts/ViewOutlineProviderTest.java b/tests/tests/view/src/android/view/cts/ViewOutlineProviderTest.java
new file mode 100644
index 0000000..bf21b30
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/ViewOutlineProviderTest.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.cts;
+
+import android.annotation.NonNull;
+import android.app.Activity;
+import android.graphics.Color;
+import android.graphics.Outline;
+import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.View;
+import android.view.ViewOutlineProvider;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ViewOutlineProviderTest {
+    @Rule
+    public ActivityTestRule mActivityTestRule = new ActivityTestRule<>(MockActivity.class);
+
+    Activity getActivity() { return mActivityTestRule.getActivity(); }
+
+    @Test
+    public void testBackground() {
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+            View view = new View(mActivityTestRule.getActivity());
+            view.setLeftTopRightBottom(100, 200, 300, 400);
+
+
+            Outline outline = new Outline();
+            outline.setAlpha(1.0f);
+            Rect queryRect = new Rect();
+
+
+            // No background - outline is 0 alpha, width x height rect
+            ViewOutlineProvider.BACKGROUND.getOutline(view, outline);
+            outline.getRect(queryRect);
+            assertEquals(new Rect(0, 0, 200, 200), queryRect);
+            assertEquals(0f, outline.getAlpha(), 0f);
+
+
+            // With background - outline is passed directly from background
+            view.setBackground(new ColorDrawable(Color.BLACK) {
+                @Override
+                public void getOutline(@NonNull Outline outline) {
+                    outline.setRect(1, 2, 3, 4);
+                    outline.setAlpha(0.123f);
+                }
+            });
+            ViewOutlineProvider.BACKGROUND.getOutline(view, outline);
+            outline.getRect(queryRect);
+            assertEquals(new Rect(1, 2, 3, 4), queryRect);
+            assertEquals(0.123f, outline.getAlpha(), 0f);
+        });
+    }
+
+
+    @Test
+    public void testBounds() {
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+            View view = new View(mActivityTestRule.getActivity());
+
+            Outline outline = new Outline();
+            Rect queryRect = new Rect();
+            outline.setAlpha(0.123f);
+
+            view.setLeftTopRightBottom(1, 2, 3, 4);
+            ViewOutlineProvider.BOUNDS.getOutline(view, outline);
+            outline.getRect(queryRect);
+            assertEquals(new Rect(0, 0, 2, 2), queryRect); // local width/height
+            assertEquals(0.123f, outline.getAlpha(), 0f); // alpha not changed
+
+            view.setLeftTopRightBottom(100, 200, 300, 400);
+            ViewOutlineProvider.BOUNDS.getOutline(view, outline);
+            outline.getRect(queryRect);
+            assertEquals(new Rect(0, 0, 200, 200), queryRect); // local width/height
+            assertEquals(0.123f, outline.getAlpha(), 0f); // alpha not changed
+        });
+    }
+
+    @Test
+    public void testPaddedBounds() {
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+            View view = new View(mActivityTestRule.getActivity());
+
+            Outline outline = new Outline();
+            Rect queryRect = new Rect();
+            outline.setAlpha(0.123f);
+
+            view.setLeftTopRightBottom(10, 20, 30, 40);
+            view.setPadding(0, 0, 0, 0);
+            ViewOutlineProvider.PADDED_BOUNDS.getOutline(view, outline);
+            outline.getRect(queryRect);
+            assertEquals(new Rect(0, 0, 20, 20), queryRect); // local width/height
+            assertEquals(0.123f, outline.getAlpha(), 0f); // alpha not changed
+
+            view.setPadding(5, 5, 5, 5);
+            ViewOutlineProvider.PADDED_BOUNDS.getOutline(view, outline);
+            outline.getRect(queryRect);
+            assertEquals(new Rect(5, 5, 15, 15), queryRect); // local width/height, inset by 5
+            assertEquals(0.123f, outline.getAlpha(), 0f); // alpha not changed
+        });
+    }
+}
diff --git a/tests/tests/view/src/android/view/cts/View_BaseSavedStateTest.java b/tests/tests/view/src/android/view/cts/View_BaseSavedStateTest.java
index ce64a18..8ce70f2 100644
--- a/tests/tests/view/src/android/view/cts/View_BaseSavedStateTest.java
+++ b/tests/tests/view/src/android/view/cts/View_BaseSavedStateTest.java
@@ -16,15 +16,86 @@
 
 package android.view.cts;
 
-
 import android.os.Parcel;
+import android.os.Parcelable;
+import android.support.test.filters.SmallTest;
 import android.test.InstrumentationTestCase;
+import android.view.AbsSavedState;
 import android.view.View.BaseSavedState;
 
-public class View_BaseSavedStateTest extends InstrumentationTestCase {
-    public void testConstructors() {
-        BaseSavedState state = new BaseSavedState(Parcel.obtain());
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
 
-        new BaseSavedState(state);
+@SmallTest
+public class View_BaseSavedStateTest extends InstrumentationTestCase {
+
+    public void testConstructors() {
+        try {
+            new BaseSavedState((Parcelable) null);
+            fail("Expected NullPointerException");
+        } catch (IllegalArgumentException e) {
+            // Expected.
+        }
+
+        try {
+            new BaseSavedState((Parcel) null);
+            fail("Expected NullPointerException");
+        } catch (NullPointerException e) {
+            // Expected.
+        }
+
+        try {
+            new BaseSavedState(null, null);
+            fail("Expected NullPointerException");
+        } catch (NullPointerException e) {
+            // Expected.
+        }
+
+        BaseSavedState superState = new BaseSavedState(Parcel.obtain());
+        assertEquals(AbsSavedState.EMPTY_STATE, superState.getSuperState());
+
+        BaseSavedState s = new BaseSavedState(superState);
+        assertEquals(superState, s.getSuperState());
+
+        Parcel source = Parcel.obtain();
+        source.writeParcelable(superState, 0);
+        source.setDataPosition(0);
+        s = new BaseSavedState(source);
+        assertTrue(s.getSuperState() instanceof BaseSavedState);
+
+        ClassLoader loader = BaseSavedState.class.getClassLoader();
+        source = Parcel.obtain();
+        source.writeParcelable(superState, 0);
+        source.setDataPosition(0);
+        s = new BaseSavedState(source, loader);
+        assertTrue(s.getSuperState() instanceof BaseSavedState);
+    }
+
+    public void testCreator() {
+        int size = 10;
+        BaseSavedState[] array = BaseSavedState.CREATOR.newArray(size);
+        assertNotNull(array);
+        assertEquals(size, array.length);
+        for (BaseSavedState state : array) {
+            assertNull(state);
+        }
+
+        BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
+        Parcel parcel = Parcel.obtain();
+        state.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+        BaseSavedState unparceled = BaseSavedState.CREATOR.createFromParcel(parcel);
+        assertNotNull(unparceled);
+        assertEquals(AbsSavedState.EMPTY_STATE, unparceled.getSuperState());
+    }
+
+    public void testWriteToParcel() {
+        Parcelable superState = mock(Parcelable.class);
+        BaseSavedState savedState = new BaseSavedState(superState);
+        Parcel dest = Parcel.obtain();
+        int flags = 2;
+        savedState.writeToParcel(dest, flags);
+        verify(superState).writeToParcel(eq(dest), eq(flags));
     }
 }
diff --git a/tests/tests/widget/Android.mk b/tests/tests/widget/Android.mk
index 4bc9eee..3d4cead 100644
--- a/tests/tests/widget/Android.mk
+++ b/tests/tests/widget/Android.mk
@@ -22,10 +22,12 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
 LOCAL_STATIC_JAVA_LIBRARIES += \
+    android-support-test \
     mockito-target \
     android-common \
     ctsdeviceutil \
-    ctstestrunner
+    ctstestrunner \
+    platform-test-annotations
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
diff --git a/tests/tests/widget/AndroidManifest.xml b/tests/tests/widget/AndroidManifest.xml
index 224966d..c200799 100644
--- a/tests/tests/widget/AndroidManifest.xml
+++ b/tests/tests/widget/AndroidManifest.xml
@@ -92,9 +92,25 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="android.widget.cts.SpinnerCtsActivity"
+                  android:label="SpinnerCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
         <activity android:name="android.widget.cts.ToolbarCtsActivity"
-            android:theme="@android:style/Theme.Material.Light.NoActionBar"
-            android:label="ToolbarCtsActivity">
+                  android:theme="@android:style/Theme.Material.Light.NoActionBar"
+                  android:label="ToolbarCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.ActionMenuViewCtsActivity"
+                  android:label="ActionMenuViewCtsActivity">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
@@ -149,6 +165,14 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="android.widget.cts.AbsSeekBarCtsActivity"
+            android:label="AbsSeekBarCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
         <activity android:name="android.widget.cts.ProgressBarCtsActivity"
             android:label="ProgressBarCtsActivity">
             <intent-filter>
@@ -189,8 +213,16 @@
             </intent-filter>
         </activity>
 
-        <activity android:name="android.widget.cts.ExpandableListSimple"
-            android:label="ExpandableListSimple">
+        <activity android:name="android.widget.cts.ExpandableListBasic"
+                  android:label="ExpandableListBasic">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.ExpandableList"
+                  android:label="ExpandableList">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
@@ -388,6 +420,70 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="android.widget.cts.DatePickerCtsActivity"
+                  android:label="DatePickerCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.SearchViewCtsActivity"
+                  android:label="SearchViewCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.ImageButtonCtsActivity"
+                  android:label="ImageButtonCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.NumberPickerCtsActivity"
+                  android:label="NumberPickerCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.CheckBoxCtsActivity"
+                  android:label="CheckBoxCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.RadioButtonCtsActivity"
+                  android:label="RadioButtonCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.ToggleButtonCtsActivity"
+                  android:label="ToggleButtonCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.TimePickerCtsActivity"
+                  android:label="TimePickerCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
         <activity android:name="android.app.ActivityGroup"
             android:label="ActivityGroup" />
 
diff --git a/tests/tests/widget/res/drawable/blue_fill.xml b/tests/tests/widget/res/drawable/blue_fill.xml
index 5a24f08..383e7db 100644
--- a/tests/tests/widget/res/drawable/blue_fill.xml
+++ b/tests/tests/widget/res/drawable/blue_fill.xml
@@ -17,5 +17,5 @@
 <shape
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle">
-    <solid android:color="#0000FF" />
+    <solid android:color="#00F" />
 </shape>
\ No newline at end of file
diff --git a/tests/tests/widget/res/drawable/green_fill.xml b/tests/tests/widget/res/drawable/green_fill.xml
new file mode 100644
index 0000000..76c1101
--- /dev/null
+++ b/tests/tests/widget/res/drawable/green_fill.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid android:color="#0F0" />
+</shape>
\ No newline at end of file
diff --git a/tests/tests/widget/res/drawable/linear_layout_divider_magenta.xml b/tests/tests/widget/res/drawable/linear_layout_divider_magenta.xml
new file mode 100644
index 0000000..2dbd654
--- /dev/null
+++ b/tests/tests/widget/res/drawable/linear_layout_divider_magenta.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid
+        android:color="#F0F" />
+    <size
+        android:width="@dimen/linear_layout_divider_size"
+        android:height="@dimen/linear_layout_divider_size" />
+</shape>
\ No newline at end of file
diff --git a/tests/tests/widget/res/drawable/linear_layout_divider_red.xml b/tests/tests/widget/res/drawable/linear_layout_divider_red.xml
new file mode 100644
index 0000000..56e88ef
--- /dev/null
+++ b/tests/tests/widget/res/drawable/linear_layout_divider_red.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid
+        android:color="#F00" />
+    <size
+        android:width="@dimen/linear_layout_divider_size"
+        android:height="@dimen/linear_layout_divider_size" />
+</shape>
\ No newline at end of file
diff --git a/tests/tests/widget/res/drawable/magenta_fill.xml b/tests/tests/widget/res/drawable/magenta_fill.xml
index cbb594f..8b6da76 100644
--- a/tests/tests/widget/res/drawable/magenta_fill.xml
+++ b/tests/tests/widget/res/drawable/magenta_fill.xml
@@ -17,5 +17,5 @@
 <shape
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle">
-    <solid android:color="#FF00FF" />
+    <solid android:color="#F0F" />
 </shape>
\ No newline at end of file
diff --git a/tests/tests/widget/res/drawable/red_fill.xml b/tests/tests/widget/res/drawable/red_fill.xml
index e443240..8baf5b6 100644
--- a/tests/tests/widget/res/drawable/red_fill.xml
+++ b/tests/tests/widget/res/drawable/red_fill.xml
@@ -17,5 +17,5 @@
 <shape
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle">
-    <solid android:color="#8F00" />
+    <solid android:color="#F00" />
 </shape>
\ No newline at end of file
diff --git a/tests/tests/widget/res/drawable/red_translucent_fill.xml b/tests/tests/widget/res/drawable/red_translucent_fill.xml
new file mode 100644
index 0000000..edfbfa0
--- /dev/null
+++ b/tests/tests/widget/res/drawable/red_translucent_fill.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid android:color="#80FF0000" />
+</shape>
\ No newline at end of file
diff --git a/tests/tests/widget/res/drawable/yellow_fill.xml b/tests/tests/widget/res/drawable/yellow_fill.xml
index 3bd80977..44f88c4 100644
--- a/tests/tests/widget/res/drawable/yellow_fill.xml
+++ b/tests/tests/widget/res/drawable/yellow_fill.xml
@@ -17,5 +17,5 @@
 <shape
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle">
-    <solid android:color="#FFFF00" />
+    <solid android:color="#FF0" />
 </shape>
\ No newline at end of file
diff --git a/tests/tests/widget/res/layout/actionmenuview_layout.xml b/tests/tests/widget/res/layout/actionmenuview_layout.xml
new file mode 100644
index 0000000..5d2895e
--- /dev/null
+++ b/tests/tests/widget/res/layout/actionmenuview_layout.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="horizontal">
+
+    <Button
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/button" />
+
+    <ActionMenuView
+        android:id="@+id/action_menu_view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+</LinearLayout>
+
diff --git a/tests/tests/widget/res/layout/autocompletetextview_layout.xml b/tests/tests/widget/res/layout/autocompletetextview_layout.xml
index 27eccab..8e023a1 100644
--- a/tests/tests/widget/res/layout/autocompletetextview_layout.xml
+++ b/tests/tests/widget/res/layout/autocompletetextview_layout.xml
@@ -24,10 +24,11 @@
         android:layout_height="wrap_content"
         android:text="@string/notify" />
 
-    <android.widget.cts.AutoCompleteTextViewNoIme android:id="@+id/autocompletetv_edit"
-        android:completionThreshold="1"
-        android:completionHint="@string/tabs_1"
+    <android.widget.cts.AutoCompleteTextViewNoIme
+        android:id="@+id/autocompletetv_edit"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:completionThreshold="1"
+        android:completionHint="@string/tabs_1"
         android:inputType="none"/>
 </LinearLayout>
diff --git a/tests/tests/widget/res/layout/calendarview_layout.xml b/tests/tests/widget/res/layout/calendarview_layout.xml
index 3bc5e47..507d48e 100644
--- a/tests/tests/widget/res/layout/calendarview_layout.xml
+++ b/tests/tests/widget/res/layout/calendarview_layout.xml
@@ -17,6 +17,7 @@
 
 <ScrollView
     xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/scroller"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:fillViewport="true">
diff --git a/tests/tests/widget/res/layout/checkbox_layout.xml b/tests/tests/widget/res/layout/checkbox_layout.xml
index a1f1718..c922436 100644
--- a/tests/tests/widget/res/layout/checkbox_layout.xml
+++ b/tests/tests/widget/res/layout/checkbox_layout.xml
@@ -14,12 +14,14 @@
  * 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"
-                android:orientation="vertical">
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
 
-    <CheckBox android:id="@+id/check_box"
+    <CheckBox
+        android:id="@+id/check_box"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="@string/hello_world" />
diff --git a/tests/tests/widget/res/layout/checkedtextview_layout.xml b/tests/tests/widget/res/layout/checkedtextview_layout.xml
index d5b9c1f..fbee93e 100644
--- a/tests/tests/widget/res/layout/checkedtextview_layout.xml
+++ b/tests/tests/widget/res/layout/checkedtextview_layout.xml
@@ -14,20 +14,22 @@
      limitations under the License.
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent">
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
 
-    <ListView android:id="@+id/checkedtextview_listview"
-        android:orientation="vertical"
+    <ListView
+        android:id="@+id/checkedtextview_listview"
         android:layout_width="match_parent"
-        android:layout_height="match_parent">
-    </ListView>
+        android:layout_height="0dip"
+        android:layout_weight="1" />
 
-    <CheckedTextView android:id="@+id/checkedtextview_test"
-        android:orientation="vertical"
+    <CheckedTextView
+        android:id="@+id/checkedtextview_test"
         android:layout_width="match_parent"
-        android:layout_height="match_parent">
-    </CheckedTextView>
+        android:layout_height="wrap_content"
+        android:text="@string/hello_world" />
 
 </LinearLayout>
diff --git a/tests/tests/widget/res/layout/datepicker_layout.xml b/tests/tests/widget/res/layout/datepicker_layout.xml
index 925674c..9857440 100644
--- a/tests/tests/widget/res/layout/datepicker_layout.xml
+++ b/tests/tests/widget/res/layout/datepicker_layout.xml
@@ -14,14 +14,29 @@
      limitations under the License.
 -->
 
-<RelativeLayout
+<ScrollView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
-    <DatePicker
-        android:id="@+id/datePicker_dp"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_centerInParent="true" />
+    android:layout_height="match_parent"
+    android:fillViewport="true">
 
-</RelativeLayout>
+    <LinearLayout
+        android:id="@+id/container"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+
+        <DatePicker
+            android:id="@+id/date_picker_calendar_mode"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:datePickerMode="calendar" />
+
+        <DatePicker
+            android:id="@+id/date_picker_spinner_mode"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:datePickerMode="spinner" />
+
+    </LinearLayout>
+</ScrollView>
diff --git a/tests/tests/widget/res/layout/expandablelistview_child.xml b/tests/tests/widget/res/layout/expandablelistview_child.xml
new file mode 100644
index 0000000..b34f10b
--- /dev/null
+++ b/tests/tests/widget/res/layout/expandablelistview_child.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:textSize="18sp" />
diff --git a/tests/tests/widget/res/layout/expandablelistview_group.xml b/tests/tests/widget/res/layout/expandablelistview_group.xml
new file mode 100644
index 0000000..be929ee
--- /dev/null
+++ b/tests/tests/widget/res/layout/expandablelistview_group.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:textStyle="bold"
+    android:textSize="24sp" />
diff --git a/tests/tests/widget/res/layout/imagebutton_layout.xml b/tests/tests/widget/res/layout/imagebutton_layout.xml
new file mode 100644
index 0000000..f59f669
--- /dev/null
+++ b/tests/tests/widget/res/layout/imagebutton_layout.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2016 The Android Open Source Project.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <ImageButton
+        android:id="@+id/image_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:src="@drawable/icon_red" />
+
+</LinearLayout>
diff --git a/tests/tests/widget/res/layout/imagebutton_test.xml b/tests/tests/widget/res/layout/imagebutton_test.xml
deleted file mode 100644
index 7d4b691..0000000
--- a/tests/tests/widget/res/layout/imagebutton_test.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2008 The Android Open Source Project.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-<ImageButton xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/imagebutton"
-    android:layout_width="96px"
-    android:layout_height="76px"
-    android:soundEffectsEnabled="false"
-/>
-
diff --git a/tests/tests/widget/res/layout/linearlayout_layout.xml b/tests/tests/widget/res/layout/linearlayout_layout.xml
index 8881552..11d2a71 100644
--- a/tests/tests/widget/res/layout/linearlayout_layout.xml
+++ b/tests/tests/widget/res/layout/linearlayout_layout.xml
@@ -14,125 +14,228 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:id="@+id/linearlayout_root"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:orientation="vertical">
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/linearlayout_root"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
 
-    <LinearLayout android:id="@+id/horizontal"
-        android:orientation="horizontal"
+    <LinearLayout
+        android:id="@+id/horizontal"
         android:layout_width="wrap_content"
         android:layout_height="100dip"
-        android:background="#FF909090">
+        android:orientation="horizontal"
+        android:background="#888">
 
-        <TextView android:id="@+id/gravity_top"
-            android:background="#FF00FF00"
+        <TextView
+            android:id="@+id/gravity_top"
             android:layout_width="wrap_content"
             android:layout_height="50dip"
             android:layout_gravity="top"
-            android:text="@string/horizontal_text_1"/>
+            android:background="#0F0"
+            android:text="@string/horizontal_text_1" />
 
-        <TextView android:id="@+id/gravity_center_vertical"
-            android:background="#FF00FF00"
+        <TextView
+            android:id="@+id/gravity_center_vertical"
             android:layout_width="wrap_content"
             android:layout_height="50dip"
             android:layout_gravity="center_vertical"
-            android:text="@string/horizontal_text_2"/>
+            android:background="#0F0"
+            android:text="@string/horizontal_text_2" />
 
-        <TextView android:id="@+id/gravity_bottom"
-            android:background="#FF00FF00"
+        <TextView
+            android:id="@+id/gravity_bottom"
             android:layout_width="wrap_content"
             android:layout_height="50dip"
             android:layout_gravity="bottom"
-            android:text="@string/horizontal_text_3"/>
+            android:background="#0F0"
+            android:text="@string/horizontal_text_3" />
     </LinearLayout>
 
-    <LinearLayout android:id="@+id/vertical"
-        android:orientation="vertical"
+    <LinearLayout
+        android:id="@+id/vertical"
         android:layout_width="100dip"
         android:layout_height="wrap_content"
-        android:background="#FFFF0909">
+        android:orientation="vertical"
+        android:background="#F00">
 
-        <TextView android:id="@+id/gravity_left"
-            android:background="#FF00FF00"
+        <TextView
+            android:id="@+id/gravity_left"
             android:layout_width="wrap_content"
             android:layout_height="20dip"
             android:layout_gravity="left"
-            android:text="@string/vertical_text_1"/>
+            android:background="#0F0"
+            android:text="@string/vertical_text_1" />
 
-        <TextView android:id="@+id/gravity_center_horizontal"
-            android:background="#FF0000FF"
+        <TextView
+            android:id="@+id/gravity_center_horizontal"
             android:layout_width="wrap_content"
             android:layout_height="20dip"
             android:layout_gravity="center_horizontal"
-            android:text="@string/vertical_text_2"/>
+            android:background="#00F"
+            android:text="@string/vertical_text_2" />
 
-        <TextView android:id="@+id/gravity_right"
-            android:background="#FF00FF00"
+        <TextView
+            android:id="@+id/gravity_right"
             android:layout_width="wrap_content"
             android:layout_height="20dip"
             android:layout_gravity="right"
-            android:text="@string/vertical_text_3"/>
+            android:background="#0F0"
+            android:text="@string/vertical_text_3" />
     </LinearLayout>
 
-    <LinearLayout android:id="@+id/weightsum"
+    <LinearLayout
+        android:id="@+id/weightsum"
+        android:layout_width="100dip"
+        android:layout_height="100dip"
         android:orientation="horizontal"
         android:weightSum="1.0"
         android:baselineAligned="false"
-        android:layout_width="100dip"
-        android:layout_height="100dip"
-        android:background="#FF909090">
+        android:background="#888">
 
-        <TextView android:id="@+id/weight_0_2"
-            android:background="#FF0000FF"
+        <TextView
+            android:id="@+id/weight_0_2"
             android:layout_width="0dip"
             android:layout_height="wrap_content"
             android:layout_weight="0.2"
-            android:text="@string/horizontal_text_1"/>
+            android:background="#00F"
+            android:text="@string/horizontal_text_1" />
 
-        <TextView android:id="@+id/weight_0_5"
-            android:background="#FFF00F0F"
+        <TextView
+            android:id="@+id/weight_0_5"
             android:layout_width="0dip"
             android:layout_height="wrap_content"
             android:layout_weight="0.5"
-            android:text="@string/horizontal_text_2"/>
+            android:background="#F00"
+            android:text="@string/horizontal_text_2" />
 
-        <TextView android:id="@+id/weight_0_3"
-            android:background="#FF0000FF"
+        <TextView
+            android:id="@+id/weight_0_3"
             android:layout_width="0dip"
             android:layout_height="wrap_content"
             android:layout_weight="0.3"
-            android:text="@string/horizontal_text_3"/>
+            android:background="#00F"
+            android:text="@string/horizontal_text_3" />
     </LinearLayout>
 
-    <LinearLayout android:id="@+id/baseline_aligned_child_index"
+    <LinearLayout
+        android:id="@+id/weightsum_vertical"
+        android:layout_width="100dip"
+        android:layout_height="100dip"
         android:orientation="vertical"
-        android:baselineAlignedChildIndex="1"
+        android:weightSum="1.0"
+        android:baselineAligned="false"
+        android:background="#888">
+
+        <TextView
+            android:id="@+id/weight_0_1"
+            android:layout_width="wrap_content"
+            android:layout_height="0dip"
+            android:layout_weight="0.1"
+            android:background="#00F"
+            android:text="@string/vertical_text_1" />
+
+        <TextView
+            android:id="@+id/weight_0_4"
+            android:layout_width="wrap_content"
+            android:layout_height="0dip"
+            android:layout_weight="0.4"
+            android:background="#F00"
+            android:text="@string/vertical_text_2" />
+
+        <TextView
+            android:id="@+id/weight_0_5"
+            android:layout_width="wrap_content"
+            android:layout_height="0dip"
+            android:layout_weight="0.5"
+            android:background="#00F"
+            android:text="@string/vertical_text_3" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/baseline_aligned_child_index"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:background="#FFFF0909">
+        android:orientation="vertical"
+        android:baselineAlignedChildIndex="1"
+        android:background="#F00">
 
-        <TextView android:id="@+id/textview1"
-            android:background="#FF00FF00"
+        <TextView
+            android:id="@+id/textview1"
             android:layout_width="wrap_content"
             android:layout_height="20dip"
             android:layout_gravity="left"
-            android:text="@string/vertical_text_1"/>
+            android:background="#0F0"
+            android:text="@string/vertical_text_1" />
 
-        <TextView android:id="@+id/textview2"
-            android:background="#FF0000FF"
+        <TextView
+            android:id="@+id/textview2"
             android:layout_width="wrap_content"
             android:layout_height="20dip"
             android:layout_gravity="center_horizontal"
-            android:text="@string/vertical_text_2"/>
+            android:background="#00F"
+            android:text="@string/vertical_text_2" />
 
-        <TextView android:id="@+id/textview3"
-            android:background="#FF00FF00"
+        <TextView
+            android:id="@+id/textview3"
             android:layout_width="wrap_content"
             android:layout_height="20dip"
             android:layout_gravity="right"
-            android:text="@string/vertical_text_3"/>
+            android:background="#0F0"
+            android:text="@string/vertical_text_3" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/vertical_with_divider"
+        android:layout_width="100px"
+        android:layout_height="100px"
+        android:orientation="vertical"
+        android:background="#FF0"
+        android:showDividers="middle"
+        android:divider="@drawable/linear_layout_divider_red"
+        android:dividerPadding="@dimen/linear_layout_divider_padding">
+
+        <View
+            android:id="@+id/child1"
+            android:layout_width="match_parent"
+            android:layout_height="0dip"
+            android:layout_weight="0.5"
+            android:background="#00F" />
+
+        <View
+            android:id="@+id/child2"
+            android:layout_width="match_parent"
+            android:layout_height="0dip"
+            android:layout_weight="0.5"
+            android:background="#0F0" />
+
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/horizontal_with_divider"
+        android:layout_width="100px"
+        android:layout_height="100px"
+        android:orientation="horizontal"
+        android:background="#FF0"
+        android:showDividers="middle"
+        android:divider="@drawable/linear_layout_divider_red"
+        android:dividerPadding="@dimen/linear_layout_divider_padding">
+
+        <View
+            android:id="@+id/child1"
+            android:layout_width="0dip"
+            android:layout_height="match_parent"
+            android:layout_weight="0.5"
+            android:background="#00F" />
+
+        <View
+            android:id="@+id/child2"
+            android:layout_width="0dip"
+            android:layout_height="match_parent"
+            android:layout_weight="0.5"
+            android:background="#0F0" />
+
     </LinearLayout>
 
 </LinearLayout>
diff --git a/tests/tests/widget/res/layout/numberpicker_layout.xml b/tests/tests/widget/res/layout/numberpicker_layout.xml
new file mode 100644
index 0000000..2e370d8
--- /dev/null
+++ b/tests/tests/widget/res/layout/numberpicker_layout.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <NumberPicker
+        android:id="@+id/number_picker"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/tests/widget/res/layout/progressbar_layout.xml b/tests/tests/widget/res/layout/progressbar_layout.xml
index a1786b8..f242135 100644
--- a/tests/tests/widget/res/layout/progressbar_layout.xml
+++ b/tests/tests/widget/res/layout/progressbar_layout.xml
@@ -14,28 +14,47 @@
      limitations under the License.
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<ScrollView
+    xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:fillViewport="true">
 
-    <ProgressBar
-        android:id="@+id/progress_tint"
-        android:progressTint="@android:color/white"
-        android:progressTintMode="src_over"
-        android:progressBackgroundTint="@android:color/white"
-        android:progressBackgroundTintMode="src_over"
-        android:secondaryProgressTint="@android:color/white"
-        android:secondaryProgressTintMode="src_over"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        style="@android:style/Widget.ProgressBar.Horizontal" />
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
 
-    <ProgressBar
-        android:id="@+id/indeterminate_tint"
-        android:indeterminateTint="@android:color/white"
-        android:indeterminateTintMode="src_over"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        style="@android:style/Widget.ProgressBar.Large" />
+        <ProgressBar
+            style="@android:style/Widget.Material.Light.ProgressBar"
+            android:id="@+id/progress"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
 
-</LinearLayout>
+        <ProgressBar
+            style="@android:style/Widget.Material.Light.ProgressBar.Horizontal"
+            android:id="@+id/progress_horizontal"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" />
+
+        <ProgressBar
+            style="@android:style/Widget.Material.Light.ProgressBar.Horizontal"
+            android:id="@+id/progress_tint"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:progressTint="@android:color/white"
+            android:progressTintMode="src_over"
+            android:progressBackgroundTint="@android:color/white"
+            android:progressBackgroundTintMode="src_over"
+            android:secondaryProgressTint="@android:color/white"
+            android:secondaryProgressTintMode="src_over" />
+
+        <ProgressBar
+            style="@android:style/Widget.Material.Light.ProgressBar.Large"
+            android:id="@+id/indeterminate_tint"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:indeterminateTint="@android:color/white"
+            android:indeterminateTintMode="src_over" />
+
+    </LinearLayout>
+</ScrollView>
\ No newline at end of file
diff --git a/tests/tests/widget/res/layout/radiobutton_layout.xml b/tests/tests/widget/res/layout/radiobutton_layout.xml
new file mode 100644
index 0000000..23c1839
--- /dev/null
+++ b/tests/tests/widget/res/layout/radiobutton_layout.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2016 The Android Open Source Project.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <RadioButton
+        android:id="@+id/radio_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/hello_world" />
+
+</LinearLayout>
diff --git a/tests/tests/widget/res/layout/ratingbar_layout.xml b/tests/tests/widget/res/layout/ratingbar_layout.xml
index acc7fa8..b2fb4c7 100644
--- a/tests/tests/widget/res/layout/ratingbar_layout.xml
+++ b/tests/tests/widget/res/layout/ratingbar_layout.xml
@@ -14,18 +14,19 @@
      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">
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
 
-    <RatingBar android:id="@+id/ratingbar_constructor"
+    <RatingBar
+        android:id="@+id/ratingbar_constructor"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
         android:isIndicator="false"
         android:numStars="50"
         android:rating="1.2"
-        android:stepSize="0.2"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_weight="1"/>
+        android:stepSize="0.2" />
 
 </LinearLayout>
diff --git a/tests/tests/widget/res/layout/remoteviews_good.xml b/tests/tests/widget/res/layout/remoteviews_good.xml
index 8fdbc64..1db2157 100644
--- a/tests/tests/widget/res/layout/remoteviews_good.xml
+++ b/tests/tests/widget/res/layout/remoteviews_good.xml
@@ -14,42 +14,56 @@
      limitations under the License.
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/remoteViews_good"
-    android:orientation="vertical"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
 
-    <LinearLayout android:id="@+id/remoteView_linear"
+    <LinearLayout
+        android:id="@+id/remoteView_linear"
         android:layout_width="10dip"
         android:layout_height="10dip" />
 
-    <TextView android:id="@+id/remoteView_text"
+    <TextView
+        android:id="@+id/remoteView_text"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content" />
 
-    <ImageView android:id="@+id/remoteView_image"
+    <ImageView
+        android:id="@+id/remoteView_image"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content" />
 
-    <FrameLayout android:id="@+id/remoteView_frame"
+    <FrameLayout
+        android:id="@+id/remoteView_frame"
         android:layout_width="10dip"
         android:layout_height="10dip" />
 
-    <RelativeLayout android:id="@+id/remoteView_relative"
+    <RelativeLayout
+        android:id="@+id/remoteView_relative"
         android:layout_width="10dip"
         android:layout_height="10dip" />
 
-    <AbsoluteLayout android:id="@+id/remoteView_absolute"
+    <AbsoluteLayout
+        android:id="@+id/remoteView_absolute"
         android:layout_width="10dip"
         android:layout_height="10dip" />
 
-    <ProgressBar android:id="@+id/remoteView_progress"
+    <ProgressBar
+        android:id="@+id/remoteView_progress"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         style="?android:attr/progressBarStyleHorizontal" />
 
-    <Chronometer android:id="@+id/remoteView_chronometer"
+    <Chronometer
+        android:id="@+id/remoteView_chronometer"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <android.widget.cts.MyRemotableView
+        android:id="@+id/remoteView_custom"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content" />
 
diff --git a/tests/tests/widget/res/layout/searchview_layout.xml b/tests/tests/widget/res/layout/searchview_layout.xml
new file mode 100644
index 0000000..b8705e0
--- /dev/null
+++ b/tests/tests/widget/res/layout/searchview_layout.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <SearchView
+        android:id="@+id/search_view"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+
+    <SearchView
+        android:id="@+id/search_view_with_defaults"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:maxWidth="@dimen/search_view_max_width"
+        android:iconifiedByDefault="false"
+        android:queryHint="@string/search_query_hint"
+        android:inputType="textCapCharacters"
+        android:imeOptions="actionDone" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/tests/widget/res/layout/searchview_suggestion_item.xml b/tests/tests/widget/res/layout/searchview_suggestion_item.xml
new file mode 100644
index 0000000..91f02f5
--- /dev/null
+++ b/tests/tests/widget/res/layout/searchview_suggestion_item.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/text1"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/search_view_suggestion_row_height"
+    android:textAppearance="?android:attr/textAppearanceListItemSmall"
+    android:gravity="center_vertical"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" />
diff --git a/tests/tests/widget/res/layout/simple_spinner_item_layout.xml b/tests/tests/widget/res/layout/simple_spinner_item_layout.xml
new file mode 100644
index 0000000..512b138
--- /dev/null
+++ b/tests/tests/widget/res/layout/simple_spinner_item_layout.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/text1"
+    style="?android:attr/spinnerItemStyle"
+    android:singleLine="true"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:ellipsize="marquee"
+    android:textAlignment="inherit"/>
diff --git a/tests/tests/widget/res/layout/spinner_layout.xml b/tests/tests/widget/res/layout/spinner_layout.xml
new file mode 100644
index 0000000..43a6411
--- /dev/null
+++ b/tests/tests/widget/res/layout/spinner_layout.xml
@@ -0,0 +1,44 @@
+<?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.
+-->
+
+<ScrollView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:fillViewport="true">
+
+    <LinearLayout
+        android:id="@+id/container"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+
+        <Spinner
+            android:id="@+id/spinner_dropdown_mode"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:spinnerMode="dropdown"
+            android:prompt="@string/text_view_hello" />
+
+        <Spinner
+            android:id="@+id/spinner_dialog_mode"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:spinnerMode="dialog"
+            android:prompt="@string/text_view_hello" />
+
+    </LinearLayout>
+</ScrollView>
diff --git a/tests/tests/widget/res/layout/switch_layout.xml b/tests/tests/widget/res/layout/switch_layout.xml
index 12e10d2..880c6df 100644
--- a/tests/tests/widget/res/layout/switch_layout.xml
+++ b/tests/tests/widget/res/layout/switch_layout.xml
@@ -15,11 +15,31 @@
   ~ limitations under the License
   -->
 
-<Switch xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/switch_view"
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <Switch
+        android:id="@+id/switch1"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:thumbTint="@android:color/white"
         android:thumbTintMode="src_over"
         android:trackTint="@android:color/black"
         android:trackTintMode="src_atop" />
+
+    <Switch
+        android:id="@+id/switch2"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:thumb="@drawable/icon_blue"
+        android:track="@drawable/red_translucent_fill" />
+
+    <Switch
+        android:id="@+id/switch3"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/tests/widget/res/layout/textview_layout.xml b/tests/tests/widget/res/layout/textview_layout.xml
index e3144eb..87ceac1 100644
--- a/tests/tests/widget/res/layout/textview_layout.xml
+++ b/tests/tests/widget/res/layout/textview_layout.xml
@@ -14,209 +14,264 @@
      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:id="@+id/layout_textviewtest">
+<ScrollView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/scroller"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:fillViewport="true">
 
-    <ScrollView android:layout_width="match_parent"
-            android:layout_height="match_parent">
+        <LinearLayout
+            android:id="@+id/layout_textviewtest"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
 
-        <LinearLayout android:orientation="vertical"
+            <TextView
+                android:id="@+id/textview_textAttr"
+                android:fontFamily="@null"
+                android:text="@string/text_view_hello"
+                android:textColor="@drawable/black"
+                android:textColorHighlight="@drawable/yellow"
+                android:textColorHint="@drawable/red"
+                android:textColorLink="@drawable/blue"
+                android:textScaleX="1.2"
+                android:typeface="normal"
+                android:textSize="20px"
+                android:textStyle="normal"
+                android:textAppearance="@null"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"/>
+
+            <TextView
+                android:id="@+id/textview_password"
+                android:password="true"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"/>
+
+            <TextView
+                android:id="@+id/textview_singleLine"
+                android:singleLine="true"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"/>
+
+            <TextView
+                android:id="@+id/textview_text"
+                android:text="@string/text_view_hello"
+                android:breakStrategy="simple"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"/>
+
+            <TextView
+                android:id="@+id/textview_text_two_lines"
+                android:text="@string/text_view_hello_two_lines"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"/>
+
+            <android.widget.cts.MockTextView
+                android:id="@+id/mock_textview_left"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:requiresFadingEdge="horizontal"
+                android:singleLine="true"
+                android:text="@string/long_text"
+                android:gravity="left" />
+
+            <android.widget.cts.MockTextView
+                android:id="@+id/mock_textview_right"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:requiresFadingEdge="horizontal"
+                android:singleLine="true"
+                android:text="@string/long_text"
+                android:gravity="right" />
+
+            <android.widget.cts.MockTextView
+                android:id="@+id/mock_textview_center"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:requiresFadingEdge="horizontal"
+                android:singleLine="true"
+                android:text="@string/long_text"
+                android:gravity="center" />
+
+            <TextView
+                android:id="@+id/textview_ltr"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"/>
+
+            <TextView
+                android:id="@+id/textview_rtl"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"/>
+
+            <TextView
+                android:id="@+id/textview_drawable_1_1"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:drawableLeft="@drawable/icon_blue"
+                android:drawableRight="@drawable/icon_red"
+                android:drawableTop="@drawable/icon_green"
+                android:drawableBottom="@drawable/icon_yellow"
+                android:layoutDirection="ltr" />
+
+            <TextView
+                android:id="@+id/textview_drawable_1_2"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:drawableLeft="@drawable/icon_blue"
+                android:drawableRight="@drawable/icon_red"
+                android:drawableTop="@drawable/icon_green"
+                android:drawableBottom="@drawable/icon_yellow"
+                android:layoutDirection="rtl" />
+
+            <TextView
+                android:id="@+id/textview_drawable_2_1"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:drawableStart="@drawable/icon_blue"
+                android:drawableEnd="@drawable/icon_red"
+                android:drawableTop="@drawable/icon_green"
+                android:drawableBottom="@drawable/icon_yellow"
+                android:layoutDirection="ltr" />
+
+            <TextView
+                android:id="@+id/textview_drawable_2_2"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:drawableStart="@drawable/icon_blue"
+                android:drawableEnd="@drawable/icon_red"
+                android:drawableTop="@drawable/icon_green"
+                android:drawableBottom="@drawable/icon_yellow"
+                android:layoutDirection="rtl" />
+
+            <TextView
+                android:id="@+id/textview_drawable_3_1"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:drawableLeft="@drawable/icon_black"
+                android:drawableRight="@drawable/icon_black"
+                android:drawableStart="@drawable/icon_blue"
+                android:drawableEnd="@drawable/icon_red"
+                android:drawableTop="@drawable/icon_green"
+                android:drawableBottom="@drawable/icon_yellow"
+                android:layoutDirection="ltr" />
+
+            <TextView
+                android:id="@+id/textview_drawable_3_2"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:drawableLeft="@drawable/icon_black"
+                android:drawableRight="@drawable/icon_black"
+                android:drawableStart="@drawable/icon_blue"
+                android:drawableEnd="@drawable/icon_red"
+                android:drawableTop="@drawable/icon_green"
+                android:drawableBottom="@drawable/icon_yellow"
+                android:layoutDirection="rtl" />
+
+            <LinearLayout
+                android:orientation="vertical"
                 android:layout_width="match_parent"
-                android:layout_height="match_parent">
+                android:layout_height="wrap_content"
+                android:layoutDirection="ltr">
 
-            <TextView android:id="@+id/textview_textAttr"
-                    android:fontFamily="@null"
-                    android:text="@string/text_view_hello"
-                    android:textColor="@drawable/black"
-                    android:textColorHighlight="@drawable/yellow"
-                    android:textColorHint="@drawable/red"
-                    android:textColorLink="@drawable/blue"
-                    android:textScaleX="1.2"
-                    android:typeface="normal"
-                    android:textSize="20px"
-                    android:textStyle="normal"
-                    android:textAppearance="@null"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"/>
-
-            <TextView android:id="@+id/textview_password"
-                    android:password="true"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"/>
-
-            <TextView android:id="@+id/textview_singleLine"
-                    android:singleLine="true"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"/>
-
-            <TextView android:id="@+id/textview_text"
-                    android:text="@string/text_view_hello"
-                    android:breakStrategy="simple"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"/>
-
-            <TextView android:id="@+id/textview_text_two_lines"
-                    android:text="@string/text_view_hello_two_lines"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"/>
-
-            <android.widget.cts.MockTextView
-                    android:id="@+id/mock_textview_left"
-                    android:layout_width="wrap_content"
+                <TextView
+                    android:id="@+id/textview_drawable_4_1"
                     android:layout_height="wrap_content"
-                    android:requiresFadingEdge="horizontal"
-                    android:singleLine="true"
-                    android:text="@string/long_text"
-                    android:gravity="left"
-                    />
-
-            <android.widget.cts.MockTextView
-                    android:id="@+id/mock_textview_right"
                     android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:requiresFadingEdge="horizontal"
-                    android:singleLine="true"
-                    android:text="@string/long_text"
-                    android:gravity="right"
-                    />
+                    android:drawableStart="@drawable/icon_blue"
+                    android:drawableEnd="@drawable/icon_red"
+                    android:drawableTop="@drawable/icon_green"
+                    android:drawableBottom="@drawable/icon_yellow" />
 
-            <android.widget.cts.MockTextView
-                    android:id="@+id/mock_textview_center"
-                    android:layout_width="wrap_content"
+                <TextView
+                    android:id="@+id/textview_drawable_5_1"
                     android:layout_height="wrap_content"
-                    android:requiresFadingEdge="horizontal"
-                    android:singleLine="true"
-                    android:text="@string/long_text"
-                    android:gravity="center"
-                    />
+                    android:layout_width="wrap_content"
+                    android:drawableLeft="@drawable/icon_black"
+                    android:drawableRight="@drawable/icon_black"
+                    android:drawableStart="@drawable/icon_blue"
+                    android:drawableEnd="@drawable/icon_red"
+                    android:drawableTop="@drawable/icon_green"
+                    android:drawableBottom="@drawable/icon_yellow" />
+
+            </LinearLayout>
+
+            <LinearLayout
+                android:orientation="vertical"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layoutDirection="rtl">
+
+                <TextView
+                    android:id="@+id/textview_drawable_4_2"
+                    android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    android:drawableStart="@drawable/icon_blue"
+                    android:drawableEnd="@drawable/icon_red"
+                    android:drawableTop="@drawable/icon_green"
+                    android:drawableBottom="@drawable/icon_yellow" />
+
+                <TextView
+                    android:id="@+id/textview_drawable_5_2"
+                    android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    android:drawableLeft="@drawable/icon_black"
+                    android:drawableRight="@drawable/icon_black"
+                    android:drawableStart="@drawable/icon_blue"
+                    android:drawableEnd="@drawable/icon_red"
+                    android:drawableTop="@drawable/icon_green"
+                    android:drawableBottom="@drawable/icon_yellow" />
+
+            </LinearLayout>
+
+
+            <TextView
+                android:id="@+id/textview_compound_drawable_ltr"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:paddingLeft="@dimen/textview_padding_left"
+                android:paddingRight="@dimen/textview_padding_right"
+                android:paddingTop="@dimen/textview_padding_top"
+                android:paddingBottom="@dimen/textview_padding_bottom"
+                android:drawablePadding="@dimen/textview_drawable_padding"
+                android:drawableStart="@drawable/icon_blue"
+                android:drawableEnd="@drawable/icon_red"
+                android:drawableTop="@drawable/icon_green"
+                android:drawableBottom="@drawable/icon_yellow"
+                android:layoutDirection="ltr" />
+
+            <TextView
+                android:id="@+id/textview_compound_drawable_rtl"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:paddingLeft="@dimen/textview_padding_left"
+                android:paddingRight="@dimen/textview_padding_right"
+                android:paddingTop="@dimen/textview_padding_top"
+                android:paddingBottom="@dimen/textview_padding_bottom"
+                android:drawablePadding="@dimen/textview_drawable_padding"
+                android:drawableStart="@drawable/icon_blue"
+                android:drawableEnd="@drawable/icon_red"
+                android:drawableTop="@drawable/icon_green"
+                android:drawableBottom="@drawable/icon_yellow"
+                android:layoutDirection="rtl" />
+
+            <TextView
+                android:id="@+id/textview_with_shadow"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:text="@string/text_view_hello"
+                android:shadowDx="1.0"
+                android:shadowDy="2.0"
+                android:shadowRadius="3.0"
+                android:shadowColor="@color/testcolor1" />
+
+            <EditText
+                android:id="@+id/editview_text"
+                android:text="@string/text_view_hello"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"/>
+
         </LinearLayout>
 
-    </ScrollView>
-
-    <TextView android:id="@+id/textview_ltr"
-              android:layout_height="wrap_content"
-              android:layout_width="wrap_content"/>
-
-    <TextView android:id="@+id/textview_rtl"
-              android:layout_height="wrap_content"
-              android:layout_width="wrap_content"/>
-
-    <TextView android:id="@+id/textview_drawable_1_1"
-              android:layout_height="wrap_content"
-              android:layout_width="wrap_content"
-              android:drawableLeft="@drawable/icon_blue"
-              android:drawableRight="@drawable/icon_red"
-              android:drawableTop="@drawable/icon_green"
-              android:drawableBottom="@drawable/icon_yellow"
-            />
-
-    <TextView android:id="@+id/textview_drawable_1_2"
-              android:layout_height="wrap_content"
-              android:layout_width="wrap_content"
-              android:drawableLeft="@drawable/icon_blue"
-              android:drawableRight="@drawable/icon_red"
-              android:drawableTop="@drawable/icon_green"
-              android:drawableBottom="@drawable/icon_yellow"
-              android:layoutDirection="rtl"
-            />
-
-    <TextView android:id="@+id/textview_drawable_2_1"
-              android:layout_height="wrap_content"
-              android:layout_width="wrap_content"
-              android:drawableStart="@drawable/icon_blue"
-              android:drawableEnd="@drawable/icon_red"
-              android:drawableTop="@drawable/icon_green"
-              android:drawableBottom="@drawable/icon_yellow"
-            />
-
-    <TextView android:id="@+id/textview_drawable_2_2"
-              android:layout_height="wrap_content"
-              android:layout_width="wrap_content"
-              android:drawableStart="@drawable/icon_blue"
-              android:drawableEnd="@drawable/icon_red"
-              android:drawableTop="@drawable/icon_green"
-              android:drawableBottom="@drawable/icon_yellow"
-              android:layoutDirection="rtl"
-            />
-
-    <TextView android:id="@+id/textview_drawable_3_1"
-              android:layout_height="wrap_content"
-              android:layout_width="wrap_content"
-              android:drawableLeft="@drawable/icon_black"
-              android:drawableRight="@drawable/icon_black"
-              android:drawableStart="@drawable/icon_blue"
-              android:drawableEnd="@drawable/icon_red"
-              android:drawableTop="@drawable/icon_green"
-              android:drawableBottom="@drawable/icon_yellow"
-            />
-
-    <TextView android:id="@+id/textview_drawable_3_2"
-              android:layout_height="wrap_content"
-              android:layout_width="wrap_content"
-              android:drawableLeft="@drawable/icon_black"
-              android:drawableRight="@drawable/icon_black"
-              android:drawableStart="@drawable/icon_blue"
-              android:drawableEnd="@drawable/icon_red"
-              android:drawableTop="@drawable/icon_green"
-              android:drawableBottom="@drawable/icon_yellow"
-              android:layoutDirection="rtl"
-            />
-
-
-    <LinearLayout android:orientation="vertical"
-                  android:layout_width="match_parent"
-                  android:layout_height="match_parent"
-                  android:layoutDirection="ltr">
-
-        <TextView android:id="@+id/textview_drawable_4_1"
-                  android:layout_height="wrap_content"
-                  android:layout_width="wrap_content"
-                  android:drawableStart="@drawable/icon_blue"
-                  android:drawableEnd="@drawable/icon_red"
-                  android:drawableTop="@drawable/icon_green"
-                  android:drawableBottom="@drawable/icon_yellow"
-                />
-
-        <TextView android:id="@+id/textview_drawable_5_1"
-                  android:layout_height="wrap_content"
-                  android:layout_width="wrap_content"
-                  android:drawableLeft="@drawable/icon_black"
-                  android:drawableRight="@drawable/icon_black"
-                  android:drawableStart="@drawable/icon_blue"
-                  android:drawableEnd="@drawable/icon_red"
-                  android:drawableTop="@drawable/icon_green"
-                  android:drawableBottom="@drawable/icon_yellow"
-                />
-
-    </LinearLayout>
-
-    <LinearLayout android:orientation="vertical"
-                  android:layout_width="match_parent"
-                  android:layout_height="match_parent"
-                  android:layoutDirection="rtl">
-
-        <TextView android:id="@+id/textview_drawable_4_2"
-                  android:layout_height="wrap_content"
-                  android:layout_width="wrap_content"
-                  android:drawableStart="@drawable/icon_blue"
-                  android:drawableEnd="@drawable/icon_red"
-                  android:drawableTop="@drawable/icon_green"
-                  android:drawableBottom="@drawable/icon_yellow"
-                />
-
-        <TextView android:id="@+id/textview_drawable_5_2"
-                  android:layout_height="wrap_content"
-                  android:layout_width="wrap_content"
-                  android:drawableLeft="@drawable/icon_black"
-                  android:drawableRight="@drawable/icon_black"
-                  android:drawableStart="@drawable/icon_blue"
-                  android:drawableEnd="@drawable/icon_red"
-                  android:drawableTop="@drawable/icon_green"
-                  android:drawableBottom="@drawable/icon_yellow"
-                />
-
-    </LinearLayout>
-
-</LinearLayout>
+</ScrollView>
diff --git a/tests/tests/widget/res/layout/timepicker.xml b/tests/tests/widget/res/layout/timepicker.xml
index 352f69b..a8273b2 100644
--- a/tests/tests/widget/res/layout/timepicker.xml
+++ b/tests/tests/widget/res/layout/timepicker.xml
@@ -14,6 +14,8 @@
      limitations under the License.
 -->
 
-<TimePicker xmlns:android="http://schemas.android.com/apk/res/android"
+<TimePicker
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/timepicker"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"/>
diff --git a/tests/tests/widget/res/layout/togglebutton_layout.xml b/tests/tests/widget/res/layout/togglebutton_layout.xml
index a6c08e1..de2faf3 100644
--- a/tests/tests/widget/res/layout/togglebutton_layout.xml
+++ b/tests/tests/widget/res/layout/togglebutton_layout.xml
@@ -15,8 +15,8 @@
  * limitations under the License.
  -->
 
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
+<ScrollView
+    xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
@@ -25,19 +25,35 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content">
 
-        <ToggleButton android:id="@+id/toggle1"
+        <ToggleButton
+            android:id="@+id/toggle1"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content" />
 
-        <ToggleButton android:id="@+id/toggle2"
+        <ToggleButton
+            android:id="@+id/toggle2"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content" />
 
-        <ToggleButton android:id="@+id/button_tint"
+        <ToggleButton
+            android:id="@+id/toggle_with_defaults"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textOn="@string/toggle_text_on_alt"
+            android:textOff="@string/toggle_text_off_alt" />
+
+        <ToggleButton
+            style="@style/Theme_Toggle"
+            android:id="@+id/toggle_with_style"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+
+        <ToggleButton
+            android:id="@+id/button_tint"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
             android:buttonTint="@android:color/white"
-            android:buttonTintMode="src_over"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content" />
+            android:buttonTintMode="src_over" />
 
     </LinearLayout>
 
diff --git a/tests/tests/widget/res/layout/zoombutton_layout.xml b/tests/tests/widget/res/layout/zoombutton_layout.xml
index 1b1e0b2..49031a8 100644
--- a/tests/tests/widget/res/layout/zoombutton_layout.xml
+++ b/tests/tests/widget/res/layout/zoombutton_layout.xml
@@ -14,9 +14,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  -->
-<ZoomButton xmlns:android="http://schemas.android.com/apk/res/android"
+<ZoomButton
+    xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/zoombutton_test"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
-/>
+    android:src="@drawable/icon_red" />
 
diff --git a/tests/tests/widget/res/values/attrs.xml b/tests/tests/widget/res/values/attrs.xml
index 4c3d9db..b2bea6f 100644
--- a/tests/tests/widget/res/values/attrs.xml
+++ b/tests/tests/widget/res/values/attrs.xml
@@ -142,4 +142,7 @@
     <attr name="themeGravity" />
     <attr name="themeTileMode" />
     <attr name="themeAngle" />
+
+    <attr name="chronometerStyle" format="string" />
+
 </resources>
diff --git a/tests/tests/widget/res/values/dimens.xml b/tests/tests/widget/res/values/dimens.xml
index 3690039..7cbff3a 100644
--- a/tests/tests/widget/res/values/dimens.xml
+++ b/tests/tests/widget/res/values/dimens.xml
@@ -15,4 +15,33 @@
 -->
 <resources>
     <dimen name="popup_row_height">48dp</dimen>
+
+    <dimen name="switch_padding">24dp</dimen>
+    <dimen name="switch_thumb_text_padding">12dp</dimen>
+    <dimen name="switch_min_width">160dp</dimen>
+    <dimen name="switch_min_width2">200dp</dimen>
+
+    <dimen name="autocomplete_textview_dropdown_height">120dp</dimen>
+    <dimen name="autocomplete_textview_dropdown_width">160dp</dimen>
+    <dimen name="autocomplete_textview_dropdown_offset_h">24dp</dimen>
+    <dimen name="autocomplete_textview_dropdown_offset_v">32dp</dimen>
+
+    <dimen name="spinner_dropdown_width">200dp</dimen>
+    <dimen name="spinner_dropdown_offset_h">64dp</dimen>
+    <dimen name="spinner_dropdown_offset_v">48dp</dimen>
+
+    <dimen name="search_view_max_width">160dp</dimen>
+    <dimen name="search_view_max_width2">200dp</dimen>
+    <dimen name="search_view_suggestion_row_height">48dp</dimen>
+
+    <dimen name="linear_layout_divider_size">10px</dimen>
+    <dimen name="linear_layout_divider_padding">8px</dimen>
+
+    <dimen name="textview_padding_left">4dip</dimen>
+    <dimen name="textview_padding_right">6dip</dimen>
+    <dimen name="textview_padding_start">8dip</dimen>
+    <dimen name="textview_padding_end">10dip</dimen>
+    <dimen name="textview_padding_top">2dip</dimen>
+    <dimen name="textview_padding_bottom">4dip</dimen>
+    <dimen name="textview_drawable_padding">2dip</dimen>
 </resources>
\ No newline at end of file
diff --git a/tests/tests/widget/res/values/strings.xml b/tests/tests/widget/res/values/strings.xml
index 63ceffa..3820072 100644
--- a/tests/tests/widget/res/values/strings.xml
+++ b/tests/tests/widget/res/values/strings.xml
@@ -193,4 +193,15 @@
     <string name="toolbar_subtitle">Toolbar subtitle</string>
     <string name="toolbar_navigation">Toolbar navigation</string>
     <string name="toolbar_logo">Toolbar logo</string>
+
+    <string name="search_query_hint">query hint</string>
+
+    <string name="remote_content_description">remote description</string>
+
+    <string name="toggle_text_on">On</string>
+    <string name="toggle_text_off">Off</string>
+    <string name="toggle_text_on_alt">On Alt</string>
+    <string name="toggle_text_off_alt">Off Alt</string>
+
+    <string name="chronometer_format">Current count: %s</string>
 </resources>
diff --git a/tests/tests/widget/res/values/styles.xml b/tests/tests/widget/res/values/styles.xml
index 345b450..bddc891 100644
--- a/tests/tests/widget/res/values/styles.xml
+++ b/tests/tests/widget/res/values/styles.xml
@@ -202,4 +202,19 @@
     </style>
 
     <style name="ToolbarPopupTheme_Test" parent="@android:style/ThemeOverlay.Material.Light" />
+
+    <style name="Theme_Toggle" parent="@android:style/Widget.Material.Light.Button.Toggle">
+        <item name="android:textOn">@string/toggle_text_on</item>
+        <item name="android:textOff">@string/toggle_text_off</item>
+    </style>
+
+    <style name="ChronometerStyle" parent="@android:style/Widget.Material.Light.TextView">
+        <item name="android:format">@string/chronometer_format</item>
+        <item name="android:countDown">true</item>
+    </style>
+
+    <style name="ChronometerAwareTheme" parent="@android:style/Theme.Material.Light">
+        <item name="chronometerStyle">@style/ChronometerStyle</item>
+    </style>
+
 </resources>
diff --git a/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java b/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java
index cf8012e..d080e0a 100644
--- a/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java
@@ -16,12 +16,6 @@
 
 package android.widget.cts;
 
-import android.test.suitebuilder.annotation.MediumTest;
-import android.widget.cts.R;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.content.Context;
@@ -33,6 +27,7 @@
 import android.graphics.drawable.Drawable;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.TouchUtils;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.text.Editable;
 import android.text.SpannableStringBuilder;
 import android.util.AttributeSet;
@@ -42,17 +37,29 @@
 import android.view.ViewGroup;
 import android.widget.AbsListView;
 import android.widget.AbsListView.OnScrollListener;
-import android.widget.AbsListView.RecyclerListener;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemLongClickListener;
 import android.widget.ArrayAdapter;
 import android.widget.ListAdapter;
 import android.widget.ListView;
 import android.widget.TextView;
+import android.widget.cts.util.TestUtilsMatchers;
+
+import org.hamcrest.MatcherAssert;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static org.mockito.Mockito.*;
 
 public class AbsListViewTest extends ActivityInstrumentationTestCase2<ListViewCtsActivity> {
     private final String[] mShortList = new String[] {
@@ -83,12 +90,7 @@
         super.setUp();
 
         mActivity = getActivity();
-        new PollingCheck() {
-            @Override
-                protected boolean check() {
-                return mActivity.hasWindowFocus();
-            }
-        }.run();
+        PollingCheck.waitFor(() -> mActivity.hasWindowFocus());
         mInstrumentation = getInstrumentation();
 
         XmlPullParser parser = mActivity.getResources().getXml(R.layout.listview_layout);
@@ -156,90 +158,110 @@
         });
         mInstrumentation.waitForIdleSync();
     }
+
     public void testSetOnScrollListener() throws Throwable {
-        MockOnScrollListener onScrollListener = new MockOnScrollListener();
+        AbsListView.OnScrollListener mockScrollListener =
+                mock(AbsListView.OnScrollListener.class);
 
-        assertNull(onScrollListener.getView());
-        assertEquals(0, onScrollListener.getFirstVisibleItem());
-        assertEquals(0, onScrollListener.getVisibleItemCount());
-        assertEquals(0, onScrollListener.getTotalItemCount());
-        assertEquals(-1, onScrollListener.getScrollState());
+        verifyZeroInteractions(mockScrollListener);
 
-        assertFalse(onScrollListener.isOnScrollCalled());
-        assertFalse(onScrollListener.isOnScrollStateChangedCalled());
+        mListView.setOnScrollListener(mockScrollListener);
+        verify(mockScrollListener, times(1)).onScroll(mListView, 0, 0, 0);
+        verifyNoMoreInteractions(mockScrollListener);
 
-        mListView.setOnScrollListener(onScrollListener);
-        assertSame(mListView, onScrollListener.getView());
-        assertEquals(0, onScrollListener.getFirstVisibleItem());
-        assertEquals(0, onScrollListener.getVisibleItemCount());
-        assertEquals(0, onScrollListener.getTotalItemCount());
-        assertEquals(-1, onScrollListener.getScrollState());
-
-        assertTrue(onScrollListener.isOnScrollCalled());
-        assertFalse(onScrollListener.isOnScrollStateChangedCalled());
-        onScrollListener.reset();
+        reset(mockScrollListener);
 
         setAdapter();
+        verify(mockScrollListener, times(1)).onScroll(mListView, 0, mListView.getChildCount(),
+                mCountryList.length);
+        verifyNoMoreInteractions(mockScrollListener);
 
-        assertSame(mListView, onScrollListener.getView());
-        assertEquals(0, onScrollListener.getFirstVisibleItem());
-        assertEquals(mListView.getChildCount(), onScrollListener.getVisibleItemCount());
-        assertEquals(mCountryList.length, onScrollListener.getTotalItemCount());
-        assertEquals(-1, onScrollListener.getScrollState());
-
-        assertTrue(onScrollListener.isOnScrollCalled());
-        assertFalse(onScrollListener.isOnScrollStateChangedCalled());
-        onScrollListener.reset();
+        reset(mockScrollListener);
 
         TouchUtils.scrollToBottom(this, mActivity, mListView);
-        assertSame(mListView, onScrollListener.getView());
-        assertEquals(mListView.getChildCount(), onScrollListener.getVisibleItemCount());
-        assertEquals(mCountryList.length, onScrollListener.getTotalItemCount());
 
-        assertTrue(onScrollListener.isOnScrollCalled());
-        assertTrue(onScrollListener.isOnScrollStateChangedCalled());
+        ArgumentCaptor<Integer> firstVisibleItemCaptor = ArgumentCaptor.forClass(Integer.class);
+        ArgumentCaptor<Integer> visibleItemCountCaptor = ArgumentCaptor.forClass(Integer.class);
+        verify(mockScrollListener, atLeastOnce()).onScroll(eq(mListView),
+                firstVisibleItemCaptor.capture(), visibleItemCountCaptor.capture(),
+                eq(mCountryList.length));
+
+        // We expect the first visible item values to be increasing
+        MatcherAssert.assertThat(firstVisibleItemCaptor.getAllValues(),
+                TestUtilsMatchers.inAscendingOrder());
+        // The number of visible items during scrolling may change depending on the specific
+        // scroll position. As such we only test this number at the very end
+        final List<Integer> capturedVisibleItemCounts = visibleItemCountCaptor.getAllValues();
+        assertEquals(mListView.getChildCount(),
+                (int) capturedVisibleItemCounts.get(capturedVisibleItemCounts.size() - 1));
+
+        ArgumentCaptor<Integer> scrollStateCaptor = ArgumentCaptor.forClass(Integer.class);
+        verify(mockScrollListener, atLeastOnce()).onScrollStateChanged(eq(mListView),
+                scrollStateCaptor.capture());
+
+        // Verify that the last scroll state is IDLE
+        final List<Integer> capturedScrollStates = scrollStateCaptor.getAllValues();
+        assertEquals(AbsListView.OnScrollListener.SCROLL_STATE_IDLE,
+                (int) capturedScrollStates.get(capturedScrollStates.size() - 1));
     }
 
     public void testFling() throws Throwable {
-        MockOnScrollListener onScrollListener = new MockOnScrollListener();
-        mListView.setOnScrollListener(onScrollListener);
+        AbsListView.OnScrollListener mockScrollListener = mock(AbsListView.OnScrollListener.class);
+        mListView.setOnScrollListener(mockScrollListener);
 
         setAdapter();
 
         // Fling down from top, expect a scroll.
-        fling(10000, onScrollListener);
-        assertTrue(onScrollListener.isOnScrollCalled());
-        assertTrue(0 < onScrollListener.getFirstVisibleItem());
+        fling(10000, mockScrollListener);
+        ArgumentCaptor<Integer> firstVisibleItemCaptor = ArgumentCaptor.forClass(Integer.class);
+        verify(mockScrollListener, atLeastOnce()).onScroll(eq(mListView),
+                firstVisibleItemCaptor.capture(), anyInt(), eq(mCountryList.length));
+        List<Integer> capturedFirstVisibleItems = firstVisibleItemCaptor.getAllValues();
+        assertTrue(capturedFirstVisibleItems.get(capturedFirstVisibleItems.size() - 1) > 0);
 
         // Fling up the same amount, expect a scroll to the original position.
-        fling(-10000, onScrollListener);
-        assertTrue(onScrollListener.isOnScrollCalled());
-        assertEquals(0, onScrollListener.getFirstVisibleItem());
+        fling(-10000, mockScrollListener);
+        firstVisibleItemCaptor = ArgumentCaptor.forClass(Integer.class);
+        verify(mockScrollListener, atLeastOnce()).onScroll(eq(mListView),
+                firstVisibleItemCaptor.capture(), anyInt(), eq(mCountryList.length));
+        capturedFirstVisibleItems = firstVisibleItemCaptor.getAllValues();
+        assertTrue(capturedFirstVisibleItems.get(capturedFirstVisibleItems.size() - 1) == 0);
 
         // Fling up again, expect no scroll, as the viewport is already at top.
-        fling(-10000, onScrollListener);
-        assertFalse(onScrollListener.isOnScrollCalled());
-        assertEquals(0, onScrollListener.getFirstVisibleItem());
+        fling(-10000, mockScrollListener);
+        verify(mockScrollListener, never()).onScroll(any(AbsListView.class), anyInt(), anyInt(),
+                anyInt());
 
         // Fling up again with a huge velocity, expect no scroll.
-        fling(-50000, onScrollListener);
-        assertFalse(onScrollListener.isOnScrollCalled());
-        assertEquals(0, onScrollListener.getFirstVisibleItem());
+        fling(-50000, mockScrollListener);
+        verify(mockScrollListener, never()).onScroll(any(AbsListView.class), anyInt(), anyInt(),
+                anyInt());
     }
 
-    private void fling(int velocityY, MockOnScrollListener onScrollListener) throws Throwable {
-        onScrollListener.reset();
+    private void fling(int velocityY, OnScrollListener mockScrollListener) throws Throwable {
+        reset(mockScrollListener);
 
-        final int v = velocityY;
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                mListView.fling(v);
-            }
-        });
+        // Create a count down latch and configure it to be counted down when out mock
+        // listener is invoked with IDLE state
+        final CountDownLatch countDownLatch = new CountDownLatch(1);
+        doAnswer(new Answer<Void>() {
+                     @Override
+                     public Void answer(InvocationOnMock invocation) {
+                         countDownLatch.countDown();
+                         return null;
+                     }
+                 }
+        ).when(mockScrollListener).onScrollStateChanged(
+                mListView, OnScrollListener.SCROLL_STATE_IDLE);
 
-        do {
-            mInstrumentation.waitForIdleSync();
-        } while (onScrollListener.getScrollState() != OnScrollListener.SCROLL_STATE_IDLE);
+        // Now fling the list view
+        runTestOnUiThread(() -> mListView.fling(velocityY));
+
+        // And wait for the latch to be triggered
+        try {
+            assertTrue(countDownLatch.await(20L, TimeUnit.SECONDS));
+        } catch (InterruptedException e) {
+        }
     }
 
     public void testGetFocusedRect() throws Throwable {
@@ -358,12 +380,7 @@
         final Rect r = drawable.getBounds();
 
         final TextView v = (TextView) mListView.getSelectedView();
-        new PollingCheck() {
-            @Override
-            protected boolean check() {
-                return v.getRight() == r.right;
-            }
-        }.run();
+        PollingCheck.waitFor(() -> v.getRight() == r.right);
         assertEquals(v.getLeft(), r.left);
         assertEquals(v.getTop(), r.top);
         assertEquals(v.getBottom(), r.bottom);
@@ -428,17 +445,23 @@
     public void testSetRecyclerListener() throws Throwable {
         setAdapter();
 
-        MockRecyclerListener recyclerListener = new MockRecyclerListener();
-        List<View> views = new ArrayList<View>();
+        AbsListView.RecyclerListener mockRecyclerListener =
+                mock(AbsListView.RecyclerListener.class);
+        verifyZeroInteractions(mockRecyclerListener);
 
-        assertNull(recyclerListener.getView());
-        mListView.setRecyclerListener(recyclerListener);
+        mListView.setRecyclerListener(mockRecyclerListener);
+        List<View> views = new ArrayList<>();
         mListView.reclaimViews(views);
 
         assertTrue(views.size() > 0);
-        assertNotNull(recyclerListener.getView());
 
-        assertSame(recyclerListener.getView(), views.get(views.size() - 1));
+        // Verify that onMovedToScrapHeap was called on each view in the order that they were
+        // put in the list that we passed to reclaimViews
+        final InOrder reclaimedOrder = inOrder(mockRecyclerListener);
+        for (View reclaimed : views) {
+            reclaimedOrder.verify(mockRecyclerListener, times(1)).onMovedToScrapHeap(reclaimed);
+        }
+        verifyNoMoreInteractions(mockRecyclerListener);
     }
 
     public void testAccessCacheColorHint() {
@@ -577,27 +600,37 @@
         final TextView v = (TextView) listView.getSelectedView();
         assertNull(listView.getContextMenuInfo());
 
-        final MockOnItemLongClickListener listener = new MockOnItemLongClickListener();
-        listView.setOnItemLongClickListener(listener);
+        final AbsListView.OnItemLongClickListener mockOnItemLongClickListener =
+                mock(AbsListView.OnItemLongClickListener.class);
+        listView.setOnItemLongClickListener(mockOnItemLongClickListener);
 
-        assertNull(listener.getParent());
-        assertNull(listener.getView());
-        assertEquals(0, listener.getPosition());
-        assertEquals(0, listener.getID());
+        verifyZeroInteractions(mockOnItemLongClickListener);
+
+        // Create a count down latch and configure it to be counted down when out mock
+        // listener is invoked with the expected view
+        final CountDownLatch countDownLatch = new CountDownLatch(1);
+        doAnswer(new Answer<Void>() {
+             @Override
+             public Void answer(InvocationOnMock invocation) {
+                 countDownLatch.countDown();
+                 return null;
+             }
+         }).when(mockOnItemLongClickListener).onItemLongClick(listView, v, 2,
+                listView.getItemIdAtPosition(2));
 
         mInstrumentation.waitForIdleSync();
+
+        // Now long click our view
         TouchUtils.longClickView(this, v);
 
-        new PollingCheck() {
-            @Override
-            protected boolean check() {
-                return v == listener.getView();
-            }
-        }.run();
+        // And wait for the latch to be triggered
+        try {
+            assertTrue(countDownLatch.await(20L, TimeUnit.SECONDS));
+        } catch (InterruptedException e) {
+        }
 
-        assertSame(listView, listener.getParent());
-        assertEquals(2, listener.getPosition());
-        assertEquals(listView.getItemIdAtPosition(2), listener.getID());
+        verify(mockOnItemLongClickListener, times(1)).onItemLongClick(listView, v, 2,
+                listView.getItemIdAtPosition(2));
 
         ContextMenuInfo cmi = listView.getContextMenuInfo();
         assertNotNull(cmi);
@@ -748,131 +781,6 @@
          */
     }
 
-    public void testFoo() {
-        /**
-         * Do not test these APIs. They are callbacks which:
-         *
-         * 1. The callback machanism has been tested in super class
-         * 2. The functionality is implmentation details, no need to test
-         */
-    }
-
-    private static class MockOnScrollListener implements OnScrollListener {
-        private AbsListView mView;
-        private int mFirstVisibleItem;
-        private int mVisibleItemCount;
-        private int mTotalItemCount;
-        private int mScrollState;
-
-        private boolean mIsOnScrollCalled;
-        private boolean mIsOnScrollStateChangedCalled;
-
-        private MockOnScrollListener() {
-            mView = null;
-            mFirstVisibleItem = 0;
-            mVisibleItemCount = 0;
-            mTotalItemCount = 0;
-            mScrollState = -1;
-
-            mIsOnScrollCalled = false;
-            mIsOnScrollStateChangedCalled = false;
-        }
-
-        public void onScroll(AbsListView view, int firstVisibleItem,
-                int visibleItemCount, int totalItemCount) {
-            mView = view;
-            mFirstVisibleItem = firstVisibleItem;
-            mVisibleItemCount = visibleItemCount;
-            mTotalItemCount = totalItemCount;
-            mIsOnScrollCalled = true;
-        }
-
-        public void onScrollStateChanged(AbsListView view, int scrollState) {
-            mScrollState = scrollState;
-            mIsOnScrollStateChangedCalled = true;
-        }
-
-        public AbsListView getView() {
-            return mView;
-        }
-
-        public int getFirstVisibleItem() {
-            return mFirstVisibleItem;
-        }
-
-        public int getVisibleItemCount() {
-            return mVisibleItemCount;
-        }
-
-        public int getTotalItemCount() {
-            return mTotalItemCount;
-        }
-
-        public int getScrollState() {
-            return mScrollState;
-        }
-
-        public boolean isOnScrollCalled() {
-            return mIsOnScrollCalled;
-        }
-
-        public boolean isOnScrollStateChangedCalled() {
-            return mIsOnScrollStateChangedCalled;
-        }
-
-        public void reset() {
-            mIsOnScrollCalled = false;
-            mIsOnScrollStateChangedCalled = false;
-        }
-    }
-
-    private static class MockRecyclerListener implements RecyclerListener {
-        private View mView;
-
-        private MockRecyclerListener() {
-            mView = null;
-        }
-
-        public void onMovedToScrapHeap(View view) {
-            mView = view;
-        }
-
-        public View getView() {
-            return mView;
-        }
-    }
-
-    private static class MockOnItemLongClickListener implements OnItemLongClickListener {
-        private AdapterView<?> parent;
-        private View view;
-        private int position;
-        private long id;
-
-        public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
-            this.parent = parent;
-            this.view = view;
-            this.position = position;
-            this.id = id;
-            return false;
-        }
-
-        public AdapterView<?> getParent() {
-            return parent;
-        }
-
-        public View getView() {
-            return view;
-        }
-
-        public int getPosition() {
-            return position;
-        }
-
-        public long getID() {
-            return id;
-        }
-    }
-
     /**
      * MyListView for test
      */
diff --git a/tests/tests/widget/src/android/widget/cts/AbsSeekBarCtsActivity.java b/tests/tests/widget/src/android/widget/cts/AbsSeekBarCtsActivity.java
new file mode 100644
index 0000000..1bac1f5
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/AbsSeekBarCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.AbsSeekBar;
+
+/**
+ * A minimal application for {@link AbsSeekBar} test
+ */
+public class AbsSeekBarCtsActivity extends Activity {
+    /**
+     * Called when the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.seekbar_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/AbsSeekBarTest.java b/tests/tests/widget/src/android/widget/cts/AbsSeekBarTest.java
index 93032f6..e2108d9 100644
--- a/tests/tests/widget/src/android/widget/cts/AbsSeekBarTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AbsSeekBarTest.java
@@ -16,16 +16,14 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
 import android.app.Activity;
+import android.app.Instrumentation;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.cts.util.PollingCheck;
-import android.graphics.Canvas;
 import android.graphics.Color;
-import android.graphics.ColorFilter;
 import android.graphics.PorterDuff;
+import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
@@ -33,21 +31,31 @@
 import android.view.KeyEvent;
 import android.widget.AbsSeekBar;
 import android.widget.SeekBar;
+import android.widget.cts.util.TestUtils;
+import android.widget.cts.util.ViewTestUtils;
+
+import org.mockito.ArgumentCaptor;
+
+import java.util.List;
+
+import static org.mockito.Mockito.*;
 
 /**
  * Test {@link AbsSeekBar}.
  */
-public class AbsSeekBarTest extends ActivityInstrumentationTestCase2<ProgressBarCtsActivity> {
+public class AbsSeekBarTest extends ActivityInstrumentationTestCase2<AbsSeekBarCtsActivity> {
     public AbsSeekBarTest() {
-        super("android.widget.cts", ProgressBarCtsActivity.class);
+        super("android.widget.cts", AbsSeekBarCtsActivity.class);
     }
 
+    private Instrumentation mInstrumentation;
     private Activity mActivity;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
 
+        mInstrumentation = getInstrumentation();
         mActivity = getActivity();
     }
 
@@ -57,6 +65,8 @@
         new MyAbsSeekBar(mActivity, null);
 
         new MyAbsSeekBar(mActivity, null, android.R.attr.progressBarStyle);
+
+        new MyAbsSeekBar(mActivity, null, 0, android.R.style.Widget_Material_Light_ProgressBar);
     }
 
     public void testAccessThumbOffset() {
@@ -75,56 +85,74 @@
         assertEquals(negative, myAbsSeekBar.getThumbOffset());
     }
 
-    public void testSetThumb() {
-        MyAbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity);
+    public void testAccessThumb() {
+        // Both are pointing to the same object. This works around current limitation in CTS
+        // coverage report tool for properly reporting coverage of base class method calls.
+        final MyAbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity);
+        final AbsSeekBar absSeekBar = myAbsSeekBar;
+
         Drawable drawable1 = mActivity.getDrawable(R.drawable.scenery);
         Drawable drawable2 = mActivity.getDrawable(R.drawable.pass);
 
         assertFalse(myAbsSeekBar.verifyDrawable(drawable1));
         assertFalse(myAbsSeekBar.verifyDrawable(drawable2));
 
-        myAbsSeekBar.setThumb(drawable1);
-        assertSame(drawable1, myAbsSeekBar.getThumb());
+        absSeekBar.setThumb(drawable1);
+        assertSame(drawable1, absSeekBar.getThumb());
         assertTrue(myAbsSeekBar.verifyDrawable(drawable1));
         assertFalse(myAbsSeekBar.verifyDrawable(drawable2));
 
-        myAbsSeekBar.setThumb(drawable2);
-        assertSame(drawable2, myAbsSeekBar.getThumb());
+        absSeekBar.setThumb(drawable2);
+        assertSame(drawable2, absSeekBar.getThumb());
         assertFalse(myAbsSeekBar.verifyDrawable(drawable1));
         assertTrue(myAbsSeekBar.verifyDrawable(drawable2));
     }
 
-    public void testSetTickMark() {
-        MyAbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity);
+    public void testAccessTickMark() {
+        // Both are pointing to the same object. This works around current limitation in CTS
+        // coverage report tool for properly reporting coverage of base class method calls.
+        final MyAbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity);
+        final AbsSeekBar absSeekBar = myAbsSeekBar;
+
         Drawable drawable1 = mActivity.getDrawable(R.drawable.black);
         Drawable drawable2 = mActivity.getDrawable(R.drawable.black);
 
         assertFalse(myAbsSeekBar.verifyDrawable(drawable1));
         assertFalse(myAbsSeekBar.verifyDrawable(drawable2));
 
-        myAbsSeekBar.setTickMark(drawable1);
-        assertSame(drawable1, myAbsSeekBar.getTickMark());
+        absSeekBar.setTickMark(drawable1);
+        assertSame(drawable1, absSeekBar.getTickMark());
         assertTrue(myAbsSeekBar.verifyDrawable(drawable1));
         assertFalse(myAbsSeekBar.verifyDrawable(drawable2));
 
-        myAbsSeekBar.setTickMark(drawable2);
-        assertSame(drawable2, myAbsSeekBar.getTickMark());
+        absSeekBar.setTickMark(drawable2);
+        assertSame(drawable2, absSeekBar.getTickMark());
         assertFalse(myAbsSeekBar.verifyDrawable(drawable1));
         assertTrue(myAbsSeekBar.verifyDrawable(drawable2));
     }
 
     public void testDrawableStateChanged() {
         MyAbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity);
-        MockDrawable drawable = new MockDrawable();
-        myAbsSeekBar.setProgressDrawable(drawable);
+        Drawable mockProgressDrawable = spy(new ColorDrawable(Color.YELLOW));
+        myAbsSeekBar.setProgressDrawable(mockProgressDrawable);
 
+        ArgumentCaptor<Integer> alphaCaptor = ArgumentCaptor.forClass(Integer.class);
         myAbsSeekBar.setEnabled(false);
         myAbsSeekBar.drawableStateChanged();
-        assertEquals(0, drawable.getAlpha());
+        verify(mockProgressDrawable, atLeastOnce()).setAlpha(alphaCaptor.capture());
+        // Verify that the last call to setAlpha was with argument 0x00
+        List<Integer> alphaCaptures = alphaCaptor.getAllValues();
+        assertTrue(!alphaCaptures.isEmpty());
+        assertEquals(Integer.valueOf(0x00), alphaCaptures.get(alphaCaptures.size() - 1));
 
+        alphaCaptor = ArgumentCaptor.forClass(Integer.class);
         myAbsSeekBar.setEnabled(true);
         myAbsSeekBar.drawableStateChanged();
-        assertEquals(0xFF, drawable.getAlpha());
+        verify(mockProgressDrawable, atLeastOnce()).setAlpha(alphaCaptor.capture());
+        // Verify that the last call to setAlpha was with argument 0xFF
+        alphaCaptures = alphaCaptor.getAllValues();
+        assertTrue(!alphaCaptures.isEmpty());
+        assertEquals(Integer.valueOf(0xFF), alphaCaptures.get(alphaCaptures.size() - 1));
     }
 
     public void testVerifyDrawable() {
@@ -162,42 +190,31 @@
 
     public void testAccessKeyProgressIncrement() throws Throwable {
         // AbsSeekBar is an abstract class, use its subclass: SeekBar to do this test.
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                mActivity.setContentView(R.layout.seekbar_layout);
-            }
-        });
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> mActivity.setContentView(R.layout.seekbar_layout));
+        mInstrumentation.waitForIdleSync();
 
         final SeekBar seekBar = (SeekBar) mActivity.findViewById(R.id.seekBar);
         final int keyProgressIncrement = 2;
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                seekBar.setKeyProgressIncrement(keyProgressIncrement);
-                seekBar.setFocusable(true);
-                seekBar.requestFocus();
-            }
+        mInstrumentation.runOnMainSync(() -> {
+            seekBar.setKeyProgressIncrement(keyProgressIncrement);
+            seekBar.setFocusable(true);
+            seekBar.requestFocus();
         });
-        new PollingCheck(1000) {
-            @Override
-            protected boolean check() {
-                return seekBar.hasWindowFocus();
-            }
-        }.run();
+        PollingCheck.waitFor(1000, () -> seekBar.hasWindowFocus());
         assertEquals(keyProgressIncrement, seekBar.getKeyProgressIncrement());
 
         int oldProgress = seekBar.getProgress();
         KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT);
-        getInstrumentation().sendKeySync(keyEvent);
+        mInstrumentation.sendKeySync(keyEvent);
         assertEquals(oldProgress + keyProgressIncrement, seekBar.getProgress());
         oldProgress = seekBar.getProgress();
         keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_LEFT);
-        getInstrumentation().sendKeySync(keyEvent);
+        mInstrumentation.sendKeySync(keyEvent);
         assertEquals(oldProgress - keyProgressIncrement, seekBar.getProgress());
     }
 
-    public void testSetMax() {
-        MyAbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity, null, R.style.TestProgressBar);
+    public void testAccessMax() {
+        AbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity, null, R.style.TestProgressBar);
 
         int progress = 10;
         myAbsSeekBar.setProgress(progress);
@@ -226,58 +243,70 @@
 
     @UiThreadTest
     public void testThumbTint() {
-        mActivity.setContentView(R.layout.seekbar_layout);
-
-        SeekBar inflatedView = (SeekBar) mActivity.findViewById(R.id.thumb_tint);
+        AbsSeekBar inflatedView = (AbsSeekBar) mActivity.findViewById(R.id.thumb_tint);
 
         assertEquals("Thumb tint inflated correctly",
                 Color.WHITE, inflatedView.getThumbTintList().getDefaultColor());
         assertEquals("Thumb tint mode inflated correctly",
                 PorterDuff.Mode.SRC_OVER, inflatedView.getThumbTintMode());
 
-        MockDrawable thumb = new MockDrawable();
-        SeekBar view = new SeekBar(mActivity);
+        Drawable mockThumb = spy(new ColorDrawable(Color.BLUE));
 
-        view.setThumb(thumb);
-        assertFalse("No thumb tint applied by default", thumb.hasCalledSetTint());
+        inflatedView.setThumb(mockThumb);
+        verify(mockThumb, times(1)).setTintList(TestUtils.colorStateListOf(Color.WHITE));
 
-        view.setThumbTintList(ColorStateList.valueOf(Color.WHITE));
-        assertTrue("Thumb tint applied when setThumbTintList() called after setThumb()",
-                thumb.hasCalledSetTint());
+        reset(mockThumb);
+        inflatedView.setThumbTintList(ColorStateList.valueOf(Color.RED));
+        verify(mockThumb, times(1)).setTintList(TestUtils.colorStateListOf(Color.RED));
 
-        thumb.reset();
-        view.setThumb(null);
-        view.setThumb(thumb);
-        assertTrue("Thumb tint applied when setThumbTintList() called before setThumb()",
-                thumb.hasCalledSetTint());
+        inflatedView.setThumbTintMode(PorterDuff.Mode.DST_ATOP);
+        assertEquals("Thumb tint mode changed correctly",
+                PorterDuff.Mode.DST_ATOP, inflatedView.getThumbTintMode());
+
+        reset(mockThumb);
+        inflatedView.setThumb(null);
+        inflatedView.setThumb(mockThumb);
+        verify(mockThumb, times(1)).setTintList(TestUtils.colorStateListOf(Color.RED));
     }
 
     @UiThreadTest
     public void testTickMarkTint() {
-        mActivity.setContentView(R.layout.seekbar_layout);
-
-        SeekBar inflatedView = (SeekBar) mActivity.findViewById(R.id.tick_mark_tint);
+        AbsSeekBar inflatedView = (AbsSeekBar) mActivity.findViewById(R.id.tick_mark_tint);
 
         assertEquals("TickMark tint inflated correctly",
                 Color.WHITE, inflatedView.getTickMarkTintList().getDefaultColor());
         assertEquals("TickMark tint mode inflated correctly",
                 PorterDuff.Mode.SRC_OVER, inflatedView.getTickMarkTintMode());
 
-        MockDrawable tickMark = new MockDrawable();
-        SeekBar view = new SeekBar(mActivity);
+        Drawable mockTickMark = spy(new ColorDrawable(Color.BLUE));
 
-        view.setTickMark(tickMark);
-        assertFalse("No tickMark tint applied by default", tickMark.hasCalledSetTint());
+        inflatedView.setTickMark(mockTickMark);
+        verify(mockTickMark, times(1)).setTintList(TestUtils.colorStateListOf(Color.WHITE));
 
-        view.setTickMarkTintList(ColorStateList.valueOf(Color.WHITE));
-        assertTrue("TickMark tint applied when setTickMarkTintList() called after setTickMark()",
-                tickMark.hasCalledSetTint());
+        reset(mockTickMark);
+        inflatedView.setTickMarkTintList(ColorStateList.valueOf(Color.RED));
+        verify(mockTickMark, times(1)).setTintList(TestUtils.colorStateListOf(Color.RED));
 
-        tickMark.reset();
-        view.setTickMark(null);
-        view.setTickMark(tickMark);
-        assertTrue("TickMark tint applied when setTickMarkTintList() called before setTickMark()",
-                tickMark.hasCalledSetTint());
+        inflatedView.setTickMarkTintMode(PorterDuff.Mode.DARKEN);
+        assertEquals("TickMark tint mode changed correctly",
+                PorterDuff.Mode.DARKEN, inflatedView.getTickMarkTintMode());
+
+        reset(mockTickMark);
+        inflatedView.setTickMark(null);
+        inflatedView.setTickMark(mockTickMark);
+        verify(mockTickMark, times(1)).setTintList(TestUtils.colorStateListOf(Color.RED));
+    }
+
+    public void testAccessSplitTrack() {
+        AbsSeekBar inflatedView = (AbsSeekBar) mActivity.findViewById(R.id.tick_mark_tint);
+
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, inflatedView,
+                () -> inflatedView.setSplitTrack(true));
+        assertTrue(inflatedView.getSplitTrack());
+
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, inflatedView,
+                () -> inflatedView.setSplitTrack(false));
+        assertFalse(inflatedView.getSplitTrack());
     }
 
     private static class MyAbsSeekBar extends AbsSeekBar {
@@ -293,6 +322,10 @@
             super(context, attrs, defStyle);
         }
 
+        public MyAbsSeekBar(Context context, AttributeSet attrs, int defStyle, int defStyleRes) {
+            super(context, attrs, defStyle, defStyleRes);
+        }
+
         @Override
         protected void drawableStateChanged() {
             super.drawableStateChanged();
@@ -303,45 +336,4 @@
             return super.verifyDrawable(who);
         }
     }
-
-    private static class MockDrawable extends Drawable {
-        private int mAlpha;
-        private boolean mCalledDraw = false;
-        private boolean mCalledSetTint = false;
-
-        @Override
-        public void draw(Canvas canvas) { }
-
-        public void reset() {
-            mCalledDraw = false;
-            mCalledSetTint = false;
-        }
-
-        @Override
-        public int getOpacity() {
-            return 0;
-        }
-
-        @Override
-        public void setAlpha(int alpha) {
-            mAlpha = alpha;
-        }
-
-        public int getAlpha() {
-            return mAlpha;
-        }
-
-        @Override
-        public void setColorFilter(ColorFilter cf) { }
-
-        @Override
-        public void setTintList(ColorStateList tint) {
-            super.setTintList(tint);
-            mCalledSetTint = true;
-        }
-
-        public boolean hasCalledSetTint() {
-            return mCalledSetTint;
-        }
-    }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/ActionMenuViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ActionMenuViewCtsActivity.java
new file mode 100644
index 0000000..1b58b63
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ActionMenuViewCtsActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.ActionMenuView;
+
+/**
+ * A minimal application for {@link ActionMenuView} test.
+ */
+public class ActionMenuViewCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.actionmenuview_layout);
+    }
+}
+
diff --git a/tests/tests/widget/src/android/widget/cts/ActionMenuViewTest.java b/tests/tests/widget/src/android/widget/cts/ActionMenuViewTest.java
new file mode 100644
index 0000000..6de7c39
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ActionMenuViewTest.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.cts;
+
+import android.app.Instrumentation;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.ActionMenuView;
+import android.widget.Toolbar;
+import android.widget.cts.util.TestUtils;
+import android.widget.cts.util.ViewTestUtils;
+
+import static org.mockito.Mockito.*;
+
+@MediumTest
+public class ActionMenuViewTest
+        extends ActivityInstrumentationTestCase2<ActionMenuViewCtsActivity> {
+    private Instrumentation mInstrumentation;
+    private ActionMenuViewCtsActivity mActivity;
+    private ActionMenuView mActionMenuView;
+
+    public ActionMenuViewTest() {
+        super("android.widget.cts", ActionMenuViewCtsActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mInstrumentation = getInstrumentation();
+        mActivity = getActivity();
+        mActionMenuView = (ActionMenuView) mActivity.findViewById(R.id.action_menu_view);
+    }
+
+    public void testConstructor() {
+        new ActionMenuView(mActivity);
+
+        new ActionMenuView(mActivity, null);
+    }
+
+    public void testMenuContent() {
+        final Menu menu = mActionMenuView.getMenu();
+        assertNotNull(menu);
+
+        mInstrumentation.runOnMainSync(
+                () -> mActivity.getMenuInflater().inflate(
+                        R.menu.toolbar_menu, menu));
+
+        assertEquals(6, menu.size());
+        assertEquals(R.id.action_highlight, menu.getItem(0).getItemId());
+        assertEquals(R.id.action_edit, menu.getItem(1).getItemId());
+        assertEquals(R.id.action_delete, menu.getItem(2).getItemId());
+        assertEquals(R.id.action_ignore, menu.getItem(3).getItemId());
+        assertEquals(R.id.action_share, menu.getItem(4).getItemId());
+        assertEquals(R.id.action_print, menu.getItem(5).getItemId());
+
+        ActionMenuView.OnMenuItemClickListener menuItemClickListener =
+                mock(ActionMenuView.OnMenuItemClickListener.class);
+        mActionMenuView.setOnMenuItemClickListener(menuItemClickListener);
+
+        menu.performIdentifierAction(R.id.action_highlight, 0);
+        verify(menuItemClickListener, times(1)).onMenuItemClick(
+                menu.findItem(R.id.action_highlight));
+
+        menu.performIdentifierAction(R.id.action_share, 0);
+        verify(menuItemClickListener, times(1)).onMenuItemClick(
+                menu.findItem(R.id.action_share));
+    }
+
+    public void testMenuOverflowShowHide() {
+        // Inflate menu and check that we're not showing overflow menu yet
+        mInstrumentation.runOnMainSync(
+                () -> mActivity.getMenuInflater().inflate(
+                        R.menu.toolbar_menu, mActionMenuView.getMenu()));
+        assertFalse(mActionMenuView.isOverflowMenuShowing());
+
+        // Ask to show overflow menu and check that it's showing
+        mInstrumentation.runOnMainSync(() -> mActionMenuView.showOverflowMenu());
+        mInstrumentation.waitForIdleSync();
+        assertTrue(mActionMenuView.isOverflowMenuShowing());
+
+        // Ask to hide the overflow menu and check that it's not showing
+        mInstrumentation.runOnMainSync(() -> mActionMenuView.hideOverflowMenu());
+        mInstrumentation.waitForIdleSync();
+        assertFalse(mActionMenuView.isOverflowMenuShowing());
+    }
+
+    public void testMenuOverflowSubmenu() {
+        // Inflate menu and check that we're not showing overflow menu yet
+        mInstrumentation.runOnMainSync(
+                () -> mActivity.getMenuInflater().inflate(
+                        R.menu.toolbar_menu, mActionMenuView.getMenu()));
+        assertFalse(mActionMenuView.isOverflowMenuShowing());
+
+        // Ask to show overflow menu and check that it's showing
+        mInstrumentation.runOnMainSync(() -> mActionMenuView.showOverflowMenu());
+        mInstrumentation.waitForIdleSync();
+        assertTrue(mActionMenuView.isOverflowMenuShowing());
+
+        // Register a mock menu item click listener on the toolbar
+        ActionMenuView.OnMenuItemClickListener menuItemClickListener =
+                mock(ActionMenuView.OnMenuItemClickListener.class);
+        mActionMenuView.setOnMenuItemClickListener(menuItemClickListener);
+
+        final Menu menu = mActionMenuView.getMenu();
+
+        // Ask to "perform" the share action and check that the menu click listener has
+        // been notified
+        mInstrumentation.runOnMainSync(() -> menu.performIdentifierAction(R.id.action_share, 0));
+        verify(menuItemClickListener, times(1)).onMenuItemClick(
+                menu.findItem(R.id.action_share));
+
+        // Ask to dismiss all the popups and check that we're not showing the overflow menu
+        mInstrumentation.runOnMainSync(() -> mActionMenuView.dismissPopupMenus());
+        mInstrumentation.waitForIdleSync();
+        assertFalse(mActionMenuView.isOverflowMenuShowing());
+    }
+
+    public void testMenuOverflowIcon() {
+        // Inflate menu and check that we're not showing overflow menu yet
+        mInstrumentation.runOnMainSync(
+                () -> mActivity.getMenuInflater().inflate(
+                        R.menu.toolbar_menu, mActionMenuView.getMenu()));
+
+        final Drawable overflowIcon = mActivity.getDrawable(R.drawable.icon_red);
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mActionMenuView,
+                () -> mActionMenuView.setOverflowIcon(overflowIcon));
+
+        final Drawable toolbarOverflowIcon = mActionMenuView.getOverflowIcon();
+        TestUtils.assertAllPixelsOfColor("Overflow icon is red", toolbarOverflowIcon,
+                toolbarOverflowIcon.getIntrinsicWidth(), toolbarOverflowIcon.getIntrinsicHeight(),
+                true, Color.RED, 1, false);
+    }
+
+    public void testPopupTheme() {
+        mInstrumentation.runOnMainSync(() -> {
+                mActivity.getMenuInflater().inflate(R.menu.toolbar_menu, mActionMenuView.getMenu());
+                mActionMenuView.setPopupTheme(R.style.ToolbarPopupTheme_Test);
+        });
+        assertEquals(R.style.ToolbarPopupTheme_Test, mActionMenuView.getPopupTheme());
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java b/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java
index 1b9137f..72ecf7e 100644
--- a/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java
@@ -16,12 +16,12 @@
 
 package android.widget.cts;
 
-import org.xmlpull.v1.XmlPullParser;
-
-import android.app.Activity;
+import android.app.Instrumentation;
 import android.content.Context;
 import android.os.Parcelable;
+import android.provider.Settings;
 import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.util.AttributeSet;
 import android.util.SparseArray;
 import android.util.Xml;
@@ -31,17 +31,17 @@
 import android.view.animation.LayoutAnimationController;
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
+import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.ListAdapter;
 import android.widget.ListView;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.AdapterView.OnItemLongClickListener;
-import android.widget.AdapterView.OnItemSelectedListener;
-import android.provider.Settings;
+import android.widget.cts.util.ViewTestUtils;
 
-import android.widget.cts.R;
+import org.xmlpull.v1.XmlPullParser;
 
+import static org.mockito.Mockito.*;
 
+@SmallTest
 public class AdapterViewTest extends ActivityInstrumentationTestCase2<AdapterViewCtsActivity> {
 
     private final static int INVALID_ID = -1;
@@ -51,7 +51,7 @@
 
     final String[] FRUIT = { "1", "2", "3", "4", "5", "6", "7", "8" };
 
-    private Activity mActivity;
+    private AdapterViewCtsActivity mActivity;
     private AdapterView<ListAdapter> mAdapterView;
 
     public AdapterViewTest() {
@@ -250,47 +250,67 @@
     }
 
     public void testAccessOnItemClickAndLongClickListener() {
-        MockOnItemClickListener clickListener = new MockOnItemClickListener();
-        MockOnItemLongClickListener longClickListener = new MockOnItemLongClickListener();
+        AdapterView.OnItemClickListener mockClickListener =
+                mock(AdapterView.OnItemClickListener.class);
+        AdapterView.OnItemLongClickListener mockLongClickListener =
+                mock(AdapterView.OnItemLongClickListener.class);
+        when(mockLongClickListener.onItemLongClick(
+                any(AdapterView.class), any(View.class), anyInt(), anyLong())).thenReturn(true);
+
+        assertNull(mAdapterView.getOnItemLongClickListener());
+        assertNull(mAdapterView.getOnItemClickListener());
 
         assertFalse(mAdapterView.performItemClick(null, 0, 0));
 
-        mAdapterView.setOnItemClickListener(clickListener);
-        mAdapterView.setOnItemLongClickListener(longClickListener);
+        mAdapterView.setOnItemClickListener(mockClickListener);
+        mAdapterView.setOnItemLongClickListener(mockLongClickListener);
+        assertEquals(mockLongClickListener, mAdapterView.getOnItemLongClickListener());
 
-        assertFalse(clickListener.isClicked());
+        verifyZeroInteractions(mockClickListener);
         assertTrue(mAdapterView.performItemClick(null, 0, 0));
-        assertTrue(clickListener.isClicked());
+        verify(mockClickListener, times(1)).onItemClick(eq(mAdapterView), any(View.class),
+                eq(0), eq(0L));
 
         setArrayAdapter(mAdapterView);
-        assertFalse(longClickListener.isClicked());
+        verifyZeroInteractions(mockLongClickListener);
         mAdapterView.layout(0, 0, LAYOUT_WIDTH, LAYOUT_HEIGHT);
         assertTrue(mAdapterView.showContextMenuForChild(mAdapterView.getChildAt(0)));
-        assertTrue(longClickListener.isClicked());
+        verify(mockLongClickListener, times(1)).onItemLongClick(eq(mAdapterView), any(View.class),
+                eq(0), eq(0L));
     }
 
     public void testAccessOnItemSelectedListener() {
-        // FIXME: we can not select the item in touch mode, how can we change the mode to test
-        setArrayAdapter(mAdapterView);
-        MockOnItemSelectedListener selectedListener = new MockOnItemSelectedListener();
-        mAdapterView.setOnItemSelectedListener(selectedListener);
+        mAdapterView = mActivity.getListView();
+        final Instrumentation instrumentation = getInstrumentation();
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mAdapterView,
+                () -> mAdapterView.setLayoutParams(new FrameLayout.LayoutParams(
+                        ViewGroup.LayoutParams.MATCH_PARENT,
+                        ViewGroup.LayoutParams.MATCH_PARENT)));
 
-//        mAdapterView.layout(0, 0, LAYOUT_WIDTH, LAYOUT_HEIGHT);
-//
-//        assertFalse(selectedListener.isItemSelected());
-//        assertFalse(selectedListener.isNothingSelected());
-//
-//        mAdapterView.setSelection(1);
-//        assertTrue(selectedListener.isItemSelected());
-//        assertFalse(selectedListener.isNothingSelected());
-//
-//        mAdapterView.setSelection(-1);
-//        assertTrue(selectedListener.isItemSelected());
-//        assertTrue(selectedListener.isNothingSelected());
-//
-//        mAdapterView.setSelection(FRUIT.length);
-//        assertTrue(selectedListener.isItemSelected());
-//        assertTrue(selectedListener.isNothingSelected());
+        instrumentation.runOnMainSync(() -> setArrayAdapter(mAdapterView));
+
+        AdapterView.OnItemSelectedListener mockSelectedListener =
+                mock(AdapterView.OnItemSelectedListener.class);
+        mAdapterView.setOnItemSelectedListener(mockSelectedListener);
+        assertEquals(mockSelectedListener, mAdapterView.getOnItemSelectedListener());
+
+        verifyZeroInteractions(mockSelectedListener);
+
+        // Select item #1 and verify that the listener has been notified
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mAdapterView,
+                () -> mAdapterView.setSelection(1));
+        verify(mockSelectedListener, times(1)).onItemSelected(eq(mAdapterView), any(View.class),
+                eq(1), eq(1L));
+        verifyNoMoreInteractions(mockSelectedListener);
+
+        // Select last item and verify that the listener has been notified
+        reset(mockSelectedListener);
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mAdapterView,
+                () -> mAdapterView.setSelection(FRUIT.length - 1));
+        verify(mockSelectedListener, times(1)).onItemSelected(
+                eq(mAdapterView), any(View.class), eq(FRUIT.length - 1),
+                eq((long) FRUIT.length - 1));
+        verifyNoMoreInteractions(mockSelectedListener);
     }
 
     /*
@@ -459,62 +479,7 @@
     }
 
     private void setArrayAdapter(AdapterView<ListAdapter> adapterView) {
-        ((ListView) adapterView).setAdapter(new ArrayAdapter<String>(
+        adapterView.setAdapter(new ArrayAdapter<>(
                 mActivity, R.layout.adapterview_layout, FRUIT));
     }
-
-    /**
-     * this is a mock item click listener for check out call back
-     */
-    private class MockOnItemClickListener implements OnItemClickListener {
-        private boolean mClicked;
-
-        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-            mClicked = true;
-        }
-
-        protected boolean isClicked() {
-            return mClicked;
-        }
-    }
-
-    /**
-     * this is a mock long item click listener for check out call back
-     */
-    private class MockOnItemLongClickListener implements OnItemLongClickListener {
-        private boolean mClicked;
-
-        public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
-            mClicked = true;
-            return true;
-        }
-
-        protected boolean isClicked() {
-            return mClicked;
-        }
-    }
-
-    /**
-     * this is a mock item selected listener for check out call lback
-     */
-    private class MockOnItemSelectedListener implements OnItemSelectedListener {
-        private boolean mIsItemSelected;
-        private boolean mIsNothingSelected;
-
-        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
-            mIsItemSelected = true;
-        }
-
-        public void onNothingSelected(AdapterView<?> parent) {
-            mIsNothingSelected = true;
-        }
-
-        protected boolean isItemSelected() {
-            return mIsItemSelected;
-        }
-
-        protected boolean isNothingSelected() {
-            return mIsNothingSelected;
-        }
-    }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/ArrayAdapterTest.java b/tests/tests/widget/src/android/widget/cts/ArrayAdapterTest.java
index 03677f2..2cb8ee4 100644
--- a/tests/tests/widget/src/android/widget/cts/ArrayAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ArrayAdapterTest.java
@@ -25,16 +25,17 @@
 import android.database.DataSetObserver;
 import android.test.InstrumentationTestCase;
 import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.widget.ArrayAdapter;
 import android.widget.Filter;
 import android.widget.TextView;
 
-import android.widget.cts.R;
+import static org.mockito.Mockito.*;
 
-
+@SmallTest
 public class ArrayAdapterTest extends InstrumentationTestCase {
 
-    private static final int INVALD_ID = -1;
+    private static final int INVALID_ID = -1;
     private static final String STR1 = "string1";
     private static final String STR2 = "string2";
     private static final String STR3 = "string3";
@@ -46,30 +47,30 @@
     protected void setUp() throws Exception {
         super.setUp();
         mContext = getInstrumentation().getTargetContext();
-        mArrayAdapter = new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line);
+        mArrayAdapter = new ArrayAdapter<>(mContext, R.layout.simple_dropdown_item_1line);
     }
 
     public void testConstructor() {
 
         new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line);
-        new ArrayAdapter<String>(mContext, INVALD_ID);// invalid resource id
+        new ArrayAdapter<String>(mContext, INVALID_ID); // invalid resource id
 
         new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line, R.id.text1);
-        new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line, INVALD_ID);
+        new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line, INVALID_ID);
 
-        new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line,
+        new ArrayAdapter<>(mContext, R.layout.simple_dropdown_item_1line,
                 new String[] {"str1", "str2"});
 
-        new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line, R.id.text1,
+        new ArrayAdapter<>(mContext, R.layout.simple_dropdown_item_1line, R.id.text1,
                 new String[] {"str1", "str2"});
 
-        List<String> list = new ArrayList<String>();
+        List<String> list = new ArrayList<>();
         list.add(STR1);
         list.add(STR2);
 
-        new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line, list);
+        new ArrayAdapter<>(mContext, R.layout.simple_dropdown_item_1line, list);
 
-        new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line, R.id.text1, list);
+        new ArrayAdapter<>(mContext, R.layout.simple_dropdown_item_1line, R.id.text1, list);
 
         // invalid input
         try {
@@ -81,46 +82,46 @@
     }
 
     public void testDataChangeEvent() {
-        final MockDataSetObserver mockDataSetObserver = new MockDataSetObserver();
+        final DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
         mArrayAdapter.registerDataSetObserver(mockDataSetObserver);
 
         // enable automatically notifying.
         mArrayAdapter.setNotifyOnChange(true);
-        assertEquals(0, mockDataSetObserver.getCalledOnChangedCount());
+        verifyZeroInteractions(mockDataSetObserver);
         mArrayAdapter.add(STR1);
         assertEquals(1, mArrayAdapter.getCount());
-        assertEquals(1, mockDataSetObserver.getCalledOnChangedCount());
+        verify(mockDataSetObserver, times(1)).onChanged();
         mArrayAdapter.add(STR2);
         assertEquals(2, mArrayAdapter.getCount());
-        assertEquals(2, mockDataSetObserver.getCalledOnChangedCount());
+        verify(mockDataSetObserver, times(2)).onChanged();
 
         // reset data
         mArrayAdapter.clear();
         // clear notify changed
-        assertEquals(3, mockDataSetObserver.getCalledOnChangedCount());
+        verify(mockDataSetObserver, times(3)).onChanged();
         assertEquals(0, mArrayAdapter.getCount());
         // if empty before, clear also notify changed
         mArrayAdapter.clear();
-        assertEquals(4, mockDataSetObserver.getCalledOnChangedCount());
-        mockDataSetObserver.clearCount();
-        assertEquals(0, mockDataSetObserver.getCalledOnChangedCount());
+        verify(mockDataSetObserver, times(4)).onChanged();
+
+        reset(mockDataSetObserver);
 
         // disable auto notify
         mArrayAdapter.setNotifyOnChange(false);
 
         mArrayAdapter.add(STR3);
         assertEquals(1, mArrayAdapter.getCount());
-        assertEquals(0, mockDataSetObserver.getCalledOnChangedCount());
+        verifyZeroInteractions(mockDataSetObserver);
 
         // manually notify
         mArrayAdapter.notifyDataSetChanged();
-        assertEquals(1, mockDataSetObserver.getCalledOnChangedCount());
+        verify(mockDataSetObserver, times(1)).onChanged();
         // no data changed, but force notify
         mArrayAdapter.notifyDataSetChanged();
-        assertEquals(2, mockDataSetObserver.getCalledOnChangedCount());
+        verify(mockDataSetObserver, times(2)).onChanged();
         // once called notify, auto notify enabled
         mArrayAdapter.add(STR3);
-        assertEquals(3, mockDataSetObserver.getCalledOnChangedCount());
+        verify(mockDataSetObserver, times(3)).onChanged();
     }
 
     public void testAccessView() {
@@ -202,7 +203,7 @@
             // expected exception
         }
 
-        mArrayAdapter.setDropDownViewResource(INVALD_ID);
+        mArrayAdapter.setDropDownViewResource(INVALID_ID);
     }
 
     public void testAccessDropDownViewTheme() {
@@ -217,13 +218,13 @@
      */
     public void testInsert() {
         mArrayAdapter.setNotifyOnChange(true);
-        final MockDataSetObserver mockDataSetObserver = new MockDataSetObserver();
+        final DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
         mArrayAdapter.registerDataSetObserver(mockDataSetObserver);
 
         mArrayAdapter.insert(STR1, 0);
         assertEquals(1, mArrayAdapter.getCount());
         assertEquals(0, mArrayAdapter.getPosition(STR1));
-        assertEquals(1, mockDataSetObserver.getCalledOnChangedCount());
+        verify(mockDataSetObserver, times(1)).onChanged();
 
         mArrayAdapter.insert(STR2, 0);
         assertEquals(2, mArrayAdapter.getCount());
@@ -294,8 +295,7 @@
 
         // test invalid input
         assertEquals(-1, mArrayAdapter.getItemId(-1));
-        assertEquals(mArrayAdapter.getCount(),
-                mArrayAdapter.getItemId(mArrayAdapter.getCount()));
+        assertEquals(mArrayAdapter.getCount(), mArrayAdapter.getItemId(mArrayAdapter.getCount()));
     }
 
     /*
@@ -322,23 +322,22 @@
      * remove first one if duplicated string in the array
      */
     public void testRemove() {
-        final MockDataSetObserver mockDataSetObserver = new MockDataSetObserver();
+        final DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
         mArrayAdapter.registerDataSetObserver(mockDataSetObserver);
         mArrayAdapter.setNotifyOnChange(true);
 
         // remove the not exist one
         assertEquals(0, mArrayAdapter.getCount());
-        assertEquals(0, mockDataSetObserver.getCalledOnChangedCount());
+        verifyZeroInteractions(mockDataSetObserver);
         // remove the item not exist also notify change
         mArrayAdapter.remove(STR1);
-        assertEquals(1, mockDataSetObserver.getCalledOnChangedCount());
+        verify(mockDataSetObserver, times(1)).onChanged();
 
         mArrayAdapter.add(STR1);
         mArrayAdapter.add(STR2);
         mArrayAdapter.add(STR3);
         mArrayAdapter.add(STR2);
-        mockDataSetObserver.clearCount();
-        assertEquals(0, mockDataSetObserver.getCalledOnChangedCount());
+        reset(mockDataSetObserver);
         assertEquals(4, mArrayAdapter.getCount());
 
         mArrayAdapter.remove(STR1);
@@ -346,11 +345,11 @@
         assertEquals(-1, mArrayAdapter.getPosition(STR1));
         assertEquals(0, mArrayAdapter.getPosition(STR2));
         assertEquals(1, mArrayAdapter.getPosition(STR3));
-        assertEquals(1, mockDataSetObserver.getCalledOnChangedCount());
+        verify(mockDataSetObserver, times(1)).onChanged();
 
         mArrayAdapter.remove(STR2);
         assertEquals(2, mArrayAdapter.getCount());
-        // remove the first one if dumplicated
+        // remove the first one if duplicated
         assertEquals(1, mArrayAdapter.getPosition(STR2));
         assertEquals(0, mArrayAdapter.getPosition(STR3));
 
@@ -376,30 +375,26 @@
         }
 
         try {
-            ArrayAdapter.createFromResource(mContext, INVALD_ID, R.layout.simple_spinner_item);
+            ArrayAdapter.createFromResource(mContext, INVALID_ID, R.layout.simple_spinner_item);
             fail("should throw NullPointerException");
         } catch (NullPointerException e) {
             // expected exception
         }
 
-       ArrayAdapter.createFromResource(mContext, R.array.string, INVALD_ID);
+       ArrayAdapter.createFromResource(mContext, R.array.string, INVALID_ID);
     }
 
     public void testSort() {
-        final MockDataSetObserver mockDataSetObserver = new MockDataSetObserver();
+        final DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
         mArrayAdapter.registerDataSetObserver(mockDataSetObserver);
         mArrayAdapter.setNotifyOnChange(true);
-        assertEquals(0, mockDataSetObserver.getCalledOnChangedCount());
+        verifyZeroInteractions(mockDataSetObserver);
 
-        mArrayAdapter.sort( new Comparator<String>() {
-            public int compare(String o1, String o2) {
-                return 0;
-            }
-        });
-        assertEquals(1, mockDataSetObserver.getCalledOnChangedCount());
+        mArrayAdapter.sort((String o1, String o2) -> 0);
+        verify(mockDataSetObserver, times(1)).onChanged();
 
         mArrayAdapter.sort(null);
-        assertEquals(2, mockDataSetObserver.getCalledOnChangedCount());
+        verify(mockDataSetObserver, times(2)).onChanged();
     }
 
     /**
@@ -408,7 +403,7 @@
      */
     public void testAdd() {
         mArrayAdapter.setNotifyOnChange(true);
-        final MockDataSetObserver mockDataSetObserver = new MockDataSetObserver();
+        final DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
         mArrayAdapter.registerDataSetObserver(mockDataSetObserver);
 
         mArrayAdapter.clear();
@@ -427,10 +422,10 @@
      */
     public void testAddAllCollection() {
         mArrayAdapter.setNotifyOnChange(true);
-        final MockDataSetObserver mockDataSetObserver = new MockDataSetObserver();
+        final DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
         mArrayAdapter.registerDataSetObserver(mockDataSetObserver);
 
-        List<String> list = new ArrayList<String>();
+        List<String> list = new ArrayList<>();
         list.add("");
         list.add("hello");
         list.add("android");
@@ -454,7 +449,7 @@
      */
     public void testAddAllParams() {
         mArrayAdapter.setNotifyOnChange(true);
-        final MockDataSetObserver mockDataSetObserver = new MockDataSetObserver();
+        final DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
         mArrayAdapter.registerDataSetObserver(mockDataSetObserver);
 
         mArrayAdapter.clear();
@@ -468,35 +463,4 @@
         assertEquals(mArrayAdapter.getItem(3), "unit");
         assertEquals(mArrayAdapter.getItem(4), "test");
     }
-
-    private static class MockDataSetObserver extends DataSetObserver {
-
-        private int mCalledOnChangedCount;
-        private int mOnCalledInvalidatedCount;
-
-        public MockDataSetObserver() {
-            clearCount();
-        }
-
-        public int getCalledOnChangedCount() {
-            return mCalledOnChangedCount;
-        }
-
-        public int getCalledOnInvalidatedCount() {
-            return mOnCalledInvalidatedCount;
-        }
-
-        public void clearCount() {
-            mCalledOnChangedCount = 0;
-            mOnCalledInvalidatedCount = 0;
-        }
-
-        public void onChanged() {
-            mCalledOnChangedCount++;
-        }
-
-        public void onInvalidated() {
-            mOnCalledInvalidatedCount++;
-        }
-    }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java b/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java
index eb22d6b..520b430 100644
--- a/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java
@@ -16,21 +16,22 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.app.UiModeManager;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.cts.util.PollingCheck;
+import android.graphics.Color;
 import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.text.Editable;
+import android.text.TextWatcher;
 import android.util.AttributeSet;
 import android.util.Xml;
 import android.view.KeyCharacterMap;
@@ -40,37 +41,30 @@
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
 import android.widget.AutoCompleteTextView;
+import android.widget.AutoCompleteTextView.Validator;
 import android.widget.Filter;
 import android.widget.Filterable;
-import android.widget.AutoCompleteTextView.Validator;
+import android.widget.cts.util.TestUtils;
+import org.xmlpull.v1.XmlPullParser;
 
-import java.io.IOException;
+import static org.mockito.Mockito.*;
 
+@MediumTest
 public class AutoCompleteTextViewTest extends
         ActivityInstrumentationTestCase2<AutoCompleteCtsActivity> {
+    private final static String[] WORDS =
+            new String[] { "testOne", "testTwo", "testThree", "testFour" };
+    private final static String STRING_TEST = "To be tested";
+    private final static String STRING_VALIDATED = "String Validated";
+    private final static String STRING_CHECK = "To be checked";
 
-    /**
-     * Instantiates a new text view test.
-     */
-    public AutoCompleteTextViewTest() {
-        super("android.widget.cts", AutoCompleteCtsActivity.class);
-    }
-
-    /** The m activity. */
     private Activity mActivity;
-
-    /** The m instrumentation. */
     private Instrumentation mInstrumentation;
     private AutoCompleteTextView mAutoCompleteTextView;
     private boolean mNumeric = false;
-    ArrayAdapter<String> mAdapter;
-    private final String[] WORDS = new String[] { "testOne", "testTwo", "testThree", "testFour" };
-    boolean isOnFilterComplete = false;
-    final String STRING_TEST = "To be tested";
-    final String STRING_VALIDATED = "String Validated";
-    final String STRING_CHECK = "To be checked";
-    final String STRING_APPEND = "and be appended";
-    Validator mValidator = new Validator() {
+    private ArrayAdapter<String> mAdapter;
+
+    private final Validator mValidator = new Validator() {
         public CharSequence fixText(CharSequence invalidText) {
             return STRING_VALIDATED;
         }
@@ -80,6 +74,36 @@
         }
     };
 
+    protected class MyTextWatcher implements TextWatcher {
+        private CharSequence mExpectedAfter;
+
+        public MyTextWatcher(CharSequence expectedAfter) {
+            mExpectedAfter = expectedAfter;
+        }
+
+        @Override
+        public void onTextChanged(CharSequence s, int start, int before, int count) {
+            assertEquals(mExpectedAfter.toString(), s.toString());
+            // This watcher is expected to be notified in the middle of completion
+            assertTrue(mAutoCompleteTextView.isPerformingCompletion());
+        }
+
+        @Override
+        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+        }
+
+        @Override
+        public void afterTextChanged(Editable s) {
+        }
+    }
+
+    /**
+     * Instantiates a new text view test.
+     */
+    public AutoCompleteTextViewTest() {
+        super("android.widget.cts", AutoCompleteCtsActivity.class);
+    }
+
     /*
      * (non-Javadoc)
      *
@@ -89,12 +113,8 @@
     protected void setUp() throws Exception {
         super.setUp();
         mActivity = getActivity();
-        new PollingCheck() {
-            @Override
-                protected boolean check() {
-                return mActivity.hasWindowFocus();
-            }
-        }.run();
+        PollingCheck.waitFor(() -> mActivity.hasWindowFocus());
+
         mInstrumentation = getInstrumentation();
         mAutoCompleteTextView = (AutoCompleteTextView) mActivity
                 .findViewById(R.id.autocompletetv_edit);
@@ -116,20 +136,32 @@
     public void testConstructor() {
         XmlPullParser parser;
 
-        // new the AutoCompleteTextView instance
         new AutoCompleteTextView(mActivity);
+        new AutoCompleteTextView(mActivity, null);
+        new AutoCompleteTextView(mActivity, null, android.R.attr.autoCompleteTextViewStyle);
+        new AutoCompleteTextView(mActivity, null, 0,
+                android.R.style.Widget_DeviceDefault_AutoCompleteTextView);
+        new AutoCompleteTextView(mActivity, null, 0,
+                android.R.style.Widget_DeviceDefault_Light_AutoCompleteTextView);
+        new AutoCompleteTextView(mActivity, null, 0,
+                android.R.style.Widget_Material_AutoCompleteTextView);
+        new AutoCompleteTextView(mActivity, null, 0,
+                android.R.style.Widget_Material_Light_AutoCompleteTextView);
+
+        final Resources.Theme popupTheme = mActivity.getResources().newTheme();
+        popupTheme.applyStyle(android.R.style.Theme_Material, true);
+        new AutoCompleteTextView(mActivity, null, 0,
+                android.R.style.Widget_Material_Light_AutoCompleteTextView, popupTheme);
 
         // new the AutoCompleteTextView instance
         parser = mActivity.getResources().getXml(R.layout.simple_dropdown_item_1line);
         AttributeSet attributeSet = Xml.asAttributeSet(parser);
         new AutoCompleteTextView(mActivity, attributeSet);
-        new AutoCompleteTextView(mActivity, null);
 
         // new the AutoCompleteTextView instance
         parser = mActivity.getResources().getXml(R.layout.framelayout_layout);
         attributeSet = Xml.asAttributeSet(parser);
         new AutoCompleteTextView(mActivity, attributeSet, 0);
-        new AutoCompleteTextView(mActivity, null, 0);
         // Test constructor with null Context, in fact, previous two functions will
         // finally invoke this version.
         try {
@@ -145,38 +177,39 @@
         new AutoCompleteTextView(mActivity, null, -1);
     }
 
-    public void testEnoughToFilter() throws Throwable {
+    public void testEnoughToFilter() {
         mAutoCompleteTextView.setThreshold(3);
         assertEquals(3, mAutoCompleteTextView.getThreshold());
 
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                String testString = "TryToTest";
-                mAutoCompleteTextView.setText(testString);
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setText("TryToTest"));
         mInstrumentation.waitForIdleSync();
         assertTrue(mAutoCompleteTextView.enoughToFilter());
 
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                String testString = "No";
-                mAutoCompleteTextView.setText(testString);
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setText("No"));
         mInstrumentation.waitForIdleSync();
         assertFalse(mAutoCompleteTextView.enoughToFilter());
     }
 
-    @UiThreadTest
     public void testAccessAdapter() {
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setAdapter(null));
+        assertNull(mAutoCompleteTextView.getAdapter());
+
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setAdapter(mAdapter));
+        assertSame(mAdapter, mAutoCompleteTextView.getAdapter());
+
+        // Re-set adapter to null
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setAdapter(null));
+        assertNull(mAutoCompleteTextView.getAdapter());
+    }
+
+    @UiThreadTest
+    public void testAccessFilter() {
         MockAutoCompleteTextView autoCompleteTextView = new MockAutoCompleteTextView(mActivity);
 
         // Set Threshold to 4 characters
         autoCompleteTextView.setThreshold(4);
 
-        ArrayAdapter<String> adapter = null;
-        autoCompleteTextView.setAdapter(adapter);
+        autoCompleteTextView.setAdapter(null);
         assertNull(autoCompleteTextView.getAdapter());
         assertNull(autoCompleteTextView.getFilter());
 
@@ -187,49 +220,51 @@
         assertSame(filter, autoCompleteTextView.getFilter());
 
         // Re-set adapter to null
-        autoCompleteTextView.setAdapter(adapter);
+        autoCompleteTextView.setAdapter(null);
         assertNull(autoCompleteTextView.getAdapter());
         assertNull(autoCompleteTextView.getFilter());
     }
 
-    @SuppressWarnings("deprecation")
     public void testAccessItemClickListener() {
-        final MockOnItemClickListener testOnItemClickListener = new MockOnItemClickListener();
+        final AdapterView.OnItemClickListener mockItemClickListener =
+                mock(AdapterView.OnItemClickListener.class);
 
         // To ensure null listener
         mAutoCompleteTextView.setOnItemClickListener(null);
         assertNull(mAutoCompleteTextView.getItemClickListener());
         assertNull(mAutoCompleteTextView.getOnItemClickListener());
 
-        assertNotNull(testOnItemClickListener);
-        mAutoCompleteTextView.setOnItemClickListener(testOnItemClickListener);
-        assertSame(testOnItemClickListener, mAutoCompleteTextView.getItemClickListener());
-        assertSame(testOnItemClickListener, mAutoCompleteTextView.getOnItemClickListener());
+        mAutoCompleteTextView.setOnItemClickListener(mockItemClickListener);
+        assertSame(mockItemClickListener, mAutoCompleteTextView.getItemClickListener());
+        assertSame(mockItemClickListener, mAutoCompleteTextView.getOnItemClickListener());
+        verifyZeroInteractions(mockItemClickListener);
 
         // re-clear listener by setOnItemClickListener
         mAutoCompleteTextView.setOnItemClickListener(null);
         assertNull(mAutoCompleteTextView.getItemClickListener());
         assertNull(mAutoCompleteTextView.getOnItemClickListener());
+        verifyZeroInteractions(mockItemClickListener);
     }
 
-    @SuppressWarnings("deprecation")
     public void testAccessItemSelectedListener() {
-        MockOnItemSelectedListener testOnItemSelectedListener = new MockOnItemSelectedListener();
+        final AdapterView.OnItemSelectedListener mockItemSelectedListener =
+                mock(AdapterView.OnItemSelectedListener.class);
 
         // To ensure null listener
         mAutoCompleteTextView.setOnItemSelectedListener(null);
         assertNull(mAutoCompleteTextView.getItemSelectedListener());
         assertNull(mAutoCompleteTextView.getOnItemSelectedListener());
 
-        assertNotNull(testOnItemSelectedListener);
-        mAutoCompleteTextView.setOnItemSelectedListener(testOnItemSelectedListener);
-        assertSame(testOnItemSelectedListener, mAutoCompleteTextView.getItemSelectedListener());
-        assertSame(testOnItemSelectedListener, mAutoCompleteTextView.getOnItemSelectedListener());
+        mAutoCompleteTextView.setOnItemSelectedListener(mockItemSelectedListener);
+        assertSame(mockItemSelectedListener, mAutoCompleteTextView.getItemSelectedListener());
+        assertSame(mockItemSelectedListener, mAutoCompleteTextView.getOnItemSelectedListener());
+        verifyZeroInteractions(mockItemSelectedListener);
 
         //re-clear listener by setOnItemClickListener
         mAutoCompleteTextView.setOnItemSelectedListener(null);
         assertNull(mAutoCompleteTextView.getItemSelectedListener());
         assertNull(mAutoCompleteTextView.getOnItemSelectedListener());
+        verifyZeroInteractions(mockItemSelectedListener);
     }
 
     @UiThreadTest
@@ -247,73 +282,130 @@
 
     @UiThreadTest
     public void testOnTextChanged() {
-        MockAutoCompleteTextView autoCompleteTextView = new MockAutoCompleteTextView(mActivity);
+        final TextWatcher mockTextWatcher = mock(TextWatcher.class);
+        mAutoCompleteTextView.addTextChangedListener(mockTextWatcher);
+        verify(mockTextWatcher, never()).onTextChanged(any(CharSequence.class),
+                anyInt(), anyInt(), anyInt());
 
-        assertFalse(autoCompleteTextView.isOnTextChanged());
-        assertEquals("", autoCompleteTextView.getLastChangeText());
-        assertEquals("", autoCompleteTextView.getText().toString());
-        assertEquals(0, autoCompleteTextView.getStart());
-        assertEquals(0, autoCompleteTextView.getBefore());
-        assertEquals(0, autoCompleteTextView.getAfter());
-
-        autoCompleteTextView.setText(STRING_TEST);
-        assertEquals(STRING_TEST, autoCompleteTextView.getText().toString());
-        assertTrue(autoCompleteTextView.isOnTextChanged());
-        assertEquals(STRING_TEST, autoCompleteTextView.getLastChangeText());
-        assertEquals(0, autoCompleteTextView.getStart());
-        assertEquals(0, autoCompleteTextView.getBefore());
-        assertEquals(STRING_TEST.length(), autoCompleteTextView.getAfter());
+        mAutoCompleteTextView.setText(STRING_TEST);
+        verify(mockTextWatcher, times(1)).onTextChanged(TestUtils.sameCharSequence(STRING_TEST),
+                eq(0), eq(0), eq(STRING_TEST.length()));
 
         // Test replacing text.
-        autoCompleteTextView.resetStatus();
-        autoCompleteTextView.setText(STRING_CHECK);
-        assertEquals(STRING_CHECK, autoCompleteTextView.getText().toString());
-        assertEquals(STRING_CHECK, autoCompleteTextView.getLastChangeText());
-        assertEquals(0, autoCompleteTextView.getStart());
-        assertEquals(STRING_TEST.length(), autoCompleteTextView.getBefore());
-        assertEquals(STRING_CHECK.length(), autoCompleteTextView.getAfter());
+        mAutoCompleteTextView.setText(STRING_CHECK);
+        verify(mockTextWatcher, times(1)).onTextChanged(TestUtils.sameCharSequence(STRING_CHECK),
+                eq(0), eq(STRING_TEST.length()), eq(STRING_CHECK.length()));
     }
 
-    @UiThreadTest
-    public void testPopupWindow() throws XmlPullParserException, IOException {
-        assertFalse(mAutoCompleteTextView.isPopupShowing());
-        mAutoCompleteTextView.showDropDown();
-        assertTrue(mAutoCompleteTextView.isPopupShowing());
+    public void testPopupWindow() {
+        final AutoCompleteTextView.OnDismissListener mockDismissListener =
+                mock(AutoCompleteTextView.OnDismissListener.class);
+        mAutoCompleteTextView.setOnDismissListener(mockDismissListener);
 
-        mAutoCompleteTextView.dismissDropDown();
         assertFalse(mAutoCompleteTextView.isPopupShowing());
-
-        mAutoCompleteTextView.showDropDown();
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.showDropDown());
         assertTrue(mAutoCompleteTextView.isPopupShowing());
+        verifyZeroInteractions(mockDismissListener);
+
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.dismissDropDown());
+        assertFalse(mAutoCompleteTextView.isPopupShowing());
+        verify(mockDismissListener, times(1)).onDismiss();
+
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.showDropDown());
+        assertTrue(mAutoCompleteTextView.isPopupShowing());
+        verify(mockDismissListener, times(1)).onDismiss();
 
         final MockValidator validator = new MockValidator();
         mAutoCompleteTextView.setValidator(validator);
-        mAutoCompleteTextView.requestFocus();
-        mAutoCompleteTextView.showDropDown();
-        assertTrue(mAutoCompleteTextView.isPopupShowing());
-        mAutoCompleteTextView.setText(STRING_TEST);
+        mInstrumentation.runOnMainSync(() -> {
+            mAutoCompleteTextView.requestFocus();
+            mAutoCompleteTextView.showDropDown();
+            mAutoCompleteTextView.setText(STRING_TEST);
+        });
         assertEquals(STRING_TEST, mAutoCompleteTextView.getText().toString());
+
         // clearFocus will trigger onFocusChanged, and onFocusChanged will validate the text.
-        mAutoCompleteTextView.clearFocus();
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.clearFocus());
         assertFalse(mAutoCompleteTextView.isPopupShowing());
         assertEquals(STRING_VALIDATED, mAutoCompleteTextView.getText().toString());
+        verify(mockDismissListener, times(2)).onDismiss();
+
+        verifyNoMoreInteractions(mockDismissListener);
+    }
+
+    public void testDropDownMetrics() {
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setAdapter(mAdapter));
+
+        final Resources res = mActivity.getResources();
+        final int dropDownWidth =
+                res.getDimensionPixelSize(R.dimen.autocomplete_textview_dropdown_width);
+        final int dropDownHeight =
+                res.getDimensionPixelSize(R.dimen.autocomplete_textview_dropdown_height);
+        final int dropDownOffsetHorizontal =
+                res.getDimensionPixelSize(R.dimen.autocomplete_textview_dropdown_offset_h);
+        final int dropDownOffsetVertical =
+                res.getDimensionPixelSize(R.dimen.autocomplete_textview_dropdown_offset_v);
+
+        mInstrumentation.runOnMainSync(() -> {
+            mAutoCompleteTextView.setDropDownWidth(dropDownWidth);
+            mAutoCompleteTextView.setDropDownHeight(dropDownHeight);
+            mAutoCompleteTextView.setDropDownHorizontalOffset(dropDownOffsetHorizontal);
+            mAutoCompleteTextView.setDropDownVerticalOffset(dropDownOffsetVertical);
+
+            mAutoCompleteTextView.showDropDown();
+        });
+
+        assertEquals(dropDownWidth, mAutoCompleteTextView.getDropDownWidth());
+        assertEquals(dropDownHeight, mAutoCompleteTextView.getDropDownHeight());
+        assertEquals(dropDownOffsetHorizontal, mAutoCompleteTextView.getDropDownHorizontalOffset());
+        assertEquals(dropDownOffsetVertical, mAutoCompleteTextView.getDropDownVerticalOffset());
+    }
+
+    public void testDropDownBackground() {
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setAdapter(mAdapter));
+
+        mInstrumentation.runOnMainSync(() -> {
+            mAutoCompleteTextView.setDropDownBackgroundResource(R.drawable.blue_fill);
+            mAutoCompleteTextView.showDropDown();
+        });
+        mInstrumentation.waitForIdleSync();
+
+        Drawable dropDownBackground = mAutoCompleteTextView.getDropDownBackground();
+        TestUtils.assertAllPixelsOfColor("Drop down should be blue", dropDownBackground,
+                dropDownBackground.getBounds().width(), dropDownBackground.getBounds().height(),
+                false, Color.BLUE, 1, true);
+
+        mInstrumentation.runOnMainSync(() -> {
+            mAutoCompleteTextView.dismissDropDown();
+            mAutoCompleteTextView.setDropDownBackgroundDrawable(
+                    mActivity.getDrawable(R.drawable.yellow_fill));
+            mAutoCompleteTextView.showDropDown();
+        });
+        mInstrumentation.waitForIdleSync();
+
+        dropDownBackground = mAutoCompleteTextView.getDropDownBackground();
+        TestUtils.assertAllPixelsOfColor("Drop down should be yellow", dropDownBackground,
+                dropDownBackground.getBounds().width(), dropDownBackground.getBounds().height(),
+                false, Color.YELLOW, 1, true);
     }
 
     @UiThreadTest
     public void testReplaceText() {
         MockAutoCompleteTextView autoCompleteTextView = new MockAutoCompleteTextView(mActivity);
+        final TextWatcher mockTextWatcher = mock(TextWatcher.class);
+        autoCompleteTextView.addTextChangedListener(mockTextWatcher);
+        verify(mockTextWatcher, never()).onTextChanged(any(CharSequence.class),
+                anyInt(), anyInt(), anyInt());
 
-        assertEquals("", autoCompleteTextView.getText().toString());
-        assertFalse(autoCompleteTextView.isOnTextChanged());
         autoCompleteTextView.replaceText("Text");
         assertEquals("Text", autoCompleteTextView.getText().toString());
-        assertTrue(autoCompleteTextView.isOnTextChanged());
+        verify(mockTextWatcher, times(1)).onTextChanged(TestUtils.sameCharSequence("Text"),
+                eq(0), eq(0), eq("Text".length()));
 
-        autoCompleteTextView.resetStatus();
-        assertFalse(autoCompleteTextView.isOnTextChanged());
         autoCompleteTextView.replaceText("Another");
         assertEquals("Another", autoCompleteTextView.getText().toString());
-        assertTrue(autoCompleteTextView.isOnTextChanged());
+        verify(mockTextWatcher, times(1)).onTextChanged(TestUtils.sameCharSequence("Another"),
+                eq(0), eq("Text".length()), eq("Another".length()));
     }
 
     @UiThreadTest
@@ -342,21 +434,17 @@
     }
 
     public void testGetThreshold() {
-        final AutoCompleteTextView autoCompleteTextView = (AutoCompleteTextView) mActivity
-                .findViewById(R.id.autocompletetv_edit);
-        assertNotNull(autoCompleteTextView);
-
-        assertEquals(1, autoCompleteTextView.getThreshold());
-        autoCompleteTextView.setThreshold(3);
-        assertEquals(3, autoCompleteTextView.getThreshold());
+        assertEquals(1, mAutoCompleteTextView.getThreshold());
+        mAutoCompleteTextView.setThreshold(3);
+        assertEquals(3, mAutoCompleteTextView.getThreshold());
 
         // Test negative value input
-        autoCompleteTextView.setThreshold(-5);
-        assertEquals(1, autoCompleteTextView.getThreshold());
+        mAutoCompleteTextView.setThreshold(-5);
+        assertEquals(1, mAutoCompleteTextView.getThreshold());
 
         // Test zero
-        autoCompleteTextView.setThreshold(0);
-        assertEquals(1, autoCompleteTextView.getThreshold());
+        mAutoCompleteTextView.setThreshold(0);
+        assertEquals(1, mAutoCompleteTextView.getThreshold());
     }
 
     public void testAccessValidater() {
@@ -371,7 +459,7 @@
         assertNull(mAutoCompleteTextView.getValidator());
     }
 
-    public void testOnFilterComplete() throws Throwable {
+    public void testOnFilterComplete() {
         // Set Threshold to 4 characters
         mAutoCompleteTextView.setThreshold(4);
 
@@ -384,22 +472,15 @@
         }
 
         // Test the filter if the input string is not long enough to threshold
-        runTestOnUiThread(new Runnable() {
-            public void run() {
+        mInstrumentation.runOnMainSync(() -> {
                 mAutoCompleteTextView.setAdapter(mAdapter);
                 mAutoCompleteTextView.setText("");
                 mAutoCompleteTextView.requestFocus();
-            }
         });
         mInstrumentation.sendStringSync(testString);
 
         // onFilterComplete will close the popup.
-        new PollingCheck() {
-            @Override
-            protected boolean check() {
-                return !mAutoCompleteTextView.isPopupShowing();
-            }
-        }.run();
+        PollingCheck.waitFor(() -> !mAutoCompleteTextView.isPopupShowing());
 
         if (mNumeric) {
             // "that" in case of 12-key(NUMERIC) keyboard
@@ -408,20 +489,13 @@
             testString = "that";
         }
         mInstrumentation.sendStringSync(testString);
-        new PollingCheck() {
-            @Override
-            protected boolean check() {
-                return !mAutoCompleteTextView.isPopupShowing();
-            }
-        }.run();
+        PollingCheck.waitFor(() -> !mAutoCompleteTextView.isPopupShowing());
 
         // Test the expected filter matching scene
-        runTestOnUiThread(new Runnable() {
-            public void run() {
+        mInstrumentation.runOnMainSync(() -> {
                 mAutoCompleteTextView.setFocusable(true);
                 mAutoCompleteTextView.requestFocus();
                 mAutoCompleteTextView.setText("");
-            }
         });
         if (mNumeric) {
             // "test" in case of 12-key(NUMERIC) keyboard
@@ -431,20 +505,14 @@
         }
         assertTrue(mAutoCompleteTextView.hasFocus());
         assertTrue(mAutoCompleteTextView.hasWindowFocus());
-        new PollingCheck() {
-            @Override
-            protected boolean check() {
-                return mAutoCompleteTextView.isPopupShowing();
-            }
-        }.run();
+        PollingCheck.waitFor(() -> mAutoCompleteTextView.isPopupShowing());
     }
 
-    public void testPerformFiltering() throws Throwable {
+    public void testPerformFiltering() {
         if (isTvMode()) {
             return;
         }
-        runTestOnUiThread(new Runnable() {
-            public void run() {
+        mInstrumentation.runOnMainSync(() -> {
                 mAutoCompleteTextView.setAdapter(mAdapter);
                 mAutoCompleteTextView.setValidator(mValidator);
 
@@ -452,7 +520,6 @@
                 mAutoCompleteTextView.setFocusable(true);
                 mAutoCompleteTextView.requestFocus();
                 mAutoCompleteTextView.showDropDown();
-            }
         });
         mInstrumentation.waitForIdleSync();
         assertTrue(mAutoCompleteTextView.isPopupShowing());
@@ -461,11 +528,9 @@
         // KeyBack will close the popup.
         assertFalse(mAutoCompleteTextView.isPopupShowing());
 
-        runTestOnUiThread(new Runnable() {
-            public void run() {
+        mInstrumentation.runOnMainSync(() -> {
                 mAutoCompleteTextView.dismissDropDown();
                 mAutoCompleteTextView.setText(STRING_TEST);
-            }
         });
         mInstrumentation.waitForIdleSync();
 
@@ -478,12 +543,10 @@
                 android.R.layout.simple_dropdown_item_1line, WORDS);
 
         // Set Threshold to 4 charactersonKeyDown
-        runTestOnUiThread(new Runnable() {
-            public void run() {
+        mInstrumentation.runOnMainSync(() -> {
                 mAutoCompleteTextView.setAdapter(adapter);
                 mAutoCompleteTextView.requestFocus();
                 mAutoCompleteTextView.setText("");
-            }
         });
         mInstrumentation.waitForIdleSync();
         // Create and get the filter.
@@ -495,38 +558,27 @@
         if (mNumeric) {
             // "numeric" in case of 12-key(NUMERIC) keyboard
             mInstrumentation.sendStringSync("6688633777444222");
-            new PollingCheck() {
-                @Override
-                protected boolean check() {
-                    return "numeric".equals(filter.getResult());
-                }
-            }.run();
+            PollingCheck.waitFor(() -> "numeric".equals(filter.getResult()));
         } else {
-            Thread.sleep(200);
+            SystemClock.sleep(200);
             mInstrumentation.sendStringSync(STRING_TEST);
-            new PollingCheck() {
-                @Override
-                protected boolean check() {
-                    return STRING_TEST.equals(filter.getResult());
-                }
-            }.run();
+            PollingCheck.waitFor(() -> STRING_TEST.equals(filter.getResult()));
         }
     }
 
-    public void testPerformCompletion() throws Throwable {
+    public void testPerformCompletionWithDPad() {
         if (isTvMode()) {
             return;
         }
-        final MockOnItemClickListener listener = new MockOnItemClickListener();
+        final AdapterView.OnItemClickListener mockItemClickListener =
+                mock(AdapterView.OnItemClickListener.class);
         assertFalse(mAutoCompleteTextView.isPerformingCompletion());
 
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                mAutoCompleteTextView.setOnItemClickListener(listener);
-                mAutoCompleteTextView.setAdapter(mAdapter);
-                mAutoCompleteTextView.requestFocus();
-                mAutoCompleteTextView.showDropDown();
-            }
+        mInstrumentation.runOnMainSync(() -> {
+            mAutoCompleteTextView.setOnItemClickListener(mockItemClickListener);
+            mAutoCompleteTextView.setAdapter(mAdapter);
+            mAutoCompleteTextView.requestFocus();
+            mAutoCompleteTextView.showDropDown();
         });
         mInstrumentation.waitForIdleSync();
         assertFalse(mAutoCompleteTextView.isPerformingCompletion());
@@ -535,54 +587,112 @@
         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_ENTER);
         mInstrumentation.waitForIdleSync();
-        assertTrue(listener.isOnItemClicked());
-
+        verify(mockItemClickListener, times(1)).onItemClick(any(AdapterView.class), any(View.class),
+                eq(0), eq(0L));
         assertEquals(WORDS[0], mAutoCompleteTextView.getText().toString());
 
-        // re-set 'clicked' flag to false
-        listener.clearItemClickedStatus();
-
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                mAutoCompleteTextView.showDropDown();
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.showDropDown());
         mInstrumentation.waitForIdleSync();
         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
-        assertTrue(listener.isOnItemClicked());
+        verify(mockItemClickListener, times(2)).onItemClick(any(AdapterView.class), any(View.class),
+                eq(0), eq(0L));
         assertEquals(WORDS[0], mAutoCompleteTextView.getText().toString());
         assertFalse(mAutoCompleteTextView.isPerformingCompletion());
 
-        listener.clearItemClickedStatus();
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                mAutoCompleteTextView.showDropDown();
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.showDropDown());
         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
         // Test normal key code.
         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_0);
-        assertFalse(listener.isOnItemClicked());
+        verifyNoMoreInteractions(mockItemClickListener);
         assertNotSame("", mAutoCompleteTextView.getText().toString());
         assertFalse(mAutoCompleteTextView.isPerformingCompletion());
 
-        listener.clearItemClickedStatus();
-
         // Test the method on the scene of popup is closed.
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-               mAutoCompleteTextView.dismissDropDown();
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.dismissDropDown());
 
         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_ENTER);
-        assertFalse(listener.isOnItemClicked());
+        verifyNoMoreInteractions(mockItemClickListener);
         assertNotSame("", mAutoCompleteTextView.getText().toString());
         assertFalse(mAutoCompleteTextView.isPerformingCompletion());
     }
 
+    public void testPerformCompletionExplicit() {
+        final AdapterView.OnItemClickListener mockItemClickListener =
+                mock(AdapterView.OnItemClickListener.class);
+        assertFalse(mAutoCompleteTextView.isPerformingCompletion());
+
+        // Create a custom watcher that checks isPerformingCompletion to return true
+        // in the "middle" of the performCompletion processing. We also spy on this watcher
+        // to make sure that its onTextChanged is invoked.
+        final TextWatcher myTextWatcher = new MyTextWatcher(WORDS[1]);
+        final TextWatcher spyTextWatcher = spy(myTextWatcher);
+        mAutoCompleteTextView.addTextChangedListener(spyTextWatcher);
+
+        mInstrumentation.runOnMainSync(() -> {
+            mAutoCompleteTextView.setOnItemClickListener(mockItemClickListener);
+            mAutoCompleteTextView.setAdapter(mAdapter);
+            mAutoCompleteTextView.requestFocus();
+            mAutoCompleteTextView.showDropDown();
+        });
+        mInstrumentation.waitForIdleSync();
+
+        assertTrue(mAutoCompleteTextView.isPopupShowing());
+        assertFalse(mAutoCompleteTextView.isPerformingCompletion());
+
+        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
+        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.performCompletion());
+        verify(mockItemClickListener, times(1)).onItemClick(any(AdapterView.class), any(View.class),
+                eq(1), eq(1L));
+        assertEquals(WORDS[1], mAutoCompleteTextView.getText().toString());
+        assertFalse(mAutoCompleteTextView.isPerformingCompletion());
+        assertFalse(mAutoCompleteTextView.isPopupShowing());
+
+        verify(spyTextWatcher, atLeastOnce()).onTextChanged(TestUtils.sameCharSequence(WORDS[1]),
+                eq(0), eq(0), eq(WORDS[1].length()));
+        verifyNoMoreInteractions(mockItemClickListener);
+    }
+
+    public void testSetTextWithCompletion() {
+        final AdapterView.OnItemClickListener mockItemClickListener =
+                mock(AdapterView.OnItemClickListener.class);
+
+        mInstrumentation.runOnMainSync(() -> {
+            mAutoCompleteTextView.setOnItemClickListener(mockItemClickListener);
+            mAutoCompleteTextView.setAdapter(mAdapter);
+        });
+        mInstrumentation.waitForIdleSync();
+
+        assertFalse(mAutoCompleteTextView.isPopupShowing());
+
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setText("testO", true));
+        mInstrumentation.waitForIdleSync();
+
+        assertTrue(mAutoCompleteTextView.isPopupShowing());
+        verifyZeroInteractions(mockItemClickListener);
+    }
+
+    public void testSetTextWithNoCompletion() {
+        final AdapterView.OnItemClickListener mockItemClickListener =
+                mock(AdapterView.OnItemClickListener.class);
+
+        mInstrumentation.runOnMainSync(() -> {
+            mAutoCompleteTextView.setOnItemClickListener(mockItemClickListener);
+            mAutoCompleteTextView.setAdapter(mAdapter);
+        });
+        mInstrumentation.waitForIdleSync();
+
+        assertFalse(mAutoCompleteTextView.isPopupShowing());
+
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setText("testO", false));
+        mInstrumentation.waitForIdleSync();
+
+        assertFalse(mAutoCompleteTextView.isPopupShowing());
+        verifyZeroInteractions(mockItemClickListener);
+    }
+
     @UiThreadTest
     public void testPerformValidation() {
         final CharSequence text = "this";
@@ -596,41 +706,27 @@
         mAutoCompleteTextView.setValidator(null);
     }
 
-    public void testSetCompletionHint() {
+    public void testAccessCompletionHint() {
         mAutoCompleteTextView.setCompletionHint("TEST HINT");
+        assertEquals("TEST HINT", mAutoCompleteTextView.getCompletionHint());
+
+        mAutoCompleteTextView.setCompletionHint(null);
+        assertNull(mAutoCompleteTextView.getCompletionHint());
     }
 
-    public void testOnAttachedToWindow() {
-        // implement details, do not test
-    }
+    public void testAccessListSelection() {
+        final AdapterView.OnItemClickListener mockItemClickListener =
+                mock(AdapterView.OnItemClickListener.class);
 
-    public void testOnCommitCompletion() {
-        // implement details, do not test
-    }
-
-    public void testOnDetachedFromWindow() {
-        // implement details, do not test
-    }
-
-    public void testOnKeyPreIme() {
-        // implement details, do not test
-    }
-
-    public void testAccessListSelection() throws Throwable {
-        final MockOnItemClickListener listener = new MockOnItemClickListener();
-
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                mAutoCompleteTextView.setOnItemClickListener(listener);
+        mInstrumentation.runOnMainSync(() -> {
+                mAutoCompleteTextView.setOnItemClickListener(mockItemClickListener);
                 mAutoCompleteTextView.setAdapter(mAdapter);
                 mAutoCompleteTextView.requestFocus();
                 mAutoCompleteTextView.showDropDown();
-            }
         });
         mInstrumentation.waitForIdleSync();
 
-        runTestOnUiThread(new Runnable() {
-            public void run() {
+        mInstrumentation.runOnMainSync(() -> {
                 mAutoCompleteTextView.setListSelection(1);
                 assertEquals(1, mAutoCompleteTextView.getListSelection());
 
@@ -639,7 +735,6 @@
 
                 mAutoCompleteTextView.clearListSelection();
                 assertEquals(2, mAutoCompleteTextView.getListSelection());
-            }
         });
         mInstrumentation.waitForIdleSync();
     }
@@ -660,75 +755,25 @@
         assertEquals(ViewGroup.LayoutParams.MATCH_PARENT, mAutoCompleteTextView.getDropDownWidth());
     }
 
-    private static class MockOnItemClickListener implements AdapterView.OnItemClickListener {
-        private boolean mOnItemClickedFlag = false;
-
-        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-            mOnItemClickedFlag = true;
-            return;
-        }
-
-        public boolean isOnItemClicked() {
-            return mOnItemClickedFlag;
-        }
-
-        public void clearItemClickedStatus() {
-            mOnItemClickedFlag = false;
-        }
-    }
-
-    private static class MockOnItemSelectedListener implements AdapterView.OnItemSelectedListener {
-        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
-            return;
-        }
-
-        public void onNothingSelected(AdapterView<?> parent) {
-            return;
-        }
-    }
-
     private class MockValidator implements AutoCompleteTextView.Validator {
         public CharSequence fixText(CharSequence invalidText) {
             return STRING_VALIDATED;
         }
 
         public boolean isValid(CharSequence text) {
-            if (text == STRING_TEST) {
-                return true;
-            }
-            return false;
+            return (text == STRING_TEST);
         }
     }
 
-    private static class MockAutoCompleteTextView extends AutoCompleteTextView {
-        private boolean mOnTextChangedFlag = false;
-        private boolean mOnFilterCompleteFlag = false;
-        private String lastChangeText = "";
-        private int mStart = 0;
-        private int mBefore = 0;
-        private int mAfter = 0;
-
-        public void resetStatus() {
-            mOnTextChangedFlag = false;
-            mOnFilterCompleteFlag = false;
-            mStart = 0;
-            mBefore = 0;
-            mAfter = 0;
-        }
-
+    protected static class MockAutoCompleteTextView extends AutoCompleteTextView {
         public MockAutoCompleteTextView(Context context) {
             super(context);
-            resetStatus();
         }
 
         public MockAutoCompleteTextView(Context context, AttributeSet attrs) {
             super(context, attrs);
         }
 
-        protected MockAutoCompleteTextView(Context context, AttributeSet attrs, int defStyle) {
-            super(context, attrs, defStyle);
-        }
-
         @Override
         protected CharSequence convertSelectionToString(Object selectedItem) {
             return super.convertSelectionToString(selectedItem);
@@ -745,16 +790,6 @@
         }
 
         @Override
-        protected void onTextChanged(CharSequence text, int start, int before, int after) {
-            super.onTextChanged(text, start, before, after);
-            mOnTextChangedFlag = true;
-            lastChangeText = text.toString();
-            mStart = start;
-            mBefore = before;
-            mAfter = after;
-        }
-
-        @Override
         protected void performFiltering(CharSequence text, int keyCode) {
             super.performFiltering(text, keyCode);
         }
@@ -768,36 +803,6 @@
         protected boolean setFrame(int l, int t, int r, int b) {
             return super.setFrame(l, t, r, b);
         }
-
-        @Override
-        public void onFilterComplete(int count) {
-            super.onFilterComplete(count);
-            mOnFilterCompleteFlag = true;
-        }
-
-        protected boolean isOnTextChanged() {
-            return mOnTextChangedFlag;
-        }
-
-        protected String getLastChangeText() {
-            return lastChangeText;
-        }
-
-        protected boolean isOnFilterComplete() {
-            return mOnFilterCompleteFlag;
-        }
-
-        protected int getStart() {
-            return mStart;
-        }
-
-        protected int getBefore() {
-            return mBefore;
-        }
-
-        protected int getAfter() {
-            return mAfter;
-        }
     }
 
     private static class MockFilter extends Filter {
diff --git a/tests/tests/widget/src/android/widget/cts/BaseAdapterTest.java b/tests/tests/widget/src/android/widget/cts/BaseAdapterTest.java
index 7659c1e0..5a9a1fa 100644
--- a/tests/tests/widget/src/android/widget/cts/BaseAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/BaseAdapterTest.java
@@ -22,6 +22,8 @@
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
 
+import static org.mockito.Mockito.*;
+
 /**
  * Test {@link BaseAdapter}.
  */
@@ -33,34 +35,34 @@
 
     public void testDataSetObserver() {
         BaseAdapter baseAdapter = new MockBaseAdapter();
-        MockDataSetObserver dataSetObserver = new MockDataSetObserver();
+        DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
 
-        assertFalse(dataSetObserver.hasCalledOnChanged());
+        verifyZeroInteractions(mockDataSetObserver);
         baseAdapter.notifyDataSetChanged();
-        assertFalse(dataSetObserver.hasCalledOnChanged());
+        verifyZeroInteractions(mockDataSetObserver);
 
-        baseAdapter.registerDataSetObserver(dataSetObserver);
+        baseAdapter.registerDataSetObserver(mockDataSetObserver);
         baseAdapter.notifyDataSetChanged();
-        assertTrue(dataSetObserver.hasCalledOnChanged());
+        verify(mockDataSetObserver, times(1)).onChanged();
 
-        dataSetObserver.reset();
-        assertFalse(dataSetObserver.hasCalledOnChanged());
-        baseAdapter.unregisterDataSetObserver(dataSetObserver);
+        reset(mockDataSetObserver);
+        verifyZeroInteractions(mockDataSetObserver);
+        baseAdapter.unregisterDataSetObserver(mockDataSetObserver);
         baseAdapter.notifyDataSetChanged();
-        assertFalse(dataSetObserver.hasCalledOnChanged());
+        verifyZeroInteractions(mockDataSetObserver);
     }
 
     public void testNotifyDataSetInvalidated() {
         BaseAdapter baseAdapter = new MockBaseAdapter();
-        MockDataSetObserver dataSetObserver = new MockDataSetObserver();
+        DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
 
-        assertFalse(dataSetObserver.hasCalledOnInvalidated());
+        verifyZeroInteractions(mockDataSetObserver);
         baseAdapter.notifyDataSetInvalidated();
-        assertFalse(dataSetObserver.hasCalledOnInvalidated());
+        verifyZeroInteractions(mockDataSetObserver);
 
-        baseAdapter.registerDataSetObserver(dataSetObserver);
+        baseAdapter.registerDataSetObserver(mockDataSetObserver);
         baseAdapter.notifyDataSetInvalidated();
-        assertTrue(dataSetObserver.hasCalledOnInvalidated());
+        verify(mockDataSetObserver, times(1)).onInvalidated();
     }
 
     public void testAreAllItemsEnabled() {
@@ -121,34 +123,4 @@
             return null;
         }
     }
-
-    private static class MockDataSetObserver extends DataSetObserver {
-        private boolean mCalledOnChanged = false;
-        private boolean mCalledOnInvalidated = false;
-
-        @Override
-        public void onChanged() {
-            super.onChanged();
-            mCalledOnChanged = true;
-        }
-
-        public boolean hasCalledOnChanged() {
-            return mCalledOnChanged;
-        }
-
-        @Override
-        public void onInvalidated() {
-            super.onInvalidated();
-            mCalledOnInvalidated = true;
-        }
-
-        public boolean hasCalledOnInvalidated() {
-            return mCalledOnInvalidated;
-        }
-
-        public void reset() {
-            mCalledOnChanged = false;
-            mCalledOnInvalidated = false;
-        }
-    }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/BaseExpandableListAdapterTest.java b/tests/tests/widget/src/android/widget/cts/BaseExpandableListAdapterTest.java
index 1737cfd..ad29526 100644
--- a/tests/tests/widget/src/android/widget/cts/BaseExpandableListAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/BaseExpandableListAdapterTest.java
@@ -22,6 +22,8 @@
 import android.view.ViewGroup;
 import android.widget.BaseExpandableListAdapter;
 
+import static org.mockito.Mockito.*;
+
 /**
  * Test {@link BaseExpandableListAdapter}.
  */
@@ -54,22 +56,22 @@
 
     public void testNotifyDataSetChanged() {
         MockBaseExpandableListAdapter adapter = new MockBaseExpandableListAdapter();
-        MockDataSetObserver dataSetObserver = new MockDataSetObserver();
-        adapter.registerDataSetObserver(dataSetObserver);
+        DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
+        adapter.registerDataSetObserver(mockDataSetObserver);
 
-        assertFalse(dataSetObserver.hasCalledOnChanged());
+        verifyZeroInteractions(mockDataSetObserver);
         adapter.notifyDataSetChanged();
-        assertTrue(dataSetObserver.hasCalledOnChanged());
+        verify(mockDataSetObserver, times(1)).onChanged();
     }
 
     public void testNotifyDataSetInvalidated() {
         MockBaseExpandableListAdapter adapter = new MockBaseExpandableListAdapter();
-        MockDataSetObserver dataSetObserver = new MockDataSetObserver();
-        adapter.registerDataSetObserver(dataSetObserver);
+        DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
+        adapter.registerDataSetObserver(mockDataSetObserver);
 
-        assertFalse(dataSetObserver.hasCalledOnInvalidated());
+        verifyZeroInteractions(mockDataSetObserver);
         adapter.notifyDataSetInvalidated();
-        assertTrue(dataSetObserver.hasCalledOnInvalidated());
+        verify(mockDataSetObserver, times(1)).onInvalidated();
     }
 
     public void testOnGroupCollapsed() {
@@ -86,47 +88,18 @@
 
     public void testDataSetObserver() {
         MockBaseExpandableListAdapter adapter = new MockBaseExpandableListAdapter();
-        MockDataSetObserver dataSetObserver = new MockDataSetObserver();
-        adapter.registerDataSetObserver(dataSetObserver);
+        DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
+        adapter.registerDataSetObserver(mockDataSetObserver);
 
-        assertFalse(dataSetObserver.hasCalledOnChanged());
+        verifyZeroInteractions(mockDataSetObserver);
         adapter.notifyDataSetChanged();
-        assertTrue(dataSetObserver.hasCalledOnChanged());
+        verify(mockDataSetObserver, times(1)).onChanged();
 
-        dataSetObserver.reset();
-        assertFalse(dataSetObserver.hasCalledOnChanged());
-        adapter.unregisterDataSetObserver(dataSetObserver);
+        reset(mockDataSetObserver);
+        verifyZeroInteractions(mockDataSetObserver);
+        adapter.unregisterDataSetObserver(mockDataSetObserver);
         adapter.notifyDataSetChanged();
-        assertFalse(dataSetObserver.hasCalledOnChanged());
-    }
-
-    private class MockDataSetObserver extends DataSetObserver {
-        private boolean mCalledOnChanged = false;
-        private boolean mCalledOnInvalidated = false;
-
-        @Override
-        public void onChanged() {
-            super.onChanged();
-            mCalledOnChanged = true;
-        }
-
-        public boolean hasCalledOnChanged() {
-            return mCalledOnChanged;
-        }
-
-        @Override
-        public void onInvalidated() {
-            super.onInvalidated();
-            mCalledOnInvalidated = true;
-        }
-
-        public boolean hasCalledOnInvalidated() {
-            return mCalledOnInvalidated;
-        }
-
-        public void reset() {
-            mCalledOnChanged = false;
-        }
+        verifyZeroInteractions(mockDataSetObserver);
     }
 
     private class MockBaseExpandableListAdapter extends BaseExpandableListAdapter {
diff --git a/tests/tests/widget/src/android/widget/cts/CalendarViewTest.java b/tests/tests/widget/src/android/widget/cts/CalendarViewTest.java
index 31ad341..956ebf1 100644
--- a/tests/tests/widget/src/android/widget/cts/CalendarViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/CalendarViewTest.java
@@ -18,14 +18,22 @@
 
 import android.annotation.ColorInt;
 import android.app.Instrumentation;
+import android.graphics.Rect;
+import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.MediumTest;
+import android.view.MotionEvent;
+import android.view.ViewGroup;
 import android.widget.CalendarView;
+import android.widget.ScrollView;
 import android.widget.cts.util.TestUtils;
+import android.widget.cts.util.ViewTestUtils;
 
 import java.util.Calendar;
 import java.util.GregorianCalendar;
 
+import static org.mockito.Mockito.*;
+
 @MediumTest
 public class CalendarViewTest extends ActivityInstrumentationTestCase2<CalendarViewCtsActivity> {
     private CalendarViewCtsActivity mActivity;
@@ -58,6 +66,13 @@
 
         new CalendarView(mActivity, null, android.R.attr.calendarViewStyle);
 
+        new CalendarView(mActivity, null, 0, android.R.style.Widget_DeviceDefault_CalendarView);
+
+        new CalendarView(mActivity, null, 0,
+                android.R.style.Widget_DeviceDefault_Light_CalendarView);
+
+        new CalendarView(mActivity, null, 0, android.R.style.Widget_Material_CalendarView);
+
         new CalendarView(mActivity, null, 0, android.R.style.Widget_Material_Light_CalendarView);
     }
 
@@ -103,6 +118,64 @@
         assertEquals(mCalendarViewMaterial.getMaxDate(), maxDate);
     }
 
+    private void verifyOnDateChangeListener(CalendarView calendarView,
+            boolean onlyAllowOneChangeEvent) {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        final CalendarView.OnDateChangeListener mockDateChangeListener =
+                mock(CalendarView.OnDateChangeListener.class);
+        calendarView.setOnDateChangeListener(mockDateChangeListener);
+
+        // Go back to September 2008
+        final Calendar calendar = new GregorianCalendar();
+        calendar.set(Calendar.YEAR, 2008);
+        calendar.set(Calendar.MONTH, Calendar.SEPTEMBER);
+        calendar.set(Calendar.DAY_OF_MONTH, 16);
+        instrumentation.runOnMainSync(
+                () -> calendarView.setDate(calendar.getTime().getTime(), false, true));
+        instrumentation.waitForIdleSync();
+
+        // Get bounds of 09/23/2008
+        calendar.set(Calendar.DAY_OF_MONTH, 23);
+        final Rect dayBounds = new Rect();
+        final boolean getDayBoundsSuccess = calendarView.getBoundsForDate(
+                calendar.getTime().getTime(), dayBounds);
+        assertTrue(getDayBoundsSuccess);
+
+        if (onlyAllowOneChangeEvent) {
+            verifyZeroInteractions(mockDateChangeListener);
+        }
+
+        // Use instrumentation to emulate a tap on 09/23/2008
+        ViewTestUtils.emulateTapOnScreen(instrumentation, calendarView,
+                dayBounds.left + dayBounds.width() / 2,
+                dayBounds.top + dayBounds.height() / 2);
+
+        verify(mockDateChangeListener, times(1)).onSelectedDayChange(calendarView,
+                2008, Calendar.SEPTEMBER, 23);
+        if (onlyAllowOneChangeEvent) {
+            verifyNoMoreInteractions(mockDateChangeListener);
+        }
+    }
+
+    public void testOnDateChangeListenerHolo() {
+        // Scroll the Holo calendar view all the way up so it's fully visible
+        final ScrollView scroller = (ScrollView) mActivity.findViewById(R.id.scroller);
+        final ViewGroup container = (ViewGroup) scroller.findViewById(R.id.container);
+        final Instrumentation instrumentation = getInstrumentation();
+
+        instrumentation.runOnMainSync(() -> scroller.scrollTo(0, container.getHeight()));
+        // Note that in pre-Material world we are "allowing" the CalendarView to notify
+        // the date change listener on multiple occasions. This is the old behavior of the widget.
+        verifyOnDateChangeListener(mCalendarViewHolo, false);
+    }
+
+    public void testOnDateChangeListenerMaterial() {
+        // Note that in Material world only "real" date change events are allowed to be reported
+        // to our listener. This is the new behavior of the widget.
+        verifyOnDateChangeListener(mCalendarViewMaterial, true);
+    }
+
     public void testAppearanceMaterial() {
         // The logic in this method is performed on a Material-styled CalendarView and
         // non-deprecated attributes / visual appearance APIs
@@ -118,12 +191,12 @@
 
         // Change the visual appearance of the widget
         instrumentation.runOnMainSync(() -> {
-            mCalendarViewMaterial.setFirstDayOfWeek(3);
+            mCalendarViewMaterial.setFirstDayOfWeek(Calendar.TUESDAY);
             mCalendarViewMaterial.setDateTextAppearance(R.style.TextAppearance_WithColorBlue);
             mCalendarViewMaterial.setWeekDayTextAppearance(R.style.TextAppearance_WithColorMagenta);
         });
 
-        assertEquals(3, mCalendarViewMaterial.getFirstDayOfWeek());
+        assertEquals(Calendar.TUESDAY, mCalendarViewMaterial.getFirstDayOfWeek());
         assertEquals(R.style.TextAppearance_WithColorBlue,
                 mCalendarViewMaterial.getDateTextAppearance());
         assertEquals(R.style.TextAppearance_WithColorMagenta,
@@ -166,7 +239,7 @@
                 mActivity.getColor(R.color.calendarview_week_separatorline_new);
 
         instrumentation.runOnMainSync(() -> {
-            mCalendarViewHolo.setFirstDayOfWeek(1);
+            mCalendarViewHolo.setFirstDayOfWeek(Calendar.SUNDAY);
             mCalendarViewHolo.setShownWeekCount(4);
             mCalendarViewHolo.setShowWeekNumber(true);
             mCalendarViewHolo.setDateTextAppearance(R.style.TextAppearance_WithColorBlue);
@@ -178,7 +251,7 @@
             mCalendarViewHolo.setWeekSeparatorLineColor(newWeekSeparatorLineColor);
         });
 
-        assertEquals(1, mCalendarViewHolo.getFirstDayOfWeek());
+        assertEquals(Calendar.SUNDAY, mCalendarViewHolo.getFirstDayOfWeek());
         assertEquals(4, mCalendarViewHolo.getShownWeekCount());
         assertTrue(mCalendarViewHolo.getShowWeekNumber());
         assertEquals(R.style.TextAppearance_WithColorBlue,
diff --git a/tests/tests/widget/src/android/widget/cts/CheckBoxCtsActivity.java b/tests/tests/widget/src/android/widget/cts/CheckBoxCtsActivity.java
new file mode 100644
index 0000000..9ad0b23
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/CheckBoxCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.CheckBox;
+
+/**
+ * A minimal application for {@link CheckBox} test.
+ */
+public class CheckBoxCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.checkbox_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/CheckBoxTest.java b/tests/tests/widget/src/android/widget/cts/CheckBoxTest.java
index b3a6e67..346861e 100644
--- a/tests/tests/widget/src/android/widget/cts/CheckBoxTest.java
+++ b/tests/tests/widget/src/android/widget/cts/CheckBoxTest.java
@@ -16,24 +16,47 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-
-import android.test.AndroidTestCase;
-import android.util.AttributeSet;
-import android.util.Xml;
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.TextUtils;
 import android.widget.CheckBox;
+import android.widget.cts.util.ViewTestUtils;
 
-public class CheckBoxTest extends AndroidTestCase {
+import static org.mockito.Mockito.*;
+
+@SmallTest
+public class CheckBoxTest extends ActivityInstrumentationTestCase2<CheckBoxCtsActivity> {
+    private Instrumentation mInstrumentation;
+    private Activity mActivity;
+    private CheckBox mCheckBox;
+
+    public CheckBoxTest() {
+        super("android.widget.cts", CheckBoxCtsActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mInstrumentation = getInstrumentation();
+        mActivity = getActivity();
+        mCheckBox = (CheckBox) mActivity.findViewById(R.id.check_box);
+    }
+
     public void testConstructor() {
-        XmlPullParser parser = mContext.getResources().getXml(R.layout.checkbox_layout);
-        AttributeSet mAttrSet = Xml.asAttributeSet(parser);
-
-        new CheckBox(mContext, mAttrSet, 0);
-        new CheckBox(mContext, mAttrSet);
-        new CheckBox(mContext);
+        new CheckBox(mActivity);
+        new CheckBox(mActivity, null);
+        new CheckBox(mActivity, null, android.R.attr.checkboxStyle);
+        new CheckBox(mActivity, null, 0,
+                android.R.style.Widget_DeviceDefault_CompoundButton_CheckBox);
+        new CheckBox(mActivity, null, 0,
+                android.R.style.Widget_DeviceDefault_Light_CompoundButton_CheckBox);
+        new CheckBox(mActivity, null, 0,
+                android.R.style.Widget_Material_CompoundButton_CheckBox);
+        new CheckBox(mActivity, null, 0,
+                android.R.style.Widget_Material_Light_CompoundButton_CheckBox);
 
         try {
             new CheckBox(null, null, -1);
@@ -56,4 +79,109 @@
             // expected, test success.
         }
     }
+
+    public void testText() {
+        assertTrue(TextUtils.equals(
+                mActivity.getString(R.string.hello_world), mCheckBox.getText()));
+
+        mInstrumentation.runOnMainSync(() -> mCheckBox.setText("new text"));
+        assertTrue(TextUtils.equals("new text", mCheckBox.getText()));
+
+        mInstrumentation.runOnMainSync(() -> mCheckBox.setText(R.string.text_name));
+        assertTrue(TextUtils.equals(mActivity.getString(R.string.text_name), mCheckBox.getText()));
+    }
+
+    public void testAccessChecked() {
+        final CheckBox.OnCheckedChangeListener mockCheckedChangeListener =
+                mock(CheckBox.OnCheckedChangeListener.class);
+        mCheckBox.setOnCheckedChangeListener(mockCheckedChangeListener);
+        verifyZeroInteractions(mockCheckedChangeListener);
+
+        assertFalse(mCheckBox.isChecked());
+
+        // not checked -> not checked
+        mInstrumentation.runOnMainSync(() -> mCheckBox.setChecked(false));
+        verifyZeroInteractions(mockCheckedChangeListener);
+        assertFalse(mCheckBox.isChecked());
+
+        // not checked -> checked
+        mInstrumentation.runOnMainSync(() -> mCheckBox.setChecked(true));
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, true);
+        assertTrue(mCheckBox.isChecked());
+
+        // checked -> checked
+        mInstrumentation.runOnMainSync(() -> mCheckBox.setChecked(true));
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, true);
+        assertTrue(mCheckBox.isChecked());
+
+        // checked -> not checked
+        mInstrumentation.runOnMainSync(() -> mCheckBox.setChecked(false));
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, false);
+        assertFalse(mCheckBox.isChecked());
+
+        verifyNoMoreInteractions(mockCheckedChangeListener);
+    }
+
+    public void testToggleViaApi() {
+        final CheckBox.OnCheckedChangeListener mockCheckedChangeListener =
+                mock(CheckBox.OnCheckedChangeListener.class);
+        mCheckBox.setOnCheckedChangeListener(mockCheckedChangeListener);
+        verifyZeroInteractions(mockCheckedChangeListener);
+
+        assertFalse(mCheckBox.isChecked());
+
+        // toggle to checked
+        mInstrumentation.runOnMainSync(() -> mCheckBox.toggle());
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, true);
+        assertTrue(mCheckBox.isChecked());
+
+        // toggle to not checked
+        mInstrumentation.runOnMainSync(() -> mCheckBox.toggle());
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, false);
+        assertFalse(mCheckBox.isChecked());
+
+        verifyNoMoreInteractions(mockCheckedChangeListener);
+    }
+
+    public void testToggleViaEmulatedTap() {
+        final CheckBox.OnCheckedChangeListener mockCheckedChangeListener =
+                mock(CheckBox.OnCheckedChangeListener.class);
+        mCheckBox.setOnCheckedChangeListener(mockCheckedChangeListener);
+        verifyZeroInteractions(mockCheckedChangeListener);
+
+        assertFalse(mCheckBox.isChecked());
+
+        // tap to checked
+        ViewTestUtils.emulateTapOnViewCenter(mInstrumentation, mCheckBox);
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, true);
+        assertTrue(mCheckBox.isChecked());
+
+        // tap to not checked
+        ViewTestUtils.emulateTapOnViewCenter(mInstrumentation, mCheckBox);
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, false);
+        assertFalse(mCheckBox.isChecked());
+
+        verifyNoMoreInteractions(mockCheckedChangeListener);
+    }
+
+    public void testToggleViaPerformClick() {
+        final CheckBox.OnCheckedChangeListener mockCheckedChangeListener =
+                mock(CheckBox.OnCheckedChangeListener.class);
+        mCheckBox.setOnCheckedChangeListener(mockCheckedChangeListener);
+        verifyZeroInteractions(mockCheckedChangeListener);
+
+        assertFalse(mCheckBox.isChecked());
+
+        // click to checked
+        mInstrumentation.runOnMainSync(() -> mCheckBox.performClick());
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, true);
+        assertTrue(mCheckBox.isChecked());
+
+        // click to not checked
+        mInstrumentation.runOnMainSync(() -> mCheckBox.performClick());
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, false);
+        assertFalse(mCheckBox.isChecked());
+
+        verifyNoMoreInteractions(mockCheckedChangeListener);
+    }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/CheckedTextViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/CheckedTextViewCtsActivity.java
index 52bef54..066697a 100644
--- a/tests/tests/widget/src/android/widget/cts/CheckedTextViewCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/CheckedTextViewCtsActivity.java
@@ -16,13 +16,12 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
 import android.app.Activity;
 import android.os.Bundle;
+import android.widget.CheckedTextView;
 
 /**
- * A minimal application for CheckedTextView test.
+ * A minimal application for {@link CheckedTextView} test.
  */
 public class CheckedTextViewCtsActivity extends Activity {
     /**
diff --git a/tests/tests/widget/src/android/widget/cts/CheckedTextViewTest.java b/tests/tests/widget/src/android/widget/cts/CheckedTextViewTest.java
index 039ca70..6c9350a 100644
--- a/tests/tests/widget/src/android/widget/cts/CheckedTextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/CheckedTextViewTest.java
@@ -16,17 +16,17 @@
 
 package android.widget.cts;
 
-import android.os.Parcelable;
-import android.widget.cts.R;
-
-
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.content.Context;
-import android.content.res.Resources;
+import android.content.res.ColorStateList;
 import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
+import android.os.Parcelable;
 import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.util.AttributeSet;
 import android.util.StateSet;
 import android.view.View;
@@ -35,14 +35,19 @@
 import android.widget.CheckedTextView;
 import android.widget.ListAdapter;
 import android.widget.ListView;
+import android.widget.cts.util.TestUtils;
+import android.widget.cts.util.ViewTestUtils;
 
 import java.util.Arrays;
 
+@SmallTest
 public class CheckedTextViewTest extends
         ActivityInstrumentationTestCase2<CheckedTextViewCtsActivity> {
-    private Resources mResources;
-    private Activity mActivity;
     private Instrumentation mInstrumentation;
+    private Activity mActivity;
+    private ListView mListView;
+    private CheckedTextView mCheckedTextView;
+    private Parcelable mState;
 
     public CheckedTextViewTest() {
         super("android.widget.cts", CheckedTextViewCtsActivity.class);
@@ -51,32 +56,42 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mActivity = getActivity();
+
         mInstrumentation = getInstrumentation();
-        mResources = mActivity.getResources();
+        mActivity = getActivity();
+        mListView = (ListView) mActivity.findViewById(R.id.checkedtextview_listview);
+        mCheckedTextView = (CheckedTextView) mActivity.findViewById(R.id.checkedtextview_test);
     }
 
     public void testConstructor() {
-        new MockCheckedTextView(mActivity, null, 0);
-        new MockCheckedTextView(mActivity, null);
-        new MockCheckedTextView(mActivity);
+        new CheckedTextView(mActivity);
+        new CheckedTextView(mActivity, null);
+        new CheckedTextView(mActivity, null, android.R.attr.checkedTextViewStyle);
+        new CheckedTextView(mActivity, null, 0,
+                android.R.style.Widget_DeviceDefault_CheckedTextView);
+        new CheckedTextView(mActivity, null, 0,
+                android.R.style.Widget_DeviceDefault_Light_CheckedTextView);
+        new CheckedTextView(mActivity, null, 0,
+                android.R.style.Widget_Material_CheckedTextView);
+        new CheckedTextView(mActivity, null, 0,
+                android.R.style.Widget_Material_Light_CheckedTextView);
 
         try {
-            new MockCheckedTextView(null, null, -1);
+            new CheckedTextView(null, null, -1);
             fail("Should throw NullPointerException.");
         } catch (NullPointerException e) {
             // expected, test success.
         }
 
         try {
-            new MockCheckedTextView(null, null);
+            new CheckedTextView(null, null);
             fail("Should throw NullPointerException.");
         } catch (NullPointerException e) {
             // expected, test success.
         }
 
         try {
-            new MockCheckedTextView(null);
+            new CheckedTextView(null);
             fail("Should throw NullPointerException.");
         } catch (NullPointerException e) {
             // expected, test success.
@@ -84,35 +99,29 @@
     }
 
     public void testChecked() {
-        final ListView lv = (ListView) mActivity.findViewById(R.id.checkedtextview_listview);
+        mInstrumentation.runOnMainSync(() -> {
+            mListView.setAdapter(new CheckedTextViewAdapter());
 
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                lv.setAdapter(new CheckedTextViewAdapter());
-
-                lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
-                lv.setItemChecked(1, true);
-            }
+            mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+            mListView.setItemChecked(1, true);
         });
         mInstrumentation.waitForIdleSync();
 
-        assertEquals(1, lv.getCheckedItemPosition());
-        assertTrue(lv.isItemChecked(1));
-        assertFalse(lv.isItemChecked(0));
+        assertEquals(1, mListView.getCheckedItemPosition());
+        assertTrue(mListView.isItemChecked(1));
+        assertFalse(mListView.isItemChecked(0));
 
-        ListAdapter adapter = lv.getAdapter();
-        CheckedTextView view0 = (CheckedTextView) adapter.getView(0, null, null);
-        CheckedTextView view1 = (CheckedTextView) adapter.getView(1, null, null);
-        CheckedTextView view2 = (CheckedTextView) adapter.getView(2, null, null);
+        final ListAdapter adapter = mListView.getAdapter();
+        final CheckedTextView view0 = (CheckedTextView) adapter.getView(0, null, null);
+        final CheckedTextView view1 = (CheckedTextView) adapter.getView(1, null, null);
+        final CheckedTextView view2 = (CheckedTextView) adapter.getView(2, null, null);
         assertFalse(view0.isChecked());
         assertTrue(view1.isChecked());
         assertFalse(view2.isChecked());
 
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
-                lv.setItemChecked(2, true);
-            }
+        mInstrumentation.runOnMainSync(() -> {
+            mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
+            mListView.setItemChecked(2, true);
         });
         mInstrumentation.waitForIdleSync();
         assertFalse(view0.isChecked());
@@ -128,184 +137,219 @@
     }
 
     public void testToggle() {
-        CheckedTextView checkedTextView = new MockCheckedTextView(mActivity);
-        assertFalse(checkedTextView.isChecked());
+        assertFalse(mCheckedTextView.isChecked());
 
-        checkedTextView.toggle();
-        assertTrue(checkedTextView.isChecked());
+        mInstrumentation.runOnMainSync(() -> mCheckedTextView.toggle());
+        assertTrue(mCheckedTextView.isChecked());
 
-        checkedTextView.toggle();
-        assertFalse(checkedTextView.isChecked());
+        mInstrumentation.runOnMainSync(() -> mCheckedTextView.toggle());
+        assertFalse(mCheckedTextView.isChecked());
 
-        checkedTextView.setChecked(true);
-        checkedTextView.toggle();
-        assertFalse(checkedTextView.isChecked());
+        mInstrumentation.runOnMainSync(() -> {
+            mCheckedTextView.setChecked(true);
+            mCheckedTextView.toggle();
+        });
+        assertFalse(mCheckedTextView.isChecked());
     }
 
     public void testDrawableStateChanged() {
         MockCheckedTextView checkedTextView = new MockCheckedTextView(mActivity);
 
-        checkedTextView.reset();
         assertFalse(checkedTextView.hasDrawableStateChanged());
         checkedTextView.refreshDrawableState();
         assertTrue(checkedTextView.hasDrawableStateChanged());
     }
 
     public void testSetPadding() {
-        final CheckedTextView lv
-                = (CheckedTextView) mActivity.findViewById(R.id.checkedtextview_test);
-        assertNotNull(lv);
-
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                lv.setPadding(1, 2, 3, 4);
-                lv.requestLayout();
-            }
+        mInstrumentation.runOnMainSync(() -> {
+            mListView.setPadding(1, 2, 3, 4);
+            mListView.requestLayout();
         });
         mInstrumentation.waitForIdleSync();
-        int origTop = lv.getPaddingTop();
-        int origBottom = lv.getPaddingBottom();
-        int origLeft = lv.getPaddingLeft();
-        int origRight = lv.getPaddingRight();
 
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                lv.setPadding(10, 20, 30, 40);
-                lv.requestLayout();
-            }
+        final int origTop = mListView.getPaddingTop();
+        final int origBottom = mListView.getPaddingBottom();
+        final int origLeft = mListView.getPaddingLeft();
+        final int origRight = mListView.getPaddingRight();
+
+        mInstrumentation.runOnMainSync(() -> {
+            mListView.setPadding(10, 20, 30, 40);
+            mListView.requestLayout();
         });
         mInstrumentation.waitForIdleSync();
-        assertTrue(origTop < lv.getPaddingTop());
-        assertTrue(origBottom < lv.getPaddingBottom());
-        assertTrue(origLeft < lv.getPaddingLeft());
-        assertTrue(origRight < lv.getPaddingRight());
+
+        assertTrue(origTop < mListView.getPaddingTop());
+        assertTrue(origBottom < mListView.getPaddingBottom());
+        assertTrue(origLeft < mListView.getPaddingLeft());
+        assertTrue(origRight < mListView.getPaddingRight());
     }
 
     private void cleanUpForceLayoutFlags(View view) {
         if (view != null) {
-            view.layout(0, 0, 0, 0);
+            mInstrumentation.runOnMainSync(() -> view.layout(0, 0, 0, 0));
             assertFalse(view.isLayoutRequested());
         }
     }
 
     public void testSetCheckMarkDrawableByDrawable() {
-        CheckedTextView checkedTextView;
         int basePaddingRight = 10;
 
         // set drawable when checkedTextView is GONE
-        checkedTextView = new MockCheckedTextView(mActivity);
-        checkedTextView.setVisibility(View.GONE);
-        Drawable firstDrawable = mResources.getDrawable(R.drawable.scenery);
+        mInstrumentation.runOnMainSync(() -> mCheckedTextView.setVisibility(View.GONE));
+        final Drawable firstDrawable = mActivity.getDrawable(R.drawable.scenery);
         firstDrawable.setVisible(true, false);
         assertEquals(StateSet.WILD_CARD, firstDrawable.getState());
-        cleanUpForceLayoutFlags(checkedTextView);
+        cleanUpForceLayoutFlags(mCheckedTextView);
 
-        checkedTextView.setCheckMarkDrawable(firstDrawable);
-        assertEquals(firstDrawable.getIntrinsicWidth(), checkedTextView.getPaddingRight());
+        mInstrumentation.runOnMainSync(() -> mCheckedTextView.setCheckMarkDrawable(firstDrawable));
+        assertEquals(firstDrawable.getIntrinsicWidth(), mCheckedTextView.getPaddingRight());
         assertFalse(firstDrawable.isVisible());
-        assertTrue(Arrays.equals(checkedTextView.getDrawableState(), firstDrawable.getState()));
-        assertTrue(checkedTextView.isLayoutRequested());
+        assertTrue(Arrays.equals(mCheckedTextView.getDrawableState(), firstDrawable.getState()));
+        assertTrue(mCheckedTextView.isLayoutRequested());
+
+        mInstrumentation.runOnMainSync(() -> mCheckedTextView.setCheckMarkDrawable(null));
 
         // update drawable when checkedTextView is VISIBLE
-        checkedTextView = new MockCheckedTextView(mActivity);
-        checkedTextView.setVisibility(View.VISIBLE);
-        checkedTextView.setPadding(0, 0, basePaddingRight, 0);
-        Drawable secondDrawable = mResources.getDrawable(R.drawable.pass);
+        mInstrumentation.runOnMainSync(() -> {
+            mCheckedTextView.setVisibility(View.VISIBLE);
+            mCheckedTextView.setPadding(0, 0, basePaddingRight, 0);
+        });
+        final Drawable secondDrawable = mActivity.getDrawable(R.drawable.pass);
         secondDrawable.setVisible(true, false);
         assertEquals(StateSet.WILD_CARD, secondDrawable.getState());
-        cleanUpForceLayoutFlags(checkedTextView);
+        cleanUpForceLayoutFlags(mCheckedTextView);
 
-        checkedTextView.setCheckMarkDrawable(secondDrawable);
+        mInstrumentation.runOnMainSync(() -> mCheckedTextView.setCheckMarkDrawable(secondDrawable));
         assertEquals(secondDrawable.getIntrinsicWidth() + basePaddingRight,
-                checkedTextView.getPaddingRight());
+                mCheckedTextView.getPaddingRight());
         assertTrue(secondDrawable.isVisible());
-        assertTrue(Arrays.equals(checkedTextView.getDrawableState(), secondDrawable.getState()));
-        assertTrue(checkedTextView.isLayoutRequested());
+        assertTrue(Arrays.equals(mCheckedTextView.getDrawableState(), secondDrawable.getState()));
+        assertTrue(mCheckedTextView.isLayoutRequested());
 
-        cleanUpForceLayoutFlags(checkedTextView);
-        checkedTextView.setCheckMarkDrawable(null);
-        assertEquals(basePaddingRight, checkedTextView.getPaddingRight());
-        assertTrue(checkedTextView.isLayoutRequested());
+        cleanUpForceLayoutFlags(mCheckedTextView);
+        mInstrumentation.runOnMainSync(() -> mCheckedTextView.setCheckMarkDrawable(null));
+        assertEquals(basePaddingRight, mCheckedTextView.getPaddingRight());
+        assertTrue(mCheckedTextView.isLayoutRequested());
     }
 
     public void testSetCheckMarkDrawableById() {
-        CheckedTextView checkedTextView;
         int basePaddingRight = 10;
 
         // set drawable
-        checkedTextView = new MockCheckedTextView(mActivity);
-        checkedTextView.setPadding(0, 0, basePaddingRight, 0);
-        Drawable firstDrawable = mResources.getDrawable(R.drawable.scenery);
-        cleanUpForceLayoutFlags(checkedTextView);
+        mInstrumentation.runOnMainSync(
+                () -> mCheckedTextView.setPadding(0, 0, basePaddingRight, 0));
+        Drawable firstDrawable = mActivity.getDrawable(R.drawable.scenery);
+        cleanUpForceLayoutFlags(mCheckedTextView);
 
-        checkedTextView.setCheckMarkDrawable(R.drawable.scenery);
+        mInstrumentation.runOnMainSync(
+                () -> mCheckedTextView.setCheckMarkDrawable(R.drawable.scenery));
         assertEquals(firstDrawable.getIntrinsicWidth() + basePaddingRight,
-                checkedTextView.getPaddingRight());
-        assertTrue(checkedTextView.isLayoutRequested());
+                mCheckedTextView.getPaddingRight());
+        assertTrue(mCheckedTextView.isLayoutRequested());
 
         // set the same drawable again
-        cleanUpForceLayoutFlags(checkedTextView);
-        checkedTextView.setCheckMarkDrawable(R.drawable.scenery);
+        cleanUpForceLayoutFlags(mCheckedTextView);
+        mInstrumentation.runOnMainSync(
+                () -> mCheckedTextView.setCheckMarkDrawable(R.drawable.scenery));
         assertEquals(firstDrawable.getIntrinsicWidth() + basePaddingRight,
-                checkedTextView.getPaddingRight());
-        assertFalse(checkedTextView.isLayoutRequested());
+                mCheckedTextView.getPaddingRight());
+        assertFalse(mCheckedTextView.isLayoutRequested());
 
         // update drawable
-        Drawable secondDrawable = mResources.getDrawable(R.drawable.pass);
-        checkedTextView.setCheckMarkDrawable(secondDrawable);
+        final Drawable secondDrawable = mActivity.getDrawable(R.drawable.pass);
+        mInstrumentation.runOnMainSync(() -> mCheckedTextView.setCheckMarkDrawable(secondDrawable));
         assertEquals(secondDrawable.getIntrinsicWidth() + basePaddingRight,
-                checkedTextView.getPaddingRight());
-        assertTrue(checkedTextView.isLayoutRequested());
+                mCheckedTextView.getPaddingRight());
+        assertTrue(mCheckedTextView.isLayoutRequested());
+
+        mInstrumentation.runOnMainSync(() -> mCheckedTextView.setCheckMarkDrawable(null));
 
         // resId is 0
-        checkedTextView = new MockCheckedTextView(mActivity);
-        checkedTextView.setPadding(0, 0, basePaddingRight, 0);
-        cleanUpForceLayoutFlags(checkedTextView);
+        mInstrumentation.runOnMainSync(
+                () -> mCheckedTextView.setPadding(0, 0, basePaddingRight, 0));
+        cleanUpForceLayoutFlags(mCheckedTextView);
 
-        checkedTextView.setCheckMarkDrawable(0);
-        assertEquals(basePaddingRight, checkedTextView.getPaddingRight());
-        assertFalse(checkedTextView.isLayoutRequested());
+        mInstrumentation.runOnMainSync(() -> mCheckedTextView.setCheckMarkDrawable(0));
+        assertEquals(basePaddingRight, mCheckedTextView.getPaddingRight());
+        assertFalse(mCheckedTextView.isLayoutRequested());
     }
 
     public void testSetCheckMarkByMixedTypes() {
-        CheckedTextView checkedTextView = new MockCheckedTextView(mActivity);
-        cleanUpForceLayoutFlags(checkedTextView);
+        cleanUpForceLayoutFlags(mCheckedTextView);
 
         // Specifically test for b/22626247 (AOSP issue 180455).
-        checkedTextView.setCheckMarkDrawable(R.drawable.scenery);
-        checkedTextView.setCheckMarkDrawable(null);
-        checkedTextView.setCheckMarkDrawable(R.drawable.scenery);
-        assertNotNull(checkedTextView.getCheckMarkDrawable());
+        mInstrumentation.runOnMainSync(() -> {
+            mCheckedTextView.setCheckMarkDrawable(R.drawable.scenery);
+            mCheckedTextView.setCheckMarkDrawable(null);
+            mCheckedTextView.setCheckMarkDrawable(R.drawable.scenery);
+        });
+        assertNotNull(mCheckedTextView.getCheckMarkDrawable());
     }
 
     public void testAccessInstanceState() {
-        CheckedTextView checkedTextView = new MockCheckedTextView(mActivity);
-        Parcelable state;
+        assertFalse(mCheckedTextView.isChecked());
+        assertFalse(mCheckedTextView.getFreezesText());
 
-        assertFalse(checkedTextView.isChecked());
-        assertFalse(checkedTextView.getFreezesText());
+        mInstrumentation.runOnMainSync(() -> mState = mCheckedTextView.onSaveInstanceState());
+        assertNotNull(mState);
+        assertFalse(mCheckedTextView.getFreezesText());
 
-        state = checkedTextView.onSaveInstanceState();
-        assertNotNull(state);
-        assertFalse(checkedTextView.getFreezesText());
+        mInstrumentation.runOnMainSync(() -> mCheckedTextView.setChecked(true));
 
-        checkedTextView.setChecked(true);
-
-        checkedTextView.onRestoreInstanceState(state);
-        assertFalse(checkedTextView.isChecked());
-        assertTrue(checkedTextView.isLayoutRequested());
+        mInstrumentation.runOnMainSync(() -> mCheckedTextView.onRestoreInstanceState(mState));
+        assertFalse(mCheckedTextView.isChecked());
+        assertTrue(mCheckedTextView.isLayoutRequested());
     }
 
-    public void testOnDraw() {
-        // Do not test. Implementation details.
-    }
+    public void testCheckMarkTinting() {
+        mInstrumentation.runOnMainSync(() -> mCheckedTextView.setChecked(true));
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mCheckedTextView,
+                () -> mCheckedTextView.setCheckMarkDrawable(R.drawable.icon_red));
 
-    public void testOnCreateDrawableState() {
-        // Do not test. Implementation details.
+        Drawable checkMark = mCheckedTextView.getCheckMarkDrawable();
+        TestUtils.assertAllPixelsOfColor("Initial state is red", checkMark,
+                checkMark.getBounds().width(), checkMark.getBounds().height(), false,
+                Color.RED, 1, true);
+
+        // With SRC_IN we're expecting the translucent tint color to "take over" the
+        // original red checkmark.
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mCheckedTextView, () -> {
+            mCheckedTextView.setCheckMarkTintMode(PorterDuff.Mode.SRC_IN);
+            mCheckedTextView.setCheckMarkTintList(ColorStateList.valueOf(0x8000FF00));
+        });
+
+        assertEquals(PorterDuff.Mode.SRC_IN, mCheckedTextView.getCheckMarkTintMode());
+        assertEquals(0x8000FF00, mCheckedTextView.getCheckMarkTintList().getDefaultColor());
+        checkMark = mCheckedTextView.getCheckMarkDrawable();
+        TestUtils.assertAllPixelsOfColor("Expected 50% green", checkMark,
+                checkMark.getIntrinsicWidth(), checkMark.getIntrinsicHeight(), false,
+                0x8000FF00, 1, true);
+
+        // With SRC_OVER we're expecting the translucent tint color to be drawn on top
+        // of the original red checkmark, creating a composite color fill as the result.
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mCheckedTextView,
+                () -> mCheckedTextView.setCheckMarkTintMode(PorterDuff.Mode.SRC_OVER));
+
+        assertEquals(PorterDuff.Mode.SRC_OVER, mCheckedTextView.getCheckMarkTintMode());
+        assertEquals(0x8000FF00, mCheckedTextView.getCheckMarkTintList().getDefaultColor());
+        checkMark = mCheckedTextView.getCheckMarkDrawable();
+        TestUtils.assertAllPixelsOfColor("Expected 50% green over full red", checkMark,
+                checkMark.getIntrinsicWidth(), checkMark.getIntrinsicHeight(), false,
+                TestUtils.compositeColors(0x8000FF00, Color.RED), 1, true);
+
+        // Switch to a different color for the underlying checkmark and verify that the
+        // currently configured tinting (50% green overlay) is still respected
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mCheckedTextView,
+                () -> mCheckedTextView.setCheckMarkDrawable(R.drawable.icon_yellow));
+        assertEquals(PorterDuff.Mode.SRC_OVER, mCheckedTextView.getCheckMarkTintMode());
+        assertEquals(0x8000FF00, mCheckedTextView.getCheckMarkTintList().getDefaultColor());
+        checkMark = mCheckedTextView.getCheckMarkDrawable();
+        TestUtils.assertAllPixelsOfColor("Expected 50% green over full yellow", checkMark,
+                checkMark.getIntrinsicWidth(), checkMark.getIntrinsicHeight(), false,
+                TestUtils.compositeColors(0x8000FF00, Color.YELLOW), 1, true);
     }
 
     private static final class MockCheckedTextView extends CheckedTextView {
-        private boolean mHasRefreshDrawableState = false;
         private boolean mHasDrawableStateChanged = false;
 
         public MockCheckedTextView(Context context) {
@@ -320,10 +364,6 @@
             super(context, attrs, defStyle);
         }
 
-        public static int[] getSuperViewStateSet() {
-            return ENABLED_STATE_SET;
-        }
-
         @Override
         protected void drawableStateChanged() {
             super.drawableStateChanged();
@@ -340,24 +380,9 @@
             super.onDraw(canvas);
         }
 
-        @Override
-        public void refreshDrawableState() {
-            mHasRefreshDrawableState = true;
-            super.refreshDrawableState();
-        }
-
-        public boolean hasRefreshDrawableState() {
-            return mHasRefreshDrawableState;
-        }
-
         public boolean hasDrawableStateChanged() {
             return mHasDrawableStateChanged;
         }
-
-        public void reset() {
-            mHasRefreshDrawableState = false;
-            mHasDrawableStateChanged = false;
-        }
     }
 
     private class CheckedTextViewAdapter extends BaseAdapter {
diff --git a/tests/tests/widget/src/android/widget/cts/ChronometerTest.java b/tests/tests/widget/src/android/widget/cts/ChronometerTest.java
index ff1435f..4a66e25 100644
--- a/tests/tests/widget/src/android/widget/cts/ChronometerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ChronometerTest.java
@@ -16,17 +16,29 @@
 
 package android.widget.cts;
 
-
+import android.app.Instrumentation;
+import android.content.Context;
+import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.ContextThemeWrapper;
 import android.widget.Chronometer;
-import android.widget.Chronometer.OnChronometerTickListener;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.mockito.Mockito.*;
 
 /**
  * Test {@link Chronometer}.
  */
 public class ChronometerTest extends ActivityInstrumentationTestCase2<ChronometerCtsActivity> {
+    private Instrumentation mInstrumentation;
     private ChronometerCtsActivity mActivity;
+
     public ChronometerTest() {
         super("android.widget.cts", ChronometerCtsActivity.class);
     }
@@ -34,6 +46,8 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+
+        mInstrumentation = getInstrumentation();
         mActivity = getActivity();
     }
 
@@ -47,6 +61,22 @@
     }
 
     @UiThreadTest
+    public void testConstructorFromAttr() {
+        final Context context = new ContextThemeWrapper(mActivity, R.style.ChronometerAwareTheme);
+        final Chronometer chronometer = new Chronometer(context, null, R.attr.chronometerStyle);
+        assertTrue(chronometer.isCountDown());
+        assertEquals(mActivity.getString(R.string.chronometer_format), chronometer.getFormat());
+    }
+
+    @UiThreadTest
+    public void testConstructorFromStyle() {
+        final Chronometer chronometer = new Chronometer(mActivity, null, 0,
+                R.style.ChronometerStyle);
+        assertTrue(chronometer.isCountDown());
+        assertEquals(mActivity.getString(R.string.chronometer_format), chronometer.getFormat());
+    }
+
+    @UiThreadTest
     public void testAccessBase() {
         Chronometer chronometer = mActivity.getChronometer();
         CharSequence oldText = chronometer.getText();
@@ -89,79 +119,94 @@
         assertTrue(text.endsWith("trail"));
     }
 
-    public void testFoo() {
-        // Do not test these APIs. They are callbacks which:
-        // 1. The callback machanism has been tested in super class
-        // 2. The functionality is implmentation details, no need to test
-    }
-
-    public void testStartAndStop() throws Throwable {
+    public void testStartAndStop() {
         final Chronometer chronometer = mActivity.getChronometer();
 
         // we will check the text is really updated every 1000ms after start,
         // so we need sleep a moment to wait wait this time. The sleep code shouldn't
         // in the same thread with UI, that's why we use runOnMainSync here.
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                // the text will update immediately when call start.
-                CharSequence expected = chronometer.getText();
-                chronometer.start();
-                assertNotSame(expected, chronometer.getText());
-            }
+        mInstrumentation.runOnMainSync(() -> {
+            // the text will update immediately when call start.
+            final CharSequence valueBeforeStart = chronometer.getText();
+            chronometer.start();
+            assertNotSame(valueBeforeStart, chronometer.getText());
         });
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.waitForIdleSync();
+
         CharSequence expected = chronometer.getText();
-        Thread.sleep(1500);
+        SystemClock.sleep(1500);
         assertFalse(expected.equals(chronometer.getText()));
 
         // we will check the text is really NOT updated anymore every 1000ms after stop,
         // so we need sleep a moment to wait wait this time. The sleep code shouldn't
         // in the same thread with UI, that's why we use runOnMainSync here.
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                // the text will never be updated when call stop.
-                CharSequence expected = chronometer.getText();
-                chronometer.stop();
-                assertSame(expected, chronometer.getText());
-            }
+        mInstrumentation.runOnMainSync(() -> {
+            // the text will never be updated when call stop.
+            final CharSequence valueBeforeStop = chronometer.getText();
+            chronometer.stop();
+            assertSame(valueBeforeStop, chronometer.getText());
         });
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.waitForIdleSync();
+
         expected = chronometer.getText();
-        Thread.sleep(1500);
+        SystemClock.sleep(1500);
         assertTrue(expected.equals(chronometer.getText()));
     }
 
-    public void testAccessOnChronometerTickListener() throws Throwable {
+    public void testAccessOnChronometerTickListener() {
         final Chronometer chronometer = mActivity.getChronometer();
-        final MockOnChronometerTickListener listener = new MockOnChronometerTickListener();
+        final Chronometer.OnChronometerTickListener mockTickListener =
+                mock(Chronometer.OnChronometerTickListener.class);
 
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                chronometer.setOnChronometerTickListener(listener);
-                chronometer.start();
-            }
+        mInstrumentation.runOnMainSync(() -> {
+            chronometer.setOnChronometerTickListener(mockTickListener);
+            chronometer.start();
         });
-        getInstrumentation().waitForIdleSync();
-        assertEquals(listener, chronometer.getOnChronometerTickListener());
-        assertTrue(listener.hasCalledOnChronometerTick());
-        listener.reset();
-        Thread.sleep(1500);
-        assertTrue(listener.hasCalledOnChronometerTick());
+        mInstrumentation.waitForIdleSync();
+
+        assertEquals(mockTickListener, chronometer.getOnChronometerTickListener());
+        verify(mockTickListener, atLeastOnce()).onChronometerTick(chronometer);
+
+        reset(mockTickListener);
+        SystemClock.sleep(1500);
+        verify(mockTickListener, atLeastOnce()).onChronometerTick(chronometer);
     }
 
-    private static class MockOnChronometerTickListener implements OnChronometerTickListener {
-        private boolean mCalledOnChronometerTick = false;
+    @LargeTest
+    public void testCountDown() {
+        final Chronometer chronometer = mActivity.getChronometer();
+        final Chronometer.OnChronometerTickListener mockTickListener =
+                mock(Chronometer.OnChronometerTickListener.class);
 
-        public void onChronometerTick(Chronometer chronometer) {
-            mCalledOnChronometerTick = true;
-        }
+        mInstrumentation.runOnMainSync(() -> {
+            chronometer.setCountDown(true);
+            chronometer.setOnChronometerTickListener(mockTickListener);
+            chronometer.start();
+        });
+        mInstrumentation.waitForIdleSync();
 
-        public boolean hasCalledOnChronometerTick() {
-            return mCalledOnChronometerTick;
-        }
+        assertTrue(chronometer.isCountDown());
 
-        public void reset() {
-            mCalledOnChronometerTick = false;
-        }
+        SystemClock.sleep(5000);
+        verify(mockTickListener, atLeastOnce()).onChronometerTick(chronometer);
+    }
+
+    @LargeTest
+    public void testCountUp() {
+        final Chronometer chronometer = mActivity.getChronometer();
+        final Chronometer.OnChronometerTickListener mockTickListener =
+                mock(Chronometer.OnChronometerTickListener.class);
+
+        mInstrumentation.runOnMainSync(() -> {
+            chronometer.setCountDown(false);
+            chronometer.setOnChronometerTickListener(mockTickListener);
+            chronometer.start();
+        });
+        mInstrumentation.waitForIdleSync();
+
+        assertFalse(chronometer.isCountDown());
+
+        SystemClock.sleep(5000);
+        verify(mockTickListener, atLeastOnce()).onChronometerTick(chronometer);
     }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/CompoundButtonTest.java b/tests/tests/widget/src/android/widget/cts/CompoundButtonTest.java
index 34d94a5..67d3fa8 100644
--- a/tests/tests/widget/src/android/widget/cts/CompoundButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/CompoundButtonTest.java
@@ -16,21 +16,14 @@
 
 package android.widget.cts;
 
-import android.content.res.ColorStateList;
-import android.graphics.Color;
-import android.graphics.ColorFilter;
-import android.graphics.PorterDuff;
-import android.view.LayoutInflater;
-import android.widget.ToggleButton;
-import android.widget.cts.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
 import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Parcelable;
 import android.test.AndroidTestCase;
@@ -38,10 +31,17 @@
 import android.util.StateSet;
 import android.util.Xml;
 import android.view.Gravity;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.CompoundButton;
-import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.ToggleButton;
+import android.widget.cts.util.TestUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.*;
 
 /**
  * Test {@link CompoundButton}.
@@ -87,44 +87,42 @@
 
     public void testAccessChecked() {
         CompoundButton compoundButton = new MockCompoundButton(mContext);
-        MockOnCheckedChangeListener listener = new MockOnCheckedChangeListener();
-        compoundButton.setOnCheckedChangeListener(listener);
+        CompoundButton.OnCheckedChangeListener mockCheckedChangeListener =
+                mock(CompoundButton.OnCheckedChangeListener.class);
+        compoundButton.setOnCheckedChangeListener(mockCheckedChangeListener);
         assertFalse(compoundButton.isChecked());
-        assertFalse(listener.hasCalledCheckedChange());
+        verifyZeroInteractions(mockCheckedChangeListener);
 
         compoundButton.setChecked(true);
         assertTrue(compoundButton.isChecked());
-        assertTrue(listener.hasCalledCheckedChange());
-        assertSame(compoundButton, listener.getInputCompoundButton());
-        assertTrue(listener.getInputChecked());
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(compoundButton, true);
 
-        listener.reset();
+        reset(mockCheckedChangeListener);
         compoundButton.setChecked(true);
         assertTrue(compoundButton.isChecked());
-        assertFalse(listener.hasCalledCheckedChange());
+        verifyZeroInteractions(mockCheckedChangeListener);
 
         compoundButton.setChecked(false);
         assertFalse(compoundButton.isChecked());
-        assertTrue(listener.hasCalledCheckedChange());
-        assertSame(compoundButton, listener.getInputCompoundButton());
-        assertFalse(listener.getInputChecked());
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(compoundButton, false);
     }
 
     public void testSetOnCheckedChangeListener() {
         CompoundButton compoundButton = new MockCompoundButton(mContext);
-        MockOnCheckedChangeListener listener = new MockOnCheckedChangeListener();
-        compoundButton.setOnCheckedChangeListener(listener);
+        CompoundButton.OnCheckedChangeListener mockCheckedChangeListener =
+                mock(CompoundButton.OnCheckedChangeListener.class);
+        compoundButton.setOnCheckedChangeListener(mockCheckedChangeListener);
         assertFalse(compoundButton.isChecked());
-        assertFalse(listener.hasCalledCheckedChange());
+        verifyZeroInteractions(mockCheckedChangeListener);
 
         compoundButton.setChecked(true);
-        assertTrue(listener.hasCalledCheckedChange());
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(compoundButton, true);
 
         // set null
         compoundButton.setOnCheckedChangeListener(null);
-        listener.reset();
+        reset(mockCheckedChangeListener);
         compoundButton.setChecked(false);
-        assertFalse(listener.hasCalledCheckedChange());
+        verifyZeroInteractions(mockCheckedChangeListener);
     }
 
     public void testToggle() {
@@ -154,10 +152,7 @@
         assertFalse(compoundButton.isChecked());
 
         // performClick with OnClickListener will return true.
-        compoundButton.setOnClickListener(new OnClickListener() {
-            public void onClick(View v) {
-            }
-        });
+        compoundButton.setOnClickListener((view) -> {});
         assertTrue(compoundButton.performClick());
         assertTrue(compoundButton.isChecked());
 
@@ -340,53 +335,22 @@
         assertEquals("Button tint mode inflated correctly",
                 PorterDuff.Mode.SRC_OVER, inflatedView.getButtonTintMode());
 
-        MockDrawable button = new MockDrawable();
+        Drawable mockDrawable = spy(new ColorDrawable(Color.GREEN));
         CompoundButton view = new ToggleButton(mContext);
 
-        view.setButtonDrawable(button);
-        assertFalse("No button tint applied by default", button.hasCalledSetTint());
+        view.setButtonDrawable(mockDrawable);
+        // No button tint applied by default
+        verify(mockDrawable, never()).setTintList(any(ColorStateList.class));
 
         view.setButtonTintList(ColorStateList.valueOf(Color.WHITE));
-        assertTrue("Button tint applied when setButtonTintList() called after setButton()",
-                button.hasCalledSetTint());
+        // Button tint applied when setButtonTintList() called after setButton()
+        verify(mockDrawable, times(1)).setTintList(TestUtils.colorStateListOf(Color.WHITE));
 
-        button.reset();
+        reset(mockDrawable);
         view.setButtonDrawable(null);
-        view.setButtonDrawable(button);
-        assertTrue("Button tint applied when setButtonTintList() called before setButton()",
-                button.hasCalledSetTint());
-    }
-
-    private static class MockDrawable extends Drawable {
-        private boolean mCalledSetTint = false;
-
-        @Override
-        public void draw(Canvas canvas) {}
-
-        @Override
-        public void setAlpha(int alpha) {}
-
-        @Override
-        public void setColorFilter(ColorFilter cf) {}
-
-        @Override
-        public void setTintList(ColorStateList tint) {
-            super.setTintList(tint);
-            mCalledSetTint = true;
-        }
-
-        @Override
-        public int getOpacity() {
-            return 0;
-        }
-
-        public boolean hasCalledSetTint() {
-            return mCalledSetTint;
-        }
-
-        public void reset() {
-            mCalledSetTint = false;
-        }
+        view.setButtonDrawable(mockDrawable);
+        // Button tint applied when setButtonTintList() called before setButton()
+        verify(mockDrawable, times(1)).setTintList(TestUtils.colorStateListOf(Color.WHITE));
     }
 
     private final class MockCompoundButton extends CompoundButton {
@@ -422,34 +386,4 @@
             return super.verifyDrawable(who);
         }
     }
-
-    private final class MockOnCheckedChangeListener implements OnCheckedChangeListener {
-        private boolean mHasCalledChecked;
-        private CompoundButton mCompoundButton;
-        private boolean mIsChecked;
-
-        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
-            mHasCalledChecked = true;
-            mCompoundButton = buttonView;
-            mIsChecked = isChecked;
-        }
-
-        public boolean getInputChecked() {
-            return mIsChecked;
-        }
-
-        public CompoundButton getInputCompoundButton() {
-            return mCompoundButton;
-        }
-
-        public boolean hasCalledCheckedChange() {
-            return mHasCalledChecked;
-        }
-
-        public void reset() {
-            mHasCalledChecked = false;
-            mCompoundButton = null;
-            mIsChecked = false;
-        }
-    }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/CursorTreeAdapterTest.java b/tests/tests/widget/src/android/widget/cts/CursorTreeAdapterTest.java
index 8ef414d..0df58ff 100644
--- a/tests/tests/widget/src/android/widget/cts/CursorTreeAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/CursorTreeAdapterTest.java
@@ -34,6 +34,8 @@
 
 import android.widget.cts.R;
 
+import static org.mockito.Mockito.*;
+
 
 /**
  * Test {@link CursorTreeAdapter}.
@@ -199,23 +201,23 @@
     @UiThreadTest
     public void testNotifyDataSetChangedBoolean() {
         MockCursorTreeAdapter adapter = new MockCursorTreeAdapter(mGroupCursor, mContext);
-        MockDataSetObserver observer = new MockDataSetObserver();
-        adapter.registerDataSetObserver(observer);
+        DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
+        adapter.registerDataSetObserver(mockDataSetObserver);
 
         // mChildrenCursorHelpers is empty
-        assertFalse(observer.hasCalledOnChanged());
+        verifyZeroInteractions(mockDataSetObserver);
         adapter.notifyDataSetChanged(false);
-        assertTrue(observer.hasCalledOnChanged());
+        verify(mockDataSetObserver, times(1)).onChanged();
 
         // add group 0 into mChildrenCursorHelpers
         adapter.getChild(0, 0);
         // add group 1 into mChildrenCursorHelpers
         adapter.getChild(1, 0);
-        observer.reset();
-        assertFalse(observer.hasCalledOnChanged());
+        reset(mockDataSetObserver);
+        verifyZeroInteractions(mockDataSetObserver);
 
         adapter.notifyDataSetChanged(true);
-        assertTrue(observer.hasCalledOnChanged());
+        verify(mockDataSetObserver, times(1)).onChanged();
         adapter.reset();
         adapter.getChild(0, 0);
         assertTrue(adapter.hasAddedChild1IntoCache());
@@ -223,11 +225,11 @@
         assertTrue(adapter.hasAddedChild2IntoCache());
 
         // both group 0 and group 1 are in mChildrenCursorHelpers
-        observer.reset();
-        assertFalse(observer.hasCalledOnChanged());
+        reset(mockDataSetObserver);
+        verifyZeroInteractions(mockDataSetObserver);
         // does not release cursors
         adapter.notifyDataSetChanged(false);
-        assertTrue(observer.hasCalledOnChanged());
+        verify(mockDataSetObserver, times(1)).onChanged();
         adapter.reset();
         adapter.getChild(0, 0);
         assertFalse(adapter.hasAddedChild1IntoCache());
@@ -238,22 +240,22 @@
     @UiThreadTest
     public void testNotifyDataSetChanged() {
         MockCursorTreeAdapter adapter = new MockCursorTreeAdapter(mGroupCursor, mContext);
-        MockDataSetObserver observer = new MockDataSetObserver();
-        adapter.registerDataSetObserver(observer);
+        DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
+        adapter.registerDataSetObserver(mockDataSetObserver);
 
         // mChildrenCursorHelpers is empty
-        assertFalse(observer.hasCalledOnChanged());
+        verifyZeroInteractions(mockDataSetObserver);
         adapter.notifyDataSetChanged();
-        assertTrue(observer.hasCalledOnChanged());
+        verify(mockDataSetObserver, times(1)).onChanged();
 
         // add group 0 into mChildrenCursorHelpers
         adapter.getChild(0, 0);
         // add group 1 into mChildrenCursorHelpers
         adapter.getChild(1, 0);
-        observer.reset();
-        assertFalse(observer.hasCalledOnChanged());
+        reset(mockDataSetObserver);
+        verifyZeroInteractions(mockDataSetObserver);
         adapter.notifyDataSetChanged();
-        assertTrue(observer.hasCalledOnChanged());
+        verify(mockDataSetObserver, times(1)).onChanged();
         adapter.reset();
         adapter.getChild(0, 0);
         assertTrue(adapter.hasAddedChild1IntoCache());
@@ -264,22 +266,22 @@
     @UiThreadTest
     public void testNotifyDataSetInvalidated() {
         MockCursorTreeAdapter adapter = new MockCursorTreeAdapter(mGroupCursor, mContext);
-        MockDataSetObserver observer = new MockDataSetObserver();
-        adapter.registerDataSetObserver(observer);
+        DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
+        adapter.registerDataSetObserver(mockDataSetObserver);
 
-        assertFalse(observer.hasCalledOnInvalidated());
+        verifyZeroInteractions(mockDataSetObserver);
         // mChildrenCursorHelpers is empty
         adapter.notifyDataSetInvalidated();
-        assertTrue(observer.hasCalledOnInvalidated());
+        verify(mockDataSetObserver, times(1)).onInvalidated();
 
         // add group 0 into mChildrenCursorHelpers
         adapter.getChild(0, 0);
         // add group 1 into mChildrenCursorHelpers
         adapter.getChild(1, 0);
-        observer.reset();
-        assertFalse(observer.hasCalledOnInvalidated());
+        reset(mockDataSetObserver);
+        verifyZeroInteractions(mockDataSetObserver);
         adapter.notifyDataSetInvalidated();
-        assertTrue(observer.hasCalledOnInvalidated());
+        verify(mockDataSetObserver, times(1)).onInvalidated();
         adapter.reset();
         adapter.getChild(0, 0);
         assertTrue(adapter.hasAddedChild1IntoCache());
@@ -707,34 +709,4 @@
             return null;
         }
     }
-
-    private final class MockDataSetObserver extends DataSetObserver {
-        private boolean mHasCalledOnChanged = false;
-        private boolean mHasCalledOnInvalidated = false;
-
-        @Override
-        public void onChanged() {
-            super.onChanged();
-            mHasCalledOnChanged = true;
-        }
-
-        @Override
-        public void onInvalidated() {
-            super.onInvalidated();
-            mHasCalledOnInvalidated = true;
-        }
-
-        public boolean hasCalledOnChanged() {
-            return mHasCalledOnChanged;
-        }
-
-        public boolean hasCalledOnInvalidated() {
-            return mHasCalledOnInvalidated;
-        }
-
-        public void reset() {
-            mHasCalledOnChanged = false;
-            mHasCalledOnInvalidated = false;
-        }
-    }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/DatePickerCtsActivity.java b/tests/tests/widget/src/android/widget/cts/DatePickerCtsActivity.java
new file mode 100644
index 0000000..81e6e69
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/DatePickerCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.DatePicker;
+
+/**
+ * A minimal application for {@link DatePicker} test.
+ */
+public class DatePickerCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.datepicker_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/DatePickerDialogTest.java b/tests/tests/widget/src/android/widget/cts/DatePickerDialogTest.java
index 1477f73..c8e888d 100644
--- a/tests/tests/widget/src/android/widget/cts/DatePickerDialogTest.java
+++ b/tests/tests/widget/src/android/widget/cts/DatePickerDialogTest.java
@@ -77,14 +77,7 @@
         assertFalse("Date picker still dismissed", d.isShowing());
     }
 
-    private MockDatePickerDialog createDatePickerDialog() {
-        return new MockDatePickerDialog(mActivity, null, 1970, 1, 1);
-    }
-
-    private class MockDatePickerDialog extends DatePickerDialog {
-        public MockDatePickerDialog(Context context, OnDateSetListener callBack,
-                int year, int monthOfYear, int dayOfMonth) {
-            super(context, callBack, year, monthOfYear, dayOfMonth);
-        }
+    private DatePickerDialog createDatePickerDialog() {
+        return new DatePickerDialog(mActivity, null, 1970, 1, 1);
     }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/DatePickerTest.java b/tests/tests/widget/src/android/widget/cts/DatePickerTest.java
index c48f684..097cbe2 100644
--- a/tests/tests/widget/src/android/widget/cts/DatePickerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/DatePickerTest.java
@@ -16,120 +16,258 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
+import android.app.Activity;
+import android.app.Instrumentation;
 import android.content.Context;
-import android.content.res.XmlResourceParser;
 import android.os.Parcelable;
-import android.test.InstrumentationTestCase;
+import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
-import android.util.AttributeSet;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.util.SparseArray;
-import android.util.Xml;
 import android.view.View;
 import android.widget.DatePicker;
-import android.widget.cts.util.XmlUtils;
+
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+
+import static org.mockito.Mockito.*;
 
 /**
  * Test {@link DatePicker}.
  */
-public class DatePickerTest extends InstrumentationTestCase {
+@MediumTest
+public class DatePickerTest extends ActivityInstrumentationTestCase2<DatePickerCtsActivity> {
+    private Activity mActivity;
+    private DatePicker mDatePickerSpinnerMode;
+    private DatePicker mDatePickerCalendarMode;
 
-    private Context mContext;
+    public DatePickerTest() {
+        super("android.widget.cts", DatePickerCtsActivity.class);
+    }
 
     @Override
-    public void setUp() {
-        mContext = getInstrumentation().getTargetContext();
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+        mDatePickerSpinnerMode = (DatePicker) mActivity.findViewById(R.id.date_picker_spinner_mode);
+        mDatePickerCalendarMode =
+                (DatePicker) mActivity.findViewById(R.id.date_picker_calendar_mode);
     }
 
-    @UiThreadTest
     public void testConstructor() {
-        new DatePicker(mContext);
+        new DatePicker(mActivity);
 
-        new DatePicker(mContext, null);
+        new DatePicker(mActivity, null);
 
-        new DatePicker(mContext, getAttributeSet(R.layout.datepicker_layout));
+        new DatePicker(mActivity, null, android.R.attr.datePickerStyle);
 
-        new DatePicker(mContext, getAttributeSet(R.layout.datepicker_layout), 0);
+        new DatePicker(mActivity, null, 0, android.R.style.Widget_DeviceDefault_DatePicker);
 
-        // Test constructor with null Context, in fact, previous two functions will finally invoke
-        // this version.
-        try {
-            // Test with null Context
-            new DatePicker(null, getAttributeSet(R.layout.datepicker_layout), 0);
-            fail("should throw NullPointerException");
-        } catch (Exception e) {
-        }
+        new DatePicker(mActivity, null, 0, android.R.style.Widget_Material_DatePicker);
+
+        new DatePicker(mActivity, null, 0, android.R.style.Widget_Material_Light_DatePicker);
     }
 
-    @UiThreadTest
     public void testSetEnabled() {
-        MockDatePicker datePicker = createDatePicker();
+        final Instrumentation instrumentation = getInstrumentation();
 
-        assertTrue(datePicker.isEnabled());
+        assertTrue(mDatePickerCalendarMode.isEnabled());
 
-        datePicker.setEnabled(false);
-        assertFalse(datePicker.isEnabled());
+        instrumentation.runOnMainSync(() -> mDatePickerCalendarMode.setEnabled(false));
+        assertFalse(mDatePickerCalendarMode.isEnabled());
 
-        datePicker.setEnabled(true);
-        assertTrue(datePicker.isEnabled());
+        instrumentation.runOnMainSync(() -> mDatePickerCalendarMode.setEnabled(true));
+        assertTrue(mDatePickerCalendarMode.isEnabled());
     }
 
-    @UiThreadTest
+    private void verifyInit(DatePicker datePicker) {
+        final Instrumentation instrumentation = getInstrumentation();
+        final DatePicker.OnDateChangedListener mockDateChangeListener =
+                mock(DatePicker.OnDateChangedListener.class);
+
+        instrumentation.runOnMainSync(
+                () -> datePicker.init(2000, 10, 15, mockDateChangeListener));
+        assertEquals(2000, datePicker.getYear());
+        assertEquals(10, datePicker.getMonth());
+        assertEquals(15, datePicker.getDayOfMonth());
+
+        verifyZeroInteractions(mockDateChangeListener);
+    }
+
     public void testInit() {
-        MockOnDateChangedListener onDateChangedListener = new MockOnDateChangedListener();
-        DatePicker datePicker = createDatePicker();
+        verifyInit(mDatePickerSpinnerMode);
+        verifyInit(mDatePickerCalendarMode);
+    }
 
-        /* The month display uses 1-12 but our internal state stores it
-         * 0-11 so add one when setting the display.
-         */
-        datePicker.init(2000, 10, 15, onDateChangedListener);
+    private void verifyAccessDate(DatePicker datePicker) {
+        final Instrumentation instrumentation = getInstrumentation();
+        final DatePicker.OnDateChangedListener mockDateChangeListener =
+                mock(DatePicker.OnDateChangedListener.class);
+
+        instrumentation.runOnMainSync(() -> datePicker.init(2000, 10, 15, mockDateChangeListener));
         assertEquals(2000, datePicker.getYear());
         assertEquals(10, datePicker.getMonth());
         assertEquals(15, datePicker.getDayOfMonth());
+        verify(mockDateChangeListener, never()).onDateChanged(any(DatePicker.class), anyInt(),
+                anyInt(), anyInt());
+
+        instrumentation.runOnMainSync(() -> datePicker.updateDate(1989, 9, 19));
+        assertEquals(1989, datePicker.getYear());
+        assertEquals(9, datePicker.getMonth());
+        assertEquals(19, datePicker.getDayOfMonth());
+        verify(mockDateChangeListener, times(1)).onDateChanged(datePicker, 1989, 9, 19);
+
+        verifyNoMoreInteractions(mockDateChangeListener);
     }
 
-    @UiThreadTest
     public void testAccessDate() {
-        DatePicker datePicker = createDatePicker();
+        verifyAccessDate(mDatePickerSpinnerMode);
+        verifyAccessDate(mDatePickerCalendarMode);
+    }
 
-        /* The month display uses 1-12 but our internal state stores it
-         * 0-11 so add one when setting the display.
-         */
-        MockOnDateChangedListener onDateChangedListener = new MockOnDateChangedListener();
-        datePicker.init(2000, 10, 15, onDateChangedListener);
+    private void verifySetOnDateChangedListener(DatePicker datePicker) {
+        final Instrumentation instrumentation = getInstrumentation();
+        final DatePicker.OnDateChangedListener mockDateChangeListener1 =
+                mock(DatePicker.OnDateChangedListener.class);
+        final DatePicker.OnDateChangedListener mockDateChangeListener2 =
+                mock(DatePicker.OnDateChangedListener.class);
+
+        instrumentation.runOnMainSync(() -> datePicker.init(2000, 10, 15, mockDateChangeListener1));
+        instrumentation.runOnMainSync(() -> datePicker.updateDate(1989, 9, 19));
+        assertEquals(1989, datePicker.getYear());
+        assertEquals(9, datePicker.getMonth());
+        assertEquals(19, datePicker.getDayOfMonth());
+        verify(mockDateChangeListener1, times(1)).onDateChanged(datePicker, 1989, 9, 19);
+        verify(mockDateChangeListener2, times(0)).onDateChanged(datePicker, 1989, 9, 19);
+
+        instrumentation.runOnMainSync(() -> datePicker.setOnDateChangedListener(
+                mockDateChangeListener2));
+        instrumentation.runOnMainSync(() -> datePicker.updateDate(2000, 10, 15));
         assertEquals(2000, datePicker.getYear());
         assertEquals(10, datePicker.getMonth());
         assertEquals(15, datePicker.getDayOfMonth());
+        verify(mockDateChangeListener1, times(0)).onDateChanged(datePicker, 2000, 10, 15);
+        verify(mockDateChangeListener2, times(1)).onDateChanged(datePicker, 2000, 10, 15);
 
-        datePicker.updateDate(1989, 9, 19);
+    }
+
+    public void testSetOnDateChangedListener() {
+        verifySetOnDateChangedListener(mDatePickerSpinnerMode);
+        verifySetOnDateChangedListener(mDatePickerCalendarMode);
+    }
+
+    private void verifyUpdateDate(DatePicker datePicker) {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        instrumentation.runOnMainSync(() -> datePicker.updateDate(1989, 9, 19));
         assertEquals(1989, datePicker.getYear());
         assertEquals(9, datePicker.getMonth());
         assertEquals(19, datePicker.getDayOfMonth());
     }
 
-    @UiThreadTest
     public void testUpdateDate() {
-        DatePicker datePicker = createDatePicker();
+        verifyUpdateDate(mDatePickerSpinnerMode);
+        verifyUpdateDate(mDatePickerCalendarMode);
+    }
 
-        // Test normal input values
-        /* The month display uses 1-12 but our internal state stores it
-         * 0-11 so add one when setting the display.
-         */
-        datePicker.updateDate(1989, 9, 19);
-        assertEquals(1989, datePicker.getYear());
-        assertEquals(9, datePicker.getMonth());
-        assertEquals(19, datePicker.getDayOfMonth());
+    private void verifyMinMaxDate(DatePicker datePicker) {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        // Use a range of minus/plus one year as min/max dates
+        final Calendar minCalendar = new GregorianCalendar();
+        minCalendar.set(Calendar.YEAR, minCalendar.get(Calendar.YEAR) - 1);
+        final Calendar maxCalendar = new GregorianCalendar();
+        maxCalendar.set(Calendar.YEAR, maxCalendar.get(Calendar.YEAR) + 1);
+
+        final long minDate = minCalendar.getTime().getTime();
+        final long maxDate = maxCalendar.getTime().getTime();
+
+        instrumentation.runOnMainSync(() -> {
+            datePicker.setMinDate(minDate);
+            datePicker.setMaxDate(maxDate);
+        });
+
+        assertEquals(datePicker.getMinDate(), minDate);
+        assertEquals(datePicker.getMaxDate(), maxDate);
+    }
+
+    public void testMinMaxDate() {
+        verifyMinMaxDate(mDatePickerSpinnerMode);
+        verifyMinMaxDate(mDatePickerCalendarMode);
+    }
+
+    private void verifyFirstDayOfWeek(DatePicker datePicker) {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        instrumentation.runOnMainSync(() -> datePicker.setFirstDayOfWeek(Calendar.TUESDAY));
+        assertEquals(Calendar.TUESDAY, datePicker.getFirstDayOfWeek());
+
+        instrumentation.runOnMainSync(() -> datePicker.setFirstDayOfWeek(Calendar.SUNDAY));
+        assertEquals(Calendar.SUNDAY, datePicker.getFirstDayOfWeek());
+    }
+
+    public void testFirstDayOfWeek() {
+        verifyFirstDayOfWeek(mDatePickerSpinnerMode);
+        verifyFirstDayOfWeek(mDatePickerCalendarMode);
+    }
+
+    public void testCalendarViewInSpinnerMode() {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        assertNotNull(mDatePickerSpinnerMode.getCalendarView());
+
+        // Update the DatePicker and test that its CalendarView is synced to the same date
+        final Calendar calendar = new GregorianCalendar();
+        calendar.set(Calendar.YEAR, 2008);
+        calendar.set(Calendar.MONTH, Calendar.SEPTEMBER);
+        calendar.set(Calendar.DAY_OF_MONTH, 23);
+        instrumentation.runOnMainSync(
+                () -> mDatePickerSpinnerMode.updateDate(
+                        calendar.get(Calendar.YEAR),
+                        calendar.get(Calendar.MONTH),
+                        calendar.get(Calendar.DAY_OF_MONTH)));
+
+        final Calendar calendarFromSpinner = new GregorianCalendar();
+        final long timeFromSpinnerCalendar = mDatePickerSpinnerMode.getCalendarView().getDate();
+        calendarFromSpinner.setTimeInMillis(timeFromSpinnerCalendar);
+
+        assertEquals(calendar.get(Calendar.YEAR), calendarFromSpinner.get(Calendar.YEAR));
+        assertEquals(calendar.get(Calendar.MONTH), calendarFromSpinner.get(Calendar.MONTH));
+        assertEquals(calendar.get(Calendar.DAY_OF_MONTH),
+                calendarFromSpinner.get(Calendar.DAY_OF_MONTH));
+    }
+
+    public void testPartsVisibilityInSpinnerMode() {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        assertTrue(mDatePickerSpinnerMode.getSpinnersShown());
+        assertTrue(mDatePickerSpinnerMode.getCalendarViewShown());
+
+        instrumentation.runOnMainSync(() -> mDatePickerSpinnerMode.setSpinnersShown(false));
+        assertFalse(mDatePickerSpinnerMode.getSpinnersShown());
+        assertTrue(mDatePickerSpinnerMode.getCalendarViewShown());
+
+        instrumentation.runOnMainSync(() -> mDatePickerSpinnerMode.setCalendarViewShown(false));
+        assertFalse(mDatePickerSpinnerMode.getSpinnersShown());
+        assertFalse(mDatePickerSpinnerMode.getCalendarViewShown());
+
+        instrumentation.runOnMainSync(() -> mDatePickerSpinnerMode.setSpinnersShown(true));
+        assertTrue(mDatePickerSpinnerMode.getSpinnersShown());
+        assertFalse(mDatePickerSpinnerMode.getCalendarViewShown());
+
+        instrumentation.runOnMainSync(() -> mDatePickerSpinnerMode.setCalendarViewShown(true));
+        assertTrue(mDatePickerSpinnerMode.getSpinnersShown());
+        assertTrue(mDatePickerSpinnerMode.getCalendarViewShown());
     }
 
     @UiThreadTest
-    public void testOnSaveInstanceState() {
-        MockDatePicker datePicker = createDatePicker();
+    public void testAccessInstanceState() {
+        MockDatePicker datePicker = new MockDatePicker(mActivity);
 
         datePicker.updateDate(2008, 9, 10);
         SparseArray<Parcelable> container = new SparseArray<Parcelable>();
 
-        // Test onSaveHierarchyState
+        // Test saveHierarchyState -> onSaveInstanceState path
         assertEquals(View.NO_ID, datePicker.getId());
         datePicker.setId(99);
         assertFalse(datePicker.hasCalledOnSaveInstanceState());
@@ -137,43 +275,23 @@
         assertEquals(1, datePicker.getChildCount());
         assertTrue(datePicker.hasCalledOnSaveInstanceState());
 
-        // Test dispatchRestoreInstanceState
-        datePicker = createDatePicker();
+        // Test dispatchRestoreInstanceState -> onRestoreInstanceState path
+        datePicker = new MockDatePicker(mActivity);
         datePicker.setId(99);
         assertFalse(datePicker.hasCalledOnRestoreInstanceState());
         datePicker.dispatchRestoreInstanceState(container);
         assertEquals(2008, datePicker.getYear());
         assertEquals(9, datePicker.getMonth());
         assertEquals(10, datePicker.getDayOfMonth());
-
-        // Test onRestoreInstanceState
         assertTrue(datePicker.hasCalledOnRestoreInstanceState());
     }
 
-    private AttributeSet getAttributeSet(int resourceId) {
-        final XmlResourceParser parser = mContext.getResources().getXml(resourceId);
-        try {
-            XmlUtils.beginDocument(parser, "RelativeLayout");
-        } catch (Exception e) {
-            fail("Found unexpected loading process error before invoking generateLayoutParams.");
-        }
-        final AttributeSet attr = Xml.asAttributeSet(parser);
-        assertNotNull(attr);
-        return attr;
-    }
-
-    private MockDatePicker createDatePicker() {
-        MockDatePicker datePicker = new MockDatePicker(mContext,
-                getAttributeSet(R.layout.datepicker_layout));
-        return datePicker;
-    }
-
     private class MockDatePicker extends DatePicker {
         private boolean mCalledOnSaveInstanceState = false;
         private boolean mCalledOnRestoreInstanceState = false;
 
-        public MockDatePicker(Context context, AttributeSet attrs) {
-            super(context, attrs);
+        public MockDatePicker(Context context) {
+            super(context);
         }
 
         @Override
@@ -201,10 +319,4 @@
             return mCalledOnRestoreInstanceState;
         }
     }
-
-    private class MockOnDateChangedListener implements DatePicker.OnDateChangedListener {
-        public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
-
-        }
-    }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/DialerFilterTest.java b/tests/tests/widget/src/android/widget/cts/DialerFilterTest.java
index a99f56a..8616448 100644
--- a/tests/tests/widget/src/android/widget/cts/DialerFilterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/DialerFilterTest.java
@@ -53,12 +53,7 @@
         super.setUp();
 
         mActivity = getActivity();
-        new PollingCheck() {
-            @Override
-                protected boolean check() {
-                return mActivity.hasWindowFocus();
-            }
-        }.run();
+        PollingCheck.waitFor(() -> mActivity.hasWindowFocus());
         mInstrumentation = getInstrumentation();
 
         mDialerFilter = (DialerFilter) mActivity.findViewById(R.id.dialer_filter);
diff --git a/tests/tests/widget/src/android/widget/cts/ExpandableList.java b/tests/tests/widget/src/android/widget/cts/ExpandableList.java
new file mode 100644
index 0000000..48fa5e9
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ExpandableList.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.cts;
+
+import android.widget.ExpandableListAdapter;
+
+public class ExpandableList extends ExpandableListBasic {
+    @Override
+    protected ExpandableListAdapter createAdapter() {
+        return null;
+    }
+
+    @Override
+    protected boolean shouldRegisterItemClickListener() {
+        return false;
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/ExpandableListSimple.java b/tests/tests/widget/src/android/widget/cts/ExpandableListBasic.java
similarity index 71%
rename from tests/tests/widget/src/android/widget/cts/ExpandableListSimple.java
rename to tests/tests/widget/src/android/widget/cts/ExpandableListBasic.java
index f2e87ee7..52bb0a06 100644
--- a/tests/tests/widget/src/android/widget/cts/ExpandableListSimple.java
+++ b/tests/tests/widget/src/android/widget/cts/ExpandableListBasic.java
@@ -22,22 +22,22 @@
 import android.widget.BaseExpandableListAdapter;
 import android.widget.cts.util.ExpandableListScenario;
 
-public class ExpandableListSimple extends ExpandableListScenario {
-    private static final int[] NUM_CHILDREN = {4, 3, 2, 1, 0};
+public class ExpandableListBasic extends ExpandableListScenario {
+    private static final int[] CHILD_COUNT = {4, 3, 2, 1, 0};
 
     @Override
     protected void init(ExpandableParams params) {
-        params.setNumChildren(NUM_CHILDREN).setItemScreenSizeFactor(0.14);
+        params.setNumChildren(CHILD_COUNT).setItemScreenSizeFactor(0.14);
     }
 
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
-        menu.add("Add item").setOnMenuItemClickListener(new OnMenuItemClickListener() {
-            public boolean onMenuItemClick(MenuItem item) {
+        menu.add("Add item").setOnMenuItemClickListener((MenuItem item) -> {
                 mGroups.add(0, new MyGroup(2));
-                ((BaseExpandableListAdapter) mAdapter).notifyDataSetChanged();
+                if (mAdapter != null) {
+                    ((BaseExpandableListAdapter) mAdapter).notifyDataSetChanged();
+                }
                 return true;
-            }
         });
 
         return true;
diff --git a/tests/tests/widget/src/android/widget/cts/ExpandableListViewBasicTest.java b/tests/tests/widget/src/android/widget/cts/ExpandableListViewBasicTest.java
index dd8d6a2..b40a75f 100644
--- a/tests/tests/widget/src/android/widget/cts/ExpandableListViewBasicTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ExpandableListViewBasicTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-
+import android.app.Instrumentation;
 import android.cts.util.PollingCheck;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.MediumTest;
@@ -30,34 +30,31 @@
 
 import java.util.List;
 
+@MediumTest
 public class ExpandableListViewBasicTest extends
-        ActivityInstrumentationTestCase2<ExpandableListSimple> {
+        ActivityInstrumentationTestCase2<ExpandableListBasic> {
+    private Instrumentation mInstrumentation;
     private ExpandableListScenario mActivity;
     private ExpandableListView mExpandableListView;
     private ExpandableListAdapter mAdapter;
     private ListUtil mListUtil;
 
     public ExpandableListViewBasicTest() {
-        super(ExpandableListSimple.class);
+        super(ExpandableListBasic.class);
     }
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
 
+        mInstrumentation = getInstrumentation();
         mActivity = getActivity();
-        new PollingCheck() {
-            @Override
-                protected boolean check() {
-                return mActivity.hasWindowFocus();
-            }
-        }.run();
+        PollingCheck.waitFor(() -> mActivity.hasWindowFocus());
         mExpandableListView = mActivity.getExpandableListView();
         mAdapter = mExpandableListView.getExpandableListAdapter();
         mListUtil = new ListUtil(mExpandableListView, getInstrumentation());
     }
 
-    @MediumTest
     public void testPreconditions() {
         assertNotNull(mActivity);
         assertNotNull(mExpandableListView);
@@ -69,7 +66,7 @@
         assertTrue("Could not find group to expand", groupPos >= 0);
         assertFalse("Group is already expanded", mExpandableListView.isGroupExpanded(groupPos));
         mListUtil.arrowScrollToSelectedPosition(groupPos);
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.waitForIdleSync();
         sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
         getInstrumentation().waitForIdleSync();
         assertTrue("Group did not expand", mExpandableListView.isGroupExpanded(groupPos));
@@ -77,32 +74,29 @@
         return groupPos;
     }
 
-    @MediumTest
     public void testExpandGroup() {
         expandGroup(-1, true);
     }
 
-    @MediumTest
     public void testCollapseGroup() {
         final int groupPos = expandGroup(-1, true);
 
         sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.waitForIdleSync();
         assertFalse("Group did not collapse", mExpandableListView.isGroupExpanded(groupPos));
     }
 
-    @MediumTest
     public void testExpandedGroupMovement() {
         // Expand the first group
         mListUtil.arrowScrollToSelectedPosition(0);
         sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.waitForIdleSync();
 
         // Ensure it expanded
         assertTrue("Group did not expand", mExpandableListView.isGroupExpanded(0));
 
         // Wait until that's all good
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.waitForIdleSync();
 
         // Make sure it expanded
         assertTrue("Group did not expand", mExpandableListView.isGroupExpanded(0));
@@ -117,12 +111,8 @@
                 mAdapter instanceof BaseExpandableListAdapter);
         final BaseExpandableListAdapter adapter = (BaseExpandableListAdapter) mAdapter;
 
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                adapter.notifyDataSetChanged();
-            }
-        });
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> adapter.notifyDataSetChanged());
+        mInstrumentation.waitForIdleSync();
 
         // Make sure the right group is expanded
         assertTrue("The expanded state didn't stay with the proper group",
@@ -131,20 +121,17 @@
                 mExpandableListView.isGroupExpanded(0));
     }
 
-    @MediumTest
     public void testContextMenus() {
         ExpandableListTester tester = new ExpandableListTester(mExpandableListView, this);
         tester.testContextMenus();
     }
 
-    @MediumTest
     public void testConvertionBetweenFlatAndPacked() {
         ExpandableListTester tester = new ExpandableListTester(mExpandableListView, this);
         tester.testConvertionBetweenFlatAndPackedOnGroups();
         tester.testConvertionBetweenFlatAndPackedOnChildren();
     }
 
-    @MediumTest
     public void testSelectedPosition() {
         ExpandableListTester tester = new ExpandableListTester(mExpandableListView, this);
         tester.testSelectedPositionOnGroups();
diff --git a/tests/tests/widget/src/android/widget/cts/ExpandableListViewTest.java b/tests/tests/widget/src/android/widget/cts/ExpandableListViewTest.java
index e773ebf..b6b238e 100644
--- a/tests/tests/widget/src/android/widget/cts/ExpandableListViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ExpandableListViewTest.java
@@ -16,43 +16,76 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-
+import android.app.Instrumentation;
 import android.content.Context;
+import android.cts.util.PollingCheck;
 import android.database.DataSetObserver;
 import android.graphics.Canvas;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Parcelable;
-import android.test.AndroidTestCase;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.util.AttributeSet;
 import android.util.Xml;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.AdapterView;
 import android.widget.ExpandableListAdapter;
 import android.widget.ExpandableListView;
 import android.widget.ListAdapter;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.ExpandableListView.OnChildClickListener;
-import android.widget.ExpandableListView.OnGroupClickListener;
+import android.widget.TextView;
+import android.widget.cts.util.ExpandableListScenario;
 
-public class ExpandableListViewTest extends AndroidTestCase {
+import org.xmlpull.v1.XmlPullParser;
+
+import static org.mockito.Mockito.*;
+
+@MediumTest
+public class ExpandableListViewTest extends ActivityInstrumentationTestCase2<ExpandableList> {
+    private Instrumentation mInstrumentation;
+    private ExpandableListScenario mActivity;
+    private ExpandableListView mExpandableListView;
+
+    public ExpandableListViewTest() {
+        super(ExpandableList.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mInstrumentation = getInstrumentation();
+        mActivity = getActivity();
+        PollingCheck.waitFor(() -> mActivity.hasWindowFocus());
+        mExpandableListView = mActivity.getExpandableListView();
+    }
+
     public void testConstructor() {
-        new ExpandableListView(mContext);
+        new ExpandableListView(mActivity);
 
-        new ExpandableListView(mContext, null);
+        new ExpandableListView(mActivity, null);
 
-        new ExpandableListView(mContext, null, 0);
+        new ExpandableListView(mActivity, null, android.R.attr.expandableListViewStyle);
+
+        new ExpandableListView(mActivity, null, 0,
+                android.R.style.Widget_DeviceDefault_ExpandableListView);
+
+        new ExpandableListView(mActivity, null, 0,
+                android.R.style.Widget_DeviceDefault_Light_ExpandableListView);
+
+        new ExpandableListView(mActivity, null, 0,
+                android.R.style.Widget_Material_ExpandableListView);
+
+        new ExpandableListView(mActivity, null, 0,
+                android.R.style.Widget_Material_Light_ExpandableListView);
 
         XmlPullParser parser =
-            getContext().getResources().getXml(R.layout.expandablelistview_layout);
+                mActivity.getResources().getXml(R.layout.expandablelistview_layout);
         AttributeSet attrs = Xml.asAttributeSet(parser);
-        new ExpandableListView(mContext, attrs);
-        new ExpandableListView(mContext, attrs, 0);
+        new ExpandableListView(mActivity, attrs);
+        new ExpandableListView(mActivity, attrs, 0);
 
         try {
             new ExpandableListView(null);
@@ -74,230 +107,292 @@
     }
 
     public void testSetChildDivider() {
-        ExpandableListView expandableListView = new ExpandableListView(mContext);
-        Drawable drawable = mContext.getResources().getDrawable(R.drawable.scenery);
-        expandableListView.setChildDivider(drawable);
+        Drawable drawable = mActivity.getResources().getDrawable(R.drawable.scenery);
+        mExpandableListView.setChildDivider(drawable);
     }
 
     public void testSetAdapter() {
-        ExpandableListView expandableListView = new ExpandableListView(mContext);
         try {
-            expandableListView.setAdapter((ListAdapter) null);
+            mExpandableListView.setAdapter((ListAdapter) null);
             fail("setAdapter(ListAdapter) should throw RuntimeException here.");
         } catch (RuntimeException e) {
         }
     }
 
+    @UiThreadTest
     public void testGetAdapter() {
-        ExpandableListView expandableListView = new ExpandableListView(mContext);
-        assertNull(expandableListView.getAdapter());
+        assertNull(mExpandableListView.getAdapter());
 
         ExpandableListAdapter expandableAdapter = new MockExpandableListAdapter();
-        expandableListView.setAdapter(expandableAdapter);
-        assertNotNull(expandableListView.getAdapter());
+        mExpandableListView.setAdapter(expandableAdapter);
+        assertNotNull(mExpandableListView.getAdapter());
     }
 
+    @UiThreadTest
     public void testAccessExpandableListAdapter() {
-        ExpandableListView expandableListView = new ExpandableListView(mContext);
         ExpandableListAdapter expandableAdapter = new MockExpandableListAdapter();
 
-        assertNull(expandableListView.getExpandableListAdapter());
-        expandableListView.setAdapter(expandableAdapter);
-        assertSame(expandableAdapter, expandableListView.getExpandableListAdapter());
+        assertNull(mExpandableListView.getExpandableListAdapter());
+        mExpandableListView.setAdapter(expandableAdapter);
+        assertSame(expandableAdapter, mExpandableListView.getExpandableListAdapter());
     }
 
+    @UiThreadTest
     public void testPerformItemClick() {
-        ExpandableListView expandableListView = new ExpandableListView(mContext);
+        assertFalse(mExpandableListView.performItemClick(null, 100, 99));
 
-        assertFalse(expandableListView.performItemClick(null, 100, 99));
-
-        MockOnItemClickListener onClickListener = new MockOnItemClickListener();
-        expandableListView.setOnItemClickListener(onClickListener);
-        assertTrue(expandableListView.performItemClick(null, 100, 99));
+        ExpandableListView.OnItemClickListener mockOnItemClickListener =
+                mock(ExpandableListView.OnItemClickListener.class);
+        mExpandableListView.setOnItemClickListener(mockOnItemClickListener);
+        assertTrue(mExpandableListView.performItemClick(null, 100, 99));
+        verify(mockOnItemClickListener, times(1)).onItemClick(eq(mExpandableListView),
+                any(View.class), eq(100), eq(99L));
     }
 
     public void testSetOnItemClickListener() {
-        ExpandableListView expandableListView = new ExpandableListView(mContext);
-        MockOnItemClickListener listener = new MockOnItemClickListener();
+        ExpandableListView.OnItemClickListener mockOnItemClickListener =
+                mock(ExpandableListView.OnItemClickListener.class);
 
-        assertNull(expandableListView.getOnItemClickListener());
-        expandableListView.setOnItemClickListener(listener);
-        assertSame(listener, expandableListView.getOnItemClickListener());
+        assertNull(mExpandableListView.getOnItemClickListener());
+        mExpandableListView.setOnItemClickListener(mockOnItemClickListener);
+        assertSame(mockOnItemClickListener, mExpandableListView.getOnItemClickListener());
     }
 
+    @UiThreadTest
     public void testExpandGroup() {
-        ExpandableListView expandableListView = new ExpandableListView(mContext);
         ExpandableListAdapter expandableAdapter = new MockExpandableListAdapter();
-        expandableListView.setAdapter(expandableAdapter);
+        mExpandableListView.setAdapter(expandableAdapter);
 
-        MockOnGroupExpandListener mockOnGroupExpandListener = new MockOnGroupExpandListener();
-        expandableListView.setOnGroupExpandListener(mockOnGroupExpandListener);
+        ExpandableListView.OnGroupExpandListener mockOnGroupExpandListener =
+                mock(ExpandableListView.OnGroupExpandListener.class);
+        mExpandableListView.setOnGroupExpandListener(mockOnGroupExpandListener);
 
-        assertFalse(mockOnGroupExpandListener.hasCalledOnGroupExpand());
-        assertTrue(expandableListView.expandGroup(0));
-        assertTrue(mockOnGroupExpandListener.hasCalledOnGroupExpand());
-        mockOnGroupExpandListener.reset();
-        assertFalse(expandableListView.expandGroup(0));
-        assertTrue(mockOnGroupExpandListener.hasCalledOnGroupExpand());
-        mockOnGroupExpandListener.reset();
-        assertTrue(expandableListView.expandGroup(1));
-        assertTrue(mockOnGroupExpandListener.hasCalledOnGroupExpand());
-        mockOnGroupExpandListener.reset();
-        assertFalse(expandableListView.expandGroup(1));
-        assertTrue(mockOnGroupExpandListener.hasCalledOnGroupExpand());
-        mockOnGroupExpandListener.reset();
+        verifyZeroInteractions(mockOnGroupExpandListener);
 
-        expandableListView.setAdapter((ExpandableListAdapter) null);
+        assertTrue(mExpandableListView.expandGroup(0));
+        verify(mockOnGroupExpandListener, times(1)).onGroupExpand(0);
+        assertTrue(mExpandableListView.isGroupExpanded(0));
+
+        reset(mockOnGroupExpandListener);
+        assertFalse(mExpandableListView.expandGroup(0));
+        verify(mockOnGroupExpandListener, times(1)).onGroupExpand(0);
+        assertTrue(mExpandableListView.isGroupExpanded(0));
+
+        reset(mockOnGroupExpandListener);
+        assertTrue(mExpandableListView.expandGroup(1));
+        verify(mockOnGroupExpandListener, times(1)).onGroupExpand(1);
+        assertTrue(mExpandableListView.isGroupExpanded(1));
+
+        reset(mockOnGroupExpandListener);
+        assertFalse(mExpandableListView.expandGroup(1));
+        verify(mockOnGroupExpandListener, times(1)).onGroupExpand(1);
+        assertTrue(mExpandableListView.isGroupExpanded(1));
+
+        reset(mockOnGroupExpandListener);
+        mExpandableListView.setAdapter((ExpandableListAdapter) null);
         try {
-            expandableListView.expandGroup(0);
+            mExpandableListView.expandGroup(0);
             fail("should throw NullPointerException");
         } catch (NullPointerException e) {
         }
     }
 
+    public void testExpandGroupSmooth() {
+        mInstrumentation.runOnMainSync(
+                () -> mExpandableListView.setAdapter(new MockExpandableListAdapter()));
+
+        ExpandableListView.OnGroupExpandListener mockOnGroupExpandListener =
+                mock(ExpandableListView.OnGroupExpandListener.class);
+        mExpandableListView.setOnGroupExpandListener(mockOnGroupExpandListener);
+
+        verifyZeroInteractions(mockOnGroupExpandListener);
+        mInstrumentation.runOnMainSync(() -> assertTrue(mExpandableListView.expandGroup(0, true)));
+        mInstrumentation.waitForIdleSync();
+        verify(mockOnGroupExpandListener, times(1)).onGroupExpand(0);
+        assertTrue(mExpandableListView.isGroupExpanded(0));
+
+        reset(mockOnGroupExpandListener);
+        mInstrumentation.runOnMainSync(() -> assertFalse(mExpandableListView.expandGroup(0, true)));
+        mInstrumentation.waitForIdleSync();
+        verify(mockOnGroupExpandListener, times(1)).onGroupExpand(0);
+        assertTrue(mExpandableListView.isGroupExpanded(0));
+
+        reset(mockOnGroupExpandListener);
+        mInstrumentation.runOnMainSync(() -> assertTrue(mExpandableListView.expandGroup(1, true)));
+        mInstrumentation.waitForIdleSync();
+        verify(mockOnGroupExpandListener, times(1)).onGroupExpand(1);
+        assertTrue(mExpandableListView.isGroupExpanded(1));
+
+        reset(mockOnGroupExpandListener);
+        mInstrumentation.runOnMainSync(() -> assertFalse(mExpandableListView.expandGroup(1, true)));
+        mInstrumentation.waitForIdleSync();
+        verify(mockOnGroupExpandListener, times(1)).onGroupExpand(1);
+        assertTrue(mExpandableListView.isGroupExpanded(1));
+
+        reset(mockOnGroupExpandListener);
+        mInstrumentation.runOnMainSync(() -> {
+            mExpandableListView.setAdapter((ExpandableListAdapter) null);
+            try {
+                mExpandableListView.expandGroup(0);
+                fail("should throw NullPointerException");
+            } catch (NullPointerException e) {
+            }
+        });
+    }
+
+    @UiThreadTest
     public void testCollapseGroup() {
-        ExpandableListView expandableListView = new ExpandableListView(mContext);
         ExpandableListAdapter expandableAdapter = new MockExpandableListAdapter();
-        expandableListView.setAdapter(expandableAdapter);
+        mExpandableListView.setAdapter(expandableAdapter);
 
-        MockOnGroupCollapseListener mockOnGroupCollapseListener =
-            new MockOnGroupCollapseListener();
-        expandableListView.setOnGroupCollapseListener(mockOnGroupCollapseListener);
+        ExpandableListView.OnGroupCollapseListener mockOnGroupCollapseListener =
+                mock(ExpandableListView.OnGroupCollapseListener.class);
+        mExpandableListView.setOnGroupCollapseListener(mockOnGroupCollapseListener);
 
-        assertFalse(mockOnGroupCollapseListener.hasCalledOnGroupCollapse());
-        assertFalse(expandableListView.collapseGroup(0));
-        assertTrue(mockOnGroupCollapseListener.hasCalledOnGroupCollapse());
-        mockOnGroupCollapseListener.reset();
+        verifyZeroInteractions(mockOnGroupCollapseListener);
+        assertFalse(mExpandableListView.collapseGroup(0));
+        verify(mockOnGroupCollapseListener, times(1)).onGroupCollapse(0);
+        assertFalse(mExpandableListView.isGroupExpanded(0));
 
-        expandableListView.expandGroup(0);
-        assertTrue(expandableListView.collapseGroup(0));
-        assertTrue(mockOnGroupCollapseListener.hasCalledOnGroupCollapse());
-        mockOnGroupCollapseListener.reset();
-        assertFalse(expandableListView.collapseGroup(1));
-        assertTrue(mockOnGroupCollapseListener.hasCalledOnGroupCollapse());
-        mockOnGroupCollapseListener.reset();
+        reset(mockOnGroupCollapseListener);
+        mExpandableListView.expandGroup(0);
+        assertTrue(mExpandableListView.collapseGroup(0));
+        verify(mockOnGroupCollapseListener, times(1)).onGroupCollapse(0);
+        assertFalse(mExpandableListView.isGroupExpanded(0));
 
-        expandableListView.setAdapter((ExpandableListAdapter) null);
+        reset(mockOnGroupCollapseListener);
+        assertFalse(mExpandableListView.collapseGroup(1));
+        verify(mockOnGroupCollapseListener, times(1)).onGroupCollapse(1);
+        assertFalse(mExpandableListView.isGroupExpanded(1));
+
+        reset(mockOnGroupCollapseListener);
+        mExpandableListView.setAdapter((ExpandableListAdapter) null);
         try {
-            expandableListView.collapseGroup(0);
+            mExpandableListView.collapseGroup(0);
             fail("should throw NullPointerException");
         } catch (NullPointerException e) {
         }
     }
 
+    @UiThreadTest
     public void testSetOnGroupClickListener() {
-        ExpandableListView expandableListView = new ExpandableListView(mContext);
-        expandableListView.setAdapter(new MockExpandableListAdapter());
-        MockOnGroupClickListener listener = new MockOnGroupClickListener();
+        mExpandableListView.setAdapter(new MockExpandableListAdapter());
 
-        expandableListView.setOnGroupClickListener(listener);
-        assertFalse(listener.hasCalledOnGroupClick());
-        expandableListView.performItemClick(null, 0, 0);
-        assertTrue(listener.hasCalledOnGroupClick());
+        ExpandableListView.OnGroupClickListener mockOnGroupClickListener =
+                mock(ExpandableListView.OnGroupClickListener.class);
+
+        mExpandableListView.setOnGroupClickListener(mockOnGroupClickListener);
+        verifyZeroInteractions(mockOnGroupClickListener);
+
+        mExpandableListView.performItemClick(null, 0, 0);
+        verify(mockOnGroupClickListener, times(1)).onGroupClick(eq(mExpandableListView),
+                any(View.class), eq(0), eq(0L));
     }
 
+    @UiThreadTest
     public void testSetOnChildClickListener() {
-        ExpandableListView expandableListView = new ExpandableListView(mContext);
-        expandableListView.setAdapter(new MockExpandableListAdapter());
-        MockOnChildClickListener listener = new MockOnChildClickListener();
+        mExpandableListView.setAdapter(new MockExpandableListAdapter());
 
-        expandableListView.setOnChildClickListener(listener);
-        assertFalse(listener.hasCalledOnChildClick());
+        ExpandableListView.OnChildClickListener mockOnChildClickListener =
+                mock(ExpandableListView.OnChildClickListener.class);
+
+        mExpandableListView.setOnChildClickListener(mockOnChildClickListener);
+        verifyZeroInteractions(mockOnChildClickListener);
+
         // first let the list expand
-        expandableListView.expandGroup(0);
+        mExpandableListView.expandGroup(0);
         // click on the child list of the first group
-        expandableListView.performItemClick(null, 1, 0);
-        assertTrue(listener.hasCalledOnChildClick());
+        mExpandableListView.performItemClick(null, 1, 0);
+        verify(mockOnChildClickListener, times(1)).onChildClick(eq(mExpandableListView),
+                any(View.class), eq(0), eq(0), eq(0L));
     }
 
+    @UiThreadTest
     public void testGetExpandableListPosition() {
-        ExpandableListView expandableListView = new ExpandableListView(mContext);
-        expandableListView.setAdapter(new MockExpandableListAdapter());
+        mExpandableListView.setAdapter(new MockExpandableListAdapter());
 
-        assertEquals(0, expandableListView.getExpandableListPosition(0));
+        assertEquals(0, mExpandableListView.getExpandableListPosition(0));
 
         // Group 0 is not expanded, position 1 is invalid
         assertEquals(ExpandableListView.PACKED_POSITION_VALUE_NULL,
-                expandableListView.getExpandableListPosition(1));
+                mExpandableListView.getExpandableListPosition(1));
 
         // Position 1 becomes valid when group 0 is expanded
-        expandableListView.expandGroup(0);
+        mExpandableListView.expandGroup(0);
         assertEquals(ExpandableListView.getPackedPositionForChild(0, 0),
-                expandableListView.getExpandableListPosition(1));
+                mExpandableListView.getExpandableListPosition(1));
 
         // Position 2 is still invalid (only one child).
         assertEquals(ExpandableListView.PACKED_POSITION_VALUE_NULL,
-                expandableListView.getExpandableListPosition(2));
+                mExpandableListView.getExpandableListPosition(2));
     }
 
+    @UiThreadTest
     public void testGetFlatListPosition() {
-        ExpandableListView expandableListView = new ExpandableListView(mContext);
-        expandableListView.setAdapter(new MockExpandableListAdapter());
+        mExpandableListView.setAdapter(new MockExpandableListAdapter());
 
         try {
-            expandableListView.getFlatListPosition(ExpandableListView.PACKED_POSITION_VALUE_NULL);
+            mExpandableListView.getFlatListPosition(ExpandableListView.PACKED_POSITION_VALUE_NULL);
         } catch (NullPointerException e) {
         }
-        assertEquals(0, expandableListView.getFlatListPosition(
+        assertEquals(0, mExpandableListView.getFlatListPosition(
                 ExpandableListView.PACKED_POSITION_TYPE_CHILD<<32));
         // 0x8000000100000000L means this is a child and group position is 1.
-        assertEquals(1, expandableListView.getFlatListPosition(0x8000000100000000L));
+        assertEquals(1, mExpandableListView.getFlatListPosition(0x8000000100000000L));
     }
 
+    @UiThreadTest
     public void testGetSelectedPosition() {
-        ExpandableListView expandableListView = new ExpandableListView(mContext);
-
         assertEquals(ExpandableListView.PACKED_POSITION_VALUE_NULL,
-                expandableListView.getSelectedPosition());
+                mExpandableListView.getSelectedPosition());
 
-        expandableListView.setAdapter(new MockExpandableListAdapter());
+        mExpandableListView.setAdapter(new MockExpandableListAdapter());
 
-        expandableListView.setSelectedGroup(0);
-        assertEquals(0, expandableListView.getSelectedPosition());
+        mExpandableListView.setSelectedGroup(0);
+        assertEquals(0, mExpandableListView.getSelectedPosition());
 
-        expandableListView.setSelectedGroup(1);
-        assertEquals(0, expandableListView.getSelectedPosition());
+        mExpandableListView.setSelectedGroup(1);
+        assertEquals(0, mExpandableListView.getSelectedPosition());
     }
 
+    @UiThreadTest
     public void testGetSelectedId() {
-        ExpandableListView expandableListView = new ExpandableListView(mContext);
+        assertEquals(-1, mExpandableListView.getSelectedId());
+        mExpandableListView.setAdapter(new MockExpandableListAdapter());
 
-        assertEquals(-1, expandableListView.getSelectedId());
-        expandableListView.setAdapter(new MockExpandableListAdapter());
+        mExpandableListView.setSelectedGroup(0);
+        assertEquals(0, mExpandableListView.getSelectedId());
 
-        expandableListView.setSelectedGroup(0);
-        assertEquals(0, expandableListView.getSelectedId());
-
-        expandableListView.setSelectedGroup(1);
-        assertEquals(0, expandableListView.getSelectedId());
+        mExpandableListView.setSelectedGroup(1);
+        assertEquals(0, mExpandableListView.getSelectedId());
     }
 
+    @UiThreadTest
     public void testSetSelectedGroup() {
-        ExpandableListView expandableListView = new ExpandableListView(mContext);
-        expandableListView.setAdapter(new MockExpandableListAdapter());
+        mExpandableListView.setAdapter(new MockExpandableListAdapter());
 
-        expandableListView.setSelectedGroup(0);
-        assertEquals(0, expandableListView.getSelectedPosition());
+        mExpandableListView.setSelectedGroup(0);
+        assertEquals(0, mExpandableListView.getSelectedPosition());
 
-        expandableListView.setSelectedGroup(1);
-        assertEquals(0, expandableListView.getSelectedPosition());
+        mExpandableListView.setSelectedGroup(1);
+        assertEquals(0, mExpandableListView.getSelectedPosition());
     }
 
+    @UiThreadTest
     public void testSetSelectedChild() {
-        ExpandableListView expandableListView = new ExpandableListView(mContext);
-        expandableListView.setAdapter(new MockExpandableListAdapter());
+        mExpandableListView.setAdapter(new MockExpandableListAdapter());
 
-        assertTrue(expandableListView.setSelectedChild(0, 0, false));
-        assertTrue(expandableListView.setSelectedChild(0, 1, true));
+        assertTrue(mExpandableListView.setSelectedChild(0, 0, false));
+        assertTrue(mExpandableListView.setSelectedChild(0, 1, true));
     }
 
+    @UiThreadTest
     public void testIsGroupExpanded() {
-        ExpandableListView expandableListView = new ExpandableListView(mContext);
-        expandableListView.setAdapter(new MockExpandableListAdapter());
+        mExpandableListView.setAdapter(new MockExpandableListAdapter());
 
-        expandableListView.expandGroup(1);
-        assertFalse(expandableListView.isGroupExpanded(0));
-        assertTrue(expandableListView.isGroupExpanded(1));
+        mExpandableListView.expandGroup(1);
+        assertFalse(mExpandableListView.isGroupExpanded(0));
+        assertTrue(mExpandableListView.isGroupExpanded(1));
     }
 
     public void testGetPackedPositionType() {
@@ -356,31 +451,35 @@
     }
 
     public void testSetChildIndicator() {
-        ExpandableListView expandableListView = new ExpandableListView(mContext);
-        expandableListView.setChildIndicator(null);
+        mExpandableListView.setChildIndicator(null);
     }
 
     public void testSetChildIndicatorBounds() {
-        ExpandableListView expandableListView = new ExpandableListView(mContext);
-        expandableListView.setChildIndicatorBounds(10, 10);
+        mExpandableListView.setChildIndicatorBounds(10, 20);
+    }
+
+    public void testSetChildIndicatorBoundsRelative() {
+        mExpandableListView.setChildIndicatorBoundsRelative(10, 20);
     }
 
     public void testSetGroupIndicator() {
-        ExpandableListView expandableListView = new ExpandableListView(mContext);
         Drawable drawable = new BitmapDrawable();
-        expandableListView.setGroupIndicator(drawable);
+        mExpandableListView.setGroupIndicator(drawable);
     }
 
     public void testSetIndicatorBounds() {
-        ExpandableListView expandableListView = new ExpandableListView(mContext);
-        expandableListView.setIndicatorBounds(10,10);
+        mExpandableListView.setIndicatorBounds(10, 30);
+    }
+
+    public void testSetIndicatorBoundsRelative() {
+        mExpandableListView.setIndicatorBoundsRelative(10, 30);
     }
 
     public void testOnSaveInstanceState() {
-        ExpandableListView src = new ExpandableListView(mContext);
+        ExpandableListView src = new ExpandableListView(mActivity);
         Parcelable p1 = src.onSaveInstanceState();
 
-        ExpandableListView dest = new ExpandableListView(mContext);
+        ExpandableListView dest = new ExpandableListView(mActivity);
         dest.onRestoreInstanceState(p1);
         Parcelable p2 = dest.onSaveInstanceState();
 
@@ -389,11 +488,17 @@
     }
 
     public void testDispatchDraw() {
-        MockExpandableListView expandableListView = new MockExpandableListView(mContext);
+        MockExpandableListView expandableListView = new MockExpandableListView(mActivity);
         expandableListView.dispatchDraw(new Canvas());
     }
 
     private class MockExpandableListAdapter implements ExpandableListAdapter {
+        private final LayoutInflater mLayoutInflater;
+
+        public MockExpandableListAdapter() {
+            mLayoutInflater = LayoutInflater.from(mActivity);
+        }
+
         public void registerDataSetObserver(DataSetObserver observer) {
         }
 
@@ -443,12 +548,24 @@
 
         public View getGroupView(int groupPosition, boolean isExpanded,
                 View convertView, ViewGroup parent) {
-            return null;
+            TextView result = (TextView) convertView;
+            if (result == null) {
+                result = (TextView) mLayoutInflater.inflate(
+                        R.layout.expandablelistview_group, parent, false);
+            }
+            result.setText("Group " + groupPosition);
+            return result;
         }
 
         public View getChildView(int groupPosition, int childPosition,
                 boolean isLastChild, View convertView, ViewGroup parent) {
-            return null;
+            TextView result = (TextView) convertView;
+            if (result == null) {
+                result = (TextView) mLayoutInflater.inflate(
+                        R.layout.expandablelistview_child, parent, false);
+            }
+            result.setText("Child " + childPosition);
+            return result;
         }
 
         public boolean isChildSelectable(int groupPosition, int childPosition) {
@@ -478,72 +595,6 @@
         }
     }
 
-    private class MockOnGroupExpandListener implements ExpandableListView.OnGroupExpandListener {
-        private boolean mCalledOnGroupExpand = false;
-
-        public void onGroupExpand(int groupPosition) {
-            mCalledOnGroupExpand = true;
-        }
-
-        public boolean hasCalledOnGroupExpand() {
-            return mCalledOnGroupExpand;
-        }
-
-        public void reset() {
-            mCalledOnGroupExpand = false;
-        }
-    }
-
-    private class MockOnGroupCollapseListener implements
-            ExpandableListView.OnGroupCollapseListener {
-        private boolean mCalledOnGroupCollapse = false;
-
-        public void onGroupCollapse(int groupPosition) {
-            mCalledOnGroupCollapse = true;
-        }
-
-        public boolean hasCalledOnGroupCollapse() {
-            return mCalledOnGroupCollapse;
-        }
-
-        public void reset() {
-            mCalledOnGroupCollapse = false;
-        }
-    }
-
-    private class MockOnItemClickListener implements OnItemClickListener {
-        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-        }
-    }
-
-    private class MockOnGroupClickListener implements OnGroupClickListener {
-        private boolean mCalledOnGroupClick = false;
-
-        public boolean onGroupClick(ExpandableListView parent, View v,
-                int groupPosition, long id) {
-            mCalledOnGroupClick = true;
-            return true;
-        }
-
-        public boolean hasCalledOnGroupClick() {
-            return mCalledOnGroupClick;
-        }
-    }
-
-    private class MockOnChildClickListener implements OnChildClickListener {
-        private boolean mCalledOnChildClick = false;
-
-        public boolean onChildClick(ExpandableListView parent, View v,
-                int groupPosition, int childPosition, long id) {
-            mCalledOnChildClick = true;
-            return true;
-        }
-
-        public boolean hasCalledOnChildClick() {
-            return mCalledOnChildClick;
-        }
-    }
-
     private class MockExpandableListView extends ExpandableListView {
         public MockExpandableListView(Context context) {
             super(context);
diff --git a/tests/tests/widget/src/android/widget/cts/ExpandableListViewWithHeadersTest.java b/tests/tests/widget/src/android/widget/cts/ExpandableListViewWithHeadersTest.java
index 7f4715f..9cbc92e 100644
--- a/tests/tests/widget/src/android/widget/cts/ExpandableListViewWithHeadersTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ExpandableListViewWithHeadersTest.java
@@ -39,12 +39,7 @@
         super.setUp();
 
         final ExpandableListWithHeaders activity = getActivity();
-        new PollingCheck() {
-            @Override
-                protected boolean check() {
-                return activity.hasWindowFocus();
-            }
-        }.run();
+        PollingCheck.waitFor(() -> activity.hasWindowFocus());
         mExpandableListView = activity.getExpandableListView();
         mListUtil = new ListUtil(mExpandableListView, getInstrumentation());
     }
diff --git a/tests/tests/widget/src/android/widget/cts/ExpandableListWithHeaders.java b/tests/tests/widget/src/android/widget/cts/ExpandableListWithHeaders.java
index 259d443..17e8a59 100644
--- a/tests/tests/widget/src/android/widget/cts/ExpandableListWithHeaders.java
+++ b/tests/tests/widget/src/android/widget/cts/ExpandableListWithHeaders.java
@@ -22,14 +22,14 @@
 import android.widget.cts.util.ExpandableListScenario;
 
 public class ExpandableListWithHeaders extends ExpandableListScenario {
-    private static final int[] sNumChildren = {1, 4, 3, 2, 6};
-    private static final int sNumOfHeadersAndFooters = 12;
+    private static final int[] CHILD_COUNT = {1, 4, 3, 2, 6};
+    private static final int HEADER_FOOTER_COUNT = 12;
 
     @Override
     protected void init(ExpandableParams params) {
         params.setStackFromBottom(false)
                 .setStartingSelectionPosition(-1)
-                .setNumChildren(sNumChildren)
+                .setNumChildren(CHILD_COUNT)
                 .setItemScreenSizeFactor(0.14)
                 .setConnectAdapter(false);
     }
@@ -41,13 +41,13 @@
         final ExpandableListView expandableListView = getExpandableListView();
         expandableListView.setItemsCanFocus(true);
 
-        for (int i = 0; i < sNumOfHeadersAndFooters; i++) {
+        for (int i = 0; i < HEADER_FOOTER_COUNT; i++) {
             Button header = new Button(this);
             header.setText("Header View");
             expandableListView.addHeaderView(header);
         }
 
-        for (int i = 0; i < sNumOfHeadersAndFooters; i++) {
+        for (int i = 0; i < HEADER_FOOTER_COUNT; i++) {
             Button footer = new Button(this);
             footer.setText("Footer View");
             expandableListView.addFooterView(footer);
@@ -61,6 +61,6 @@
      * @return The number of headers (and the same number of footers)
      */
     public int getNumOfHeadersAndFooters() {
-        return sNumOfHeadersAndFooters;
+        return HEADER_FOOTER_COUNT;
     }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/FilterTest.java b/tests/tests/widget/src/android/widget/cts/FilterTest.java
index 7a1d111..77c73f3 100644
--- a/tests/tests/widget/src/android/widget/cts/FilterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/FilterTest.java
@@ -24,6 +24,16 @@
 import android.test.ActivityInstrumentationTestCase2;
 import android.widget.Filter;
 import android.widget.Filter.FilterListener;
+import org.junit.Assert;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
 
 public class FilterTest extends ActivityInstrumentationTestCase2<CtsActivity> {
     private static final long TIME_OUT = 10000;
@@ -66,26 +76,22 @@
         });
         getInstrumentation().waitForIdleSync();
 
-        new PollingCheck(TIME_OUT) {
-            @Override
-            protected boolean check() {
-                return mMockFilter.hadPerformedFiltering();
-            }
-        }.run();
+        PollingCheck.waitFor(TIME_OUT, () -> mMockFilter.hadPerformedFiltering());
         assertEquals(TEST_CONSTRAINT, mMockFilter.getPerformFilteringConstraint());
 
-        new PollingCheck(TIME_OUT) {
-            @Override
-            protected boolean check() {
-                return mMockFilter.hadPublishedResults();
-            }
-        }.run();
+        PollingCheck.waitFor(TIME_OUT, () -> mMockFilter.hadPublishedResults());
         assertEquals(TEST_CONSTRAINT, mMockFilter.getPublishResultsConstraint());
         assertSame(mMockFilter.getExpectResults(), mMockFilter.getResults());
     }
 
     public void testFilter2() {
-        final MockFilterListener mockFilterListener = new MockFilterListener();
+        final CountDownLatch countDownLatch = new CountDownLatch(1);
+        final Filter.FilterListener mockFilterListener = mock(Filter.FilterListener.class);
+        doAnswer((InvocationOnMock invocation) -> {
+            countDownLatch.countDown();
+            return null;
+        }).when(mockFilterListener).onFilterComplete(anyInt());
+
         getActivity().runOnUiThread(new Runnable() {
             public void run() {
                 mMockFilter = new MockFilter();
@@ -94,29 +100,18 @@
         });
         getInstrumentation().waitForIdleSync();
 
-        new PollingCheck(TIME_OUT) {
-            @Override
-            protected boolean check() {
-                return mMockFilter.hadPerformedFiltering();
-            }
-        }.run();
+        PollingCheck.waitFor(TIME_OUT, () -> mMockFilter.hadPerformedFiltering());
         assertEquals(TEST_CONSTRAINT, mMockFilter.getPerformFilteringConstraint());
 
-        new PollingCheck(TIME_OUT) {
-            @Override
-            protected boolean check() {
-                return mMockFilter.hadPublishedResults();
-            }
-        }.run();
+        PollingCheck.waitFor(TIME_OUT, () -> mMockFilter.hadPublishedResults());
         assertEquals(TEST_CONSTRAINT, mMockFilter.getPublishResultsConstraint());
         assertSame(mMockFilter.getExpectResults(), mMockFilter.getResults());
 
-        new PollingCheck(TIME_OUT) {
-            @Override
-            protected boolean check() {
-                return mockFilterListener.hasCalledOnFilterComplete();
-            }
-        }.run();
+        try {
+            countDownLatch.await(TIME_OUT, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException ie) {
+            Assert.fail(ie.toString());
+        }
     }
 
     private static class MockFilter extends Filter {
@@ -185,16 +180,4 @@
             }
         }
     }
-
-    private static class MockFilterListener implements FilterListener {
-        private boolean mCalledOnFilterComplete = false;
-
-        public void onFilterComplete(int count) {
-            mCalledOnFilterComplete = true;
-        }
-
-        public boolean hasCalledOnFilterComplete() {
-            return mCalledOnFilterComplete;
-        }
-    }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java b/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java
index 4309dbb..f4ac880 100644
--- a/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java
@@ -16,6 +16,9 @@
 
 package android.widget.cts;
 
+import android.graphics.drawable.ColorDrawable;
+import android.test.suitebuilder.annotation.SmallTest;
+import org.mockito.ArgumentCaptor;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -49,6 +52,10 @@
 
 import java.io.IOException;
 
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.*;
+
+@SmallTest
 public class FrameLayoutTest extends ActivityInstrumentationTestCase2<FrameLayoutCtsActivity> {
     private Activity mActivity;
     private Instrumentation mInstrumentation;
@@ -94,17 +101,12 @@
         assertTrue(foreground.isVisible());
         final Rect rect = foreground.getBounds();
         // foreground has been stretched
-        new PollingCheck() {
-            @Override
-            protected boolean check() {
-                return mFrameLayout.getHeight() == rect.bottom - rect.top;
-            }
-        }.run();
+        PollingCheck.waitFor(() -> mFrameLayout.getHeight() == rect.bottom - rect.top);
         assertEquals(mFrameLayout.getWidth(), rect.right - rect.left);
 
         // should get a new foreground again, because former foreground has been stretched
         final BitmapDrawable newForeground =
-                (BitmapDrawable) mActivity.getResources().getDrawable(R.drawable.size_48x48);
+                (BitmapDrawable) mActivity.getDrawable(R.drawable.size_48x48);
         compareScaledPixels(48, newForeground.getIntrinsicHeight());
         compareScaledPixels(48, newForeground.getIntrinsicWidth());
         assertTrue(mFrameLayout.getHeight() > newForeground.getIntrinsicHeight());
@@ -156,7 +158,7 @@
         assertEquals(textView.getMeasuredWidth(), frameLayout.getMeasuredWidth());
 
         // measureAll is false and text view is GONE, text view will NOT be measured
-        mActivity.runOnUiThread(() -> {
+        mInstrumentation.runOnMainSync(() -> {
             textView.setVisibility(View.GONE);
             frameLayout.requestLayout();
         });
@@ -169,11 +171,12 @@
         assertEquals(button.getMeasuredWidth(), frameLayout.getMeasuredWidth());
 
         // measureAll is true and text view is GONE, text view will be measured
-        mActivity.runOnUiThread(() -> {
+        mInstrumentation.runOnMainSync(() -> {
             frameLayout.setMeasureAllChildren(true);
             frameLayout.requestLayout();
         });
         mInstrumentation.waitForIdleSync();
+        assertTrue(frameLayout.getMeasureAllChildren());
         assertTrue(frameLayout.getConsiderGoneChildrenWhenMeasuring());
         assertEquals(textView.getMeasuredHeight(), frameLayout.getMeasuredHeight());
         assertEquals(textView.getMeasuredWidth(), frameLayout.getMeasuredWidth());
@@ -285,21 +288,25 @@
         assertEquals("Foreground tint mode inflated correctly",
                 PorterDuff.Mode.SRC_OVER, inflatedView.getForegroundTintMode());
 
-        MockDrawable foreground = new MockDrawable();
+        final Drawable foreground = spy(new ColorDrawable());
         FrameLayout view = new FrameLayout(mActivity);
 
         view.setForeground(foreground);
-        assertFalse("No foreground tint applied by default", foreground.hasCalledSetTint());
+        verify(foreground, never()).setTintList(any(ColorStateList.class));
 
-        view.setForegroundTintList(ColorStateList.valueOf(Color.WHITE));
-        assertTrue("Foreground tint applied when setForegroundTintList() called after setForeground()",
-                foreground.hasCalledSetTint());
+        view.setForegroundTintList(ColorStateList.valueOf(Color.RED));
+        final ArgumentCaptor<ColorStateList> colorStateListCaptor =
+                ArgumentCaptor.forClass(ColorStateList.class);
+        verify(foreground, times(1)).setTintList(colorStateListCaptor.capture());
+        assertEquals(1, colorStateListCaptor.getValue().getColors().length);
+        assertEquals(Color.RED, colorStateListCaptor.getValue().getColors()[0]);
 
-        foreground.reset();
+        reset(foreground);
         view.setForeground(null);
         view.setForeground(foreground);
-        assertTrue("Foreground tint applied when setForegroundTintList() called before setForeground()",
-                foreground.hasCalledSetTint());
+        verify(foreground, times(1)).setTintList(colorStateListCaptor.capture());
+        assertEquals(1, colorStateListCaptor.getValue().getColors().length);
+        assertEquals(Color.RED, colorStateListCaptor.getValue().getColors()[0]);
     }
 
     private static void assertCenterAligned(View container, Drawable drawable) {
@@ -319,38 +326,6 @@
         return Xml.asAttributeSet(parser);
     }
 
-    private static class MockDrawable extends Drawable {
-        private boolean mCalledSetTint = false;
-
-        @Override
-        public void draw(Canvas canvas) {}
-
-        @Override
-        public void setAlpha(int alpha) {}
-
-        @Override
-        public void setColorFilter(ColorFilter cf) {}
-
-        @Override
-        public void setTintList(ColorStateList tint) {
-            super.setTintList(tint);
-            mCalledSetTint = true;
-        }
-
-        @Override
-        public int getOpacity() {
-            return 0;
-        }
-
-        public boolean hasCalledSetTint() {
-            return mCalledSetTint;
-        }
-
-        public void reset() {
-            mCalledSetTint = false;
-        }
-    }
-
     private static class MyFrameLayout extends FrameLayout {
         public MyFrameLayout(Context context) {
             super(context);
diff --git a/tests/tests/widget/src/android/widget/cts/GalleryTest.java b/tests/tests/widget/src/android/widget/cts/GalleryTest.java
index dd39461..5394319 100644
--- a/tests/tests/widget/src/android/widget/cts/GalleryTest.java
+++ b/tests/tests/widget/src/android/widget/cts/GalleryTest.java
@@ -16,40 +16,29 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 import android.app.Activity;
 import android.app.Instrumentation;
-import android.content.ComponentName;
 import android.content.Context;
-import android.content.Intent;
 import android.cts.util.WidgetTestUtils;
-import android.graphics.drawable.Drawable;
 import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
 import android.test.ViewAsserts;
 import android.util.AttributeSet;
 import android.util.Xml;
-import android.view.ContextMenu;
 import android.view.Gravity;
 import android.view.KeyEvent;
-import android.view.MenuItem;
-import android.view.SubMenu;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.View.OnCreateContextMenuListener;
 import android.view.ViewGroup.LayoutParams;
 import android.view.animation.Transformation;
 import android.widget.AdapterView;
 import android.widget.BaseAdapter;
 import android.widget.Gallery;
 import android.widget.ImageView;
-import android.widget.AdapterView.OnItemSelectedListener;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
 
@@ -348,37 +337,4 @@
                 R.drawable.testimage,
         };
     }
-
-    private static class MockOnItemSelectedListener implements OnItemSelectedListener {
-        private boolean mIsItemSelected;
-        private boolean mNothingSelected;
-        private int mItemSelectedCalledCount;
-
-        public boolean isItemSelected() {
-            return mIsItemSelected;
-        }
-
-        public boolean hasNothingSelected() {
-            return mNothingSelected;
-        }
-
-        public int getItemSelectedCalledCount() {
-            return mItemSelectedCalledCount;
-        }
-
-        public void reset() {
-            mIsItemSelected = false;
-            mNothingSelected = true;
-            mItemSelectedCalledCount = 0;
-        }
-
-        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
-            mIsItemSelected = true;
-            mItemSelectedCalledCount++;
-        }
-
-        public void onNothingSelected(AdapterView<?> parent) {
-            mNothingSelected = true;
-        }
-    }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/GridViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/GridViewCtsActivity.java
index 7b2e7a3..47ad5d8 100644
--- a/tests/tests/widget/src/android/widget/cts/GridViewCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/GridViewCtsActivity.java
@@ -16,17 +16,16 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
 import android.app.Activity;
 import android.os.Bundle;
+import android.widget.GridView;
 
 /**
  * A minimal application for {@link GridView} test.
  */
 public class GridViewCtsActivity extends Activity {
     /**
-     * Called with the activity is first created.
+     * Called when the activity is first created.
      */
     @Override
     public void onCreate(Bundle savedInstanceState) {
diff --git a/tests/tests/widget/src/android/widget/cts/GridViewTest.java b/tests/tests/widget/src/android/widget/cts/GridViewTest.java
index 7b83416..e770395 100644
--- a/tests/tests/widget/src/android/widget/cts/GridViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/GridViewTest.java
@@ -16,12 +16,6 @@
 
 package android.widget.cts;
 
-import android.test.suitebuilder.annotation.MediumTest;
-import android.widget.cts.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.content.Context;
@@ -30,9 +24,11 @@
 import android.database.DataSetObserver;
 import android.graphics.Rect;
 import android.test.ActivityInstrumentationTestCase;
-import android.test.TouchUtils;
 import android.test.UiThreadTest;
 import android.test.ViewAsserts;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.util.AttributeSet;
 import android.util.Xml;
 import android.view.Gravity;
@@ -47,12 +43,23 @@
 import android.widget.GridView;
 import android.widget.ImageView;
 import android.widget.ListAdapter;
-import android.widget.AdapterView.OnItemClickListener;
 import android.widget.cts.util.ViewTestUtils;
 
+import org.xmlpull.v1.XmlPullParser;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.*;
+
 /**
  * Test {@link GridView}.
  */
+@SmallTest
 public class GridViewTest extends ActivityInstrumentationTestCase<GridViewCtsActivity> {
     private GridView mGridView;
     private Activity mActivity;
@@ -62,22 +69,15 @@
         super("android.widget.cts", GridViewCtsActivity.class);
     }
 
-    private GridView findGridViewById(int id) {
-        return (GridView) mActivity.findViewById(id);
-    }
-
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mGridView = null;
-        mActivity = getActivity();
-        new PollingCheck() {
-            @Override
-            protected boolean check() {
-                return mActivity.hasWindowFocus();
-            }
-        }.run();
+
         mInstrumentation = getInstrumentation();
+        mActivity = getActivity();
+        mGridView = (GridView) mActivity.findViewById(R.id.gridview);
+
+        PollingCheck.waitFor(() -> mActivity.hasWindowFocus());
     }
 
     public void testConstructor() {
@@ -87,6 +87,14 @@
 
         new GridView(mActivity, null, android.R.attr.gridViewStyle);
 
+        new GridView(mActivity, null, 0, android.R.style.Widget_DeviceDefault_GridView);
+
+        new GridView(mActivity, null, 0, android.R.style.Widget_DeviceDefault_Light_GridView);
+
+        new GridView(mActivity, null, 0, android.R.style.Widget_Material_GridView);
+
+        new GridView(mActivity, null, 0, android.R.style.Widget_Material_Light_GridView);
+
         XmlPullParser parser = mActivity.getResources().getXml(R.layout.gridview_layout);
         AttributeSet attrs = Xml.asAttributeSet(parser);
         new GridView(mActivity, attrs);
@@ -111,8 +119,8 @@
         }
     }
 
+    @UiThreadTest
     public void testAccessAdapter() {
-        mGridView = new GridView(mActivity);
         // set Adapter
         ImageAdapter adapter = new ImageAdapter(mActivity);
         mGridView.setAdapter(adapter);
@@ -122,8 +130,8 @@
         assertNull(mGridView.getAdapter());
     }
 
+    @UiThreadTest
     public void testSetSelection() {
-        mGridView = new GridView(mActivity);
         mGridView.setSelection(0);
         assertEquals(0, mGridView.getSelectedItemPosition());
 
@@ -136,10 +144,10 @@
 
     public void testPressKey() {
         final int NUM_COLUMNS = 3;
-        mGridView = findGridViewById(R.id.gridview);
 
-        MockOnItemClickListener listener = new MockOnItemClickListener();
-        mGridView.setOnItemClickListener(listener);
+        GridView.OnItemClickListener mockItemClickListener =
+                mock(GridView.OnItemClickListener.class);
+        mGridView.setOnItemClickListener(mockItemClickListener);
 
         // this test case can not be ran in UI thread.
         mActivity.runOnUiThread(new Runnable() {
@@ -172,20 +180,19 @@
         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
         assertEquals(NUM_COLUMNS, mGridView.getSelectedItemPosition());
 
-        assertFalse(listener.hasOnItemClickCalled());
+        verify(mockItemClickListener, never()).onItemClick(any(AdapterView.class), any(View.class),
+                anyInt(), anyLong());
         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
-        assertTrue(listener.hasOnItemClickCalled());
+        verify(mockItemClickListener, times(1)).onItemClick(eq(mGridView), any(View.class),
+                eq(NUM_COLUMNS), eq((long) NUM_COLUMNS));
 
-        listener.reset();
-        assertFalse(listener.hasOnItemClickCalled());
+        reset(mockItemClickListener);
         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_ENTER);
-        assertTrue(listener.hasOnItemClickCalled());
+        verify(mockItemClickListener, times(1)).onItemClick(eq(mGridView), any(View.class),
+                eq(NUM_COLUMNS), eq((long) NUM_COLUMNS));
     }
 
     public void testSetGravity() {
-        mGridView = findGridViewById(R.id.gridview);
-
-        View child;
         final int NUM_COLUMNS = 1;
         // this test case can not be ran in UI thread.
         mActivity.runOnUiThread(new Runnable() {
@@ -207,8 +214,8 @@
         });
         mInstrumentation.waitForIdleSync();
 
-        child = mGridView.getChildAt(0); // get the first view.
-        ViewAsserts.assertHorizontalCenterAligned(mGridView, child);
+        assertEquals(Gravity.CENTER_HORIZONTAL, mGridView.getGravity());
+        ViewAsserts.assertHorizontalCenterAligned(mGridView, mGridView.getChildAt(0));
 
         mActivity.runOnUiThread(new Runnable() {
             public void run() {
@@ -219,8 +226,9 @@
         });
         mInstrumentation.waitForIdleSync();
 
-        child = mGridView.getChildAt(0); // get the first view.
-        ViewAsserts.assertLeftAligned(mGridView, child, mGridView.getListPaddingLeft());
+        assertEquals(Gravity.LEFT, mGridView.getGravity());
+        ViewAsserts.assertLeftAligned(mGridView, mGridView.getChildAt(0),
+                mGridView.getListPaddingLeft());
 
         mActivity.runOnUiThread(new Runnable() {
             public void run() {
@@ -231,41 +239,34 @@
         });
         mInstrumentation.waitForIdleSync();
 
-        child = mGridView.getChildAt(0); // get the first view.
-        ViewAsserts.assertRightAligned(mGridView, child, mGridView.getListPaddingRight());
+        assertEquals(Gravity.RIGHT, mGridView.getGravity());
+        ViewAsserts.assertRightAligned(mGridView, mGridView.getChildAt(0),
+                mGridView.getListPaddingRight());
     }
 
-    public void testSetHorizontalSpacing() {
-        testSetHorizontalSpacing(View.LAYOUT_DIRECTION_LTR);
+    public void testAccessHorizontalSpacing() {
+        verifyAccessHorizontalSpacing(View.LAYOUT_DIRECTION_LTR);
     }
 
-    public void testSetHorizontalSpacingRTL() {
-        testSetHorizontalSpacing(View.LAYOUT_DIRECTION_RTL);
+    public void testAccessHorizontalSpacingRTL() {
+        verifyAccessHorizontalSpacing(View.LAYOUT_DIRECTION_RTL);
     }
 
-    public void testSetHorizontalSpacing(final int layoutDir) {
-        mGridView = findGridViewById(R.id.gridview);
-        mActivity.runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mGridView.setLayoutDirection(layoutDir);
-            }
-        });
+    private void verifyAccessHorizontalSpacing(final int layoutDir) {
+        mActivity.runOnUiThread(() -> mGridView.setLayoutDirection(layoutDir));
         mGridView.setStretchMode(GridView.NO_STRETCH);
         // Number of columns should be big enough, otherwise the
         // horizontal spacing cannot be correctly verified.
         mGridView.setNumColumns(28);
 
-
-        // this test case can not be ran in UI thread.
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                mGridView.setAdapter(new MockGridViewAdapter(3));
-                mGridView.setHorizontalSpacing(0);
-            }
+        mActivity.runOnUiThread(() ->  {
+            mGridView.setAdapter(new MockGridViewAdapter(3));
+            mGridView.setHorizontalSpacing(0);
         });
         mInstrumentation.waitForIdleSync();
 
+        assertEquals(0, mGridView.getRequestedHorizontalSpacing());
+        assertEquals(0, mGridView.getHorizontalSpacing());
         View child0 = mGridView.getChildAt(0);
         View child1 = mGridView.getChildAt(1);
         if (layoutDir == View.LAYOUT_DIRECTION_LTR) {
@@ -274,13 +275,11 @@
             assertEquals(0, child0.getLeft() - child1.getRight());
         }
 
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                mGridView.setHorizontalSpacing(5);
-            }
-        });
+        mActivity.runOnUiThread(() -> mGridView.setHorizontalSpacing(5));
         mInstrumentation.waitForIdleSync();
 
+        assertEquals(5, mGridView.getRequestedHorizontalSpacing());
+        assertEquals(5, mGridView.getHorizontalSpacing());
         child0 = mGridView.getChildAt(0);
         child1 = mGridView.getChildAt(1);
         if (layoutDir == View.LAYOUT_DIRECTION_LTR) {
@@ -290,36 +289,28 @@
         }
     }
 
-    public void testSetVerticalSpacing() {
-        mGridView = findGridViewById(R.id.gridview);
-
-        // this test case can not be ran in UI thread.
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                mGridView.setAdapter(new MockGridViewAdapter(3));
-                mGridView.setVerticalSpacing(0);
-            }
+    public void testAccessVerticalSpacing() {
+        mActivity.runOnUiThread(() -> {
+            mGridView.setAdapter(new MockGridViewAdapter(3));
+            mGridView.setVerticalSpacing(0);
         });
         mInstrumentation.waitForIdleSync();
 
+        assertEquals(0, mGridView.getVerticalSpacing());
         View child0 = mGridView.getChildAt(0);
         View child1 = mGridView.getChildAt(1);
         assertEquals(0, child1.getTop() - child0.getBottom());
 
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                mGridView.setVerticalSpacing(5);
-            }
-        });
+        mActivity.runOnUiThread(() -> mGridView.setVerticalSpacing(5));
         mInstrumentation.waitForIdleSync();
 
+        assertEquals(5, mGridView.getVerticalSpacing());
         child0 = mGridView.getChildAt(0);
         child1 = mGridView.getChildAt(1);
         assertEquals(5, child1.getTop() - child0.getBottom());
     }
 
     public void testAccessStretchMode() {
-        mGridView = findGridViewById(R.id.gridview);
         View child;
 
         final int NUM_COLUMNS = 8;
@@ -417,8 +408,6 @@
     }
 
     public void testSetNumColumns() {
-        mGridView = findGridViewById(R.id.gridview);
-
         // this test case can not be ran in UI thread.
         mActivity.runOnUiThread(new Runnable() {
             public void run() {
@@ -459,13 +448,12 @@
         }
     }
 
+    public void testDefaultNumColumns() {
+        final GridView gridView = new GridView(mActivity);
+        assertEquals(gridView.getNumColumns(), GridView.AUTO_FIT);
+    }
+
     public void testGetNumColumns() {
-        mGridView = new GridView(mActivity);
-
-        assertEquals(mGridView.getNumColumns(), GridView.AUTO_FIT);
-
-        mGridView = findGridViewById(R.id.gridview);
-
         mActivity.runOnUiThread(new Runnable() {
             public void run() {
                 mGridView.setAdapter(new MockGridViewAdapter(10));
@@ -532,36 +520,33 @@
         // Do not test it. It's implementation detail.
     }
 
-    public void testSetColumnWidth() {
-        mGridView = findGridViewById(R.id.gridview);
-
-        // this test case can not be ran in UI thread.
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                mGridView.setAdapter(new MockGridViewAdapter(10));
-                mGridView.setNumColumns(GridView.AUTO_FIT);
-                mGridView.setHorizontalSpacing(0);
-                mGridView.setVerticalSpacing(0);
-                mGridView.setColumnWidth(0);
-            }
+    public void testAccessColumnWidth() {
+        mActivity.runOnUiThread(() -> {
+            mGridView.setAdapter(new MockGridViewAdapter(10));
+            mGridView.setNumColumns(GridView.AUTO_FIT);
+            mGridView.setHorizontalSpacing(0);
+            mGridView.setVerticalSpacing(0);
+            mGridView.setColumnWidth(0);
         });
         mInstrumentation.waitForIdleSync();
 
         // Verify whether column number equals 2.
+        assertEquals(0, mGridView.getRequestedColumnWidth());
+        assertEquals(mGridView.getWidth() / 2, mGridView.getColumnWidth());
         View child0 = mGridView.getChildAt(0);
         View child1 = mGridView.getChildAt(1);
         View child2 = mGridView.getChildAt(2);
         assertEquals(child0.getBottom(), child1.getBottom());
         assertEquals(child0.getLeft(), child2.getLeft());
 
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                mGridView.setNumColumns(GridView.AUTO_FIT);
-                mGridView.setColumnWidth(Integer.MAX_VALUE);
-            }
+        mActivity.runOnUiThread(() -> {
+            mGridView.setNumColumns(GridView.AUTO_FIT);
+            mGridView.setColumnWidth(Integer.MAX_VALUE);
         });
         mInstrumentation.waitForIdleSync();
 
+        assertEquals(Integer.MAX_VALUE, mGridView.getRequestedColumnWidth());
+        assertEquals(mGridView.getWidth(), mGridView.getColumnWidth());
         child0 = mGridView.getChildAt(0);
         child1 = mGridView.getChildAt(1);
         assertEquals(child0.getBottom(), child1.getTop());
@@ -570,7 +555,6 @@
 
     @MediumTest
     public void testFullyDetachUnusedViewOnScroll() {
-        mGridView = findGridViewById(R.id.gridview);
         final AttachDetachAwareView theView = new AttachDetachAwareView(mActivity);
         ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mGridView, () -> {
             mGridView.setAdapter(new DummyAdapter(1000, theView));
@@ -596,7 +580,6 @@
 
     @MediumTest
     public void testFullyDetachUnusedViewOnReLayout() {
-        mGridView = findGridViewById(R.id.gridview);
         final AttachDetachAwareView theView = new AttachDetachAwareView(mActivity);
         ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mGridView, () -> {
             mGridView.setAdapter(new DummyAdapter(1000, theView));
@@ -620,7 +603,6 @@
 
     @MediumTest
     public void testFullyDetachUnusedViewOnScrollForFocus() {
-        mGridView = findGridViewById(R.id.gridview);
         final AttachDetachAwareView theView = new AttachDetachAwareView(mActivity);
         ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mGridView, () -> {
             mGridView.setAdapter(new DummyAdapter(1000, theView));
@@ -639,24 +621,63 @@
             ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mGridView, null);
         }
         assertEquals("the view should be re-attached", 2, theView.mOnAttachCount);
-        assertEquals("the view should not recieve another detach", 1, theView.mOnDetachCount);
+        assertEquals("the view should not receive another detach", 1, theView.mOnDetachCount);
         assertFalse(theView.isTemporarilyDetached());
     }
 
-    private static class MockGridView extends GridView {
-        private boolean mCalledOnMeasure = false;
-        private boolean mCalledOnFocusChanged = false;
+    @LargeTest
+    public void testSmoothScrollByOffset() {
+        final int itemCount = 300;
+        mActivity.runOnUiThread(() -> {
+            mGridView.setAdapter(new MockGridViewAdapter(itemCount));
+            mGridView.setNumColumns(GridView.AUTO_FIT);
+            mGridView.setHorizontalSpacing(0);
+            mGridView.setVerticalSpacing(0);
+            mGridView.setColumnWidth(Integer.MAX_VALUE);
+        });
+        mInstrumentation.waitForIdleSync();
 
-        public boolean hasCalledOnMeasure() {
-            return mCalledOnMeasure;
+        assertEquals(0, mGridView.getFirstVisiblePosition());
+
+        // Register a scroll listener on our GridView. The listener will notify our latch
+        // when the "target" item comes into view. If that never happens, the latch will
+        // time out and fail the test.
+        final CountDownLatch latch = new CountDownLatch(1);
+        final int positionToScrollTo = itemCount - 10;
+        mGridView.setOnScrollListener(new AbsListView.OnScrollListener() {
+            @Override
+            public void onScrollStateChanged(AbsListView view, int scrollState) {
+            }
+
+            @Override
+            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
+                    int totalItemCount) {
+                if ((positionToScrollTo >= firstVisibleItem) &&
+                        (positionToScrollTo <= (firstVisibleItem + visibleItemCount))) {
+                    latch.countDown();
+                }
+            }
+        });
+        int offset = positionToScrollTo - mGridView.getLastVisiblePosition();
+        mActivity.runOnUiThread(() -> mGridView.smoothScrollByOffset(offset));
+
+        boolean result = false;
+        try {
+            result = latch.await(20, TimeUnit.SECONDS);
+        } catch (InterruptedException e) {
+            // ignore
         }
+        assertTrue("Timed out while waiting for the target view to be scrolled into view", result);
+    }
+
+    private static class MockGridView extends GridView {
+        private boolean mCalledOnFocusChanged = false;
 
         public boolean hasCalledOnFocusChanged() {
             return mCalledOnFocusChanged;
         }
 
         public void reset() {
-            mCalledOnMeasure = false;
             mCalledOnFocusChanged = false;
         }
 
@@ -684,48 +705,11 @@
         }
 
         @Override
-        protected int computeVerticalScrollExtent() {
-            return super.computeVerticalScrollExtent();
-        }
-
-        @Override
-        protected int computeVerticalScrollOffset() {
-            return super.computeVerticalScrollOffset();
-        }
-
-        @Override
-        protected int computeVerticalScrollRange() {
-            return super.computeVerticalScrollRange();
-        }
-
-        @Override
         protected void onFocusChanged(boolean gainFocus, int direction,
                 Rect previouslyFocusedRect) {
             mCalledOnFocusChanged = true;
             super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
         }
-
-        @Override
-        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-            mCalledOnMeasure = true;
-            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-        }
-    }
-
-    class MockOnItemClickListener implements OnItemClickListener {
-        private boolean mOnItemClickCalled = false;
-
-        public boolean hasOnItemClickCalled() {
-            return mOnItemClickCalled;
-        }
-
-        public void reset() {
-            mOnItemClickCalled = false;
-        }
-
-        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-            mOnItemClickCalled = true;
-        }
     }
 
     private class MockGridViewAdapter implements ListAdapter, Filterable {
@@ -735,10 +719,6 @@
             mCount = count;
         }
 
-        MockGridViewAdapter() {
-            this(1);
-        }
-
         public boolean areAllItemsEnabled() {
             return true;
         }
diff --git a/tests/tests/widget/src/android/widget/cts/HeaderViewListAdapterTest.java b/tests/tests/widget/src/android/widget/cts/HeaderViewListAdapterTest.java
index 2b92a4d..426fe5aa 100644
--- a/tests/tests/widget/src/android/widget/cts/HeaderViewListAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/HeaderViewListAdapterTest.java
@@ -31,6 +31,8 @@
 
 import java.util.ArrayList;
 
+import static org.mockito.Mockito.mock;
+
 /**
  * Test {@link HeaderViewListAdapter}.
  */
@@ -334,21 +336,21 @@
         HeaderViewFullAdapter fullAdapter = new HeaderViewFullAdapter();
         HeaderViewListAdapter headerViewListAdapter =
             new HeaderViewListAdapter(null, null, fullAdapter);
-        DataSetObserver observer = new HeaderViewDataSetObserver();
-        headerViewListAdapter.registerDataSetObserver(observer);
-        assertSame(observer, fullAdapter.getDataSetObserver());
+        DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
+        headerViewListAdapter.registerDataSetObserver(mockDataSetObserver);
+        assertSame(mockDataSetObserver, fullAdapter.getDataSetObserver());
     }
 
     public void testUnregisterDataSetObserver() {
         HeaderViewFullAdapter fullAdapter = new HeaderViewFullAdapter();
         HeaderViewListAdapter headerViewListAdapter =
             new HeaderViewListAdapter(null, null, fullAdapter);
-        DataSetObserver observer = new HeaderViewDataSetObserver();
-        headerViewListAdapter.registerDataSetObserver(observer);
+        DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
+        headerViewListAdapter.registerDataSetObserver(mockDataSetObserver);
 
         headerViewListAdapter.unregisterDataSetObserver(null);
-        assertSame(observer, fullAdapter.getDataSetObserver());
-        headerViewListAdapter.unregisterDataSetObserver(observer);
+        assertSame(mockDataSetObserver, fullAdapter.getDataSetObserver());
+        headerViewListAdapter.unregisterDataSetObserver(mockDataSetObserver);
         assertNull(fullAdapter.getDataSetObserver());
     }
 
@@ -504,16 +506,4 @@
         protected void publishResults(CharSequence constraint, Filter.FilterResults results) {
         }
     }
-
-    private class HeaderViewDataSetObserver extends DataSetObserver {
-        @Override
-        public void onChanged() {
-            // Do nothing
-        }
-
-        @Override
-        public void onInvalidated() {
-            // Do nothing
-        }
-    }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java b/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java
index afdc869..7a5f8f1 100644
--- a/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java
@@ -16,12 +16,6 @@
 
 package android.widget.cts;
 
-import android.widget.FrameLayout;
-import android.widget.cts.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-
 import android.app.Activity;
 import android.content.Context;
 import android.cts.util.PollingCheck;
@@ -32,10 +26,14 @@
 import android.util.AttributeSet;
 import android.util.Xml;
 import android.view.View;
-import android.view.ViewGroup;
 import android.view.View.MeasureSpec;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
 import android.widget.HorizontalScrollView;
 import android.widget.TextView;
+
+import org.xmlpull.v1.XmlPullParser;
+
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -800,55 +798,34 @@
         }
 
         if (fromY != toY) {
-            new PollingCheck() {
-                @Override
-                protected boolean check() {
-                    return isInRange(mScrollView.getScrollY(), fromY, toY);
-                }
-            }.run();
+            PollingCheck.waitFor(() -> isInRange(mScrollView.getScrollY(), fromY, toY));
         }
 
         if (fromX != toX) {
-            new PollingCheck() {
-                @Override
-                protected boolean check() {
-                    return isInRange(mScrollView.getScrollX(), fromX, toX);
-                }
-            }.run();
+            PollingCheck.waitFor(() -> isInRange(mScrollView.getScrollX(), fromX, toX));
         }
 
-        new PollingCheck() {
-            @Override
-            protected boolean check() {
-                return toX == mScrollView.getScrollX() && toY == mScrollView.getScrollY();
-            }
-        }.run();
+        PollingCheck.waitFor(
+                () -> toX == mScrollView.getScrollX() && toY == mScrollView.getScrollY());
     }
 
     private void pollingCheckFling(final int startPosition, final boolean movingRight) {
-        new PollingCheck() {
-            @Override
-            protected boolean check() {
-                if (movingRight) {
-                    return mScrollView.getScrollX() > startPosition;
-                }
-                return mScrollView.getScrollX() < startPosition;
+        PollingCheck.waitFor(() -> {
+            if (movingRight) {
+                return mScrollView.getScrollX() > startPosition;
             }
-        }.run();
+            return mScrollView.getScrollX() < startPosition;
+        });
 
-        new PollingCheck() {
-            private int mPreviousScrollX = mScrollView.getScrollX();
-
-            @Override
-            protected boolean check() {
-                if (mScrollView.getScrollX() == mPreviousScrollX) {
-                    return true;
-                } else {
-                    mPreviousScrollX = mScrollView.getScrollX();
-                    return false;
-                }
+        final int[] previousScrollX = new int[] { mScrollView.getScrollX() };
+        PollingCheck.waitFor(() -> {
+            if (mScrollView.getScrollX() == previousScrollX[0]) {
+                return true;
+            } else {
+                previousScrollX[0] = mScrollView.getScrollX();
+                return false;
             }
-        }.run();
+        });
     }
 
     public static class MyView extends View {
diff --git a/tests/tests/widget/src/android/widget/cts/ImageButtonCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ImageButtonCtsActivity.java
new file mode 100644
index 0000000..5f91950
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ImageButtonCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.ImageButton;
+
+/**
+ * A minimal application for {@link ImageButton} test.
+ */
+public class ImageButtonCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.imagebutton_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/ImageButtonTest.java b/tests/tests/widget/src/android/widget/cts/ImageButtonTest.java
index 05c0e3f..485024b 100644
--- a/tests/tests/widget/src/android/widget/cts/ImageButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ImageButtonTest.java
@@ -16,27 +16,42 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-
-import android.test.AndroidTestCase;
-import android.util.AttributeSet;
-import android.util.Xml;
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.widget.ImageButton;
+import android.widget.cts.util.TestUtils;
 
-public class ImageButtonTest extends AndroidTestCase {
+@SmallTest
+public class ImageButtonTest extends ActivityInstrumentationTestCase2<ImageButtonCtsActivity> {
+    private Instrumentation mInstrumentation;
+    private Activity mActivity;
+    private ImageButton mImageButton;
+
+    public ImageButtonTest() {
+        super("android.widget.cts", ImageButtonCtsActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mInstrumentation = getInstrumentation();
+        mActivity = getActivity();
+        mImageButton = (ImageButton) mActivity.findViewById(R.id.image_button);
+    }
+
     public void testConstructor() {
-        XmlPullParser parser = getContext().getResources().getXml(R.layout.imagebutton_test);
-        AttributeSet attrs = Xml.asAttributeSet(parser);
-        assertNotNull(attrs);
-
-        new ImageButton(getContext());
-
-        new ImageButton(getContext(), attrs);
-
-        new ImageButton(getContext(), attrs, 0);
+        new ImageButton(mActivity);
+        new ImageButton(mActivity, null);
+        new ImageButton(mActivity, null, android.R.attr.imageButtonStyle);
+        new ImageButton(mActivity, null, 0, android.R.style.Widget_DeviceDefault_ImageButton);
+        new ImageButton(mActivity, null, 0, android.R.style.Widget_DeviceDefault_Light_ImageButton);
+        new ImageButton(mActivity, null, 0, android.R.style.Widget_Material_ImageButton);
+        new ImageButton(mActivity, null, 0, android.R.style.Widget_Material_Light_ImageButton);
 
         try {
             new ImageButton(null);
@@ -57,7 +72,23 @@
         }
     }
 
-    public void testOnSetAlpha() {
-        // Do not test, it's controlled by View. Implementation details.
+    public void testImageSource() {
+        Drawable imageButtonDrawable = mImageButton.getDrawable();
+        TestUtils.assertAllPixelsOfColor("Default source is red", imageButtonDrawable,
+                imageButtonDrawable.getIntrinsicWidth(), imageButtonDrawable.getIntrinsicHeight(),
+                true, Color.RED, 1, false);
+
+        mInstrumentation.runOnMainSync(() -> mImageButton.setImageResource(R.drawable.icon_green));
+        imageButtonDrawable = mImageButton.getDrawable();
+        TestUtils.assertAllPixelsOfColor("New source is green", imageButtonDrawable,
+                imageButtonDrawable.getIntrinsicWidth(), imageButtonDrawable.getIntrinsicHeight(),
+                true, Color.GREEN, 1, false);
+
+        mInstrumentation.runOnMainSync(
+                () -> mImageButton.setImageDrawable(mActivity.getDrawable(R.drawable.icon_yellow)));
+        imageButtonDrawable = mImageButton.getDrawable();
+        TestUtils.assertAllPixelsOfColor("New source is yellow", imageButtonDrawable,
+                imageButtonDrawable.getIntrinsicWidth(), imageButtonDrawable.getIntrinsicHeight(),
+                true, Color.YELLOW, 1, false);
     }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/LinearLayoutTest.java b/tests/tests/widget/src/android/widget/cts/LinearLayoutTest.java
index 4d0903a..24878ce 100644
--- a/tests/tests/widget/src/android/widget/cts/LinearLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/LinearLayoutTest.java
@@ -16,15 +16,20 @@
 
 package android.widget.cts;
 
-import org.xmlpull.v1.XmlPullParser;
-
+import android.annotation.ColorInt;
 import android.app.Activity;
+import android.app.Instrumentation;
 import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.Color;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
 import android.test.ActivityInstrumentationTestCase;
 import android.test.ViewAsserts;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.util.AttributeSet;
 import android.util.Xml;
+import android.view.Gravity;
 import android.view.View;
 import android.view.View.MeasureSpec;
 import android.view.ViewGroup;
@@ -34,7 +39,10 @@
 import android.widget.LinearLayout.LayoutParams;
 import android.widget.ListView;
 import android.widget.TextView;
-import android.widget.cts.R;
+import android.widget.cts.util.TestUtils;
+import android.widget.cts.util.ViewTestUtils;
+
+import org.xmlpull.v1.XmlPullParser;
 
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -42,6 +50,7 @@
 /**
  * Test {@link LinearLayout}.
  */
+@SmallTest
 public class LinearLayoutTest extends ActivityInstrumentationTestCase<LinearLayoutCtsActivity> {
     private Context mContext;
     private Activity mActivity;
@@ -152,9 +161,9 @@
      */
     public void testAccessWeightSum() {
         LinearLayout parent = (LinearLayout) mActivity.findViewById(R.id.weightsum);
-        TextView weight02 = (TextView) mActivity.findViewById(R.id.weight_0_2);
-        TextView weight05 = (TextView) mActivity.findViewById(R.id.weight_0_5);
-        TextView weight03 = (TextView) mActivity.findViewById(R.id.weight_0_3);
+        TextView weight02 = (TextView) parent.findViewById(R.id.weight_0_2);
+        TextView weight05 = (TextView) parent.findViewById(R.id.weight_0_5);
+        TextView weight03 = (TextView) parent.findViewById(R.id.weight_0_3);
 
         assertNotNull(parent);
         assertNotNull(weight02);
@@ -399,6 +408,182 @@
         assertEquals(parent.getWidth(), rightView.getRight());
     }
 
+    public void testVerticalCenterGravityOnHorizontalLayout() {
+        final Instrumentation instrumentation = getInstrumentation();
+        LinearLayout parent = (LinearLayout) mActivity.findViewById(R.id.weightsum);
+        TextView leftView = (TextView) parent.findViewById(R.id.weight_0_2);
+        TextView centerView = (TextView) parent.findViewById(R.id.weight_0_5);
+        TextView rightView = (TextView) parent.findViewById(R.id.weight_0_3);
+
+        instrumentation.runOnMainSync(() -> parent.setLayoutDirection(View.LAYOUT_DIRECTION_LTR));
+        instrumentation.waitForIdleSync();
+
+        int originalLeftViewRight = leftView.getRight();
+        int originalCenterViewLeft = centerView.getLeft();
+        int originalCenterViewRight = centerView.getRight();
+        int originalRightViewLeft = rightView.getLeft();
+
+        instrumentation.runOnMainSync(() -> parent.setVerticalGravity(Gravity.CENTER_VERTICAL));
+        instrumentation.waitForIdleSync();
+
+        assertEquals(Gravity.CENTER_VERTICAL, parent.getGravity() & Gravity.VERTICAL_GRAVITY_MASK);
+
+        ViewAsserts.assertVerticalCenterAligned(parent, leftView);
+        ViewAsserts.assertVerticalCenterAligned(parent, centerView);
+        ViewAsserts.assertVerticalCenterAligned(parent, rightView);
+
+        final int parentHeight = parent.getHeight();
+
+        int verticalOffset = (parentHeight - leftView.getHeight()) / 2;
+        assertEquals(verticalOffset, leftView.getTop());
+        assertEquals(verticalOffset + leftView.getHeight(), leftView.getBottom());
+        assertEquals(0, leftView.getLeft());
+        assertEquals(originalLeftViewRight, leftView.getRight());
+
+        verticalOffset = (parentHeight - centerView.getHeight()) / 2;
+        assertEquals(verticalOffset, centerView.getTop());
+        assertEquals(verticalOffset + centerView.getHeight(), centerView.getBottom());
+        assertEquals(originalCenterViewLeft, centerView.getLeft());
+        assertEquals(originalCenterViewRight, centerView.getRight());
+
+        verticalOffset = (parentHeight - rightView.getHeight()) / 2;
+        assertEquals(verticalOffset, rightView.getTop());
+        assertEquals(verticalOffset + rightView.getHeight(), rightView.getBottom());
+        assertEquals(originalRightViewLeft, rightView.getLeft());
+        assertEquals(parent.getWidth(), rightView.getRight());
+    }
+
+    public void testBottomGravityOnHorizontalLayout() {
+        final Instrumentation instrumentation = getInstrumentation();
+        LinearLayout parent = (LinearLayout) mActivity.findViewById(R.id.weightsum);
+        TextView leftView = (TextView) parent.findViewById(R.id.weight_0_2);
+        TextView centerView = (TextView) parent.findViewById(R.id.weight_0_5);
+        TextView rightView = (TextView) parent.findViewById(R.id.weight_0_3);
+
+        instrumentation.runOnMainSync(() -> parent.setLayoutDirection(View.LAYOUT_DIRECTION_LTR));
+        instrumentation.waitForIdleSync();
+
+        int originalLeftViewRight = leftView.getRight();
+        int originalCenterViewLeft = centerView.getLeft();
+        int originalCenterViewRight = centerView.getRight();
+        int originalRightViewLeft = rightView.getLeft();
+
+        instrumentation.runOnMainSync(() -> parent.setVerticalGravity(Gravity.BOTTOM));
+        instrumentation.waitForIdleSync();
+
+        assertEquals(Gravity.BOTTOM, parent.getGravity() & Gravity.VERTICAL_GRAVITY_MASK);
+
+        ViewAsserts.assertBottomAligned(parent, leftView);
+        ViewAsserts.assertBottomAligned(parent, centerView);
+        ViewAsserts.assertBottomAligned(parent, rightView);
+
+        final int parentHeight = parent.getHeight();
+
+        assertEquals(parentHeight - leftView.getHeight(), leftView.getTop());
+        assertEquals(parentHeight, leftView.getBottom());
+        assertEquals(0, leftView.getLeft());
+        assertEquals(originalLeftViewRight, leftView.getRight());
+
+        assertEquals(parentHeight - centerView.getHeight(), centerView.getTop());
+        assertEquals(parentHeight, centerView.getBottom());
+        assertEquals(originalCenterViewLeft, centerView.getLeft());
+        assertEquals(originalCenterViewRight, centerView.getRight());
+
+        assertEquals(parentHeight - rightView.getHeight(), rightView.getTop());
+        assertEquals(parentHeight, rightView.getBottom());
+        assertEquals(originalRightViewLeft, rightView.getLeft());
+        assertEquals(parent.getWidth(), rightView.getRight());
+    }
+
+    public void testHorizontalCenterGravityOnVerticalLayout() {
+        final Instrumentation instrumentation = getInstrumentation();
+        LinearLayout parent = (LinearLayout) mActivity.findViewById(R.id.weightsum_vertical);
+        TextView topView = (TextView) parent.findViewById(R.id.weight_0_1);
+        TextView centerView = (TextView) parent.findViewById(R.id.weight_0_4);
+        TextView bottomView = (TextView) parent.findViewById(R.id.weight_0_5);
+
+        instrumentation.runOnMainSync(() -> parent.setLayoutDirection(View.LAYOUT_DIRECTION_LTR));
+        instrumentation.waitForIdleSync();
+
+        final int parentWidth = parent.getHeight();
+
+        int originalTopViewBottom = topView.getBottom();
+        int originalCenterViewTop = centerView.getTop();
+        int originalCenterViewBottom = centerView.getBottom();
+        int originalBottomViewTop = bottomView.getTop();
+
+        instrumentation.runOnMainSync(() -> parent.setHorizontalGravity(Gravity.CENTER_HORIZONTAL));
+        instrumentation.waitForIdleSync();
+
+        assertEquals(Gravity.CENTER_HORIZONTAL,
+                parent.getGravity() & Gravity.HORIZONTAL_GRAVITY_MASK);
+
+        ViewAsserts.assertHorizontalCenterAligned(parent, topView);
+        ViewAsserts.assertHorizontalCenterAligned(parent, centerView);
+        ViewAsserts.assertHorizontalCenterAligned(parent, bottomView);
+
+        int horizontalOffset = (parentWidth - topView.getWidth()) / 2;
+        assertEquals(0, topView.getTop());
+        assertEquals(originalTopViewBottom, topView.getBottom());
+        assertEquals(horizontalOffset, topView.getLeft());
+        assertEquals(horizontalOffset + topView.getWidth(), topView.getRight());
+
+        horizontalOffset = (parentWidth - centerView.getWidth()) / 2;
+        assertEquals(originalCenterViewTop, centerView.getTop());
+        assertEquals(originalCenterViewBottom, centerView.getBottom());
+        assertEquals(horizontalOffset, centerView.getLeft());
+        assertEquals(horizontalOffset + centerView.getWidth(), centerView.getRight());
+
+        horizontalOffset = (parentWidth - bottomView.getWidth()) / 2;
+        assertEquals(originalBottomViewTop, bottomView.getTop());
+        assertEquals(parent.getHeight(), bottomView.getBottom());
+        assertEquals(horizontalOffset, bottomView.getLeft());
+        assertEquals(horizontalOffset + bottomView.getWidth(), bottomView.getRight());
+    }
+
+    public void testRightGravityOnVerticalLayout() {
+        final Instrumentation instrumentation = getInstrumentation();
+        LinearLayout parent = (LinearLayout) mActivity.findViewById(R.id.weightsum_vertical);
+        TextView topView = (TextView) parent.findViewById(R.id.weight_0_1);
+        TextView centerView = (TextView) parent.findViewById(R.id.weight_0_4);
+        TextView bottomView = (TextView) parent.findViewById(R.id.weight_0_5);
+
+        instrumentation.runOnMainSync(() -> parent.setLayoutDirection(View.LAYOUT_DIRECTION_LTR));
+        instrumentation.waitForIdleSync();
+
+        final int parentWidth = parent.getHeight();
+
+        int originalTopViewBottom = topView.getBottom();
+        int originalCenterViewTop = centerView.getTop();
+        int originalCenterViewBottom = centerView.getBottom();
+        int originalBottomViewTop = bottomView.getTop();
+
+        instrumentation.runOnMainSync(() -> parent.setHorizontalGravity(Gravity.RIGHT));
+        instrumentation.waitForIdleSync();
+
+        assertEquals(Gravity.RIGHT,
+                parent.getGravity() & Gravity.HORIZONTAL_GRAVITY_MASK);
+
+        ViewAsserts.assertRightAligned(parent, topView);
+        ViewAsserts.assertRightAligned(parent, centerView);
+        ViewAsserts.assertRightAligned(parent, bottomView);
+
+        assertEquals(0, topView.getTop());
+        assertEquals(originalTopViewBottom, topView.getBottom());
+        assertEquals(parentWidth - topView.getWidth(), topView.getLeft());
+        assertEquals(parentWidth, topView.getRight());
+
+        assertEquals(originalCenterViewTop, centerView.getTop());
+        assertEquals(originalCenterViewBottom, centerView.getBottom());
+        assertEquals(parentWidth - centerView.getWidth(), centerView.getLeft());
+        assertEquals(parentWidth, centerView.getRight());
+
+        assertEquals(originalBottomViewTop, bottomView.getTop());
+        assertEquals(parent.getHeight(), bottomView.getBottom());
+        assertEquals(parentWidth - bottomView.getWidth(), bottomView.getLeft());
+        assertEquals(parentWidth, bottomView.getRight());
+    }
+
     private void checkBounds(final ViewGroup viewGroup, final View view,
             final CountDownLatch countDownLatch, final int left, final int top,
             final int width, final int height) {
@@ -471,6 +656,523 @@
         countDownLatch3.await(500, TimeUnit.MILLISECONDS);
     }
 
+    private void verifyVisualsOfVerticalLayoutWithDivider(LinearLayout parent,
+            int expectedDividerPositionMask,
+            int expectedDividerSize, @ColorInt int expectedDividerColor,
+            int expectedDividerPadding) {
+        final int parentWidth = parent.getWidth();
+        final int parentHeight = parent.getHeight();
+
+        final boolean expectingTopDivider =
+                (expectedDividerPositionMask & LinearLayout.SHOW_DIVIDER_BEGINNING) != 0;
+        final boolean expectingMiddleDivider =
+                (expectedDividerPositionMask & LinearLayout.SHOW_DIVIDER_MIDDLE) != 0;
+        final boolean expectingBottomDivider =
+                (expectedDividerPositionMask & LinearLayout.SHOW_DIVIDER_END) != 0;
+        final int expectedDividerCount = (expectingTopDivider ? 1 : 0)
+                + (expectingMiddleDivider ? 1 : 0) + (expectingBottomDivider ? 1 : 0);
+
+        final int expectedChildHeight =
+                (parentHeight - expectedDividerCount * expectedDividerSize) / 2;
+
+        final int expectedTopChildTop = expectingTopDivider ? expectedDividerSize : 0;
+        TestUtils.assertRegionPixelsOfColor("Region of first child is blue", parent,
+                new Rect(0, expectedTopChildTop, parentWidth,
+                        expectedTopChildTop + expectedChildHeight),
+                Color.BLUE, 1, true);
+
+        final int expectedBottomChildBottom =
+                expectingBottomDivider ? parentHeight - expectedDividerSize : parentHeight;
+        TestUtils.assertRegionPixelsOfColor("Region of second child is green", parent,
+                new Rect(0, expectedBottomChildBottom - expectedChildHeight, parentWidth,
+                        expectedBottomChildBottom),
+                Color.GREEN, 1, true);
+
+        if (expectedDividerSize == 0) {
+            return;
+        }
+
+        // Do we expect top divider?
+        if (expectingTopDivider) {
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of top divider is " + TestUtils.formatColorToHex(expectedDividerColor),
+                    parent,
+                    new Rect(expectedDividerPadding, 0, parentWidth - expectedDividerPadding,
+                            expectedDividerSize),
+                    expectedDividerColor, 1, true);
+            TestUtils.assertRegionPixelsOfColor("Region of left padding of top divider is yellow",
+                    parent,
+                    new Rect(0, 0, expectedDividerPadding, expectedDividerSize),
+                    Color.YELLOW, 1, true);
+            TestUtils.assertRegionPixelsOfColor("Region of right padding of top divider is yellow",
+                    parent,
+                    new Rect(parentWidth - expectedDividerPadding, 0, parentWidth,
+                            expectedDividerSize),
+                    Color.YELLOW, 1, true);
+        }
+
+        // Do we expect middle divider?
+        if (expectingMiddleDivider) {
+            final int expectedMiddleDividerTop = expectedTopChildTop + expectedChildHeight;
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of middle divider is " +
+                            TestUtils.formatColorToHex(expectedDividerColor),
+                    parent,
+                    new Rect(expectedDividerPadding, expectedMiddleDividerTop,
+                            parentWidth - expectedDividerPadding,
+                            expectedMiddleDividerTop + expectedDividerSize),
+                    expectedDividerColor, 1, true);
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of left padding of middle divider is yellow",
+                    parent,
+                    new Rect(0, expectedMiddleDividerTop, expectedDividerPadding,
+                            expectedMiddleDividerTop + expectedDividerSize),
+                    Color.YELLOW, 1, true);
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of right padding of middle divider is yellow",
+                    parent,
+                    new Rect(parentWidth - expectedDividerPadding, expectedMiddleDividerTop,
+                            parentWidth, expectedMiddleDividerTop + expectedDividerSize),
+                    Color.YELLOW, 1, true);
+        }
+
+        // Do we expect bottom divider?
+        if (expectingBottomDivider) {
+            final int expectedBottomDividerTop = expectedBottomChildBottom;
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of bottom divider is " +
+                            TestUtils.formatColorToHex(expectedDividerColor),
+                    parent,
+                    new Rect(expectedDividerPadding, expectedBottomDividerTop,
+                            parentWidth - expectedDividerPadding,
+                            expectedBottomDividerTop + expectedDividerSize),
+                    expectedDividerColor, 1, true);
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of left padding of bottom divider is yellow",
+                    parent,
+                    new Rect(0, expectedBottomDividerTop, expectedDividerPadding,
+                            expectedBottomDividerTop + expectedDividerSize),
+                    Color.YELLOW, 1, true);
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of right padding of bottom divider is yellow",
+                    parent,
+                    new Rect(parentWidth - expectedDividerPadding, expectedBottomDividerTop,
+                            parentWidth, expectedBottomDividerTop + expectedDividerSize),
+                    Color.YELLOW, 1, true);
+        }
+    }
+
+    /**
+     * layout of vertical LinearLayout.
+     * -----------------------------------
+     * | ------------------------------- |
+     * | |            child1           | |
+     * | ------------------------------- |
+     * | - - - - - - divider - - - - - - |
+     * | ------------------------------- |
+     * | |            child2           | |
+     * | ------------------------------- |
+     * -----------------------------------
+     *
+     * Parent is filled with yellow color. Child 1 is filled with green and child 2 is filled
+     * with blue. Divider is red at the beginning. Throughout this method we reconfigure the
+     * visibility, drawable and paddings of the divider and verify the overall visuals of the
+     * container.
+     */
+    public void testDividersInVerticalLayout() {
+        final LinearLayout parent =
+                (LinearLayout) mActivity.findViewById(R.id.vertical_with_divider);
+
+        final Instrumentation instrumentation = getInstrumentation();
+
+        final Resources res = mActivity.getResources();
+        final int dividerSize = res.getDimensionPixelSize(R.dimen.linear_layout_divider_size);
+        final int dividerPadding = res.getDimensionPixelSize(R.dimen.linear_layout_divider_padding);
+
+        assertEquals(LinearLayout.SHOW_DIVIDER_MIDDLE, parent.getShowDividers());
+        assertEquals(dividerPadding, parent.getDividerPadding());
+        final Drawable dividerDrawable = parent.getDividerDrawable();
+        TestUtils.assertAllPixelsOfColor("Divider is red", dividerDrawable,
+                dividerDrawable.getIntrinsicWidth(), dividerDrawable.getIntrinsicHeight(),
+                false, Color.RED, 1, true);
+
+        // Test the initial visuals of the entire parent
+        verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Change the divider to magenta
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setDividerDrawable(
+                        mActivity.getDrawable(R.drawable.linear_layout_divider_magenta)));
+        verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.MAGENTA, dividerPadding);
+
+        // Change the divider to null (no divider effectively)
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setDividerDrawable(null));
+        verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                0, Color.TRANSPARENT, 0);
+
+        // Change the divider back to red
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setDividerDrawable(
+                        mActivity.getDrawable(R.drawable.linear_layout_divider_red)));
+        verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Change the padding to half the original size
+        final int halfPadding = dividerPadding / 2;
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setDividerPadding(halfPadding));
+        assertEquals(halfPadding, parent.getDividerPadding());
+        verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.RED, halfPadding);
+
+        // Change the padding to twice the original size
+        final int doublePadding = dividerPadding * 2;
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setDividerPadding(doublePadding));
+        assertEquals(doublePadding, parent.getDividerPadding());
+        verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.RED, doublePadding);
+
+        // And back to the original padding
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setDividerPadding(dividerPadding));
+        assertEquals(dividerPadding, parent.getDividerPadding());
+        verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Set show dividers to NONE (no divider effectively)
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(LinearLayout.SHOW_DIVIDER_NONE));
+        assertEquals(LinearLayout.SHOW_DIVIDER_NONE, parent.getShowDividers());
+        verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_NONE,
+                0, Color.TRANSPARENT, 0);
+
+        // Show only top divider
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(LinearLayout.SHOW_DIVIDER_BEGINNING));
+        assertEquals(LinearLayout.SHOW_DIVIDER_BEGINNING, parent.getShowDividers());
+        verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_BEGINNING,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Show only bottom divider
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(LinearLayout.SHOW_DIVIDER_END));
+        assertEquals(LinearLayout.SHOW_DIVIDER_END, parent.getShowDividers());
+        verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_END,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Show top and bottom dividers
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(
+                        LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_END));
+        assertEquals(LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_END,
+                parent.getShowDividers());
+        verifyVisualsOfVerticalLayoutWithDivider(parent,
+                LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_END,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Show top and middle dividers
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(
+                        LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE));
+        assertEquals(LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE,
+                parent.getShowDividers());
+        verifyVisualsOfVerticalLayoutWithDivider(parent,
+                LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Show middle and bottom dividers
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(
+                        LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_END));
+        assertEquals(LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_END,
+                parent.getShowDividers());
+        verifyVisualsOfVerticalLayoutWithDivider(parent,
+                LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_END,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Show top, middle and bottom dividers
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(
+                        LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE
+                                | LinearLayout.SHOW_DIVIDER_END));
+        assertEquals(
+                LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE
+                        | LinearLayout.SHOW_DIVIDER_END,
+                parent.getShowDividers());
+        verifyVisualsOfVerticalLayoutWithDivider(parent,
+                LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE
+                        | LinearLayout.SHOW_DIVIDER_END,
+                dividerSize, Color.RED, dividerPadding);
+    }
+
+    private void verifyVisualsOfHorizontalLayoutWithDivider(LinearLayout parent,
+            int expectedDividerPositionMask,
+            int expectedDividerSize, @ColorInt int expectedDividerColor,
+            int expectedDividerPadding) {
+        final int parentWidth = parent.getWidth();
+        final int parentHeight = parent.getHeight();
+
+        final boolean expectingLeftDivider =
+                (expectedDividerPositionMask & LinearLayout.SHOW_DIVIDER_BEGINNING) != 0;
+        final boolean expectingMiddleDivider =
+                (expectedDividerPositionMask & LinearLayout.SHOW_DIVIDER_MIDDLE) != 0;
+        final boolean expectingRightDivider =
+                (expectedDividerPositionMask & LinearLayout.SHOW_DIVIDER_END) != 0;
+        final int expectedDividerCount = (expectingLeftDivider ? 1 : 0)
+                + (expectingMiddleDivider ? 1 : 0) + (expectingRightDivider ? 1 : 0);
+
+        final int expectedChildWidth =
+                (parentWidth - expectedDividerCount * expectedDividerSize) / 2;
+
+        final int expectedLeftChildLeft = expectingLeftDivider ? expectedDividerSize : 0;
+        TestUtils.assertRegionPixelsOfColor("Region of first child is blue", parent,
+                new Rect(expectedLeftChildLeft, 0,
+                        expectedLeftChildLeft + expectedChildWidth, parentHeight),
+                Color.BLUE, 1, true);
+
+        final int expectedRightChildRight =
+                expectingRightDivider ? parentWidth - expectedDividerSize : parentWidth;
+        TestUtils.assertRegionPixelsOfColor("Region of second child is green", parent,
+                new Rect(expectedRightChildRight - expectedChildWidth, 0, expectedRightChildRight,
+                        parentHeight),
+                Color.GREEN, 1, true);
+
+        if (expectedDividerSize == 0) {
+            return;
+        }
+
+        // Do we expect left divider?
+        if (expectingLeftDivider) {
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of left divider is " + TestUtils.formatColorToHex(expectedDividerColor),
+                    parent,
+                    new Rect(0, expectedDividerPadding, expectedDividerSize,
+                            parentHeight - expectedDividerPadding),
+                    expectedDividerColor, 1, true);
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of top padding of left divider is yellow",
+                    parent,
+                    new Rect(0, 0, expectedDividerSize, expectedDividerPadding),
+                    Color.YELLOW, 1, true);
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of bottom padding of left divider is yellow",
+                    parent,
+                    new Rect(0, parentHeight - expectedDividerPadding, expectedDividerSize,
+                            parentHeight),
+                    Color.YELLOW, 1, true);
+        }
+
+        // Do we expect middle divider?
+        if (expectingMiddleDivider) {
+            final int expectedMiddleDividerLeft = expectedLeftChildLeft + expectedChildWidth;
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of middle divider is " +
+                            TestUtils.formatColorToHex(expectedDividerColor),
+                    parent,
+                    new Rect(expectedMiddleDividerLeft, expectedDividerPadding,
+                            expectedMiddleDividerLeft + expectedDividerSize,
+                            parentHeight - expectedDividerPadding),
+                    expectedDividerColor, 1, true);
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of top padding of middle divider is yellow",
+                    parent,
+                    new Rect(expectedMiddleDividerLeft, 0,
+                            expectedMiddleDividerLeft + expectedDividerSize,
+                            expectedDividerPadding),
+                    Color.YELLOW, 1, true);
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of bottom padding of middle divider is yellow",
+                    parent,
+                    new Rect(expectedMiddleDividerLeft, parentHeight - expectedDividerPadding,
+                            expectedMiddleDividerLeft + expectedDividerSize, parentHeight),
+                    Color.YELLOW, 1, true);
+        }
+
+        // Do we expect right divider?
+        if (expectingRightDivider) {
+            final int expectedRightDividerLeft = expectedRightChildRight;
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of right divider is " +
+                            TestUtils.formatColorToHex(expectedDividerColor),
+                    parent,
+                    new Rect(expectedRightDividerLeft, expectedDividerPadding,
+                            expectedRightDividerLeft + expectedDividerSize,
+                            parentHeight - expectedDividerPadding),
+                    expectedDividerColor, 1, true);
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of top padding of right divider is yellow",
+                    parent,
+                    new Rect(expectedRightDividerLeft, 0,
+                            expectedRightDividerLeft + expectedDividerSize,
+                            expectedDividerPadding),
+                    Color.YELLOW, 1, true);
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of bottom padding of right divider is yellow",
+                    parent,
+                    new Rect(expectedRightDividerLeft, parentHeight - expectedDividerPadding,
+                            expectedRightDividerLeft + expectedDividerSize, parentHeight),
+                    Color.YELLOW, 1, true);
+        }
+    }
+
+    /**
+     * layout of horizontal LinearLayout.
+     * -----------------------------------
+     * | ------------  |  -------------  |
+     * | |          |     |           |  |
+     * | |          |  d  |           |  |
+     * | |          |  i  |           |  |
+     * | |          |  v  |           |  |
+     * | |  child1  |  i  |  child2   |  |
+     * | |          |  d  |           |  |
+     * | |          |  e  |           |  |
+     * | |          |  r  |           |  |
+     * | |          |     |           |  |
+     * | ------------  |  -------------  |
+     * -----------------------------------
+     *
+     * Parent is filled with yellow color. Child 1 is filled with green and child 2 is filled
+     * with blue. Divider is red at the beginning. Throughout this method we reconfigure the
+     * visibility, drawable and paddings of the divider and verify the overall visuals of the
+     * container.
+     */
+    public void testDividersInHorizontalLayout() {
+        final LinearLayout parent =
+                (LinearLayout) mActivity.findViewById(R.id.horizontal_with_divider);
+
+        final Instrumentation instrumentation = getInstrumentation();
+
+        instrumentation.runOnMainSync(() -> parent.setLayoutDirection(View.LAYOUT_DIRECTION_LTR));
+        instrumentation.waitForIdleSync();
+
+        final Resources res = mActivity.getResources();
+        final int dividerSize = res.getDimensionPixelSize(R.dimen.linear_layout_divider_size);
+        final int dividerPadding = res.getDimensionPixelSize(R.dimen.linear_layout_divider_padding);
+
+        assertEquals(LinearLayout.SHOW_DIVIDER_MIDDLE, parent.getShowDividers());
+        assertEquals(dividerPadding, parent.getDividerPadding());
+        final Drawable dividerDrawable = parent.getDividerDrawable();
+        TestUtils.assertAllPixelsOfColor("Divider is red", dividerDrawable,
+                dividerDrawable.getIntrinsicWidth(), dividerDrawable.getIntrinsicHeight(),
+                false, Color.RED, 1, true);
+
+        // Test the initial visuals of the entire parent
+        verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Change the divider to magenta
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setDividerDrawable(
+                        mActivity.getDrawable(R.drawable.linear_layout_divider_magenta)));
+        verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.MAGENTA, dividerPadding);
+
+        // Change the divider to null (no divider effectively)
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setDividerDrawable(null));
+        verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                0, Color.TRANSPARENT, 0);
+
+        // Change the divider back to red
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setDividerDrawable(
+                        mActivity.getDrawable(R.drawable.linear_layout_divider_red)));
+        verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Change the padding to half the original size
+        final int halfPadding = dividerPadding / 2;
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setDividerPadding(halfPadding));
+        assertEquals(halfPadding, parent.getDividerPadding());
+        verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.RED, halfPadding);
+
+        // Change the padding to twice the original size
+        final int doublePadding = dividerPadding * 2;
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setDividerPadding(doublePadding));
+        assertEquals(doublePadding, parent.getDividerPadding());
+        verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.RED, doublePadding);
+
+        // And back to the original padding
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setDividerPadding(dividerPadding));
+        assertEquals(dividerPadding, parent.getDividerPadding());
+        verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Set show dividers to NONE (no divider effectively)
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(LinearLayout.SHOW_DIVIDER_NONE));
+        assertEquals(LinearLayout.SHOW_DIVIDER_NONE, parent.getShowDividers());
+        verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_NONE,
+                0, Color.TRANSPARENT, 0);
+
+        // Show only left divider
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(LinearLayout.SHOW_DIVIDER_BEGINNING));
+        assertEquals(LinearLayout.SHOW_DIVIDER_BEGINNING, parent.getShowDividers());
+        verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_BEGINNING,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Show only right divider
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(LinearLayout.SHOW_DIVIDER_END));
+        assertEquals(LinearLayout.SHOW_DIVIDER_END, parent.getShowDividers());
+        verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_END,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Show left and right dividers
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(
+                        LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_END));
+        assertEquals(LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_END,
+                parent.getShowDividers());
+        verifyVisualsOfHorizontalLayoutWithDivider(parent,
+                LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_END,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Show left and middle dividers
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(
+                        LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE));
+        assertEquals(LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE,
+                parent.getShowDividers());
+        verifyVisualsOfHorizontalLayoutWithDivider(parent,
+                LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Show middle and right dividers
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(
+                        LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_END));
+        assertEquals(LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_END,
+                parent.getShowDividers());
+        verifyVisualsOfHorizontalLayoutWithDivider(parent,
+                LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_END,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Show left, middle and right dividers
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(
+                        LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE
+                                | LinearLayout.SHOW_DIVIDER_END));
+        assertEquals(
+                LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE
+                        | LinearLayout.SHOW_DIVIDER_END,
+                parent.getShowDividers());
+        verifyVisualsOfHorizontalLayoutWithDivider(parent,
+                LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE
+                        | LinearLayout.SHOW_DIVIDER_END,
+                dividerSize, Color.RED, dividerPadding);
+    }
+
     private class MockListView extends ListView {
         private final static int DEFAULT_CHILD_BASE_LINE = 1;
 
diff --git a/tests/tests/widget/src/android/widget/cts/LinearLayout_LayoutParamsTest.java b/tests/tests/widget/src/android/widget/cts/LinearLayout_LayoutParamsTest.java
index 4f36e94..8773247 100644
--- a/tests/tests/widget/src/android/widget/cts/LinearLayout_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/LinearLayout_LayoutParamsTest.java
@@ -16,16 +16,14 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
-import org.xmlpull.v1.XmlPullParserException;
-
 import android.content.res.XmlResourceParser;
 import android.test.AndroidTestCase;
+import android.view.Gravity;
 import android.view.ViewGroup.LayoutParams;
 import android.view.ViewGroup.MarginLayoutParams;
 import android.widget.LinearLayout;
 import android.widget.cts.util.XmlUtils;
+import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
 
@@ -34,17 +32,47 @@
         XmlResourceParser p = mContext.getResources().getLayout(R.layout.linearlayout_layout);
 
         XmlUtils.beginDocument(p, "LinearLayout");
-        new LinearLayout.LayoutParams(getContext(), p);
+        LinearLayout.LayoutParams linearLayoutParams =
+                new LinearLayout.LayoutParams(getContext(), p);
+        assertEquals(LayoutParams.MATCH_PARENT, linearLayoutParams.width);
+        assertEquals(LayoutParams.WRAP_CONTENT, linearLayoutParams.height);
+        assertEquals(0.0f, linearLayoutParams.weight);
+        assertEquals(-1, linearLayoutParams.gravity);
 
-        new LinearLayout.LayoutParams(320, 240);
+        linearLayoutParams = new LinearLayout.LayoutParams(320, 240);
+        assertEquals(320, linearLayoutParams.width);
+        assertEquals(240, linearLayoutParams.height);
+        assertEquals(0.0f, linearLayoutParams.weight);
+        assertEquals(-1, linearLayoutParams.gravity);
 
-        new LinearLayout.LayoutParams(320, 240, 0);
+        linearLayoutParams = new LinearLayout.LayoutParams(360, 320, 0.4f);
+        assertEquals(360, linearLayoutParams.width);
+        assertEquals(320, linearLayoutParams.height);
+        assertEquals(0.4f, linearLayoutParams.weight);
+        assertEquals(-1, linearLayoutParams.gravity);
 
-        LayoutParams layoutParams = new LayoutParams(320, 480);
-        new LinearLayout.LayoutParams(layoutParams);
+        LayoutParams layoutParams = new LayoutParams(200, 480);
+        linearLayoutParams = new LinearLayout.LayoutParams(layoutParams);
+        assertEquals(200, linearLayoutParams.width);
+        assertEquals(480, linearLayoutParams.height);
+        assertEquals(0.0f, linearLayoutParams.weight);
+        assertEquals(-1, linearLayoutParams.gravity);
 
-        MarginLayoutParams marginLayoutParams = new MarginLayoutParams(320, 480);
-        new LinearLayout.LayoutParams(marginLayoutParams);
+        MarginLayoutParams marginLayoutParams = new MarginLayoutParams(320, 200);
+        linearLayoutParams = new LinearLayout.LayoutParams(marginLayoutParams);
+        assertEquals(320, linearLayoutParams.width);
+        assertEquals(200, linearLayoutParams.height);
+        assertEquals(0.0f, linearLayoutParams.weight);
+        assertEquals(-1, linearLayoutParams.gravity);
+
+        LinearLayout.LayoutParams linearLayoutParams2 = new LinearLayout.LayoutParams(360, 720);
+        linearLayoutParams2.weight = 0.9f;
+        linearLayoutParams2.gravity = Gravity.RIGHT;
+        linearLayoutParams = new LinearLayout.LayoutParams(linearLayoutParams2);
+        assertEquals(360, linearLayoutParams.width);
+        assertEquals(720, linearLayoutParams.height);
+        assertEquals(0.9f, linearLayoutParams.weight);
+        assertEquals(Gravity.RIGHT, linearLayoutParams.gravity);
     }
 
     public void testDebug() {
diff --git a/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java b/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
index b50f8c9..1564caf 100644
--- a/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
@@ -105,7 +105,16 @@
 
         new ListPopupWindow(mActivity, null, android.R.attr.popupWindowStyle);
 
+        new ListPopupWindow(mActivity, null, 0,
+                android.R.style.Widget_DeviceDefault_ListPopupWindow);
+
+        new ListPopupWindow(mActivity, null, 0,
+                android.R.style.Widget_DeviceDefault_Light_ListPopupWindow);
+
         new ListPopupWindow(mActivity, null, 0, android.R.style.Widget_Material_ListPopupWindow);
+
+        new ListPopupWindow(mActivity, null, 0,
+                android.R.style.Widget_Material_Light_ListPopupWindow);
     }
 
     public void testNoDefaultVisibility() {
@@ -372,17 +381,6 @@
         // Make sure that the modality of the popup window is set up correctly
         assertEquals("Popup window modality", setupAsModal, mPopupWindow.isModal());
 
-        // Determine the location of the popup on the screen so that we can emulate
-        // a tap outside of its bounds to dismiss it
-        final int[] popupOnScreenXY = new int[2];
-        final Rect rect = new Rect();
-        mPopupWindow.getListView().getLocationOnScreen(popupOnScreenXY);
-        mPopupWindow.getBackground().getPadding(rect);
-
-        int emulatedTapX = popupOnScreenXY[0] - rect.left - 20;
-        int emulatedTapY = popupOnScreenXY[1] + mPopupWindow.getListView().getHeight() +
-                rect.top + rect.bottom + 20;
-
         // The logic below uses Instrumentation to emulate a tap outside the bounds of the
         // displayed list popup window. This tap is then treated by the framework to be "split" as
         // the ACTION_OUTSIDE for the popup itself, as well as DOWN / MOVE / UP for the underlying
@@ -392,29 +390,12 @@
         // of Instrumentation is necessary here since Espresso's actions operate at the level
         // of view or data. Also, we don't want to use View.dispatchTouchEvent directly as
         // that would require emulation of two separate sequences as well.
-
-        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
-
-        // Inject DOWN event
-        long downTime = SystemClock.uptimeMillis();
-        MotionEvent eventDown = MotionEvent.obtain(
-                downTime, downTime, MotionEvent.ACTION_DOWN, emulatedTapX, emulatedTapY, 1);
-        instrumentation.sendPointerSync(eventDown);
-
-        // Inject MOVE event
-        long moveTime = SystemClock.uptimeMillis();
-        MotionEvent eventMove = MotionEvent.obtain(
-                moveTime, moveTime, MotionEvent.ACTION_MOVE, emulatedTapX, emulatedTapY, 1);
-        instrumentation.sendPointerSync(eventMove);
-
-        // Inject UP event
-        long upTime = SystemClock.uptimeMillis();
-        MotionEvent eventUp = MotionEvent.obtain(
-                upTime, upTime, MotionEvent.ACTION_UP, emulatedTapX, emulatedTapY, 1);
-        instrumentation.sendPointerSync(eventUp);
-
-        // Wait for the system to process all events in the queue
-        instrumentation.waitForIdleSync();
+        final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+        final ListView popupListView = mPopupWindow.getListView();
+        final Rect rect = new Rect();
+        mPopupWindow.getBackground().getPadding(rect);
+        ViewTestUtils.emulateTapOnScreen(instrumentation, popupListView,
+                -rect.left - 20, popupListView.getHeight() + rect.top + rect.bottom + 20);
 
         // At this point our popup should not be showing and should have notified its
         // dismiss listener
@@ -668,40 +649,6 @@
         verifyNoMoreInteractions(mPopupWindowBuilder.mOnDismissListener);
     }
 
-    /**
-     * Emulates a drag-down gestures by injecting ACTION events with {@link Instrumentation}.
-     */
-    private void emulateDragDownGesture(int emulatedX, int emulatedStartY, int swipeAmount) {
-        // The logic below uses Instrumentation to emulate a swipe / drag gesture to bring up
-        // the popup content.
-
-        // Inject DOWN event
-        long downTime = SystemClock.uptimeMillis();
-        MotionEvent eventDown = MotionEvent.obtain(
-                downTime, downTime, MotionEvent.ACTION_DOWN, emulatedX, emulatedStartY, 1);
-        mInstrumentation.sendPointerSync(eventDown);
-
-        // Inject a sequence of MOVE events that emulate a "swipe down" gesture
-        for (int i = 0; i < 10; i++) {
-            long moveTime = SystemClock.uptimeMillis();
-            final int moveY = emulatedStartY + swipeAmount * i / 10;
-            MotionEvent eventMove = MotionEvent.obtain(
-                    moveTime, moveTime, MotionEvent.ACTION_MOVE, emulatedX, moveY, 1);
-            mInstrumentation.sendPointerSync(eventMove);
-            // sleep for a bit to emulate a 200ms swipe
-            SystemClock.sleep(20);
-        }
-
-        // Inject UP event
-        long upTime = SystemClock.uptimeMillis();
-        MotionEvent eventUp = MotionEvent.obtain(
-                upTime, upTime, MotionEvent.ACTION_UP, emulatedX, emulatedStartY + swipeAmount, 1);
-        mInstrumentation.sendPointerSync(eventUp);
-
-        // Wait for the system to process all events in the queue
-        mInstrumentation.waitForIdleSync();
-    }
-
     public void testCreateOnDragListener() throws Throwable {
         // In this test we want precise control over the height of the popup content since
         // we need to know by how much to swipe down to end the emulated gesture over the
@@ -738,7 +685,8 @@
         int swipeAmount = 2 * popupRowHeight;
 
         // Emulate drag-down gesture with a sequence of motion events
-        emulateDragDownGesture(emulatedX, emulatedStartY, swipeAmount);
+        ViewTestUtils.emulateDragGesture(getInstrumentation(), emulatedX, emulatedStartY,
+                0, swipeAmount);
 
         // We expect the swipe / drag gesture to result in clicking the second item in our list.
         verify(mPopupWindowBuilder.mOnItemClickListener, times(1)).onItemClick(
@@ -952,7 +900,8 @@
             if (mHasItemSelectedListener) {
                 mOnItemSelectedListener = mock(AdapterView.OnItemSelectedListener.class);
                 mPopupWindow.setOnItemSelectedListener(mOnItemSelectedListener);
-                mPopupWindow.setListSelector(mActivity.getDrawable(R.drawable.red_fill));
+                mPopupWindow.setListSelector(
+                        mActivity.getDrawable(R.drawable.red_translucent_fill));
             }
 
             if (mHasDismissListener) {
diff --git a/tests/tests/widget/src/android/widget/cts/ListViewTest.java b/tests/tests/widget/src/android/widget/cts/ListViewTest.java
index e89b3d3..a0d2f57 100644
--- a/tests/tests/widget/src/android/widget/cts/ListViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ListViewTest.java
@@ -16,22 +16,21 @@
 
 package android.widget.cts;
 
-import android.widget.BaseAdapter;
-import android.widget.LinearLayout;
-import android.widget.cts.R;
-
-import org.xmlpull.v1.XmlPullParser;
-
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.content.Context;
 import android.cts.util.PollingCheck;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.os.Parcelable;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.util.AttributeSet;
 import android.util.Pair;
 import android.util.SparseBooleanArray;
@@ -40,25 +39,41 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.animation.LayoutAnimationController;
+import android.widget.AbsListView;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.ArrayAdapter;
+import android.widget.LinearLayout;
 import android.widget.ListView;
 import android.widget.TextView;
+import android.widget.cts.util.TestUtils;
 import android.widget.cts.util.ViewTestUtils;
+import junit.framework.Assert;
+
+import org.xmlpull.v1.XmlPullParser;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-
-import junit.framework.Assert;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 import static org.mockito.Mockito.*;
 
+@SmallTest
 public class ListViewTest extends ActivityInstrumentationTestCase2<ListViewCtsActivity> {
     private final String[] mCountryList = new String[] {
         "Argentina", "Australia", "China", "France", "Germany", "Italy", "Japan", "United States"
     };
+    private final String[] mLongCountryList = new String[] {
+        "Argentina", "Australia", "Belize", "Botswana", "Brazil", "Cameroon", "China", "Cyprus",
+        "Denmark", "Djibouti", "Ethiopia", "Fiji", "Finland", "France", "Gabon", "Germany",
+        "Ghana", "Haiti", "Honduras", "Iceland", "India", "Indonesia", "Ireland", "Italy",
+        "Japan", "Kiribati", "Laos", "Lesotho", "Liberia", "Malaysia", "Mongolia", "Myanmar",
+        "Nauru", "Norway", "Oman", "Pakistan", "Philippines", "Portugal", "Romania", "Russia",
+        "Rwanda", "Singapore", "Slovakia", "Slovenia", "Somalia", "Swaziland", "Togo", "Tuvalu",
+        "Uganda", "Ukraine", "United States", "Vanuatu", "Venezuela", "Zimbabwe"
+    };
     private final String[] mNameList = new String[] {
         "Jacky", "David", "Kevin", "Michael", "Andy"
     };
@@ -69,6 +84,7 @@
     private Instrumentation mInstrumentation;
     private AttributeSet mAttributeSet;
     private ArrayAdapter<String> mAdapter_countries;
+    private ArrayAdapter<String> mAdapter_longCountries;
     private ArrayAdapter<String> mAdapter_names;
     private ArrayAdapter<String> mAdapter_empty;
 
@@ -84,11 +100,13 @@
         XmlPullParser parser = mActivity.getResources().getXml(R.layout.listview_layout);
         mAttributeSet = Xml.asAttributeSet(parser);
 
-        mAdapter_countries = new ArrayAdapter<String>(mActivity,
+        mAdapter_countries = new ArrayAdapter<>(mActivity,
                 android.R.layout.simple_list_item_1, mCountryList);
-        mAdapter_names = new ArrayAdapter<String>(mActivity, android.R.layout.simple_list_item_1,
+        mAdapter_longCountries = new ArrayAdapter<>(mActivity,
+                android.R.layout.simple_list_item_1, mLongCountryList);
+        mAdapter_names = new ArrayAdapter<>(mActivity, android.R.layout.simple_list_item_1,
                 mNameList);
-        mAdapter_empty = new ArrayAdapter<String>(mActivity, android.R.layout.simple_list_item_1,
+        mAdapter_empty = new ArrayAdapter<>(mActivity, android.R.layout.simple_list_item_1,
                 mEmptyList);
 
         mListView = (ListView) mActivity.findViewById(R.id.listview_default);
@@ -142,12 +160,7 @@
 
         Drawable d = mListView.getDivider();
         final Rect r = d.getBounds();
-        new PollingCheck() {
-            @Override
-            protected boolean check() {
-                return r.bottom - r.top > 0;
-            }
-        }.run();
+        PollingCheck.waitFor(() -> r.bottom - r.top > 0);
 
         ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mListView,
                 () -> mListView.setDividerHeight(20));
@@ -266,14 +279,18 @@
         footerView2.setText("footerview2");
 
         mInstrumentation.runOnMainSync(() -> mListView.setFooterDividersEnabled(true));
+        assertTrue(mListView.areFooterDividersEnabled());
         assertEquals(0, mListView.getFooterViewsCount());
 
         mInstrumentation.runOnMainSync(() -> mListView.addFooterView(footerView1, null, true));
+        assertTrue(mListView.areFooterDividersEnabled());
         assertEquals(1, mListView.getFooterViewsCount());
 
-        mInstrumentation.runOnMainSync(() -> mListView.addFooterView(footerView2));
-
-        mInstrumentation.waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> {
+            mListView.setFooterDividersEnabled(false);
+            mListView.addFooterView(footerView2);
+        });
+        assertFalse(mListView.areFooterDividersEnabled());
         assertEquals(2, mListView.getFooterViewsCount());
 
         ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mListView,
@@ -281,10 +298,12 @@
 
         ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mListView,
                 () -> mListView.removeFooterView(footerView1));
+        assertFalse(mListView.areFooterDividersEnabled());
         assertEquals(1, mListView.getFooterViewsCount());
 
         ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mListView,
                 () -> mListView.removeFooterView(footerView2));
+        assertFalse(mListView.areFooterDividersEnabled());
         assertEquals(0, mListView.getFooterViewsCount());
     }
 
@@ -293,18 +312,28 @@
         final TextView headerView2 = (TextView) mActivity.findViewById(R.id.headerview2);
 
         mInstrumentation.runOnMainSync(() -> mListView.setHeaderDividersEnabled(true));
+        assertTrue(mListView.areHeaderDividersEnabled());
         assertEquals(0, mListView.getHeaderViewsCount());
 
         mInstrumentation.runOnMainSync(() -> mListView.addHeaderView(headerView2, null, true));
+        assertTrue(mListView.areHeaderDividersEnabled());
         assertEquals(1, mListView.getHeaderViewsCount());
 
-        mInstrumentation.runOnMainSync(() -> mListView.addHeaderView(headerView1));
+        mInstrumentation.runOnMainSync(() -> {
+            mListView.setHeaderDividersEnabled(false);
+            mListView.addHeaderView(headerView1);
+        });
+        assertFalse(mListView.areHeaderDividersEnabled());
         assertEquals(2, mListView.getHeaderViewsCount());
+
+        mInstrumentation.runOnMainSync(() -> mListView.removeHeaderView(headerView2));
+        assertFalse(mListView.areHeaderDividersEnabled());
+        assertEquals(1, mListView.getHeaderViewsCount());
     }
 
     public void testHeaderFooterType() throws Throwable {
         final TextView headerView = new TextView(getActivity());
-        final List<Pair<View, View>> mismatch = new ArrayList<Pair<View, View>>();
+        final List<Pair<View, View>> mismatch = new ArrayList<>();
         final ArrayAdapter adapter = new ArrayAdapter<String>(mActivity,
                 android.R.layout.simple_list_item_1, mNameList) {
             @Override
@@ -317,7 +346,7 @@
             public View getView(int position, View convertView, ViewGroup parent) {
                 if (position == 0) {
                     if (convertView != null && convertView != headerView) {
-                        mismatch.add(new Pair<View, View>(headerView, convertView));
+                        mismatch.add(new Pair<>(headerView, convertView));
                     }
                     return headerView;
                 } else {
@@ -345,12 +374,7 @@
 
         Drawable defaultDrawable = mListView.getDivider();
         final Rect r = defaultDrawable.getBounds();
-        new PollingCheck() {
-            @Override
-            protected boolean check() {
-                return r.bottom - r.top > 0;
-            }
-        }.run();
+        PollingCheck.waitFor(() -> r.bottom - r.top > 0);
 
         final Drawable d = mActivity.getResources().getDrawable(R.drawable.scenery);
 
@@ -418,8 +442,24 @@
         verifyNoMoreInteractions(onClickListener);
     }
 
-    public void testSaveAndRestoreInstanceState() {
-        // implementation details, do NOT test
+    public void testSaveAndRestoreInstanceState_positionIsRestored() {
+        ListView listView = new ListView(mActivity);
+        listView.setAdapter(mAdapter_countries);
+        assertEquals(0, listView.getSelectedItemPosition());
+
+        int positionToTest = mAdapter_countries.getCount() - 1;
+        listView.setSelection(positionToTest);
+        assertEquals(positionToTest, listView.getSelectedItemPosition());
+        Parcelable savedState = listView.onSaveInstanceState();
+
+        listView.setSelection(positionToTest - 1);
+        assertEquals(positionToTest - 1, listView.getSelectedItemPosition());
+
+        listView.onRestoreInstanceState(savedState);
+        int measureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY);
+        listView.measure(measureSpec,measureSpec);
+        listView.layout(0, 0, 100, 100);
+        assertEquals(positionToTest, listView.getSelectedItemPosition());
     }
 
     public void testDispatchKeyEvent() {
@@ -574,7 +614,7 @@
         ListView listView = new ListView(mActivity);
         List<String> items = new ArrayList<>();
         items.add("hello");
-        Adapter<String> adapter = new Adapter<String>(mActivity, 0, items);
+        Adapter<String> adapter = new Adapter<>(mActivity, 0, items);
         listView.setAdapter(adapter);
 
         int measureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY);
@@ -599,7 +639,7 @@
         listView.addHeaderView(new View(mActivity), null, false);
         List<String> items = new ArrayList<>();
         items.add("hello");
-        Adapter<String> adapter = new Adapter<String>(mActivity, 0, items);
+        Adapter<String> adapter = new Adapter<>(mActivity, 0, items);
         listView.setAdapter(adapter);
 
         listView.setSelection(1);
@@ -930,28 +970,27 @@
     }
 
     public void testTransientStateStableIds() throws Exception {
-        final ListView listView = mListView;
-        final ArrayList<String> items = new ArrayList<String>(Arrays.asList(mCountryList));
-        final StableArrayAdapter<String> adapter = new StableArrayAdapter<String>(mActivity,
+        final ArrayList<String> items = new ArrayList<>(Arrays.asList(mCountryList));
+        final StableArrayAdapter<String> adapter = new StableArrayAdapter<>(mActivity,
                 android.R.layout.simple_list_item_1, items);
 
         ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mListView,
-                () -> listView.setAdapter(adapter));
+                () -> mListView.setAdapter(adapter));
 
         final Object tag = new Object();
-        final View oldItem = listView.getChildAt(2);
+        final View oldItem = mListView.getChildAt(2);
         final CharSequence oldText = ((TextView) oldItem.findViewById(android.R.id.text1))
                 .getText();
         oldItem.setHasTransientState(true);
         oldItem.setTag(tag);
 
-        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, listView,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mListView,
                 () -> {
                     adapter.remove(adapter.getItem(0));
                     adapter.notifyDataSetChanged();
                 });
 
-        final View newItem = listView.getChildAt(1);
+        final View newItem = mListView.getChildAt(1);
         final CharSequence newText = ((TextView) newItem.findViewById(android.R.id.text1))
                 .getText();
 
@@ -975,4 +1014,132 @@
             return true;
         }
     }
+
+    @LargeTest
+    public void testSmoothScrollByOffset() {
+        final int itemCount = mLongCountryList.length;
+
+        mActivity.runOnUiThread(() -> mListView.setAdapter(mAdapter_longCountries));
+        mInstrumentation.waitForIdleSync();
+
+        assertEquals(0, mListView.getFirstVisiblePosition());
+
+        // If we're on a really big display, we might be in a situation where the position
+        // we're going to scroll to is already visible. In that case the logic in the rest
+        // of this test will never fire off a listener callback and then fail the test.
+        final int positionToScrollTo = itemCount - 10;
+        final int lastVisiblePosition = mListView.getLastVisiblePosition();
+        if (positionToScrollTo <= lastVisiblePosition) {
+            return;
+        }
+
+        // Register a scroll listener on our ListView. The listener will notify our latch
+        // when the "target" item comes into view. If that never happens, the latch will
+        // time out and fail the test.
+        final CountDownLatch latch = new CountDownLatch(1);
+        mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
+            @Override
+            public void onScrollStateChanged(AbsListView view, int scrollState) {
+            }
+
+            @Override
+            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
+                    int totalItemCount) {
+                if ((positionToScrollTo >= firstVisibleItem) &&
+                        (positionToScrollTo <= (firstVisibleItem + visibleItemCount))) {
+                    latch.countDown();
+                }
+            }
+        });
+        int offset = positionToScrollTo - lastVisiblePosition;
+        mActivity.runOnUiThread(() -> mListView.smoothScrollByOffset(offset));
+
+        boolean result = false;
+        try {
+            result = latch.await(20, TimeUnit.SECONDS);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+        assertTrue("Timed out while waiting for the target view to be scrolled into view", result);
+    }
+
+    private static class PositionArrayAdapter<T> extends ArrayAdapter<T> {
+        public PositionArrayAdapter(Context context, int resource, List<T> objects) {
+            super(context, resource, objects);
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public boolean hasStableIds() {
+            return true;
+        }
+    }
+
+    public void testGetCheckItemIds() {
+        final ArrayList<String> items = new ArrayList<>(Arrays.asList(mCountryList));
+        final ArrayAdapter<String> adapter = new PositionArrayAdapter<>(mActivity,
+                android.R.layout.simple_list_item_1, items);
+
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mListView,
+                () -> mListView.setAdapter(adapter));
+
+        mInstrumentation.runOnMainSync(
+                () -> mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE));
+        assertTrue(mListView.getCheckItemIds().length == 0);
+
+        mInstrumentation.runOnMainSync(() -> mListView.setItemChecked(2, true));
+        TestUtils.assertIdentical(new long[] { 2 }, mListView.getCheckItemIds());
+
+        mInstrumentation.runOnMainSync(() -> mListView.setItemChecked(4, true));
+        TestUtils.assertIdentical(new long[] { 2, 4 }, mListView.getCheckItemIds());
+
+        mInstrumentation.runOnMainSync(() -> mListView.setItemChecked(2, false));
+        TestUtils.assertIdentical(new long[] { 4 }, mListView.getCheckItemIds());
+
+        mInstrumentation.runOnMainSync(() -> mListView.setItemChecked(4, false));
+        assertTrue(mListView.getCheckItemIds().length == 0);
+    }
+
+    public void testAccessOverscrollHeader() {
+        final Drawable overscrollHeaderDrawable = spy(new ColorDrawable(Color.YELLOW));
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mListView, () -> {
+            mListView.setAdapter(mAdapter_longCountries);
+            mListView.setOverscrollHeader(overscrollHeaderDrawable);
+        });
+
+        assertEquals(overscrollHeaderDrawable, mListView.getOverscrollHeader());
+        verify(overscrollHeaderDrawable, never()).draw(any(Canvas.class));
+
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mListView,
+                () -> mListView.setScrollY(-mListView.getHeight() / 2));
+
+        verify(overscrollHeaderDrawable, atLeastOnce()).draw(any(Canvas.class));
+    }
+
+    public void testAccessOverscrollFooter() {
+        final Drawable overscrollFooterDrawable = spy(new ColorDrawable(Color.MAGENTA));
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mListView, () -> {
+            // Configure ListView to automatically scroll to the selected item
+            mListView.setStackFromBottom(true);
+            mListView.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
+
+            mListView.setAdapter(mAdapter_longCountries);
+            mListView.setOverscrollFooter(overscrollFooterDrawable);
+
+            // Set selection to the last item
+            mListView.setSelection(mAdapter_longCountries.getCount() - 1);
+        });
+
+        assertEquals(overscrollFooterDrawable, mListView.getOverscrollFooter());
+        verify(overscrollFooterDrawable, never()).draw(any(Canvas.class));
+
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mListView,
+                () -> mListView.setScrollY(mListView.getHeight() / 2));
+
+        verify(overscrollFooterDrawable, atLeastOnce()).draw(any(Canvas.class));
+    }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/MediaControllerTest.java b/tests/tests/widget/src/android/widget/cts/MediaControllerTest.java
index 2c60a91..8e312ed 100644
--- a/tests/tests/widget/src/android/widget/cts/MediaControllerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/MediaControllerTest.java
@@ -16,11 +16,6 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.content.Context;
@@ -31,14 +26,17 @@
 import android.util.Xml;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.View.OnClickListener;
 import android.widget.MediaController;
 import android.widget.VideoView;
 
+import org.xmlpull.v1.XmlPullParser;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 
+import static org.mockito.Mockito.mock;
+
 /**
  * Test {@link MediaController}.
  */
@@ -47,7 +45,6 @@
     private MediaController mMediaController;
     private Activity mActivity;
     private Instrumentation mInstrumentation;
-    private static final long DEFAULT_TIMEOUT = 3000;
 
     public MediaControllerTest() {
         super("android.widget.cts", MediaControllerCtsActivity.class);
@@ -151,12 +148,7 @@
         assertTrue(mMediaController.isShowing());
 
         // isShowing() should return false, but MediaController still shows, this may be a bug.
-        new PollingCheck(timeout + 500) {
-            @Override
-            protected boolean check() {
-                return mMediaController.isShowing();
-            }
-        }.run();
+        PollingCheck.waitFor(500, () -> mMediaController.isShowing());
     }
 
     private String prepareSampleVideo() {
@@ -236,9 +228,9 @@
         mMediaController.setAnchorView(videoView);
         mMediaController.setMediaPlayer(mediaPlayerControl);
 
-        final MockOnClickListener next = new MockOnClickListener();
-        final MockOnClickListener prev = new MockOnClickListener();
-        mMediaController.setPrevNextListeners(next, prev);
+        final View.OnClickListener mockNextClickListener = mock(View.OnClickListener.class);
+        final View.OnClickListener mockPrevClickListener = mock(View.OnClickListener.class);
+        mMediaController.setPrevNextListeners(mockNextClickListener, mockPrevClickListener);
 
         mMediaController.show();
 
@@ -258,9 +250,9 @@
         mMediaController.setAnchorView(videoView);
         mMediaController.setMediaPlayer(mediaPlayerControl);
 
-        final MockOnClickListener next = new MockOnClickListener();
-        final MockOnClickListener prev = new MockOnClickListener();
-        mMediaController.setPrevNextListeners(next, prev);
+        final View.OnClickListener mockNextClickListener = mock(View.OnClickListener.class);
+        final View.OnClickListener mockPrevClickListener = mock(View.OnClickListener.class);
+        mMediaController.setPrevNextListeners(mockNextClickListener, mockPrevClickListener);
     }
 
     private static class MockMediaPlayerControl implements MediaController.MediaPlayerControl {
@@ -318,16 +310,4 @@
             return 0;
         }
     }
-
-    private static class MockOnClickListener implements OnClickListener {
-        private boolean mOnClickCalled = false;
-
-        public boolean hasOnClickCalled() {
-            return mOnClickCalled;
-        }
-
-        public void onClick(View v) {
-            mOnClickCalled = true;
-        }
-    }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/MockTextView.java b/tests/tests/widget/src/android/widget/cts/MockTextView.java
index 977e4b2..1bc80dc 100644
--- a/tests/tests/widget/src/android/widget/cts/MockTextView.java
+++ b/tests/tests/widget/src/android/widget/cts/MockTextView.java
@@ -36,6 +36,11 @@
     private boolean mHasCalledOnWindowFocusChanged;
     private boolean mHasCalledOnPrivateIMECommand;
     private boolean mHasCalledOnKeyMultiple;
+    private boolean mHasCalledOnSelectionChanged;
+    private int mSelectionChangedStart;
+    private int mSelectionChangedEnd;
+    private boolean mHasCalledOnBeginBatchEdit;
+    private boolean mHasCalledOnEndBatchEdit;
 
     public MockTextView(Context context) {
         super(context);
@@ -81,6 +86,26 @@
         return mHasCalledOnKeyMultiple;
     }
 
+    public boolean hasCalledOnSelectionChanged() {
+        return mHasCalledOnSelectionChanged;
+    }
+
+    public boolean hasCalledOnBeginBatchEdit() {
+        return mHasCalledOnBeginBatchEdit;
+    }
+
+    public boolean hasCalledOnEndBatchEdit() {
+        return mHasCalledOnEndBatchEdit;
+    }
+
+    public int getSelectionChangedStart() {
+        return mSelectionChangedStart;
+    }
+
+    public int getSelectionChangedEnd() {
+        return mSelectionChangedEnd;
+    }
+
     public void reset() {
         mHasCalledOnWindowFocusChanged = false;
         mHasCalledDrawableStateChanged = false;
@@ -90,6 +115,11 @@
         mHasCalledOnTextChanged = false;
         mHasCalledOnPrivateIMECommand = false;
         mHasCalledOnKeyMultiple = false;
+        mHasCalledOnSelectionChanged = false;
+        mSelectionChangedStart = -1;
+        mSelectionChangedEnd = -1;
+        mHasCalledOnBeginBatchEdit = false;
+        mHasCalledOnEndBatchEdit = false;
     }
 
     public int computeHorizontalScrollRange() {
@@ -178,6 +208,14 @@
         return super.onPrivateIMECommand(action, data);
     }
 
+    @Override
+    protected void onSelectionChanged(int selStart, int selEnd) {
+        super.onSelectionChanged(selStart, selEnd);
+        mHasCalledOnSelectionChanged = true;
+        mSelectionChangedStart = selStart;
+        mSelectionChangedEnd = selEnd;
+    }
+
     public int getFrameLeft() {
         return getLeft();
     }
@@ -221,4 +259,16 @@
     public int computeVerticalScrollExtent() {
         return super.computeVerticalScrollExtent();
     }
+
+    @Override
+    public void onBeginBatchEdit() {
+        super.onBeginBatchEdit();
+        mHasCalledOnBeginBatchEdit = true;
+    }
+
+    @Override
+    public void onEndBatchEdit() {
+        super.onEndBatchEdit();
+        mHasCalledOnEndBatchEdit = true;
+    }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextViewTest.java b/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextViewTest.java
index 5c18030..2792504 100644
--- a/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextViewTest.java
@@ -16,32 +16,35 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-
 import android.app.Activity;
+import android.app.Instrumentation;
 import android.content.Context;
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.text.SpannableString;
 import android.text.Spanned;
 import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.util.Xml;
 import android.view.KeyEvent;
 import android.widget.ArrayAdapter;
+import android.widget.AutoCompleteTextView;
 import android.widget.Filter;
 import android.widget.MultiAutoCompleteTextView;
 import android.widget.MultiAutoCompleteTextView.CommaTokenizer;
 import android.widget.MultiAutoCompleteTextView.Tokenizer;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
 
-public class MultiAutoCompleteTextViewTest extends ActivityInstrumentationTestCase2
-        <MultiAutoCompleteTextViewCtsActivity> {
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@MediumTest
+public class MultiAutoCompleteTextViewTest
+        extends ActivityInstrumentationTestCase2<MultiAutoCompleteTextViewCtsActivity> {
+    private Instrumentation mInstrumentation;
+    private Activity mActivity;
     private MultiAutoCompleteTextView mMultiAutoCompleteTextView_country;
     private MultiAutoCompleteTextView mMultiAutoCompleteTextView_name;
-    private Activity mActivity;
 
     public MultiAutoCompleteTextViewTest() {
         super("android.widget.cts", MultiAutoCompleteTextViewCtsActivity.class);
@@ -51,23 +54,26 @@
     protected void setUp() throws Exception {
         super.setUp();
 
+        mInstrumentation = getInstrumentation();
         mActivity = getActivity();
-
         mMultiAutoCompleteTextView_country = (MultiAutoCompleteTextView)mActivity
                 .findViewById(R.id.country_edit);
         mMultiAutoCompleteTextView_name = (MultiAutoCompleteTextView)mActivity
                 .findViewById(R.id.name_edit);
     }
 
-    @UiThreadTest
     public void testConstructor() {
-        XmlPullParser parser = mActivity.getResources()
-                .getXml(R.layout.multi_auto_complete_text_view_layout);
-        AttributeSet attr = Xml.asAttributeSet(parser);
-
         new MultiAutoCompleteTextView(mActivity);
-        new MultiAutoCompleteTextView(mActivity, attr);
-        new MultiAutoCompleteTextView(mActivity, attr, 0);
+        new MultiAutoCompleteTextView(mActivity, null);
+        new MultiAutoCompleteTextView(mActivity, null, android.R.attr.autoCompleteTextViewStyle);
+        new MultiAutoCompleteTextView(mActivity, null, 0,
+                android.R.style.Widget_DeviceDefault_AutoCompleteTextView);
+        new MultiAutoCompleteTextView(mActivity, null, 0,
+                android.R.style.Widget_DeviceDefault_Light_AutoCompleteTextView);
+        new MultiAutoCompleteTextView(mActivity, null, 0,
+                android.R.style.Widget_Material_AutoCompleteTextView);
+        new MultiAutoCompleteTextView(mActivity, null, 0,
+                android.R.style.Widget_Material_Light_AutoCompleteTextView);
 
         try {
             new MultiAutoCompleteTextView(null);
@@ -91,19 +97,21 @@
         }
     }
 
-    @UiThreadTest
-    private void setText(MultiAutoCompleteTextView m, CharSequence c) {
-        m.setText(c);
-        m.setSelection(0, c.length());
+    private void setText(final MultiAutoCompleteTextView m, final CharSequence c) {
+        mInstrumentation.runOnMainSync(() -> {
+            m.setText(c);
+            m.setSelection(0, c.length());
+        });
     }
 
-    @UiThreadTest
     public void testMultiAutoCompleteTextView() {
-        mMultiAutoCompleteTextView_country.setTokenizer(new CommaTokenizer());
-        mMultiAutoCompleteTextView_name.setTokenizer(new CommaTokenizer());
+        mInstrumentation.runOnMainSync(() -> {
+            mMultiAutoCompleteTextView_country.setTokenizer(new CommaTokenizer());
+            mMultiAutoCompleteTextView_name.setTokenizer(new CommaTokenizer());
 
-        mMultiAutoCompleteTextView_country.setThreshold(3);
-        mMultiAutoCompleteTextView_name.setThreshold(2);
+            mMultiAutoCompleteTextView_country.setThreshold(3);
+            mMultiAutoCompleteTextView_name.setThreshold(2);
+        });
 
         assertFalse(mMultiAutoCompleteTextView_country.enoughToFilter());
         assertFalse(mMultiAutoCompleteTextView_name.enoughToFilter());
@@ -125,76 +133,84 @@
 
         setText(mMultiAutoCompleteTextView_name, "Jacky");
         assertTrue(mMultiAutoCompleteTextView_name.enoughToFilter());
-
-        MockValidator v = new MockValidator();
-        v.setValid(true);
-        mMultiAutoCompleteTextView_name.setValidator(v);
-
-        // There will be an endless loop when using CommaTokenizer as the Tokenizer
-        // mMultiAutoCompleteTextView_name.performValidation();
-        mMultiAutoCompleteTextView_name.setValidator(null);
     }
 
-    @UiThreadTest
     public void testPerformValidation() {
-        MockValidator v = new MockValidator();
-        v.setValid(true);
-        mMultiAutoCompleteTextView_country.setValidator(v);
+        final AutoCompleteTextView.Validator validator = mock(AutoCompleteTextView.Validator.class);
+        when(validator.isValid(any(CharSequence.class))).thenReturn(true);
+        when(validator.fixText(any(CharSequence.class))).thenAnswer(
+                new Answer<CharSequence>() {
+                    @Override
+                    public CharSequence answer(InvocationOnMock invocation) throws Throwable {
+                        // Return the originally passed parameter
+                        return (CharSequence) invocation.getArguments()[0];
+                    }
+                });
+
+        mInstrumentation.runOnMainSync(
+                () -> mMultiAutoCompleteTextView_country.setValidator(validator));
         MockTokenizer t = new MockTokenizer();
-        mMultiAutoCompleteTextView_country.setTokenizer(t);
+        mInstrumentation.runOnMainSync(() -> mMultiAutoCompleteTextView_country.setTokenizer(t));
         String str = new String("Foo, Android Test, OH");
-        mMultiAutoCompleteTextView_country.setText(str);
-        mMultiAutoCompleteTextView_country.performValidation();
+        mInstrumentation.runOnMainSync(() -> {
+            mMultiAutoCompleteTextView_country.setText(str);
+            mMultiAutoCompleteTextView_country.performValidation();
+        });
         assertEquals(str, mMultiAutoCompleteTextView_country.getText().toString());
 
-        v.setValid(false);
-        mMultiAutoCompleteTextView_country.performValidation();
+        when(validator.isValid(any(CharSequence.class))).thenReturn(false);
+        mInstrumentation.runOnMainSync(
+                () -> mMultiAutoCompleteTextView_country.performValidation());
         assertEquals(str + ", ", mMultiAutoCompleteTextView_country.getText().toString());
     }
 
-    @UiThreadTest
     public void testPerformFiltering() {
         MyMultiAutoCompleteTextView multiAutoCompleteTextView =
             new MyMultiAutoCompleteTextView(mActivity);
         CommaTokenizer t = new CommaTokenizer();
-        multiAutoCompleteTextView.setTokenizer(t);
+        mInstrumentation.runOnMainSync(() -> multiAutoCompleteTextView.setTokenizer(t));
 
         ArrayAdapter<String> adapter = new ArrayAdapter<String>(mActivity,
                 R.layout.simple_dropdown_item_1line);
         assertNotNull(adapter);
 
-        multiAutoCompleteTextView.setAdapter(adapter);
+        mInstrumentation.runOnMainSync(() -> multiAutoCompleteTextView.setAdapter(adapter));
         assertNotNull(multiAutoCompleteTextView.getFilter());
 
         String text = "Android test.";
-        multiAutoCompleteTextView.setText(text);
-        multiAutoCompleteTextView.setSelection(0, 12);
+        mInstrumentation.runOnMainSync(() -> {
+            multiAutoCompleteTextView.setText(text);
+            multiAutoCompleteTextView.setSelection(0, 12);
+            multiAutoCompleteTextView.performFiltering(text, KeyEvent.KEYCODE_0);
+        });
 
-        multiAutoCompleteTextView.performFiltering(text, KeyEvent.KEYCODE_0);
         assertNotNull(multiAutoCompleteTextView.getFilter());
 
-        multiAutoCompleteTextView.performFiltering(text, 0, text.length(), KeyEvent.KEYCODE_E);
+        mInstrumentation.runOnMainSync(
+                () -> multiAutoCompleteTextView.performFiltering(text, 0, text.length(),
+                        KeyEvent.KEYCODE_E));
         assertNotNull(multiAutoCompleteTextView.getFilter());
     }
 
-    @UiThreadTest
     public void testReplaceText() {
         MyMultiAutoCompleteTextView multiAutoCompleteTextView =
             new MyMultiAutoCompleteTextView(mActivity);
         CommaTokenizer t = new CommaTokenizer();
-        multiAutoCompleteTextView.setTokenizer(t);
+        mInstrumentation.runOnMainSync(() -> multiAutoCompleteTextView.setTokenizer(t));
 
         String text = "CTS.";
-        multiAutoCompleteTextView.setText(text);
+        mInstrumentation.runOnMainSync(() -> multiAutoCompleteTextView.setText(text));
         assertEquals(text, multiAutoCompleteTextView.getText().toString());
-        multiAutoCompleteTextView.setSelection(0, text.length());
+        mInstrumentation.runOnMainSync(
+                () -> multiAutoCompleteTextView.setSelection(0, text.length()));
 
         // set the selection range.
-        multiAutoCompleteTextView.replaceText("Android Test.");
+        mInstrumentation.runOnMainSync(
+                () -> multiAutoCompleteTextView.replaceText("Android Test."));
         assertEquals("Android Test., ", multiAutoCompleteTextView.getText().toString());
 
         // do not set the selection range.
-        multiAutoCompleteTextView.replaceText("replace test");
+        mInstrumentation.runOnMainSync(() -> multiAutoCompleteTextView.replaceText("replace test"));
         assertEquals("Android Test., replace test, ",
                 multiAutoCompleteTextView.getText().toString());
     }
@@ -253,22 +269,6 @@
         }
     }
 
-    private class MockValidator implements MultiAutoCompleteTextView.Validator {
-        private boolean mIsValid;
-
-        public void setValid(boolean b) {
-            mIsValid = b;
-        }
-
-        public boolean isValid(CharSequence text) {
-            return mIsValid;
-        }
-
-        public CharSequence fixText(CharSequence invalidText) {
-            return invalidText;
-        }
-    }
-
     /**
      * MyMultiAutoCompleteTextView
      */
diff --git a/tests/tests/widget/src/android/widget/cts/MyRemotableView.java b/tests/tests/widget/src/android/widget/cts/MyRemotableView.java
new file mode 100644
index 0000000..5452125
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/MyRemotableView.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.cts;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.RemoteViews;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+@RemoteViews.RemoteView
+public class MyRemotableView extends TextView {
+    private byte mByteField;
+    private char mCharField;
+    private double mDoubleField;
+    private short mShortField;
+    private Bundle mBundleField;
+
+    public MyRemotableView(Context context) {
+        super(context);
+    }
+
+    public MyRemotableView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public MyRemotableView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    @android.view.RemotableViewMethod
+    public void setByteField(byte value) {
+        mByteField = value;
+    }
+
+    public byte getByteField() {
+        return mByteField;
+    }
+
+    @android.view.RemotableViewMethod
+    public void setCharField(char value) {
+        mCharField = value;
+    }
+
+    public char getCharField() {
+        return mCharField;
+    }
+
+    @android.view.RemotableViewMethod
+    public void setDoubleField(double value) {
+        mDoubleField = value;
+    }
+
+    public double getDoubleField() {
+        return mDoubleField;
+    }
+
+    @android.view.RemotableViewMethod
+    public void setShortField(short value) {
+        mShortField = value;
+    }
+
+    public short getShortField() {
+        return mShortField;
+    }
+
+    @android.view.RemotableViewMethod
+    public void setBundleField(Bundle value) {
+        mBundleField = value;
+    }
+
+    public Bundle getBundleField() {
+        return mBundleField;
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/NumberPickerCtsActivity.java b/tests/tests/widget/src/android/widget/cts/NumberPickerCtsActivity.java
new file mode 100644
index 0000000..f93a1da
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/NumberPickerCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.NumberPicker;
+
+/**
+ * A minimal application for {@link NumberPicker} test.
+ */
+public class NumberPickerCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.numberpicker_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/NumberPickerTest.java b/tests/tests/widget/src/android/widget/cts/NumberPickerTest.java
new file mode 100644
index 0000000..cf69073
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/NumberPickerTest.java
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+package android.widget.cts;
+
+import android.app.Instrumentation;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.TextUtils;
+import android.widget.NumberPicker;
+import android.widget.cts.util.ViewTestUtils;
+import org.mockito.InOrder;
+
+import static org.mockito.Mockito.*;
+
+@SmallTest
+public class NumberPickerTest extends ActivityInstrumentationTestCase2<NumberPickerCtsActivity> {
+    private static final String[] NUMBER_NAMES3 = {"One", "Two", "Three"};
+    private static final String[] NUMBER_NAMES_ALT3 = {"Three", "Four", "Five"};
+    private static final String[] NUMBER_NAMES5 = {"One", "Two", "Three", "Four", "Five"};
+
+    private Instrumentation mInstrumentation;
+    private NumberPickerCtsActivity mActivity;
+    private NumberPicker mNumberPicker;
+
+    public NumberPickerTest() {
+        super("android.widget.cts", NumberPickerCtsActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mInstrumentation = getInstrumentation();
+        mActivity = getActivity();
+        mNumberPicker = (NumberPicker) mActivity.findViewById(R.id.number_picker);
+    }
+
+    @UiThreadTest
+    public void testConstructor() {
+        new NumberPicker(mActivity);
+
+        new NumberPicker(mActivity, null);
+
+        new NumberPicker(mActivity, null, android.R.attr.numberPickerStyle);
+
+        new NumberPicker(mActivity, null, 0, android.R.style.Widget_Material_NumberPicker);
+
+        new NumberPicker(mActivity, null, 0, android.R.style.Widget_Material_Light_NumberPicker);
+    }
+
+    private void verifyDisplayedValues(String[] expected) {
+        final String[] displayedValues = mNumberPicker.getDisplayedValues();
+        assertEquals(expected.length, displayedValues.length);
+        for (int i = 0; i < expected.length; i++) {
+            assertEquals(expected[i], displayedValues[i]);
+        }
+    }
+
+    public void testSetDisplayedValuesRangeMatch() {
+        mInstrumentation.runOnMainSync(() -> {
+            mNumberPicker.setMinValue(10);
+            mNumberPicker.setMaxValue(12);
+            mNumberPicker.setDisplayedValues(NUMBER_NAMES3);
+        });
+
+        assertEquals(10, mNumberPicker.getMinValue());
+        assertEquals(12, mNumberPicker.getMaxValue());
+        verifyDisplayedValues(NUMBER_NAMES3);
+
+        // Set a different displayed values array, but still matching the min/max range
+        mInstrumentation.runOnMainSync(() -> {
+            mNumberPicker.setDisplayedValues(NUMBER_NAMES_ALT3);
+        });
+
+        assertEquals(10, mNumberPicker.getMinValue());
+        assertEquals(12, mNumberPicker.getMaxValue());
+        verifyDisplayedValues(NUMBER_NAMES_ALT3);
+
+        mInstrumentation.runOnMainSync(() -> {
+            mNumberPicker.setMinValue(24);
+            mNumberPicker.setMaxValue(26);
+        });
+
+        assertEquals(24, mNumberPicker.getMinValue());
+        assertEquals(26, mNumberPicker.getMaxValue());
+        verifyDisplayedValues(NUMBER_NAMES_ALT3);
+    }
+
+    public void testSetDisplayedValuesRangeMismatch() {
+        mInstrumentation.runOnMainSync(() -> {
+            mNumberPicker.setMinValue(10);
+            mNumberPicker.setMaxValue(14);
+        });
+        assertEquals(10, mNumberPicker.getMinValue());
+        assertEquals(14, mNumberPicker.getMaxValue());
+
+        // Try setting too few displayed entries
+        mInstrumentation.runOnMainSync(() -> {
+            try {
+                // This is expected to fail since the displayed values only has three entries,
+                // while the min/max range has five.
+                mNumberPicker.setDisplayedValues(NUMBER_NAMES3);
+                fail("The size of the displayed values array must be equal to min/max range!");
+            } catch (Exception e) {
+                // We are expecting to catch an exception. Set displayed values to an array that
+                // matches the min/max range.
+                mNumberPicker.setDisplayedValues(NUMBER_NAMES5);
+            }
+        });
+    }
+
+    public void testSelectionDisplayedValueFromDisplayedValues() {
+        mInstrumentation.runOnMainSync(() -> {
+            mNumberPicker.setMinValue(1);
+            mNumberPicker.setMaxValue(3);
+            mNumberPicker.setDisplayedValues(NUMBER_NAMES3);
+        });
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(1));
+        assertTrue(TextUtils.equals(NUMBER_NAMES3[0],
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(2));
+        assertTrue(TextUtils.equals(NUMBER_NAMES3[1],
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(3));
+        assertTrue(TextUtils.equals(NUMBER_NAMES3[2],
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        // Switch to a different displayed values array
+        mInstrumentation.runOnMainSync(() -> {
+            mNumberPicker.setDisplayedValues(NUMBER_NAMES_ALT3);
+        });
+        assertTrue(TextUtils.equals(NUMBER_NAMES_ALT3[2],
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(1));
+        assertTrue(TextUtils.equals(NUMBER_NAMES_ALT3[0],
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(2));
+        assertTrue(TextUtils.equals(NUMBER_NAMES_ALT3[1],
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+    }
+
+    public void testSelectionDisplayedValueFromFormatter() {
+        mInstrumentation.runOnMainSync(() -> {
+            mNumberPicker.setMinValue(0);
+            mNumberPicker.setMaxValue(4);
+            mNumberPicker.setFormatter((int value) -> "entry " + value);
+        });
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(0));
+        assertTrue(TextUtils.equals("entry 0",
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(1));
+        assertTrue(TextUtils.equals("entry 1",
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(2));
+        assertTrue(TextUtils.equals("entry 2",
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(3));
+        assertTrue(TextUtils.equals("entry 3",
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(4));
+        assertTrue(TextUtils.equals("entry 4",
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        // Switch to a different formatter
+        mInstrumentation.runOnMainSync(
+                () -> mNumberPicker.setFormatter((int value) -> "row " + value));
+        // Check that the currently selected value has new displayed value
+        assertTrue(TextUtils.equals("row 4",
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        // and check a couple more values for the new formatting
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(0));
+        assertTrue(TextUtils.equals("row 0",
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(1));
+        assertTrue(TextUtils.equals("row 1",
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+    }
+
+
+    public void testSelectionDisplayedValuePrecedence() {
+        mInstrumentation.runOnMainSync(() -> {
+            mNumberPicker.setMinValue(1);
+            mNumberPicker.setMaxValue(3);
+            mNumberPicker.setDisplayedValues(NUMBER_NAMES3);
+            mNumberPicker.setFormatter((int value) -> "entry " + value);
+        });
+
+        // According to the widget documentation, displayed values take precedence over formatter
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(1));
+        assertTrue(TextUtils.equals(NUMBER_NAMES3[0],
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(2));
+        assertTrue(TextUtils.equals(NUMBER_NAMES3[1],
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(3));
+        assertTrue(TextUtils.equals(NUMBER_NAMES3[2],
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        // Set displayed values to null and test that the widget is using the formatter
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setDisplayedValues(null));
+        assertTrue(TextUtils.equals("entry 3",
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(1));
+        assertTrue(TextUtils.equals("entry 1",
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(2));
+        assertTrue(TextUtils.equals("entry 2",
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        // Set a different displayed values array and test that it's taking precedence
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setDisplayedValues(NUMBER_NAMES_ALT3));
+        assertTrue(TextUtils.equals(NUMBER_NAMES_ALT3[1],
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(1));
+        assertTrue(TextUtils.equals(NUMBER_NAMES_ALT3[0],
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(3));
+        assertTrue(TextUtils.equals(NUMBER_NAMES_ALT3[2],
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+    }
+
+    public void testAccessValue() {
+        mInstrumentation.runOnMainSync(() -> {
+            mNumberPicker.setMinValue(20);
+            mNumberPicker.setMaxValue(22);
+            mNumberPicker.setDisplayedValues(NUMBER_NAMES3);
+        });
+
+        final NumberPicker.OnValueChangeListener mockValueChangeListener =
+                mock(NumberPicker.OnValueChangeListener.class);
+        mNumberPicker.setOnValueChangedListener(mockValueChangeListener);
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(21));
+        assertEquals(21, mNumberPicker.getValue());
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(20));
+        assertEquals(20, mNumberPicker.getValue());
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(22));
+        assertEquals(22, mNumberPicker.getValue());
+
+        // Check trying to set value out of min/max range
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(10));
+        assertEquals(20, mNumberPicker.getValue());
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(100));
+        assertEquals(22, mNumberPicker.getValue());
+
+        // Since all changes to value are via API calls, we should have no interactions /
+        // callbacks on our listener.
+        verifyZeroInteractions(mockValueChangeListener);
+    }
+
+    public void testInteractionWithSwipeDown() {
+        mInstrumentation.runOnMainSync(() -> {
+            mNumberPicker.setMinValue(6);
+            mNumberPicker.setMaxValue(8);
+            mNumberPicker.setDisplayedValues(NUMBER_NAMES_ALT3);
+        });
+
+        final NumberPicker.OnValueChangeListener mockValueChangeListener =
+                mock(NumberPicker.OnValueChangeListener.class);
+        mNumberPicker.setOnValueChangedListener(mockValueChangeListener);
+
+        final NumberPicker.OnScrollListener mockScrollListener =
+                mock(NumberPicker.OnScrollListener.class);
+        mNumberPicker.setOnScrollListener(mockScrollListener);
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(7));
+        assertEquals(7, mNumberPicker.getValue());
+
+        // Swipe down across our number picker
+        final int[] numberPickerLocationOnScreen = new int[2];
+        mNumberPicker.getLocationOnScreen(numberPickerLocationOnScreen);
+
+        ViewTestUtils.emulateDragGesture(mInstrumentation,
+                numberPickerLocationOnScreen[0] + mNumberPicker.getWidth() / 2,
+                numberPickerLocationOnScreen[1] + 1,
+                0,
+                mNumberPicker.getHeight() - 2);
+
+        // At this point we expect that the drag-down gesture has selected the value
+        // that was "above" the previously selected one, and that our value change listener
+        // has been notified of that change exactly once.
+        assertEquals(6, mNumberPicker.getValue());
+        verify(mockValueChangeListener, times(1)).onValueChange(mNumberPicker, 7, 6);
+        verifyNoMoreInteractions(mockValueChangeListener);
+
+        // We expect that our scroll listener will be called with specific state changes.
+        InOrder inOrder = inOrder(mockScrollListener);
+        inOrder.verify(mockScrollListener).onScrollStateChange(mNumberPicker,
+                NumberPicker.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
+        inOrder.verify(mockScrollListener).onScrollStateChange(mNumberPicker,
+                NumberPicker.OnScrollListener.SCROLL_STATE_IDLE);
+        verifyNoMoreInteractions(mockScrollListener);
+    }
+
+    public void testInteractionWithSwipeUp() {
+        mInstrumentation.runOnMainSync(() -> {
+            mNumberPicker.setMinValue(10);
+            mNumberPicker.setMaxValue(12);
+            mNumberPicker.setDisplayedValues(NUMBER_NAMES_ALT3);
+        });
+
+        final NumberPicker.OnValueChangeListener mockValueChangeListener =
+                mock(NumberPicker.OnValueChangeListener.class);
+        mNumberPicker.setOnValueChangedListener(mockValueChangeListener);
+
+        final NumberPicker.OnScrollListener mockScrollListener =
+                mock(NumberPicker.OnScrollListener.class);
+        mNumberPicker.setOnScrollListener(mockScrollListener);
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(11));
+        assertEquals(11, mNumberPicker.getValue());
+
+        // Swipe up across our number picker
+        final int[] numberPickerLocationOnScreen = new int[2];
+        mNumberPicker.getLocationOnScreen(numberPickerLocationOnScreen);
+
+        ViewTestUtils.emulateDragGesture(mInstrumentation,
+                numberPickerLocationOnScreen[0] + mNumberPicker.getWidth() / 2,
+                numberPickerLocationOnScreen[1] + mNumberPicker.getHeight() - 1,
+                0,
+                - (mNumberPicker.getHeight() - 2));
+
+        // At this point we expect that the drag-up gesture has selected the value
+        // that was "below" the previously selected one, and that our value change listener
+        // has been notified of that change exactly once.
+        assertEquals(12, mNumberPicker.getValue());
+        verify(mockValueChangeListener, times(1)).onValueChange(mNumberPicker, 11, 12);
+        verifyNoMoreInteractions(mockValueChangeListener);
+
+        // We expect that our scroll listener will be called with specific state changes.
+        InOrder inOrder = inOrder(mockScrollListener);
+        inOrder.verify(mockScrollListener).onScrollStateChange(mNumberPicker,
+                NumberPicker.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
+        inOrder.verify(mockScrollListener).onScrollStateChange(mNumberPicker,
+                NumberPicker.OnScrollListener.SCROLL_STATE_IDLE);
+        verifyNoMoreInteractions(mockScrollListener);
+    }
+
+    public void testAccessWrapSelectorValue() {
+        mInstrumentation.runOnMainSync(() -> {
+            mNumberPicker.setMinValue(100);
+            mNumberPicker.setMaxValue(200);
+        });
+        // As specified in the Javadocs of NumberPicker.setWrapSelectorWheel, when min/max
+        // range is larger than what the widget is showing, the selector wheel is enabled.
+        assertTrue(mNumberPicker.getWrapSelectorWheel());
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setWrapSelectorWheel(false));
+        assertFalse(mNumberPicker.getWrapSelectorWheel());
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setWrapSelectorWheel(true));
+        assertTrue(mNumberPicker.getWrapSelectorWheel());
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java b/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java
index ee38448..aa37127 100644
--- a/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java
+++ b/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java
@@ -30,6 +30,7 @@
 import android.view.View;
 import android.widget.EditText;
 import android.widget.PopupMenu;
+import android.widget.cts.util.ViewTestUtils;
 
 import static org.mockito.Mockito.*;
 
@@ -183,15 +184,7 @@
         runTestOnUiThread(() -> mBuilder.show());
         mInstrumentation.waitForIdleSync();
 
-        // Determine the location of the anchor on the screen so that we can emulate
-        // a tap outside of the popup bounds to dismiss the popup
-        final int[] anchorOnScreenXY = new int[2];
-        mBuilder.mAnchor.getLocationOnScreen(anchorOnScreenXY);
-
-        int emulatedTapX = anchorOnScreenXY[0] + 10;
-        int emulatedTapY = anchorOnScreenXY[1] - 20;
-
-        // The logic below uses Instrumentation to emulate a tap outside the bounds of the
+        // The call below uses Instrumentation to emulate a tap outside the bounds of the
         // displayed popup menu. This tap is then treated by the framework to be "split" as
         // the ACTION_OUTSIDE for the popup itself, as well as DOWN / MOVE / UP for the underlying
         // view root if the popup is not modal.
@@ -200,27 +193,7 @@
         // of Instrumentation is necessary here since Espresso's actions operate at the level
         // of view or data. Also, we don't want to use View.dispatchTouchEvent directly as
         // that would require emulation of two separate sequences as well.
-
-        // Inject DOWN event
-        long downTime = SystemClock.uptimeMillis();
-        MotionEvent eventDown = MotionEvent.obtain(
-                downTime, downTime, MotionEvent.ACTION_DOWN, emulatedTapX, emulatedTapY, 1);
-        mInstrumentation.sendPointerSync(eventDown);
-
-        // Inject MOVE event
-        long moveTime = SystemClock.uptimeMillis();
-        MotionEvent eventMove = MotionEvent.obtain(
-                moveTime, moveTime, MotionEvent.ACTION_MOVE, emulatedTapX, emulatedTapY, 1);
-        mInstrumentation.sendPointerSync(eventMove);
-
-        // Inject UP event
-        long upTime = SystemClock.uptimeMillis();
-        MotionEvent eventUp = MotionEvent.obtain(
-                upTime, upTime, MotionEvent.ACTION_UP, emulatedTapX, emulatedTapY, 1);
-        mInstrumentation.sendPointerSync(eventUp);
-
-        // Wait for the system to process all events in the queue
-        mInstrumentation.waitForIdleSync();
+        ViewTestUtils.emulateTapOnScreen(mInstrumentation, mBuilder.mAnchor, 10, -20);
 
         // At this point our popup should have notified its dismiss listener
         verify(mBuilder.mOnDismissListener, times(1)).onDismiss(mPopupMenu);
diff --git a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
index 96b37d3..9da8c5d 100644
--- a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
@@ -20,12 +20,14 @@
 import android.app.Instrumentation;
 import android.content.Context;
 import android.graphics.Color;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.transition.Transition;
 import android.transition.Transition.TransitionListener;
 import android.transition.TransitionValues;
@@ -51,6 +53,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+@SmallTest
 public class PopupWindowTest extends
         ActivityInstrumentationTestCase2<PopupWindowCtsActivity> {
     private Instrumentation mInstrumentation;
@@ -84,6 +87,14 @@
 
         new PopupWindow(mActivity, null, android.R.attr.popupWindowStyle);
 
+        new PopupWindow(mActivity, null, 0, android.R.style.Widget_DeviceDefault_PopupWindow);
+
+        new PopupWindow(mActivity, null, 0, android.R.style.Widget_DeviceDefault_Light_PopupWindow);
+
+        new PopupWindow(mActivity, null, 0, android.R.style.Widget_Material_PopupWindow);
+
+        new PopupWindow(mActivity, null, 0, android.R.style.Widget_Material_Light_PopupWindow);
+
         mPopupWindow = new PopupWindow();
         assertEquals(0, mPopupWindow.getWidth());
         assertEquals(0, mPopupWindow.getHeight());
@@ -575,6 +586,8 @@
         // Do not attach within the decor; we will be measuring location
         // with regard to screen coordinates.
         mPopupWindow.setAttachedInDecor(false);
+        assertFalse(mPopupWindow.isAttachedInDecor());
+
         final View upperAnchor = mActivity.findViewById(R.id.anchor_upper);
 
         final int xOff = 10;
@@ -656,42 +669,73 @@
 
     public void testGetMaxAvailableHeight() {
         mPopupWindow = createPopupWindow(createPopupContent(50, 50));
+        final Point point = new Point();
+        getDisplay().getSize(point);
+        final int displayHeight = point.y;
 
         View anchorView = mActivity.findViewById(R.id.anchor_upper);
-        int avaliable = getDisplay().getHeight() - anchorView.getHeight();
+        int available = displayHeight - anchorView.getHeight();
         int maxAvailableHeight = mPopupWindow.getMaxAvailableHeight(anchorView);
+        int maxAvailableHeightIgnoringBottomDecoration =
+                mPopupWindow.getMaxAvailableHeight(anchorView, 0, true);
         assertTrue(maxAvailableHeight > 0);
-        assertTrue(maxAvailableHeight <= avaliable);
+        assertTrue(maxAvailableHeight <= available);
+        assertTrue(maxAvailableHeightIgnoringBottomDecoration >= maxAvailableHeight);
+        assertTrue(maxAvailableHeightIgnoringBottomDecoration <= available);
+
         int maxAvailableHeightWithOffset = mPopupWindow.getMaxAvailableHeight(anchorView, 2);
         assertEquals(maxAvailableHeight - 2, maxAvailableHeightWithOffset);
+
         maxAvailableHeightWithOffset =
                 mPopupWindow.getMaxAvailableHeight(anchorView, maxAvailableHeight);
         assertTrue(maxAvailableHeightWithOffset > 0);
-        assertTrue(maxAvailableHeightWithOffset <= avaliable);
+        assertTrue(maxAvailableHeightWithOffset <= available);
+
         maxAvailableHeightWithOffset =
                 mPopupWindow.getMaxAvailableHeight(anchorView, maxAvailableHeight / 2 - 1);
         assertTrue(maxAvailableHeightWithOffset > 0);
-        assertTrue(maxAvailableHeightWithOffset <= avaliable);
+        assertTrue(maxAvailableHeightWithOffset <= available);
+
         maxAvailableHeightWithOffset = mPopupWindow.getMaxAvailableHeight(anchorView, -1);
         assertTrue(maxAvailableHeightWithOffset > 0);
-        assertTrue(maxAvailableHeightWithOffset <= avaliable);
+        assertTrue(maxAvailableHeightWithOffset <= available);
+
+        int maxAvailableHeightWithOffsetIgnoringBottomDecoration =
+                mPopupWindow.getMaxAvailableHeight(anchorView, 2, true);
+        assertEquals(maxAvailableHeightIgnoringBottomDecoration - 2,
+                maxAvailableHeightWithOffsetIgnoringBottomDecoration);
+
+        maxAvailableHeightWithOffsetIgnoringBottomDecoration =
+                mPopupWindow.getMaxAvailableHeight(anchorView, maxAvailableHeight, true);
+        assertTrue(maxAvailableHeightWithOffsetIgnoringBottomDecoration > 0);
+        assertTrue(maxAvailableHeightWithOffsetIgnoringBottomDecoration <= available);
+
+        maxAvailableHeightWithOffsetIgnoringBottomDecoration =
+                mPopupWindow.getMaxAvailableHeight(anchorView, maxAvailableHeight / 2 - 1, true);
+        assertTrue(maxAvailableHeightWithOffsetIgnoringBottomDecoration > 0);
+        assertTrue(maxAvailableHeightWithOffsetIgnoringBottomDecoration <= available);
+
+        maxAvailableHeightWithOffsetIgnoringBottomDecoration =
+                mPopupWindow.getMaxAvailableHeight(anchorView, -1, true);
+        assertTrue(maxAvailableHeightWithOffsetIgnoringBottomDecoration > 0);
+        assertTrue(maxAvailableHeightWithOffsetIgnoringBottomDecoration <= available);
 
         anchorView = mActivity.findViewById(R.id.anchor_lower);
         // On some devices the view might actually have larger size than the physical display
         // due to chin and content will be laid out as if outside of the display. We need to use
         // larger from the display height and the main view height.
-        avaliable = Math.max(getDisplay().getHeight(),
+        available = Math.max(displayHeight,
                 mActivity.findViewById(android.R.id.content).getHeight()) - anchorView.getHeight();
         maxAvailableHeight = mPopupWindow.getMaxAvailableHeight(anchorView);
         assertTrue(maxAvailableHeight > 0);
-        assertTrue(maxAvailableHeight <= avaliable);
+        assertTrue(maxAvailableHeight <= available);
 
         anchorView = mActivity.findViewById(R.id.anchor_middle_left);
-        avaliable = getDisplay().getHeight() - anchorView.getHeight()
+        available = displayHeight - anchorView.getHeight()
                 - mActivity.findViewById(R.id.anchor_upper).getHeight();
         maxAvailableHeight = mPopupWindow.getMaxAvailableHeight(anchorView);
         assertTrue(maxAvailableHeight > 0);
-        assertTrue(maxAvailableHeight <= avaliable);
+        assertTrue(maxAvailableHeight <= available);
     }
 
     @UiThreadTest
@@ -815,6 +859,7 @@
         mInstrumentation.waitForIdleSync();
         // Do not update if it is not shown
         assertFalse(mPopupWindow.isShowing());
+        assertFalse(mPopupWindow.isAttachedInDecor());
         assertEquals(100, mPopupWindow.getWidth());
         assertEquals(100, mPopupWindow.getHeight());
 
@@ -822,6 +867,14 @@
         mPopupWindow.getContentView().getLocationInWindow(viewInWindowXY);
 
         // update if it is not shown
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.update(80, 80));
+
+        mInstrumentation.waitForIdleSync();
+        assertTrue(mPopupWindow.isShowing());
+        assertEquals(80, mPopupWindow.getWidth());
+        assertEquals(80, mPopupWindow.getHeight());
+
+        // update if it is not shown
         mInstrumentation.runOnMainSync(() -> mPopupWindow.update(20, 50, 50, 50));
 
         mInstrumentation.waitForIdleSync();
@@ -1061,6 +1114,61 @@
         assertEquals(LayoutParams.MATCH_PARENT, p.height);
     }
 
+    public void testAccessElevation() {
+        mPopupWindow = createPopupWindow(createPopupContent(50, 50));
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.setElevation(2.0f));
+
+        showPopup();
+        assertEquals(2.0f, mPopupWindow.getElevation());
+
+        dismissPopup();
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.setElevation(4.0f));
+        showPopup();
+        assertEquals(4.0f, mPopupWindow.getElevation());
+
+        dismissPopup();
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.setElevation(10.0f));
+        showPopup();
+        assertEquals(10.0f, mPopupWindow.getElevation());
+    }
+
+    public void testAccessSoftInputMode() {
+        mPopupWindow = createPopupWindow(createPopupContent(50, 50));
+        mInstrumentation.runOnMainSync(
+                () -> mPopupWindow.setSoftInputMode(
+                        WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE));
+
+        showPopup();
+        assertEquals(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE,
+                mPopupWindow.getSoftInputMode());
+
+        dismissPopup();
+        mInstrumentation.runOnMainSync(
+                () -> mPopupWindow.setSoftInputMode(
+                        WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN));
+        showPopup();
+        assertEquals(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN,
+                mPopupWindow.getSoftInputMode());
+    }
+
+    public void testAccessSplitTouchEnabled() {
+        mPopupWindow = createPopupWindow(createPopupContent(50, 50));
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.setSplitTouchEnabled(true));
+
+        showPopup();
+        assertTrue(mPopupWindow.isSplitTouchEnabled());
+
+        dismissPopup();
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.setSplitTouchEnabled(false));
+        showPopup();
+        assertFalse(mPopupWindow.isSplitTouchEnabled());
+
+        dismissPopup();
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.setSplitTouchEnabled(true));
+        showPopup();
+        assertTrue(mPopupWindow.isSplitTouchEnabled());
+    }
+
     private static class BaseTransition extends Transition {
         @Override
         public void captureStartValues(TransitionValues transitionValues) {}
diff --git a/tests/tests/widget/src/android/widget/cts/ProgressBarCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ProgressBarCtsActivity.java
index 8298d5f..2b3a45d 100644
--- a/tests/tests/widget/src/android/widget/cts/ProgressBarCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/ProgressBarCtsActivity.java
@@ -18,17 +18,18 @@
 
 import android.app.Activity;
 import android.os.Bundle;
+import android.widget.ProgressBar;
 
 /**
- * An application for ProgressBar test
- *
+ * A minimal application for {@link ProgressBar} test.
  */
 public class ProgressBarCtsActivity extends Activity {
     /**
-     * Called with the activity is first created.
+     * Called when the activity is first created.
      */
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        setContentView(R.layout.progressbar_layout);
     }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/ProgressBarTest.java b/tests/tests/widget/src/android/widget/cts/ProgressBarTest.java
index 1cf7334..040b26d 100644
--- a/tests/tests/widget/src/android/widget/cts/ProgressBarTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ProgressBarTest.java
@@ -16,412 +16,449 @@
 
 package android.widget.cts;
 
+import android.content.Context;
 import android.content.res.ColorStateList;
+import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.PorterDuff;
-import android.view.LayoutInflater;
-
-import android.widget.cts.R;
-
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
+import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Parcelable;
-import android.test.InstrumentationTestCase;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.view.View;
 import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.AccelerateInterpolator;
 import android.view.animation.Interpolator;
 import android.view.animation.LinearInterpolator;
 import android.widget.ProgressBar;
+import android.widget.cts.util.TestUtils;
 
-public class ProgressBarTest extends InstrumentationTestCase {
-    // The target context.
-    private Context mContext;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.*;
+
+@SmallTest
+public class ProgressBarTest extends ActivityInstrumentationTestCase2<ProgressBarCtsActivity> {
+    private ProgressBarCtsActivity mActivity;
+    private ProgressBar mProgressBar;
+    private ProgressBar mProgressBarHorizontal;
+
+    public ProgressBarTest() {
+        super("android.widget.cts", ProgressBarCtsActivity.class);
+    }
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mContext = getInstrumentation().getTargetContext();
+
+        mActivity = getActivity();
+        mProgressBar = (ProgressBar) mActivity.findViewById(R.id.progress);
+        mProgressBarHorizontal = (ProgressBar) mActivity.findViewById(R.id.progress_horizontal);
     }
 
     public void testConstructor() {
-        new ProgressBar(mContext);
+        new ProgressBar(mActivity);
 
-        new ProgressBar(mContext, null);
+        new ProgressBar(mActivity, null);
 
-        new ProgressBar(mContext, null, android.R.attr.progressBarStyle);
+        new ProgressBar(mActivity, null, android.R.attr.progressBarStyle);
+
+        new ProgressBar(mActivity, null, android.R.attr.progressBarStyleHorizontal);
+
+        new ProgressBar(mActivity, null, android.R.attr.progressBarStyleInverse);
+
+        new ProgressBar(mActivity, null, android.R.attr.progressBarStyleLarge);
+
+        new ProgressBar(mActivity, null, android.R.attr.progressBarStyleLargeInverse);
+
+        new ProgressBar(mActivity, null, android.R.attr.progressBarStyleSmall);
+
+        new ProgressBar(mActivity, null, android.R.attr.progressBarStyleSmallInverse);
+
+        new ProgressBar(mActivity, null, android.R.attr.progressBarStyleSmallTitle);
+
+        new ProgressBar(mActivity, null, 0, android.R.style.Widget_DeviceDefault_Light_ProgressBar);
+
+        new ProgressBar(mActivity, null, 0,
+                android.R.style.Widget_DeviceDefault_Light_ProgressBar_Horizontal);
+
+        new ProgressBar(mActivity, null, 0,
+                android.R.style.Widget_DeviceDefault_Light_ProgressBar_Inverse);
+
+        new ProgressBar(mActivity, null, 0,
+                android.R.style.Widget_DeviceDefault_Light_ProgressBar_Large);
+
+        new ProgressBar(mActivity, null, 0,
+                android.R.style.Widget_DeviceDefault_Light_ProgressBar_Large_Inverse);
+
+        new ProgressBar(mActivity, null, 0,
+                android.R.style.Widget_DeviceDefault_Light_ProgressBar_Small);
+
+        new ProgressBar(mActivity, null, 0,
+                android.R.style.Widget_DeviceDefault_Light_ProgressBar_Small_Inverse);
+
+        new ProgressBar(mActivity, null, 0,
+                android.R.style.Widget_DeviceDefault_Light_ProgressBar_Small_Title);
+
+        new ProgressBar(mActivity, null, 0, android.R.style.Widget_Material_Light_ProgressBar);
+
+        new ProgressBar(mActivity, null, 0,
+                android.R.style.Widget_Material_Light_ProgressBar_Horizontal);
+
+        new ProgressBar(mActivity, null, 0,
+                android.R.style.Widget_Material_Light_ProgressBar_Inverse);
+
+        new ProgressBar(mActivity, null, 0,
+                android.R.style.Widget_Material_Light_ProgressBar_Large);
+
+        new ProgressBar(mActivity, null, 0,
+                android.R.style.Widget_Material_Light_ProgressBar_Large_Inverse);
+
+        new ProgressBar(mActivity, null, 0,
+                android.R.style.Widget_Material_Light_ProgressBar_Small);
+
+        new ProgressBar(mActivity, null, 0,
+                android.R.style.Widget_Material_Light_ProgressBar_Small_Inverse);
+
+        new ProgressBar(mActivity, null, 0,
+                android.R.style.Widget_Material_Light_ProgressBar_Small_Title);
     }
 
+    @UiThreadTest
     public void testSetIndeterminate() {
-        ProgressBar progressBar = new ProgressBar(mContext);
-        assertTrue(progressBar.isIndeterminate());
+        assertTrue(mProgressBar.isIndeterminate());
 
-        progressBar.setIndeterminate(true);
-        assertTrue(progressBar.isIndeterminate());
+        mProgressBar.setIndeterminate(true);
+        assertTrue(mProgressBar.isIndeterminate());
 
-        progressBar.setIndeterminate(false);
+        mProgressBar.setIndeterminate(false);
         // because default is Indeterminate only progressBar, can't change the status
-        assertTrue(progressBar.isIndeterminate());
+        assertTrue(mProgressBar.isIndeterminate());
 
-        progressBar = new ProgressBar(mContext, null, android.R.attr.progressBarStyleHorizontal);
-        assertFalse(progressBar.isIndeterminate());
+        assertFalse(mProgressBarHorizontal.isIndeterminate());
 
-        progressBar.setIndeterminate(true);
-        assertTrue(progressBar.isIndeterminate());
+        mProgressBarHorizontal.setIndeterminate(true);
+        assertTrue(mProgressBarHorizontal.isIndeterminate());
 
-        progressBar.setIndeterminate(false);
-        assertFalse(progressBar.isIndeterminate());
+        mProgressBarHorizontal.setIndeterminate(false);
+        assertFalse(mProgressBarHorizontal.isIndeterminate());
     }
 
+    @UiThreadTest
     public void testAccessIndeterminateDrawable() {
-        ProgressBar progressBar = new ProgressBar(mContext);
-
         // set IndeterminateDrawable
         // normal value
-        MockDrawable mockDrawable = new MockDrawable();
-        progressBar.setIndeterminateDrawable(mockDrawable);
-        assertSame(mockDrawable, progressBar.getIndeterminateDrawable());
-        assertFalse(mockDrawable.hasCalledDraw());
-        progressBar.draw(new Canvas());
-        assertTrue(mockDrawable.hasCalledDraw());
+        Drawable mockProgressDrawable = spy(new ColorDrawable(Color.YELLOW));
+        mProgressBar.setIndeterminateDrawable(mockProgressDrawable);
+        assertSame(mockProgressDrawable, mProgressBar.getIndeterminateDrawable());
+        verify(mockProgressDrawable, never()).draw(any(Canvas.class));
+        mProgressBar.draw(new Canvas());
+        verify(mockProgressDrawable, atLeastOnce()).draw(any(Canvas.class));
 
         // exceptional value
-        progressBar.setIndeterminateDrawable(null);
-        assertNull(progressBar.getIndeterminateDrawable());
+        mProgressBar.setIndeterminateDrawable(null);
+        assertNull(mProgressBar.getIndeterminateDrawable());
     }
 
+    @UiThreadTest
     public void testAccessProgressDrawable() {
-        ProgressBar progressBar = new ProgressBar(mContext, null,
-                android.R.attr.progressBarStyleHorizontal);
-
         // set ProgressDrawable
         // normal value
-        MockDrawable mockDrawable = new MockDrawable();
-        progressBar.setProgressDrawable(mockDrawable);
-        assertSame(mockDrawable, progressBar.getProgressDrawable());
-        assertFalse(mockDrawable.hasCalledDraw());
-        progressBar.draw(new Canvas());
-        assertTrue(mockDrawable.hasCalledDraw());
+        Drawable mockProgressDrawable = spy(new ColorDrawable(Color.BLUE));
+        mProgressBarHorizontal.setProgressDrawable(mockProgressDrawable);
+        assertSame(mockProgressDrawable, mProgressBarHorizontal.getProgressDrawable());
+        verify(mockProgressDrawable, never()).draw(any(Canvas.class));
+        mProgressBarHorizontal.draw(new Canvas());
+        verify(mockProgressDrawable, atLeastOnce()).draw(any(Canvas.class));
 
         // exceptional value
-        progressBar.setProgressDrawable(null);
-        assertNull(progressBar.getProgressDrawable());
+        mProgressBarHorizontal.setProgressDrawable(null);
+        assertNull(mProgressBarHorizontal.getProgressDrawable());
     }
 
+    @UiThreadTest
     public void testAccessProgress() {
-        ProgressBar progressBar = new ProgressBar(mContext, null,
-                android.R.attr.progressBarStyleHorizontal);
-        assertEquals(0, progressBar.getProgress());
+        assertEquals(0, mProgressBarHorizontal.getProgress());
 
-        final int maxProgress = progressBar.getMax();
+        final int maxProgress = mProgressBarHorizontal.getMax();
         // set Progress
         // normal value
-        progressBar.setProgress(maxProgress >> 1);
-        assertEquals(maxProgress >> 1, progressBar.getProgress());
+        mProgressBarHorizontal.setProgress(maxProgress >> 1);
+        assertEquals(maxProgress >> 1, mProgressBarHorizontal.getProgress());
 
         // exceptional values
-        progressBar.setProgress(-1);
-        assertEquals(0, progressBar.getProgress());
+        mProgressBarHorizontal.setProgress(-1);
+        assertEquals(0, mProgressBarHorizontal.getProgress());
 
-        progressBar.setProgress(maxProgress + 1);
-        assertEquals(maxProgress, progressBar.getProgress());
+        mProgressBarHorizontal.setProgress(maxProgress + 1);
+        assertEquals(maxProgress, mProgressBarHorizontal.getProgress());
 
-        progressBar.setProgress(Integer.MAX_VALUE);
-        assertEquals(maxProgress, progressBar.getProgress());
+        mProgressBarHorizontal.setProgress(Integer.MAX_VALUE);
+        assertEquals(maxProgress, mProgressBarHorizontal.getProgress());
+
+        mProgressBarHorizontal.setProgress(0, true);
+        assertEquals(0, mProgressBarHorizontal.getProgress());
 
         // when in indeterminate mode
-        progressBar.setIndeterminate(true);
-        progressBar.setProgress(maxProgress >> 1);
-        assertEquals(0, progressBar.getProgress());
+        mProgressBarHorizontal.setIndeterminate(true);
+        mProgressBarHorizontal.setProgress(maxProgress >> 1);
+        assertEquals(0, mProgressBarHorizontal.getProgress());
     }
 
+    @UiThreadTest
     public void testAccessSecondaryProgress() {
-        ProgressBar progressBar = new ProgressBar(mContext, null,
-                android.R.attr.progressBarStyleHorizontal);
-        assertEquals(0, progressBar.getSecondaryProgress());
+        assertEquals(0, mProgressBarHorizontal.getSecondaryProgress());
 
-        final int maxProgress = progressBar.getMax();
+        final int maxProgress = mProgressBarHorizontal.getMax();
         // set SecondaryProgress
         // normal value
-        progressBar.setSecondaryProgress(maxProgress >> 1);
-        assertEquals(maxProgress >> 1, progressBar.getSecondaryProgress());
+        mProgressBarHorizontal.setSecondaryProgress(maxProgress >> 1);
+        assertEquals(maxProgress >> 1, mProgressBarHorizontal.getSecondaryProgress());
 
         // exceptional value
-        progressBar.setSecondaryProgress(-1);
-        assertEquals(0, progressBar.getSecondaryProgress());
+        mProgressBarHorizontal.setSecondaryProgress(-1);
+        assertEquals(0, mProgressBarHorizontal.getSecondaryProgress());
 
-        progressBar.setSecondaryProgress(maxProgress + 1);
-        assertEquals(maxProgress, progressBar.getSecondaryProgress());
+        mProgressBarHorizontal.setSecondaryProgress(maxProgress + 1);
+        assertEquals(maxProgress, mProgressBarHorizontal.getSecondaryProgress());
 
-        progressBar.setSecondaryProgress(Integer.MAX_VALUE);
-        assertEquals(maxProgress, progressBar.getSecondaryProgress());
+        mProgressBarHorizontal.setSecondaryProgress(Integer.MAX_VALUE);
+        assertEquals(maxProgress, mProgressBarHorizontal.getSecondaryProgress());
 
         // when in indeterminate mode
-        progressBar.setIndeterminate(true);
-        progressBar.setSecondaryProgress(maxProgress >> 1);
-        assertEquals(0, progressBar.getSecondaryProgress());
+        mProgressBarHorizontal.setIndeterminate(true);
+        mProgressBarHorizontal.setSecondaryProgress(maxProgress >> 1);
+        assertEquals(0, mProgressBarHorizontal.getSecondaryProgress());
     }
 
+    @UiThreadTest
     public void testIncrementProgressBy() {
-        ProgressBar progressBar = new ProgressBar(mContext, null,
-                android.R.attr.progressBarStyleHorizontal);
-
         // normal value
         int increment = 1;
-        int oldProgress = progressBar.getProgress();
-        progressBar.incrementProgressBy(increment);
-        assertEquals(oldProgress + increment, progressBar.getProgress());
+        int oldProgress = mProgressBarHorizontal.getProgress();
+        mProgressBarHorizontal.incrementProgressBy(increment);
+        assertEquals(oldProgress + increment, mProgressBarHorizontal.getProgress());
 
-        increment = progressBar.getMax() >> 1;
-        oldProgress = progressBar.getProgress();
-        progressBar.incrementProgressBy(increment);
-        assertEquals(oldProgress + increment, progressBar.getProgress());
+        increment = mProgressBarHorizontal.getMax() >> 1;
+        oldProgress = mProgressBarHorizontal.getProgress();
+        mProgressBarHorizontal.incrementProgressBy(increment);
+        assertEquals(oldProgress + increment, mProgressBarHorizontal.getProgress());
 
         // exceptional values
-        progressBar.setProgress(0);
-        progressBar.incrementProgressBy(Integer.MAX_VALUE);
-        assertEquals(progressBar.getMax(), progressBar.getProgress());
+        mProgressBarHorizontal.setProgress(0);
+        mProgressBarHorizontal.incrementProgressBy(Integer.MAX_VALUE);
+        assertEquals(mProgressBarHorizontal.getMax(), mProgressBarHorizontal.getProgress());
 
-        progressBar.setProgress(0);
-        progressBar.incrementProgressBy(Integer.MIN_VALUE);
-        assertEquals(0, progressBar.getProgress());
+        mProgressBarHorizontal.setProgress(0);
+        mProgressBarHorizontal.incrementProgressBy(Integer.MIN_VALUE);
+        assertEquals(0, mProgressBarHorizontal.getProgress());
     }
 
+    @UiThreadTest
     public void testIncrementSecondaryProgressBy() {
-        ProgressBar progressBar = new ProgressBar(mContext, null,
-                android.R.attr.progressBarStyleHorizontal);
-
         // normal value
         int increment = 1;
-        int oldSecondaryProgress = progressBar.getSecondaryProgress();
-        progressBar.incrementSecondaryProgressBy(increment);
-        assertEquals(oldSecondaryProgress + increment, progressBar.getSecondaryProgress());
+        int oldSecondaryProgress = mProgressBarHorizontal.getSecondaryProgress();
+        mProgressBarHorizontal.incrementSecondaryProgressBy(increment);
+        assertEquals(oldSecondaryProgress + increment,
+                mProgressBarHorizontal.getSecondaryProgress());
 
-        increment = progressBar.getMax() >> 1;
-        oldSecondaryProgress = progressBar.getSecondaryProgress();
-        progressBar.incrementSecondaryProgressBy(increment);
-        assertEquals(oldSecondaryProgress + increment, progressBar.getSecondaryProgress());
+        increment = mProgressBarHorizontal.getMax() >> 1;
+        oldSecondaryProgress = mProgressBarHorizontal.getSecondaryProgress();
+        mProgressBarHorizontal.incrementSecondaryProgressBy(increment);
+        assertEquals(oldSecondaryProgress + increment,
+                mProgressBarHorizontal.getSecondaryProgress());
 
         // exceptional values
-        progressBar.setSecondaryProgress(0);
-        progressBar.incrementSecondaryProgressBy(Integer.MAX_VALUE);
-        assertEquals(progressBar.getMax(), progressBar.getSecondaryProgress());
+        mProgressBarHorizontal.setSecondaryProgress(0);
+        mProgressBarHorizontal.incrementSecondaryProgressBy(Integer.MAX_VALUE);
+        assertEquals(mProgressBarHorizontal.getMax(),
+                mProgressBarHorizontal.getSecondaryProgress());
 
-        progressBar.setSecondaryProgress(0);
-        progressBar.incrementSecondaryProgressBy(Integer.MIN_VALUE);
-        assertEquals(0, progressBar.getSecondaryProgress());
+        mProgressBarHorizontal.setSecondaryProgress(0);
+        mProgressBarHorizontal.incrementSecondaryProgressBy(Integer.MIN_VALUE);
+        assertEquals(0, mProgressBarHorizontal.getSecondaryProgress());
     }
 
+    @UiThreadTest
     public void testAccessInterpolator() {
-        ProgressBar progressBar = new ProgressBar(mContext);
-
         // default should be LinearInterpolator
-        assertTrue(progressBar.getInterpolator() instanceof LinearInterpolator);
+        assertTrue(mProgressBar.getInterpolator() instanceof LinearInterpolator);
 
-        // normal value
-        Interpolator i = new AccelerateDecelerateInterpolator();
-        progressBar.setInterpolator(i);
-        assertEquals(i, progressBar.getInterpolator());
+        Interpolator interpolator = new AccelerateDecelerateInterpolator();
+        mProgressBar.setInterpolator(interpolator);
+        assertEquals(interpolator, mProgressBar.getInterpolator());
+
+        mProgressBar.setInterpolator(mActivity, android.R.anim.accelerate_interpolator);
+        assertTrue(mProgressBar.getInterpolator() instanceof AccelerateInterpolator);
     }
 
+    @UiThreadTest
     public void testSetVisibility() {
-        ProgressBar progressBar = new ProgressBar(mContext, null,
-                android.R.attr.progressBarStyleHorizontal);
-
         // set visibility
         // normal value
         int visibility = View.VISIBLE;
-        progressBar.setVisibility(visibility);
-        assertEquals(visibility, progressBar.getVisibility());
+        mProgressBarHorizontal.setVisibility(visibility);
+        assertEquals(visibility, mProgressBarHorizontal.getVisibility());
 
         visibility = View.GONE;
-        progressBar.setVisibility(visibility);
-        assertEquals(visibility, progressBar.getVisibility());
+        mProgressBarHorizontal.setVisibility(visibility);
+        assertEquals(visibility, mProgressBarHorizontal.getVisibility());
 
         // exceptional value
         visibility = 0xfffffff5; // -11
         int mask = 0x0000000C; // View.VISIBILITY_MASK
-        int expected = (progressBar.getVisibility() & ~mask) | (visibility & mask);
-        progressBar.setVisibility(visibility);
-        assertEquals(expected, progressBar.getVisibility());
+        int expected = (mProgressBarHorizontal.getVisibility() & ~mask) | (visibility & mask);
+        mProgressBarHorizontal.setVisibility(visibility);
+        assertEquals(expected, mProgressBarHorizontal.getVisibility());
 
         visibility = 0x7fffffff; // Integer.MAX_VALUE;
-        expected = (progressBar.getVisibility() & ~mask) | (visibility & mask);
-        progressBar.setVisibility(Integer.MAX_VALUE);
-        assertEquals(expected, progressBar.getVisibility());
+        expected = (mProgressBarHorizontal.getVisibility() & ~mask) | (visibility & mask);
+        mProgressBarHorizontal.setVisibility(Integer.MAX_VALUE);
+        assertEquals(expected, mProgressBarHorizontal.getVisibility());
     }
 
+    @UiThreadTest
     public void testInvalidateDrawable() {
-        MockProgressBar mockProgressBar = new MockProgressBar(mContext);
+        ProgressBar mockProgressBar = spy(new ProgressBar(mActivity));
 
-        MockDrawable mockDrawable1 = new MockDrawable();
-        MockDrawable mockDrawable2 = new MockDrawable();
+        Drawable mockDrawable1 = spy(new ColorDrawable(Color.RED));
+        Drawable mockDrawable2 = spy(new ColorDrawable(Color.GREEN));
         mockProgressBar.setBackgroundDrawable(mockDrawable1);
 
         mockProgressBar.invalidateDrawable(mockDrawable1);
-        assertTrue(mockProgressBar.hasCalledInvalidate());
+        verify(mockProgressBar, atLeastOnce()).invalidate(anyInt(), anyInt(), anyInt(), anyInt());
 
-        mockProgressBar.reset();
+        reset(mockProgressBar);
         mockProgressBar.invalidateDrawable(mockDrawable2);
-        assertFalse(mockProgressBar.hasCalledInvalidate());
+        verify(mockProgressBar, never()).invalidate(anyInt(), anyInt(), anyInt(), anyInt());
 
         mockProgressBar.setIndeterminateDrawable(mockDrawable1);
         mockProgressBar.setProgressDrawable(mockDrawable2);
     }
 
+    @UiThreadTest
     public void testPostInvalidate() {
-        MockProgressBar mockProgressBar = new MockProgressBar(mContext);
-        mockProgressBar.postInvalidate();
+        mProgressBarHorizontal.postInvalidate();
     }
 
+    @UiThreadTest
     public void testAccessMax() {
-        ProgressBar progressBar = new ProgressBar(mContext, null,
-                android.R.attr.progressBarStyleHorizontal);
-
         // set Progress
         int progress = 10;
-        progressBar.setProgress(progress);
+        mProgressBarHorizontal.setProgress(progress);
 
         // normal value
         int max = progress + 1;
-        progressBar.setMax(max);
-        assertEquals(max, progressBar.getMax());
-        assertEquals(progress, progressBar.getProgress());
+        mProgressBarHorizontal.setMax(max);
+        assertEquals(max, mProgressBarHorizontal.getMax());
+        assertEquals(progress, mProgressBarHorizontal.getProgress());
 
         max = progress - 1;
-        progressBar.setMax(max);
-        assertEquals(max, progressBar.getMax());
-        assertEquals(max, progressBar.getProgress());
+        mProgressBarHorizontal.setMax(max);
+        assertEquals(max, mProgressBarHorizontal.getMax());
+        assertEquals(max, mProgressBarHorizontal.getProgress());
 
         // exceptional values
-        progressBar.setMax(-1);
-        assertEquals(0, progressBar.getMax());
-        assertEquals(0, progressBar.getProgress());
+        mProgressBarHorizontal.setMax(-1);
+        assertEquals(0, mProgressBarHorizontal.getMax());
+        assertEquals(0, mProgressBarHorizontal.getProgress());
 
-        progressBar.setMax(Integer.MAX_VALUE);
-        assertEquals(Integer.MAX_VALUE, progressBar.getMax());
-        assertEquals(0, progressBar.getProgress());
+        mProgressBarHorizontal.setMax(Integer.MAX_VALUE);
+        assertEquals(Integer.MAX_VALUE, mProgressBarHorizontal.getMax());
+        assertEquals(0, mProgressBarHorizontal.getProgress());
     }
 
     public void testOnDraw() {
         // Do not test, it's controlled by View. Implementation details
     }
 
+    @UiThreadTest
     public void testProgressTint() {
-        LayoutInflater inflater = LayoutInflater.from(mContext);
-        View layout = inflater.inflate(R.layout.progressbar_layout, null);
-        ProgressBar inflatedView = (ProgressBar) layout.findViewById(R.id.progress_tint);
+        ProgressBar tintedProgressBar = (ProgressBar) mActivity.findViewById(R.id.progress_tint);
 
         assertEquals("Progress tint inflated correctly",
-                Color.WHITE, inflatedView.getProgressTintList().getDefaultColor());
+                Color.WHITE, tintedProgressBar.getProgressTintList().getDefaultColor());
         assertEquals("Progress tint mode inflated correctly",
-                PorterDuff.Mode.SRC_OVER, inflatedView.getProgressTintMode());
+                PorterDuff.Mode.SRC_OVER, tintedProgressBar.getProgressTintMode());
 
         assertEquals("Progress background tint inflated correctly",
-                Color.WHITE, inflatedView.getProgressBackgroundTintList().getDefaultColor());
+                Color.WHITE, tintedProgressBar.getProgressBackgroundTintList().getDefaultColor());
         assertEquals("Progress background tint mode inflated correctly",
-                PorterDuff.Mode.SRC_OVER, inflatedView.getProgressBackgroundTintMode());
+                PorterDuff.Mode.SRC_OVER, tintedProgressBar.getProgressBackgroundTintMode());
 
         assertEquals("Secondary progress tint inflated correctly",
-                Color.WHITE, inflatedView.getSecondaryProgressTintList().getDefaultColor());
+                Color.WHITE, tintedProgressBar.getSecondaryProgressTintList().getDefaultColor());
         assertEquals("Secondary progress tint mode inflated correctly",
-                PorterDuff.Mode.SRC_OVER, inflatedView.getSecondaryProgressTintMode());
+                PorterDuff.Mode.SRC_OVER, tintedProgressBar.getSecondaryProgressTintMode());
 
-        MockDrawable progress = new MockDrawable();
-        ProgressBar view = new ProgressBar(mContext);
+        Drawable mockProgressDrawable = spy(new ColorDrawable(Color.BLACK));
 
-        view.setProgressDrawable(progress);
-        assertFalse("No progress tint applied by default", progress.hasCalledSetTint());
+        mProgressBar.setProgressDrawable(mockProgressDrawable);
+        // No progress tint applied by default
+        verify(mockProgressDrawable, never()).setTintList(any(ColorStateList.class));
 
-        view.setProgressBackgroundTintList(ColorStateList.valueOf(Color.WHITE));
-        assertFalse("Progress background tint not applied when layer missing",
-                progress.hasCalledSetTint());
+        mProgressBar.setProgressBackgroundTintList(ColorStateList.valueOf(Color.WHITE));
+        // Progress background tint not applied when layer missing
+        verify(mockProgressDrawable, never()).setTintList(any(ColorStateList.class));
 
-        view.setSecondaryProgressTintList(ColorStateList.valueOf(Color.WHITE));
-        assertFalse("Secondary progress tint not applied when layer missing",
-                progress.hasCalledSetTint());
+        mProgressBar.setSecondaryProgressTintList(ColorStateList.valueOf(Color.WHITE));
+        // Secondary progress tint not applied when layer missing
+        verify(mockProgressDrawable, never()).setTintList(any(ColorStateList.class));
 
-        view.setProgressTintList(ColorStateList.valueOf(Color.WHITE));
-        assertTrue("Progress tint applied when setProgressTintList() called after setProgress()",
-                progress.hasCalledSetTint());
+        mProgressBar.setProgressTintList(ColorStateList.valueOf(Color.WHITE));
+        // Progress tint applied when setProgressTintList() called after setProgress()
+        verify(mockProgressDrawable, times(1)).setTintList(TestUtils.colorStateListOf(Color.WHITE));
 
-        progress.reset();
-        view.setProgressDrawable(null);
-        view.setProgressDrawable(progress);
-        assertTrue("Progress tint applied when setProgressTintList() called before setProgress()",
-                progress.hasCalledSetTint());
+        mProgressBar.setProgressBackgroundTintMode(PorterDuff.Mode.DST_OVER);
+        assertEquals(PorterDuff.Mode.DST_OVER, mProgressBar.getProgressBackgroundTintMode());
+
+        mProgressBar.setSecondaryProgressTintMode(PorterDuff.Mode.DST_IN);
+        assertEquals(PorterDuff.Mode.DST_IN, mProgressBar.getSecondaryProgressTintMode());
+
+        mProgressBar.setProgressTintMode(PorterDuff.Mode.DST_ATOP);
+        assertEquals(PorterDuff.Mode.DST_ATOP, mProgressBar.getProgressTintMode());
+
+        reset(mockProgressDrawable);
+        mProgressBar.setProgressDrawable(null);
+        mProgressBar.setProgressDrawable(mockProgressDrawable);
+        // Progress tint applied when setProgressTintList() called before setProgress()
+        verify(mockProgressDrawable, times(1)).setTintList(TestUtils.colorStateListOf(Color.WHITE));
     }
 
+    @UiThreadTest
     public void testIndeterminateTint() {
-        LayoutInflater inflater = LayoutInflater.from(mContext);
-        View layout = inflater.inflate(R.layout.progressbar_layout, null);
-        ProgressBar inflatedView = (ProgressBar) layout.findViewById(R.id.indeterminate_tint);
+        ProgressBar tintedProgressBar =
+                (ProgressBar) mActivity.findViewById(R.id.indeterminate_tint);
 
         assertEquals("Indeterminate tint inflated correctly",
-                Color.WHITE, inflatedView.getIndeterminateTintList().getDefaultColor());
+                Color.WHITE, tintedProgressBar.getIndeterminateTintList().getDefaultColor());
         assertEquals("Indeterminate tint mode inflated correctly",
-                PorterDuff.Mode.SRC_OVER, inflatedView.getIndeterminateTintMode());
+                PorterDuff.Mode.SRC_OVER, tintedProgressBar.getIndeterminateTintMode());
 
-        MockDrawable indeterminate = new MockDrawable();
-        ProgressBar view = new ProgressBar(mContext);
+        Drawable mockIndeterminateDrawable = spy(new ColorDrawable(Color.MAGENTA));
 
-        view.setIndeterminateDrawable(indeterminate);
-        assertFalse("No indeterminate tint applied by default", indeterminate.hasCalledSetTint());
+        mProgressBar.setIndeterminateDrawable(mockIndeterminateDrawable);
+        // No indeterminate tint applied by default
+        verify(mockIndeterminateDrawable, never()).setTintList(any(ColorStateList.class));
 
-        view.setIndeterminateTintList(ColorStateList.valueOf(Color.WHITE));
-        assertTrue("Indeterminate tint applied when setIndeterminateTintList() called after "
-                + "setIndeterminate()", indeterminate.hasCalledSetTint());
+        mProgressBar.setIndeterminateTintList(ColorStateList.valueOf(Color.RED));
+        // Indeterminate tint applied when setIndeterminateTintList() called after
+        // setIndeterminate()
+        verify(mockIndeterminateDrawable, times(1)).setTintList(
+                TestUtils.colorStateListOf(Color.RED));
 
-        indeterminate.reset();
-        view.setIndeterminateDrawable(null);
-        view.setIndeterminateDrawable(indeterminate);
-        assertTrue("Indeterminate tint applied when setIndeterminateTintList() called before "
-                + "setIndeterminate()", indeterminate.hasCalledSetTint());
-    }
+        mProgressBar.setIndeterminateTintMode(PorterDuff.Mode.LIGHTEN);
+        assertEquals(PorterDuff.Mode.LIGHTEN, mProgressBar.getIndeterminateTintMode());
 
-    private class MockDrawable extends Drawable {
-        private boolean mCalledDraw = false;
-        private boolean mCalledSetTint = false;
-
-        @Override
-        public void draw(Canvas canvas) {
-            mCalledDraw = true;
-        }
-
-        @Override
-        public int getOpacity() {
-            return 0;
-        }
-
-        @Override
-        public void setAlpha(int alpha) {
-        }
-
-        @Override
-        public void setColorFilter(ColorFilter cf) {
-        }
-
-        @Override
-        public void setTintList(ColorStateList tint) {
-            super.setTintList(tint);
-            mCalledSetTint = true;
-        }
-
-        public boolean hasCalledSetTint() {
-            return mCalledSetTint;
-        }
-
-        public boolean hasCalledDraw() {
-            return mCalledDraw;
-        }
-
-        public void reset() {
-            mCalledDraw = false;
-            mCalledSetTint = false;
-        }
-
+        reset(mockIndeterminateDrawable);
+        mProgressBar.setIndeterminateDrawable(null);
+        mProgressBar.setIndeterminateDrawable(mockIndeterminateDrawable);
+        // Indeterminate tint applied when setIndeterminateTintList() called before
+        // setIndeterminate()
+        verify(mockIndeterminateDrawable, times(1)).setTintList(
+                TestUtils.colorStateListOf(Color.RED));
     }
 
     public void testOnMeasure() {
@@ -432,13 +469,14 @@
         // onSizeChanged() is implementation details, do NOT test
     }
 
+    @UiThreadTest
     public void testVerifyDrawable() {
-        MockProgressBar mockProgressBar = new MockProgressBar(mContext);
+        MockProgressBar mockProgressBar = new MockProgressBar(mActivity);
         assertTrue(mockProgressBar.verifyDrawable(null));
 
-        Drawable d1 = mContext.getResources().getDrawable(R.drawable.blue);
-        Drawable d2 = mContext.getResources().getDrawable(R.drawable.red);
-        Drawable d3 = mContext.getResources().getDrawable(R.drawable.yellow);
+        Drawable d1 = mActivity.getResources().getDrawable(R.drawable.blue);
+        Drawable d2 = mActivity.getResources().getDrawable(R.drawable.red);
+        Drawable d3 = mActivity.getResources().getDrawable(R.drawable.yellow);
 
         mockProgressBar.setBackgroundDrawable(d1);
         assertTrue(mockProgressBar.verifyDrawable(null));
@@ -463,39 +501,33 @@
         // drawableStateChanged() is implementation details, do NOT test
     }
 
+    @UiThreadTest
     public void testOnSaveAndRestoreInstanceState() {
-        ProgressBar progressBar = new ProgressBar(mContext, null,
-                android.R.attr.progressBarStyleHorizontal);
         int oldProgress = 1;
-        int oldSecondaryProgress = progressBar.getMax() - 1;
-        progressBar.setProgress(oldProgress);
-        progressBar.setSecondaryProgress(oldSecondaryProgress);
-        assertEquals(oldProgress, progressBar.getProgress());
-        assertEquals(oldSecondaryProgress, progressBar.getSecondaryProgress());
+        int oldSecondaryProgress = mProgressBarHorizontal.getMax() - 1;
+        mProgressBarHorizontal.setProgress(oldProgress);
+        mProgressBarHorizontal.setSecondaryProgress(oldSecondaryProgress);
+        assertEquals(oldProgress, mProgressBarHorizontal.getProgress());
+        assertEquals(oldSecondaryProgress, mProgressBarHorizontal.getSecondaryProgress());
 
-        Parcelable state = progressBar.onSaveInstanceState();
+        Parcelable state = mProgressBarHorizontal.onSaveInstanceState();
 
         int newProgress = 2;
-        int newSecondaryProgress = progressBar.getMax() - 2;
-        progressBar.setProgress(newProgress);
-        progressBar.setSecondaryProgress(newSecondaryProgress);
-        assertEquals(newProgress, progressBar.getProgress());
-        assertEquals(newSecondaryProgress, progressBar.getSecondaryProgress());
+        int newSecondaryProgress = mProgressBarHorizontal.getMax() - 2;
+        mProgressBarHorizontal.setProgress(newProgress);
+        mProgressBarHorizontal.setSecondaryProgress(newSecondaryProgress);
+        assertEquals(newProgress, mProgressBarHorizontal.getProgress());
+        assertEquals(newSecondaryProgress, mProgressBarHorizontal.getSecondaryProgress());
 
-        progressBar.onRestoreInstanceState(state);
-        assertEquals(oldProgress, progressBar.getProgress());
-        assertEquals(oldSecondaryProgress, progressBar.getSecondaryProgress());
+        mProgressBarHorizontal.onRestoreInstanceState(state);
+        assertEquals(oldProgress, mProgressBarHorizontal.getProgress());
+        assertEquals(oldSecondaryProgress, mProgressBarHorizontal.getSecondaryProgress());
     }
 
     /*
      * Mock class for ProgressBar to test protected methods
      */
     private class MockProgressBar extends ProgressBar {
-        private boolean mCalledInvalidate = false;
-
-        /**
-         * @param context
-         */
         public MockProgressBar(Context context) {
             super(context);
         }
@@ -504,44 +536,5 @@
         protected boolean verifyDrawable(Drawable who) {
             return super.verifyDrawable(who);
         }
-
-        @Override
-        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
-            super.onSizeChanged(w, h, oldw, oldh);
-        }
-
-        @Override
-        protected synchronized void onMeasure(int widthMeasureSpec,
-                int heightMeasureSpec) {
-            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-        }
-
-        @Override
-        protected synchronized void onDraw(Canvas canvas) {
-            super.onDraw(canvas);
-        }
-
-        @Override
-        protected void drawableStateChanged() {
-            super.drawableStateChanged();
-        }
-
-        public void invalidate(int l, int t, int r, int b) {
-            mCalledInvalidate = true;
-            super.invalidate(l, t, r, b);
-        }
-
-        public void invalidate() {
-            mCalledInvalidate = true;
-            super.invalidate();
-        }
-
-        public boolean hasCalledInvalidate() {
-            return mCalledInvalidate;
-        }
-
-        public void reset() {
-            mCalledInvalidate = false;
-        }
     }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/RadioButtonCtsActivity.java b/tests/tests/widget/src/android/widget/cts/RadioButtonCtsActivity.java
new file mode 100644
index 0000000..442d5f7
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/RadioButtonCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.RadioButton;
+
+/**
+ * A minimal application for {@link RadioButton} test.
+ */
+public class RadioButtonCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.radiobutton_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java b/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java
index eb9387b..0b03557 100644
--- a/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java
@@ -16,6 +16,12 @@
 
 package android.widget.cts;
 
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.TextUtils;
+import android.widget.CheckBox;
 import android.widget.cts.R;
 
 
@@ -24,59 +30,160 @@
 import android.test.UiThreadTest;
 import android.util.AttributeSet;
 import android.widget.RadioButton;
+import android.widget.cts.util.ViewTestUtils;
 
-/**
- * Test {@link RadioButton}.
- */
-public class RadioButtonTest extends InstrumentationTestCase {
-    private Context mContext;
+import static org.mockito.Mockito.*;
+
+@SmallTest
+public class RadioButtonTest extends ActivityInstrumentationTestCase2<RadioButtonCtsActivity> {
+    private Instrumentation mInstrumentation;
+    private Activity mActivity;
+    private RadioButton mRadioButton;
+
+    public RadioButtonTest() {
+        super("android.widget.cts", RadioButtonCtsActivity.class);
+    }
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mContext = getInstrumentation().getTargetContext();
+
+        mInstrumentation = getInstrumentation();
+        mActivity = getActivity();
+        mRadioButton = (RadioButton) mActivity.findViewById(R.id.radio_button);
     }
 
     public void testConstructor() {
-        AttributeSet attrs = mContext.getResources().getLayout(R.layout.radiogroup_1);
-        assertNotNull(attrs);
+        new RadioButton(mActivity);
+        new RadioButton(mActivity, null);
+        new RadioButton(mActivity, null, android.R.attr.radioButtonStyle);
+        new RadioButton(mActivity, null, 0,
+                android.R.style.Widget_DeviceDefault_CompoundButton_RadioButton);
+        new RadioButton(mActivity, null, 0,
+                android.R.style.Widget_DeviceDefault_Light_CompoundButton_RadioButton);
+        new RadioButton(mActivity, null, 0,
+                android.R.style.Widget_Material_CompoundButton_RadioButton);
+        new RadioButton(mActivity, null, 0,
+                android.R.style.Widget_Material_Light_CompoundButton_RadioButton);
 
-        new RadioButton(mContext);
         try {
             new RadioButton(null);
             fail("The constructor should throw NullPointerException when param Context is null.");
         } catch (NullPointerException e) {
         }
 
-        new RadioButton(mContext, attrs);
         try {
-            new RadioButton(null, attrs);
+            new RadioButton(null, null);
             fail("The constructor should throw NullPointerException when param Context is null.");
         } catch (NullPointerException e) {
         }
-        new RadioButton(mContext, null);
-
-        new RadioButton(mContext, attrs, 0);
         try {
-            new RadioButton(null, attrs, 0);
+            new RadioButton(null, null, 0);
             fail("The constructor should throw NullPointerException when param Context is null.");
         } catch (NullPointerException e) {
         }
-        new RadioButton(mContext, null, 0);
-        new RadioButton(mContext, attrs, Integer.MAX_VALUE);
-        new RadioButton(mContext, attrs, Integer.MIN_VALUE);
     }
 
-    @UiThreadTest
-    public void testToggle() {
-        RadioButton button = new RadioButton(mContext);
-        assertFalse(button.isChecked());
+    public void testText() {
+        assertTrue(TextUtils.equals(
+                mActivity.getString(R.string.hello_world), mRadioButton.getText()));
 
-        button.toggle();
-        assertTrue(button.isChecked());
+        mInstrumentation.runOnMainSync(() -> mRadioButton.setText("new text"));
+        assertTrue(TextUtils.equals("new text", mRadioButton.getText()));
 
-        // Can't be toggled if it is checked
-        button.toggle();
-        assertTrue(button.isChecked());
+        mInstrumentation.runOnMainSync(() -> mRadioButton.setText(R.string.text_name));
+        assertTrue(TextUtils.equals(
+                mActivity.getString(R.string.text_name), mRadioButton.getText()));
+    }
+
+    public void testAccessChecked() {
+        final RadioButton.OnCheckedChangeListener mockCheckedChangeListener =
+                mock(RadioButton.OnCheckedChangeListener.class);
+        mRadioButton.setOnCheckedChangeListener(mockCheckedChangeListener);
+        verifyZeroInteractions(mockCheckedChangeListener);
+
+        assertFalse(mRadioButton.isChecked());
+
+        // not checked -> not checked
+        mInstrumentation.runOnMainSync(() -> mRadioButton.setChecked(false));
+        verifyZeroInteractions(mockCheckedChangeListener);
+        assertFalse(mRadioButton.isChecked());
+
+        // not checked -> checked
+        mInstrumentation.runOnMainSync(() -> mRadioButton.setChecked(true));
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mRadioButton, true);
+        assertTrue(mRadioButton.isChecked());
+
+        // checked -> checked
+        mInstrumentation.runOnMainSync(() -> mRadioButton.setChecked(true));
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mRadioButton, true);
+        assertTrue(mRadioButton.isChecked());
+
+        // checked -> not checked
+        mInstrumentation.runOnMainSync(() -> mRadioButton.setChecked(false));
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mRadioButton, false);
+        assertFalse(mRadioButton.isChecked());
+
+        verifyNoMoreInteractions(mockCheckedChangeListener);
+    }
+
+    public void testToggleViaApi() {
+        final RadioButton.OnCheckedChangeListener mockCheckedChangeListener =
+                mock(RadioButton.OnCheckedChangeListener.class);
+        mRadioButton.setOnCheckedChangeListener(mockCheckedChangeListener);
+        verifyZeroInteractions(mockCheckedChangeListener);
+
+        assertFalse(mRadioButton.isChecked());
+
+        // toggle to checked
+        mInstrumentation.runOnMainSync(() -> mRadioButton.toggle());
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mRadioButton, true);
+        assertTrue(mRadioButton.isChecked());
+
+        // try toggle to not checked - this should leave the radio button in checked state
+        mInstrumentation.runOnMainSync(() -> mRadioButton.toggle());
+        assertTrue(mRadioButton.isChecked());
+
+        verifyNoMoreInteractions(mockCheckedChangeListener);
+    }
+
+    public void testToggleViaEmulatedTap() {
+        final RadioButton.OnCheckedChangeListener mockCheckedChangeListener =
+                mock(RadioButton.OnCheckedChangeListener.class);
+        mRadioButton.setOnCheckedChangeListener(mockCheckedChangeListener);
+        verifyZeroInteractions(mockCheckedChangeListener);
+
+        assertFalse(mRadioButton.isChecked());
+
+        // tap to checked
+        ViewTestUtils.emulateTapOnViewCenter(mInstrumentation, mRadioButton);
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mRadioButton, true);
+        assertTrue(mRadioButton.isChecked());
+
+        // tap to not checked - this should leave the radio button in checked state
+        ViewTestUtils.emulateTapOnViewCenter(mInstrumentation, mRadioButton);
+        assertTrue(mRadioButton.isChecked());
+
+        verifyNoMoreInteractions(mockCheckedChangeListener);
+    }
+
+    public void testToggleViaPerformClick() {
+        final RadioButton.OnCheckedChangeListener mockCheckedChangeListener =
+                mock(RadioButton.OnCheckedChangeListener.class);
+        mRadioButton.setOnCheckedChangeListener(mockCheckedChangeListener);
+        verifyZeroInteractions(mockCheckedChangeListener);
+
+        assertFalse(mRadioButton.isChecked());
+
+        // click to checked
+        mInstrumentation.runOnMainSync(() -> mRadioButton.performClick());
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mRadioButton, true);
+        assertTrue(mRadioButton.isChecked());
+
+        // click to not checked - this should leave the radio button in checked state
+        mInstrumentation.runOnMainSync(() -> mRadioButton.performClick());
+        assertTrue(mRadioButton.isChecked());
+
+        verifyNoMoreInteractions(mockCheckedChangeListener);
     }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/RatingBarTest.java b/tests/tests/widget/src/android/widget/cts/RatingBarTest.java
index 669e7a1..aa5f3c8 100644
--- a/tests/tests/widget/src/android/widget/cts/RatingBarTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RatingBarTest.java
@@ -16,20 +16,21 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
-import android.content.Context;
+import android.app.Instrumentation;
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.widget.RatingBar;
-import android.widget.RatingBar.OnRatingBarChangeListener;
+
+import static org.mockito.Mockito.*;
 
 /**
  * Test {@link RatingBar}.
  */
+@SmallTest
 public class RatingBarTest extends ActivityInstrumentationTestCase2<RatingBarCtsActivity> {
-    private Context mContext;
+    private Instrumentation mInstrumentation;
     private RatingBarCtsActivity mActivity;
+    private RatingBar mRatingBar;
 
     public RatingBarTest() {
         super("android.widget.cts", RatingBarCtsActivity.class);
@@ -38,213 +39,137 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+
+        mInstrumentation = getInstrumentation();
         mActivity = getActivity();
-        assertNotNull(mActivity);
-        mContext = getInstrumentation().getContext();
+        mRatingBar = (RatingBar) mActivity.findViewById(R.id.ratingbar_constructor);
     }
 
     public void testConstructor() {
-        new RatingBar(mContext, null, android.R.attr.ratingBarStyle);
-
-        new RatingBar(mContext, null);
-
-        new RatingBar(mContext);
-
-        RatingBar ratingBar = (RatingBar) mActivity.findViewById(R.id.ratingbar_constructor);
-        assertNotNull(ratingBar);
-        assertFalse(ratingBar.isIndicator());
-        assertEquals(50, ratingBar.getNumStars());
-        assertEquals(1.2f, ratingBar.getRating());
-        assertEquals(0.2f, ratingBar.getStepSize());
+        new RatingBar(mActivity);
+        new RatingBar(mActivity, null);
+        new RatingBar(mActivity, null, android.R.attr.ratingBarStyle);
+        new RatingBar(mActivity, null, 0, android.R.style.Widget_DeviceDefault_RatingBar);
+        new RatingBar(mActivity, null, 0, android.R.style.Widget_DeviceDefault_RatingBar_Indicator);
+        new RatingBar(mActivity, null, 0, android.R.style.Widget_DeviceDefault_RatingBar_Small);
+        new RatingBar(mActivity, null, 0, android.R.style.Widget_Material_RatingBar);
+        new RatingBar(mActivity, null, 0, android.R.style.Widget_Material_RatingBar_Indicator);
+        new RatingBar(mActivity, null, 0, android.R.style.Widget_Material_RatingBar_Small);
+        new RatingBar(mActivity, null, 0, android.R.style.Widget_Material_Light_RatingBar);
+        new RatingBar(mActivity, null, 0, android.R.style.Widget_Material_Light_RatingBar_Indicator);
+        new RatingBar(mActivity, null, 0, android.R.style.Widget_Material_Light_RatingBar_Small);
     }
 
-    @UiThreadTest
+    public void testAttributesFromLayout() {
+        assertFalse(mRatingBar.isIndicator());
+        assertEquals(50, mRatingBar.getNumStars());
+        assertEquals(1.2f, mRatingBar.getRating());
+        assertEquals(0.2f, mRatingBar.getStepSize());
+    }
+
     public void testAccessOnRatingBarChangeListener() {
-        RatingBar ratingBar = (RatingBar)mActivity.findViewById(R.id.ratingbar_constructor);
+        final RatingBar.OnRatingBarChangeListener listener =
+                mock(RatingBar.OnRatingBarChangeListener.class);
+        mRatingBar.setOnRatingBarChangeListener(listener);
+        assertSame(listener, mRatingBar.getOnRatingBarChangeListener());
+        verifyZeroInteractions(listener);
 
-        MockOnRatingBarChangeListener listener = new MockOnRatingBarChangeListener();
-
-        // set OnRatingBarChangeListener
         // normal value
-        ratingBar.setOnRatingBarChangeListener(listener);
-        assertSame(listener, ratingBar.getOnRatingBarChangeListener());
-        ratingBar.setRating(2.2f);
-        assertTrue(listener.hasCalledOnRatingChanged());
+        mInstrumentation.runOnMainSync(() -> mRatingBar.setRating(2.2f));
+        verify(listener, times(1)).onRatingChanged(mRatingBar, 2.2f, false);
 
         // exceptional value
-        listener.reset();
-        ratingBar.setOnRatingBarChangeListener(null);
-        assertNull(ratingBar.getOnRatingBarChangeListener());
-        ratingBar.setRating(1.2f);
-        assertFalse(listener.hasCalledOnRatingChanged());
+        mRatingBar.setOnRatingBarChangeListener(null);
+        assertNull(mRatingBar.getOnRatingBarChangeListener());
+        mRatingBar.setRating(1.2f);
+        verifyNoMoreInteractions(listener);
     }
 
     public void testAccessIndicator() {
-        RatingBar ratingBar = new RatingBar(mContext);
+        mInstrumentation.runOnMainSync(() -> mRatingBar.setIsIndicator(true));
+        assertTrue(mRatingBar.isIndicator());
 
-        ratingBar.setIsIndicator(true);
-        assertTrue(ratingBar.isIndicator());
-
-        ratingBar.setIsIndicator(false);
-        assertFalse(ratingBar.isIndicator());
+        mInstrumentation.runOnMainSync(() -> mRatingBar.setIsIndicator(false));
+        assertFalse(mRatingBar.isIndicator());
     }
 
     public void testAccessNumStars() {
-        MockRatingBar mockRatingBar = new MockRatingBar(mContext);
-
         // set NumStars
         // normal value
-        assertFalse(mockRatingBar.hasCalledRequestLayout());
-        mockRatingBar.setNumStars(20);
-        assertTrue(mockRatingBar.hasCalledRequestLayout());
-        assertEquals(20, mockRatingBar.getNumStars());
+        mInstrumentation.runOnMainSync(() -> mRatingBar.setNumStars(20));
+        assertEquals(20, mRatingBar.getNumStars());
 
-        // exceptional value
-        mockRatingBar.reset();
-        mockRatingBar.setNumStars(-10);
-        assertFalse(mockRatingBar.hasCalledRequestLayout());
-        assertEquals(20, mockRatingBar.getNumStars());
+        // invalid value - the currently set one stays
+        mInstrumentation.runOnMainSync(() -> mRatingBar.setNumStars(-10));
+        assertEquals(20, mRatingBar.getNumStars());
 
-        mockRatingBar.reset();
-        mockRatingBar.setNumStars(Integer.MAX_VALUE);
-        assertTrue(mockRatingBar.hasCalledRequestLayout());
-        assertEquals(Integer.MAX_VALUE, mockRatingBar.getNumStars());
+        mInstrumentation.runOnMainSync(() -> mRatingBar.setNumStars(Integer.MAX_VALUE));
+        assertEquals(Integer.MAX_VALUE, mRatingBar.getNumStars());
     }
 
     public void testAccessRating() {
-        RatingBar ratingBar = new RatingBar(mContext);
-
         // set Rating
         // normal value
-        ratingBar.setRating(2.0f);
-        assertEquals(2.0f, ratingBar.getRating());
+        mInstrumentation.runOnMainSync(() -> mRatingBar.setRating(2.0f));
+        assertEquals(2.0f, mRatingBar.getRating());
 
         // exceptional value
-        ratingBar.setRating(-2.0f);
-        assertEquals(0f, ratingBar.getRating());
+        mInstrumentation.runOnMainSync(() -> mRatingBar.setRating(-2.0f));
+        assertEquals(0f, mRatingBar.getRating());
 
-        ratingBar.setRating(Float.MAX_VALUE);
-        assertEquals((float) ratingBar.getNumStars(), ratingBar.getRating());
+        mInstrumentation.runOnMainSync(() -> mRatingBar.setRating(Float.MAX_VALUE));
+        assertEquals((float) mRatingBar.getNumStars(), mRatingBar.getRating());
     }
 
     public void testSetMax() {
-        RatingBar ratingBar = new RatingBar(mContext);
-
         // normal value
-        ratingBar.setMax(10);
-        assertEquals(10, ratingBar.getMax());
+        mInstrumentation.runOnMainSync(() -> mRatingBar.setMax(10));
+        assertEquals(10, mRatingBar.getMax());
 
-        ratingBar.setProgress(10);
+        mInstrumentation.runOnMainSync(() -> mRatingBar.setProgress(10));
 
         // exceptional values
-        ratingBar.setMax(-10);
-        assertEquals(10, ratingBar.getMax());
-        assertEquals(10, ratingBar.getProgress());
+        mInstrumentation.runOnMainSync(() -> mRatingBar.setMax(-10));
+        assertEquals(10, mRatingBar.getMax());
+        assertEquals(10, mRatingBar.getProgress());
 
-        ratingBar.setMax(Integer.MAX_VALUE);
-        assertEquals(Integer.MAX_VALUE, ratingBar.getMax());
+        mInstrumentation.runOnMainSync(() -> mRatingBar.setMax(Integer.MAX_VALUE));
+        assertEquals(Integer.MAX_VALUE, mRatingBar.getMax());
     }
 
     public void testAccessStepSize() {
-        RatingBar ratingBar = new RatingBar(mContext);
-
         // normal value
-        ratingBar.setStepSize(1.5f);
-        float expectedMax = ratingBar.getNumStars() / ratingBar.getStepSize();
-        float expectedProgress = expectedMax / ratingBar.getMax() * ratingBar.getProgress();
-        assertEquals((int) expectedMax, ratingBar.getMax());
-        assertEquals((int) expectedProgress, ratingBar.getProgress());
-        assertEquals((float) ratingBar.getNumStars() / (int) (ratingBar.getNumStars() / 1.5f),
-                ratingBar.getStepSize());
+        mInstrumentation.runOnMainSync(() -> mRatingBar.setStepSize(1.5f));
+        final float expectedMax = mRatingBar.getNumStars() / mRatingBar.getStepSize();
+        final float expectedProgress = expectedMax / mRatingBar.getMax() * mRatingBar.getProgress();
+        assertEquals((int) expectedMax, mRatingBar.getMax());
+        assertEquals((int) expectedProgress, mRatingBar.getProgress());
+        assertEquals((float) mRatingBar.getNumStars() / (int) (mRatingBar.getNumStars() / 1.5f),
+                mRatingBar.getStepSize());
 
-        int currentMax = ratingBar.getMax();
-        int currentProgress = ratingBar.getProgress();
-        float currentStepSize = ratingBar.getStepSize();
+        final int currentMax = mRatingBar.getMax();
+        final int currentProgress = mRatingBar.getProgress();
+        final float currentStepSize = mRatingBar.getStepSize();
         // exceptional value
-        ratingBar.setStepSize(-1.5f);
-        assertEquals(currentMax, ratingBar.getMax());
-        assertEquals(currentProgress, ratingBar.getProgress());
-        assertEquals(currentStepSize, ratingBar.getStepSize());
+        mInstrumentation.runOnMainSync(() -> mRatingBar.setStepSize(-1.5f));
+        assertEquals(currentMax, mRatingBar.getMax());
+        assertEquals(currentProgress, mRatingBar.getProgress());
+        assertEquals(currentStepSize, mRatingBar.getStepSize());
 
-        ratingBar.setStepSize(0f);
-        assertEquals(currentMax, ratingBar.getMax());
-        assertEquals(currentProgress, ratingBar.getProgress());
-        assertEquals(currentStepSize, ratingBar.getStepSize());
+        mInstrumentation.runOnMainSync(() -> mRatingBar.setStepSize(0f));
+        assertEquals(currentMax, mRatingBar.getMax());
+        assertEquals(currentProgress, mRatingBar.getProgress());
+        assertEquals(currentStepSize, mRatingBar.getStepSize());
 
-        ratingBar.setStepSize(ratingBar.getNumStars() + 0.1f);
-        assertEquals(currentMax, ratingBar.getMax());
-        assertEquals(currentProgress, ratingBar.getProgress());
-        assertEquals(currentStepSize, ratingBar.getStepSize());
+        mInstrumentation.runOnMainSync(
+                () -> mRatingBar.setStepSize(mRatingBar.getNumStars() + 0.1f));
+        assertEquals(currentMax, mRatingBar.getMax());
+        assertEquals(currentProgress, mRatingBar.getProgress());
+        assertEquals(currentStepSize, mRatingBar.getStepSize());
 
-        ratingBar.setStepSize(Float.MAX_VALUE);
-        assertEquals(currentMax, ratingBar.getMax());
-        assertEquals(currentProgress, ratingBar.getProgress());
-        assertEquals(currentStepSize, ratingBar.getStepSize());
-    }
-
-    /**
-     * The listener interface for receiving OnRatingBarChangeListener events.
-     * The class that is interested in processing a OnRatingBarChangeListener
-     * event implements this interface, and the object created with that class
-     * is registered with a component using the component's
-     * <code>setOnRatingBarChangeListener<code> method. When
-     * the OnRatingBarChangeListener event occurs, that object's appropriate
-     * method is invoked.
-     */
-    private class MockOnRatingBarChangeListener implements OnRatingBarChangeListener {
-        private boolean mCalledOnRatingChanged = false;
-
-        boolean hasCalledOnRatingChanged() {
-            return mCalledOnRatingChanged;
-        }
-
-        /*
-         * (non-Javadoc)
-         * @see android.widget.RadioGroup.OnRatingBarChangeListener#onRatingChanged
-         * (RatingBar ratingBar, float rating, boolean fromTouch)
-         */
-        public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromTouch) {
-            mCalledOnRatingChanged = true;
-        }
-
-        public void reset() {
-            mCalledOnRatingChanged = false;
-        }
-    }
-
-    /*
-     * Mock class for ProgressBar to test protected methods
-     */
-    private class MockRatingBar extends RatingBar {
-        public MockRatingBar(Context context) {
-            super(context);
-        }
-
-        private boolean mCalledOnMeasure = false;
-        private boolean mCalledRequestLayout = false;
-
-        public boolean hasCalledOnMeasure() {
-            return mCalledOnMeasure;
-        }
-
-        @Override
-        protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-            mCalledOnMeasure = true;
-            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-        }
-
-        public void requestLayout() {
-            mCalledRequestLayout = true;
-            super.requestLayout();
-        }
-
-        public boolean hasCalledRequestLayout() {
-            return mCalledRequestLayout;
-        }
-
-        public void reset() {
-            mCalledOnMeasure = false;
-            mCalledRequestLayout = false;
-        }
+        mInstrumentation.runOnMainSync(() -> mRatingBar.setStepSize(Float.MAX_VALUE));
+        assertEquals(currentMax, mRatingBar.getMax());
+        assertEquals(currentProgress, mRatingBar.getProgress());
+        assertEquals(currentStepSize, mRatingBar.getStepSize());
     }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/RelativeLayoutTest.java b/tests/tests/widget/src/android/widget/cts/RelativeLayoutTest.java
index 2f3be6f..dfff694 100644
--- a/tests/tests/widget/src/android/widget/cts/RelativeLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RelativeLayoutTest.java
@@ -16,6 +16,7 @@
 
 package android.widget.cts;
 
+import android.app.Instrumentation;
 import android.widget.cts.R;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -43,6 +44,7 @@
  */
 public class RelativeLayoutTest extends
         ActivityInstrumentationTestCase2<RelativeLayoutCtsActivity> {
+    private Instrumentation mInstrumentation;
     private Activity mActivity;
 
     public RelativeLayoutTest() {
@@ -52,6 +54,8 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+
+        mInstrumentation = getInstrumentation();
         mActivity = getActivity();
     }
 
@@ -86,27 +90,19 @@
         ViewAsserts.assertRightAligned(relativeLayout, view13);
 
         relativeLayout.setIgnoreGravity(R.id.relative_view13);
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                relativeLayout.requestLayout();
-            }
-        });
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> relativeLayout.requestLayout());
+        mInstrumentation.waitForIdleSync();
         ViewAsserts.assertRightAligned(relativeLayout, view12);
         ViewAsserts.assertLeftAligned(relativeLayout, view13);
 
         relativeLayout.setIgnoreGravity(0);
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                relativeLayout.requestLayout();
-            }
-        });
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> relativeLayout.requestLayout());
+        mInstrumentation.waitForIdleSync();
         ViewAsserts.assertRightAligned(relativeLayout, view12);
         ViewAsserts.assertRightAligned(relativeLayout, view13);
     }
 
-    public void testSetGravity() {
+    public void testAccessGravity() {
         final RelativeLayout relativeLayout = (RelativeLayout) mActivity.findViewById(
                 R.id.relative_sublayout_gravity);
 
@@ -120,48 +116,38 @@
         assertEquals(view11.getTop(), view10.getBottom());
 
         // -- BOTTOM && RIGHT
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                relativeLayout.setGravity(Gravity.BOTTOM | Gravity.RIGHT);
-            }
-        });
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.runOnMainSync(
+                () -> relativeLayout.setGravity(Gravity.BOTTOM | Gravity.RIGHT));
+        mInstrumentation.waitForIdleSync();
+        assertEquals(Gravity.BOTTOM | Gravity.RIGHT, relativeLayout.getGravity());
         ViewAsserts.assertRightAligned(relativeLayout, view10);
         assertEquals(view11.getTop(), view10.getBottom());
         ViewAsserts.assertRightAligned(relativeLayout, view11);
         ViewAsserts.assertBottomAligned(relativeLayout, view11);
 
         // -- BOTTOM
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                relativeLayout.setGravity(Gravity.BOTTOM);
-            }
-        });
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> relativeLayout.setGravity(Gravity.BOTTOM));
+        mInstrumentation.waitForIdleSync();
+        assertEquals(Gravity.BOTTOM | Gravity.START, relativeLayout.getGravity());
         ViewAsserts.assertLeftAligned(relativeLayout, view10);
         assertEquals(view11.getTop(), view10.getBottom());
         ViewAsserts.assertLeftAligned(relativeLayout, view11);
         ViewAsserts.assertBottomAligned(relativeLayout, view11);
 
         // CENTER_HORIZONTAL
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                relativeLayout.setGravity(Gravity.CENTER_HORIZONTAL);
-            }
-        });
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> relativeLayout.setGravity(Gravity.CENTER_HORIZONTAL));
+        mInstrumentation.waitForIdleSync();
+        assertEquals(Gravity.CENTER_HORIZONTAL | Gravity.TOP,
+                relativeLayout.getGravity());
         ViewAsserts.assertHorizontalCenterAligned(relativeLayout, view10);
         ViewAsserts.assertTopAligned(relativeLayout, view10);
         ViewAsserts.assertHorizontalCenterAligned(relativeLayout, view11);
         assertEquals(view11.getTop(), view10.getBottom());
 
         // CENTER_VERTICAL
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                relativeLayout.setGravity(Gravity.CENTER_VERTICAL);
-            }
-        });
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> relativeLayout.setGravity(Gravity.CENTER_VERTICAL));
+        mInstrumentation.waitForIdleSync();
+        assertEquals(Gravity.CENTER_VERTICAL | Gravity.START, relativeLayout.getGravity());
         ViewAsserts.assertLeftAligned(relativeLayout, view10);
         int topSpace = view10.getTop();
         int bottomSpace = relativeLayout.getHeight() - view11.getBottom();
@@ -184,24 +170,20 @@
         assertEquals(view11.getTop(), view10.getBottom());
 
         // RIGHT
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                relativeLayout.setHorizontalGravity(Gravity.RIGHT);
-            }
-        });
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> relativeLayout.setHorizontalGravity(Gravity.RIGHT));
+        mInstrumentation.waitForIdleSync();
+        assertEquals(Gravity.RIGHT, Gravity.HORIZONTAL_GRAVITY_MASK & relativeLayout.getGravity());
         ViewAsserts.assertRightAligned(relativeLayout, view10);
         ViewAsserts.assertTopAligned(relativeLayout, view10);
         ViewAsserts.assertRightAligned(relativeLayout, view11);
         assertEquals(view11.getTop(), view10.getBottom());
 
         // CENTER_HORIZONTAL
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                relativeLayout.setHorizontalGravity(Gravity.CENTER_HORIZONTAL);
-            }
-        });
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.runOnMainSync(
+                () -> relativeLayout.setHorizontalGravity(Gravity.CENTER_HORIZONTAL));
+        mInstrumentation.waitForIdleSync();
+        assertEquals(Gravity.CENTER_HORIZONTAL,
+                Gravity.HORIZONTAL_GRAVITY_MASK & relativeLayout.getGravity());
         ViewAsserts.assertHorizontalCenterAligned(relativeLayout, view10);
         ViewAsserts.assertTopAligned(relativeLayout, view10);
         ViewAsserts.assertHorizontalCenterAligned(relativeLayout, view11);
@@ -222,24 +204,20 @@
         assertEquals(view11.getTop(), view10.getBottom());
 
         // BOTTOM
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                relativeLayout.setVerticalGravity(Gravity.BOTTOM);
-            }
-        });
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> relativeLayout.setVerticalGravity(Gravity.BOTTOM));
+        mInstrumentation.waitForIdleSync();
+        assertEquals(Gravity.BOTTOM, Gravity.VERTICAL_GRAVITY_MASK & relativeLayout.getGravity());
         ViewAsserts.assertLeftAligned(relativeLayout, view10);
         assertEquals(view11.getTop(), view10.getBottom());
         ViewAsserts.assertLeftAligned(relativeLayout, view11);
         ViewAsserts.assertBottomAligned(relativeLayout, view11);
 
         // CENTER_VERTICAL
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                relativeLayout.setVerticalGravity(Gravity.CENTER_VERTICAL);
-            }
-        });
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.runOnMainSync(
+                () -> relativeLayout.setVerticalGravity(Gravity.CENTER_VERTICAL));
+        mInstrumentation.waitForIdleSync();
+        assertEquals(Gravity.CENTER_VERTICAL,
+                Gravity.VERTICAL_GRAVITY_MASK & relativeLayout.getGravity());
         ViewAsserts.assertLeftAligned(relativeLayout, view10);
         int topSpace = view10.getTop();
         int bottomSpace = relativeLayout.getHeight() - view11.getBottom();
@@ -352,12 +330,9 @@
      * Tests to prevent regressions in baseline alignment.
      */
     public void testBaselineAlignment() {
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                mActivity.setContentView(R.layout.relative_layout_baseline);
-            }
-        });
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.runOnMainSync(
+                () -> mActivity.setContentView(R.layout.relative_layout_baseline));
+        mInstrumentation.waitForIdleSync();
 
         View button = mActivity.findViewById(R.id.button1);
         assertTrue(button.getHeight() > 0);
diff --git a/tests/tests/widget/src/android/widget/cts/RelativeLayout_LayoutParamsTest.java b/tests/tests/widget/src/android/widget/cts/RelativeLayout_LayoutParamsTest.java
index 5706781..30f07da 100644
--- a/tests/tests/widget/src/android/widget/cts/RelativeLayout_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RelativeLayout_LayoutParamsTest.java
@@ -16,26 +16,40 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
+import android.app.Activity;
+import android.content.res.XmlResourceParser;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.ViewAsserts;
 import android.util.LayoutDirection;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.ViewGroup.MarginLayoutParams;
 import android.widget.RelativeLayout;
+import android.widget.cts.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
 
 /**
  * Test {@link RelativeLayout.LayoutParams}.
  */
 public class RelativeLayout_LayoutParamsTest extends
         ActivityInstrumentationTestCase2<RelativeLayoutCtsActivity> {
+    private Activity mActivity;
 
     public RelativeLayout_LayoutParamsTest() {
         super("android.widget.cts", RelativeLayoutCtsActivity.class);
     }
 
-    public void testConstructor() {
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+    }
+
+    public void testConstructor() throws XmlPullParserException, IOException {
 
         RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(200, 300);
         assertEquals(200, layoutParams.width);
@@ -46,22 +60,32 @@
         assertEquals(200, layoutParams.width);
         assertEquals(300, layoutParams.height);
 
+        ViewGroup.LayoutParams tempViewGroupLayoutParams = new ViewGroup.LayoutParams(300, 400);
+        layoutParams = new RelativeLayout.LayoutParams(tempViewGroupLayoutParams);
+        assertEquals(300, layoutParams.width);
+        assertEquals(400, layoutParams.height);
+
         MarginLayoutParams tempMarginLayoutParams = new MarginLayoutParams(400, 500);
         layoutParams = new RelativeLayout.LayoutParams(tempMarginLayoutParams);
         assertEquals(400, layoutParams.width);
         assertEquals(500, layoutParams.height);
 
+        XmlResourceParser p = mActivity.getResources().getLayout(R.layout.relative_layout);
+        XmlUtils.beginDocument(p, "RelativeLayout");
+        layoutParams = new RelativeLayout.LayoutParams(mActivity, p);
+        assertEquals(ViewGroup.LayoutParams.MATCH_PARENT, layoutParams.width);
+        assertEquals(ViewGroup.LayoutParams.MATCH_PARENT, layoutParams.height);
+
         // Test RelativeLayout.Params which generated from the xml file.
         int rules[];
-        RelativeLayoutCtsActivity activity = getActivity();
 
         // test attributes used in RelativeLayout.
-        RelativeLayout relativeLayout = (RelativeLayout) activity.findViewById(
+        RelativeLayout relativeLayout = (RelativeLayout) mActivity.findViewById(
                 R.id.relative_sublayout_attrs);
 
         // view1, centered within its parent.
         // TEST: android:layout_centerInParent
-        View view1 = activity.findViewById(R.id.relative_view1);
+        View view1 = mActivity.findViewById(R.id.relative_view1);
         ViewAsserts.assertHorizontalCenterAligned(relativeLayout, view1);
         ViewAsserts.assertVerticalCenterAligned(relativeLayout, view1);
         layoutParams = (RelativeLayout.LayoutParams) (view1.getLayoutParams());
@@ -70,7 +94,7 @@
 
         // view2, below view1 and has same left position with view1.
         // TEST: android:layout_below; android:layout_alignLeft
-        View view2 = activity.findViewById(R.id.relative_view2);
+        View view2 = mActivity.findViewById(R.id.relative_view2);
         ViewAsserts.assertLeftAligned(view1, view2);
         assertEquals(view1.getBottom(), view2.getTop());
         layoutParams = (RelativeLayout.LayoutParams) (view2.getLayoutParams());
@@ -81,7 +105,7 @@
         // view3, has same top position with view1 and same bottom position with view2,
         // and on the right of view1.1.
         // TEST: android:layout_alignTop; android:layout_alignBottom; android:layout_toRightOf
-        View view3 = activity.findViewById(R.id.relative_view3);
+        View view3 = mActivity.findViewById(R.id.relative_view3);
         ViewAsserts.assertTopAligned(view1, view3);
         ViewAsserts.assertBottomAligned(view2, view3);
         assertEquals(view1.getRight(), view3.getLeft());
@@ -93,7 +117,7 @@
 
         // view4, has same right position with view3 and above view3.
         // TEST: android:layout_alignRight; android:layout_above
-        View view4 = activity.findViewById(R.id.relative_view4);
+        View view4 = mActivity.findViewById(R.id.relative_view4);
         ViewAsserts.assertRightAligned(view3, view4);
         assertEquals(view3.getTop(), view4.getBottom());
         layoutParams = (RelativeLayout.LayoutParams) (view4.getLayoutParams());
@@ -103,7 +127,7 @@
 
         // view5 goes on the left-bottom.
         // TEST: android:layout_alignParentBottom; android:layout_alignParentLeft
-        View view5 = activity.findViewById(R.id.relative_view5);
+        View view5 = mActivity.findViewById(R.id.relative_view5);
         ViewAsserts.assertLeftAligned(relativeLayout, view5);
         ViewAsserts.assertBottomAligned(relativeLayout, view5);
         layoutParams = (RelativeLayout.LayoutParams) (view5.getLayoutParams());
@@ -113,7 +137,7 @@
 
         // view6 goes on the top-right.
         // TEST: android:layout_alignParentTop; android:layout_alignParentRight
-        View view6 = activity.findViewById(R.id.relative_view6);
+        View view6 = mActivity.findViewById(R.id.relative_view6);
         ViewAsserts.assertTopAligned(relativeLayout, view6);
         ViewAsserts.assertRightAligned(relativeLayout, view6);
         layoutParams = (RelativeLayout.LayoutParams) (view6.getLayoutParams());
@@ -123,7 +147,7 @@
 
         // view7, has same baseline with view6 and centered horizontally within its parent.
         // TEST: android:layout_alignBaseline; android:layout_centerHorizontal
-        View view7 = activity.findViewById(R.id.relative_view7);
+        View view7 = mActivity.findViewById(R.id.relative_view7);
         ViewAsserts.assertBaselineAligned(view6, view7);
         ViewAsserts.assertHorizontalCenterAligned(relativeLayout, view7);
         layoutParams = (RelativeLayout.LayoutParams) (view7.getLayoutParams());
@@ -133,7 +157,7 @@
 
         // view8, centered vertically within its parent and on the left of view1.
         // TEST: android:layout_toLeftOf; android:layout_centerVertical
-        View view8 = activity.findViewById(R.id.relative_view8);
+        View view8 = mActivity.findViewById(R.id.relative_view8);
         ViewAsserts.assertVerticalCenterAligned(relativeLayout, view8);
         assertEquals(view1.getLeft(), view8.getRight());
         layoutParams = (RelativeLayout.LayoutParams) (view8.getLayoutParams());
@@ -144,7 +168,7 @@
         // view9, has same top and bottom position with view3 and same left position with its parent
         // TEST: android:layout_alignLeft; android:layout_alignTop; android:layout_alignBottom;
         // android:layout_alignWithParentIfMissing
-        View view9 = activity.findViewById(R.id.relative_view9);
+        View view9 = mActivity.findViewById(R.id.relative_view9);
         ViewAsserts.assertTopAligned(view3, view9);
         ViewAsserts.assertBottomAligned(view3, view9);
         ViewAsserts.assertLeftAligned(relativeLayout, view9);
@@ -160,15 +184,14 @@
 
         // Test RelativeLayout.Params which generated from the xml file.
         int rules[];
-        RelativeLayoutCtsActivity activity = getActivity();
 
         // test attributes used in RelativeLayout.
-        RelativeLayout relativeLayout = (RelativeLayout) activity.findViewById(
+        RelativeLayout relativeLayout = (RelativeLayout) mActivity.findViewById(
                 R.id.relative_sublayout_attrs_2);
 
         // view1, centered within its parent.
         // TEST: android:layout_centerInParent
-        View view1 = activity.findViewById(R.id.relative_view21);
+        View view1 = mActivity.findViewById(R.id.relative_view21);
         ViewAsserts.assertHorizontalCenterAligned(relativeLayout, view1);
         ViewAsserts.assertVerticalCenterAligned(relativeLayout, view1);
         layoutParams = (RelativeLayout.LayoutParams) (view1.getLayoutParams());
@@ -177,7 +200,7 @@
 
         // view2, below view1 and has same left position with view1.
         // TEST: android:layout_below; android:layout_alignStart
-        View view2 = activity.findViewById(R.id.relative_view22);
+        View view2 = mActivity.findViewById(R.id.relative_view22);
         ViewAsserts.assertLeftAligned(view1, view2);
         assertEquals(view1.getBottom(), view2.getTop());
         layoutParams = (RelativeLayout.LayoutParams) (view2.getLayoutParams());
@@ -197,7 +220,7 @@
         // view3, has same top position with view1 and same bottom position with view2,
         // and on the right of view1.1.
         // TEST: android:layout_alignTop; android:layout_alignBottom; android:layout_toEndOf
-        View view3 = activity.findViewById(R.id.relative_view23);
+        View view3 = mActivity.findViewById(R.id.relative_view23);
         ViewAsserts.assertTopAligned(view1, view3);
         ViewAsserts.assertBottomAligned(view2, view3);
         assertEquals(view1.getRight(), view3.getLeft());
@@ -219,7 +242,7 @@
 
         // view4, has same right position with view3 and above view3.
         // TEST: android:layout_alignEnd; android:layout_above
-        View view4 = activity.findViewById(R.id.relative_view24);
+        View view4 = mActivity.findViewById(R.id.relative_view24);
         ViewAsserts.assertRightAligned(view3, view4);
         assertEquals(view3.getTop(), view4.getBottom());
         layoutParams = (RelativeLayout.LayoutParams) (view4.getLayoutParams());
@@ -238,7 +261,7 @@
 
         // view5 goes on the left-bottom.
         // TEST: android:layout_alignParentBottom; android:layout_alignParentStart
-        View view5 = activity.findViewById(R.id.relative_view25);
+        View view5 = mActivity.findViewById(R.id.relative_view25);
         ViewAsserts.assertLeftAligned(relativeLayout, view5);
         ViewAsserts.assertBottomAligned(relativeLayout, view5);
         layoutParams = (RelativeLayout.LayoutParams) (view5.getLayoutParams());
@@ -257,7 +280,7 @@
 
         // view6 goes on the top-right.
         // TEST: android:layout_alignParentTop; android:layout_alignParentEnd
-        View view6 = activity.findViewById(R.id.relative_view26);
+        View view6 = mActivity.findViewById(R.id.relative_view26);
         ViewAsserts.assertTopAligned(relativeLayout, view6);
         ViewAsserts.assertRightAligned(relativeLayout, view6);
         layoutParams = (RelativeLayout.LayoutParams) (view6.getLayoutParams());
@@ -276,7 +299,7 @@
 
         // view7, has same baseline with view6 and centered horizontally within its parent.
         // TEST: android:layout_alignBaseline; android:layout_centerHorizontal
-        View view7 = activity.findViewById(R.id.relative_view27);
+        View view7 = mActivity.findViewById(R.id.relative_view27);
         ViewAsserts.assertBaselineAligned(view6, view7);
         ViewAsserts.assertHorizontalCenterAligned(relativeLayout, view7);
         layoutParams = (RelativeLayout.LayoutParams) (view7.getLayoutParams());
@@ -291,7 +314,7 @@
 
         // view8, centered vertically within its parent and on the left of view1.
         // TEST: android:layout_toStartOf; android:layout_centerVertical
-        View view8 = activity.findViewById(R.id.relative_view28);
+        View view8 = mActivity.findViewById(R.id.relative_view28);
         ViewAsserts.assertVerticalCenterAligned(relativeLayout, view8);
         assertEquals(view1.getLeft(), view8.getRight());
         layoutParams = (RelativeLayout.LayoutParams) (view8.getLayoutParams());
@@ -311,7 +334,7 @@
         // view9, has same top and bottom position with view3 and same left position with its parent
         // TEST: android:layout_alignStart; android:layout_alignTop; android:layout_alignBottom;
         // android:layout_alignWithParentIfMissing
-        View view9 = activity.findViewById(R.id.relative_view29);
+        View view9 = mActivity.findViewById(R.id.relative_view29);
         ViewAsserts.assertTopAligned(view3, view9);
         ViewAsserts.assertBottomAligned(view3, view9);
         ViewAsserts.assertLeftAligned(relativeLayout, view9);
diff --git a/tests/tests/widget/src/android/widget/cts/RemoteViewsTest.java b/tests/tests/widget/src/android/widget/cts/RemoteViewsTest.java
index 605dbb6..f3a04be 100644
--- a/tests/tests/widget/src/android/widget/cts/RemoteViewsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RemoteViewsTest.java
@@ -17,8 +17,8 @@
 package android.widget.cts;
 
 import android.graphics.drawable.Icon;
+import android.os.Bundle;
 import android.test.UiThreadTest;
-import android.widget.cts.R;
 
 
 import android.app.Activity;
@@ -34,20 +34,34 @@
 import android.net.Uri;
 import android.os.Parcel;
 import android.test.ActivityInstrumentationTestCase2;
+import android.text.TextUtils;
+import android.util.TypedValue;
 import android.view.View;
 import android.widget.AbsoluteLayout;
+import android.widget.AnalogClock;
+import android.widget.Button;
 import android.widget.Chronometer;
+import android.widget.DatePicker;
+import android.widget.DateTimeView;
 import android.widget.EditText;
 import android.widget.FrameLayout;
+import android.widget.GridLayout;
 import android.widget.GridView;
+import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.ListView;
+import android.widget.NumberPicker;
 import android.widget.ProgressBar;
+import android.widget.RatingBar;
 import android.widget.RelativeLayout;
 import android.widget.RemoteViews;
+import android.widget.SeekBar;
+import android.widget.StackView;
+import android.widget.TextClock;
 import android.widget.TextView;
 import android.widget.RemoteViews.ActionException;
+import android.widget.ViewFlipper;
 
 import java.io.File;
 import java.io.FileOutputStream;
@@ -61,16 +75,18 @@
 public class RemoteViewsTest extends ActivityInstrumentationTestCase2<RemoteViewsCtsActivity> {
     private static final String PACKAGE_NAME = "android.widget.cts";
 
-    private static final int INVALD_ID = -1;
+    private static final int INVALID_ID = -1;
 
     private static final long TEST_TIMEOUT = 5000;
 
+    private Instrumentation mInstrumentation;
+
+    private Activity mActivity;
+
     private RemoteViews mRemoteViews;
 
     private View mResult;
 
-    private Activity mActivity;
-
     public RemoteViewsTest() {
         super(PACKAGE_NAME, RemoteViewsCtsActivity.class);
     }
@@ -78,13 +94,12 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+
+        mInstrumentation = getInstrumentation();
         mActivity = getActivity();
-        getInstrumentation().runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                mRemoteViews = new RemoteViews(PACKAGE_NAME, R.layout.remoteviews_good);
-                mResult = mRemoteViews.apply(mActivity, null);
-            }
+        mInstrumentation.runOnMainSync(() -> {
+            mRemoteViews = new RemoteViews(PACKAGE_NAME, R.layout.remoteviews_good);
+            mResult = mRemoteViews.apply(mActivity, null);
         });
     }
 
@@ -107,13 +122,24 @@
         mRemoteViews = new RemoteViews(PACKAGE_NAME, R.layout.listview_layout);
         assertEquals(R.layout.listview_layout, mRemoteViews.getLayoutId());
 
-        mRemoteViews = new RemoteViews(PACKAGE_NAME, INVALD_ID);
-        assertEquals(INVALD_ID, mRemoteViews.getLayoutId());
+        mRemoteViews = new RemoteViews(PACKAGE_NAME, INVALID_ID);
+        assertEquals(INVALID_ID, mRemoteViews.getLayoutId());
 
         mRemoteViews = new RemoteViews(PACKAGE_NAME, 0);
         assertEquals(0, mRemoteViews.getLayoutId());
     }
 
+    public void testSetContentDescription() {
+        View view = mResult.findViewById(R.id.remoteView_frame);
+
+        assertNull(view.getContentDescription());
+
+        CharSequence contentDescription = mActivity.getString(R.string.remote_content_description);
+        mRemoteViews.setContentDescription(R.id.remoteView_frame, contentDescription);
+        mRemoteViews.reapply(mActivity, mResult);
+        assertTrue(TextUtils.equals(contentDescription, view.getContentDescription()));
+    }
+
     public void testSetViewVisibility() {
         View view = mResult.findViewById(R.id.remoteView_chronometer);
         assertEquals(View.VISIBLE, view.getVisibility());
@@ -153,6 +179,23 @@
         }
     }
 
+    public void testSetTextViewTextSize() {
+        TextView textView = (TextView) mResult.findViewById(R.id.remoteView_text);
+
+        mRemoteViews.setTextViewTextSize(R.id.remoteView_text, TypedValue.COMPLEX_UNIT_SP, 18);
+        mRemoteViews.reapply(mActivity, mResult);
+        assertEquals(mActivity.getResources().getDisplayMetrics().scaledDensity * 18,
+                textView.getTextSize());
+
+        mRemoteViews.setTextViewTextSize(R.id.remoteView_absolute, TypedValue.COMPLEX_UNIT_SP, 20);
+        try {
+            mRemoteViews.reapply(mActivity, mResult);
+            fail("Should throw Throwable");
+        } catch (Throwable t) {
+            // expected
+        }
+    }
+
     public void testSetIcon() {
         ImageView image = (ImageView) mResult.findViewById(R.id.remoteView_image);
         assertNull(image.getDrawable());
@@ -262,6 +305,26 @@
         }
     }
 
+    public void testSetChronometerCountDown() {
+        Chronometer chronometer = (Chronometer) mResult.findViewById(R.id.remoteView_chronometer);
+
+        mRemoteViews.setChronometerCountDown(R.id.remoteView_chronometer, true);
+        mRemoteViews.reapply(mActivity, mResult);
+        assertTrue(chronometer.isCountDown());
+
+        mRemoteViews.setChronometerCountDown(R.id.remoteView_chronometer, false);
+        mRemoteViews.reapply(mActivity, mResult);
+        assertFalse(chronometer.isCountDown());
+
+        mRemoteViews.setChronometerCountDown(R.id.remoteView_absolute, true);
+        try {
+            mRemoteViews.reapply(mActivity, mResult);
+            fail("Should throw ActionException");
+        } catch (ActionException e) {
+            // expected
+        }
+    }
+
     public void testSetProgressBar() {
         ProgressBar progress = (ProgressBar) mResult.findViewById(R.id.remoteView_progress);
         assertEquals(100, progress.getMax());
@@ -305,7 +368,6 @@
     }
 
     public void testReapply() {
-        TextView text = new TextView(mActivity);
         ImageView image = (ImageView) mResult.findViewById(R.id.remoteView_image);
         assertNull(image.getDrawable());
 
@@ -321,19 +383,31 @@
     public void testOnLoadClass() {
         mRemoteViews = new RemoteViews(Parcel.obtain());
 
-        assertTrue(mRemoteViews.onLoadClass(RelativeLayout.class));
-        assertTrue(mRemoteViews.onLoadClass(FrameLayout.class));
         assertTrue(mRemoteViews.onLoadClass(AbsoluteLayout.class));
-        assertTrue(mRemoteViews.onLoadClass(LinearLayout.class));
-        assertTrue(mRemoteViews.onLoadClass(TextView.class));
-        assertTrue(mRemoteViews.onLoadClass(ImageView.class));
-        assertTrue(mRemoteViews.onLoadClass(ProgressBar.class));
+        assertTrue(mRemoteViews.onLoadClass(AnalogClock.class));
+        assertTrue(mRemoteViews.onLoadClass(Button.class));
         assertTrue(mRemoteViews.onLoadClass(Chronometer.class));
-        assertTrue(mRemoteViews.onLoadClass(ListView.class));
+        assertTrue(mRemoteViews.onLoadClass(DateTimeView.class));
+        assertTrue(mRemoteViews.onLoadClass(FrameLayout.class));
+        assertTrue(mRemoteViews.onLoadClass(GridLayout.class));
         assertTrue(mRemoteViews.onLoadClass(GridView.class));
+        assertTrue(mRemoteViews.onLoadClass(ImageButton.class));
+        assertTrue(mRemoteViews.onLoadClass(ImageView.class));
+        assertTrue(mRemoteViews.onLoadClass(LinearLayout.class));
+        assertTrue(mRemoteViews.onLoadClass(ListView.class));
+        assertTrue(mRemoteViews.onLoadClass(ProgressBar.class));
+        assertTrue(mRemoteViews.onLoadClass(RelativeLayout.class));
+        assertTrue(mRemoteViews.onLoadClass(StackView.class));
+        assertTrue(mRemoteViews.onLoadClass(TextClock.class));
+        assertTrue(mRemoteViews.onLoadClass(TextView.class));
+        assertTrue(mRemoteViews.onLoadClass(ViewFlipper.class));
 
         // those classes without annotation @RemoteView
         assertFalse(mRemoteViews.onLoadClass(EditText.class));
+        assertFalse(mRemoteViews.onLoadClass(DatePicker.class));
+        assertFalse(mRemoteViews.onLoadClass(NumberPicker.class));
+        assertFalse(mRemoteViews.onLoadClass(RatingBar.class));
+        assertFalse(mRemoteViews.onLoadClass(SeekBar.class));
     }
 
     public void testDescribeContents() {
@@ -609,33 +683,106 @@
         }
     }
 
-    public void testNotFeasibleSetters() {
-        // there is no RemotableViewMethods to use them, how to test?
+    public void testSetByte() {
+        MyRemotableView customView = (MyRemotableView) mResult.findViewById(R.id.remoteView_custom);
+        assertEquals(0, customView.getByteField());
+
+        byte b = 100;
+        mRemoteViews.setByte(R.id.remoteView_custom, "setByteField", b);
+        mRemoteViews.reapply(mActivity, mResult);
+        assertEquals(b, customView.getByteField());
+
+        mRemoteViews.setByte(R.id.remoteView_absolute, "setByteField", b);
+        try {
+            mRemoteViews.reapply(mActivity, mResult);
+            fail("Should throw ActionException");
+        } catch (ActionException e) {
+            // expected
+        }
+    }
+
+    public void testSetChar() {
+        MyRemotableView customView = (MyRemotableView) mResult.findViewById(R.id.remoteView_custom);
+        assertEquals('\u0000', customView.getCharField());
+
+        mRemoteViews.setChar(R.id.remoteView_custom, "setCharField", 'q');
+        mRemoteViews.reapply(mActivity, mResult);
+        assertEquals('q', customView.getCharField());
+
+        mRemoteViews.setChar(R.id.remoteView_absolute, "setCharField", 'w');
+        try {
+            mRemoteViews.reapply(mActivity, mResult);
+            fail("Should throw ActionException");
+        } catch (ActionException e) {
+            // expected
+        }
+    }
+
+    public void testSetDouble() {
+        MyRemotableView customView = (MyRemotableView) mResult.findViewById(R.id.remoteView_custom);
+        assertEquals(0.0, customView.getDoubleField());
+
+        mRemoteViews.setDouble(R.id.remoteView_custom, "setDoubleField", 0.5);
+        mRemoteViews.reapply(mActivity, mResult);
+        assertEquals(0.5, customView.getDoubleField());
+
+        mRemoteViews.setDouble(R.id.remoteView_absolute, "setDoubleField", 1.0);
+        try {
+            mRemoteViews.reapply(mActivity, mResult);
+            fail("Should throw ActionException");
+        } catch (ActionException e) {
+            // expected
+        }
+    }
+
+    public void testSetShort() {
+        MyRemotableView customView = (MyRemotableView) mResult.findViewById(R.id.remoteView_custom);
+        assertEquals(0, customView.getShortField());
+
+        short s = 25;
+        mRemoteViews.setShort(R.id.remoteView_custom, "setShortField", s);
+        mRemoteViews.reapply(mActivity, mResult);
+        assertEquals(s, customView.getShortField());
+
+        mRemoteViews.setShort(R.id.remoteView_absolute, "setShortField", s);
+        try {
+            mRemoteViews.reapply(mActivity, mResult);
+            fail("Should throw ActionException");
+        } catch (ActionException e) {
+            // expected
+        }
+    }
+
+    public void testSetBundle() {
+        MyRemotableView customView = (MyRemotableView) mResult.findViewById(R.id.remoteView_custom);
+        assertNull(customView.getBundleField());
+
+        final Bundle bundle = new Bundle();
+        bundle.putString("STR", "brexit");
+        bundle.putInt("INT", 2016);
+        mRemoteViews.setBundle(R.id.remoteView_custom, "setBundleField", bundle);
+        mRemoteViews.reapply(mActivity, mResult);
+        Bundle fromRemote = customView.getBundleField();
+        assertEquals("brexit", fromRemote.getString("STR", ""));
+        assertEquals(2016, fromRemote.getInt("INT", 0));
+
+        mRemoteViews.setBundle(R.id.remoteView_absolute, "setBundleField", bundle);
+        try {
+            mRemoteViews.reapply(mActivity, mResult);
+            fail("Should throw ActionException");
+        } catch (ActionException e) {
+            // expected
+        }
     }
 
     private void createSampleImage(File imagefile, int resid) throws IOException {
-        InputStream source = null;
-        OutputStream target = null;
-
-        try {
-            source = mActivity.getResources().openRawResource(resid);
-            target = new FileOutputStream(imagefile);
+        try (InputStream source = mActivity.getResources().openRawResource(resid);
+             OutputStream target = new FileOutputStream(imagefile)) {
 
             byte[] buffer = new byte[1024];
             for (int len = source.read(buffer); len > 0; len = source.read(buffer)) {
                 target.write(buffer, 0, len);
             }
-        } finally {
-            try {
-                if (source != null) {
-                    source.close();
-                }
-                if (target != null) {
-                    target.close();
-                }
-            } catch (IOException ignored) {
-                // Ignore the IOException.
-            }
         }
     }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/ScrollViewTest.java b/tests/tests/widget/src/android/widget/cts/ScrollViewTest.java
index 26510f27..aec6cf2 100644
--- a/tests/tests/widget/src/android/widget/cts/ScrollViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ScrollViewTest.java
@@ -24,6 +24,7 @@
 import android.widget.cts.R;
 
 
+import android.widget.cts.util.TestUtils;
 import org.xmlpull.v1.XmlPullParser;
 
 import android.app.Activity;
@@ -75,11 +76,10 @@
         mScrollView = (MyScrollView) mActivity.findViewById(R.id.scroll_view);
 
         // calculate pixel positions from dpi constants.
-        final float density = getActivity().getResources().getDisplayMetrics().density;
-        mItemWidth = (int) (ITEM_WIDTH_DPI * density + 0.5f);
-        mItemHeight = (int) (ITEM_HEIGHT_DPI * density + 0.5f);
-        mPageWidth = (int) (PAGE_WIDTH_DPI * density + 0.5f);
-        mPageHeight = (int) (PAGE_HEIGHT_DPI * density + 0.5f);
+        mItemWidth = TestUtils.dpToPx(mActivity, ITEM_WIDTH_DPI);
+        mItemHeight = TestUtils.dpToPx(mActivity, ITEM_HEIGHT_DPI);
+        mPageWidth = TestUtils.dpToPx(mActivity, PAGE_WIDTH_DPI);
+        mPageHeight = TestUtils.dpToPx(mActivity, PAGE_HEIGHT_DPI);
 
         mScrollBottom = mItemHeight * ITEM_COUNT - mPageHeight;
         mScrollRight = mItemWidth - mPageWidth;
@@ -829,55 +829,34 @@
         }
 
         if (fromY != toY) {
-            new PollingCheck() {
-                @Override
-                protected boolean check() {
-                    return isInRange(mScrollView.getScrollY(), fromY, toY);
-                }
-            }.run();
+            PollingCheck.waitFor(() -> isInRange(mScrollView.getScrollY(), fromY, toY));
         }
 
         if (fromX != toX) {
-            new PollingCheck() {
-                @Override
-                protected boolean check() {
-                    return isInRange(mScrollView.getScrollX(), fromX, toX);
-                }
-            }.run();
+            PollingCheck.waitFor(() -> isInRange(mScrollView.getScrollX(), fromX, toX));
         }
 
-        new PollingCheck() {
-            @Override
-            protected boolean check() {
-                return toX == mScrollView.getScrollX() && toY == mScrollView.getScrollY();
-            }
-        }.run();
+        PollingCheck.waitFor(
+                () -> toX == mScrollView.getScrollX() && toY == mScrollView.getScrollY());
     }
 
     private void pollingCheckFling(final int startPosition, final boolean movingDown) {
-        new PollingCheck() {
-            @Override
-            protected boolean check() {
-                if (movingDown) {
-                    return mScrollView.getScrollY() > startPosition;
-                }
-                return mScrollView.getScrollY() < startPosition;
+        PollingCheck.waitFor(() -> {
+            if (movingDown) {
+                return mScrollView.getScrollY() > startPosition;
             }
-        };
+            return mScrollView.getScrollY() < startPosition;
+        });
 
-        new PollingCheck() {
-            private int mPreviousScrollY = mScrollView.getScrollY();
-
-            @Override
-            protected boolean check() {
-                if (mScrollView.getScrollY() == mPreviousScrollY) {
-                    return true;
-                } else {
-                    mPreviousScrollY = mScrollView.getScrollY();
-                    return false;
-                }
+        final int[] previousScrollY = new int[] { mScrollView.getScrollY() };
+        PollingCheck.waitFor(() -> {
+            if (mScrollView.getScrollY() == previousScrollY[0]) {
+                return true;
+            } else {
+                previousScrollY[0] = mScrollView.getScrollY();
+                return false;
             }
-        }.run();
+        });
     }
 
     public static class MyView extends View {
diff --git a/tests/tests/widget/src/android/widget/cts/SearchViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/SearchViewCtsActivity.java
new file mode 100644
index 0000000..5da8a32
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/SearchViewCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.SearchView;
+
+/**
+ * A minimal application for {@link SearchView} test.
+ */
+public class SearchViewCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.searchview_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/SearchViewTest.java b/tests/tests/widget/src/android/widget/cts/SearchViewTest.java
new file mode 100644
index 0000000..1701a8c
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/SearchViewTest.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.res.Resources;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.text.InputType;
+import android.text.TextUtils;
+import android.view.inputmethod.EditorInfo;
+import android.widget.SearchView;
+
+import static org.mockito.Mockito.*;
+
+/**
+ * Test {@link SearchView}.
+ */
+@MediumTest
+public class SearchViewTest extends ActivityInstrumentationTestCase2<SearchViewCtsActivity> {
+    private Instrumentation mInstrumentation;
+    private Activity mActivity;
+    private SearchView mSearchView;
+
+    public SearchViewTest() {
+        super("android.widget.cts", SearchViewCtsActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mInstrumentation = getInstrumentation();
+        mActivity = getActivity();
+        mSearchView = (SearchView) mActivity.findViewById(R.id.search_view);
+    }
+
+    @UiThreadTest
+    public void testConstructor() {
+        new SearchView(mActivity);
+
+        new SearchView(mActivity, null);
+
+        new SearchView(mActivity, null, android.R.attr.searchViewStyle);
+
+        new SearchView(mActivity, null, 0, android.R.style.Widget_Material_SearchView);
+
+        new SearchView(mActivity, null, 0, android.R.style.Widget_Material_Light_SearchView);
+    }
+
+    @UiThreadTest
+    public void testAttributesFromXml() {
+        SearchView searchViewWithAttributes =
+                (SearchView) mActivity.findViewById(R.id.search_view_with_defaults);
+        assertEquals(mActivity.getString(R.string.search_query_hint),
+                searchViewWithAttributes.getQueryHint());
+        assertFalse(searchViewWithAttributes.isIconfiedByDefault());
+        assertEquals(EditorInfo.TYPE_TEXT_FLAG_CAP_CHARACTERS | EditorInfo.TYPE_CLASS_TEXT,
+                searchViewWithAttributes.getInputType());
+        assertEquals(EditorInfo.IME_ACTION_DONE, searchViewWithAttributes.getImeOptions());
+        assertEquals(mActivity.getResources().getDimensionPixelSize(R.dimen.search_view_max_width),
+                searchViewWithAttributes.getMaxWidth());
+    }
+
+    public void testAccessIconified() {
+        mInstrumentation.runOnMainSync(() -> mSearchView.setIconified(true));
+        assertTrue(mSearchView.isIconified());
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setIconified(false));
+        assertFalse(mSearchView.isIconified());
+    }
+
+    public void testAccessIconifiedByDefault() {
+        mInstrumentation.runOnMainSync(() -> mSearchView.setIconifiedByDefault(true));
+        assertTrue(mSearchView.isIconfiedByDefault());
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setIconifiedByDefault(false));
+        assertFalse(mSearchView.isIconfiedByDefault());
+    }
+
+    public void testDenyIconifyingNonInconifiableView() {
+        mInstrumentation.runOnMainSync(() -> {
+            mSearchView.setIconifiedByDefault(false);
+            mSearchView.setIconified(false);
+        });
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setIconified(true));
+        mInstrumentation.waitForIdleSync();
+
+        // Since our search view is marked with iconifiedByDefault=false, call to setIconified
+        // with true us going to be ignored, as detailed in the class-level documentation of
+        // SearchView.
+        assertFalse(mSearchView.isIconified());
+    }
+
+    public void testDenyIconifyingInconifiableView() {
+        mInstrumentation.runOnMainSync(() -> {
+            mSearchView.setIconifiedByDefault(true);
+            mSearchView.setIconified(false);
+        });
+
+        final SearchView.OnCloseListener mockDenyCloseListener =
+                mock(SearchView.OnCloseListener.class);
+        when(mockDenyCloseListener.onClose()).thenReturn(Boolean.TRUE);
+        mSearchView.setOnCloseListener(mockDenyCloseListener);
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setIconified(true));
+        mInstrumentation.waitForIdleSync();
+
+        // Our mock listener is configured to return true from its onClose, thereby preventing
+        // the iconify request to be completed. Check that the listener was called and that the
+        // search view is not iconified.
+        verify(mockDenyCloseListener, times(1)).onClose();
+        assertFalse(mSearchView.isIconified());
+    }
+
+    public void testAllowIconifyingInconifiableView() {
+        mInstrumentation.runOnMainSync(() -> {
+            mSearchView.setIconifiedByDefault(true);
+            mSearchView.setIconified(false);
+        });
+
+        final SearchView.OnCloseListener mockAllowCloseListener =
+                mock(SearchView.OnCloseListener.class);
+        when(mockAllowCloseListener.onClose()).thenReturn(Boolean.FALSE);
+        mSearchView.setOnCloseListener(mockAllowCloseListener);
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setIconified(true));
+        mInstrumentation.waitForIdleSync();
+
+        // Our mock listener is configured to return false from its onClose, thereby allowing
+        // the iconify request to be completed. Check that the listener was called and that the
+        // search view is not iconified.
+        verify(mockAllowCloseListener, times(1)).onClose();
+        assertTrue(mSearchView.isIconified());
+    }
+
+    public void testAccessMaxWidth() {
+        final Resources res = mActivity.getResources();
+        final int maxWidth1 = res.getDimensionPixelSize(R.dimen.search_view_max_width);
+        final int maxWidth2 = res.getDimensionPixelSize(R.dimen.search_view_max_width2);
+
+        // Set search view to not be iconified before running max-width tests
+        mInstrumentation.runOnMainSync(() -> mSearchView.setIconified(false));
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setMaxWidth(maxWidth1));
+        mInstrumentation.waitForIdleSync();
+        assertEquals(maxWidth1, mSearchView.getMaxWidth());
+        assertTrue(mSearchView.getWidth() <= maxWidth1);
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setMaxWidth(maxWidth2));
+        mInstrumentation.waitForIdleSync();
+        assertEquals(maxWidth2, mSearchView.getMaxWidth());
+        assertTrue(mSearchView.getWidth() <= maxWidth2);
+    }
+
+    public void testAccessQuery() {
+        mInstrumentation.runOnMainSync(() -> mSearchView.setIconified(false));
+
+        final SearchView.OnQueryTextListener mockQueryTextListener =
+                mock(SearchView.OnQueryTextListener.class);
+        when(mockQueryTextListener.onQueryTextSubmit(anyString())).thenReturn(Boolean.TRUE);
+        mSearchView.setOnQueryTextListener(mockQueryTextListener);
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setQuery("alpha", false));
+        assertTrue(TextUtils.equals("alpha", mSearchView.getQuery()));
+        // Since we passed false as the second parameter to setQuery, our query text listener
+        // should have been invoked only with text change
+        verify(mockQueryTextListener, times(1)).onQueryTextChange("alpha");
+        verify(mockQueryTextListener, never()).onQueryTextSubmit(anyString());
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setQuery("beta", true));
+        assertTrue(TextUtils.equals("beta", mSearchView.getQuery()));
+        // Since we passed true as the second parameter to setQuery, our query text listener
+        // should have been invoked on both callbacks
+        verify(mockQueryTextListener, times(1)).onQueryTextChange("beta");
+        verify(mockQueryTextListener, times(1)).onQueryTextSubmit("beta");
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setQuery("gamma", true));
+        assertTrue(TextUtils.equals("gamma", mSearchView.getQuery()));
+        // Since we passed true as the second parameter to setQuery, our query text listener
+        // should have been invoked on both callbacks
+        verify(mockQueryTextListener, times(1)).onQueryTextChange("gamma");
+        verify(mockQueryTextListener, times(1)).onQueryTextSubmit("gamma");
+
+        verifyNoMoreInteractions(mockQueryTextListener);
+    }
+
+    public void testAccessQueryHint() {
+        mInstrumentation.runOnMainSync(() -> mSearchView.setQueryHint("hint 1"));
+        assertTrue(TextUtils.equals("hint 1", mSearchView.getQueryHint()));
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setQueryHint("hint 2"));
+        assertTrue(TextUtils.equals("hint 2", mSearchView.getQueryHint()));
+    }
+
+    public void testAccessInputType() {
+        mInstrumentation.runOnMainSync(() ->
+                mSearchView.setInputType(InputType.TYPE_CLASS_NUMBER
+                    | InputType.TYPE_NUMBER_FLAG_DECIMAL
+                    | InputType.TYPE_NUMBER_FLAG_SIGNED));
+        assertEquals(InputType.TYPE_CLASS_NUMBER
+                | InputType.TYPE_NUMBER_FLAG_DECIMAL
+                | InputType.TYPE_NUMBER_FLAG_SIGNED, mSearchView.getInputType());
+
+        mInstrumentation.runOnMainSync(() ->
+                mSearchView.setInputType(InputType.TYPE_CLASS_TEXT
+                        | InputType.TYPE_TEXT_FLAG_CAP_WORDS));
+        assertEquals(InputType.TYPE_CLASS_TEXT
+                | InputType.TYPE_TEXT_FLAG_CAP_WORDS, mSearchView.getInputType());
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setInputType(InputType.TYPE_CLASS_PHONE));
+        assertEquals(InputType.TYPE_CLASS_PHONE, mSearchView.getInputType());
+    }
+
+    public void testAccessImeOptions() {
+        mInstrumentation.runOnMainSync(() -> mSearchView.setImeOptions(EditorInfo.IME_ACTION_GO));
+        assertEquals(EditorInfo.IME_ACTION_GO, mSearchView.getImeOptions());
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setImeOptions(EditorInfo.IME_ACTION_DONE));
+        assertEquals(EditorInfo.IME_ACTION_DONE, mSearchView.getImeOptions());
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setImeOptions(EditorInfo.IME_NULL));
+        assertEquals(EditorInfo.IME_NULL, mSearchView.getImeOptions());
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/SearchView_CursorTest.java b/tests/tests/widget/src/android/widget/cts/SearchView_CursorTest.java
new file mode 100644
index 0000000..5b8dbfc
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/SearchView_CursorTest.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.cts.util.PollingCheck;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.provider.BaseColumns;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.text.TextUtils;
+import android.widget.CursorAdapter;
+import android.widget.SearchView;
+import android.widget.SimpleCursorAdapter;
+import android.widget.cts.util.ViewTestUtils;
+
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.*;
+
+/**
+ * Test {@link SearchView} with {@link Cursor}-backed suggestions adapter.
+ */
+@MediumTest
+public class SearchView_CursorTest extends ActivityInstrumentationTestCase2<SearchViewCtsActivity> {
+    private Instrumentation mInstrumentation;
+    private Activity mActivity;
+    private SearchView mSearchView;
+
+    private static final String TEXT_COLUMN_NAME = "text";
+    private String[] mTextContent;
+
+    private CursorAdapter mSuggestionsAdapter;
+
+    protected class MyQueryTextListener implements SearchView.OnQueryTextListener {
+        @Override
+        public boolean onQueryTextSubmit(String s) {
+            return false;
+        }
+
+        @Override
+        public boolean onQueryTextChange(String s) {
+            if (mSuggestionsAdapter == null) {
+                return false;
+            }
+
+            final MatrixCursor c = new MatrixCursor(
+                    new String[] { BaseColumns._ID, TEXT_COLUMN_NAME} );
+            for (int i = 0; i < mTextContent.length; i++) {
+                if (mTextContent[i].toLowerCase().startsWith(s.toLowerCase())) {
+                    c.addRow(new Object[]{i, mTextContent[i]});
+                }
+            }
+            mSuggestionsAdapter.swapCursor(c);
+            return false;
+        }
+    }
+
+    protected class MySuggestionListener implements SearchView.OnSuggestionListener {
+        @Override
+        public boolean onSuggestionSelect(int position) {
+            return false;
+        }
+
+        @Override
+        public boolean onSuggestionClick(int position) {
+            if (mSuggestionsAdapter != null) {
+                final Cursor cursor = mSuggestionsAdapter.getCursor();
+                if (cursor != null) {
+                    cursor.moveToPosition(position);
+                    mSearchView.setQuery(cursor.getString(1), false);
+                }
+            }
+            return false;
+        }
+    }
+
+    public SearchView_CursorTest() {
+        super("android.widget.cts", SearchViewCtsActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mInstrumentation = getInstrumentation();
+        mActivity = getActivity();
+        mSearchView = (SearchView) mActivity.findViewById(R.id.search_view);
+
+        // Local test data for the tests
+        mTextContent = new String[] { "Akon", "Bono", "Ciara", "Dido", "Diplo" };
+
+        mInstrumentation.runOnMainSync(() -> {
+            // Use an adapter with our custom layout for each entry. The adapter "maps"
+            // the content of the text column of our cursor to the @id/text1 view in the
+            // layout.
+            mSuggestionsAdapter = new SimpleCursorAdapter(
+                    mActivity,
+                    R.layout.searchview_suggestion_item,
+                    null,
+                    new String[] { TEXT_COLUMN_NAME },
+                    new int[] { android.R.id.text1 },
+                    CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
+            mSearchView.setSuggestionsAdapter(mSuggestionsAdapter);
+        });
+    }
+
+    public void testSuggestionFiltering() {
+        final SearchView.OnQueryTextListener mockQueryTextListener =
+                spy(new MyQueryTextListener());
+        when(mockQueryTextListener.onQueryTextChange(anyString())).thenCallRealMethod();
+
+        mInstrumentation.runOnMainSync(() -> {
+                    mSearchView.setIconifiedByDefault(false);
+                    mSearchView.setOnQueryTextListener(mockQueryTextListener);
+                    mSearchView.requestFocus();
+                });
+
+        assertTrue(mSearchView.hasFocus());
+        assertEquals(mSuggestionsAdapter, mSearchView.getSuggestionsAdapter());
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setQuery("Bon", false));
+        verify(mockQueryTextListener, times(1)).onQueryTextChange("Bon");
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setQuery("Di", false));
+        verify(mockQueryTextListener, times(1)).onQueryTextChange("Di");
+    }
+
+    public void testSuggestionSelection() {
+        final SearchView.OnSuggestionListener mockSuggestionListener =
+                spy(new MySuggestionListener());
+        when(mockSuggestionListener.onSuggestionClick(anyInt())).thenCallRealMethod();
+
+        final SearchView.OnQueryTextListener mockQueryTextListener =
+                spy(new MyQueryTextListener());
+        when(mockQueryTextListener.onQueryTextChange(anyString())).thenCallRealMethod();
+
+        mInstrumentation.runOnMainSync(() -> {
+                    mSearchView.setIconifiedByDefault(false);
+                    mSearchView.setOnQueryTextListener(mockQueryTextListener);
+                    mSearchView.setOnSuggestionListener(mockSuggestionListener);
+                    mSearchView.requestFocus();
+                });
+
+        assertTrue(mSearchView.hasFocus());
+        assertEquals(mSuggestionsAdapter, mSearchView.getSuggestionsAdapter());
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setQuery("Di", false));
+        mInstrumentation.waitForIdleSync();
+        verify(mockQueryTextListener, times(1)).onQueryTextChange("Di");
+
+        // Emulate click on the first suggestion - which should be Dido
+        final int suggestionRowHeight = mActivity.getResources().getDimensionPixelSize(
+                R.dimen.search_view_suggestion_row_height);
+        ViewTestUtils.emulateTapOnScreen(mInstrumentation, mSearchView, mSearchView.getWidth() / 2,
+                mSearchView.getHeight() + suggestionRowHeight / 2);
+
+        // At this point we expect the click on the first suggestion to have activated a sequence
+        // of events that ends up in our suggestion listener that sets the full suggestion text
+        // as the current query. Some parts of this sequence of events are asynchronous, and those
+        // are not "caught" by Instrumentation.waitForIdleSync - which is in general not a very
+        // reliable way to wait for everything to be completed. As such, we are using our own
+        // polling check mechanism to wait until the search view's query is the fully completed
+        // suggestion for Dido. This check will time out and fail after a few seconds if anything
+        // goes wrong during the processing of the emulated tap and the code never gets to our
+        // suggestion listener
+        PollingCheck.waitFor(() -> TextUtils.equals("Dido", mSearchView.getQuery()));
+
+        // Just to be sure, verify that our spy suggestion listener was called
+        verify(mockSuggestionListener, times(1)).onSuggestionClick(0);
+        verifyNoMoreInteractions(mockSuggestionListener);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/SeekBarCtsActivity.java b/tests/tests/widget/src/android/widget/cts/SeekBarCtsActivity.java
index e22b910..5dcbe56 100644
--- a/tests/tests/widget/src/android/widget/cts/SeekBarCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/SeekBarCtsActivity.java
@@ -16,8 +16,6 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
 import android.app.Activity;
 import android.os.Bundle;
 import android.view.View;
@@ -28,7 +26,7 @@
  */
 public class SeekBarCtsActivity extends Activity {
     /**
-     * Called with the activity is first created.
+     * Called when the activity is first created.
      */
     @Override
     public void onCreate(Bundle savedInstanceState) {
diff --git a/tests/tests/widget/src/android/widget/cts/SeekBarTest.java b/tests/tests/widget/src/android/widget/cts/SeekBarTest.java
index b9ad733..fa47940 100644
--- a/tests/tests/widget/src/android/widget/cts/SeekBarTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SeekBarTest.java
@@ -16,20 +16,20 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
-
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.view.MotionEvent;
 import android.widget.SeekBar;
-import android.widget.SeekBar.OnSeekBarChangeListener;
+
+import static org.mockito.Mockito.*;
 
 /**
  * Test {@link SeekBar}.
  */
+@SmallTest
 public class SeekBarTest extends ActivityInstrumentationTestCase2<SeekBarCtsActivity> {
     private SeekBar mSeekBar;
 
@@ -55,13 +55,21 @@
         new SeekBar(mActivity, null);
 
         new SeekBar(mActivity, null, android.R.attr.seekBarStyle);
+
+        new SeekBar(mActivity, null, 0, android.R.style.Widget_DeviceDefault_SeekBar);
+
+        new SeekBar(mActivity, null, 0, android.R.style.Widget_DeviceDefault_Light_SeekBar);
+
+        new SeekBar(mActivity, null, 0, android.R.style.Widget_Material_SeekBar);
+
+        new SeekBar(mActivity, null, 0, android.R.style.Widget_Material_Light_SeekBar);
     }
 
     public void testSetOnSeekBarChangeListener() {
-        MockOnSeekBarListener listener = new MockOnSeekBarListener();
+        SeekBar.OnSeekBarChangeListener mockChangeListener =
+                mock(SeekBar.OnSeekBarChangeListener.class);
 
-        mSeekBar.setOnSeekBarChangeListener(listener);
-        listener.reset();
+        mSeekBar.setOnSeekBarChangeListener(mockChangeListener);
         long downTime = SystemClock.uptimeMillis();
         long eventTime = SystemClock.uptimeMillis();
         int seekBarXY[] = new int[2];
@@ -70,66 +78,28 @@
                 seekBarXY[0], seekBarXY[1], 0);
         mInstrumentation.sendPointerSync(event);
         mInstrumentation.waitForIdleSync();
-        assertTrue(listener.hasCalledOnStartTrackingTouch());
+        verify(mockChangeListener, times(1)).onStartTrackingTouch(mSeekBar);
         // while starting to track, the progress is changed also
-        assertTrue(listener.hasCalledOnProgressChanged());
+        verify(mockChangeListener, atLeastOnce()).onProgressChanged(eq(mSeekBar), anyInt(),
+                eq(true));
 
-        listener.reset();
+        reset(mockChangeListener);
         downTime = SystemClock.uptimeMillis();
         eventTime = SystemClock.uptimeMillis();
         event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE,
                 seekBarXY[0] + (mSeekBar.getWidth() >> 1), seekBarXY[1], 0);
         mInstrumentation.sendPointerSync(event);
         mInstrumentation.waitForIdleSync();
-        assertTrue(listener.hasCalledOnProgressChanged());
+        verify(mockChangeListener, atLeastOnce()).onProgressChanged(eq(mSeekBar), anyInt(),
+                eq(true));
 
-        listener.reset();
+        reset(mockChangeListener);
         downTime = SystemClock.uptimeMillis();
         eventTime = SystemClock.uptimeMillis();
         event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP,
                 seekBarXY[0] + (mSeekBar.getWidth() >> 1), seekBarXY[1], 0);
         mInstrumentation.sendPointerSync(event);
         mInstrumentation.waitForIdleSync();
-        assertTrue(listener.hasCalledOnStopTrackingTouch());
-
-        mSeekBar.setOnSeekBarChangeListener(null);
-    }
-
-    private class MockOnSeekBarListener implements OnSeekBarChangeListener {
-        private boolean mHasCalledOnProgressChanged;
-
-        private boolean mHasCalledOnStartTrackingTouch;
-
-        private boolean mHasCalledOnStopTrackingTouch;
-
-        public boolean hasCalledOnProgressChanged() {
-            return mHasCalledOnProgressChanged;
-        }
-
-        public boolean hasCalledOnStartTrackingTouch() {
-            return mHasCalledOnStartTrackingTouch;
-        }
-
-        public boolean hasCalledOnStopTrackingTouch() {
-            return mHasCalledOnStopTrackingTouch;
-        }
-
-        public void reset(){
-            mHasCalledOnProgressChanged = false;
-            mHasCalledOnStartTrackingTouch = false;
-            mHasCalledOnStopTrackingTouch = false;
-        }
-
-        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
-            mHasCalledOnProgressChanged = true;
-        }
-
-        public void onStartTrackingTouch(SeekBar seekBar) {
-            mHasCalledOnStartTrackingTouch = true;
-        }
-
-        public void onStopTrackingTouch(SeekBar seekBar) {
-            mHasCalledOnStopTrackingTouch = true;
-        }
+        verify(mockChangeListener, times(1)).onStopTrackingTouch(mSeekBar);
     }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/SlidingDrawerTest.java b/tests/tests/widget/src/android/widget/cts/SlidingDrawerTest.java
index 2af1b06..efed9e8 100644
--- a/tests/tests/widget/src/android/widget/cts/SlidingDrawerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SlidingDrawerTest.java
@@ -16,29 +16,27 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 import android.app.Activity;
-import android.content.Context;
 import android.cts.util.PollingCheck;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
 import android.util.AttributeSet;
 import android.util.Xml;
-import android.view.MotionEvent;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.SlidingDrawer;
 import android.widget.TextView;
-import android.widget.SlidingDrawer.OnDrawerCloseListener;
-import android.widget.SlidingDrawer.OnDrawerOpenListener;
-import android.widget.SlidingDrawer.OnDrawerScrollListener;
+
+import org.mockito.InOrder;
+import org.mockito.invocation.InvocationOnMock;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static org.mockito.Mockito.*;
 
 /**
  * Test {@link SlidingDrawer}.
@@ -48,7 +46,6 @@
 
     private static final long TEST_TIMEOUT = 5000L;
     private Activity mActivity;
-    private Object mLock;
 
     public SlidingDrawerTest() {
         super("android.widget.cts", SlidingDrawerCtsActivity.class);
@@ -58,7 +55,6 @@
     protected void setUp() throws Exception {
         super.setUp();
         mActivity = getActivity();
-        mLock = new Object();
     }
 
     @UiThreadTest
@@ -118,40 +114,20 @@
         assertFalse(drawer.isOpened());
         assertEquals(View.GONE, content.getVisibility());
 
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                drawer.animateOpen();
-            }
-        });
+        runTestOnUiThread(() -> drawer.animateOpen());
         assertTrue(drawer.isMoving());
-        assertOpened(false, drawer);
         assertEquals(View.GONE, content.getVisibility());
 
-        new PollingCheck() {
-            @Override
-            protected boolean check() {
-                return !drawer.isMoving();
-            }
-        }.run();
-        assertOpened(true, drawer);
+        PollingCheck.waitFor(() -> !drawer.isMoving());
+        PollingCheck.waitFor(() -> drawer.isOpened());
         assertEquals(View.VISIBLE, content.getVisibility());
 
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                drawer.animateClose();
-            }
-        });
+        runTestOnUiThread(() -> drawer.animateClose());
         assertTrue(drawer.isMoving());
-        assertOpened(true, drawer);
         assertEquals(View.GONE, content.getVisibility());
 
-        new PollingCheck() {
-            @Override
-            protected boolean check() {
-                return !drawer.isMoving();
-            }
-        }.run();
-        assertOpened(false, drawer);
+        PollingCheck.waitFor(() -> !drawer.isMoving());
+        PollingCheck.waitFor(() -> !drawer.isOpened());
         assertEquals(View.GONE, content.getVisibility());
     }
 
@@ -162,52 +138,23 @@
         assertFalse(drawer.isOpened());
         assertEquals(View.GONE, content.getVisibility());
 
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                drawer.animateToggle();
-            }
-        });
+        runTestOnUiThread(() -> drawer.animateToggle());
         assertTrue(drawer.isMoving());
-        assertOpened(false, drawer);
         assertEquals(View.GONE, content.getVisibility());
 
-        new PollingCheck() {
-            @Override
-            protected boolean check() {
-                return !drawer.isMoving();
-            }
-        }.run();
-        assertOpened(true, drawer);
+        PollingCheck.waitFor(() -> !drawer.isMoving());
+        PollingCheck.waitFor(() -> drawer.isOpened());
         assertEquals(View.VISIBLE, content.getVisibility());
 
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                drawer.animateToggle();
-            }
-        });
+        runTestOnUiThread(() -> drawer.animateToggle());
         assertTrue(drawer.isMoving());
-        assertOpened(true, drawer);
         assertEquals(View.GONE, content.getVisibility());
 
-        new PollingCheck() {
-            @Override
-            protected boolean check() {
-                return !drawer.isMoving();
-            }
-        }.run();
-        assertOpened(false, drawer);
+        PollingCheck.waitFor(() -> !drawer.isMoving());
+        PollingCheck.waitFor(() -> !drawer.isOpened());
         assertEquals(View.GONE, content.getVisibility());
     }
 
-    private void assertOpened(final boolean opened, final SlidingDrawer drawer) {
-        new PollingCheck() {
-            @Override
-            protected boolean check() {
-                return drawer.isOpened() == opened;
-            }
-        }.run();
-    }
-
     @UiThreadTest
     public void testToggle() {
         SlidingDrawer drawer = (SlidingDrawer) mActivity.findViewById(R.id.drawer);
@@ -254,56 +201,61 @@
     @UiThreadTest
     public void testSetOnDrawerOpenListener() {
         SlidingDrawer drawer = (SlidingDrawer) mActivity.findViewById(R.id.drawer);
-        MockOnDrawerOpenListener listener = new MockOnDrawerOpenListener();
-        drawer.setOnDrawerOpenListener(listener);
+        SlidingDrawer.OnDrawerOpenListener mockOpenListener =
+                mock(SlidingDrawer.OnDrawerOpenListener.class);
+        drawer.setOnDrawerOpenListener(mockOpenListener);
 
-        assertFalse(listener.hadOpenedDrawer());
+        verifyZeroInteractions(mockOpenListener);
 
         drawer.open();
-        assertTrue(listener.hadOpenedDrawer());
+        verify(mockOpenListener, times(1)).onDrawerOpened();
     }
 
     @UiThreadTest
     public void testSetOnDrawerCloseListener() {
         SlidingDrawer drawer = (SlidingDrawer) mActivity.findViewById(R.id.drawer);
-        MockOnDrawerCloseListener listener = new MockOnDrawerCloseListener();
-        drawer.setOnDrawerCloseListener(listener);
+        SlidingDrawer.OnDrawerCloseListener mockCloseListener =
+                mock(SlidingDrawer.OnDrawerCloseListener.class);
+        drawer.setOnDrawerCloseListener(mockCloseListener);
 
-        assertFalse(listener.hadClosedDrawer());
+        verifyZeroInteractions(mockCloseListener);
 
         drawer.open();
-        assertFalse(listener.hadClosedDrawer());
+        verifyZeroInteractions(mockCloseListener);
 
         drawer.close();
-        assertTrue(listener.hadClosedDrawer());
+        verify(mockCloseListener, times(1)).onDrawerClosed();
     }
 
     public void testSetOnDrawerScrollListener() throws Throwable {
         final SlidingDrawer drawer = (SlidingDrawer) mActivity.findViewById(R.id.drawer);
-        MockOnDrawerScrollListener listener = new MockOnDrawerScrollListener();
-        drawer.setOnDrawerScrollListener(listener);
-        assertFalse(listener.hadStartedScroll());
-        assertFalse(listener.hadEndedScroll());
 
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                drawer.animateOpen();
-            }
-        });
-        if ( !listener.hadStartedScroll() ) {
-            synchronized (mLock) {
-                mLock.wait(TEST_TIMEOUT);
-            }
-        }
-        assertTrue(listener.hadStartedScroll());
+        final CountDownLatch countDownLatch = new CountDownLatch(2);
+        final SlidingDrawer.OnDrawerScrollListener mockScrollListener =
+                mock(SlidingDrawer.OnDrawerScrollListener.class);
+        doAnswer((InvocationOnMock invocation) -> {
+            countDownLatch.countDown();
+            return null;
+        }).when(mockScrollListener).onScrollStarted();
+        doAnswer((InvocationOnMock invocation) -> {
+            countDownLatch.countDown();
+            return null;
+        }).when(mockScrollListener).onScrollEnded();
+        drawer.setOnDrawerScrollListener(mockScrollListener);
 
-        if ( !listener.hadEndedScroll() ) {
-            synchronized (mLock) {
-                mLock.wait(TEST_TIMEOUT);
-            }
+        runTestOnUiThread(() -> drawer.animateOpen());
+
+        try {
+            countDownLatch.await(2 * TEST_TIMEOUT, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException ie) {
+            // Do nothing as we're about to verify that both callbacks have been called
+            // in any case
         }
-        assertTrue(listener.hadStartedScroll());
-        assertTrue(listener.hadEndedScroll());
+
+        InOrder inOrder = inOrder(mockScrollListener);
+        inOrder.verify(mockScrollListener).onScrollStarted();
+        inOrder.verify(mockScrollListener).onScrollEnded();
+        verifyNoMoreInteractions(mockScrollListener);
     }
 
     public void testOnLayout() {
@@ -329,56 +281,4 @@
     public void testOnTouchEvent() {
         // onTouchEvent() is implementation details, do NOT test
     }
-
-    private static final class MockOnDrawerOpenListener implements OnDrawerOpenListener {
-        private boolean mHadOpenedDrawer = false;
-
-        public void onDrawerOpened() {
-            mHadOpenedDrawer = true;
-        }
-
-        public boolean hadOpenedDrawer() {
-            return mHadOpenedDrawer;
-        }
-    }
-
-    private static final class MockOnDrawerCloseListener implements OnDrawerCloseListener {
-        private boolean mHadClosedDrawer = false;
-
-        public void onDrawerClosed() {
-            mHadClosedDrawer = true;
-        }
-
-        public boolean hadClosedDrawer() {
-            return mHadClosedDrawer;
-        }
-    }
-
-    private final class MockOnDrawerScrollListener implements OnDrawerScrollListener {
-        private boolean mHadEndedScroll = false;
-        private boolean mHadStartedScroll = false;
-
-        public void onScrollEnded() {
-            synchronized (mLock) {
-                assertTrue(mHadStartedScroll);
-                mHadEndedScroll = true;
-                mLock.notify();
-            }
-        }
-
-        public void onScrollStarted() {
-            synchronized (mLock) {
-                mHadStartedScroll = true;
-                mLock.notify();
-            }
-        }
-
-        public boolean hadEndedScroll() {
-            return mHadEndedScroll;
-        }
-
-        public boolean hadStartedScroll() {
-            return mHadStartedScroll;
-        }
-    }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/SpinnerCtsActivity.java b/tests/tests/widget/src/android/widget/cts/SpinnerCtsActivity.java
new file mode 100644
index 0000000..16fb30e
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/SpinnerCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.Spinner;
+
+/**
+ * A minimal application for {@link Spinner} test.
+ */
+public class SpinnerCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.spinner_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/SpinnerTest.java b/tests/tests/widget/src/android/widget/cts/SpinnerTest.java
index eea1e3e..62fe412 100644
--- a/tests/tests/widget/src/android/widget/cts/SpinnerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SpinnerTest.java
@@ -16,101 +16,163 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
-
+import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Dialog;
-import android.content.Context;
+import android.app.Instrumentation;
+import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
 import android.content.res.Resources.Theme;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.view.ContextThemeWrapper;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
 import android.widget.Spinner;
+import android.widget.cts.util.TestUtils;
+import android.widget.cts.util.ViewTestUtils;
+
+import static org.mockito.Mockito.mock;
 
 /**
  * Test {@link Spinner}.
  */
-public class SpinnerTest extends ActivityInstrumentationTestCase2<RelativeLayoutCtsActivity> {
-    private Context mTargetContext;
+@MediumTest
+public class SpinnerTest extends ActivityInstrumentationTestCase2<SpinnerCtsActivity> {
+    private Activity mActivity;
+    private Spinner mSpinnerDialogMode;
+    private Spinner mSpinnerDropdownMode;
 
     public SpinnerTest() {
-        super("android.widget.cts", RelativeLayoutCtsActivity.class);
+        super("android.widget.cts", SpinnerCtsActivity.class);
     }
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mTargetContext = getInstrumentation().getTargetContext();
+
+        mActivity = getActivity();
+        mSpinnerDialogMode = (Spinner) mActivity.findViewById(R.id.spinner_dialog_mode);
+        mSpinnerDropdownMode = (Spinner) mActivity.findViewById(R.id.spinner_dropdown_mode);
     }
 
-    @UiThreadTest
     public void testConstructor() {
-        new Spinner(mTargetContext);
+        new Spinner(mActivity);
 
-        new Spinner(mTargetContext, null);
+        new Spinner(mActivity, null);
 
-        new Spinner(mTargetContext, null, android.R.attr.spinnerStyle);
+        new Spinner(mActivity, null, android.R.attr.spinnerStyle);
 
-        new Spinner(mTargetContext, Spinner.MODE_DIALOG);
+        new Spinner(mActivity, Spinner.MODE_DIALOG);
 
-        new Spinner(mTargetContext, null, android.R.attr.spinnerStyle,
+        new Spinner(mActivity, Spinner.MODE_DROPDOWN);
+
+        new Spinner(mActivity, null, android.R.attr.spinnerStyle, Spinner.MODE_DIALOG);
+
+        new Spinner(mActivity, null, android.R.attr.spinnerStyle, Spinner.MODE_DROPDOWN);
+
+        new Spinner(mActivity, null, 0, android.R.style.Widget_DeviceDefault_Spinner,
                 Spinner.MODE_DIALOG);
 
-        new Spinner(mTargetContext, null, android.R.attr.spinnerStyle, 0,
+        new Spinner(mActivity, null, 0, android.R.style.Widget_DeviceDefault_Spinner,
+                Spinner.MODE_DROPDOWN);
+
+        new Spinner(mActivity, null, 0, android.R.style.Widget_DeviceDefault_Light_Spinner,
                 Spinner.MODE_DIALOG);
 
-        new Spinner(mTargetContext, null, android.R.attr.spinnerStyle, 0,
-                Spinner.MODE_DIALOG, mTargetContext.getTheme());
+        new Spinner(mActivity, null, 0, android.R.style.Widget_DeviceDefault_Light_Spinner,
+                Spinner.MODE_DROPDOWN);
 
-        Spinner spinner = (Spinner) getActivity().findViewById(R.id.spinner1);
-        assertEquals(mTargetContext.getString(R.string.text_view_hello), spinner.getPrompt());
+        new Spinner(mActivity, null, 0, android.R.style.Widget_Material_Spinner,
+                Spinner.MODE_DIALOG);
+
+        new Spinner(mActivity, null, 0, android.R.style.Widget_Material_Spinner,
+                Spinner.MODE_DROPDOWN);
+
+        new Spinner(mActivity, null, 0, android.R.style.Widget_Material_Spinner_Underlined,
+                Spinner.MODE_DIALOG);
+
+        new Spinner(mActivity, null, 0, android.R.style.Widget_Material_Spinner_Underlined,
+                Spinner.MODE_DROPDOWN);
+
+        new Spinner(mActivity, null, 0, android.R.style.Widget_Material_Light_Spinner,
+                Spinner.MODE_DIALOG);
+
+        new Spinner(mActivity, null, 0, android.R.style.Widget_Material_Light_Spinner,
+                Spinner.MODE_DROPDOWN);
+
+        new Spinner(mActivity, null, 0, android.R.style.Widget_Material_Light_Spinner_Underlined,
+                Spinner.MODE_DIALOG);
+
+        new Spinner(mActivity, null, 0, android.R.style.Widget_Material_Light_Spinner_Underlined,
+                Spinner.MODE_DROPDOWN);
+
+        final Resources.Theme popupTheme = mActivity.getResources().newTheme();
+        popupTheme.applyStyle(android.R.style.Theme_Material, true);
+
+        new Spinner(mActivity, null, android.R.attr.spinnerStyle, 0, Spinner.MODE_DIALOG,
+                popupTheme);
+
+        new Spinner(mActivity, null, android.R.attr.spinnerStyle, 0, Spinner.MODE_DROPDOWN,
+                popupTheme);
     }
 
-    @UiThreadTest
-    public void testGetBaseline() {
-        Spinner spinner = new Spinner(mTargetContext);
-
+    private void verifyGetBaseline(Spinner spinner) {
         assertEquals(-1, spinner.getBaseline());
 
-        spinner = (Spinner) getActivity().findViewById(R.id.spinner1);
-        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mTargetContext,
-                android.widget.cts.R.array.string, android.R.layout.simple_spinner_item);
+        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mActivity,
+                R.array.string, android.R.layout.simple_spinner_item);
         adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
-        spinner.setAdapter(adapter);
-        assertTrue(spinner.getBaseline() > 0);
+        getInstrumentation().runOnMainSync(() -> {
+            spinner.setAdapter(adapter);
+            assertTrue(spinner.getBaseline() > 0);
+        });
     }
 
-    @UiThreadTest
-    public void testSetOnItemClickListener() {
-        Spinner spinner = new Spinner(mTargetContext);
+    public void testGetBaseline() {
+        verifyGetBaseline(mSpinnerDialogMode);
+        verifyGetBaseline(mSpinnerDropdownMode);
+    }
 
+    private void verifySetOnItemClickListener(Spinner spinner) {
         try {
             spinner.setOnItemClickListener(null);
             fail("Should throw RuntimeException");
         } catch (RuntimeException e) {
         }
+
+        try {
+            spinner.setOnItemClickListener(mock(Spinner.OnItemClickListener.class));
+            fail("Should throw RuntimeException");
+        } catch (RuntimeException e) {
+        }
     }
 
-    @UiThreadTest
+    public void testSetOnItemClickListener() {
+        verifySetOnItemClickListener(mSpinnerDialogMode);
+        verifySetOnItemClickListener(mSpinnerDropdownMode);
+    }
+
+    private void verifyPerformClick(Spinner spinner) {
+        getInstrumentation().runOnMainSync(() -> assertTrue(spinner.performClick()));
+    }
+
     public void testPerformClick() {
-        final Spinner spinner = (Spinner) getActivity().findViewById(R.id.spinner1);
-
-        assertTrue(spinner.performClick());
-
-        // TODO: no description for the expected result for this method in its javadoc, issue?
-        // Or do UI check?
+        verifyPerformClick(mSpinnerDialogMode);
+        verifyPerformClick(mSpinnerDropdownMode);
     }
 
-    @UiThreadTest
-    public void testOnClick() {
-        Spinner spinner = new Spinner(mTargetContext);
+    private void verifyOnClick(Spinner spinner) {
         // normal value
         AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
         AlertDialog alertDialog = builder.show();
         assertTrue(alertDialog.isShowing());
+
         spinner.onClick(alertDialog, 10);
         assertEquals(10, spinner.getSelectedItemPosition());
         assertFalse(alertDialog.isShowing());
@@ -125,32 +187,42 @@
         Dialog dialog = new Dialog(getActivity());
         dialog.show();
         assertTrue(dialog.isShowing());
+
         spinner.onClick(dialog, -10);
         assertEquals(-10, spinner.getSelectedItemPosition());
         assertFalse(dialog.isShowing());
     }
 
     @UiThreadTest
-    public void testAccessPrompt() {
+    public void testOnClick() {
+        verifyOnClick(mSpinnerDialogMode);
+        verifyOnClick(mSpinnerDropdownMode);
+    }
+
+    private void verifyAccessPrompt(Spinner spinner) {
+        final String initialPrompt = mActivity.getString(R.string.text_view_hello);
+        assertEquals(initialPrompt, spinner.getPrompt());
+
+        final Instrumentation instrumentation = getInstrumentation();
         final String promptText = "prompt text";
 
-        Spinner spinner = new Spinner(mTargetContext);
-
-        spinner.setPrompt(promptText);
+        instrumentation.runOnMainSync(() -> spinner.setPrompt(promptText));
         assertEquals(promptText, spinner.getPrompt());
 
         spinner.setPrompt(null);
         assertNull(spinner.getPrompt());
-
-        // TODO: find the dialog and get its title to assert whether setPrompt() takes effect?
     }
 
-    @UiThreadTest
-    public void testSetPromptId() {
-        Spinner spinner = new Spinner(mTargetContext);
+    public void testAccessPrompt() {
+        verifyAccessPrompt(mSpinnerDialogMode);
+        verifyAccessPrompt(mSpinnerDropdownMode);
+    }
 
-        spinner.setPromptId(R.string.hello_world);
-        assertEquals(mTargetContext.getString(R.string.hello_world), spinner.getPrompt());
+    private void verifySetPromptId(Spinner spinner) {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        instrumentation.runOnMainSync(() -> spinner.setPromptId(R.string.hello_world));
+        assertEquals(mActivity.getString(R.string.hello_world), spinner.getPrompt());
 
         try {
             spinner.setPromptId(-1);
@@ -165,23 +237,209 @@
         } catch (NotFoundException e) {
             // issue 1695243, not clear what is supposed to happen if promptId is exceptional.
         }
+    }
 
-        // TODO: find the dialog and get its title to assert whether setPromptId() takes effect?
+    public void testSetPromptId() {
+        verifySetPromptId(mSpinnerDialogMode);
+        verifySetPromptId(mSpinnerDropdownMode);
     }
 
     @UiThreadTest
     public void testGetPopupContext() {
-        Theme theme = mTargetContext.getResources().newTheme();
-        Spinner themeSpinner = new Spinner(mTargetContext, null,
+        Theme theme = mActivity.getResources().newTheme();
+        Spinner themeSpinner = new Spinner(mActivity, null,
                 android.R.attr.spinnerStyle, 0, Spinner.MODE_DIALOG, theme);
-        assertNotSame(mTargetContext, themeSpinner.getPopupContext());
+        assertNotSame(mActivity, themeSpinner.getPopupContext());
         assertSame(theme, themeSpinner.getPopupContext().getTheme());
 
         ContextThemeWrapper context = (ContextThemeWrapper)themeSpinner.getPopupContext();
-        assertSame(mTargetContext, context.getBaseContext());
+        assertSame(mActivity, context.getBaseContext());
     }
 
-    public void testOnLayout() {
-        // onLayout() is implementation details, do NOT test
+    private void verifyGravity(Spinner spinner) {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        // Note that here we're using a custom layout for the spinner's selected item
+        // that doesn't span the whole width of the parent. That way we're exercising the
+        // relevant path in spinner's layout pass that handles the currently set gravity
+        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mActivity,
+                R.array.string, R.layout.simple_spinner_item_layout);
+        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        instrumentation.runOnMainSync(() -> spinner.setAdapter(adapter));
+
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, spinner, () -> {
+            spinner.setSelection(1);
+            spinner.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
+            spinner.requestLayout();
+        });
+
+        instrumentation.runOnMainSync(() -> spinner.setGravity(Gravity.LEFT));
+        assertEquals(Gravity.LEFT, spinner.getGravity());
+
+        instrumentation.runOnMainSync(() -> spinner.setGravity(Gravity.CENTER_HORIZONTAL));
+        assertEquals(Gravity.CENTER_HORIZONTAL, spinner.getGravity());
+
+        instrumentation.runOnMainSync((() -> spinner.setGravity(Gravity.RIGHT)));
+        assertEquals(Gravity.RIGHT, spinner.getGravity());
+
+        instrumentation.runOnMainSync(() -> spinner.setGravity(Gravity.START));
+        assertEquals(Gravity.START, spinner.getGravity());
+
+        instrumentation.runOnMainSync(() -> spinner.setGravity(Gravity.END));
+        assertEquals(Gravity.END, spinner.getGravity());
+    }
+
+    public void testGravity() {
+        verifyGravity(mSpinnerDialogMode);
+        verifyGravity(mSpinnerDropdownMode);
+    }
+
+    public void testDropDownMetricsDropdownMode() {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mActivity,
+                R.array.string, android.R.layout.simple_spinner_item);
+        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        instrumentation.runOnMainSync(() -> mSpinnerDropdownMode.setAdapter(adapter));
+
+        final Resources res = mActivity.getResources();
+        final int dropDownWidth = res.getDimensionPixelSize(R.dimen.spinner_dropdown_width);
+        final int dropDownOffsetHorizontal =
+                res.getDimensionPixelSize(R.dimen.spinner_dropdown_offset_h);
+        final int dropDownOffsetVertical =
+                res.getDimensionPixelSize(R.dimen.spinner_dropdown_offset_v);
+
+        instrumentation.runOnMainSync(() -> {
+            mSpinnerDropdownMode.setDropDownWidth(dropDownWidth);
+            mSpinnerDropdownMode.setDropDownHorizontalOffset(dropDownOffsetHorizontal);
+            mSpinnerDropdownMode.setDropDownVerticalOffset(dropDownOffsetVertical);
+        });
+
+        // Use instrumentation to emulate a tap on the spinner to bring down its popup
+        ViewTestUtils.emulateTapOnViewCenter(instrumentation, mSpinnerDropdownMode);
+        // Verify that we're showing the popup
+        assertTrue(mSpinnerDropdownMode.isPopupShowing());
+
+        // And test its attributes
+        assertEquals(dropDownWidth, mSpinnerDropdownMode.getDropDownWidth());
+        // TODO: restore when b/28089349 is addressed
+        // assertEquals(dropDownOffsetHorizontal,
+        //      mSpinnerDropdownMode.getDropDownHorizontalOffset());
+        assertEquals(dropDownOffsetVertical, mSpinnerDropdownMode.getDropDownVerticalOffset());
+    }
+
+    public void testDropDownMetricsDialogMode() {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mActivity,
+                R.array.string, android.R.layout.simple_spinner_item);
+        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        instrumentation.runOnMainSync(() -> mSpinnerDialogMode.setAdapter(adapter));
+
+        final Resources res = mActivity.getResources();
+        final int dropDownWidth = res.getDimensionPixelSize(R.dimen.spinner_dropdown_width);
+        final int dropDownOffsetHorizontal =
+                res.getDimensionPixelSize(R.dimen.spinner_dropdown_offset_h);
+        final int dropDownOffsetVertical =
+                res.getDimensionPixelSize(R.dimen.spinner_dropdown_offset_v);
+
+        instrumentation.runOnMainSync(() -> {
+            // These are all expected to be no-ops
+            mSpinnerDialogMode.setDropDownWidth(dropDownWidth);
+            mSpinnerDialogMode.setDropDownHorizontalOffset(dropDownOffsetHorizontal);
+            mSpinnerDialogMode.setDropDownVerticalOffset(dropDownOffsetVertical);
+        });
+
+        // Use instrumentation to emulate a tap on the spinner to bring down its popup
+        ViewTestUtils.emulateTapOnViewCenter(instrumentation, mSpinnerDialogMode);
+        // Verify that we're showing the popup
+        assertTrue(mSpinnerDialogMode.isPopupShowing());
+
+        // And test its attributes. Note that we are not testing the result of getDropDownWidth
+        // for this mode
+        assertEquals(0, mSpinnerDialogMode.getDropDownHorizontalOffset());
+        assertEquals(0, mSpinnerDialogMode.getDropDownVerticalOffset());
+    }
+
+    public void testDropDownBackgroundDropdownMode() {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mActivity,
+                R.array.string, android.R.layout.simple_spinner_item);
+        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        instrumentation.runOnMainSync(() -> mSpinnerDropdownMode.setAdapter(adapter));
+
+        // Set blue background on the popup
+        instrumentation.runOnMainSync(() ->
+                mSpinnerDropdownMode.setPopupBackgroundResource(R.drawable.blue_fill));
+
+        // Use instrumentation to emulate a tap on the spinner to bring down its popup
+        ViewTestUtils.emulateTapOnViewCenter(instrumentation, mSpinnerDropdownMode);
+        // Verify that we're showing the popup
+        assertTrue(mSpinnerDropdownMode.isPopupShowing());
+        // And test its fill
+        Drawable dropDownBackground = mSpinnerDropdownMode.getPopupBackground();
+        TestUtils.assertAllPixelsOfColor("Drop down should be blue", dropDownBackground,
+                dropDownBackground.getBounds().width(), dropDownBackground.getBounds().height(),
+                false, Color.BLUE, 1, true);
+
+        // Dismiss the popup with the emulated back key
+        instrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
+        instrumentation.waitForIdleSync();
+        // Verify that we're not showing the popup
+        assertFalse(mSpinnerDropdownMode.isPopupShowing());
+
+        // Set yellow background on the popup
+        instrumentation.runOnMainSync(() ->
+                mSpinnerDropdownMode.setPopupBackgroundDrawable(
+                        mActivity.getDrawable(R.drawable.yellow_fill)));
+
+        // Use instrumentation to emulate a tap on the spinner to bring down its popup
+        ViewTestUtils.emulateTapOnViewCenter(instrumentation, mSpinnerDropdownMode);
+        // Verify that we're showing the popup
+        assertTrue(mSpinnerDropdownMode.isPopupShowing());
+        // And test its fill
+        dropDownBackground = mSpinnerDropdownMode.getPopupBackground();
+        TestUtils.assertAllPixelsOfColor("Drop down should be yellow", dropDownBackground,
+                dropDownBackground.getBounds().width(), dropDownBackground.getBounds().height(),
+                false, Color.YELLOW, 1, true);
+    }
+
+    public void testDropDownBackgroundDialogMode() {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mActivity,
+                R.array.string, android.R.layout.simple_spinner_item);
+        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        instrumentation.runOnMainSync(() -> mSpinnerDialogMode.setAdapter(adapter));
+
+        // Set blue background on the popup
+        instrumentation.runOnMainSync(() ->
+                mSpinnerDialogMode.setPopupBackgroundResource(R.drawable.blue_fill));
+
+        // Use instrumentation to emulate a tap on the spinner to bring down its popup
+        ViewTestUtils.emulateTapOnViewCenter(instrumentation, mSpinnerDialogMode);
+        // Verify that we're showing the popup
+        assertTrue(mSpinnerDialogMode.isPopupShowing());
+        // And test that getPopupBackground returns null
+        assertNull(mSpinnerDialogMode.getPopupBackground());
+
+        // Dismiss the popup with the emulated back key
+        instrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
+        instrumentation.waitForIdleSync();
+        // Verify that we're not showing the popup
+        assertFalse(mSpinnerDialogMode.isPopupShowing());
+
+        // Set yellow background on the popup
+        instrumentation.runOnMainSync(() ->
+                mSpinnerDialogMode.setPopupBackgroundDrawable(
+                        mActivity.getDrawable(R.drawable.yellow_fill)));
+
+        // Use instrumentation to emulate a tap on the spinner to bring down its popup
+        ViewTestUtils.emulateTapOnViewCenter(instrumentation, mSpinnerDialogMode);
+        // Verify that we're showing the popup
+        assertTrue(mSpinnerDialogMode.isPopupShowing());
+        // And test that getPopupBackground returns null
+        assertNull(mSpinnerDialogMode.getPopupBackground());
     }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/SwitchTest.java b/tests/tests/widget/src/android/widget/cts/SwitchTest.java
index 216b17b..fb449ed 100644
--- a/tests/tests/widget/src/android/widget/cts/SwitchTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SwitchTest.java
@@ -17,22 +17,28 @@
 package android.widget.cts;
 
 import android.app.Activity;
+import android.app.Instrumentation;
 import android.content.res.ColorStateList;
 import android.graphics.Color;
 import android.graphics.PorterDuff.Mode;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
 import android.test.ActivityInstrumentationTestCase;
+import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
 import android.test.suitebuilder.annotation.SmallTest;
+import android.view.ContextThemeWrapper;
+import android.view.ViewGroup;
 import android.widget.Switch;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
+import android.widget.cts.util.TestUtils;
+import android.widget.cts.util.ViewTestUtils;
 
 /**
  * Test {@link Switch}.
  */
 @SmallTest
-public class SwitchTest extends ActivityInstrumentationTestCase<SwitchCtsActivity> {
+public class SwitchTest extends ActivityInstrumentationTestCase2<SwitchCtsActivity> {
     private Activity mActivity;
     private Switch mSwitch;
 
@@ -44,7 +50,10 @@
     protected void setUp() throws Exception {
         super.setUp();
         mActivity = getActivity();
-        mSwitch = (Switch) mActivity.findViewById(R.id.switch_view);
+    }
+
+    private Switch findSwitchById(int id) {
+        return (Switch) mActivity.findViewById(id);
     }
 
     @UiThreadTest
@@ -55,11 +64,16 @@
 
         new Switch(mActivity, null, android.R.attr.switchStyle);
 
+        new Switch(mActivity, null, 0, android.R.style.Widget_Material_CompoundButton_Switch);
+
         new Switch(mActivity, null, 0, android.R.style.Widget_Material_Light_CompoundButton_Switch);
     }
 
     @UiThreadTest
     public void testAccessThumbTint() {
+        mSwitch = findSwitchById(R.id.switch1);
+
+        // These are the default set in layout XML
         assertEquals(Color.WHITE, mSwitch.getThumbTintList().getDefaultColor());
         assertEquals(Mode.SRC_OVER, mSwitch.getThumbTintMode());
 
@@ -73,6 +87,9 @@
 
     @UiThreadTest
     public void testAccessTrackTint() {
+        mSwitch = findSwitchById(R.id.switch1);
+
+        // These are the default set in layout XML
         assertEquals(Color.BLACK, mSwitch.getTrackTintList().getDefaultColor());
         assertEquals(Mode.SRC_ATOP, mSwitch.getTrackTintMode());
 
@@ -83,4 +100,175 @@
         assertSame(colors, mSwitch.getTrackTintList());
         assertEquals(Mode.XOR, mSwitch.getTrackTintMode());
     }
+
+    public void testAccessThumbDrawable() {
+        mSwitch = findSwitchById(R.id.switch2);
+        final Instrumentation instrumentation = getInstrumentation();
+
+        // This is the default set in layout XML
+        Drawable thumbDrawable = mSwitch.getThumbDrawable();
+        TestUtils.assertAllPixelsOfColor("Thumb drawable should be blue", thumbDrawable,
+                thumbDrawable.getIntrinsicWidth(), thumbDrawable.getIntrinsicHeight(), false,
+                Color.BLUE, 1, true);
+
+        // Change thumb drawable to red
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setThumbDrawable(mActivity.getDrawable(R.drawable.icon_red)));
+        thumbDrawable = mSwitch.getThumbDrawable();
+        TestUtils.assertAllPixelsOfColor("Thumb drawable should be red", thumbDrawable,
+                thumbDrawable.getIntrinsicWidth(), thumbDrawable.getIntrinsicHeight(), false,
+                Color.RED, 1, true);
+
+        // Change thumb drawable to green
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setThumbResource(R.drawable.icon_green));
+        thumbDrawable = mSwitch.getThumbDrawable();
+        TestUtils.assertAllPixelsOfColor("Thumb drawable should be green", thumbDrawable,
+                thumbDrawable.getIntrinsicWidth(), thumbDrawable.getIntrinsicHeight(), false,
+                Color.GREEN, 1, true);
+
+        // Now tint the latest (green) thumb drawable with 50% blue SRC_OVER
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch, () -> {
+            mSwitch.setThumbTintList(ColorStateList.valueOf(0x800000FF));
+            mSwitch.setThumbTintMode(Mode.SRC_OVER);
+        });
+        thumbDrawable = mSwitch.getThumbDrawable();
+        TestUtils.assertAllPixelsOfColor("Thumb drawable should be green / blue", thumbDrawable,
+                thumbDrawable.getIntrinsicWidth(), thumbDrawable.getIntrinsicHeight(), false,
+                TestUtils.compositeColors(0x800000FF, Color.GREEN), 1, true);
+    }
+
+    public void testAccessTrackDrawable() {
+        mSwitch = findSwitchById(R.id.switch2);
+        final Instrumentation instrumentation = getInstrumentation();
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+            () -> mSwitch.setTrackTintMode(Mode.DST));
+
+        // This is the default set in layout XML
+        Drawable trackDrawable = mSwitch.getTrackDrawable();
+        Rect trackDrawableBounds = trackDrawable.getBounds();
+        TestUtils.assertAllPixelsOfColor("Track drawable should be 50% red", trackDrawable,
+                trackDrawableBounds.width(), trackDrawableBounds.height(), false,
+                0x80FF0000, 1, true);
+
+        // Change track drawable to blue
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setTrackDrawable(mActivity.getDrawable(R.drawable.blue_fill)));
+        trackDrawable = mSwitch.getTrackDrawable();
+        trackDrawableBounds = trackDrawable.getBounds();
+        TestUtils.assertAllPixelsOfColor("Track drawable should be blue", trackDrawable,
+                trackDrawableBounds.width(), trackDrawableBounds.height(), false,
+                Color.BLUE, 1, true);
+
+        // Change track drawable to green
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setTrackResource(R.drawable.green_fill));
+        trackDrawable = mSwitch.getTrackDrawable();
+        trackDrawableBounds = trackDrawable.getBounds();
+        TestUtils.assertAllPixelsOfColor("Track drawable should be green", trackDrawable,
+                trackDrawableBounds.width(), trackDrawableBounds.height(), false,
+                Color.GREEN, 1, true);
+
+        // Now tint the latest (green) track drawable with 50% blue SRC_OVER
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch, () -> {
+            mSwitch.setTrackTintList(ColorStateList.valueOf(0x800000FF));
+            mSwitch.setTrackTintMode(Mode.SRC_OVER);
+        });
+        trackDrawable = mSwitch.getTrackDrawable();
+        trackDrawableBounds = trackDrawable.getBounds();
+        TestUtils.assertAllPixelsOfColor("Track drawable should be green / blue", trackDrawable,
+                trackDrawableBounds.width(), trackDrawableBounds.height(), false,
+                TestUtils.compositeColors(0x800000FF, Color.GREEN), 1, true);
+    }
+
+    public void testAccessText() {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        // Run text-related tests on a Holo-themed switch, since under Material themes we
+        // are not showing texts by default.
+        mSwitch = new Switch(new ContextThemeWrapper(mActivity, android.R.style.Theme_Holo_Light));
+        instrumentation.runOnMainSync(
+                () -> ((ViewGroup) mActivity.findViewById(R.id.container)).addView(mSwitch));
+
+        // Set "on" text and verify it
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setTextOn("Text on"));
+        assertEquals("Text on", mSwitch.getTextOn());
+
+        // Set "off" text and verify it
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setTextOff("Text off"));
+        assertEquals("Text off", mSwitch.getTextOff());
+
+        // Turn text display on
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setShowText(true));
+        assertTrue(mSwitch.getShowText());
+
+        // Use custom text appearance. Since we don't have APIs to query this facet of Switch,
+        // just test that it's not crashing.
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setSwitchTextAppearance(mActivity, R.style.TextAppearance_WithColor));
+
+        // Use custom typeface. Since we don't have APIs to query this facet of Switch,
+        // just test that it's not crashing.
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setSwitchTypeface(Typeface.MONOSPACE));
+
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setSwitchTypeface(Typeface.SERIF, Typeface.ITALIC));
+
+        // Set and verify padding between the thumb and the text
+        final int thumbTextPadding = mActivity.getResources().getDimensionPixelSize(
+                R.dimen.switch_thumb_text_padding);
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setThumbTextPadding(thumbTextPadding));
+        assertEquals(thumbTextPadding, mSwitch.getThumbTextPadding());
+
+        // Set and verify padding between the switch and the text
+        final int switchPadding = mActivity.getResources().getDimensionPixelSize(
+                R.dimen.switch_padding);
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setSwitchPadding(switchPadding));
+        assertEquals(switchPadding, mSwitch.getSwitchPadding());
+
+        // Turn text display off
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setShowText(false));
+        assertFalse(mSwitch.getShowText());
+    }
+
+    public void testAccessMinWidth() {
+        mSwitch = findSwitchById(R.id.switch3);
+        final Instrumentation instrumentation = getInstrumentation();
+
+        // Set custom min width on the switch and verify that it's at least that wide
+        final int switchMinWidth = mActivity.getResources().getDimensionPixelSize(
+                R.dimen.switch_min_width);
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setSwitchMinWidth(switchMinWidth));
+        assertEquals(switchMinWidth, mSwitch.getSwitchMinWidth());
+        assertTrue(mSwitch.getWidth() >= switchMinWidth);
+
+        // And set another (larger) min width
+        final int switchMinWidth2 = mActivity.getResources().getDimensionPixelSize(
+                R.dimen.switch_min_width2);
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setSwitchMinWidth(switchMinWidth2));
+        assertEquals(switchMinWidth2, mSwitch.getSwitchMinWidth());
+        assertTrue(mSwitch.getWidth() >= switchMinWidth2);
+    }
+
+    public void testAccessSplitTrack() {
+        mSwitch = findSwitchById(R.id.switch3);
+        final Instrumentation instrumentation = getInstrumentation();
+
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setSplitTrack(true));
+        assertTrue(mSwitch.getSplitTrack());
+
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setSplitTrack(false));
+        assertFalse(mSwitch.getSplitTrack());
+    }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/TableLayoutTest.java b/tests/tests/widget/src/android/widget/cts/TableLayoutTest.java
index ccf22d9..d35e5cb 100644
--- a/tests/tests/widget/src/android/widget/cts/TableLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TableLayoutTest.java
@@ -16,8 +16,6 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
 import android.content.Context;
 import android.content.res.XmlResourceParser;
 import android.test.ActivityInstrumentationTestCase2;
@@ -25,9 +23,8 @@
 import android.util.AttributeSet;
 import android.util.Xml;
 import android.view.View;
-import android.view.ViewGroup;
 import android.view.View.MeasureSpec;
-import android.view.ViewGroup.OnHierarchyChangeListener;
+import android.view.ViewGroup;
 import android.widget.LinearLayout;
 import android.widget.ListView;
 import android.widget.RelativeLayout;
@@ -35,6 +32,8 @@
 import android.widget.TableRow;
 import android.widget.TextView;
 
+import static org.mockito.Mockito.*;
+
 /**
  * Test {@link TableLayout}.
  */
@@ -72,21 +71,21 @@
     public void testSetOnHierarchyChangeListener() {
         TableLayout tableLayout = new TableLayout(mContext);
 
-        MockOnHierarchyChangeListener listener = new MockOnHierarchyChangeListener();
-        tableLayout.setOnHierarchyChangeListener(listener);
+        ViewGroup.OnHierarchyChangeListener mockHierarchyChangeListener =
+                mock(ViewGroup.OnHierarchyChangeListener.class);
+        tableLayout.setOnHierarchyChangeListener(mockHierarchyChangeListener);
 
-        tableLayout.addView(new TextView(mContext));
-        assertTrue(listener.hasCalledOnChildViewAdded());
+        View toAdd = new TextView(mContext);
+        tableLayout.addView(toAdd);
+        verify(mockHierarchyChangeListener, times(1)).onChildViewAdded(tableLayout, toAdd);
         tableLayout.removeViewAt(0);
-        assertTrue(listener.hasCalledOnChildViewRemoved());
-
-        listener.reset();
+        verify(mockHierarchyChangeListener, times(1)).onChildViewRemoved(tableLayout, toAdd);
+        verifyNoMoreInteractions(mockHierarchyChangeListener);
 
         tableLayout.setOnHierarchyChangeListener(null);
         tableLayout.addView(new TextView(mContext));
-        assertFalse(listener.hasCalledOnChildViewAdded());
         tableLayout.removeViewAt(0);
-        assertFalse(listener.hasCalledOnChildViewRemoved());
+        verifyNoMoreInteractions(mockHierarchyChangeListener);
     }
 
     public void testRequestLayout() {
@@ -456,7 +455,8 @@
         assertNull(child1.getLayoutParams());
         tableLayout.addView(child1, new ViewGroup.LayoutParams(100, 200));
         assertSame(child1, tableLayout.getChildAt(0));
-        assertEquals(100, tableLayout.getChildAt(0).getLayoutParams().width);
+        assertEquals(ViewGroup.LayoutParams.MATCH_PARENT,
+                tableLayout.getChildAt(0).getLayoutParams().width);
         assertEquals(200, tableLayout.getChildAt(0).getLayoutParams().height);
         assertTrue(tableLayout.getChildAt(0).isLayoutRequested());
 
@@ -467,9 +467,11 @@
         tableLayout.addView(child2, new TableRow.LayoutParams(200, 300, 1));
         assertSame(child1, tableLayout.getChildAt(0));
         assertSame(child2, tableLayout.getChildAt(1));
-        assertEquals(100, tableLayout.getChildAt(0).getLayoutParams().width);
+        assertEquals(ViewGroup.LayoutParams.MATCH_PARENT,
+                tableLayout.getChildAt(0).getLayoutParams().width);
         assertEquals(200, tableLayout.getChildAt(0).getLayoutParams().height);
-        assertEquals(200, tableLayout.getChildAt(1).getLayoutParams().width);
+        assertEquals(ViewGroup.LayoutParams.MATCH_PARENT,
+                tableLayout.getChildAt(1).getLayoutParams().width);
         assertEquals(300, tableLayout.getChildAt(1).getLayoutParams().height);
         assertTrue(tableLayout.getChildAt(0).isLayoutRequested());
         assertTrue(tableLayout.getChildAt(1).isLayoutRequested());
@@ -494,7 +496,8 @@
         assertNull(child1.getLayoutParams());
         tableLayout.addView(child1, 0, new ViewGroup.LayoutParams(100, 200));
         assertSame(child1, tableLayout.getChildAt(0));
-        assertEquals(100, tableLayout.getChildAt(0).getLayoutParams().width);
+        assertEquals(ViewGroup.LayoutParams.MATCH_PARENT,
+                tableLayout.getChildAt(0).getLayoutParams().width);
         assertEquals(200, tableLayout.getChildAt(0).getLayoutParams().height);
         assertTrue(tableLayout.getChildAt(0).isLayoutRequested());
 
@@ -505,9 +508,11 @@
         tableLayout.addView(child2, 0, new TableRow.LayoutParams(200, 300, 1));
         assertSame(child2, tableLayout.getChildAt(0));
         assertSame(child1, tableLayout.getChildAt(1));
-        assertEquals(200, tableLayout.getChildAt(0).getLayoutParams().width);
+        assertEquals(ViewGroup.LayoutParams.MATCH_PARENT,
+                tableLayout.getChildAt(0).getLayoutParams().width);
         assertEquals(300, tableLayout.getChildAt(0).getLayoutParams().height);
-        assertEquals(100, tableLayout.getChildAt(1).getLayoutParams().width);
+        assertEquals(ViewGroup.LayoutParams.MATCH_PARENT,
+                tableLayout.getChildAt(1).getLayoutParams().width);
         assertEquals(200, tableLayout.getChildAt(1).getLayoutParams().height);
         assertTrue(tableLayout.getChildAt(0).isLayoutRequested());
         assertTrue(tableLayout.getChildAt(1).isLayoutRequested());
@@ -520,11 +525,14 @@
         assertSame(child2, tableLayout.getChildAt(0));
         assertSame(child1, tableLayout.getChildAt(1));
         assertSame(child3, tableLayout.getChildAt(2));
-        assertEquals(200, tableLayout.getChildAt(0).getLayoutParams().width);
+        assertEquals(ViewGroup.LayoutParams.MATCH_PARENT,
+                tableLayout.getChildAt(0).getLayoutParams().width);
         assertEquals(300, tableLayout.getChildAt(0).getLayoutParams().height);
-        assertEquals(100, tableLayout.getChildAt(1).getLayoutParams().width);
+        assertEquals(ViewGroup.LayoutParams.MATCH_PARENT,
+                tableLayout.getChildAt(1).getLayoutParams().width);
         assertEquals(200, tableLayout.getChildAt(1).getLayoutParams().height);
-        assertEquals(300, tableLayout.getChildAt(2).getLayoutParams().width);
+        assertEquals(ViewGroup.LayoutParams.MATCH_PARENT,
+                tableLayout.getChildAt(2).getLayoutParams().width);
         assertEquals(400, tableLayout.getChildAt(2).getLayoutParams().height);
         assertTrue(tableLayout.getChildAt(0).isLayoutRequested());
         assertTrue(tableLayout.getChildAt(1).isLayoutRequested());
@@ -588,7 +596,7 @@
         LinearLayout.LayoutParams layoutParams = mockTableLayout.generateLayoutParams(
                 new ViewGroup.LayoutParams(200, 300));
         assertNotNull(layoutParams);
-        assertEquals(200, layoutParams.width);
+        assertEquals(ViewGroup.LayoutParams.MATCH_PARENT, layoutParams.width);
         assertEquals(300, layoutParams.height);
         assertTrue(layoutParams instanceof TableLayout.LayoutParams);
 
@@ -611,50 +619,6 @@
         mockTableLayout.onMeasure(MeasureSpec.EXACTLY, MeasureSpec.EXACTLY);
     }
 
-    private int dropNegative(int number) {
-        return (number > 0 ? number : 0);
-    }
-
-    private class MockOnHierarchyChangeListener implements OnHierarchyChangeListener {
-        private boolean mCalledOnChildViewAdded = false;
-        private boolean mCalledOnChildViewRemoved = false;
-
-        /*
-         * (non-Javadoc)
-         *
-         * @see
-         * android.view.ViewGroup.OnHierarchyChangeListener#onChildViewAdded
-         * (View, View)
-         */
-        public void onChildViewAdded(View parent, View child) {
-            mCalledOnChildViewAdded = true;
-        }
-
-        /*
-         * (non-Javadoc)
-         *
-         * @see
-         * android.view.ViewGroup.OnHierarchyChangeListener#onChildViewRemoved
-         * (View, View)
-         */
-        public void onChildViewRemoved(View parent, View child) {
-            mCalledOnChildViewRemoved = true;
-        }
-
-        public boolean hasCalledOnChildViewAdded() {
-            return mCalledOnChildViewAdded;
-        }
-
-        public boolean hasCalledOnChildViewRemoved() {
-            return mCalledOnChildViewRemoved;
-        }
-
-        public void reset() {
-            mCalledOnChildViewAdded = false;
-            mCalledOnChildViewRemoved = false;
-        }
-    }
-
     /*
      * Mock class for TableLayout to test protected methods
      */
diff --git a/tests/tests/widget/src/android/widget/cts/TableLayout_LayoutParamsTest.java b/tests/tests/widget/src/android/widget/cts/TableLayout_LayoutParamsTest.java
index fbd9f97..077c134c 100644
--- a/tests/tests/widget/src/android/widget/cts/TableLayout_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TableLayout_LayoutParamsTest.java
@@ -16,6 +16,7 @@
 
 package android.widget.cts;
 
+import android.view.ViewGroup;
 import android.widget.cts.R;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -42,28 +43,47 @@
     }
 
     public void testConstructor() {
-        new TableLayout.LayoutParams(mTargetContext, null);
+        // We expect width to be MATCH and height to be WRAP as documented in TableLayout
+        TableLayout.LayoutParams layoutParams = new TableLayout.LayoutParams();
+        assertEquals(TableLayout.LayoutParams.MATCH_PARENT, layoutParams.width);
+        assertEquals(TableLayout.LayoutParams.WRAP_CONTENT, layoutParams.height);
 
-        TableLayout.LayoutParams layoutParams = new TableLayout.LayoutParams(200, 300);
+        // We expect width to be MATCH and height to be WRAP as documented in TableLayout
+        layoutParams = new TableLayout.LayoutParams(mTargetContext, null);
+        assertEquals(TableLayout.LayoutParams.MATCH_PARENT, layoutParams.width);
+        assertEquals(TableLayout.LayoutParams.WRAP_CONTENT, layoutParams.height);
+
+        // We expect width to be MATCH, ignoring what is passed in the constructor
+        layoutParams = new TableLayout.LayoutParams(200, 300);
         assertEquals(TableLayout.LayoutParams.MATCH_PARENT, layoutParams.width);
         assertEquals(300, layoutParams.height);
-        TableLayout.LayoutParams oldParams = layoutParams;
 
-        layoutParams = new TableLayout.LayoutParams(200, 300, 1.2f);
+        // We expect width to be MATCH, ignoring what is passed in the constructor
+        layoutParams = new TableLayout.LayoutParams(250, 350, 1.2f);
         assertEquals(TableLayout.LayoutParams.MATCH_PARENT, layoutParams.width);
-        assertEquals(300, layoutParams.height);
+        assertEquals(350, layoutParams.height);
         assertEquals(1.2f, layoutParams.weight);
-        TableLayout.LayoutParams oldMarginParams = layoutParams;
 
-        new TableLayout.LayoutParams();
-
-        layoutParams = new TableLayout.LayoutParams(oldParams);
+        // We expect width to be MATCH, ignoring what is set on the passed object
+        layoutParams = new TableLayout.LayoutParams(new ViewGroup.LayoutParams(300, 360));
         assertEquals(TableLayout.LayoutParams.MATCH_PARENT, layoutParams.width);
-        assertEquals(300, layoutParams.height);
+        assertEquals(360, layoutParams.height);
 
-        layoutParams = new TableLayout.LayoutParams(oldMarginParams);
+        // We expect width to be MATCH, ignoring what is set on the passed object
+        layoutParams = new TableLayout.LayoutParams(new ViewGroup.MarginLayoutParams(320, 420));
         assertEquals(TableLayout.LayoutParams.MATCH_PARENT, layoutParams.width);
-        assertEquals(300, layoutParams.height);
+        assertEquals(420, layoutParams.height);
+
+        // We expect width to be MATCH as that is copied from the passed object
+        layoutParams = new TableLayout.LayoutParams(new TableLayout.LayoutParams(500, 400));
+        assertEquals(TableLayout.LayoutParams.MATCH_PARENT, layoutParams.width);
+        assertEquals(400, layoutParams.height);
+
+        // We expect width to be MATCH as that is copied from the passed object
+        layoutParams = new TableLayout.LayoutParams(new TableLayout.LayoutParams(550, 650, 1.4f));
+        assertEquals(TableLayout.LayoutParams.MATCH_PARENT, layoutParams.width);
+        assertEquals(650, layoutParams.height);
+        assertEquals(1.4f, layoutParams.weight);
     }
 
     public void testSetBaseAttributes() {
diff --git a/tests/tests/widget/src/android/widget/cts/TableRowTest.java b/tests/tests/widget/src/android/widget/cts/TableRowTest.java
index 2e917f8..070769f 100644
--- a/tests/tests/widget/src/android/widget/cts/TableRowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TableRowTest.java
@@ -24,17 +24,15 @@
 import android.util.AttributeSet;
 import android.util.Xml;
 import android.view.View;
-import android.view.ViewGroup;
 import android.view.View.MeasureSpec;
-import android.view.ViewGroup.OnHierarchyChangeListener;
+import android.view.ViewGroup;
 import android.widget.LinearLayout;
 import android.widget.RelativeLayout;
 import android.widget.TableLayout;
 import android.widget.TableRow;
 import android.widget.TextView;
 
-import android.widget.cts.R;
-
+import static org.mockito.Mockito.*;
 
 /**
  * Test {@link TableRow}.
@@ -63,21 +61,21 @@
     public void testSetOnHierarchyChangeListener() {
         TableRow tableRow = new TableRow(mContext);
 
-        MockOnHierarchyChangeListener listener = new MockOnHierarchyChangeListener();
-        tableRow.setOnHierarchyChangeListener(listener);
+        ViewGroup.OnHierarchyChangeListener mockHierarchyChangeListener =
+                mock(ViewGroup.OnHierarchyChangeListener.class);
+        tableRow.setOnHierarchyChangeListener(mockHierarchyChangeListener);
 
-        tableRow.addView(new TextView(mContext));
-        assertTrue(listener.hasCalledOnChildViewAdded());
+        View toAdd = new TextView(mContext);
+        tableRow.addView(toAdd);
+        verify(mockHierarchyChangeListener, times(1)).onChildViewAdded(tableRow, toAdd);
         tableRow.removeViewAt(0);
-        assertTrue(listener.hasCalledOnChildViewRemoved());
-
-        listener.reset();
+        verify(mockHierarchyChangeListener, times(1)).onChildViewRemoved(tableRow, toAdd);
+        verifyNoMoreInteractions(mockHierarchyChangeListener);
 
         tableRow.setOnHierarchyChangeListener(null);
         tableRow.addView(new TextView(mContext));
-        assertFalse(listener.hasCalledOnChildViewAdded());
         tableRow.removeViewAt(0);
-        assertFalse(listener.hasCalledOnChildViewRemoved());
+        verifyNoMoreInteractions(mockHierarchyChangeListener);
     }
 
     @UiThreadTest
@@ -189,46 +187,6 @@
         mockTableRow.onMeasure(MeasureSpec.EXACTLY, MeasureSpec.EXACTLY);
     }
 
-    private class MockOnHierarchyChangeListener implements OnHierarchyChangeListener {
-        private boolean mCalledOnChildViewAdded = false;
-        private boolean mCalledOnChildViewRemoved = false;
-
-        /*
-         * (non-Javadoc)
-         *
-         * @see
-         * android.view.ViewGroup.OnHierarchyChangeListener#onChildViewAdded
-         * (View, View)
-         */
-        public void onChildViewAdded(View parent, View child) {
-            mCalledOnChildViewAdded = true;
-        }
-
-        /*
-         * (non-Javadoc)
-         *
-         * @see
-         * android.view.ViewGroup.OnHierarchyChangeListener#onChildViewRemoved
-         * (View, View)
-         */
-        public void onChildViewRemoved(View parent, View child) {
-            mCalledOnChildViewRemoved = true;
-        }
-
-        public boolean hasCalledOnChildViewAdded() {
-            return mCalledOnChildViewAdded;
-        }
-
-        public boolean hasCalledOnChildViewRemoved() {
-            return mCalledOnChildViewRemoved;
-        }
-
-        public void reset() {
-            mCalledOnChildViewAdded = false;
-            mCalledOnChildViewRemoved = false;
-        }
-    }
-
     /*
      * Mock class for TableRow to test protected methods
      */
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/TextViewCtsActivity.java
index 31fc486..0580150 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewCtsActivity.java
@@ -16,17 +16,16 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
 import android.app.Activity;
 import android.os.Bundle;
+import android.widget.TextView;
 
 /**
- * A minimal application for TextView test.
+ * A minimal application for {@link TextView} test.
  */
 public class TextViewCtsActivity extends Activity {
     /**
-     * Called with the activity is first created.
+     * Called when the activity is first created.
      */
     @Override
     public void onCreate(Bundle savedInstanceState) {
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewFadingEdgeTest.java b/tests/tests/widget/src/android/widget/cts/TextViewFadingEdgeTest.java
index e627c2b..8334604 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewFadingEdgeTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewFadingEdgeTest.java
@@ -120,12 +120,7 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        new PollingCheck() {
-            @Override
-            protected boolean check() {
-                return getActivity().hasWindowFocus();
-            }
-        }.run();
+        PollingCheck.waitFor(() -> getActivity().hasWindowFocus());
     }
 
     public void testFadingEdge() {
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index 9f611ad..ee8974f 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -16,12 +16,16 @@
 
 package android.widget.cts;
 
+import android.annotation.IdRes;
+import android.annotation.NonNull;
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.app.Instrumentation.ActivityMonitor;
+import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.res.ColorStateList;
+import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
 import android.cts.util.KeyEventUtil;
 import android.cts.util.PollingCheck;
@@ -39,8 +43,11 @@
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.LocaleList;
+import android.os.Looper;
 import android.os.Parcelable;
+import android.os.ResultReceiver;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.TouchUtils;
 import android.test.UiThreadTest;
@@ -85,10 +92,7 @@
 import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.Menu;
-import android.view.MenuItem;
 import android.view.View;
-import android.view.View.OnCreateContextMenuListener;
-import android.view.View.OnLongClickListener;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.inputmethod.BaseInputConnection;
@@ -96,19 +100,27 @@
 import android.view.inputmethod.ExtractedText;
 import android.view.inputmethod.ExtractedTextRequest;
 import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputMethodManager;
 import android.widget.EditText;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
+import android.widget.ScrollView;
 import android.widget.Scroller;
 import android.widget.TextView;
 import android.widget.TextView.BufferType;
-import android.widget.TextView.OnEditorActionListener;
+import android.widget.cts.util.TestUtils;
+import android.widget.cts.util.ViewTestUtils;
 
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
 import java.util.Locale;
 
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.*;
+
 /**
  * Test {@link TextView}.
  */
@@ -125,6 +137,7 @@
     private static final long TIMEOUT = 5000;
     private CharSequence mTransformedText;
     private KeyEventUtil mKeyEventUtil;
+    private Handler mHandler = new Handler(Looper.getMainLooper());
 
     public TextViewTest() {
         super("android.widget.cts", TextViewCtsActivity.class);
@@ -134,12 +147,7 @@
     protected void setUp() throws Exception {
         super.setUp();
         mActivity = getActivity();
-        new PollingCheck() {
-            @Override
-                protected boolean check() {
-                return mActivity.hasWindowFocus();
-            }
-        }.run();
+        PollingCheck.waitFor(() -> mActivity.hasWindowFocus());
         mInstrumentation = getInstrumentation();
         mKeyEventUtil = new KeyEventUtil(mInstrumentation);
     }
@@ -164,7 +172,15 @@
 
         new TextView(mActivity, null);
 
-        new TextView(mActivity, null, 0);
+        new TextView(mActivity, null, android.R.attr.textViewStyle);
+
+        new TextView(mActivity, null, 0, android.R.style.Widget_DeviceDefault_TextView);
+
+        new TextView(mActivity, null, 0, android.R.style.Widget_DeviceDefault_Light_TextView);
+
+        new TextView(mActivity, null, 0, android.R.style.Widget_Material_TextView);
+
+        new TextView(mActivity, null, 0, android.R.style.Widget_Material_Light_TextView);
     }
 
     @UiThreadTest
@@ -264,7 +280,7 @@
         assertSame(movementMethod, mTextView.getMovementMethod());
         assertEquals(selectionStart, Selection.getSelectionStart(mTextView.getText()));
         assertEquals(selectionEnd, Selection.getSelectionEnd(mTextView.getText()));
-        sendKeys(KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.KEYCODE_ALT_LEFT,
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.KEYCODE_ALT_LEFT,
                 KeyEvent.KEYCODE_DPAD_UP);
         // the selection has been removed.
         assertEquals(selectionStart, Selection.getSelectionStart(mTextView.getText()));
@@ -283,7 +299,7 @@
         assertNull(mTextView.getMovementMethod());
         assertEquals(selectionStart, Selection.getSelectionStart(mTextView.getText()));
         assertEquals(selectionEnd, Selection.getSelectionEnd(mTextView.getText()));
-        sendKeys(KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.KEYCODE_ALT_LEFT,
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.KEYCODE_ALT_LEFT,
                 KeyEvent.KEYCODE_DPAD_UP);
         // the selection will not be changed.
         assertEquals(selectionStart, Selection.getSelectionStart(mTextView.getText()));
@@ -470,38 +486,78 @@
         }
     }
 
-    public void testSetHighlightColor() {
-        mTextView = new TextView(mActivity);
+    public void testAccessHighlightColor() {
+        final TextView textView = (TextView) mActivity.findViewById(R.id.textview_text);
 
-        mTextView.setHighlightColor(0x00ff00ff);
+        mActivity.runOnUiThread(() -> {
+            textView.setTextIsSelectable(true);
+            textView.setText("abcd", BufferType.EDITABLE);
+            textView.setHighlightColor(Color.BLUE);
+        });
+        mInstrumentation.waitForIdleSync();
+
+        assertTrue(textView.isTextSelectable());
+        assertEquals(Color.BLUE, textView.getHighlightColor());
+
+        // Long click on the text selects all text and shows selection handlers. The view has an
+        // attribute layout_width="wrap_content", so clicked location (the center of the view)
+        // should be on the text.
+        TouchUtils.longClickView(this, textView);
+
+        // At this point the entire content of our TextView should be selected and highlighted
+        // with blue. Now change the highlight to red while the selection is still on.
+        mActivity.runOnUiThread(() -> textView.setHighlightColor(Color.RED));
+        mInstrumentation.waitForIdleSync();
+
+        assertEquals(Color.RED, textView.getHighlightColor());
+        assertTrue(TextUtils.equals("abcd", textView.getText()));
+
+        // Remove the selection
+        mActivity.runOnUiThread(() -> Selection.removeSelection((Spannable) textView.getText()));
+        mInstrumentation.waitForIdleSync();
+
+        // And switch highlight to green after the selection has been removed
+        mActivity.runOnUiThread(() -> textView.setHighlightColor(Color.GREEN));
+        mInstrumentation.waitForIdleSync();
+
+        assertEquals(Color.GREEN, textView.getHighlightColor());
+        assertTrue(TextUtils.equals("abcd", textView.getText()));
     }
 
+    @MediumTest
     public void testSetShadowLayer() {
-        MockTextView textView = new MockTextView(mActivity);
+        // test values
+        final MockTextView mockTextView = new MockTextView(mActivity);
+
+        mockTextView.setShadowLayer(1.0f, 0.3f, 0.4f, Color.CYAN);
+        assertEquals(Color.CYAN, mockTextView.getShadowColor());
+        assertEquals(0.3f, mockTextView.getShadowDx());
+        assertEquals(0.4f, mockTextView.getShadowDy());
+        assertEquals(1.0f, mockTextView.getShadowRadius());
 
         // shadow is placed to the left and below the text
-        textView.setShadowLayer(1.0f, 0.3f, 0.3f, Color.CYAN);
-        assertTrue(textView.isPaddingOffsetRequired());
-        assertEquals(0, textView.getLeftPaddingOffset());
-        assertEquals(0, textView.getTopPaddingOffset());
-        assertEquals(1, textView.getRightPaddingOffset());
-        assertEquals(1, textView.getBottomPaddingOffset());
+        mockTextView.setShadowLayer(1.0f, 0.3f, 0.3f, Color.CYAN);
+        assertTrue(mockTextView.isPaddingOffsetRequired());
+        assertEquals(0, mockTextView.getLeftPaddingOffset());
+        assertEquals(0, mockTextView.getTopPaddingOffset());
+        assertEquals(1, mockTextView.getRightPaddingOffset());
+        assertEquals(1, mockTextView.getBottomPaddingOffset());
 
         // shadow is placed to the right and above the text
-        textView.setShadowLayer(1.0f, -0.8f, -0.8f, Color.CYAN);
-        assertTrue(textView.isPaddingOffsetRequired());
-        assertEquals(-1, textView.getLeftPaddingOffset());
-        assertEquals(-1, textView.getTopPaddingOffset());
-        assertEquals(0, textView.getRightPaddingOffset());
-        assertEquals(0, textView.getBottomPaddingOffset());
+        mockTextView.setShadowLayer(1.0f, -0.8f, -0.8f, Color.CYAN);
+        assertTrue(mockTextView.isPaddingOffsetRequired());
+        assertEquals(-1, mockTextView.getLeftPaddingOffset());
+        assertEquals(-1, mockTextView.getTopPaddingOffset());
+        assertEquals(0, mockTextView.getRightPaddingOffset());
+        assertEquals(0, mockTextView.getBottomPaddingOffset());
 
         // no shadow
-        textView.setShadowLayer(0.0f, 0.0f, 0.0f, Color.CYAN);
-        assertFalse(textView.isPaddingOffsetRequired());
-        assertEquals(0, textView.getLeftPaddingOffset());
-        assertEquals(0, textView.getTopPaddingOffset());
-        assertEquals(0, textView.getRightPaddingOffset());
-        assertEquals(0, textView.getBottomPaddingOffset());
+        mockTextView.setShadowLayer(0.0f, 0.0f, 0.0f, Color.CYAN);
+        assertFalse(mockTextView.isPaddingOffsetRequired());
+        assertEquals(0, mockTextView.getLeftPaddingOffset());
+        assertEquals(0, mockTextView.getTopPaddingOffset());
+        assertEquals(0, mockTextView.getRightPaddingOffset());
+        assertEquals(0, mockTextView.getBottomPaddingOffset());
     }
 
     @UiThreadTest
@@ -675,114 +731,199 @@
                 mTextView.getPaintFlags());
     }
 
-    public void testHeightAndWidth() {
+    @MediumTest
+    public void testHeight() {
         mTextView = findTextView(R.id.textview_text);
-        int originalWidth = mTextView.getWidth();
-        setWidth(mTextView.getWidth() >> 3);
-        int originalHeight = mTextView.getHeight();
+        final int originalHeight = mTextView.getHeight();
 
-        setMaxHeight(originalHeight + 1);
+        // test setMaxHeight
+        int newHeight = originalHeight + 1;
+        setMaxHeight(newHeight);
         assertEquals(originalHeight, mTextView.getHeight());
+        assertEquals(newHeight, mTextView.getMaxHeight());
 
-        setMaxHeight(originalHeight - 1);
-        assertEquals(originalHeight - 1, mTextView.getHeight());
+        newHeight = originalHeight - 1;
+        setMaxHeight(newHeight);
+        assertEquals(newHeight, mTextView.getHeight());
+        assertEquals(newHeight, mTextView.getMaxHeight());
 
-        setMaxHeight(-1);
+        newHeight = -1;
+        setMaxHeight(newHeight);
         assertEquals(0, mTextView.getHeight());
+        assertEquals(newHeight, mTextView.getMaxHeight());
 
-        setMaxHeight(Integer.MAX_VALUE);
+        newHeight = Integer.MAX_VALUE;
+        setMaxHeight(newHeight);
         assertEquals(originalHeight, mTextView.getHeight());
+        assertEquals(newHeight, mTextView.getMaxHeight());
 
-        setMinHeight(originalHeight + 1);
-        assertEquals(originalHeight + 1, mTextView.getHeight());
+        // test setMinHeight
+        newHeight = originalHeight + 1;
+        setMinHeight(newHeight);
+        assertEquals(newHeight, mTextView.getHeight());
+        assertEquals(newHeight, mTextView.getMinHeight());
 
-        setMinHeight(originalHeight - 1);
+        newHeight = originalHeight - 1;
+        setMinHeight(newHeight);
         assertEquals(originalHeight, mTextView.getHeight());
+        assertEquals(newHeight, mTextView.getMinHeight());
 
-        setMinHeight(-1);
+        newHeight = -1;
+        setMinHeight(newHeight);
         assertEquals(originalHeight, mTextView.getHeight());
+        assertEquals(newHeight, mTextView.getMinHeight());
 
+        // reset min and max height
         setMinHeight(0);
         setMaxHeight(Integer.MAX_VALUE);
 
-        setHeight(originalHeight + 1);
-        assertEquals(originalHeight + 1, mTextView.getHeight());
+        // test setHeight
+        newHeight = originalHeight + 1;
+        setHeight(newHeight);
+        assertEquals(newHeight, mTextView.getHeight());
+        assertEquals(newHeight, mTextView.getMaxHeight());
+        assertEquals(newHeight, mTextView.getMinHeight());
 
-        setHeight(originalHeight - 1);
-        assertEquals(originalHeight - 1, mTextView.getHeight());
+        newHeight = originalHeight - 1;
+        setHeight(newHeight);
+        assertEquals(newHeight, mTextView.getHeight());
+        assertEquals(newHeight, mTextView.getMaxHeight());
+        assertEquals(newHeight, mTextView.getMinHeight());
 
-        setHeight(-1);
+        newHeight = -1;
+        setHeight(newHeight);
         assertEquals(0, mTextView.getHeight());
+        assertEquals(newHeight, mTextView.getMaxHeight());
+        assertEquals(newHeight, mTextView.getMinHeight());
 
         setHeight(originalHeight);
         assertEquals(originalHeight, mTextView.getHeight());
+        assertEquals(originalHeight, mTextView.getMaxHeight());
+        assertEquals(originalHeight, mTextView.getMinHeight());
 
-        assertEquals(originalWidth >> 3, mTextView.getWidth());
+        // setting max/min lines should cause getMaxHeight/getMinHeight to return -1
+        setMaxLines(2);
+        assertEquals("Setting maxLines should return -1 fir maxHeight",
+                -1, mTextView.getMaxHeight());
 
-        // Min Width
-        setMinWidth(originalWidth + 1);
-        assertEquals(1, mTextView.getLineCount());
-        assertEquals(originalWidth + 1, mTextView.getWidth());
-
-        setMinWidth(originalWidth - 1);
-        assertEquals(2, mTextView.getLineCount());
-        assertEquals(originalWidth - 1, mTextView.getWidth());
-
-        // Width
-        setWidth(originalWidth + 1);
-        assertEquals(1, mTextView.getLineCount());
-        assertEquals(originalWidth + 1, mTextView.getWidth());
-
-        setWidth(originalWidth - 1);
-        assertEquals(2, mTextView.getLineCount());
-        assertEquals(originalWidth - 1, mTextView.getWidth());
+        setMinLines(1);
+        assertEquals("Setting minLines should return -1 for minHeight",
+                -1, mTextView.getMinHeight());
     }
 
+    @MediumTest
+    public void testWidth() {
+        mTextView = findTextView(R.id.textview_text);
+        int originalWidth = mTextView.getWidth();
+
+        int newWidth = mTextView.getWidth() / 8;
+        setWidth(newWidth);
+        assertEquals(newWidth, mTextView.getWidth());
+        assertEquals(newWidth, mTextView.getMaxWidth());
+        assertEquals(newWidth, mTextView.getMinWidth());
+
+        // Min Width
+        newWidth = originalWidth + 1;
+        setMinWidth(newWidth);
+        assertEquals(1, mTextView.getLineCount());
+        assertEquals(newWidth, mTextView.getWidth());
+        assertEquals(newWidth, mTextView.getMinWidth());
+
+        newWidth = originalWidth - 1;
+        setMinWidth(originalWidth - 1);
+        assertEquals(2, mTextView.getLineCount());
+        assertEquals(newWidth, mTextView.getWidth());
+        assertEquals(newWidth, mTextView.getMinWidth());
+
+        // Width
+        newWidth = originalWidth + 1;
+        setWidth(newWidth);
+        assertEquals(1, mTextView.getLineCount());
+        assertEquals(newWidth, mTextView.getWidth());
+        assertEquals(newWidth, mTextView.getMaxWidth());
+        assertEquals(newWidth, mTextView.getMinWidth());
+
+        newWidth = originalWidth - 1;
+        setWidth(newWidth);
+        assertEquals(2, mTextView.getLineCount());
+        assertEquals(newWidth, mTextView.getWidth());
+        assertEquals(newWidth, mTextView.getMaxWidth());
+        assertEquals(newWidth, mTextView.getMinWidth());
+
+        // setting ems should cause getMaxWidth/getMinWidth to return -1
+        setEms(1);
+        assertEquals("Setting ems should return -1 for maxWidth", -1, mTextView.getMaxWidth());
+        assertEquals("Setting ems should return -1 for maxWidth", -1, mTextView.getMinWidth());
+    }
+
+    @MediumTest
     public void testSetMinEms() {
         mTextView = findTextView(R.id.textview_text);
         assertEquals(1, mTextView.getLineCount());
 
-        int originalWidth = mTextView.getWidth();
-        int originalEms = originalWidth / mTextView.getLineHeight();
+        final int originalWidth = mTextView.getWidth();
+        final int originalEms = originalWidth / mTextView.getLineHeight();
 
         setMinEms(originalEms + 1);
         assertEquals((originalEms + 1) * mTextView.getLineHeight(), mTextView.getWidth());
+        assertEquals(-1, mTextView.getMinWidth());
+        assertEquals(originalEms + 1, mTextView.getMinEms());
 
         setMinEms(originalEms - 1);
         assertEquals(originalWidth, mTextView.getWidth());
+        assertEquals(-1, mTextView.getMinWidth());
+        assertEquals(originalEms - 1, mTextView.getMinEms());
+
+        setMinWidth(1);
+        assertEquals(-1, mTextView.getMinEms());
     }
 
+    @MediumTest
     public void testSetMaxEms() {
         mTextView = findTextView(R.id.textview_text);
         assertEquals(1, mTextView.getLineCount());
-        int originalWidth = mTextView.getWidth();
-        int originalEms = originalWidth / mTextView.getLineHeight();
+
+        final int originalWidth = mTextView.getWidth();
+        final int originalEms = originalWidth / mTextView.getLineHeight();
 
         setMaxEms(originalEms + 1);
         assertEquals(1, mTextView.getLineCount());
         assertEquals(originalWidth, mTextView.getWidth());
+        assertEquals(-1, mTextView.getMaxWidth());
+        assertEquals(originalEms + 1, mTextView.getMaxEms());
 
         setMaxEms(originalEms - 1);
         assertTrue(1 < mTextView.getLineCount());
-        assertEquals((originalEms - 1) * mTextView.getLineHeight(),
-                mTextView.getWidth());
+        assertEquals((originalEms - 1) * mTextView.getLineHeight(), mTextView.getWidth());
+        assertEquals(-1, mTextView.getMaxWidth());
+        assertEquals(originalEms - 1, mTextView.getMaxEms());
+
+        setMaxWidth(originalWidth);
+        assertEquals(-1, mTextView.getMaxEms());
     }
 
+    @MediumTest
     public void testSetEms() {
         mTextView = findTextView(R.id.textview_text);
         assertEquals("check height", 1, mTextView.getLineCount());
-        int originalWidth = mTextView.getWidth();
-        int originalEms = originalWidth / mTextView.getLineHeight();
+        final int originalWidth = mTextView.getWidth();
+        final int originalEms = originalWidth / mTextView.getLineHeight();
 
         setEms(originalEms + 1);
         assertEquals(1, mTextView.getLineCount());
-        assertEquals((originalEms + 1) * mTextView.getLineHeight(),
-                mTextView.getWidth());
+        assertEquals((originalEms + 1) * mTextView.getLineHeight(), mTextView.getWidth());
+        assertEquals(-1, mTextView.getMinWidth());
+        assertEquals(-1, mTextView.getMaxWidth());
+        assertEquals(originalEms + 1, mTextView.getMinEms());
+        assertEquals(originalEms + 1, mTextView.getMaxEms());
 
         setEms(originalEms - 1);
         assertTrue((1 < mTextView.getLineCount()));
-        assertEquals((originalEms - 1) * mTextView.getLineHeight(),
-                mTextView.getWidth());
+        assertEquals((originalEms - 1) * mTextView.getLineHeight(), mTextView.getWidth());
+        assertEquals(-1, mTextView.getMinWidth());
+        assertEquals(-1, mTextView.getMaxWidth());
+        assertEquals(originalEms - 1, mTextView.getMinEms());
+        assertEquals(originalEms - 1, mTextView.getMaxEms());
     }
 
     public void testSetLineSpacing() {
@@ -949,31 +1090,30 @@
     public void testSetEditableFactory() {
         mTextView = new TextView(mActivity);
         String text = "sample";
-        MockEditableFactory factory = new MockEditableFactory();
-        mTextView.setEditableFactory(factory);
 
-        factory.reset();
+        final Editable.Factory mockEditableFactory = spy(new Editable.Factory());
+        doCallRealMethod().when(mockEditableFactory).newEditable(any(CharSequence.class));
+        mTextView.setEditableFactory(mockEditableFactory);
+
         mTextView.setText(text);
-        assertFalse(factory.hasCalledNewEditable());
+        verify(mockEditableFactory, never()).newEditable(any(CharSequence.class));
 
-        factory.reset();
+        reset(mockEditableFactory);
         mTextView.setText(text, BufferType.SPANNABLE);
-        assertFalse(factory.hasCalledNewEditable());
+        verify(mockEditableFactory, never()).newEditable(any(CharSequence.class));
 
-        factory.reset();
+        reset(mockEditableFactory);
         mTextView.setText(text, BufferType.NORMAL);
-        assertFalse(factory.hasCalledNewEditable());
+        verify(mockEditableFactory, never()).newEditable(any(CharSequence.class));
 
-        factory.reset();
+        reset(mockEditableFactory);
         mTextView.setText(text, BufferType.EDITABLE);
-        assertTrue(factory.hasCalledNewEditable());
-        assertEquals(text, factory.getSource());
+        verify(mockEditableFactory, times(1)).newEditable(text);
 
         mTextView.setKeyListener(DigitsKeyListener.getInstance());
-        factory.reset();
+        reset(mockEditableFactory);
         mTextView.setText(text, BufferType.EDITABLE);
-        assertTrue(factory.hasCalledNewEditable());
-        assertEquals(text, factory.getSource());
+        verify(mockEditableFactory, times(1)).newEditable(text);
 
         try {
             mTextView.setEditableFactory(null);
@@ -985,31 +1125,30 @@
     public void testSetSpannableFactory() {
         mTextView = new TextView(mActivity);
         String text = "sample";
-        MockSpannableFactory factory = new MockSpannableFactory();
-        mTextView.setSpannableFactory(factory);
 
-        factory.reset();
+        final Spannable.Factory mockSpannableFactory = spy(new Spannable.Factory());
+        doCallRealMethod().when(mockSpannableFactory).newSpannable(any(CharSequence.class));
+        mTextView.setSpannableFactory(mockSpannableFactory);
+
         mTextView.setText(text);
-        assertFalse(factory.hasCalledNewSpannable());
+        verify(mockSpannableFactory, never()).newSpannable(any(CharSequence.class));
 
-        factory.reset();
+        reset(mockSpannableFactory);
         mTextView.setText(text, BufferType.EDITABLE);
-        assertFalse(factory.hasCalledNewSpannable());
+        verify(mockSpannableFactory, never()).newSpannable(any(CharSequence.class));
 
-        factory.reset();
+        reset(mockSpannableFactory);
         mTextView.setText(text, BufferType.NORMAL);
-        assertFalse(factory.hasCalledNewSpannable());
+        verify(mockSpannableFactory, never()).newSpannable(any(CharSequence.class));
 
-        factory.reset();
+        reset(mockSpannableFactory);
         mTextView.setText(text, BufferType.SPANNABLE);
-        assertTrue(factory.hasCalledNewSpannable());
-        assertEquals(text, factory.getSource());
+        verify(mockSpannableFactory, times(1)).newSpannable(text);
 
         mTextView.setMovementMethod(LinkMovementMethod.getInstance());
-        factory.reset();
+        reset(mockSpannableFactory);
         mTextView.setText(text, BufferType.NORMAL);
-        assertTrue(factory.hasCalledNewSpannable());
-        assertEquals(text, factory.getSource());
+        verify(mockSpannableFactory, times(1)).newSpannable(text);
 
         try {
             mTextView.setSpannableFactory(null);
@@ -1374,29 +1513,25 @@
     public void testRemoveSelectionWithSelectionHandles() {
         initTextViewForTyping();
 
-        mActivity.runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mTextView.setTextIsSelectable(true);
-                mTextView.setText("abcd", BufferType.EDITABLE);
-            }
+        assertFalse(mTextView.isTextSelectable());
+        mActivity.runOnUiThread(() -> {
+            mTextView.setTextIsSelectable(true);
+            mTextView.setText("abcd", BufferType.EDITABLE);
         });
         mInstrumentation.waitForIdleSync();
+        assertTrue(mTextView.isTextSelectable());
 
         // Long click on the text selects all text and shows selection handlers. The view has an
         // attribute layout_width="wrap_content", so clicked location (the center of the view)
         // should be on the text.
         TouchUtils.longClickView(this, mTextView);
 
-        mActivity.runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                Selection.removeSelection((Spannable) mTextView.getText());
-            }
-        });
+        mActivity.runOnUiThread(() -> Selection.removeSelection((Spannable) mTextView.getText()));
 
         // Make sure that a crash doesn't happen with {@link Selection#removeSelection}.
         mInstrumentation.waitForIdleSync();
+
+        assertTrue(TextUtils.equals("abcd", mTextView.getText()));
     }
 
     public void testUndo_insert() {
@@ -1838,7 +1973,7 @@
         initTextViewForTyping();
 
         // Type "abc".
-        mInstrumentation.sendStringSync("abc");
+        mKeyEventUtil.sendString(mTextView, "abc");
         mActivity.runOnUiThread(new Runnable() {
             public void run() {
                 // Select "bc"
@@ -1847,7 +1982,7 @@
         });
         mInstrumentation.waitForIdleSync();
         // Copy "bc"
-        sendKeys(KeyEvent.KEYCODE_COPY);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_COPY);
 
         mActivity.runOnUiThread(new Runnable() {
             public void run() {
@@ -1857,7 +1992,7 @@
         });
         mInstrumentation.waitForIdleSync();
         // Paste "bc"
-        sendKeys(KeyEvent.KEYCODE_PASTE);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_PASTE);
         assertEquals("abbcc", mTextView.getText().toString());
 
         mActivity.runOnUiThread(new Runnable() {
@@ -1922,7 +2057,7 @@
         initTextViewForTyping();
 
         // Type "abc".
-        mInstrumentation.sendStringSync("abc");
+        mKeyEventUtil.sendString(mTextView, "abc");
         mActivity.runOnUiThread(new Runnable() {
             public void run() {
                 // Select "bc"
@@ -1931,7 +2066,7 @@
         });
         mInstrumentation.waitForIdleSync();
         // Cut "bc"
-        sendKeys(KeyEvent.KEYCODE_CUT);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_CUT);
 
         mActivity.runOnUiThread(new Runnable() {
             public void run() {
@@ -1942,7 +2077,7 @@
         });
         mInstrumentation.waitForIdleSync();
         // Paste "bc"
-        sendKeys(KeyEvent.KEYCODE_PASTE);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_PASTE);
         assertEquals("bca", mTextView.getText().toString());
 
         mActivity.runOnUiThread(new Runnable() {
@@ -2223,7 +2358,7 @@
 
         assertEquals(errorText, mTextView.getError().toString());
 
-        mInstrumentation.sendStringSync("a");
+        mKeyEventUtil.sendString(mTextView, "a");
         // a key event that will not change the TextView's text
         assertEquals("", mTextView.getText().toString());
         // The icon and error message will not be reset to null
@@ -2239,7 +2374,7 @@
         });
         mInstrumentation.waitForIdleSync();
 
-        mInstrumentation.sendStringSync("1");
+        mKeyEventUtil.sendString(mTextView, "1");
         // a key event cause changes to the TextView's text
         assertEquals("1", mTextView.getText().toString());
         // the error message and icon will be cleared.
@@ -2265,13 +2400,13 @@
 
         assertSame(expected, mTextView.getFilters());
 
-        mInstrumentation.sendStringSync("a");
+        mKeyEventUtil.sendString(mTextView, "a");
         // the text is capitalized by InputFilter.AllCaps
         assertEquals("A", mTextView.getText().toString());
-        mInstrumentation.sendStringSync("b");
+        mKeyEventUtil.sendString(mTextView, "b");
         // the text is capitalized by InputFilter.AllCaps
         assertEquals("AB", mTextView.getText().toString());
-        mInstrumentation.sendStringSync("c");
+        mKeyEventUtil.sendString(mTextView, "c");
         // 'C' could not be accepted, because there is a length filter.
         assertEquals("AB", mTextView.getText().toString());
 
@@ -2468,11 +2603,11 @@
     public void testPressKey() {
         initTextViewForTyping();
 
-        mInstrumentation.sendStringSync("a");
+        mKeyEventUtil.sendString(mTextView, "a");
         assertEquals("a", mTextView.getText().toString());
-        mInstrumentation.sendStringSync("b");
+        mKeyEventUtil.sendString(mTextView, "b");
         assertEquals("ab", mTextView.getText().toString());
-        sendKeys(KeyEvent.KEYCODE_DEL);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_DEL);
         assertEquals("a", mTextView.getText().toString());
     }
 
@@ -2557,6 +2692,53 @@
         assertTrue(mTextView.hasSelection());
     }
 
+    @MediumTest
+    public void testOnSelectionChanged_isTriggeredWhenSelectionChanges() {
+        final MockTextView textView = new MockTextView(mActivity);
+        final String text = "any text";
+        textView.setText(text, BufferType.SPANNABLE);
+
+        // assert that there is currently no selection
+        assertFalse(textView.hasSelection());
+
+        // select all
+        Selection.selectAll((Spannable) textView.getText());
+
+        assertTrue("After selectAll OnSelectionChanged should have been called",
+                textView.hasCalledOnSelectionChanged());
+        assertEquals("OnSelectionChanged should have been called with 0 for selection start",
+                0, textView.getSelectionChangedStart());
+        assertEquals("OnSelectionChanged should have been called with text length for "
+                        + "selection end",
+                text.length(), textView.getSelectionChangedEnd());
+
+        // reset MockTextView selection flags
+        textView.reset();
+
+        // change selection
+        Selection.setSelection((Spannable) textView.getText(), 1, 5);
+
+        assertTrue("OnSelectionChanged should have been called",
+                textView.hasCalledOnSelectionChanged());
+        assertEquals("OnSelectionChanged should have been called with 1 for selection start",
+                1, textView.getSelectionChangedStart());
+        assertEquals("OnSelectionChanged should have been called with -1 for selection end",
+                5, textView.getSelectionChangedEnd());
+
+        // reset MockTextView selection flags
+        textView.reset();
+
+        // clear selection
+        Selection.removeSelection((Spannable) textView.getText());
+
+        assertTrue("OnSelectionChanged should have been called",
+                textView.hasCalledOnSelectionChanged());
+        assertEquals("OnSelectionChanged should have been called with -1 for selection start",
+                -1, textView.getSelectionChangedStart());
+        assertEquals("OnSelectionChanged should have been called with -1 for selection end",
+                -1, textView.getSelectionChangedEnd());
+    }
+
     @UiThreadTest
     public void testAccessEllipsize() {
         mActivity.setContentView(R.layout.textview_ellipsize);
@@ -2671,11 +2853,61 @@
         }
     }
 
-    public void testSetCursorVisible() {
+    public void testTextViewInWeigthenedLayoutChangesWidthAfterSetText() {
+        final TextView textView = new TextView(getActivity());
+        textView.setEllipsize(TruncateAt.END);
+        textView.setSingleLine(true);
+        textView.setText("a");
+
+        TextView otherTextView = new TextView(getActivity());
+        otherTextView.setSingleLine(true);
+        otherTextView.setText("any");
+
+        final LinearLayout layout = new LinearLayout(mActivity);
+        layout.setOrientation(LinearLayout.HORIZONTAL);
+
+        // TextView under test has weight 1, and width 0
+        layout.addView(textView, new LinearLayout.LayoutParams(0,
+                ViewGroup.LayoutParams.WRAP_CONTENT, 1.0f));
+
+        // other TextView has default weight
+        layout.addView(otherTextView, new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT));
+
+        // main layout params
+        layout.setLayoutParams(new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+
+        mActivity.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                getActivity().setContentView(layout);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+
+        int oldWidth = textView.getWidth();
+
+        mActivity.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                textView.setText("aaa");
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+
+        assertTrue("TextView should have larger width after a longer text is set",
+                textView.getWidth() > oldWidth);
+    }
+
+    public void testAccessCursorVisible() {
         mTextView = new TextView(mActivity);
 
         mTextView.setCursorVisible(true);
+        assertTrue(mTextView.isCursorVisible());
         mTextView.setCursorVisible(false);
+        assertFalse(mTextView.isCursorVisible());
     }
 
     public void testOnWindowFocusChanged() {
@@ -2702,27 +2934,39 @@
     public void testPerformLongClick() {
         mTextView = findTextView(R.id.textview_text);
         mTextView.setText("This is content");
-        MockOnLongClickListener onLongClickListener = new MockOnLongClickListener(true);
-        MockOnCreateContextMenuListener onCreateContextMenuListener
-                = new MockOnCreateContextMenuListener(false);
-        mTextView.setOnLongClickListener(onLongClickListener);
-        mTextView.setOnCreateContextMenuListener(onCreateContextMenuListener);
-        assertTrue(mTextView.performLongClick());
-        assertTrue(onLongClickListener.hasLongClicked());
-        assertFalse(onCreateContextMenuListener.hasCreatedContextMenu());
 
-        onLongClickListener = new MockOnLongClickListener(false);
-        mTextView.setOnLongClickListener(onLongClickListener);
-        mTextView.setOnCreateContextMenuListener(onCreateContextMenuListener);
-        assertTrue(mTextView.performLongClick());
-        assertTrue(onLongClickListener.hasLongClicked());
-        assertTrue(onCreateContextMenuListener.hasCreatedContextMenu());
+        View.OnLongClickListener mockOnLongClickListener = mock(View.OnLongClickListener.class);
+        when(mockOnLongClickListener.onLongClick(any(View.class))).thenReturn(Boolean.TRUE);
 
+        View.OnCreateContextMenuListener mockOnCreateContextMenuListener =
+                mock(View.OnCreateContextMenuListener.class);
+        doAnswer((InvocationOnMock invocation) -> {
+            ((ContextMenu) invocation.getArguments() [0]).add("menu item");
+            return null;
+        }).when(mockOnCreateContextMenuListener).onCreateContextMenu(
+                any(ContextMenu.class), any(View.class), any(ContextMenuInfo.class));
+
+        mTextView.setOnLongClickListener(mockOnLongClickListener);
+        mTextView.setOnCreateContextMenuListener(mockOnCreateContextMenuListener);
+        assertTrue(mTextView.performLongClick());
+        verify(mockOnLongClickListener, times(1)).onLongClick(mTextView);
+        verifyZeroInteractions(mockOnCreateContextMenuListener);
+
+        reset(mockOnLongClickListener);
+        when(mockOnLongClickListener.onLongClick(any(View.class))).thenReturn(Boolean.FALSE);
+        assertTrue(mTextView.performLongClick());
+        verify(mockOnLongClickListener, times(1)).onLongClick(mTextView);
+        verify(mockOnCreateContextMenuListener, times(1)).onCreateContextMenu(
+                any(ContextMenu.class), eq(mTextView), any(ContextMenuInfo.class));
+
+        reset(mockOnCreateContextMenuListener);
         mTextView.setOnLongClickListener(null);
-        onCreateContextMenuListener = new MockOnCreateContextMenuListener(true);
-        mTextView.setOnCreateContextMenuListener(onCreateContextMenuListener);
+        doNothing().when(mockOnCreateContextMenuListener).onCreateContextMenu(
+                any(ContextMenu.class), any(View.class), any(ContextMenuInfo.class));
         assertFalse(mTextView.performLongClick());
-        assertTrue(onCreateContextMenuListener.hasCreatedContextMenu());
+        verifyNoMoreInteractions(mockOnLongClickListener);
+        verify(mockOnCreateContextMenuListener, times(1)).onCreateContextMenu(
+                any(ContextMenu.class), eq(mTextView), any(ContextMenuInfo.class));
     }
 
     @UiThreadTest
@@ -2952,6 +3196,286 @@
                 urlSpans[0].getURL(), "http://android.com/textview");
     }
 
+    @MediumTest
+    public void testGetLetterSpacing_returnsValueThatWasSet() {
+        mTextView = new TextView(mActivity);
+        mTextView.setLetterSpacing(2f);
+        assertEquals("getLetterSpacing should return the value that was set",
+                2f, mTextView.getLetterSpacing());
+    }
+
+    @MediumTest
+    public void testSetLetterSpacing_changesTextWidth() {
+        final TextView textView = new TextView(mActivity);
+        textView.setText("aa");
+        textView.setLetterSpacing(0f);
+        textView.setTextSize(8f);
+
+        final FrameLayout layout = new FrameLayout(mActivity);
+        final ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.WRAP_CONTENT,
+                ViewGroup.LayoutParams.MATCH_PARENT);
+        layout.addView(textView, layoutParams);
+        layout.setLayoutParams(layoutParams);
+
+        mActivity.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                getActivity().setContentView(layout);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+
+        // measure text with zero letter spacing
+        final float zeroSpacing = textView.getLayout().getLineWidth(0);
+
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                textView.setLetterSpacing(1f);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+
+        // measure text with single letter spacing
+        final float singleSpacing = textView.getLayout().getLineWidth(0);
+
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                textView.setLetterSpacing(2f);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+
+        // measure text with double letter spacing
+        final float doubleSpacing = textView.getLayout().getLineWidth(0);
+
+        assertEquals("Double spacing should have two times the spacing of single spacing",
+                doubleSpacing - zeroSpacing, 2f * (singleSpacing - zeroSpacing), 1f);
+    }
+
+    @MediumTest
+    public void testGetFontFeatureSettings_returnsValueThatWasSet() {
+        mTextView = new TextView(mActivity);
+        mTextView.setFontFeatureSettings("\"smcp\" on");
+        assertEquals("getFontFeatureSettings should return the value that was set",
+                "\"smcp\" on", mTextView.getFontFeatureSettings());
+    }
+
+    @MediumTest
+    public void testGetOffsetForPosition_singleLineLtr() {
+        // asserts getOffsetPosition returns correct values for a single line LTR text
+        String text = "aaaaa";
+        final TextView textView = new TextView(mActivity);
+        textView.setText(text);
+        textView.setTextSize(8f);
+        textView.setSingleLine(true);
+
+        // add a compound drawable to TextView to make offset calculation more interesting
+        final Drawable drawable = getDrawable(R.drawable.red);
+        drawable.setBounds(0, 0, 10, 10);
+        textView.setCompoundDrawables(drawable, drawable, drawable, drawable);
+
+        final FrameLayout layout = new FrameLayout(mActivity);
+        final ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT);
+        layout.addView(textView, layoutParams);
+        layout.setLayoutParams(layoutParams);
+
+        mActivity.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                getActivity().setContentView(layout);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+
+        final int firstOffset = 0;
+        final int lastOffset = text.length() - 1;
+        final int midOffset = text.length() / 2;
+
+        // left edge of view
+        float x = 0f;
+        float y = textView.getHeight() / 2f;
+        assertEquals(firstOffset, textView.getOffsetForPosition(x, y));
+
+        // right edge of text
+        x = textView.getLayout().getLineWidth(0) - 1f;
+        assertEquals(lastOffset, textView.getOffsetForPosition(x, y));
+
+        // right edge of view
+        x = textView.getWidth();
+        assertEquals(lastOffset + 1, textView.getOffsetForPosition(x, y));
+
+        // left edge of view - out of bounds
+        x = -1f;
+        assertEquals(firstOffset, textView.getOffsetForPosition(x, y));
+
+        // horizontal center of text
+        x = textView.getLayout().getLineWidth(0) / 2f - 1f;
+        assertEquals(midOffset, textView.getOffsetForPosition(x, y));
+    }
+
+    @MediumTest
+    public void testGetOffsetForPosition_multiLineLtr() {
+        final String line = "aa\n";
+        final String threeLines = line + line + line;
+        final TextView textView = new TextView(mActivity);
+        textView.setText(threeLines);
+        textView.setTextSize(8f);
+        textView.setLines(2);
+
+        // add a compound drawable to TextView to make offset calculation more interesting
+        final Drawable drawable = getDrawable(R.drawable.red);
+        drawable.setBounds(0, 0, 10, 10);
+        textView.setCompoundDrawables(drawable, drawable, drawable, drawable);
+
+        final FrameLayout layout = new FrameLayout(mActivity);
+        final ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT);
+        layout.addView(textView, layoutParams);
+        layout.setLayoutParams(layoutParams);
+
+        mActivity.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                getActivity().setContentView(layout);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+
+        final Rect lineBounds = new Rect();
+        textView.getLayout().getLineBounds(0, lineBounds);
+
+        // left edge of view at first line
+        float x = 0f;
+        float y = lineBounds.height() / 2f;
+        assertEquals(0, textView.getOffsetForPosition(x, y));
+
+        // right edge of view at first line
+        x = textView.getWidth() - 1f;
+        assertEquals(line.length() - 1, textView.getOffsetForPosition(x, y));
+
+        // update lineBounds to be the second line
+        textView.getLayout().getLineBounds(1, lineBounds);
+        y = lineBounds.top + lineBounds.height() / 2;
+
+        // left edge of view at second line
+        x = 0f;
+        assertEquals(line.length(), textView.getOffsetForPosition(x, y));
+
+        // right edge of text at second line
+        x = textView.getLayout().getLineWidth(1) - 1f;
+        assertEquals(line.length() + line.length() - 1, textView.getOffsetForPosition(x, y));
+
+        // right edge of view at second line
+        x = textView.getWidth() - 1f;
+        assertEquals(line.length() + line.length() - 1, textView.getOffsetForPosition(x, y));
+
+        // horizontal center of text at second line
+        x = textView.getLayout().getLineWidth(1) / 2f;
+        assertEquals(line.length() + line.length() / 2, textView.getOffsetForPosition(x, y));
+    }
+
+    @MediumTest
+    public void testGetOffsetForPosition_multiLineRtl() {
+        final String line = "\u0635\u0635\n";
+        final String threeLines = line + line + line;
+        final TextView textView = new TextView(mActivity);
+        textView.setText(threeLines);
+        textView.setTextSize(8f);
+        textView.setLines(2);
+
+        // add a compound drawable to TextView to make offset calculation more interesting
+        final Drawable drawable = getDrawable(R.drawable.red);
+        drawable.setBounds(0, 0, 10, 10);
+        textView.setCompoundDrawables(drawable, drawable, drawable, drawable);
+
+        final FrameLayout layout = new FrameLayout(mActivity);
+        final ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT);
+        layout.addView(textView, layoutParams);
+        layout.setLayoutParams(layoutParams);
+
+        mActivity.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                getActivity().setContentView(layout);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+
+        final Rect lineBounds = new Rect();
+        textView.getLayout().getLineBounds(0, lineBounds);
+
+        // right edge of view at first line
+        float x = textView.getWidth() - 1f;
+        float y = lineBounds.height() / 2f;
+        assertEquals(0, textView.getOffsetForPosition(x, y));
+
+        // left edge of view at first line
+        x = 0f;
+        assertEquals(line.length() - 1, textView.getOffsetForPosition(x, y));
+
+        // update lineBounds to be the second line
+        textView.getLayout().getLineBounds(1, lineBounds);
+        y = lineBounds.top + lineBounds.height() / 2f;
+
+        // right edge of view at second line
+        x = textView.getWidth() - 1f;
+        assertEquals(line.length(), textView.getOffsetForPosition(x, y));
+
+        // left edge of view at second line
+        x = 0f;
+        assertEquals(line.length() + line.length() - 1, textView.getOffsetForPosition(x, y));
+
+        // right edge of text at second line
+        x = textView.getWidth() - textView.getLayout().getLineWidth(1) + 1f;
+        assertEquals(line.length() + line.length() - 1, textView.getOffsetForPosition(x, y));
+
+        // horizontal center of text at second line
+        x = textView.getWidth() - (textView.getLayout().getLineWidth(1) / 2f);
+        assertEquals(line.length() + line.length() / 2, textView.getOffsetForPosition(x, y));
+    }
+
+    @MediumTest
+    public void testIsTextSelectable_returnsFalseByDefault() {
+        final TextView textView = new TextView(getActivity());
+        textView.setText("any text");
+        assertFalse(textView.isTextSelectable());
+    }
+
+    @MediumTest
+    public void testIsTextSelectable_returnsTrueIfSetTextIsSelectableCalledWithTrue() {
+        final TextView textView = new TextView(getActivity());
+        textView.setText("any text");
+        textView.setTextIsSelectable(true);
+        assertTrue(textView.isTextSelectable());
+    }
+
+    @MediumTest
+    public void testSetIsTextSelectable() {
+        final TextView textView = new TextView(getActivity());
+
+        assertFalse(textView.isTextSelectable());
+        assertFalse(textView.isFocusable());
+        assertFalse(textView.isFocusableInTouchMode());
+        assertFalse(textView.isClickable());
+        assertFalse(textView.isLongClickable());
+
+        textView.setTextIsSelectable(true);
+
+        assertTrue(textView.isTextSelectable());
+        assertTrue(textView.isFocusable());
+        assertTrue(textView.isFocusableInTouchMode());
+        assertTrue(textView.isClickable());
+        assertTrue(textView.isLongClickable());
+        assertNotNull(textView.getMovementMethod());
+    }
 
     public void testAccessTransformationMethod() {
         // check the password attribute in xml
@@ -2983,7 +3507,7 @@
         assertSame(PasswordTransformationMethod.getInstance(),
                 mTextView.getTransformationMethod());
 
-        sendKeys("H E 2*L O");
+        mKeyEventUtil.sendKeys(mTextView, "H E 2*L O");
         mActivity.runOnUiThread(new Runnable() {
             public void run() {
                 mTextView.append(" ");
@@ -2991,15 +3515,10 @@
         });
         mInstrumentation.waitForIdleSync();
 
-        // it will get transformed after a while
-        new PollingCheck(TIMEOUT) {
-            @Override
-            protected boolean check() {
-                // "******"
-                return mTransformedText.toString()
-                        .equals("\u2022\u2022\u2022\u2022\u2022\u2022");
-            }
-        }.run();
+        // It will get transformed after a while
+        // We're waiting for transformation to "******"
+        PollingCheck.waitFor(TIMEOUT, () -> mTransformedText.toString()
+                .equals("\u2022\u2022\u2022\u2022\u2022\u2022"));
 
         // set null
         mActivity.runOnUiThread(new Runnable() {
@@ -3095,13 +3614,71 @@
         assertEquals(mTextView.getPaddingBottom(), mTextView.getCompoundPaddingBottom());
     }
 
+    @MediumTest
+    @UiThreadTest
+    public void testGetCompoundDrawablesRelative() {
+        // prepare textview
+        mTextView = new TextView(mActivity);
+
+        // prepare drawables
+        final Drawable start = getDrawable(R.drawable.blue);
+        final Drawable end = getDrawable(R.drawable.yellow);
+        final Drawable top = getDrawable(R.drawable.red);
+        final Drawable bottom = getDrawable(R.drawable.black);
+        assertNotNull(start);
+        assertNotNull(end);
+        assertNotNull(top);
+        assertNotNull(bottom);
+
+        Drawable[] drawables = mTextView.getCompoundDrawablesRelative();
+        assertNotNull(drawables);
+        assertEquals(4, drawables.length);
+        assertNull(drawables[0]);
+        assertNull(drawables[1]);
+        assertNull(drawables[2]);
+        assertNull(drawables[3]);
+
+        mTextView.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
+        mTextView.setCompoundDrawablesRelative(start, top, end, bottom);
+        drawables = mTextView.getCompoundDrawablesRelative();
+
+        assertNotNull(drawables);
+        assertEquals(4, drawables.length);
+        assertSame(start, drawables[0]);
+        assertSame(top, drawables[1]);
+        assertSame(end, drawables[2]);
+        assertSame(bottom, drawables[3]);
+
+        mTextView.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
+        mTextView.setCompoundDrawablesRelative(start, top, end, bottom);
+        drawables = mTextView.getCompoundDrawablesRelative();
+
+        assertNotNull(drawables);
+        assertEquals(4, drawables.length);
+        assertSame(start, drawables[0]);
+        assertSame(top, drawables[1]);
+        assertSame(end, drawables[2]);
+        assertSame(bottom, drawables[3]);
+
+        mTextView.setCompoundDrawablesRelative(null, null, null, null);
+        drawables = mTextView.getCompoundDrawablesRelative();
+
+        assertNotNull(drawables);
+        assertEquals(4, drawables.length);
+        assertNull(drawables[0]);
+        assertNull(drawables[1]);
+        assertNull(drawables[2]);
+        assertNull(drawables[3]);
+    }
+
+    @MediumTest
     public void testSingleLine() {
         final TextView textView = new TextView(mActivity);
         setSpannableText(textView, "This is a really long sentence"
                 + " which can not be placed in one line on the screen.");
 
         // Narrow layout assures that the text will get wrapped.
-        FrameLayout innerLayout = new FrameLayout(mActivity);
+        final FrameLayout innerLayout = new FrameLayout(mActivity);
         innerLayout.setLayoutParams(new ViewGroup.LayoutParams(100, 100));
         innerLayout.addView(textView);
 
@@ -3157,7 +3734,7 @@
     }
 
     @UiThreadTest
-    public void testSetMaxLines() {
+    public void testAccessMaxLines() {
         mTextView = findTextView(R.id.textview_text);
 
         float[] widths = new float[LONG_TEXT.length()];
@@ -3176,6 +3753,8 @@
         mTextView.setMaxLines(maxLines);
         mTextView.requestLayout();
 
+        assertEquals(2, mTextView.getMaxLines());
+        assertEquals(-1, mTextView.getMaxHeight());
         assertTrue(mTextView.getHeight() <= maxLines * mTextView.getLineHeight());
     }
 
@@ -3269,17 +3848,20 @@
         mTextView.setMaxLines(-1);
     }
 
-    public void testSetMinLines() {
+    public void testAccessMinLines() {
         mTextView = findTextView(R.id.textview_text);
         setWidth(mTextView.getWidth() >> 3);
-        int originalHeight = mTextView.getHeight();
         int originalLines = mTextView.getLineCount();
 
         setMinLines(originalLines - 1);
         assertTrue((originalLines - 1) * mTextView.getLineHeight() <= mTextView.getHeight());
+        assertEquals(originalLines - 1, mTextView.getMinLines());
+        assertEquals(-1, mTextView.getMinHeight());
 
         setMinLines(originalLines + 1);
         assertTrue((originalLines + 1) * mTextView.getLineHeight() <= mTextView.getHeight());
+        assertEquals(originalLines + 1, mTextView.getMinLines());
+        assertEquals(-1, mTextView.getMinHeight());
     }
 
     public void testSetLines() {
@@ -3519,6 +4101,8 @@
                 mTextView.getCurrentHintTextColor());
         assertEquals(mActivity.getResources().getColor(R.drawable.blue),
                 mTextView.getLinkTextColors().getDefaultColor());
+        assertEquals(mActivity.getResources().getColor(R.drawable.yellow),
+                mTextView.getHighlightColor());
 
         mTextView.setTextAppearance(R.style.TextAppearance_Colors);
         assertEquals(mActivity.getResources().getColor(R.drawable.black),
@@ -3527,6 +4111,8 @@
                 mTextView.getCurrentHintTextColor());
         assertEquals(mActivity.getResources().getColor(R.drawable.yellow),
                 mTextView.getLinkTextColors().getDefaultColor());
+        assertEquals(mActivity.getResources().getColor(R.drawable.red),
+                mTextView.getHighlightColor());
 
         mTextView.setTextAppearance(R.style.TextAppearance_NotColors);
         assertEquals(17f, mTextView.getTextSize(), 0.01f);
@@ -3676,7 +4262,11 @@
     }
 
     public void testMarquee() {
-        final MockTextView textView = new MockTextView(mActivity);
+        // Both are pointing to the same object. This works around current limitation in CTS
+        // coverage report tool for properly reporting coverage of base class method calls.
+        final MockTextView mockTextView = new MockTextView(mActivity);
+        final TextView textView = mockTextView;
+
         textView.setText(LONG_TEXT);
         textView.setSingleLine();
         textView.setEllipsize(TruncateAt.MARQUEE);
@@ -3688,11 +4278,7 @@
         // make the fading to be shown
         textView.setHorizontalFadingEdgeEnabled(true);
 
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                mActivity.setContentView(layout);
-            }
-        });
+        mActivity.runOnUiThread(() -> mActivity.setContentView(layout));
         mInstrumentation.waitForIdleSync();
 
         TestSelectedRunnable runnable = new TestSelectedRunnable(textView) {
@@ -3708,23 +4294,15 @@
 
         // wait for the marquee to run
         // fading is shown on both sides if the marquee runs for a while
-        new PollingCheck(TIMEOUT) {
-            @Override
-            protected boolean check() {
-                return textView.getLeftFadingEdgeStrength() > 0.0f
-                        && textView.getRightFadingEdgeStrength() > 0.0f;
-            }
-        }.run();
+        PollingCheck.waitFor(TIMEOUT, () -> mockTextView.getLeftFadingEdgeStrength() > 0.0f
+                && mockTextView.getRightFadingEdgeStrength() > 0.0f);
 
         // wait for left marquee to fully apply
-        new PollingCheck(TIMEOUT) {
-            @Override
-            protected boolean check() {
-                return textView.getLeftFadingEdgeStrength() > 0.99f;
-            }
-        }.run();
+        PollingCheck.waitFor(TIMEOUT, () -> mockTextView.getLeftFadingEdgeStrength() > 0.99f);
+
         assertFalse(runnable.getIsSelected1());
         assertTrue(runnable.getIsSelected2());
+        assertEquals(-1, textView.getMarqueeRepeatLimit());
 
         runnable = new TestSelectedRunnable(textView) {
             public void run() {
@@ -3741,27 +4319,28 @@
         mInstrumentation.waitForIdleSync();
         assertTrue(runnable.getIsSelected1());
         assertFalse(runnable.getIsSelected2());
-        assertEquals(0.0f, textView.getLeftFadingEdgeStrength(), 0.01f);
-        assertTrue(textView.getRightFadingEdgeStrength() > 0.0f);
+        assertEquals(0.0f, mockTextView.getLeftFadingEdgeStrength(), 0.01f);
+        assertTrue(mockTextView.getRightFadingEdgeStrength() > 0.0f);
+        assertEquals(0, textView.getMarqueeRepeatLimit());
 
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                textView.setGravity(Gravity.RIGHT);
-            }
-        });
+        mActivity.runOnUiThread(() -> textView.setGravity(Gravity.RIGHT));
         mInstrumentation.waitForIdleSync();
-        assertTrue(textView.getLeftFadingEdgeStrength() > 0.0f);
-        assertEquals(0.0f, textView.getRightFadingEdgeStrength(), 0.01f);
+        assertTrue(mockTextView.getLeftFadingEdgeStrength() > 0.0f);
+        assertEquals(0.0f, mockTextView.getRightFadingEdgeStrength(), 0.01f);
 
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                textView.setGravity(Gravity.CENTER_HORIZONTAL);
-            }
-        });
+        mActivity.runOnUiThread(() -> textView.setGravity(Gravity.CENTER_HORIZONTAL));
         mInstrumentation.waitForIdleSync();
         // there is no left fading (Is it correct?)
-        assertEquals(0.0f, textView.getLeftFadingEdgeStrength(), 0.01f);
-        assertTrue(textView.getRightFadingEdgeStrength() > 0.0f);
+        assertEquals(0.0f, mockTextView.getLeftFadingEdgeStrength(), 0.01f);
+        assertTrue(mockTextView.getRightFadingEdgeStrength() > 0.0f);
+    }
+
+    @MediumTest
+    public void testGetMarqueeRepeatLimit() {
+        final TextView textView = new TextView(mActivity);
+
+        textView.setMarqueeRepeatLimit(10);
+        assertEquals(10, textView.getMarqueeRepeatLimit());
     }
 
     public void testOnKeyMultiple() {
@@ -3975,14 +4554,16 @@
     public void testSetOnEditorActionListener() {
         mTextView = findTextView(R.id.textview_text);
 
-        MockOnEditorActionListener listener = new MockOnEditorActionListener();
-        assertFalse(listener.isOnEditorActionCalled());
+        final TextView.OnEditorActionListener mockOnEditorActionListener =
+                mock(TextView.OnEditorActionListener.class);
+        verifyZeroInteractions(mockOnEditorActionListener);
 
-        mTextView.setOnEditorActionListener(listener);
-        assertFalse(listener.isOnEditorActionCalled());
+        mTextView.setOnEditorActionListener(mockOnEditorActionListener);
+        verifyZeroInteractions(mockOnEditorActionListener);
 
         mTextView.onEditorAction(EditorInfo.IME_ACTION_DONE);
-        assertTrue(listener.isOnEditorActionCalled());
+        verify(mockOnEditorActionListener, times(1)).onEditorAction(mTextView,
+                EditorInfo.IME_ACTION_DONE, null);
     }
 
     public void testAccessImeOptions() {
@@ -4151,19 +4732,78 @@
         mInstrumentation.waitForIdleSync();
         assertTrue(mTextView.isFocused());
 
-        new PollingCheck() {
-            @Override
-            protected boolean check() {
-                return mTextView.isInputMethodTarget();
-            }
-        }.run();
+        PollingCheck.waitFor(() -> mTextView.isInputMethodTarget());
     }
 
-    public void testBeginEndBatchEdit() {
-        mTextView = findTextView(R.id.textview_text);
+    @MediumTest
+    public void testBeginEndBatchEditAreNotCalledForNonEditableText() {
+        final MockTextView mockTextView = new MockTextView(mActivity);
 
-        mTextView.beginBatchEdit();
-        mTextView.endBatchEdit();
+        assertFalse("TextView should not call onBeginBatchEdit during initialization",
+                mockTextView.hasCalledOnBeginBatchEdit());
+        assertFalse("TextView should not call onEndBatchEdit during initialization",
+                mockTextView.hasCalledOnEndBatchEdit());
+
+        // Since TextView doesn't support editing, the callbacks should not be called
+        mockTextView.beginBatchEdit();
+        assertFalse("Should not call onBeginBatchEdit when TextView doesn't support editing",
+                mockTextView.hasCalledOnBeginBatchEdit());
+        assertFalse("Should not call onEndBatchEdit when TextView doesn't support editing",
+                mockTextView.hasCalledOnEndBatchEdit());
+
+        mockTextView.endBatchEdit();
+        assertFalse("Should not call onBeginBatchEdit when TextView doesn't support editing",
+                mockTextView.hasCalledOnEndBatchEdit());
+        assertFalse("Should not call onEndBatchEdit when TextView doesn't support editing",
+                mockTextView.hasCalledOnEndBatchEdit());
+    }
+
+    @MediumTest
+    public void testBeginEndBatchEditCallbacksAreCalledForEditableText() {
+        final MockTextView mockTextView = new MockTextView(mActivity);
+
+        final FrameLayout layout = new FrameLayout(getActivity());
+        ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.MATCH_PARENT);
+        layout.addView(mockTextView, layoutParams);
+        layout.setLayoutParams(layoutParams);
+
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                getActivity().setContentView(layout);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mockTextView.setKeyListener(QwertyKeyListener.getInstance(false, Capitalize.NONE));
+                mockTextView.setText("", BufferType.EDITABLE);
+                mockTextView.requestFocus();
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+
+        mockTextView.reset();
+        assertTrue(mockTextView.hasFocus());
+        assertFalse("onBeginBatchEdit should be false",
+                mockTextView.hasCalledOnBeginBatchEdit());
+        assertFalse("onEndBatchEdit should be false",
+                mockTextView.hasCalledOnEndBatchEdit());
+
+        mockTextView.beginBatchEdit();
+        assertTrue("onBeginBatchEdit should be called after beginBatchEdit",
+                mockTextView.hasCalledOnBeginBatchEdit());
+        assertFalse("onEndBatchEdit should not be called after beginBatchEdit",
+                mockTextView.hasCalledOnEndBatchEdit());
+
+        mockTextView.reset();
+        mockTextView.endBatchEdit();
+        assertFalse("onBeginBatchEdit should not be called after endBatchEdit",
+                mockTextView.hasCalledOnBeginBatchEdit());
+        assertTrue("onEndBatchEdit should be called after endBatchEdit",
+                mockTextView.hasCalledOnEndBatchEdit());
     }
 
     @UiThreadTest
@@ -4779,228 +5419,213 @@
         assertEquals(View.TEXT_ALIGNMENT_GRAVITY, tv.getTextAlignment());
     }
 
+    private void verifyCompoundDrawables(@NonNull TextView textView,
+            @IdRes int expectedLeftDrawableId, @IdRes int expectedRightDrawableId,
+            @IdRes int expectedTopDrawableId, @IdRes int expectedBottomDrawableId) {
+        final Drawable[] compoundDrawables = textView.getCompoundDrawables();
+        if (expectedLeftDrawableId < 0) {
+            assertNull(compoundDrawables[0]);
+        } else {
+            WidgetTestUtils.assertEquals(getBitmap(expectedLeftDrawableId),
+                    ((BitmapDrawable) compoundDrawables[0]).getBitmap());
+        }
+        if (expectedTopDrawableId < 0) {
+            assertNull(compoundDrawables[1]);
+        } else {
+            WidgetTestUtils.assertEquals(getBitmap(expectedTopDrawableId),
+                    ((BitmapDrawable) compoundDrawables[1]).getBitmap());
+        }
+        if (expectedRightDrawableId < 0) {
+            assertNull(compoundDrawables[2]);
+        } else {
+            WidgetTestUtils.assertEquals(getBitmap(expectedRightDrawableId),
+                    ((BitmapDrawable) compoundDrawables[2]).getBitmap());
+        }
+        if (expectedBottomDrawableId < 0) {
+            assertNull(compoundDrawables[3]);
+        } else {
+            WidgetTestUtils.assertEquals(getBitmap(expectedBottomDrawableId),
+                    ((BitmapDrawable) compoundDrawables[3]).getBitmap());
+        }
+    }
+
+    private void verifyCompoundDrawablesRelative(@NonNull TextView textView,
+            @IdRes int expectedStartDrawableId, @IdRes int expectedEndDrawableId,
+            @IdRes int expectedTopDrawableId, @IdRes int expectedBottomDrawableId) {
+        final Drawable[] compoundDrawablesRelative = textView.getCompoundDrawablesRelative();
+        if (expectedStartDrawableId < 0) {
+            assertNull(compoundDrawablesRelative[0]);
+        } else {
+            WidgetTestUtils.assertEquals(getBitmap(expectedStartDrawableId),
+                    ((BitmapDrawable) compoundDrawablesRelative[0]).getBitmap());
+        }
+        if (expectedTopDrawableId < 0) {
+            assertNull(compoundDrawablesRelative[1]);
+        } else {
+            WidgetTestUtils.assertEquals(getBitmap(expectedTopDrawableId),
+                    ((BitmapDrawable) compoundDrawablesRelative[1]).getBitmap());
+        }
+        if (expectedEndDrawableId < 0) {
+            assertNull(compoundDrawablesRelative[2]);
+        } else {
+            WidgetTestUtils.assertEquals(getBitmap(expectedEndDrawableId),
+                    ((BitmapDrawable) compoundDrawablesRelative[2]).getBitmap());
+        }
+        if (expectedBottomDrawableId < 0) {
+            assertNull(compoundDrawablesRelative[3]);
+        } else {
+            WidgetTestUtils.assertEquals(getBitmap(expectedBottomDrawableId),
+                    ((BitmapDrawable) compoundDrawablesRelative[3]).getBitmap());
+        }
+    }
+
     @UiThreadTest
     public void testDrawableResolution() {
-        final int LEFT = 0;
-        final int TOP = 1;
-        final int RIGHT = 2;
-        final int BOTTOM = 3;
-
-        TextViewCtsActivity activity = getActivity();
-
         // Case 1.1: left / right drawable defined in default LTR mode
-        TextView tv = (TextView) activity.findViewById(R.id.textview_drawable_1_1);
-        Drawable[] drawables = tv.getCompoundDrawables();
-
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_blue),
-                ((BitmapDrawable) drawables[LEFT]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_red),
-                ((BitmapDrawable) drawables[RIGHT]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_green),
-                ((BitmapDrawable) drawables[TOP]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
-                ((BitmapDrawable) drawables[BOTTOM]).getBitmap());
+        TextView tv = (TextView) mActivity.findViewById(R.id.textview_drawable_1_1);
+        verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
+                R.drawable.icon_green, R.drawable.icon_yellow);
+        verifyCompoundDrawablesRelative(tv, -1, -1,
+                R.drawable.icon_green, R.drawable.icon_yellow);
 
         // Case 1.2: left / right drawable defined in default RTL mode
-        tv = (TextView) activity.findViewById(R.id.textview_drawable_1_2);
-        drawables = tv.getCompoundDrawables();
-
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_blue),
-                ((BitmapDrawable) drawables[LEFT]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_red),
-                ((BitmapDrawable) drawables[RIGHT]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_green),
-                ((BitmapDrawable) drawables[TOP]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
-                ((BitmapDrawable) drawables[BOTTOM]).getBitmap());
+        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_1_2);
+        verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
+                R.drawable.icon_green, R.drawable.icon_yellow);
+        verifyCompoundDrawablesRelative(tv, -1, -1,
+                R.drawable.icon_green, R.drawable.icon_yellow);
 
         // Case 2.1: start / end drawable defined in LTR mode
-        tv = (TextView) activity.findViewById(R.id.textview_drawable_2_1);
-        drawables = tv.getCompoundDrawables();
-
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_blue),
-                ((BitmapDrawable) drawables[LEFT]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_red),
-                ((BitmapDrawable) drawables[RIGHT]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_green),
-                ((BitmapDrawable) drawables[TOP]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
-                ((BitmapDrawable) drawables[BOTTOM]).getBitmap());
+        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_2_1);
+        verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
+                R.drawable.icon_green, R.drawable.icon_yellow);
+        verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
+                R.drawable.icon_green, R.drawable.icon_yellow);
 
         // Case 2.2: start / end drawable defined in RTL mode
-        tv = (TextView) activity.findViewById(R.id.textview_drawable_2_2);
-        drawables = tv.getCompoundDrawables();
-
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_red),
-                ((BitmapDrawable) drawables[LEFT]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_blue),
-                ((BitmapDrawable) drawables[RIGHT]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_green),
-                ((BitmapDrawable) drawables[TOP]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
-                ((BitmapDrawable) drawables[BOTTOM]).getBitmap());
+        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_2_2);
+        verifyCompoundDrawables(tv, R.drawable.icon_red, R.drawable.icon_blue,
+                R.drawable.icon_green, R.drawable.icon_yellow);
+        verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
+                R.drawable.icon_green, R.drawable.icon_yellow);
 
         // Case 3.1: left / right / start / end drawable defined in LTR mode
-        tv = (TextView) activity.findViewById(R.id.textview_drawable_3_1);
-        drawables = tv.getCompoundDrawables();
-
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_blue),
-                ((BitmapDrawable) drawables[LEFT]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_red),
-                ((BitmapDrawable) drawables[RIGHT]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_green),
-                ((BitmapDrawable) drawables[TOP]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
-                ((BitmapDrawable) drawables[BOTTOM]).getBitmap());
+        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_3_1);
+        verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
+                R.drawable.icon_green, R.drawable.icon_yellow);
+        verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
+                R.drawable.icon_green, R.drawable.icon_yellow);
 
         // Case 3.2: left / right / start / end drawable defined in RTL mode
-        tv = (TextView) activity.findViewById(R.id.textview_drawable_3_2);
-        drawables = tv.getCompoundDrawables();
-
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_red),
-                ((BitmapDrawable) drawables[LEFT]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_blue),
-                ((BitmapDrawable) drawables[RIGHT]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_green),
-                ((BitmapDrawable) drawables[TOP]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
-                ((BitmapDrawable) drawables[BOTTOM]).getBitmap());
+        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_3_2);
+        verifyCompoundDrawables(tv, R.drawable.icon_red, R.drawable.icon_blue,
+                R.drawable.icon_green, R.drawable.icon_yellow);
+        verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
+                R.drawable.icon_green, R.drawable.icon_yellow);
 
         // Case 4.1: start / end drawable defined in LTR mode inside a layout
         // that defines the layout direction
-        tv = (TextView) activity.findViewById(R.id.textview_drawable_4_1);
-        drawables = tv.getCompoundDrawables();
-
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_blue),
-                ((BitmapDrawable) drawables[LEFT]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_red),
-                ((BitmapDrawable) drawables[RIGHT]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_green),
-                ((BitmapDrawable) drawables[TOP]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
-                ((BitmapDrawable) drawables[BOTTOM]).getBitmap());
+        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_4_1);
+        verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
+                R.drawable.icon_green, R.drawable.icon_yellow);
+        verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
+                R.drawable.icon_green, R.drawable.icon_yellow);
 
         // Case 4.2: start / end drawable defined in RTL mode inside a layout
         // that defines the layout direction
-        tv = (TextView) activity.findViewById(R.id.textview_drawable_4_2);
-        drawables = tv.getCompoundDrawables();
-
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_red),
-                ((BitmapDrawable) drawables[LEFT]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_blue),
-                ((BitmapDrawable) drawables[RIGHT]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_green),
-                ((BitmapDrawable) drawables[TOP]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
-                ((BitmapDrawable) drawables[BOTTOM]).getBitmap());
+        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_4_2);
+        verifyCompoundDrawables(tv, R.drawable.icon_red, R.drawable.icon_blue,
+                R.drawable.icon_green, R.drawable.icon_yellow);
+        verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
+                R.drawable.icon_green, R.drawable.icon_yellow);
 
         // Case 5.1: left / right / start / end drawable defined in LTR mode inside a layout
         // that defines the layout direction
-        tv = (TextView) activity.findViewById(R.id.textview_drawable_3_1);
-        drawables = tv.getCompoundDrawables();
-
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_blue),
-                ((BitmapDrawable) drawables[LEFT]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_red),
-                ((BitmapDrawable) drawables[RIGHT]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_green),
-                ((BitmapDrawable) drawables[TOP]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
-                ((BitmapDrawable) drawables[BOTTOM]).getBitmap());
+        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_5_1);
+        verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
+                R.drawable.icon_green, R.drawable.icon_yellow);
+        verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
+                R.drawable.icon_green, R.drawable.icon_yellow);
 
         // Case 5.2: left / right / start / end drawable defined in RTL mode inside a layout
         // that defines the layout direction
-        tv = (TextView) activity.findViewById(R.id.textview_drawable_3_2);
-        drawables = tv.getCompoundDrawables();
-
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_red),
-                ((BitmapDrawable) drawables[LEFT]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_blue),
-                ((BitmapDrawable) drawables[RIGHT]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_green),
-                ((BitmapDrawable) drawables[TOP]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
-                ((BitmapDrawable) drawables[BOTTOM]).getBitmap());
+        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_5_2);
+        verifyCompoundDrawables(tv, R.drawable.icon_red, R.drawable.icon_blue,
+                R.drawable.icon_green, R.drawable.icon_yellow);
+        verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
+                R.drawable.icon_green, R.drawable.icon_yellow);
     }
 
     @UiThreadTest
     public void testDrawableResolution2() {
-        final int LEFT = 0;
-        final int TOP = 1;
-        final int RIGHT = 2;
-        final int BOTTOM = 3;
-
-        TextViewCtsActivity activity = getActivity();
-
         // Case 1.1: left / right drawable defined in default LTR mode
-        TextView tv = (TextView) activity.findViewById(R.id.textview_drawable_1_1);
-        Drawable[] drawables = tv.getCompoundDrawables();
-
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_blue),
-                ((BitmapDrawable) drawables[LEFT]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_red),
-                ((BitmapDrawable) drawables[RIGHT]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_green),
-                ((BitmapDrawable) drawables[TOP]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
-                ((BitmapDrawable) drawables[BOTTOM]).getBitmap());
+        TextView tv = (TextView) mActivity.findViewById(R.id.textview_drawable_1_1);
+        verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
+                R.drawable.icon_green, R.drawable.icon_yellow);
 
         tv.setCompoundDrawables(null, null, getDrawable(R.drawable.icon_yellow), null);
-        drawables = tv.getCompoundDrawables();
+        verifyCompoundDrawables(tv, -1, R.drawable.icon_yellow, -1, -1);
 
-        assertNull(drawables[LEFT]);
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
-                ((BitmapDrawable) drawables[RIGHT]).getBitmap());
-        assertNull(drawables[TOP]);
-        assertNull(drawables[BOTTOM]);
-
-        tv = (TextView) activity.findViewById(R.id.textview_drawable_1_2);
-        drawables = tv.getCompoundDrawables();
-
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_blue),
-                ((BitmapDrawable) drawables[LEFT]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_red),
-                ((BitmapDrawable) drawables[RIGHT]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_green),
-                ((BitmapDrawable) drawables[TOP]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
-                ((BitmapDrawable) drawables[BOTTOM]).getBitmap());
+        tv = (TextView) mActivity.findViewById(R.id.textview_drawable_1_2);
+        verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
+                R.drawable.icon_green, R.drawable.icon_yellow);
 
         tv.setCompoundDrawables(getDrawable(R.drawable.icon_yellow), null, null, null);
-        drawables = tv.getCompoundDrawables();
+        verifyCompoundDrawables(tv, R.drawable.icon_yellow, -1, -1, -1);
 
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
-                ((BitmapDrawable) drawables[LEFT]).getBitmap());
-        assertNull(drawables[RIGHT]);
-        assertNull(drawables[TOP]);
-        assertNull(drawables[BOTTOM]);
+        tv = (TextView) mActivity.findViewById(R.id.textview_ltr);
+        verifyCompoundDrawables(tv, -1, -1, -1, -1);
 
-        tv = (TextView) activity.findViewById(R.id.textview_ltr);
-        drawables = tv.getCompoundDrawables();
-
-        assertNull(drawables[LEFT]);
-        assertNull(drawables[RIGHT]);
-        assertNull(drawables[TOP]);
-        assertNull(drawables[BOTTOM]);
-
-        tv.setCompoundDrawables(getDrawable(R.drawable.icon_blue), null, getDrawable(R.drawable.icon_red), null);
-        drawables = tv.getCompoundDrawables();
-
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_blue),
-                ((BitmapDrawable) drawables[LEFT]).getBitmap());
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_red),
-                ((BitmapDrawable) drawables[RIGHT]).getBitmap());
-        assertNull(drawables[TOP]);
-        assertNull(drawables[BOTTOM]);
+        tv.setCompoundDrawables(getDrawable(R.drawable.icon_blue), null,
+                getDrawable(R.drawable.icon_red), null);
+        verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red, -1, -1);
 
         tv.setCompoundDrawablesRelative(getDrawable(R.drawable.icon_yellow), null, null, null);
-        drawables = tv.getCompoundDrawables();
+        verifyCompoundDrawables(tv, R.drawable.icon_yellow, -1, -1, -1);
+    }
 
-        WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
-                ((BitmapDrawable) drawables[LEFT]).getBitmap());
-        assertNull(drawables[RIGHT]);
-        assertNull(drawables[TOP]);
-        assertNull(drawables[BOTTOM]);
+    public void testCompoundAndTotalPadding() {
+        final Resources res = mActivity.getResources();
+        final int drawablePadding = res.getDimensionPixelSize(R.dimen.textview_drawable_padding);
+        final int paddingLeft = res.getDimensionPixelSize(R.dimen.textview_padding_left);
+        final int paddingRight = res.getDimensionPixelSize(R.dimen.textview_padding_right);
+        final int paddingTop = res.getDimensionPixelSize(R.dimen.textview_padding_top);
+        final int paddingBottom = res.getDimensionPixelSize(R.dimen.textview_padding_bottom);
+        final int iconSize = TestUtils.dpToPx(mActivity, 32);
+
+        final TextView textViewLtr = (TextView) mActivity.findViewById(
+                R.id.textview_compound_drawable_ltr);
+        final int combinedPaddingLeftLtr = paddingLeft + drawablePadding + iconSize;
+        final int combinedPaddingRightLtr = paddingRight + drawablePadding + iconSize;
+        assertEquals(combinedPaddingLeftLtr, textViewLtr.getCompoundPaddingLeft());
+        assertEquals(combinedPaddingLeftLtr, textViewLtr.getCompoundPaddingStart());
+        assertEquals(combinedPaddingLeftLtr, textViewLtr.getTotalPaddingLeft());
+        assertEquals(combinedPaddingLeftLtr, textViewLtr.getTotalPaddingStart());
+        assertEquals(combinedPaddingRightLtr, textViewLtr.getCompoundPaddingRight());
+        assertEquals(combinedPaddingRightLtr, textViewLtr.getCompoundPaddingEnd());
+        assertEquals(combinedPaddingRightLtr, textViewLtr.getTotalPaddingRight());
+        assertEquals(combinedPaddingRightLtr, textViewLtr.getTotalPaddingEnd());
+        assertEquals(paddingTop + drawablePadding + iconSize,
+                textViewLtr.getCompoundPaddingTop());
+        assertEquals(paddingBottom + drawablePadding + iconSize,
+                textViewLtr.getCompoundPaddingBottom());
+
+        final TextView textViewRtl = (TextView) mActivity.findViewById(
+                R.id.textview_compound_drawable_rtl);
+        final int combinedPaddingLeftRtl = paddingLeft + drawablePadding + iconSize;
+        final int combinedPaddingRightRtl = paddingRight + drawablePadding + iconSize;
+        assertEquals(combinedPaddingLeftRtl, textViewRtl.getCompoundPaddingLeft());
+        assertEquals(combinedPaddingLeftRtl, textViewRtl.getCompoundPaddingEnd());
+        assertEquals(combinedPaddingLeftRtl, textViewRtl.getTotalPaddingLeft());
+        assertEquals(combinedPaddingLeftRtl, textViewRtl.getTotalPaddingEnd());
+        assertEquals(combinedPaddingRightRtl, textViewRtl.getCompoundPaddingRight());
+        assertEquals(combinedPaddingRightRtl, textViewRtl.getCompoundPaddingStart());
+        assertEquals(combinedPaddingRightRtl, textViewRtl.getTotalPaddingRight());
+        assertEquals(combinedPaddingRightRtl, textViewRtl.getTotalPaddingStart());
+        assertEquals(paddingTop + drawablePadding + iconSize,
+                textViewRtl.getCompoundPaddingTop());
+        assertEquals(paddingBottom + drawablePadding + iconSize,
+                textViewRtl.getCompoundPaddingBottom());
     }
 
     public void testSetGetBreakStrategy() {
@@ -5076,9 +5701,11 @@
         // Check default value.
         assertNull(mTextView.getCustomSelectionActionModeCallback());
 
-        MockActionModeCallback callbackBlockActionMode = new MockActionModeCallback(false);
-        mTextView.setCustomSelectionActionModeCallback(callbackBlockActionMode);
-        assertEquals(callbackBlockActionMode,
+        final ActionMode.Callback mockActionModeCallback = mock(ActionMode.Callback.class);
+        when(mockActionModeCallback.onCreateActionMode(any(ActionMode.class), any(Menu.class))).
+                thenReturn(Boolean.FALSE);
+        mTextView.setCustomSelectionActionModeCallback(mockActionModeCallback);
+        assertEquals(mockActionModeCallback,
                 mTextView.getCustomSelectionActionModeCallback());
 
         mActivity.runOnUiThread(new Runnable() {
@@ -5093,7 +5720,8 @@
         });
         mInstrumentation.waitForIdleSync();
 
-        assertEquals(1, callbackBlockActionMode.getCreateCount());
+        verify(mockActionModeCallback, times(1)).onCreateActionMode(
+                any(ActionMode.class), any(Menu.class));
 
         mActivity.runOnUiThread(new Runnable() {
             public void run() {
@@ -5104,12 +5732,13 @@
         mInstrumentation.waitForIdleSync();
 
         // Action mode was blocked.
-        assertEquals(0, callbackBlockActionMode.getDestroyCount());
+        verify(mockActionModeCallback, never()).onDestroyActionMode(any(ActionMode.class));
 
-        // Overwrite callback.
-        MockActionModeCallback callbackStartActionMode = new MockActionModeCallback(true);
-        mTextView.setCustomSelectionActionModeCallback(callbackStartActionMode);
-        assertEquals(callbackStartActionMode, mTextView.getCustomSelectionActionModeCallback());
+        // Reset and reconfigure callback.
+        reset(mockActionModeCallback);
+        when(mockActionModeCallback.onCreateActionMode(any(ActionMode.class), any(Menu.class))).
+                thenReturn(Boolean.TRUE);
+        assertEquals(mockActionModeCallback, mTextView.getCustomSelectionActionModeCallback());
 
         mActivity.runOnUiThread(new Runnable() {
             public void run() {
@@ -5124,7 +5753,8 @@
         });
         mInstrumentation.waitForIdleSync();
 
-        assertEquals(1, callbackStartActionMode.getCreateCount());
+        verify(mockActionModeCallback, times(1)).onCreateActionMode(
+                any(ActionMode.class), any(Menu.class));
 
         mActivity.runOnUiThread(new Runnable() {
             public void run() {
@@ -5135,70 +5765,317 @@
         mInstrumentation.waitForIdleSync();
 
         // Action mode was started
-        assertEquals(1, callbackStartActionMode.getDestroyCount());
+        verify(mockActionModeCallback, times(1)).onDestroyActionMode(any(ActionMode.class));
     }
 
-    public void testSetAndGetCustomInseltionActionMode() {
+    public void testSetAndGetCustomInsertionActionMode() {
         initTextViewForTyping();
         // Check default value.
         assertNull(mTextView.getCustomInsertionActionModeCallback());
 
-        MockActionModeCallback callback = new MockActionModeCallback(false);
-        mTextView.setCustomInsertionActionModeCallback(callback);
-        assertEquals(callback, mTextView.getCustomInsertionActionModeCallback());
+        final ActionMode.Callback mockActionModeCallback = mock(ActionMode.Callback.class);
+        when(mockActionModeCallback.onCreateActionMode(any(ActionMode.class), any(Menu.class))).
+                thenReturn(Boolean.FALSE);
+        mTextView.setCustomInsertionActionModeCallback(mockActionModeCallback);
+        assertEquals(mockActionModeCallback, mTextView.getCustomInsertionActionModeCallback());
         // TODO(Bug: 22033189): Tests the set callback is actually used.
     }
 
-    private static class MockActionModeCallback implements ActionMode.Callback {
-        private int mCreateCount = 0;
-        private int mDestroyCount = 0;
-        private final boolean mAllowToStartActionMode;
+    public void testTextShadows() {
+        final TextView textViewWithConfiguredShadow =
+                (TextView) mActivity.findViewById(R.id.textview_with_shadow);
+        assertEquals(1.0f, textViewWithConfiguredShadow.getShadowDx());
+        assertEquals(2.0f, textViewWithConfiguredShadow.getShadowDy());
+        assertEquals(3.0f, textViewWithConfiguredShadow.getShadowRadius());
+        assertEquals(Color.GREEN, textViewWithConfiguredShadow.getShadowColor());
 
-        public MockActionModeCallback(boolean allowToStartActionMode) {
-            mAllowToStartActionMode = allowToStartActionMode;
-        }
+        final TextView textView = (TextView) mActivity.findViewById(R.id.textview_text);
+        assertEquals(0.0f, textView.getShadowDx());
+        assertEquals(0.0f, textView.getShadowDy());
+        assertEquals(0.0f, textView.getShadowRadius());
 
-        public int getCreateCount() {
-            return mCreateCount;
-        }
+        mActivity.runOnUiThread(() -> textView.setShadowLayer(5.0f, 3.0f, 4.0f, Color.RED));
+        mInstrumentation.waitForIdleSync();
+        assertEquals(3.0f, textView.getShadowDx());
+        assertEquals(4.0f, textView.getShadowDy());
+        assertEquals(5.0f, textView.getShadowRadius());
+        assertEquals(Color.RED, textView.getShadowColor());
+    }
 
-        public int getDestroyCount() {
-            return mDestroyCount;
+    public void testFontFeatureSettings() {
+        final TextView textView = (TextView) mActivity.findViewById(R.id.textview_text);
+        assertTrue(TextUtils.isEmpty(textView.getFontFeatureSettings()));
+
+        mActivity.runOnUiThread(() -> textView.setFontFeatureSettings("smcp"));
+        mInstrumentation.waitForIdleSync();
+        assertEquals("smcp", textView.getFontFeatureSettings());
+
+        mActivity.runOnUiThread(() -> textView.setFontFeatureSettings("frac"));
+        mInstrumentation.waitForIdleSync();
+        assertEquals("frac", textView.getFontFeatureSettings());
+    }
+
+    private static class SoftInputResultReceiver extends ResultReceiver {
+        private boolean mIsDone;
+        private int mResultCode;
+
+        public SoftInputResultReceiver(Handler handler) {
+            super(handler);
         }
 
         @Override
-        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
-            return false;
+        protected void onReceiveResult(int resultCode, Bundle resultData) {
+            mResultCode = resultCode;
+            mIsDone = true;
         }
 
-        @Override
-        public void onDestroyActionMode(ActionMode mode) {
-            mDestroyCount++;
+        public void reset() {
+            mIsDone = false;
+        }
+    }
+
+    public void testAccessShowSoftInputOnFocus() {
+        if (!mActivity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_INPUT_METHODS)) {
+            return;
         }
 
-        @Override
-        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
-            mCreateCount++;
-            return mAllowToStartActionMode;
+        // Scroll down to our EditText
+        final ScrollView scrollView = (ScrollView) mActivity.findViewById(R.id.scroller);
+        mTextView = findTextView(R.id.editview_text);
+        mActivity.runOnUiThread(() -> scrollView.fullScroll(View.FOCUS_DOWN));
+        mInstrumentation.waitForIdleSync();
+
+        // Mark it to show soft input on focus
+        mActivity.runOnUiThread(() -> mTextView.setShowSoftInputOnFocus(true));
+        mInstrumentation.waitForIdleSync();
+        assertTrue(mTextView.getShowSoftInputOnFocus());
+
+        // And emulate click on it
+        TouchUtils.clickView(this, mTextView);
+
+        // Verify that input method manager is active and accepting text
+        final InputMethodManager imManager = (InputMethodManager) mActivity
+                .getSystemService(Context.INPUT_METHOD_SERVICE);
+        PollingCheck.waitFor(() -> imManager.isActive());
+        assertTrue(imManager.isAcceptingText());
+        assertTrue(imManager.isActive(mTextView));
+
+        // Since there is no API to check that soft input is showing, we're going to ask
+        // the input method manager to show soft input, passing our custom result receiver.
+        // We're expecting to get UNCHANGED_SHOWN, indicating that the soft input was already
+        // showing before showSoftInput was called.
+        SoftInputResultReceiver receiver = new SoftInputResultReceiver(mHandler);
+        imManager.showSoftInput(mTextView, 0, receiver);
+        PollingCheck.waitFor(() -> receiver.mIsDone);
+        assertEquals(InputMethodManager.RESULT_UNCHANGED_SHOWN, receiver.mResultCode);
+
+        // Close soft input
+        sendKeys(KeyEvent.KEYCODE_BACK);
+
+        // Reconfigure our edit text to not show soft input on focus
+        mActivity.runOnUiThread(() -> mTextView.setShowSoftInputOnFocus(false));
+        mInstrumentation.waitForIdleSync();
+        assertFalse(mTextView.getShowSoftInputOnFocus());
+
+        // Emulate click on it
+        TouchUtils.clickView(this, mTextView);
+
+        // Ask input method manager to show soft input again. This time we're expecting to get
+        // SHOWN, indicating that the soft input was not showing before showSoftInput was called.
+        receiver.reset();
+        imManager.showSoftInput(mTextView, 0, receiver);
+        PollingCheck.waitFor(() -> receiver.mIsDone);
+        assertEquals(InputMethodManager.RESULT_SHOWN, receiver.mResultCode);
+
+        // Close soft input
+        sendKeys(KeyEvent.KEYCODE_BACK);
+    }
+
+    public void testIsSuggestionsEnabled() {
+        mTextView = findTextView(R.id.textview_text);
+
+        // Anything without InputType.TYPE_CLASS_TEXT doesn't have suggestions enabled
+        mInstrumentation.runOnMainSync(() -> mTextView.setInputType(InputType.TYPE_CLASS_DATETIME));
+        assertFalse(mTextView.isSuggestionsEnabled());
+
+        mInstrumentation.runOnMainSync(() -> mTextView.setInputType(InputType.TYPE_CLASS_PHONE));
+        assertFalse(mTextView.isSuggestionsEnabled());
+
+        mInstrumentation.runOnMainSync(() -> mTextView.setInputType(InputType.TYPE_CLASS_NUMBER));
+        assertFalse(mTextView.isSuggestionsEnabled());
+
+        // From this point our text view has InputType.TYPE_CLASS_TEXT
+
+        // Anything with InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS doesn't have suggestions enabled
+        mInstrumentation.runOnMainSync(
+                () -> mTextView.setInputType(
+                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS));
+        assertFalse(mTextView.isSuggestionsEnabled());
+
+        mInstrumentation.runOnMainSync(
+                () -> mTextView.setInputType(
+                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL |
+                                InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS));
+        assertFalse(mTextView.isSuggestionsEnabled());
+
+        mInstrumentation.runOnMainSync(
+                () -> mTextView.setInputType(
+                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS |
+                                InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS));
+        assertFalse(mTextView.isSuggestionsEnabled());
+
+        // Otherwise suggestions are enabled for specific type variations enumerated in the
+        // documentation of TextView.isSuggestionsEnabled
+        mInstrumentation.runOnMainSync(
+                () -> mTextView.setInputType(
+                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL));
+        assertTrue(mTextView.isSuggestionsEnabled());
+
+        mInstrumentation.runOnMainSync(
+                () -> mTextView.setInputType(
+                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_SUBJECT));
+        assertTrue(mTextView.isSuggestionsEnabled());
+
+        mInstrumentation.runOnMainSync(
+                () -> mTextView.setInputType(
+                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_LONG_MESSAGE));
+        assertTrue(mTextView.isSuggestionsEnabled());
+
+        mInstrumentation.runOnMainSync(
+                () -> mTextView.setInputType(
+                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE));
+        assertTrue(mTextView.isSuggestionsEnabled());
+
+        mInstrumentation.runOnMainSync(
+                () -> mTextView.setInputType(
+                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT));
+        assertTrue(mTextView.isSuggestionsEnabled());
+
+        // and not on any other type variation
+        mInstrumentation.runOnMainSync(
+                () -> mTextView.setInputType(
+                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS));
+        assertFalse(mTextView.isSuggestionsEnabled());
+
+        mInstrumentation.runOnMainSync(
+                () -> mTextView.setInputType(
+                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_FILTER));
+        assertFalse(mTextView.isSuggestionsEnabled());
+
+        mInstrumentation.runOnMainSync(
+                () -> mTextView.setInputType(
+                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD));
+        assertFalse(mTextView.isSuggestionsEnabled());
+
+        mInstrumentation.runOnMainSync(
+                () -> mTextView.setInputType(
+                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PERSON_NAME));
+        assertFalse(mTextView.isSuggestionsEnabled());
+
+        mInstrumentation.runOnMainSync(
+                () -> mTextView.setInputType(
+                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PHONETIC));
+        assertFalse(mTextView.isSuggestionsEnabled());
+
+        mInstrumentation.runOnMainSync(
+                () -> mTextView.setInputType(
+                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS));
+        assertFalse(mTextView.isSuggestionsEnabled());
+
+        mInstrumentation.runOnMainSync(
+                () -> mTextView.setInputType(
+                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI));
+        assertFalse(mTextView.isSuggestionsEnabled());
+
+        mInstrumentation.runOnMainSync(
+                () -> mTextView.setInputType(
+                        InputType.TYPE_CLASS_TEXT |
+                                InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD));
+        assertFalse(mTextView.isSuggestionsEnabled());
+
+        mInstrumentation.runOnMainSync(
+                () -> mTextView.setInputType(
+                        InputType.TYPE_CLASS_TEXT |
+                                InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS));
+        assertFalse(mTextView.isSuggestionsEnabled());
+
+        mInstrumentation.runOnMainSync(
+                () -> mTextView.setInputType(
+                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD));
+        assertFalse(mTextView.isSuggestionsEnabled());
+    }
+
+    public void testAccessLetterSpacing() {
+        mTextView = findTextView(R.id.textview_text);
+        assertEquals(0.0f, mTextView.getLetterSpacing());
+
+        final CharSequence text = mTextView.getText();
+        final int textLength = text.length();
+
+        // Get advance widths of each character at the default letter spacing
+        final float[] initialWidths = new float[textLength];
+        mTextView.getPaint().getTextWidths(text.toString(), initialWidths);
+
+        // Get advance widths of each character at letter spacing = 1.0f
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mTextView,
+                () -> mTextView.setLetterSpacing(1.0f));
+        assertEquals(1.0f, mTextView.getLetterSpacing());
+        final float[] singleWidths = new float[textLength];
+        mTextView.getPaint().getTextWidths(text.toString(), singleWidths);
+
+        // Get advance widths of each character at letter spacing = 2.0f
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mTextView,
+                () -> mTextView.setLetterSpacing(2.0f));
+        assertEquals(2.0f, mTextView.getLetterSpacing());
+        final float[] doubleWidths = new float[textLength];
+        mTextView.getPaint().getTextWidths(text.toString(), doubleWidths);
+
+        // Since letter spacing setter treats the parameter as EM units, and we don't have
+        // a way to convert EMs into pixels, go over the three arrays of advance widths and
+        // test that the extra advance width at letter spacing 2.0f is double the extra
+        // advance width at letter spacing 1.0f.
+        for (int i = 0; i < textLength; i++) {
+            float singleWidthDelta = singleWidths[i] - initialWidths[i];
+            float doubleWidthDelta = doubleWidths[i] - initialWidths[i];
+            assertEquals("At index " + i + " initial is " + initialWidths[i] +
+                ", single is " + singleWidths[i] + " and double is " + doubleWidths[i],
+                    singleWidthDelta * 2.0f, doubleWidthDelta, 0.05f);
+        }
+    }
+
+    private void verifyGetOffsetForPosition(final int x, final int y) {
+        final int actual = mTextView.getOffsetForPosition(x, y);
+
+        final Layout layout = mTextView.getLayout();
+        if (layout == null) {
+            assertEquals("For [" + x + ", " + y + "]", -1, actual);
+            return;
         }
 
-        @Override
-        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
-            return false;
-        }
-    };
+        // Get the line which corresponds to the Y position
+        final int line = layout.getLineForVertical(y + mTextView.getScrollY());
+        // Get the offset in that line that corresponds to the X position
+        final int expected = layout.getOffsetForHorizontal(line, x + mTextView.getScrollX());
+        assertEquals("For [" + x + ", " + y + "]", expected, actual);
+    }
 
-    private static class MockOnEditorActionListener implements OnEditorActionListener {
-        private boolean isOnEditorActionCalled;
+    public void testGetOffsetForPosition() {
+        mTextView = findTextView(R.id.textview_text);
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mTextView, () -> {
+            mTextView.setText(LONG_TEXT);
+            mTextView.setPadding(0, 0, 0, 0);
+        });
 
-        public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
-            isOnEditorActionCalled = true;
-            return true;
-        }
+        assertNotNull(mTextView.getLayout());
+        final int viewWidth = mTextView.getWidth();
+        final int viewHeight = mTextView.getHeight();
+        final int lineHeight = mTextView.getLineHeight();
 
-        public boolean isOnEditorActionCalled() {
-            return isOnEditorActionCalled;
-        }
+        verifyGetOffsetForPosition(0, 0);
+        verifyGetOffsetForPosition(0, viewHeight / 2);
+        verifyGetOffsetForPosition(viewWidth / 3, lineHeight / 2);
+        verifyGetOffsetForPosition(viewWidth / 2, viewHeight / 2);
+        verifyGetOffsetForPosition(viewWidth, viewHeight);
     }
 
     private void layout(final TextView textView) {
@@ -5235,6 +6112,15 @@
         return mActivity.getResources().getDrawable(resid);
     }
 
+    private void setMaxLines(final int lines) {
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mTextView.setMaxLines(lines);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+    }
+
     private void setMaxWidth(final int pixels) {
         mActivity.runOnUiThread(new Runnable() {
             public void run() {
@@ -5411,56 +6297,6 @@
         }
     }
 
-    private class MockEditableFactory extends Editable.Factory {
-        private boolean mhasCalledNewEditable;
-        private CharSequence mSource;
-
-        public boolean hasCalledNewEditable() {
-            return mhasCalledNewEditable;
-        }
-
-        public void reset() {
-            mhasCalledNewEditable = false;
-            mSource = null;
-        }
-
-        public CharSequence getSource() {
-            return mSource;
-        }
-
-        @Override
-        public Editable newEditable(CharSequence source) {
-            mhasCalledNewEditable = true;
-            mSource = source;
-            return super.newEditable(source);
-        }
-    }
-
-    private class MockSpannableFactory extends Spannable.Factory {
-        private boolean mHasCalledNewSpannable;
-        private CharSequence mSource;
-
-        public boolean hasCalledNewSpannable() {
-            return mHasCalledNewSpannable;
-        }
-
-        public void reset() {
-            mHasCalledNewSpannable = false;
-            mSource = null;
-        }
-
-        public CharSequence getSource() {
-            return mSource;
-        }
-
-        @Override
-        public Spannable newSpannable(CharSequence source) {
-            mHasCalledNewSpannable = true;
-            mSource = source;
-            return super.newSpannable(source);
-        }
-    }
-
     private static class MockTextWatcher implements TextWatcher {
         private boolean mHasCalledAfterTextChanged;
         private boolean mHasCalledBeforeTextChanged;
@@ -5498,70 +6334,6 @@
     }
 
     /**
-     * The listener interface for receiving mockOnLongClick events. The class
-     * that is interested in processing a mockOnLongClick event implements this
-     * interface, and the object created with that class is registered with a
-     * component using the component's
-     * <code>addMockOnLongClickListener<code> method. When
-     * the mockOnLongClick event occurs, that object's appropriate
-     * method is invoked.
-     *
-     * @see MockOnLongClickEvent
-     */
-    private static class MockOnLongClickListener implements OnLongClickListener {
-        private boolean mExpectedOnLongClickResult;
-        private boolean mHasLongClicked;
-
-        MockOnLongClickListener(boolean result) {
-            mExpectedOnLongClickResult = result;
-        }
-
-        public boolean hasLongClicked() {
-            return mHasLongClicked;
-        }
-
-        public boolean onLongClick(View v) {
-            mHasLongClicked = true;
-            return mExpectedOnLongClickResult;
-        }
-    }
-
-    /**
-     * The listener interface for receiving mockOnCreateContextMenu events. The
-     * class that is interested in processing a mockOnCreateContextMenu event
-     * implements this interface, and the object created with that class is
-     * registered with a component using the component's
-     * <code>addMockOnCreateContextMenuListener<code> method. When the
-     * mockOnCreateContextMenu event occurs, that object's appropriate method is
-     * invoked.
-     *
-     * @see MockOnCreateContextMenuEvent
-     */
-    private static class MockOnCreateContextMenuListener implements OnCreateContextMenuListener {
-        private boolean mIsMenuItemsBlank;
-        private boolean mHasCreatedContextMenu;
-
-        MockOnCreateContextMenuListener(boolean isBlank) {
-            this.mIsMenuItemsBlank = isBlank;
-        }
-
-        public boolean hasCreatedContextMenu() {
-            return mHasCreatedContextMenu;
-        }
-
-        public void reset() {
-            mHasCreatedContextMenu = false;
-        }
-
-        public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
-            mHasCreatedContextMenu = true;
-            if (!mIsMenuItemsBlank) {
-                menu.add("menu item");
-            }
-        }
-    }
-
-    /**
      * A TextWatcher that converts the text to spaces whenever the text changes.
      */
     private static class ConvertToSpacesTextWatcher implements TextWatcher {
diff --git a/tests/tests/widget/src/android/widget/cts/TimePickerCtsActivity.java b/tests/tests/widget/src/android/widget/cts/TimePickerCtsActivity.java
new file mode 100644
index 0000000..34fb8c0
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/TimePickerCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TimePicker;
+
+/**
+ * A minimal application for {@link TimePicker} test.
+ */
+public class TimePickerCtsActivity extends Activity {
+    /**
+     * Called when the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.timepicker);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/TimePickerTest.java b/tests/tests/widget/src/android/widget/cts/TimePickerTest.java
index 39554bb..6dad194 100644
--- a/tests/tests/widget/src/android/widget/cts/TimePickerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TimePickerTest.java
@@ -16,46 +16,46 @@
 
 package android.widget.cts;
 
-
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.content.Context;
 import android.os.Parcelable;
 import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.util.AttributeSet;
 import android.widget.TimePicker;
-import android.widget.TimePicker.OnTimeChangedListener;
+
+import static org.mockito.Mockito.*;
 
 /**
  * Test {@link TimePicker}.
  */
-public class TimePickerTest extends ActivityInstrumentationTestCase2<CtsActivity> {
+@SmallTest
+public class TimePickerTest extends ActivityInstrumentationTestCase2<TimePickerCtsActivity> {
     private TimePicker mTimePicker;
-
     private Activity mActivity;
-
-    private Context mContext;
-
     private Instrumentation mInstrumentation;
 
     public TimePickerTest() {
-        super("android.widget.cts", CtsActivity.class);
+        super("android.widget.cts", TimePickerCtsActivity.class);
     }
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+
         mInstrumentation = getInstrumentation();
-        mContext = mInstrumentation.getTargetContext();
         mActivity = getActivity();
+        mTimePicker = (TimePicker) mActivity.findViewById(R.id.timepicker);
     }
 
     public void testConstructors() {
         AttributeSet attrs =
-            mContext.getResources().getLayout(android.widget.cts.R.layout.timepicker);
+            mActivity.getResources().getLayout(android.widget.cts.R.layout.timepicker);
         assertNotNull(attrs);
 
-        new TimePicker(mContext);
+        new TimePicker(mActivity);
         try {
             new TimePicker(null);
             fail("did not throw NullPointerException when param context is null.");
@@ -63,29 +63,31 @@
             // expected
         }
 
-        new TimePicker(mContext, attrs);
+        new TimePicker(mActivity, attrs);
         try {
             new TimePicker(null, attrs);
             fail("did not throw NullPointerException when param context is null.");
         } catch (NullPointerException e) {
             // expected
         }
-        new TimePicker(mContext, null);
+        new TimePicker(mActivity, null);
 
-        new TimePicker(mContext, attrs, 0);
+        new TimePicker(mActivity, attrs, 0);
         try {
             new TimePicker(null, attrs, 0);
             fail("did not throw NullPointerException when param context is null.");
         } catch (NullPointerException e) {
             // expected
         }
-        new TimePicker(mContext, null, 0);
-        new TimePicker(mContext, attrs, 0);
-        new TimePicker(mContext, attrs, Integer.MIN_VALUE);
+        new TimePicker(mActivity, null, 0);
+        new TimePicker(mActivity, attrs, 0);
+        new TimePicker(mActivity, null, android.R.attr.timePickerStyle);
+        new TimePicker(mActivity, null, 0, android.R.style.Widget_Material_TimePicker);
+        new TimePicker(mActivity, null, 0, android.R.style.Widget_Material_Light_TimePicker);
     }
 
+    @UiThreadTest
     public void testSetEnabled() {
-        mTimePicker = new TimePicker(mContext);
         assertTrue(mTimePicker.isEnabled());
 
         mTimePicker.setEnabled(false);
@@ -96,49 +98,66 @@
     }
 
     public void testSetOnTimeChangedListener() {
-        int initialHour = 13;
-        int initialMinute = 50;
-        mTimePicker = new TimePicker(mContext);
+        // On time change listener is notified on every call to setCurrentHour / setCurrentMinute.
+        // We want to make sure that before we register our listener, we initialize the time picker
+        // to the time that is explicitly different from the values we'll be testing for in both
+        // hour and minute. Otherwise if the test happens to run at the time that ends in
+        // "minuteForTesting" minutes, we'll get two onTimeChanged callbacks with identical values.
+        final int initialHour = 10;
+        final int initialMinute = 38;
+        final int hourForTesting = 13;
+        final int minuteForTesting = 50;
 
-        MockOnTimeChangeListener listener = new MockOnTimeChangeListener();
-        mTimePicker.setOnTimeChangedListener(listener);
-        mTimePicker.setCurrentHour(Integer.valueOf(initialHour));
-        mTimePicker.setCurrentMinute(Integer.valueOf(initialMinute));
-        assertEquals(initialHour, listener.getNotifiedHourOfDay());
-        assertEquals(initialMinute, listener.getNotifiedMinute());
+        mInstrumentation.runOnMainSync(() -> {
+            mTimePicker.setHour(initialHour);
+            mTimePicker.setMinute(initialMinute);
+        });
+
+        // Now register the listener
+        TimePicker.OnTimeChangedListener mockOnTimeChangeListener =
+                mock(TimePicker.OnTimeChangedListener.class);
+        mTimePicker.setOnTimeChangedListener(mockOnTimeChangeListener);
+        mInstrumentation.runOnMainSync(() -> {
+                mTimePicker.setCurrentHour(Integer.valueOf(hourForTesting));
+                mTimePicker.setCurrentMinute(Integer.valueOf(minuteForTesting));
+        });
+        // We're expecting two onTimeChanged callbacks, one with new hour and one with new
+        // hour+minute
+        verify(mockOnTimeChangeListener, times(1)).onTimeChanged(
+                mTimePicker, hourForTesting, initialMinute);
+        verify(mockOnTimeChangeListener, times(1)).onTimeChanged(
+                mTimePicker, hourForTesting, minuteForTesting);
 
         // set the same hour as current
-        listener.reset();
-        mTimePicker.setCurrentHour(Integer.valueOf(initialHour));
-        assertFalse(listener.hasCalledOnTimeChanged());
+        reset(mockOnTimeChangeListener);
+        mInstrumentation.runOnMainSync(
+                () -> mTimePicker.setCurrentHour(Integer.valueOf(hourForTesting)));
+        verifyZeroInteractions(mockOnTimeChangeListener);
 
-        mTimePicker.setCurrentHour(Integer.valueOf(initialHour + 1));
-        assertTrue(listener.hasCalledOnTimeChanged());
-        assertEquals(initialHour + 1, listener.getNotifiedHourOfDay());
-        assertEquals(initialMinute, listener.getNotifiedMinute());
-        assertSame(mTimePicker, listener.getNotifiedView());
+        mInstrumentation.runOnMainSync(
+                () -> mTimePicker.setCurrentHour(Integer.valueOf(hourForTesting + 1)));
+        verify(mockOnTimeChangeListener, times(1)).onTimeChanged(
+                mTimePicker, hourForTesting + 1, minuteForTesting);
 
         // set the same minute as current
-        listener.reset();
-        mTimePicker.setCurrentMinute(initialMinute);
-        assertFalse(listener.hasCalledOnTimeChanged());
+        reset(mockOnTimeChangeListener);
+        mInstrumentation.runOnMainSync(() -> mTimePicker.setCurrentMinute(minuteForTesting));
+        verifyZeroInteractions(mockOnTimeChangeListener);
 
-        listener.reset();
-        mTimePicker.setCurrentMinute(initialMinute + 1);
-        assertTrue(listener.hasCalledOnTimeChanged());
-        assertEquals(initialHour + 1, listener.getNotifiedHourOfDay());
-        assertEquals(initialMinute + 1, listener.getNotifiedMinute());
-        assertSame(mTimePicker, listener.getNotifiedView());
+        reset(mockOnTimeChangeListener);
+        mInstrumentation.runOnMainSync(() -> mTimePicker.setCurrentMinute(minuteForTesting + 1));
+        verify(mockOnTimeChangeListener, times(1)).onTimeChanged(
+                mTimePicker, hourForTesting + 1, minuteForTesting + 1);
 
         // change time picker mode
-        listener.reset();
-        mTimePicker.setIs24HourView( !mTimePicker.is24HourView() );
-        assertFalse(listener.hasCalledOnTimeChanged());
+        reset(mockOnTimeChangeListener);
+        mInstrumentation.runOnMainSync(
+                () -> mTimePicker.setIs24HourView(!mTimePicker.is24HourView()));
+        verifyZeroInteractions(mockOnTimeChangeListener);
     }
 
+    @UiThreadTest
     public void testAccessCurrentHour() {
-        mTimePicker = new TimePicker(mContext);
-
         // AM/PM mode
         mTimePicker.setIs24HourView(false);
 
@@ -167,9 +186,8 @@
         assertEquals(Integer.valueOf(23), mTimePicker.getCurrentHour());
     }
 
+    @UiThreadTest
     public void testAccessHour() {
-        mTimePicker = new TimePicker(mContext);
-
         // AM/PM mode
         mTimePicker.setIs24HourView(false);
 
@@ -198,8 +216,8 @@
         assertEquals(23, mTimePicker.getHour());
     }
 
+    @UiThreadTest
     public void testAccessIs24HourView() {
-        mTimePicker = new TimePicker(mContext);
         assertFalse(mTimePicker.is24HourView());
 
         mTimePicker.setIs24HourView(true);
@@ -209,9 +227,8 @@
         assertFalse(mTimePicker.is24HourView());
     }
 
+    @UiThreadTest
     public void testAccessCurrentMinute() {
-        mTimePicker = new TimePicker(mContext);
-
         mTimePicker.setCurrentMinute(0);
         assertEquals(Integer.valueOf(0), mTimePicker.getCurrentMinute());
 
@@ -225,9 +242,8 @@
         assertEquals(Integer.valueOf(59), mTimePicker.getCurrentMinute());
     }
 
+    @UiThreadTest
     public void testAccessMinute() {
-        mTimePicker = new TimePicker(mContext);
-
         mTimePicker.setMinute(0);
         assertEquals(0, mTimePicker.getMinute());
 
@@ -242,13 +258,12 @@
     }
 
     public void testGetBaseline() {
-        mTimePicker = new TimePicker(mContext);
         assertEquals(-1, mTimePicker.getBaseline());
     }
 
     public void testOnSaveInstanceStateAndOnRestoreInstanceState() {
-        MyTimePicker source = new MyTimePicker(mContext);
-        MyTimePicker dest = new MyTimePicker(mContext);
+        MyTimePicker source = new MyTimePicker(mActivity);
+        MyTimePicker dest = new MyTimePicker(mActivity);
         int expectHour = (dest.getCurrentHour() + 10) % 24;
         int expectMinute = (dest.getCurrentMinute() + 10) % 60;
         source.setCurrentHour(expectHour);
@@ -261,46 +276,6 @@
         assertEquals(Integer.valueOf(expectMinute), dest.getCurrentMinute());
     }
 
-    private class MockOnTimeChangeListener implements OnTimeChangedListener {
-        private TimePicker mNotifiedView;
-
-        private boolean mHasCalledOnTimeChanged;
-
-        private int mNotifiedHourOfDay;
-
-        private int mNotifiedMinute;;
-
-        public boolean hasCalledOnTimeChanged() {
-            return mHasCalledOnTimeChanged;
-        }
-
-        public TimePicker getNotifiedView() {
-            return mNotifiedView;
-        }
-
-        public int getNotifiedHourOfDay() {
-            return mNotifiedHourOfDay;
-        }
-
-        public int getNotifiedMinute() {
-            return mNotifiedMinute;
-        }
-
-        public void reset() {
-            mNotifiedView = null;
-            mNotifiedHourOfDay = 0;
-            mNotifiedMinute = 0;
-            mHasCalledOnTimeChanged = false;
-        }
-
-        public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
-            mNotifiedView = view;
-            mNotifiedHourOfDay = hourOfDay;
-            mNotifiedMinute = minute;
-            mHasCalledOnTimeChanged = true;
-        }
-    }
-
     private class MyTimePicker extends TimePicker {
         public MyTimePicker(Context context) {
             super(context);
diff --git a/tests/tests/widget/src/android/widget/cts/ToastTest.java b/tests/tests/widget/src/android/widget/cts/ToastTest.java
index 854247e..b029cc7 100644
--- a/tests/tests/widget/src/android/widget/cts/ToastTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ToastTest.java
@@ -74,22 +74,12 @@
     }
 
     private void assertShowToast(final View view) {
-        new PollingCheck(TIME_OUT) {
-            @Override
-            protected boolean check() {
-                return null != view.getParent();
-            }
-        }.run();
+        PollingCheck.waitFor(TIME_OUT, () -> null != view.getParent());
     }
 
     private void assertShowAndHide(final View view) {
         assertShowToast(view);
-        new PollingCheck(TIME_OUT) {
-            @Override
-            protected boolean check() {
-                return null == view.getParent();
-            }
-        }.run();
+        PollingCheck.waitFor(TIME_OUT, () -> null == view.getParent());
     }
 
     private void assertNotShowToast(final View view) throws InterruptedException {
@@ -104,12 +94,7 @@
     }
 
     private void assertLayoutDone(final View view) {
-        new PollingCheck(TIME_OUT) {
-            @Override
-            protected boolean check() {
-                return mLayoutDone;
-            }
-        }.run();
+        PollingCheck.waitFor(TIME_OUT, () -> mLayoutDone);
         view.getViewTreeObserver().removeOnGlobalLayoutListener(mLayoutListener);
     }
 
diff --git a/tests/tests/widget/src/android/widget/cts/ToggleButtonCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ToggleButtonCtsActivity.java
new file mode 100644
index 0000000..3640957
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ToggleButtonCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.ToggleButton;
+
+/**
+ * A minimal application for {@link ToggleButton} test.
+ */
+public class ToggleButtonCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.togglebutton_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/ToggleButtonTest.java b/tests/tests/widget/src/android/widget/cts/ToggleButtonTest.java
index d335c13..8d54b03 100644
--- a/tests/tests/widget/src/android/widget/cts/ToggleButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ToggleButtonTest.java
@@ -16,6 +16,11 @@
 
 package android.widget.cts;
 
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.widget.RadioButton;
 import org.xmlpull.v1.XmlPullParser;
 
 import android.content.Context;
@@ -34,27 +39,35 @@
 /**
  * Test {@link ToggleButton}.
  */
-public class ToggleButtonTest extends InstrumentationTestCase {
+@SmallTest
+public class ToggleButtonTest extends ActivityInstrumentationTestCase2<ToggleButtonCtsActivity> {
     private static final String TEXT_OFF = "text off";
     private static final String TEXT_ON = "text on";
-    ToggleButton mToggleButton;
-    Context mContext;
-    AttributeSet mAttrSet;
+
+    private Instrumentation mInstrumentation;
+    private Activity mActivity;
+
+    public ToggleButtonTest() {
+        super("android.widget.cts", ToggleButtonCtsActivity.class);
+    }
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
 
-        mContext = getInstrumentation().getTargetContext();
-        XmlPullParser parser = mContext.getResources().getXml(R.layout.togglebutton_layout);
-        mAttrSet = Xml.asAttributeSet(parser);
-        mToggleButton = new ToggleButton(mContext, mAttrSet);
+        mInstrumentation = getInstrumentation();
+        mActivity = getActivity();
     }
 
     public void testConstructor() {
-        new ToggleButton(mContext, mAttrSet, 0);
-        new ToggleButton(mContext, mAttrSet);
-        new ToggleButton(mContext);
+        new ToggleButton(mActivity);
+        new ToggleButton(mActivity, null);
+        new ToggleButton(mActivity, null, android.R.attr.buttonStyleToggle);
+        new ToggleButton(mActivity, null, 0, android.R.style.Widget_DeviceDefault_Button_Toggle);
+        new ToggleButton(mActivity, null, 0,
+                android.R.style.Widget_DeviceDefault_Light_Button_Toggle);
+        new ToggleButton(mActivity, null, 0, android.R.style.Widget_Material_Button_Toggle);
+        new ToggleButton(mActivity, null, 0, android.R.style.Widget_Material_Light_Button_Toggle);
 
         try {
             new ToggleButton(null, null, -1);
@@ -78,105 +91,127 @@
         }
     }
 
-    public void testAccessTextOff() {
-        mToggleButton.setTextOff("android");
-        assertEquals("android", mToggleButton.getTextOff());
-        mToggleButton.setChecked(false);
-
-        mToggleButton.setTextOff(null);
-        assertNull(mToggleButton.getTextOff());
-
-        mToggleButton.setTextOff("");
-        assertEquals("", mToggleButton.getTextOff());
+    public void testAttributesFromStyle() {
+        final ToggleButton toggleButton =
+                (ToggleButton) mActivity.findViewById(R.id.toggle_with_style);
+        assertEquals(mActivity.getString(R.string.toggle_text_on), toggleButton.getTextOn());
+        assertEquals(mActivity.getString(R.string.toggle_text_off), toggleButton.getTextOff());
     }
 
-    @UiThreadTest
+    public void testAttributesFromLayout() {
+        final ToggleButton toggleButton =
+                (ToggleButton) mActivity.findViewById(R.id.toggle_with_defaults);
+        assertEquals(mActivity.getString(R.string.toggle_text_on_alt), toggleButton.getTextOn());
+        assertEquals(mActivity.getString(R.string.toggle_text_off_alt), toggleButton.getTextOff());
+    }
+
+    public void testAccessTextOff() {
+        final ToggleButton toggleButton = (ToggleButton) mActivity.findViewById(R.id.toggle1);
+        mInstrumentation.runOnMainSync(() -> toggleButton.setTextOff("android"));
+        assertEquals("android", toggleButton.getTextOff());
+        mInstrumentation.runOnMainSync(() -> toggleButton.setChecked(false));
+
+        mInstrumentation.runOnMainSync(() -> toggleButton.setTextOff(null));
+        assertNull(toggleButton.getTextOff());
+
+        mInstrumentation.runOnMainSync(() -> toggleButton.setTextOff(""));
+        assertEquals("", toggleButton.getTextOff());
+    }
+
     public void testDrawableStateChanged() {
-        MockToggleButton toggleButton = new MockToggleButton(mContext);
+        final MockToggleButton toggleButton = new MockToggleButton(mActivity);
 
         // drawableStateChanged without any drawable.
-        toggleButton.drawableStateChanged();
+        mInstrumentation.runOnMainSync(() -> toggleButton.drawableStateChanged());
 
-        StateListDrawable drawable = new StateListDrawable();
+        final StateListDrawable drawable = new StateListDrawable();
         drawable.addState(new int[] { android.R.attr.state_pressed },
-                mContext.getDrawable(R.drawable.scenery));
+                mActivity.getDrawable(R.drawable.scenery));
         drawable.addState(new int[] {},
-                mContext.getDrawable(R.drawable.scenery));
+                mActivity.getDrawable(R.drawable.scenery));
 
         // drawableStateChanged when CheckMarkDrawable is not null.
-        toggleButton.setButtonDrawable(drawable);
+        mInstrumentation.runOnMainSync(() -> toggleButton.setButtonDrawable(drawable));
         drawable.setState(null);
         assertNull(drawable.getState());
 
-        toggleButton.drawableStateChanged();
+        mInstrumentation.runOnMainSync(() -> toggleButton.drawableStateChanged());
         assertNotNull(drawable.getState());
         assertEquals(toggleButton.getDrawableState(), drawable.getState());
     }
 
     public void testOnFinishInflate() {
-        MockToggleButton toggleButton = new MockToggleButton(mContext);
+        MockToggleButton toggleButton = new MockToggleButton(mActivity);
         toggleButton.onFinishInflate();
     }
 
-    @UiThreadTest
     public void testSetChecked() {
-        assertFalse(mToggleButton.isChecked());
+        final ToggleButton toggleButton = (ToggleButton) mActivity.findViewById(R.id.toggle1);
+        assertFalse(toggleButton.isChecked());
 
-        mToggleButton.setChecked(true);
-        assertTrue(mToggleButton.isChecked());
+        mInstrumentation.runOnMainSync(() -> toggleButton.setChecked(true));
+        assertTrue(toggleButton.isChecked());
 
-        mToggleButton.setChecked(false);
-        assertFalse(mToggleButton.isChecked());
+        mInstrumentation.runOnMainSync(() -> toggleButton.setChecked(false));
+        assertFalse(toggleButton.isChecked());
     }
 
-    @UiThreadTest
     public void testToggleText() {
-        mToggleButton.setText("default text");
-        mToggleButton.setTextOn(TEXT_ON);
-        mToggleButton.setTextOff(TEXT_OFF);
-        mToggleButton.setChecked(true);
-        assertEquals(TEXT_ON, mToggleButton.getText().toString());
-        mToggleButton.setChecked(false);
-        assertFalse(mToggleButton.isChecked());
-        assertEquals(TEXT_OFF, mToggleButton.getText().toString());
+        final ToggleButton toggleButton = (ToggleButton) mActivity.findViewById(R.id.toggle1);
+        mInstrumentation.runOnMainSync(() -> {
+            toggleButton.setText("default text");
+            toggleButton.setTextOn(TEXT_ON);
+            toggleButton.setTextOff(TEXT_OFF);
+            toggleButton.setChecked(true);
+        });
+        assertEquals(TEXT_ON, toggleButton.getText().toString());
+        toggleButton.setChecked(false);
+        assertFalse(toggleButton.isChecked());
+        assertEquals(TEXT_OFF, toggleButton.getText().toString());
 
         // Set the current displaying text as TEXT_OFF.
         // Then set checked button, but textOn is null.
-        mToggleButton.setTextOff(TEXT_OFF);
-        mToggleButton.setChecked(false);
-        mToggleButton.setTextOn(null);
-        mToggleButton.setChecked(true);
-        assertEquals(TEXT_OFF, mToggleButton.getText().toString());
+        mInstrumentation.runOnMainSync(() -> {
+            toggleButton.setTextOff(TEXT_OFF);
+            toggleButton.setChecked(false);
+            toggleButton.setTextOn(null);
+            toggleButton.setChecked(true);
+        });
+        assertEquals(TEXT_OFF, toggleButton.getText().toString());
 
         // Set the current displaying text as TEXT_ON. Then set unchecked button,
         // but textOff is null.
-        mToggleButton.setTextOn(TEXT_ON);
-        mToggleButton.setChecked(true);
-        mToggleButton.setTextOff(null);
-        mToggleButton.setChecked(false);
-        assertEquals(TEXT_ON, mToggleButton.getText().toString());
+        mInstrumentation.runOnMainSync(() -> {
+            toggleButton.setTextOn(TEXT_ON);
+            toggleButton.setChecked(true);
+            toggleButton.setTextOff(null);
+            toggleButton.setChecked(false);
+        });
+        assertEquals(TEXT_ON, toggleButton.getText().toString());
     }
 
     public void testSetBackgroundDrawable() {
-        Drawable drawable = mContext.getResources().getDrawable(R.drawable.scenery);
+        final ToggleButton toggleButton = (ToggleButton) mActivity.findViewById(R.id.toggle1);
+        final Drawable drawable = mActivity.getDrawable(R.drawable.scenery);
 
-        mToggleButton.setBackgroundDrawable(drawable);
-        assertSame(drawable, mToggleButton.getBackground());
+        mInstrumentation.runOnMainSync(() -> toggleButton.setBackgroundDrawable(drawable));
+        assertSame(drawable, toggleButton.getBackground());
 
         // remove the background
-        mToggleButton.setBackgroundDrawable(null);
-        assertNull(mToggleButton.getBackground());
+        mInstrumentation.runOnMainSync(() -> toggleButton.setBackgroundDrawable(null));
+        assertNull(toggleButton.getBackground());
     }
 
     public void testAccessTextOn() {
-        mToggleButton.setTextOn("cts");
-        assertEquals("cts", mToggleButton.getTextOn());
+        final ToggleButton toggleButton = (ToggleButton) mActivity.findViewById(R.id.toggle1);
+        mInstrumentation.runOnMainSync(() -> toggleButton.setTextOn("cts"));
+        assertEquals("cts", toggleButton.getTextOn());
 
-        mToggleButton.setTextOn(null);
-        assertNull(mToggleButton.getTextOn());
+        mInstrumentation.runOnMainSync(() -> toggleButton.setTextOn(null));
+        assertNull(toggleButton.getTextOn());
 
-        mToggleButton.setTextOn("");
-        assertEquals("", mToggleButton.getTextOn());
+        mInstrumentation.runOnMainSync(() -> toggleButton.setTextOn(""));
+        assertEquals("", toggleButton.getTextOn());
     }
 
     /**
diff --git a/tests/tests/widget/src/android/widget/cts/ToolbarTest.java b/tests/tests/widget/src/android/widget/cts/ToolbarTest.java
index 7f9690c..872e68c 100644
--- a/tests/tests/widget/src/android/widget/cts/ToolbarTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ToolbarTest.java
@@ -17,8 +17,6 @@
 package android.widget.cts;
 
 import android.app.Instrumentation;
-import android.content.Context;
-import android.content.res.TypedArray;
 import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 import android.test.ActivityInstrumentationTestCase2;
@@ -27,7 +25,6 @@
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
-import android.widget.ListPopupWindow;
 import android.widget.Toolbar;
 import android.widget.cts.util.TestUtils;
 import android.widget.cts.util.ViewTestUtils;
@@ -36,8 +33,9 @@
 
 @MediumTest
 public class ToolbarTest extends ActivityInstrumentationTestCase2<ToolbarCtsActivity> {
-    private Toolbar mMainToolbar;
+    private Instrumentation mInstrumentation;
     private ToolbarCtsActivity mActivity;
+    private Toolbar mMainToolbar;
 
     public ToolbarTest() {
         super("android.widget.cts", ToolbarCtsActivity.class);
@@ -46,6 +44,8 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+
+        mInstrumentation = getInstrumentation();
         mActivity = getActivity();
         mMainToolbar = mActivity.getMainToolbar();
     }
@@ -67,45 +67,41 @@
         // of getTitle / getSubtitle, this logic follows the path of deferred layout
         // and invalidation of the TextViews that show the title / subtitle in the Toolbar.
 
-        final Instrumentation instrumentation = getInstrumentation();
-
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setTitle(R.string.toolbar_title));
         assertEquals(mActivity.getString(R.string.toolbar_title), mMainToolbar.getTitle());
 
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setTitle("New title"));
         assertEquals("New title", mMainToolbar.getTitle());
 
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setSubtitle(R.string.toolbar_subtitle));
         assertEquals(mActivity.getString(R.string.toolbar_subtitle), mMainToolbar.getSubtitle());
 
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setSubtitle("New subtitle"));
         assertEquals("New subtitle", mMainToolbar.getSubtitle());
     }
 
     public void testTitleAndSubtitleAppearance() {
-        final Instrumentation instrumentation = getInstrumentation();
-
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setTitle(R.string.toolbar_title));
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setSubtitle(R.string.toolbar_subtitle));
 
         // Since there are no APIs to get reference to the underlying implementation of
         // title and subtitle, here we are testing that calling the relevant APIs doesn't crash
 
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setTitleTextColor(Color.RED));
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setSubtitleTextColor(Color.BLUE));
 
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setTitleTextAppearance(
                         mActivity, R.style.TextAppearance_NotColors));
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setSubtitleTextAppearance(
                         mActivity, R.style.TextAppearance_WithColor));
     }
@@ -139,9 +135,7 @@
     }
 
     public void testMenuContent() {
-        final Instrumentation instrumentation = getInstrumentation();
-
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
 
         final Menu menu = mMainToolbar.getMenu();
@@ -170,34 +164,30 @@
     }
 
     public void testMenuOverflowShowHide() {
-        final Instrumentation instrumentation = getInstrumentation();
-
         // Inflate menu and check that we're not showing overflow menu yet
-        instrumentation.runOnMainSync(() -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
         assertFalse(mMainToolbar.isOverflowMenuShowing());
 
         // Ask to show overflow menu and check that it's showing
-        instrumentation.runOnMainSync(() -> mMainToolbar.showOverflowMenu());
-        instrumentation.waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.showOverflowMenu());
+        mInstrumentation.waitForIdleSync();
         assertTrue(mMainToolbar.isOverflowMenuShowing());
 
         // Ask to hide the overflow menu and check that it's not showing
-        instrumentation.runOnMainSync(() -> mMainToolbar.hideOverflowMenu());
-        instrumentation.waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.hideOverflowMenu());
+        mInstrumentation.waitForIdleSync();
         assertFalse(mMainToolbar.isOverflowMenuShowing());
     }
 
     public void testMenuOverflowSubmenu() {
-        final Instrumentation instrumentation = getInstrumentation();
-
         // Inflate menu and check that we're not showing overflow menu yet
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
         assertFalse(mMainToolbar.isOverflowMenuShowing());
 
         // Ask to show overflow menu and check that it's showing
-        instrumentation.runOnMainSync(() -> mMainToolbar.showOverflowMenu());
-        instrumentation.waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.showOverflowMenu());
+        mInstrumentation.waitForIdleSync();
         assertTrue(mMainToolbar.isOverflowMenuShowing());
 
         // Register a mock menu item click listener on the toolbar
@@ -209,162 +199,256 @@
 
         // Ask to "perform" the share action and check that the menu click listener has
         // been notified
-        instrumentation.runOnMainSync(() -> menu.performIdentifierAction(R.id.action_share, 0));
+        mInstrumentation.runOnMainSync(() -> menu.performIdentifierAction(R.id.action_share, 0));
         verify(menuItemClickListener, times(1)).onMenuItemClick(
                 menu.findItem(R.id.action_share));
 
         // Ask to dismiss all the popups and check that we're not showing the overflow menu
-        instrumentation.runOnMainSync(() -> mMainToolbar.dismissPopupMenus());
-        instrumentation.waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.dismissPopupMenus());
+        mInstrumentation.waitForIdleSync();
         assertFalse(mMainToolbar.isOverflowMenuShowing());
     }
 
     public void testMenuOverflowIcon() {
-        final Instrumentation instrumentation = getInstrumentation();
-
         // Inflate menu and check that we're not showing overflow menu yet
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
 
         final Drawable overflowIcon = mActivity.getDrawable(R.drawable.icon_red);
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setOverflowIcon(overflowIcon));
 
         final Drawable toolbarOverflowIcon = mMainToolbar.getOverflowIcon();
         TestUtils.assertAllPixelsOfColor("Overflow icon is red", toolbarOverflowIcon,
                 toolbarOverflowIcon.getIntrinsicWidth(), toolbarOverflowIcon.getIntrinsicHeight(),
-                true, 0XFFFF0000, 1, false);
+                true, Color.RED, 1, false);
     }
 
     public void testActionView() {
-        final Instrumentation instrumentation = getInstrumentation();
-
         // Inflate menu and check that we don't have an expanded action view
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.inflateMenu(R.menu.toolbar_menu_search));
         assertFalse(mMainToolbar.hasExpandedActionView());
 
         // Expand search menu item's action view and verify that main toolbar has an expanded
         // action view
         final MenuItem searchMenuItem = mMainToolbar.getMenu().findItem(R.id.action_search);
-        instrumentation.runOnMainSync(() -> searchMenuItem.expandActionView());
-        instrumentation.waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> searchMenuItem.expandActionView());
+        mInstrumentation.waitForIdleSync();
         assertTrue(searchMenuItem.isActionViewExpanded());
         assertTrue(mMainToolbar.hasExpandedActionView());
 
         // Collapse search menu item's action view and verify that main toolbar doesn't have an
         // expanded action view
-        instrumentation.runOnMainSync(() -> searchMenuItem.collapseActionView());
-        instrumentation.waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> searchMenuItem.collapseActionView());
+        mInstrumentation.waitForIdleSync();
         assertFalse(searchMenuItem.isActionViewExpanded());
         assertFalse(mMainToolbar.hasExpandedActionView());
 
         // Expand search menu item's action view again
-        instrumentation.runOnMainSync(() -> searchMenuItem.expandActionView());
-        instrumentation.waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> searchMenuItem.expandActionView());
+        mInstrumentation.waitForIdleSync();
         assertTrue(searchMenuItem.isActionViewExpanded());
         assertTrue(mMainToolbar.hasExpandedActionView());
 
         // Now collapse search menu item's action view via toolbar's API and verify that main
         // toolbar doesn't have an expanded action view
-        instrumentation.runOnMainSync(() -> mMainToolbar.collapseActionView());
-        instrumentation.waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.collapseActionView());
+        mInstrumentation.waitForIdleSync();
         assertFalse(searchMenuItem.isActionViewExpanded());
         assertFalse(mMainToolbar.hasExpandedActionView());
     }
 
     public void testNavigationConfiguration() {
-        final Instrumentation instrumentation = getInstrumentation();
-
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setNavigationIcon(R.drawable.icon_green));
         Drawable toolbarNavigationIcon = mMainToolbar.getNavigationIcon();
         TestUtils.assertAllPixelsOfColor("Navigation icon is green", toolbarNavigationIcon,
                 toolbarNavigationIcon.getIntrinsicWidth(),
                 toolbarNavigationIcon.getIntrinsicHeight(),
-                true, 0xFF00FF00, 1, false);
+                true, Color.GREEN, 1, false);
 
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setNavigationIcon(mActivity.getDrawable(R.drawable.icon_blue)));
         toolbarNavigationIcon = mMainToolbar.getNavigationIcon();
         TestUtils.assertAllPixelsOfColor("Navigation icon is blue", toolbarNavigationIcon,
                 toolbarNavigationIcon.getIntrinsicWidth(),
                 toolbarNavigationIcon.getIntrinsicHeight(),
-                true, 0xFF0000FF, 1, false);
+                true, Color.BLUE, 1, false);
 
-        instrumentation.runOnMainSync(
+        mInstrumentation.runOnMainSync(
                 () -> mMainToolbar.setNavigationContentDescription(R.string.toolbar_navigation));
         assertEquals(mActivity.getResources().getString(R.string.toolbar_navigation),
                 mMainToolbar.getNavigationContentDescription());
 
-        instrumentation.runOnMainSync(
+        mInstrumentation.runOnMainSync(
                 () -> mMainToolbar.setNavigationContentDescription("Navigation legend"));
         assertEquals("Navigation legend", mMainToolbar.getNavigationContentDescription());
     }
 
     public void testLogoConfiguration() {
-        final Instrumentation instrumentation = getInstrumentation();
-
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setLogo(R.drawable.icon_yellow));
         Drawable toolbarLogo = mMainToolbar.getLogo();
         TestUtils.assertAllPixelsOfColor("Logo is yellow", toolbarLogo,
                 toolbarLogo.getIntrinsicWidth(),
                 toolbarLogo.getIntrinsicHeight(),
-                true, 0xFFFFFF00, 1, false);
+                true, Color.YELLOW, 1, false);
 
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setLogo(mActivity.getDrawable(R.drawable.icon_red)));
         toolbarLogo = mMainToolbar.getLogo();
         TestUtils.assertAllPixelsOfColor("Logo is red", toolbarLogo,
                 toolbarLogo.getIntrinsicWidth(),
                 toolbarLogo.getIntrinsicHeight(),
-                true, 0xFFFF0000, 1, false);
+                true, Color.RED, 1, false);
 
-        instrumentation.runOnMainSync(
+        mInstrumentation.runOnMainSync(
                 () -> mMainToolbar.setLogoDescription(R.string.toolbar_logo));
         assertEquals(mActivity.getResources().getString(R.string.toolbar_logo),
                 mMainToolbar.getLogoDescription());
 
-        instrumentation.runOnMainSync(
+        mInstrumentation.runOnMainSync(
                 () -> mMainToolbar.setLogoDescription("Logo legend"));
         assertEquals("Logo legend", mMainToolbar.getLogoDescription());
     }
 
-    @UiThreadTest
     public void testContentInsetsLtr() {
-        mMainToolbar.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
+        mInstrumentation.runOnMainSync(
+                () -> mMainToolbar.setLayoutDirection(View.LAYOUT_DIRECTION_LTR));
 
-        mMainToolbar.setContentInsetsAbsolute(20, 25);
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetsAbsolute(20, 25));
         assertEquals(20, mMainToolbar.getContentInsetLeft());
         assertEquals(20, mMainToolbar.getContentInsetStart());
         assertEquals(25, mMainToolbar.getContentInsetRight());
         assertEquals(25, mMainToolbar.getContentInsetEnd());
 
-        mMainToolbar.setContentInsetsRelative(40, 20);
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetsRelative(40, 20));
         assertEquals(40, mMainToolbar.getContentInsetLeft());
         assertEquals(40, mMainToolbar.getContentInsetStart());
         assertEquals(20, mMainToolbar.getContentInsetRight());
         assertEquals(20, mMainToolbar.getContentInsetEnd());
     }
 
-    @UiThreadTest
     public void testContentInsetsRtl() {
-        mMainToolbar.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
+        mInstrumentation.runOnMainSync(
+                () -> mMainToolbar.setLayoutDirection(View.LAYOUT_DIRECTION_RTL));
 
-        mMainToolbar.setContentInsetsAbsolute(20, 25);
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetsAbsolute(20, 25));
         assertEquals(20, mMainToolbar.getContentInsetLeft());
         assertEquals(25, mMainToolbar.getContentInsetStart());
         assertEquals(25, mMainToolbar.getContentInsetRight());
         assertEquals(20, mMainToolbar.getContentInsetEnd());
 
-        mMainToolbar.setContentInsetsRelative(40, 20);
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetsRelative(40, 20));
         assertEquals(20, mMainToolbar.getContentInsetLeft());
         assertEquals(40, mMainToolbar.getContentInsetStart());
         assertEquals(40, mMainToolbar.getContentInsetRight());
         assertEquals(20, mMainToolbar.getContentInsetEnd());
     }
 
+    public void testCurrentContentInsetsLtr() {
+        mInstrumentation.runOnMainSync(
+                () -> mMainToolbar.setLayoutDirection(View.LAYOUT_DIRECTION_LTR));
+
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetsRelative(20, 25));
+        assertEquals(20, mMainToolbar.getCurrentContentInsetLeft());
+        assertEquals(20, mMainToolbar.getCurrentContentInsetStart());
+        assertEquals(25, mMainToolbar.getCurrentContentInsetRight());
+        assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
+
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetStartWithNavigation(50));
+        assertEquals(50, mMainToolbar.getContentInsetStartWithNavigation());
+        // Since we haven't configured the navigation icon itself, the current content insets
+        // should stay the same
+        assertEquals(20, mMainToolbar.getCurrentContentInsetLeft());
+        assertEquals(20, mMainToolbar.getCurrentContentInsetStart());
+        assertEquals(25, mMainToolbar.getCurrentContentInsetRight());
+        assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
+
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
+                () -> mMainToolbar.setNavigationIcon(R.drawable.icon_green));
+        assertEquals(50, mMainToolbar.getContentInsetStartWithNavigation());
+        // Since we have configured the navigation icon, and the currently set start inset with
+        // navigation is bigger than currently set start content inset, we should be getting that
+        // bigger value now
+        assertEquals(50, mMainToolbar.getCurrentContentInsetLeft());
+        assertEquals(50, mMainToolbar.getCurrentContentInsetStart());
+        assertEquals(25, mMainToolbar.getCurrentContentInsetRight());
+        assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
+
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetEndWithActions(35));
+        assertEquals(35, mMainToolbar.getContentInsetEndWithActions());
+        // Since we haven't configured the menu content, the current content insets
+        // should stay the same
+        assertEquals(50, mMainToolbar.getCurrentContentInsetLeft());
+        assertEquals(50, mMainToolbar.getCurrentContentInsetStart());
+        assertEquals(25, mMainToolbar.getCurrentContentInsetRight());
+        assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
+
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
+                () -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
+        assertEquals(35, mMainToolbar.getContentInsetEndWithActions());
+        // Since we have configured the menu content, and the currently set start inset with
+        // navigation is bigger than currently set end content inset, we should be getting that
+        // bigger value now
+        assertEquals(50, mMainToolbar.getCurrentContentInsetLeft());
+        assertEquals(50, mMainToolbar.getCurrentContentInsetStart());
+        assertEquals(35, mMainToolbar.getCurrentContentInsetRight());
+        assertEquals(35, mMainToolbar.getCurrentContentInsetEnd());
+    }
+
+    public void testCurrentContentInsetsRtl() {
+        mInstrumentation.runOnMainSync(
+                () -> mMainToolbar.setLayoutDirection(View.LAYOUT_DIRECTION_RTL));
+
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetsRelative(20, 25));
+        assertEquals(25, mMainToolbar.getCurrentContentInsetLeft());
+        assertEquals(20, mMainToolbar.getCurrentContentInsetStart());
+        assertEquals(20, mMainToolbar.getCurrentContentInsetRight());
+        assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
+
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetStartWithNavigation(50));
+        assertEquals(50, mMainToolbar.getContentInsetStartWithNavigation());
+        // Since we haven't configured the navigation icon itself, the current content insets
+        // should stay the same
+        assertEquals(25, mMainToolbar.getCurrentContentInsetLeft());
+        assertEquals(20, mMainToolbar.getCurrentContentInsetStart());
+        assertEquals(20, mMainToolbar.getCurrentContentInsetRight());
+        assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
+
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
+                () -> mMainToolbar.setNavigationIcon(R.drawable.icon_green));
+        assertEquals(50, mMainToolbar.getContentInsetStartWithNavigation());
+        // Since we have configured the navigation icon, and the currently set start inset with
+        // navigation is bigger than currently set start content inset, we should be getting that
+        // bigger value now
+        assertEquals(25, mMainToolbar.getCurrentContentInsetLeft());
+        assertEquals(50, mMainToolbar.getCurrentContentInsetStart());
+        assertEquals(50, mMainToolbar.getCurrentContentInsetRight());
+        assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
+
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetEndWithActions(35));
+        assertEquals(35, mMainToolbar.getContentInsetEndWithActions());
+        // Since we haven't configured the menu content, the current content insets
+        // should stay the same
+        assertEquals(25, mMainToolbar.getCurrentContentInsetLeft());
+        assertEquals(50, mMainToolbar.getCurrentContentInsetStart());
+        assertEquals(50, mMainToolbar.getCurrentContentInsetRight());
+        assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
+
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
+                () -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
+        assertEquals(35, mMainToolbar.getContentInsetEndWithActions());
+        // Since we have configured the menu content, and the currently set start inset with
+        // navigation is bigger than currently set end content inset, we should be getting that
+        // bigger value now
+        assertEquals(35, mMainToolbar.getCurrentContentInsetLeft());
+        assertEquals(50, mMainToolbar.getCurrentContentInsetStart());
+        assertEquals(50, mMainToolbar.getCurrentContentInsetRight());
+        assertEquals(35, mMainToolbar.getCurrentContentInsetEnd());
+    }
+
     @UiThreadTest
     public void testPopupTheme() {
         mMainToolbar.setPopupTheme(R.style.ToolbarPopupTheme_Test);
@@ -377,7 +461,7 @@
 
         verify(mockListener, never()).onClick(any(View.class));
 
-        getInstrumentation().runOnMainSync(() -> mMainToolbar.getNavigationView().performClick());
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.getNavigationView().performClick());
         verify(mockListener, times(1)).onClick(any(View.class));
 
         verifyNoMoreInteractions(mockListener);
diff --git a/tests/tests/widget/src/android/widget/cts/VideoViewTest.java b/tests/tests/widget/src/android/widget/cts/VideoViewTest.java
index 265b802..7bb2ef8 100644
--- a/tests/tests/widget/src/android/widget/cts/VideoViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/VideoViewTest.java
@@ -16,19 +16,11 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.content.Context;
 import android.cts.util.MediaUtils;
-import android.cts.util.PollingCheck;
-import android.media.MediaCodecInfo;
-import android.media.MediaCodecList;
 import android.media.MediaPlayer;
-import android.media.MediaPlayer.OnCompletionListener;
-import android.media.MediaPlayer.OnErrorListener;
-import android.media.MediaPlayer.OnPreparedListener;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
 import android.util.Log;
@@ -36,9 +28,16 @@
 import android.widget.MediaController;
 import android.widget.VideoView;
 
+import org.mockito.invocation.InvocationOnMock;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.*;
 
 /**
  * Test {@link VideoView}.
@@ -63,43 +62,6 @@
     private Instrumentation mInstrumentation;
     private String mVideoPath;
 
-    private static class MockListener {
-        private boolean mTriggered;
-
-        MockListener() {
-            mTriggered = false;
-        }
-
-        public boolean isTriggered() {
-            return mTriggered;
-        }
-
-        protected void onEvent() {
-            mTriggered = true;
-        }
-    }
-
-    private static class MockOnPreparedListener extends MockListener
-            implements OnPreparedListener {
-        public void onPrepared(MediaPlayer mp) {
-            super.onEvent();
-        }
-    }
-
-    private static class MockOnErrorListener extends MockListener implements OnErrorListener {
-        public boolean onError(MediaPlayer mp, int what, int extra) {
-            super.onEvent();
-            return false;
-        }
-    }
-
-    private static class MockOnCompletionListener extends MockListener
-            implements OnCompletionListener {
-        public void onCompletion(MediaPlayer mp) {
-            super.onEvent();
-        }
-    }
-
     private boolean hasCodec() {
         return MediaUtils.hasCodecsForResource(mActivity, R.raw.testvideo);
     }
@@ -190,42 +152,46 @@
             return;
         }
 
-        final MockOnPreparedListener preparedListener = new MockOnPreparedListener();
-        mVideoView.setOnPreparedListener(preparedListener);
-        final MockOnCompletionListener completionListener = new MockOnCompletionListener();
-        mVideoView.setOnCompletionListener(completionListener);
+        final MediaPlayer.OnPreparedListener mockPreparedListener =
+                mock(MediaPlayer.OnPreparedListener.class);
+        final CountDownLatch preparedLatch = new CountDownLatch(1);
+        doAnswer((InvocationOnMock invocation) -> {
+            preparedLatch.countDown();
+            return null;
+        }).when(mockPreparedListener).onPrepared(any(MediaPlayer.class));
+        mVideoView.setOnPreparedListener(mockPreparedListener);
 
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                mVideoView.setVideoPath(mVideoPath);
-            }
-        });
-        new PollingCheck(TIME_OUT) {
-            @Override
-            protected boolean check() {
-                return preparedListener.isTriggered();
-            }
-        }.run();
-        assertFalse(completionListener.isTriggered());
+        final MediaPlayer.OnCompletionListener mockCompletionListener =
+                mock(MediaPlayer.OnCompletionListener.class);
+        final CountDownLatch completionLatch = new CountDownLatch(1);
+        doAnswer((InvocationOnMock invocation) -> {
+            completionLatch.countDown();
+            return null;
+        }).when(mockCompletionListener).onCompletion(any(MediaPlayer.class));
+        mVideoView.setOnCompletionListener(mockCompletionListener);
 
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                mVideoView.start();
-            }
-        });
+        runTestOnUiThread(() -> mVideoView.setVideoPath(mVideoPath));
+        preparedLatch.await(TIME_OUT, TimeUnit.MILLISECONDS);
+        verify(mockPreparedListener, times(1)).onPrepared(any(MediaPlayer.class));
+        verifyZeroInteractions(mockCompletionListener);
+
+        runTestOnUiThread(() -> mVideoView.start());
         // wait time is longer than duration in case system is sluggish
-        new PollingCheck(mVideoView.getDuration() + TIME_OUT) {
-            @Override
-            protected boolean check() {
-                return completionListener.isTriggered();
-            }
-        }.run();
+        completionLatch.await(mVideoView.getDuration() + TIME_OUT, TimeUnit.MILLISECONDS);
+        verify(mockCompletionListener, times(1)).onCompletion(any(MediaPlayer.class));
     }
 
     public void testSetOnErrorListener() throws Throwable {
         makeVideoView();
-        final MockOnErrorListener listener = new MockOnErrorListener();
-        mVideoView.setOnErrorListener(listener);
+
+        final MediaPlayer.OnErrorListener mockErrorListener =
+                mock(MediaPlayer.OnErrorListener.class);
+        final CountDownLatch errorLatch = new CountDownLatch(1);
+        doAnswer((InvocationOnMock invocation) -> {
+            errorLatch.countDown();
+            return null;
+        }).when(mockErrorListener).onError(any(MediaPlayer.class), anyInt(), anyInt());
+        mVideoView.setOnErrorListener(mockErrorListener);
 
         runTestOnUiThread(new Runnable() {
             public void run() {
@@ -236,12 +202,8 @@
         });
         mInstrumentation.waitForIdleSync();
 
-        new PollingCheck(TIME_OUT) {
-            @Override
-            protected boolean check() {
-                return listener.isTriggered();
-            }
-        }.run();
+        errorLatch.await(TIME_OUT, TimeUnit.MILLISECONDS);
+        verify(mockErrorListener, times(1)).onError(any(MediaPlayer.class), anyInt(), anyInt());
     }
 
     public void testGetBufferPercentage() throws Throwable {
@@ -252,22 +214,20 @@
             return;
         }
 
-        final MockOnPreparedListener prepareListener = new MockOnPreparedListener();
-        mVideoView.setOnPreparedListener(prepareListener);
+        final MediaPlayer.OnPreparedListener mockPreparedListener =
+                mock(MediaPlayer.OnPreparedListener.class);
+        final CountDownLatch preparedLatch = new CountDownLatch(1);
+        doAnswer((InvocationOnMock invocation) -> {
+            preparedLatch.countDown();
+            return null;
+        }).when(mockPreparedListener).onPrepared(any(MediaPlayer.class));
+        mVideoView.setOnPreparedListener(mockPreparedListener);
 
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                mVideoView.setVideoPath(mVideoPath);
-            }
-        });
+        runTestOnUiThread(() -> mVideoView.setVideoPath(mVideoPath));
         mInstrumentation.waitForIdleSync();
 
-        new PollingCheck(TIME_OUT) {
-            @Override
-            protected boolean check() {
-                return prepareListener.isTriggered();
-            }
-        }.run();
+        preparedLatch.await(TIME_OUT, TimeUnit.MILLISECONDS);
+        verify(mockPreparedListener, times(1)).onPrepared(any(MediaPlayer.class));
         int percent = mVideoView.getBufferPercentage();
         assertTrue(percent >= 0 && percent <= 100);
     }
@@ -295,11 +255,7 @@
             return;
         }
 
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                mVideoView.setVideoPath(mVideoPath);
-            }
-        });
+        runTestOnUiThread(() -> mVideoView.setVideoPath(mVideoPath));
         waitForOperationComplete();
         assertTrue(Math.abs(mVideoView.getDuration() - TEST_VIDEO_DURATION) < DURATION_DELTA);
     }
diff --git a/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java b/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java
index 493c484..4cedd4f 100644
--- a/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java
@@ -16,23 +16,28 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-
 import android.app.Activity;
-import android.cts.util.PollingCheck;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.util.AttributeSet;
 import android.util.Xml;
 import android.view.View;
-import android.view.View.OnClickListener;
+import android.view.ViewConfiguration;
 import android.widget.ListView;
 import android.widget.ZoomButton;
+import android.widget.cts.util.ViewTestUtils;
 
+import org.xmlpull.v1.XmlPullParser;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+@SmallTest
 public class ZoomButtonTest extends ActivityInstrumentationTestCase2<ZoomButtonCtsActivity> {
+    private static long NANOS_IN_MILLI = 1000000;
     private ZoomButton mZoomButton;
     private Activity mActivity;
 
@@ -54,7 +59,9 @@
 
         new ZoomButton(mActivity, null);
 
-        new ZoomButton(mActivity, null, 0);
+        new ZoomButton(mActivity, null, android.R.attr.imageButtonStyle);
+
+        new ZoomButton(mActivity, null, 0, android.R.style.Widget_Material_Light_ImageButton);
 
         XmlPullParser parser = mActivity.getResources().getXml(R.layout.zoombutton_layout);
         AttributeSet attrs = Xml.asAttributeSet(parser);
@@ -81,6 +88,7 @@
         }
     }
 
+    @UiThreadTest
     public void testSetEnabled() {
         assertFalse(mZoomButton.isPressed());
         mZoomButton.setEnabled(true);
@@ -105,21 +113,54 @@
         assertFalse(mZoomButton.dispatchUnhandledMove(null, View.FOCUS_DOWN));
     }
 
-    public void testOnLongClick() {
-        final MockOnClickListener listener = new MockOnClickListener();
-        mZoomButton.setOnClickListener(listener);
-        mZoomButton.setEnabled(true);
-        long speed = 2000;
-        mZoomButton.setZoomSpeed(speed);
+    private void verifyZoomSpeed(ZoomClickListener zoomClickListener, long zoomSpeedMs) {
+        mZoomButton.setZoomSpeed(zoomSpeedMs);
 
-        assertFalse(listener.hasOnClickCalled());
-        mZoomButton.performLongClick();
-        new PollingCheck(speed + 500) {
-            @Override
-            protected boolean check() {
-                return listener.hasOnClickCalled();
+        final long startTime = System.nanoTime();
+        // Emulate long click that "lasts" for ten seconds
+        ViewTestUtils.emulateLongClick(getInstrumentation(), mZoomButton, 10000);
+
+        final List<Long> callbackInvocations = zoomClickListener.getClickTimes();
+        assertFalse("Expecting at least one callback", callbackInvocations.isEmpty());
+
+        // Verify that the first callback is fired after the system-level long press timeout.
+        final long minTimeUntilFirstInvocationMs = ViewConfiguration.getLongPressTimeout();
+        final long actualTimeUntilFirstInvocationNs = callbackInvocations.get(0) - startTime;
+        assertTrue("First callback not during long press timeout was " +
+                        actualTimeUntilFirstInvocationNs / NANOS_IN_MILLI +
+                        " while long press timeout is " + minTimeUntilFirstInvocationMs,
+                (callbackInvocations.get(0) - startTime) >
+                        minTimeUntilFirstInvocationMs * NANOS_IN_MILLI);
+
+        // Verify that subsequent callbacks are at least zoom-speed milliseconds apart. Note that
+        // we do not have any hard guarantee about the max limit on the time between successive
+        // callbacks.
+        final long minTimeBetweenInvocationsNs = zoomSpeedMs * NANOS_IN_MILLI;
+        if (callbackInvocations.size() > 1) {
+            for (int i = 0; i < callbackInvocations.size() - 1; i++) {
+                final long actualTimeBetweenInvocationsNs =
+                        (callbackInvocations.get(i + 1) - callbackInvocations.get(i)) *
+                                NANOS_IN_MILLI;
+                assertTrue("Callback " + (i + 1) + " happened " +
+                                actualTimeBetweenInvocationsNs / NANOS_IN_MILLI +
+                                " after the previous one, while zoom speed is " + zoomSpeedMs,
+                        actualTimeBetweenInvocationsNs > minTimeBetweenInvocationsNs);
             }
-        };
+        }
+    }
+
+    @LargeTest
+    public void testOnLongClick() {
+        // Since Mockito doesn't have utilities to track the timestamps of method invocations,
+        // we're using our own custom click listener for that. We want to verify that the
+        // first listener invocation was after long press timeout, and the rest were spaced
+        // by at least our zoom speed milliseconds
+
+        mZoomButton.setEnabled(true);
+        ZoomClickListener zoomClickListener = new ZoomClickListener();
+        mZoomButton.setOnClickListener(zoomClickListener);
+
+        verifyZoomSpeed(zoomClickListener, 2000);
     }
 
     public void testOnTouchEvent() {
@@ -130,22 +171,35 @@
         // Do not test. Implementation details.
     }
 
+    @LargeTest
     public void testSetZoomSpeed() {
-        mZoomButton.setZoomSpeed(100);
+        final long[] zoomSpeeds = { 100, -1, 5000, 1000, 2500 };
+        mZoomButton.setEnabled(true);
+        ZoomClickListener zoomClickListener = new ZoomClickListener();
+        mZoomButton.setOnClickListener(zoomClickListener);
 
-        mZoomButton.setZoomSpeed(-1);
-        // TODO: how to check?
+        for (long zoomSpeed : zoomSpeeds) {
+            // Reset the tracker list of our listener, but continue using it for testing
+            // various zoom speeds on the same ZoomButton
+            zoomClickListener.reset();
+            verifyZoomSpeed(zoomClickListener, zoomSpeed);
+        }
     }
 
-    private static class MockOnClickListener implements OnClickListener {
-        private boolean mOnClickCalled = false;
+    private static class ZoomClickListener implements View.OnClickListener {
+        private List<Long> mClickTimes = new ArrayList<>();
 
-        public boolean hasOnClickCalled() {
-            return mOnClickCalled;
+        public void reset() {
+            mClickTimes.clear();
+        }
+
+        public List<Long> getClickTimes() {
+            return Collections.unmodifiableList(mClickTimes);
         }
 
         public void onClick(View v) {
-            mOnClickCalled = true;
+            // Add the current system time to the tracker list
+            mClickTimes.add(System.nanoTime());
         }
     }
-}
+}
\ No newline at end of file
diff --git a/tests/tests/widget/src/android/widget/cts/util/ExpandableListScenario.java b/tests/tests/widget/src/android/widget/cts/util/ExpandableListScenario.java
index 1b2eb15..7e72e88 100644
--- a/tests/tests/widget/src/android/widget/cts/util/ExpandableListScenario.java
+++ b/tests/tests/widget/src/android/widget/cts/util/ExpandableListScenario.java
@@ -54,7 +54,10 @@
 
     @Override
     protected void setAdapter(ListView listView) {
-        ((ExpandableListView) listView).setAdapter(mAdapter = createAdapter());
+        mAdapter = createAdapter();
+        if (mAdapter != null) {
+            ((ExpandableListView) listView).setAdapter(mAdapter);
+        }
     }
 
     protected ExpandableListAdapter createAdapter() {
@@ -91,7 +94,7 @@
         /**
          * Sets the number of children per group.
          *
-         * @param numChildrenPerGroup The number of children per group.
+         * @param numChildren The number of children per group.
          */
         public ExpandableParams setNumChildren(int[] numChildren) {
             mNumChildren = numChildren;
@@ -275,6 +278,10 @@
      * @return A group index with the requirements.
      */
     public int findGroupWithNumChildren(int numChildren, boolean atLeastOneChild) {
+        if (mAdapter == null) {
+            return -1;
+        }
+
         final ExpandableListAdapter adapter = mAdapter;
 
         for (int i = adapter.getGroupCount() - 1; i >= 0; i--) {
@@ -292,10 +299,6 @@
         return mGroups;
     }
 
-    public ExpandableListAdapter getAdapter() {
-        return mAdapter;
-    }
-
     /**
      * Simple expandable list adapter.
      */
@@ -348,10 +351,10 @@
     }
 
     public static class MyGroup {
-        private static long mNextId = 1000;
+        private static long sNextId = 1000;
 
         String name;
-        long id = mNextId++;
+        long id = sNextId++;
         List<MyChild> children;
 
         public MyGroup(int numChildren) {
diff --git a/tests/tests/widget/src/android/widget/cts/util/ListScenario.java b/tests/tests/widget/src/android/widget/cts/util/ListScenario.java
index b61673c..c4d4199 100644
--- a/tests/tests/widget/src/android/widget/cts/util/ListScenario.java
+++ b/tests/tests/widget/src/android/widget/cts/util/ListScenario.java
@@ -79,10 +79,6 @@
         return mListView;
     }
 
-    protected int getScreenHeight() {
-        return mScreenHeight;
-    }
-
     /**
      * Return whether the item at position is selectable (i.e is a separator).
      * (external users can access this info using the adapter)
@@ -288,15 +284,6 @@
         setClickedPosition(position);
     }
 
-    /**
-     * Override this if you want to know when something has been long clicked (perhaps
-     * more importantly, that {@link android.widget.AdapterView.OnItemLongClickListener} has
-     * been triggered).
-     */
-    protected void positionLongClicked(int position) {
-        setLongClickedPosition(position);
-    }
-
     @Override
     protected void onCreate(Bundle icicle) {
         super.onCreate(icicle);
@@ -353,11 +340,13 @@
             }
         });
 
-        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
-            public void onItemClick(AdapterView parent, View v, int position, long id) {
-                positionClicked(position);
-            }
-        });
+        if (shouldRegisterItemClickListener()) {
+            mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+                public void onItemClick(AdapterView parent, View v, int position, long id) {
+                    positionClicked(position);
+                }
+            });
+        }
 
         // set the fading edge length porportionally to the screen
         // height for test stability
@@ -404,25 +393,11 @@
     }
 
     /**
-     * Returns the LinearLayout containing the ListView in this scenario.
-     *
-     * @return The LinearLayout in which the ListView is held.
+     * Override to return false if you don't want the activity to register a default item click
+     * listener that redirects clicks to {@link #positionClicked(int)}.
      */
-    protected LinearLayout getListViewContainer() {
-        return mLinearLayout;
-    }
-
-    /**
-     * Attaches a long press listener. You can find out which views were clicked by calling
-     * {@link #getLongClickedPosition()}.
-     */
-    public void enableLongPress() {
-        mListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
-            public boolean onItemLongClick(AdapterView parent, View v, int position, long id) {
-                positionLongClicked(position);
-                return true;
-            }
-        });
+    protected boolean shouldRegisterItemClickListener() {
+        return true;
     }
 
     /**
diff --git a/tests/tests/widget/src/android/widget/cts/util/TestUtils.java b/tests/tests/widget/src/android/widget/cts/util/TestUtils.java
index 8d8f573..2a043f6 100644
--- a/tests/tests/widget/src/android/widget/cts/util/TestUtils.java
+++ b/tests/tests/widget/src/android/widget/cts/util/TestUtils.java
@@ -16,20 +16,30 @@
 
 package android.widget.cts.util;
 
+import android.annotation.ColorInt;
+import android.annotation.NonNull;
+import android.content.Context;
+import android.content.res.ColorStateList;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
-import android.support.annotation.ColorInt;
-import android.support.annotation.NonNull;
+import android.text.Editable;
+import android.text.TextUtils;
 import android.util.Pair;
 import android.view.View;
 import android.view.ViewParent;
 import junit.framework.Assert;
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
+import static org.mockito.Matchers.argThat;
+
 public class TestUtils {
     /**
      * This method takes a view and returns a single bitmap that is the layered combination
@@ -100,7 +110,8 @@
     }
 
     /**
-     * Checks whether all the pixels in the specified View are of the same specified color.
+     * Checks whether all the pixels in the specified of the {@link View} are
+     * filled with the specific color.
      *
      * In case there is a color mismatch, the behavior of this method depends on the
      * <code>throwExceptionIfFails</code> parameter. If it is <code>true</code>, this method will
@@ -109,7 +120,26 @@
      */
     public static void assertAllPixelsOfColor(String failMessagePrefix, @NonNull View view,
             @ColorInt int color, int allowedComponentVariance, boolean throwExceptionIfFails) {
+        assertRegionPixelsOfColor(failMessagePrefix, view,
+                new Rect(0, 0, view.getWidth(), view.getHeight()),
+                color, allowedComponentVariance, throwExceptionIfFails);
+    }
+
+    /**
+     * Checks whether all the pixels in the specific rectangular region of the {@link View} are
+     * filled with the specific color.
+     *
+     * In case there is a color mismatch, the behavior of this method depends on the
+     * <code>throwExceptionIfFails</code> parameter. If it is <code>true</code>, this method will
+     * throw an <code>Exception</code> describing the mismatch. Otherwise this method will call
+     * <code>Assert.fail</code> with detailed description of the mismatch.
+     */
+    public static void assertRegionPixelsOfColor(String failMessagePrefix, @NonNull View view,
+            @NonNull Rect region, @ColorInt int color, int allowedComponentVariance,
+            boolean throwExceptionIfFails) {
         // Create a bitmap
+        final int viewWidth = view.getWidth();
+        final int viewHeight = view.getHeight();
         Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),
                 Bitmap.Config.ARGB_8888);
         // Create a canvas that wraps the bitmap
@@ -118,7 +148,7 @@
         view.draw(canvas);
 
         try {
-            assertAllPixelsOfColor(failMessagePrefix, bitmap, view.getWidth(), view.getHeight(),
+            assertAllPixelsOfColor(failMessagePrefix, bitmap, region,
                     color, allowedComponentVariance, throwExceptionIfFails);
         } finally {
             bitmap.recycle();
@@ -126,7 +156,8 @@
     }
 
     /**
-     * Checks whether all the pixels in the specified drawable are of the same specified color.
+     * Checks whether all the pixels in the specified {@link Drawable} are filled with the specific
+     * color.
      *
      * In case there is a color mismatch, the behavior of this method depends on the
      * <code>throwExceptionIfFails</code> parameter. If it is <code>true</code>, this method will
@@ -136,20 +167,25 @@
     public static void assertAllPixelsOfColor(String failMessagePrefix, @NonNull Drawable drawable,
             int drawableWidth, int drawableHeight, boolean callSetBounds, @ColorInt int color,
             int allowedComponentVariance, boolean throwExceptionIfFails) {
-            // Create a bitmap
-            Bitmap bitmap = Bitmap.createBitmap(drawableWidth, drawableHeight,
-                    Bitmap.Config.ARGB_8888);
-            // Create a canvas that wraps the bitmap
-            Canvas canvas = new Canvas(bitmap);
-            if (callSetBounds) {
-                // Configure the drawable to have bounds that match the passed size
-                drawable.setBounds(0, 0, drawableWidth, drawableHeight);
-            }
-            // And ask the drawable to draw itself to the canvas / bitmap
-            drawable.draw(canvas);
+        // Create a bitmap
+        Bitmap bitmap = Bitmap.createBitmap(drawableWidth, drawableHeight,
+                Bitmap.Config.ARGB_8888);
+        // Create a canvas that wraps the bitmap
+        Canvas canvas = new Canvas(bitmap);
+        if (callSetBounds) {
+            // Configure the drawable to have bounds that match the passed size
+            drawable.setBounds(0, 0, drawableWidth, drawableHeight);
+        } else {
+            // Query the current bounds of the drawable for translation
+            Rect drawableBounds = drawable.getBounds();
+            canvas.translate(-drawableBounds.left, -drawableBounds.top);
+        }
+        // And ask the drawable to draw itself to the canvas / bitmap
+        drawable.draw(canvas);
 
         try {
-            assertAllPixelsOfColor(failMessagePrefix, bitmap, drawableWidth, drawableHeight, color,
+            assertAllPixelsOfColor(failMessagePrefix, bitmap,
+                    new Rect(0, 0, drawableWidth, drawableHeight), color,
                     allowedComponentVariance, throwExceptionIfFails);
         } finally {
             bitmap.recycle();
@@ -157,49 +193,39 @@
     }
 
     /**
-     * Checks whether all the pixels in the specified bitmap are of the same specified color.
+     * Checks whether all the pixels in the specific rectangular region of the bitmap are filled
+     * with the specific color.
      *
      * In case there is a color mismatch, the behavior of this method depends on the
      * <code>throwExceptionIfFails</code> parameter. If it is <code>true</code>, this method will
      * throw an <code>Exception</code> describing the mismatch. Otherwise this method will call
      * <code>Assert.fail</code> with detailed description of the mismatch.
      */
-    public static void assertAllPixelsOfColor(String failMessagePrefix, @NonNull Bitmap bitmap,
-            int bitmapWidth, int bitmapHeight, @ColorInt int color,
-            int allowedComponentVariance, boolean throwExceptionIfFails) {
-            int[] rowPixels = new int[bitmapWidth];
-        for (int row = 0; row < bitmapHeight; row++) {
+    private static void assertAllPixelsOfColor(String failMessagePrefix, @NonNull Bitmap bitmap,
+            @NonNull Rect region, @ColorInt int color, int allowedComponentVariance,
+            boolean throwExceptionIfFails) {
+        final int bitmapWidth = bitmap.getWidth();
+        final int bitmapHeight = bitmap.getHeight();
+        final int[] rowPixels = new int[bitmapWidth];
+
+        final int startRow = region.top;
+        final int endRow = region.bottom;
+        final int startColumn = region.left;
+        final int endColumn = region.right;
+
+        for (int row = startRow; row < endRow; row++) {
             bitmap.getPixels(rowPixels, 0, bitmapWidth, 0, row, bitmapWidth, 1);
-            for (int column = 0; column < bitmapWidth; column++) {
-                int sourceAlpha = Color.alpha(rowPixels[column]);
-                int sourceRed = Color.red(rowPixels[column]);
-                int sourceGreen = Color.green(rowPixels[column]);
-                int sourceBlue = Color.blue(rowPixels[column]);
-
-                int expectedAlpha = Color.alpha(color);
-                int expectedRed = Color.red(color);
-                int expectedGreen = Color.green(color);
-                int expectedBlue = Color.blue(color);
-
-                int varianceAlpha = Math.abs(sourceAlpha - expectedAlpha);
-                int varianceRed = Math.abs(sourceRed - expectedRed);
-                int varianceGreen = Math.abs(sourceGreen - expectedGreen);
-                int varianceBlue = Math.abs(sourceBlue - expectedBlue);
-
-                boolean isColorMatch = (varianceAlpha <= allowedComponentVariance)
-                        && (varianceRed <= allowedComponentVariance)
-                        && (varianceGreen <= allowedComponentVariance)
-                        && (varianceBlue <= allowedComponentVariance);
-
-                if (!isColorMatch) {
+            for (int column = startColumn; column < endColumn; column++) {
+                @ColorInt int colorAtCurrPixel = rowPixels[column];
+                if (!areColorsTheSameWithTolerance(color, colorAtCurrPixel,
+                        allowedComponentVariance)) {
                     String mismatchDescription = failMessagePrefix
-                            + ": expected all drawable colors to be ["
-                            + expectedAlpha + "," + expectedRed + ","
-                            + expectedGreen + "," + expectedBlue
-                            + "] but at position (" + row + "," + column + ") out of ("
-                            + bitmapWidth + "," + bitmapHeight + ") found ["
-                            + sourceAlpha + "," + sourceRed + ","
-                            + sourceGreen + "," + sourceBlue + "]";
+                            + ": expected all bitmap colors in rectangle [l="
+                            + startColumn + ", t=" + startRow + ", r=" + endColumn
+                            + ", b=" + endRow + "] to be " + formatColorToHex(color)
+                            + " but at position (" + row + "," + column + ") out of ("
+                            + bitmapWidth + "," + bitmapHeight + ") found "
+                            + formatColorToHex(colorAtCurrPixel);
                     if (throwExceptionIfFails) {
                         throw new RuntimeException(mismatchDescription);
                     } else {
@@ -209,4 +235,179 @@
             }
         }
     }
+
+    /**
+     * Checks whether the center pixel in the specified bitmap is of the same specified color.
+     *
+     * In case there is a color mismatch, the behavior of this method depends on the
+     * <code>throwExceptionIfFails</code> parameter. If it is <code>true</code>, this method will
+     * throw an <code>Exception</code> describing the mismatch. Otherwise this method will call
+     * <code>Assert.fail</code> with detailed description of the mismatch.
+     */
+    public static void assertCenterPixelOfColor(String failMessagePrefix, @NonNull Bitmap bitmap,
+            @ColorInt int color,
+            int allowedComponentVariance, boolean throwExceptionIfFails) {
+        final int centerX = bitmap.getWidth() / 2;
+        final int centerY = bitmap.getHeight() / 2;
+        final @ColorInt int colorAtCenterPixel = bitmap.getPixel(centerX, centerY);
+        if (!areColorsTheSameWithTolerance(color, colorAtCenterPixel,
+                allowedComponentVariance)) {
+            String mismatchDescription = failMessagePrefix
+                    + ": expected all drawable colors to be "
+                    + formatColorToHex(color)
+                    + " but at position (" + centerX + "," + centerY + ") out of ("
+                    + bitmap.getWidth() + "," + bitmap.getHeight() + ") found"
+                    + formatColorToHex(colorAtCenterPixel);
+            if (throwExceptionIfFails) {
+                throw new RuntimeException(mismatchDescription);
+            } else {
+                Assert.fail(mismatchDescription);
+            }
+        }
+    }
+
+    /**
+     * Formats the passed integer-packed color into the #AARRGGBB format.
+     */
+    public static String formatColorToHex(@ColorInt int color) {
+        return String.format("#%08X", (0xFFFFFFFF & color));
+    }
+
+    /**
+     * Compares two integer-packed colors to be equal, each component within the specified
+     * allowed variance. Returns <code>true</code> if the two colors are sufficiently equal
+     * and <code>false</code> otherwise.
+     */
+    private static boolean areColorsTheSameWithTolerance(@ColorInt int expectedColor,
+            @ColorInt int actualColor, int allowedComponentVariance) {
+        int sourceAlpha = Color.alpha(actualColor);
+        int sourceRed = Color.red(actualColor);
+        int sourceGreen = Color.green(actualColor);
+        int sourceBlue = Color.blue(actualColor);
+
+        int expectedAlpha = Color.alpha(expectedColor);
+        int expectedRed = Color.red(expectedColor);
+        int expectedGreen = Color.green(expectedColor);
+        int expectedBlue = Color.blue(expectedColor);
+
+        int varianceAlpha = Math.abs(sourceAlpha - expectedAlpha);
+        int varianceRed = Math.abs(sourceRed - expectedRed);
+        int varianceGreen = Math.abs(sourceGreen - expectedGreen);
+        int varianceBlue = Math.abs(sourceBlue - expectedBlue);
+
+        boolean isColorMatch = (varianceAlpha <= allowedComponentVariance)
+                && (varianceRed <= allowedComponentVariance)
+                && (varianceGreen <= allowedComponentVariance)
+                && (varianceBlue <= allowedComponentVariance);
+
+        return isColorMatch;
+    }
+
+    /**
+     * Composite two potentially translucent colors over each other and returns the result.
+     */
+    public static int compositeColors(@ColorInt int foreground, @ColorInt int background) {
+        int bgAlpha = Color.alpha(background);
+        int fgAlpha = Color.alpha(foreground);
+        int a = compositeAlpha(fgAlpha, bgAlpha);
+
+        int r = compositeComponent(Color.red(foreground), fgAlpha,
+                Color.red(background), bgAlpha, a);
+        int g = compositeComponent(Color.green(foreground), fgAlpha,
+                Color.green(background), bgAlpha, a);
+        int b = compositeComponent(Color.blue(foreground), fgAlpha,
+                Color.blue(background), bgAlpha, a);
+
+        return Color.argb(a, r, g, b);
+    }
+
+    private static int compositeAlpha(int foregroundAlpha, int backgroundAlpha) {
+        return 0xFF - (((0xFF - backgroundAlpha) * (0xFF - foregroundAlpha)) / 0xFF);
+    }
+
+    private static int compositeComponent(int fgC, int fgA, int bgC, int bgA, int a) {
+        if (a == 0) return 0;
+        return ((0xFF * fgC * fgA) + (bgC * bgA * (0xFF - fgA))) / (a * 0xFF);
+    }
+
+    public static CharSequence sameCharSequence(final CharSequence expected) {
+        return argThat(new BaseMatcher<CharSequence>() {
+            @Override
+            public boolean matches(Object o) {
+                if (o instanceof CharSequence) {
+                    return TextUtils.equals(expected, (CharSequence) o);
+                }
+                return false;
+            }
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("doesn't match " + expected);
+            }
+        });
+    }
+
+    public static Editable sameEditable(final Editable expected) {
+        return argThat(new BaseMatcher<Editable>() {
+            @Override
+            public boolean matches(Object o) {
+                if (o instanceof Editable) {
+                    return TextUtils.equals(expected, (Editable) o);
+                }
+                return false;
+            }
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("doesn't match " + expected);
+            }
+        });
+    }
+
+    public static ColorStateList colorStateListOf(final @ColorInt int color) {
+        return argThat(new BaseMatcher<ColorStateList>() {
+            @Override
+            public boolean matches(Object o) {
+                if (o instanceof ColorStateList) {
+                    final ColorStateList actual = (ColorStateList) o;
+                    return (actual.getColors().length == 1) && (actual.getDefaultColor() == color);
+                }
+                return false;
+            }
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("doesn't match " + formatColorToHex(color));
+            }
+        });
+    }
+
+    public static int dpToPx(Context context, int dp) {
+        final float density = context.getResources().getDisplayMetrics().density;
+        return (int) (dp * density + 0.5f);
+    }
+
+    private static String arrayToString(final long[] array) {
+        final StringBuffer buffer = new StringBuffer();
+        if (array == null) {
+            buffer.append("null");
+        } else {
+            buffer.append("[");
+            for (int i = 0; i < array.length; i++) {
+                if (i > 0) {
+                    buffer.append(", ");
+                }
+                buffer.append(array[i]);
+            }
+            buffer.append("]");
+        }
+        return buffer.toString();
+    }
+
+    public static void assertIdentical(final long[] expected, final long[] actual) {
+        if (!Arrays.equals(expected, actual)) {
+            Assert.fail("Expected " + arrayToString(expected) + ", actual "
+                    + arrayToString(actual));
+        }
+    }
 }
\ No newline at end of file
diff --git a/tests/tests/widget/src/android/widget/cts/util/TestUtilsMatchers.java b/tests/tests/widget/src/android/widget/cts/util/TestUtilsMatchers.java
new file mode 100644
index 0000000..3664bc4
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/util/TestUtilsMatchers.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.cts.util;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+
+import java.util.List;
+
+public class TestUtilsMatchers {
+    /**
+     * Returns a matcher that matches lists of int values that are in ascending order.
+     */
+    public static Matcher<List<Integer>> inAscendingOrder() {
+        return new TypeSafeMatcher<List<Integer>>() {
+            private String mFailedDescription;
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText(mFailedDescription);
+            }
+
+            @Override
+            protected boolean matchesSafely(List<Integer> item) {
+                int itemCount = item.size();
+
+                if (itemCount >= 2) {
+                    for (int i = 0; i < itemCount - 1; i++) {
+                        int curr = item.get(i);
+                        int next = item.get(i + 1);
+
+                        if (curr > next) {
+                            mFailedDescription = "Values should increase between #" + i +
+                                    ":" + curr + " and #" + (i + 1) + ":" + next;
+                            return false;
+                        }
+                    }
+                }
+
+                return true;
+            }
+        };
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/util/ViewTestUtils.java b/tests/tests/widget/src/android/widget/cts/util/ViewTestUtils.java
index e9ef867..69c788b 100644
--- a/tests/tests/widget/src/android/widget/cts/util/ViewTestUtils.java
+++ b/tests/tests/widget/src/android/widget/cts/util/ViewTestUtils.java
@@ -16,14 +16,16 @@
 
 package android.widget.cts.util;
 
-import junit.framework.Assert;
-
 import android.app.Instrumentation;
+import android.os.SystemClock;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
+import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.ViewTreeObserver;
 import android.view.ViewTreeObserver.OnDrawListener;
+import junit.framework.Assert;
 
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -34,8 +36,8 @@
 public class ViewTestUtils {
 
     /**
-     * Runs the specified Runnable on the main thread and ensures that the
-     * specified View's tree is drawn before returning.
+     * Runs the specified Runnable on the main thread and ensures that the specified View's tree is
+     * drawn before returning.
      *
      * @param instrumentation the instrumentation used to run the test
      * @param view the view whose tree should be drawn before returning
@@ -72,4 +74,138 @@
             throw new RuntimeException(e);
         }
     }
-}
+
+    /**
+     * Emulates a tap in the center of the passed {@link View}.
+     *
+     * @param instrumentation the instrumentation used to run the test
+     * @param view the view to "tap"
+     */
+    public static void emulateTapOnViewCenter(Instrumentation instrumentation, View view) {
+        emulateTapOnScreen(instrumentation, view, view.getWidth() / 2, view.getHeight() / 2);
+    }
+
+    /**
+     * Emulates a tap on a point relative to the top-left corner of the passed {@link View}. Offset
+     * parameters are used to compute the final screen coordinates of the tap point.
+     *
+     * @param instrumentation the instrumentation used to run the test
+     * @param anchorView the anchor view to determine the tap location on the screen
+     * @param offsetX extra X offset for the tap
+     * @param offsetY extra Y offset for the tap
+     */
+    public static void emulateTapOnScreen(Instrumentation instrumentation, View anchorView,
+            int offsetX, int offsetY) {
+        // Use instrumentation to emulate a tap on the spinner to bring down its popup
+        final int[] viewOnScreenXY = new int[2];
+        anchorView.getLocationOnScreen(viewOnScreenXY);
+        int emulatedTapX = viewOnScreenXY[0] + offsetX;
+        int emulatedTapY = viewOnScreenXY[1] + offsetY;
+
+        // Inject DOWN event
+        long downTime = SystemClock.uptimeMillis();
+        MotionEvent eventDown = MotionEvent.obtain(
+                downTime, downTime, MotionEvent.ACTION_DOWN, emulatedTapX, emulatedTapY, 1);
+        instrumentation.sendPointerSync(eventDown);
+
+        // Inject MOVE event
+        long moveTime = SystemClock.uptimeMillis();
+        MotionEvent eventMove = MotionEvent.obtain(
+                moveTime, moveTime, MotionEvent.ACTION_MOVE, emulatedTapX, emulatedTapY, 1);
+        instrumentation.sendPointerSync(eventMove);
+
+        // Inject UP event
+        long upTime = SystemClock.uptimeMillis();
+        MotionEvent eventUp = MotionEvent.obtain(
+                upTime, upTime, MotionEvent.ACTION_UP, emulatedTapX, emulatedTapY, 1);
+        instrumentation.sendPointerSync(eventUp);
+
+        // Wait for the system to process all events in the queue
+        instrumentation.waitForIdleSync();
+    }
+
+    /**
+     * Emulates a drag gesture across the screen.
+     *
+     * @param instrumentation the instrumentation used to run the test
+     * @param dragStartX Start X of the emulated drag gesture
+     * @param dragStartY Start Y of the emulated drag gesture
+     * @param dragAmountX X amount of the emulated drag gesture
+     * @param dragAmountY Y amount of the emulated drag gesture
+     */
+    public static void emulateDragGesture(Instrumentation instrumentation,
+            int dragStartX, int dragStartY, int dragAmountX, int dragAmountY) {
+        // Inject DOWN event
+        long downTime = SystemClock.uptimeMillis();
+        MotionEvent eventDown = MotionEvent.obtain(
+                downTime, downTime, MotionEvent.ACTION_DOWN, dragStartX, dragStartY, 1);
+        instrumentation.sendPointerSync(eventDown);
+
+        // Inject a sequence of MOVE events that emulate a "swipe down" gesture
+        final int moveEventCount = 20;
+        for (int i = 0; i < moveEventCount; i++) {
+            long moveTime = SystemClock.uptimeMillis();
+            final int moveX = dragStartX + dragAmountX * i / moveEventCount;
+            final int moveY = dragStartY + dragAmountY * i / moveEventCount;
+            MotionEvent eventMove = MotionEvent.obtain(
+                    moveTime, moveTime, MotionEvent.ACTION_MOVE, moveX, moveY, 1);
+            instrumentation.sendPointerSync(eventMove);
+            // sleep for a bit to emulate a 2-second swipe
+            SystemClock.sleep(2000 / moveEventCount);
+        }
+
+        // Inject UP event
+        long upTime = SystemClock.uptimeMillis();
+        MotionEvent eventUp = MotionEvent.obtain(
+                upTime, upTime, MotionEvent.ACTION_UP, dragStartX + dragAmountX,
+                dragStartY + dragAmountY, 1);
+        instrumentation.sendPointerSync(eventUp);
+
+        // Wait for the system to process all events in the queue
+        instrumentation.waitForIdleSync();
+    }
+
+    /**
+     * Emulates a long click in the center of the passed {@link View}.
+     *
+     * @param instrumentation the instrumentation used to run the test
+     * @param view the view to "long click"
+     * @param extraWaitMs the duration of emulated long click in milliseconds starting
+     *      after system-level long press timeout.
+     */
+    public static void emulateLongClick(Instrumentation instrumentation, View view,
+            long extraWaitMs) {
+        // Use instrumentation to emulate a tap on the spinner to bring down its popup
+        final int[] viewOnScreenXY = new int[2];
+        view.getLocationOnScreen(viewOnScreenXY);
+        int emulatedTapX = viewOnScreenXY[0] + view.getWidth() / 2;
+        int emulatedTapY = viewOnScreenXY[1] + view.getHeight() / 2;
+
+        // Inject DOWN event
+        long downTime = SystemClock.uptimeMillis();
+        MotionEvent eventDown = MotionEvent.obtain(
+                downTime, downTime, MotionEvent.ACTION_DOWN, emulatedTapX, emulatedTapY, 1);
+        instrumentation.sendPointerSync(eventDown);
+
+        // Inject MOVE event
+        long moveTime = SystemClock.uptimeMillis();
+        MotionEvent eventMove = MotionEvent.obtain(
+                moveTime, moveTime, MotionEvent.ACTION_MOVE, emulatedTapX, emulatedTapY, 1);
+        instrumentation.sendPointerSync(eventMove);
+
+        try {
+            Thread.sleep(ViewConfiguration.getLongPressTimeout() + extraWaitMs);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+
+        // Inject UP event
+        long upTime = SystemClock.uptimeMillis();
+        MotionEvent eventUp = MotionEvent.obtain(
+                upTime, upTime, MotionEvent.ACTION_UP, emulatedTapX, emulatedTapY, 1);
+        instrumentation.sendPointerSync(eventUp);
+
+        // Wait for the system to process all events in the queue
+        instrumentation.waitForIdleSync();
+    }
+}
\ No newline at end of file
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index e1eeba6..18c3762 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -45,17 +45,6 @@
     <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testUpdateAppWidgetViaWidgetId" />
     <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testUpdateAppWidgetViaWidgetIds" />
 
-    <!-- b/21668302 -->
-    <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.AssistantContentViewTest#testAssistantContentViewDimens" />
-    <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.ExtraAssistDataTest#testAssistContentAndAssistData" />
-    <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.FocusChangeTest#testLayerCausesUnderlyingActivityToLoseFocus" />
-    <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.LargeViewHierarchyTest#testTextView" />
-    <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.ScreenshotTest#testBlueScreenshot" />
-    <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.ScreenshotTest#testGreenScreenshot" />
-    <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.ScreenshotTest#testRedScreenshot" />
-    <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.TextViewTest#testTextView" />
-    <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.WebViewTest#testWebView" />
-
     <!-- b/23776099 -->
     <option name="compatibility:exclude-filter" value="CtsCallLogTestCases" />
 
diff --git a/tools/utils/buildCts.py b/tools/utils/buildCts.py
index f983b15..bd5fc90 100755
--- a/tools/utils/buildCts.py
+++ b/tools/utils/buildCts.py
@@ -522,15 +522,6 @@
           'android.alarmclock.cts.SetAlarmTest#testAll',
           'android.alarmclock.cts.SnoozeAlarmTest#testAll',
       ],
-      'android.assist' : [
-          'android.assist.cts.AssistantContentViewTest',
-          'android.assist.cts.ExtraAssistDataTest',
-          'android.assist.cts.FocusChangeTest',
-          'android.assist.cts.LargeViewHierarchyTest',
-          'android.assist.cts.ScreenshotTest',
-          'android.assist.cts.TextViewTest',
-          'android.assist.cts.WebViewTest',
-      ],
       'android.calllog' : [
           'android.calllog.cts.CallLogBackupTest#testSingleCallBackup',
       ],