Merge "CTS for user restriction layering"
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index 1644ce6..c4b3e04 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -96,6 +96,7 @@
     CtsDeviceTaskSwitchingAppA \
     CtsDeviceTaskSwitchingAppB \
     CtsDeviceTaskSwitchingControl \
+    CtsExternalServiceService \
     CtsHostsideNetworkTestsApp \
     CtsIntentReceiverApp \
     CtsIntentSenderApp \
@@ -160,6 +161,7 @@
     CtsDreamsTestCases \
     CtsDrmTestCases \
     CtsEffectTestCases \
+    CtsExternalServiceTestCases \
     CtsFileSystemTestCases \
     CtsGestureTestCases \
     CtsGraphicsTestCases \
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/MockConditionProvider.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/MockConditionProvider.java
index 4b90d9a..99ecd0c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/MockConditionProvider.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/MockConditionProvider.java
@@ -144,11 +144,6 @@
     }
 
     @Override
-    public void onRequestConditions(int relevance) {
-
-    }
-
-    @Override
     public void onSubscribe(Uri conditionId) {
         Log.d(TAG, "subscribed to " + conditionId);
         mSubscriptions.add(conditionId);
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildHelper.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildHelper.java
index 9427805..e21f98e 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildHelper.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildHelper.java
@@ -130,8 +130,11 @@
      * @throws FileNotFoundException if the directory does not exist
      */
     public File getRootDir() throws FileNotFoundException {
-        File dir = ((IFolderBuildInfo) mBuildInfo).getRootDir();
-        if (!dir.exists()) {
+        File dir = null;
+        if (mBuildInfo instanceof IFolderBuildInfo) {
+            dir = ((IFolderBuildInfo) mBuildInfo).getRootDir();
+        }
+        if (dir == null || !dir.exists()) {
             dir = new File(mBuildInfo.getBuildAttributes().get(ROOT_DIR));
             if (!dir.exists()) {
                 dir = new File(mBuildInfo.getBuildAttributes().get(ROOT_DIR2));
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DeviceLoggingTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DeviceLoggingTest.java
new file mode 100644
index 0000000..642915f
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DeviceLoggingTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.deviceowner;
+
+import android.auditing.SecurityLog.SecurityEvent;
+import android.os.UserHandle;
+
+import java.util.List;
+
+public class DeviceLoggingTest extends BaseDeviceOwnerTest {
+
+    private static final String MESSAGE_ONLY_ONE_MANAGED_USER_ALLOWED =
+            "There should only be one user, managed by Device Owner";
+
+    /**
+     * Test: setting device logging can only be done if there's one user on the device.
+     */
+    public void testSetDeviceLoggingEnabledNotPossibleIfMoreThanOneUserPresent() {
+        try {
+            mDevicePolicyManager.setDeviceLoggingEnabled(getWho(), true);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertEquals(e.getMessage(), MESSAGE_ONLY_ONE_MANAGED_USER_ALLOWED);
+        }
+    }
+
+    /**
+     * Test: retrieving device logs can only be done if there's one user on the device.
+     */
+    public void testRetrievingDeviceLogsNotPossibleIfMoreThanOneUserPresent() {
+        try {
+            mDevicePolicyManager.retrieveDeviceLogs(getWho());
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertEquals(e.getMessage(), MESSAGE_ONLY_ONE_MANAGED_USER_ALLOWED);
+        }
+    }
+
+    /**
+     * Test: retrieving previous device logs can only be done if there's one user on the device.
+     */
+    public void testRetrievingPreviousDeviceLogsNotPossibleIfMoreThanOneUserPresent() {
+        try {
+            mDevicePolicyManager.retrievePreviousDeviceLogs(getWho());
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertEquals(e.getMessage(), MESSAGE_ONLY_ONE_MANAGED_USER_ALLOWED);
+        }
+    }
+
+    /**
+     * Test: retrieving device logs should be rate limited - subsequent attempts should return null.
+     * TODO(mkarpinski): consider how we can test that the rate limiting is set to 2 hours.
+     */
+    public void testRetrievingDeviceLogsNotPossibleImmediatelyAfterPreviousSuccessfulRetrieval() {
+        List<SecurityEvent> logs = mDevicePolicyManager.retrieveDeviceLogs(getWho());
+        // if logs is null it means that that attempt was rate limited => test PASS
+        if (logs != null) {
+            assertNull(mDevicePolicyManager.retrieveDeviceLogs(getWho()));
+            assertNull(mDevicePolicyManager.retrieveDeviceLogs(getWho()));
+        }
+    }
+}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index 35c14d9..2d235f5 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -222,6 +222,29 @@
         assertEquals("Ephemeral flag must be set", FLAG_EPHEMERAL, flags & FLAG_EPHEMERAL);
     }
 
+    public void testDeviceLoggingWithTwoUsers() throws Exception {
+        if (!mHasFeature || getMaxNumberOfUsersSupported() < 2) {
+            return;
+        }
+        int userId = -1;
+        try {
+            userId = createUser();
+            executeDeviceTestMethod(".DeviceLoggingTest",
+                    "testSetDeviceLoggingEnabledNotPossibleIfMoreThanOneUserPresent");
+            executeDeviceTestMethod(".DeviceLoggingTest",
+                    "testRetrievingDeviceLogsNotPossibleIfMoreThanOneUserPresent");
+            executeDeviceTestMethod(".DeviceLoggingTest",
+                    "testRetrievingPreviousDeviceLogsNotPossibleIfMoreThanOneUserPresent");
+        } finally {
+            removeUser(userId);
+        }
+    }
+
+    public void testDeviceLoggingWithSingleUser() throws Exception {
+        executeDeviceTestMethod(".DeviceLoggingTest",
+                "testRetrievingDeviceLogsNotPossibleImmediatelyAfterPreviousSuccessfulRetrieval");
+    }
+
     public void testLockTask() throws Exception {
         try {
             installApp(INTENT_RECEIVER_APK);
@@ -273,7 +296,7 @@
 
     private void executeDeviceTestMethod(String className, String testName) throws Exception {
         assertTrue(runDeviceTestsAsUser(DEVICE_OWNER_PKG, className, testName,
-                /* deviceOwnerUserId */0));
+                /* deviceOwnerUserId */ 0));
     }
 
     private void executeDeviceOwnerTestAsUser(String testClassName, int userId) throws Exception {
diff --git a/hostsidetests/services/activitymanager/app/AndroidManifest.xml b/hostsidetests/services/activitymanager/app/AndroidManifest.xml
index 84bbd42..ed3cece 100755
--- a/hostsidetests/services/activitymanager/app/AndroidManifest.xml
+++ b/hostsidetests/services/activitymanager/app/AndroidManifest.xml
@@ -24,6 +24,11 @@
                 android:resizeable="true"
                 android:exported="true"
         />
+        <activity android:name=".DockedActivity"
+                android:resizeable="true"
+                android:exported="true"
+                android:taskAffinity="nobody.but.DockedActivity"
+        />
         <activity android:name=".NoRelaunchActivity"
                 android:resizeable="true"
                 android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
diff --git a/hostsidetests/services/activitymanager/app/src/android/server/app/AutoEnterPipActivity.java b/hostsidetests/services/activitymanager/app/src/android/server/app/AutoEnterPipActivity.java
index 97bc041..dbd92b5 100644
--- a/hostsidetests/services/activitymanager/app/src/android/server/app/AutoEnterPipActivity.java
+++ b/hostsidetests/services/activitymanager/app/src/android/server/app/AutoEnterPipActivity.java
@@ -22,6 +22,6 @@
     @Override
     protected void onResume() {
         super.onResume();
-        enterPictureInPictureMode();
+        enterPictureInPicture();
     }
 }
diff --git a/hostsidetests/services/activitymanager/app/src/android/server/app/DockedActivity.java b/hostsidetests/services/activitymanager/app/src/android/server/app/DockedActivity.java
new file mode 100644
index 0000000..427fd29
--- /dev/null
+++ b/hostsidetests/services/activitymanager/app/src/android/server/app/DockedActivity.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.app;
+
+import android.app.Activity;
+
+public class DockedActivity extends Activity {
+}
diff --git a/hostsidetests/services/activitymanager/app/src/android/server/app/LaunchPipOnPipActivity.java b/hostsidetests/services/activitymanager/app/src/android/server/app/LaunchPipOnPipActivity.java
index b328a09..dba7cde 100644
--- a/hostsidetests/services/activitymanager/app/src/android/server/app/LaunchPipOnPipActivity.java
+++ b/hostsidetests/services/activitymanager/app/src/android/server/app/LaunchPipOnPipActivity.java
@@ -20,8 +20,8 @@
 
 public class LaunchPipOnPipActivity extends Activity {
     @Override
-    public void onPictureInPictureModeChanged(boolean pictureInPictureMode) {
-        super.onPictureInPictureModeChanged(pictureInPictureMode);
+    public void onPictureInPictureChanged(boolean inPictureInPicture) {
+        super.onPictureInPictureChanged(inPictureInPicture);
         AlwaysFocusablePipActivity.launchAlwaysFocusablePipActivity(this);
     }
 }
diff --git a/hostsidetests/services/activitymanager/app/src/android/server/app/LaunchToSideActivity.java b/hostsidetests/services/activitymanager/app/src/android/server/app/LaunchToSideActivity.java
index 388c9a6..9714393 100644
--- a/hostsidetests/services/activitymanager/app/src/android/server/app/LaunchToSideActivity.java
+++ b/hostsidetests/services/activitymanager/app/src/android/server/app/LaunchToSideActivity.java
@@ -1,12 +1,11 @@
 package android.server.app;
 
-import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_TO_SIDE;
+import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 
 import android.app.Activity;
 import android.content.Intent;
 import android.os.Bundle;
-import android.util.Log;
 
 public class LaunchToSideActivity extends Activity {
     @Override
@@ -15,7 +14,7 @@
         final Bundle extras = intent.getExtras();
          if (extras != null && extras.getBoolean("launch_to_the_side")) {
             Intent newIntent = new Intent(this, TestActivity.class);
-            newIntent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_LAUNCH_TO_SIDE);
+            newIntent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_LAUNCH_ADJACENT);
             startActivity(newIntent);
         }
     }
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
index 731ff47..92be4b8 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
@@ -16,17 +16,23 @@
 
 package android.server.cts;
 
-import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.log.LogUtil.CLog;
 
-import java.lang.Exception;
-import java.lang.String;
+import java.awt.Rectangle;
+
+import static com.android.ddmlib.Log.LogLevel.*;
 
 public class ActivityManagerDockedStackTests extends ActivityManagerTestBase {
 
     private static final String TEST_ACTIVITY_NAME = "TestActivity";
+    private static final String DOCKED_ACTIVITY_NAME = "DockedActivity";
     private static final String LAUNCH_TO_SIDE_ACTIVITY_NAME = "LaunchToSideActivity";
 
     private static final String AM_MOVE_TASK = "am stack movetask ";
+    private static final String AM_RESIZE_DOCKED_STACK = "am stack resize-docked-stack ";
+
+    private static final int TASK_SIZE = 600;
+    private static final int STACK_SIZE = 300;
 
     // TODO: Add test for non-resizeable activity.
 
@@ -140,6 +146,27 @@
         mDevice.executeShellCommand(cmd);
     }
 
+    public void testResizeDockedStack() throws Exception {
+        mDevice.executeShellCommand(getAmStartCmd(TEST_ACTIVITY_NAME));
+        mDevice.executeShellCommand(getAmStartCmd(DOCKED_ACTIVITY_NAME));
+        mDevice.executeShellCommand(AM_MOVE_TASK + getActivityTaskId(DOCKED_ACTIVITY_NAME) + " "
+                + DOCKED_STACK_ID + " true");
+        mDevice.executeShellCommand(AM_RESIZE_DOCKED_STACK
+                + "0 0 " + STACK_SIZE + " " + STACK_SIZE
+                + " 0 0 " + TASK_SIZE + " " + TASK_SIZE);
+        mAmWmState.computeState(mDevice);
+        mAmWmState.assertSanity();
+        mAmWmState.assertContainsStack("Must contain docked stack", DOCKED_STACK_ID);
+        mAmWmState.assertContainsStack("Must contain fullscreen stack",
+                FULLSCREEN_WORKSPACE_STACK_ID);
+        assertEquals(new Rectangle(0, 0, STACK_SIZE, STACK_SIZE),
+                mAmWmState.getAmState().getStackById(DOCKED_STACK_ID).getBounds());
+        assertEquals(new Rectangle(0, 0, TASK_SIZE, TASK_SIZE),
+                mAmWmState.getAmState().getTaskByActivityName(DOCKED_ACTIVITY_NAME).getBounds());
+        mAmWmState.assertVisibility(DOCKED_ACTIVITY_NAME, true);
+        mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true);
+    }
+
     private void launchActivityToSide(String activityName) throws Exception {
         mDevice.executeShellCommand(
                 getAmStartCmd(activityName) + " -f 0x20000000 --ez launch_to_the_side true");
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerReplaceWindowTests.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerReplaceWindowTests.java
index 785e487..88fcc97 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerReplaceWindowTests.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerReplaceWindowTests.java
@@ -77,11 +77,8 @@
         CLog.logAndDisplay(INFO, "==========After Docking========");
         final String newToken = getFocusedWindowToken(windowName, false);
 
-        if (relaunch) {
-            Assert.assertFalse("Window not replaced after relaunch.", oldToken.equals(newToken));
-        } else {
-            Assert.assertEquals("Window replaced without relaunch.", oldToken, newToken);
-        }
+        // For both relaunch and not relaunch case, we'd like the window to be kept.
+        Assert.assertEquals("Window replaced while docking.", oldToken, newToken);
     }
 
     private String getFocusedWindowToken(String windowName, boolean visibleOnly)
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerState.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerState.java
index 003d8e6..fcee898 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerState.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerState.java
@@ -174,6 +174,15 @@
         return false;
     }
 
+    ActivityStack getStackById(int stackId) {
+        for (ActivityStack stack : mStacks) {
+            if (stackId == stack.mStackId) {
+                return stack;
+            }
+        }
+        return null;
+    }
+
     List<ActivityStack> getStacks() {
         return new ArrayList(mStacks);
     }
@@ -195,6 +204,20 @@
         return false;
     }
 
+    ActivityTask getTaskByActivityName(String activityName) {
+        String fullName = ActivityManagerTestBase.getActivityComponentName(activityName);
+        for (ActivityStack stack : mStacks) {
+            for (ActivityTask task : stack.mTasks) {
+                for (Activity activity : task.mActivities) {
+                    if (activity.name.equals(fullName)) {
+                        return task;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
     static class ActivityStack extends ActivityContainer {
 
         private static final Pattern TASK_ID_PATTERN = Pattern.compile("Task id #(\\d+)");
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerTestBase.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerTestBase.java
index d0cd178..ceb2b63 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerTestBase.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerTestBase.java
@@ -187,7 +187,7 @@
                 "settings put system accelerometer_rotation " + rotation);
     }
 
-    private String runCommandAndPrintOutput(String command) throws DeviceNotAvailableException {
+    protected String runCommandAndPrintOutput(String command) throws DeviceNotAvailableException {
         final String output = mDevice.executeShellCommand(command);
         CLog.logAndDisplay(LogLevel.INFO, command);
         CLog.logAndDisplay(LogLevel.INFO, output);
diff --git a/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java b/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
index fc9267a..17caccb 100644
--- a/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
+++ b/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
@@ -567,6 +567,58 @@
         }
     }
 
+    public void testSetDeviceLoggingEnabled_failIfNotDeviceOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSetDeviceLoggingEnabled_failIfNotDeviceOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.setDeviceLoggingEnabled(mComponent, true);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertDeviceOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testGetDeviceLoggingEnabled_failIfNotDeviceOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testGetDeviceLoggingEnabled_failIfNotDeviceOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.getDeviceLoggingEnabled(mComponent);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertDeviceOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testRetrieveDeviceLogs_failIfNotDeviceOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testRetrieveDeviceLogs_failIfNotDeviceOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.retrieveDeviceLogs(mComponent);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertDeviceOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testRetrievePreviousDeviceLogs_failIfNotDeviceOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testRetrievePreviousDeviceLogs_failIfNotDeviceOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.retrievePreviousDeviceLogs(mComponent);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertDeviceOwnerMessage(e.getMessage());
+        }
+    }
+
     public void testCreateUser_failIfNotDeviceOwner() {
         if (!mDeviceAdmin) {
             Log.w(TAG, "Skipping testCreateUser_failIfNotDeviceOwner");
diff --git a/tests/app/src/android/app/cts/DownloadManagerTest.java b/tests/app/src/android/app/cts/DownloadManagerTest.java
index 21a227b..50eb96b 100644
--- a/tests/app/src/android/app/cts/DownloadManagerTest.java
+++ b/tests/app/src/android/app/cts/DownloadManagerTest.java
@@ -474,9 +474,9 @@
     }
 
     private boolean hasInternetConnection() {
-        // TODO: expand this to include devices with ethernet
         final PackageManager pm = getContext().getPackageManager();
         return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
-                || pm.hasSystemFeature(PackageManager.FEATURE_WIFI);
+                || pm.hasSystemFeature(PackageManager.FEATURE_WIFI)
+                || pm.hasSystemFeature(PackageManager.FEATURE_ETHERNET);
     }
 }
diff --git a/tests/app/src/android/app/cts/PipActivityTest.java b/tests/app/src/android/app/cts/PipActivityTest.java
index a553169..3f053cb 100644
--- a/tests/app/src/android/app/cts/PipActivityTest.java
+++ b/tests/app/src/android/app/cts/PipActivityTest.java
@@ -44,20 +44,20 @@
                 final boolean supportsPip =
                         mActivity.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE);
                 if (supportsPip) {
-                    mActivity.enterPictureInPictureMode();
-                    assertTrue(mActivity.inMultiWindowMode());
-                    assertTrue(mActivity.inPictureInPictureMode());
+                    mActivity.enterPictureInPicture();
+                    assertTrue(mActivity.inMultiWindow());
+                    assertTrue(mActivity.inPictureInPicture());
                 } else {
                     boolean pipSupportDisabled = false;
                     try {
-                        mActivity.enterPictureInPictureMode();
+                        mActivity.enterPictureInPicture();
                     } catch (IllegalStateException e) {
                         // Pip not supported
                         pipSupportDisabled = true;
                     }
                     assertTrue(pipSupportDisabled);
-                    assertFalse(mActivity.inMultiWindowMode());
-                    assertFalse(mActivity.inPictureInPictureMode());
+                    assertFalse(mActivity.inMultiWindow());
+                    assertFalse(mActivity.inPictureInPicture());
                 }
             }
         });
diff --git a/tests/app/src/android/app/cts/PipNotResizeableActivityTest.java b/tests/app/src/android/app/cts/PipNotResizeableActivityTest.java
index 4f7f63e..e2908cd 100644
--- a/tests/app/src/android/app/cts/PipNotResizeableActivityTest.java
+++ b/tests/app/src/android/app/cts/PipNotResizeableActivityTest.java
@@ -42,7 +42,7 @@
                 public void run() {
                     boolean pipSupportDisabled = false;
                     try {
-                        mActivity.enterPictureInPictureMode();
+                        mActivity.enterPictureInPicture();
                     } catch (IllegalStateException e) {
                         // Pip not supported
                         pipSupportDisabled = true;
@@ -51,8 +51,8 @@
                         pipSupportDisabled = true;
                     }
                     assertTrue(pipSupportDisabled);
-                    assertFalse(mActivity.inMultiWindowMode());
-                    assertFalse(mActivity.inPictureInPictureMode());
+                    assertFalse(mActivity.inMultiWindow());
+                    assertFalse(mActivity.inPictureInPicture());
                 }
             });
             mInstrumentation.waitForIdleSync();
diff --git a/tests/app/src/android/app/cts/PipNotSupportedActivityTest.java b/tests/app/src/android/app/cts/PipNotSupportedActivityTest.java
index 245421a..c9ce69c 100644
--- a/tests/app/src/android/app/cts/PipNotSupportedActivityTest.java
+++ b/tests/app/src/android/app/cts/PipNotSupportedActivityTest.java
@@ -42,7 +42,7 @@
             public void run() {
                 boolean pipSupportDisabled = false;
                 try {
-                    mActivity.enterPictureInPictureMode();
+                    mActivity.enterPictureInPicture();
                 } catch (IllegalStateException e) {
                     // Pip not supported
                     pipSupportDisabled = true;
@@ -51,8 +51,8 @@
                     pipSupportDisabled = true;
                 }
                 assertTrue(pipSupportDisabled);
-                assertFalse(mActivity.inMultiWindowMode());
-                assertFalse(mActivity.inPictureInPictureMode());
+                assertFalse(mActivity.inMultiWindow());
+                assertFalse(mActivity.inPictureInPicture());
             }
         });
         mInstrumentation.waitForIdleSync();
diff --git a/tests/camera/Android.mk b/tests/camera/Android.mk
index 62cdf25..4d653a6 100644
--- a/tests/camera/Android.mk
+++ b/tests/camera/Android.mk
@@ -20,6 +20,9 @@
 
 LOCAL_MODULE_TAGS := tests
 
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
 LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil \
 	ctstestrunner \
 	mockito-target \
diff --git a/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java b/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java
index 337aab6..cf36b05 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java
@@ -1597,14 +1597,16 @@
                     CaptureRequest.NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG);
         } else if (template == CameraDevice.TEMPLATE_PREVIEW ||
                 template == CameraDevice.TEMPLATE_RECORD){
-            List<Integer> availableEdgeModes =
-                    Arrays.asList(toObject(mStaticInfo.getAvailableEdgeModesChecked()));
-            if (availableEdgeModes.contains(CaptureRequest.EDGE_MODE_FAST)) {
-                mCollector.expectKeyValueEquals(request, EDGE_MODE,
-                        CaptureRequest.EDGE_MODE_FAST);
-            } else {
-                mCollector.expectKeyValueEquals(request, EDGE_MODE,
-                        CaptureRequest.EDGE_MODE_OFF);
+            if (mStaticInfo.areKeysAvailable(EDGE_MODE)) {
+                List<Integer> availableEdgeModes =
+                        Arrays.asList(toObject(mStaticInfo.getAvailableEdgeModesChecked()));
+                if (availableEdgeModes.contains(CaptureRequest.EDGE_MODE_FAST)) {
+                    mCollector.expectKeyValueEquals(request, EDGE_MODE,
+                            CaptureRequest.EDGE_MODE_FAST);
+                } else {
+                    mCollector.expectKeyValueEquals(request, EDGE_MODE,
+                            CaptureRequest.EDGE_MODE_OFF);
+                }
             }
 
             if (mStaticInfo.areKeysAvailable(NOISE_REDUCTION_MODE)) {
diff --git a/tests/camera/src/android/hardware/camera2/cts/CameraTestUtils.java b/tests/camera/src/android/hardware/camera2/cts/CameraTestUtils.java
index 1633c1e..0da92a6 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -36,6 +36,7 @@
 import android.hardware.camera2.TotalCaptureResult;
 import android.hardware.cts.helpers.CameraUtils;
 import android.hardware.camera2.params.MeteringRectangle;
+import android.hardware.camera2.params.OutputConfiguration;
 import android.hardware.camera2.params.StreamConfigurationMap;
 import android.location.Location;
 import android.location.LocationManager;
@@ -721,6 +722,26 @@
     }
 
     /**
+     * Configure a new camera session with output configurations.
+     *
+     * @param camera The CameraDevice to be configured.
+     * @param outputs The OutputConfiguration list that is used for camera output.
+     * @param listener The callback CameraDevice will notify when capture results are available.
+     */
+    public static CameraCaptureSession configureCameraSessionWithConfig(CameraDevice camera,
+            List<OutputConfiguration> outputs,
+            CameraCaptureSession.StateCallback listener, Handler handler)
+            throws CameraAccessException {
+        BlockingSessionCallback sessionListener = new BlockingSessionCallback(listener);
+        camera.createCaptureSessionByOutputConfiguration(outputs, sessionListener, handler);
+        CameraCaptureSession session =
+                sessionListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
+        assertFalse("Camera session should not be a reprocessable session",
+                session.isReprocessable());
+        return session;
+    }
+
+    /**
      * Configure a new camera session with output surfaces.
      *
      * @param camera The CameraDevice to be configured.
@@ -759,6 +780,40 @@
         return session;
     }
 
+    /**
+     * Create a reprocessable camera session with input and output configurations.
+     *
+     * @param camera The CameraDevice to be configured.
+     * @param inputConfiguration The input configuration used to create this session.
+     * @param outputs The output configurations used to create this session.
+     * @param listener The callback CameraDevice will notify when capture results are available.
+     * @param handler The handler used to notify callbacks.
+     * @return The session ready to use.
+     * @throws CameraAccessException
+     */
+    public static CameraCaptureSession configureReprocCameraSessionWithConfig(CameraDevice camera,
+            InputConfiguration inputConfiguration, List<OutputConfiguration> outputs,
+            CameraCaptureSession.StateCallback listener, Handler handler)
+            throws CameraAccessException {
+        BlockingSessionCallback sessionListener = new BlockingSessionCallback(listener);
+        camera.createReprocessableCaptureSessionWithConfigurations(inputConfiguration, outputs,
+                sessionListener, handler);
+
+        Integer[] sessionStates = {BlockingSessionCallback.SESSION_READY,
+                                   BlockingSessionCallback.SESSION_CONFIGURE_FAILED};
+        int state = sessionListener.getStateWaiter().waitForAnyOfStates(
+                Arrays.asList(sessionStates), SESSION_CONFIGURE_TIMEOUT_MS);
+
+        assertTrue("Creating a reprocessable session failed.",
+                state == BlockingSessionCallback.SESSION_READY);
+
+        CameraCaptureSession session =
+                sessionListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
+        assertTrue("Camera session should be a reprocessable session", session.isReprocessable());
+
+        return session;
+    }
+
     public static <T> void assertArrayNotEmpty(T arr, String message) {
         assertTrue(message, arr != null && Array.getLength(arr) > 0);
     }
diff --git a/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java b/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java
index bddbd52..4259882 100644
--- a/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java
@@ -46,13 +46,16 @@
 import android.view.Surface;
 
 import java.io.ByteArrayOutputStream;
+import java.io.File;
 import java.io.FileOutputStream;
 import java.nio.ByteBuffer;
 import java.nio.channels.FileChannel;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Calendar;
 import java.util.Collections;
 import java.util.List;
+import java.util.TimeZone;
 
 import static android.hardware.camera2.cts.helpers.AssertHelpers.*;
 
@@ -68,6 +71,19 @@
     private static final int DEFAULT_PATCH_DIMEN = 512;
     private static final int AE_TIMEOUT_MS = 2000;
 
+    // Constants used for GPS testing.
+    private static final double GPS_DIFFERENCE_TOLERANCE = 0.0001;
+    private static final double GPS_LATITUDE = 37.420016;
+    private static final double GPS_LONGITUDE = -122.081987;
+    private static final String GPS_DATESTAMP = "2015:01:27";
+    private static final String GPS_TIMESTAMP = "02:12:01";
+    private static final Calendar GPS_CALENDAR =
+            Calendar.getInstance(TimeZone.getTimeZone("GMT+0"));
+
+    static {
+        GPS_CALENDAR.set(2015, 0, 27, 2, 12, 01);
+    }
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -165,8 +181,8 @@
      *
      * <p>
      * For each camera, capture a single RAW16 image at the first capture size reported for
-     * the raw format on that device, and save that image as a DNG file.  No further validation
-     * is done.
+     * the raw format on that device, and save that image as a DNG file. GPS information validation
+     * is done via ExifInterface.
      * </p>
      *
      * <p>
@@ -222,9 +238,9 @@
                 DngCreator dngCreator = new DngCreator(characteristics, resultPair.second);
                 Location l = new Location("test");
                 l.reset();
-                l.setLatitude(37.420016);
-                l.setLongitude(-122.081987);
-                l.setTime(System.currentTimeMillis());
+                l.setLatitude(GPS_LATITUDE);
+                l.setLongitude(GPS_LONGITUDE);
+                l.setTime(GPS_CALENDAR.getTimeInMillis());
                 dngCreator.setLocation(l);
 
                 dngCreator.setDescription("helloworld");
@@ -233,16 +249,38 @@
                 outputStream = new ByteArrayOutputStream();
                 dngCreator.writeImage(outputStream, resultPair.first.get(0));
 
+                String filePath = DEBUG_FILE_NAME_BASE + "/camera_thumb_" + deviceId + "_" +
+                        DEBUG_DNG_FILE;
+                // Write out captured DNG file for the first camera device if setprop is enabled
+                fileStream = new FileOutputStream(filePath);
+                fileStream.write(outputStream.toByteArray());
+                fileStream.flush();
+                fileStream.close();
                 if (VERBOSE) {
-                    String filePath = DEBUG_FILE_NAME_BASE + "/camera_thumb_" + deviceId + "_" +
-                            DEBUG_DNG_FILE;
-                    // Write out captured DNG file for the first camera device if setprop is enabled
-                    fileStream = new FileOutputStream(filePath);
-                    fileStream.write(outputStream.toByteArray());
-                    fileStream.flush();
-                    fileStream.close();
                     Log.v(TAG, "Test DNG file for camera " + deviceId + " saved to " + filePath);
                 }
+
+                ExifInterface exifInterface = new ExifInterface(filePath);
+                // Verify GPS data.
+                float[] latLong = new float[2];
+                assertTrue(exifInterface.getLatLong(latLong));
+                assertEquals(GPS_LATITUDE, latLong[0], GPS_DIFFERENCE_TOLERANCE);
+                assertEquals(GPS_LONGITUDE, latLong[1], GPS_DIFFERENCE_TOLERANCE);
+                assertEquals(GPS_DATESTAMP,
+                        exifInterface.getAttribute(ExifInterface.TAG_GPS_DATESTAMP));
+                assertEquals(GPS_TIMESTAMP,
+                        exifInterface.getAttribute(ExifInterface.TAG_GPS_TIMESTAMP));
+
+                // Verify the orientation.
+                assertEquals(ExifInterface.ORIENTATION_FLIP_VERTICAL,
+                        exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
+                                ExifInterface.ORIENTATION_UNDEFINED));
+
+                if (!VERBOSE) {
+                    // Delete the captured DNG file.
+                    File dngFile = new File(filePath);
+                    assertTrue(dngFile.delete());
+                }
             } finally {
                 closeDevice(deviceId);
                 for (ImageReader r : captureReaders) {
diff --git a/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java b/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
index 666292c..f0f8f66 100644
--- a/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
@@ -652,7 +652,7 @@
         // 2. Create camera output ImageReaders.
         // YUV/Opaque output, camera should support output with input size/format
         mCameraZslImageListener = new SimpleImageReaderListener(
-                /*asyncMode*/true, MAX_ZSL_IMAGES / 2);
+                /*asyncMode*/true, MAX_ZSL_IMAGES - MAX_REPROCESS_IMAGES);
         mCameraZslReader = CameraTestUtils.makeImageReader(
                 maxInputSize, inputFormat, MAX_ZSL_IMAGES, mCameraZslImageListener, mHandler);
         // Jpeg reprocess output
diff --git a/tests/camera/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java b/tests/camera/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java
index 057cb18..9dd02ce 100644
--- a/tests/camera/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java
@@ -20,6 +20,9 @@
 
 import android.graphics.ImageFormat;
 import android.view.Surface;
+
+import com.android.ex.camera2.blocking.BlockingSessionCallback;
+
 import android.hardware.camera2.CameraCaptureSession;
 import android.hardware.camera2.CameraCaptureSession.CaptureCallback;
 import android.hardware.camera2.CameraDevice;
@@ -30,6 +33,7 @@
 import android.util.Size;
 import android.hardware.camera2.cts.CameraTestUtils.SimpleCaptureCallback;
 import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
+import android.hardware.camera2.params.OutputConfiguration;
 import android.util.Log;
 import android.util.Pair;
 import android.util.Range;
@@ -53,6 +57,7 @@
     private static final int NUM_FRAMES_VERIFIED = 30;
     private static final int NUM_TEST_PATTERN_FRAMES_VERIFIED = 60;
     private static final float FRAME_DURATION_ERROR_MARGIN = 0.005f; // 0.5 percent error margin.
+    private static final int PREPARE_TIMEOUT_MS = 10000; // 10 s
 
     @Override
     protected void setUp() throws Exception {
@@ -133,6 +138,31 @@
     }
 
     /**
+     * Test surface set streaming use cases.
+     *
+     * <p>
+     * The test sets output configuration with increasing surface set IDs for preview and YUV
+     * streams. The max supported preview size is selected for preview stream, and the max
+     * supported YUV size (depending on hw supported level) is selected for YUV stream. This test
+     * also exercises the prepare API.
+     * </p>
+     */
+    public void testSurfaceSet() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                openDevice(id);
+                if (!mStaticInfo.isColorOutputSupported()) {
+                    Log.i(TAG, "Camera " + id + " does not support color outputs, skipping");
+                    continue;
+                }
+                surfaceSetTestByCamera(id);
+            } finally {
+                closeDevice();
+            }
+        }
+    }
+
+    /**
      * Test to verify the {@link CameraCaptureSession#prepare} method works correctly, and has the
      * expected effects on performance.
      *
@@ -163,7 +193,6 @@
         final int UNKNOWN_LATENCY_RESULT_WAIT = 5;
         final int MAX_RESULTS_TO_WAIT = 10;
         final int FRAMES_FOR_AVERAGING = 100;
-        final int PREPARE_TIMEOUT_MS = 10000; // 10 s
         final float PREPARE_FRAME_RATE_BOUNDS = 0.05f; // fraction allowed difference
         final float PREPARE_PEAK_RATE_BOUNDS = 0.5f; // fraction allowed difference
 
@@ -330,7 +359,6 @@
      * validated.
      */
     private void previewFpsRangeTestByCamera() throws Exception {
-        final int FPS_RANGE_SIZE = 2;
         Size maxPreviewSz = mOrderedPreviewSizes.get(0);
         Range<Integer>[] fpsRanges = mStaticInfo.getAeAvailableTargetFpsRangesChecked();
         boolean antiBandingOffIsSupported = mStaticInfo.isAntiBandingOffModeSupported();
@@ -450,6 +478,72 @@
         stopPreview();
     }
 
+    private void surfaceSetTestByCamera(String cameraId) throws Exception {
+        final int MAX_SURFACE_SET_ID = 10;
+        Size maxPreviewSz = mOrderedPreviewSizes.get(0);
+        Size yuvSizeBound = maxPreviewSz; // Default case: legacy device
+        if (mStaticInfo.isHardwareLevelLimited()) {
+            yuvSizeBound = mOrderedVideoSizes.get(0);
+        } else if (mStaticInfo.isHardwareLevelAtLeastFull()) {
+            yuvSizeBound = null;
+        }
+        Size maxYuvSize = getSupportedPreviewSizes(cameraId, mCameraManager, yuvSizeBound).get(0);
+
+        CaptureRequest.Builder requestBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        ImageDropperListener imageListener = new ImageDropperListener();
+
+        updatePreviewSurface(maxPreviewSz);
+        createImageReader(maxYuvSize, ImageFormat.YUV_420_888, MAX_READER_IMAGES, imageListener);
+        List<OutputConfiguration> outputConfigs = new ArrayList<OutputConfiguration>();
+        OutputConfiguration previewConfig = new OutputConfiguration(mPreviewSurface);
+        OutputConfiguration yuvConfig = new OutputConfiguration(mReaderSurface);
+        assertEquals(OutputConfiguration.SURFACE_SET_ID_INVALID, previewConfig.getSurfaceSetId());
+        assertEquals(OutputConfiguration.SURFACE_SET_ID_INVALID, yuvConfig.getSurfaceSetId());
+        assertEquals(mPreviewSurface, previewConfig.getSurface());
+        assertEquals(mReaderSurface, yuvConfig.getSurface());
+        outputConfigs.add(previewConfig);
+        outputConfigs.add(yuvConfig);
+        requestBuilder.addTarget(mPreviewSurface);
+        requestBuilder.addTarget(mReaderSurface);
+
+        // Test different stream set ID.
+        for (int surfaceSetId = OutputConfiguration.SURFACE_SET_ID_INVALID;
+                surfaceSetId < MAX_SURFACE_SET_ID; surfaceSetId++) {
+            if (VERBOSE) {
+                Log.v(TAG, "test preview with surface set id: ");
+            }
+            for (OutputConfiguration config : outputConfigs) {
+                config.setSurfaceSetId(surfaceSetId);
+                assertEquals(surfaceSetId, config.getSurfaceSetId());
+            }
+
+            CameraCaptureSession.StateCallback mockSessionListener =
+                    mock(CameraCaptureSession.StateCallback.class);
+
+            mSession = configureCameraSessionWithConfig(mCamera, outputConfigs,
+                    mockSessionListener, mHandler);
+
+
+            mSession.prepare(mPreviewSurface);
+            verify(mockSessionListener,
+                    timeout(PREPARE_TIMEOUT_MS).times(1)).
+                    onSurfacePrepared(eq(mSession), eq(mPreviewSurface));
+
+            mSession.prepare(mReaderSurface);
+            verify(mockSessionListener,
+                    timeout(PREPARE_TIMEOUT_MS).times(1)).
+                    onSurfacePrepared(eq(mSession), eq(mReaderSurface));
+
+            CaptureRequest request = requestBuilder.build();
+            CaptureCallback mockCaptureCallback =
+                    mock(CameraCaptureSession.CaptureCallback.class);
+            mSession.setRepeatingRequest(request, mockCaptureCallback, mHandler);
+            verifyCaptureResults(mSession, mockCaptureCallback, NUM_FRAMES_VERIFIED,
+                    NUM_FRAMES_VERIFIED * FRAME_TIMEOUT_MS);
+        }
+    }
+
     private class IsCaptureResultValid extends ArgumentMatcher<TotalCaptureResult> {
         @Override
         public boolean matches(Object obj) {
diff --git a/tests/tests/content/src/android/content/cts/ContextTest.java b/tests/tests/content/src/android/content/cts/ContextTest.java
index cf27bda..c988f77 100644
--- a/tests/tests/content/src/android/content/cts/ContextTest.java
+++ b/tests/tests/content/src/android/content/cts/ContextTest.java
@@ -27,11 +27,14 @@
 import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
 import android.test.AndroidTestCase;
 import android.util.AttributeSet;
 import android.util.Xml;
 import android.view.WindowManager;
 
+import java.io.File;
 import java.io.IOException;
 
 public class ContextTest extends AndroidTestCase {
@@ -81,6 +84,108 @@
         }
     }
 
+    /**
+     * Ensure that default and device encrypted storage areas are stored
+     * separately on disk. All devices must support these storage areas, even if
+     * they don't have file-based encryption, so that apps can go through a
+     * backup/restore cycle between FBE and non-FBE devices.
+     */
+    public void testCreateDeviceEncryptedStorageContext() throws Exception {
+        final Context deviceContext = mContext.createDeviceEncryptedStorageContext();
+
+        assertFalse(mContext.isDeviceEncryptedStorage());
+        assertTrue(deviceContext.isDeviceEncryptedStorage());
+
+        final File defaultFile = new File(mContext.getFilesDir(), "test");
+        final File deviceFile = new File(deviceContext.getFilesDir(), "test");
+
+        assertFalse(deviceFile.equals(defaultFile));
+
+        deviceFile.createNewFile();
+
+        // Make sure storage areas are mutually exclusive
+        assertFalse(defaultFile.exists());
+        assertTrue(deviceFile.exists());
+    }
+
+    public void testMigrateSharedPreferencesFrom() throws Exception {
+        final Context deviceContext = mContext.createDeviceEncryptedStorageContext();
+
+        mContext.getSharedPreferences("test", Context.MODE_PRIVATE).edit().putInt("answer", 42)
+                .commit();
+
+        // Verify that we can migrate
+        assertTrue(deviceContext.migrateSharedPreferencesFrom(mContext, "test"));
+        assertEquals(0, mContext.getSharedPreferences("test", Context.MODE_PRIVATE)
+                .getInt("answer", 0));
+        assertEquals(42, deviceContext.getSharedPreferences("test", Context.MODE_PRIVATE)
+                .getInt("answer", 0));
+
+        // Trying to migrate again when already done is a no-op
+        assertTrue(deviceContext.migrateSharedPreferencesFrom(mContext, "test"));
+        assertEquals(0, mContext.getSharedPreferences("test", Context.MODE_PRIVATE)
+                .getInt("answer", 0));
+        assertEquals(42, deviceContext.getSharedPreferences("test", Context.MODE_PRIVATE)
+                .getInt("answer", 0));
+
+        // Add a new value and verify that we can migrate back
+        deviceContext.getSharedPreferences("test", Context.MODE_PRIVATE).edit()
+                .putInt("question", 24).commit();
+
+        assertTrue(mContext.migrateSharedPreferencesFrom(deviceContext, "test"));
+        assertEquals(42, mContext.getSharedPreferences("test", Context.MODE_PRIVATE)
+                .getInt("answer", 0));
+        assertEquals(24, mContext.getSharedPreferences("test", Context.MODE_PRIVATE)
+                .getInt("question", 0));
+        assertEquals(0, deviceContext.getSharedPreferences("test", Context.MODE_PRIVATE)
+                .getInt("answer", 0));
+        assertEquals(0, deviceContext.getSharedPreferences("test", Context.MODE_PRIVATE)
+                .getInt("question", 0));
+    }
+
+    public void testMigrateDatabaseFrom() throws Exception {
+        final Context deviceContext = mContext.createDeviceEncryptedStorageContext();
+
+        SQLiteDatabase db = mContext.openOrCreateDatabase("test.db",
+                Context.MODE_PRIVATE | Context.MODE_ENABLE_WRITE_AHEAD_LOGGING, null);
+        db.execSQL("CREATE TABLE list(item TEXT);");
+        db.execSQL("INSERT INTO list VALUES ('cat')");
+        db.execSQL("INSERT INTO list VALUES ('dog')");
+        db.close();
+
+        // Verify that we can migrate
+        assertTrue(deviceContext.migrateDatabaseFrom(mContext, "test.db"));
+        db = deviceContext.openOrCreateDatabase("test.db",
+                Context.MODE_PRIVATE | Context.MODE_ENABLE_WRITE_AHEAD_LOGGING, null);
+        Cursor c = db.query("list", null, null, null, null, null, null);
+        assertEquals(2, c.getCount());
+        assertTrue(c.moveToFirst());
+        assertEquals("cat", c.getString(0));
+        assertTrue(c.moveToNext());
+        assertEquals("dog", c.getString(0));
+        c.close();
+        db.execSQL("INSERT INTO list VALUES ('mouse')");
+        db.close();
+
+        // Trying to migrate again when already done is a no-op
+        assertTrue(deviceContext.migrateDatabaseFrom(mContext, "test.db"));
+
+        // Verify that we can migrate back
+        assertTrue(mContext.migrateDatabaseFrom(deviceContext, "test.db"));
+        db = mContext.openOrCreateDatabase("test.db",
+                Context.MODE_PRIVATE | Context.MODE_ENABLE_WRITE_AHEAD_LOGGING, null);
+        c = db.query("list", null, null, null, null, null, null);
+        assertEquals(3, c.getCount());
+        assertTrue(c.moveToFirst());
+        assertEquals("cat", c.getString(0));
+        assertTrue(c.moveToNext());
+        assertEquals("dog", c.getString(0));
+        assertTrue(c.moveToNext());
+        assertEquals("mouse", c.getString(0));
+        c.close();
+        db.close();
+    }
+
     public void testAccessTheme() {
         mContext.setTheme(R.style.Test_Theme);
         final Theme testTheme = mContext.getTheme();
diff --git a/tests/tests/draganddrop/dragsource/src/android/dnd/cts/dragsource/DragSource.java b/tests/tests/draganddrop/dragsource/src/android/dnd/cts/dragsource/DragSource.java
index 7b29720..bbba70d 100644
--- a/tests/tests/draganddrop/dragsource/src/android/dnd/cts/dragsource/DragSource.java
+++ b/tests/tests/draganddrop/dragsource/src/android/dnd/cts/dragsource/DragSource.java
@@ -18,9 +18,11 @@
 
 import android.app.Activity;
 import android.content.ClipData;
+import android.content.ClipDescription;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.PersistableBundle;
 import android.view.View;
 
 public class DragSource extends Activity{
@@ -65,8 +67,14 @@
         findViewById(resourceId).setOnLongClickListener(new View.OnLongClickListener() {
             @Override
             public boolean onLongClick(final View v) {
+                final ClipDescription clipDescription = new ClipDescription("", new String[] {
+                        ClipDescription.MIMETYPE_TEXT_URILIST });
+                PersistableBundle extras = new PersistableBundle(1);
+                extras.putString("extraKey", "extraValue");
+                clipDescription.setExtras(extras);
+                final ClipData clipData = new ClipData(clipDescription, new ClipData.Item(uri));
                 v.startDragAndDrop(
-                        ClipData.newUri(getContentResolver(), "", uri),
+                        clipData,
                         new View.DragShadowBuilder(v),
                         null,
                         flags);
diff --git a/tests/tests/draganddrop/droptarget/res/layout/main_activity.xml b/tests/tests/draganddrop/droptarget/res/layout/main_activity.xml
index 2af6375..4a5a5b1 100644
--- a/tests/tests/draganddrop/droptarget/res/layout/main_activity.xml
+++ b/tests/tests/draganddrop/droptarget/res/layout/main_activity.xml
@@ -92,6 +92,14 @@
     </TextView>
 
     <TextView
+            android:id="@+id/extra_value"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="10dp"
+            android:text="@string/not_available_label">
+    </TextView>
+
+    <TextView
             android:id="@+id/details"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
diff --git a/tests/tests/draganddrop/droptarget/src/android/dnd/cts/droptarget/DropTarget.java b/tests/tests/draganddrop/droptarget/src/android/dnd/cts/droptarget/DropTarget.java
index 82aaf93..2be57d4 100644
--- a/tests/tests/draganddrop/droptarget/src/android/dnd/cts/droptarget/DropTarget.java
+++ b/tests/tests/draganddrop/droptarget/src/android/dnd/cts/droptarget/DropTarget.java
@@ -22,6 +22,7 @@
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.PersistableBundle;
 import android.view.DragEvent;
 import android.view.DropPermissions;
 import android.view.View;
@@ -50,6 +51,19 @@
         findViewById(targetResourceId).setOnDragListener(listener);
     }
 
+    private String checkExtraValue(DragEvent event) {
+        PersistableBundle extras = event.getClipDescription().getExtras();
+        if (extras == null) {
+            return "Null";
+        }
+
+        final String value = extras.getString("extraKey");
+        if ("extraValue".equals(value)) {
+            return RESULT_OK;
+        }
+        return value;
+    }
+
     private abstract class OnDragUriListener implements View.OnDragListener {
         private final boolean requestPermissions;
 
@@ -62,6 +76,7 @@
             switch (event.getAction()) {
                 case DragEvent.ACTION_DRAG_STARTED:
                     ((TextView) findViewById(R.id.drag_started)).setText("DRAG_STARTED");
+                    ((TextView) findViewById(R.id.extra_value)).setText(checkExtraValue(event));
                     return true;
 
                 case DragEvent.ACTION_DRAG_ENTERED:
diff --git a/tests/tests/draganddrop/src/android/dnd/cts/DragAndDropTest.java b/tests/tests/draganddrop/src/android/dnd/cts/DragAndDropTest.java
index 71e1827..78b85f5 100644
--- a/tests/tests/draganddrop/src/android/dnd/cts/DragAndDropTest.java
+++ b/tests/tests/draganddrop/src/android/dnd/cts/DragAndDropTest.java
@@ -111,19 +111,27 @@
         assertEquals(expectedResult, drag_started.getText());
     }
 
+    private void assertExtraValue(String expectedResult) {
+        UiObject2 extra_value = findObject(DROP_TARGET_PKG, "extra_value");
+        assertEquals(expectedResult, extra_value.getText());
+    }
+
     public void testLocal() {
         doCrossAppDrag("disallow_global", "dont_request", "N/A");
         assertDragStarted("N/A");
+        assertExtraValue("N/A");
     }
 
     public void testCancel() {
         doCrossAppDrag("cancel_soon", "dont_request", "N/A");
         assertDragStarted("DRAG_STARTED");
+        assertExtraValue("OK");
     }
 
     public void testDontGrantDontRequest() {
         doCrossAppDrag("dont_grant", "dont_request", "Exception");
         assertDragStarted("DRAG_STARTED");
+        assertExtraValue("OK");
     }
 
     public void testDontGrantRequestRead() {
diff --git a/tests/tests/externalservice/Android.mk b/tests/tests/externalservice/Android.mk
new file mode 100644
index 0000000..4fa4666
--- /dev/null
+++ b/tests/tests/externalservice/Android.mk
@@ -0,0 +1,42 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Don't include this package in any target
+LOCAL_MODULE_TAGS := tests
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_STATIC_JAVA_LIBRARIES := CtsExternalServiceCommon ctsdeviceutil ctstestrunner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_CTS_MODULE_CONFIG := $(LOCAL_PATH)/Old$(CTS_MODULE_TEST_CONFIG)
+
+LOCAL_PACKAGE_NAME := CtsExternalServiceTestCases
+
+LOCAL_SDK_VERSION := system_current
+
+include $(BUILD_CTS_PACKAGE)
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/externalservice/AndroidManifest.xml b/tests/tests/externalservice/AndroidManifest.xml
new file mode 100644
index 0000000..0c5ea5d
--- /dev/null
+++ b/tests/tests/externalservice/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.externalservice.cts">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation
+        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:label="CTS external service tests"
+        android:targetPackage="android.externalservice.cts" >
+    </instrumentation>
+</manifest>
+
diff --git a/tests/tests/externalservice/AndroidTest.xml b/tests/tests/externalservice/AndroidTest.xml
new file mode 100644
index 0000000..b07f248
--- /dev/null
+++ b/tests/tests/externalservice/AndroidTest.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.
+-->
+<configuration description="Config for CTS External Service test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsExternalServiceService.apk" />
+        <option name="test-file-name" value="CtsExternalServiceTestCases.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.externalservice.cts" />
+    </test>
+</configuration>
diff --git a/tests/tests/externalservice/OldAndroidTest.xml b/tests/tests/externalservice/OldAndroidTest.xml
new file mode 100644
index 0000000..838db60
--- /dev/null
+++ b/tests/tests/externalservice/OldAndroidTest.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.
+-->
+<configuration description="Config for CTS External Service test cases">
+    <include name="common-config" />
+    <option name="cts-apk-installer:test-file-name" value="CtsExternalServiceService.apk" />
+    <option name="cts-apk-installer:test-file-name" value="CtsExternalServiceTestCases.apk" />
+</configuration>
diff --git a/tests/tests/externalservice/common/Android.mk b/tests/tests/externalservice/common/Android.mk
new file mode 100644
index 0000000..1ebf149
--- /dev/null
+++ b/tests/tests/externalservice/common/Android.mk
@@ -0,0 +1,30 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := optional
+# and when built explicitly put it in the data partition
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_MODULE := CtsExternalServiceCommon
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tests/tests/externalservice/common/src/android/externalservice/common/ServiceMessages.java b/tests/tests/externalservice/common/src/android/externalservice/common/ServiceMessages.java
new file mode 100644
index 0000000..8d23bc0
--- /dev/null
+++ b/tests/tests/externalservice/common/src/android/externalservice/common/ServiceMessages.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.externalservice.common;
+
+import android.os.IBinder;
+
+public class ServiceMessages {
+    // No arguments. Gets the UID and PID of the service.
+    public static final int MSG_IDENTIFY = IBinder.FIRST_CALL_TRANSACTION + 1;
+    // Response to MSG_IDENTIFY. arg1 is the UID, arg2 is the PID.
+    public static final int MSG_IDENTIFY_RESPONSE = MSG_IDENTIFY + 100;
+
+    // Bundle key in MSG_IDENTIFY_RESPONSE containing the package name.
+    public static final String IDENTIFY_PACKAGE = "packageName";
+
+    // No arguments. Starts an external service.
+    public static final int MSG_CREATE_EXTERNAL_SERVICE = IBinder.FIRST_CALL_TRANSACTION + 2;
+    // Responds to MSG_CREATE_EXTERNAL_SERVICE. obj is the IBinder on success, null on failure.
+    public static final int MSG_CREATE_EXTERNAL_SERVICE_RESPONSE =
+        MSG_CREATE_EXTERNAL_SERVICE + 100;
+
+    private ServiceMessages() {}
+}
diff --git a/tests/tests/externalservice/service/Android.mk b/tests/tests/externalservice/service/Android.mk
new file mode 100644
index 0000000..ca19202
--- /dev/null
+++ b/tests/tests/externalservice/service/Android.mk
@@ -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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := optional
+# and when built explicitly put it in the data partition
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := CtsExternalServiceCommon ctstestrunner ctsdeviceutil
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsExternalServiceService
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
+LOCAL_SDK_VERSION := system_current
+
+include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/tests/externalservice/service/AndroidManifest.xml b/tests/tests/externalservice/service/AndroidManifest.xml
new file mode 100644
index 0000000..06fa80e
--- /dev/null
+++ b/tests/tests/externalservice/service/AndroidManifest.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.externalservice.service">
+
+    <application android:label="External Service Host">
+        <!-- Service used to start .ExternalService from this package. -->
+        <service android:name=".ServiceCreator"
+                 android:isolatedProcess="false"
+                 android:externalService="false"
+                 android:exported="true" />
+
+        <!-- These services only respond to MSG_IDENTIFY for testing bindService(). -->
+        <service android:name=".IsolatedService"
+                 android:isolatedProcess="true"
+                 android:externalService="false"
+                 android:exported="false"/>
+        <service android:name=".ExportedService"
+                 android:isolatedProcess="true"
+                 android:externalService="false"
+                 android:exported="true"/>
+        <service android:name=".ExternalNonExportedService"
+                 android:isolatedProcess="true"
+                 android:externalService="true"
+                 android:exported="false"/>
+        <service android:name=".ExternalNonIsolatedService"
+                 android:isolatedProcess="false"
+                 android:externalService="true"
+                 android:exported="true"/>
+
+        <!-- The only valid, externalService entry. -->
+        <service android:name=".ExternalService"
+                 android:isolatedProcess="true"
+                 android:externalService="true"
+                 android:exported="true"/>
+    </application>
+
+</manifest>
diff --git a/tests/tests/externalservice/service/src/android/externalservice/service/BaseService.java b/tests/tests/externalservice/service/src/android/externalservice/service/BaseService.java
new file mode 100644
index 0000000..a14adbe
--- /dev/null
+++ b/tests/tests/externalservice/service/src/android/externalservice/service/BaseService.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.externalservice.service;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.Process;
+import android.os.RemoteException;
+import android.util.Log;
+
+import android.externalservice.common.ServiceMessages;
+
+public class BaseService extends Service {
+    private static final String TAG = "ExternalServiceTest.Service";
+
+    private final Handler mHandler = new BaseHandler(this);
+    private final Messenger mMessenger = new Messenger(mHandler);
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        Log.d(TAG, "onBind " + intent);
+        return mMessenger.getBinder();
+    }
+
+    static class BaseHandler extends Handler {
+        private Context mContext;
+
+        public BaseHandler(Context context) {
+            mContext = context;
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            Log.d(TAG, "Received message: " + msg);
+            switch (msg.what) {
+                case ServiceMessages.MSG_IDENTIFY:
+                    Message reply = Message.obtain(null, ServiceMessages.MSG_IDENTIFY_RESPONSE,
+                            Process.myUid(), Process.myPid());
+                    reply.getData().putString(ServiceMessages.IDENTIFY_PACKAGE,
+                            mContext.getPackageName());
+                    try {
+                        msg.replyTo.send(reply);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Error sending MSG_IDENTIFY_RESPONSE", e);
+                    }
+                    break;
+            }
+            super.handleMessage(msg);
+        }
+    }
+}
diff --git a/tests/tests/externalservice/service/src/android/externalservice/service/ExportedService.java b/tests/tests/externalservice/service/src/android/externalservice/service/ExportedService.java
new file mode 100644
index 0000000..faee786
--- /dev/null
+++ b/tests/tests/externalservice/service/src/android/externalservice/service/ExportedService.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.externalservice.service;
+
+public class ExportedService extends BaseService {
+}
diff --git a/tests/tests/externalservice/service/src/android/externalservice/service/ExternalNonExportedService.java b/tests/tests/externalservice/service/src/android/externalservice/service/ExternalNonExportedService.java
new file mode 100644
index 0000000..91ab426
--- /dev/null
+++ b/tests/tests/externalservice/service/src/android/externalservice/service/ExternalNonExportedService.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.externalservice.service;
+
+public class ExternalNonExportedService extends BaseService {
+}
diff --git a/tests/tests/externalservice/service/src/android/externalservice/service/ExternalNonIsolatedService.java b/tests/tests/externalservice/service/src/android/externalservice/service/ExternalNonIsolatedService.java
new file mode 100644
index 0000000..c8f4a50
--- /dev/null
+++ b/tests/tests/externalservice/service/src/android/externalservice/service/ExternalNonIsolatedService.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.externalservice.service;
+
+public class ExternalNonIsolatedService extends BaseService {
+}
diff --git a/tests/tests/externalservice/service/src/android/externalservice/service/ExternalService.java b/tests/tests/externalservice/service/src/android/externalservice/service/ExternalService.java
new file mode 100644
index 0000000..50b475a
--- /dev/null
+++ b/tests/tests/externalservice/service/src/android/externalservice/service/ExternalService.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.externalservice.service;
+
+public class ExternalService extends BaseService {
+}
diff --git a/tests/tests/externalservice/service/src/android/externalservice/service/IsolatedService.java b/tests/tests/externalservice/service/src/android/externalservice/service/IsolatedService.java
new file mode 100644
index 0000000..94db76f
--- /dev/null
+++ b/tests/tests/externalservice/service/src/android/externalservice/service/IsolatedService.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.externalservice.service;
+
+public class IsolatedService extends BaseService {
+}
diff --git a/tests/tests/externalservice/service/src/android/externalservice/service/ServiceCreator.java b/tests/tests/externalservice/service/src/android/externalservice/service/ServiceCreator.java
new file mode 100644
index 0000000..3af5c98
--- /dev/null
+++ b/tests/tests/externalservice/service/src/android/externalservice/service/ServiceCreator.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.externalservice.service;
+
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.Process;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.ArrayList;
+
+import android.externalservice.common.ServiceMessages;
+
+public class ServiceCreator extends Service {
+    private static final String TAG = "ExternalServiceTest.ServiceCreator";
+
+    private final ArrayList<CreatorConnection> mConnections = new ArrayList<>();
+
+    private final Handler mHandler = new BaseService.BaseHandler(this) {
+        @Override
+        public void handleMessage(Message msg) {
+            Log.d(TAG, "Received message: " + msg);
+            switch (msg.what) {
+                case ServiceMessages.MSG_CREATE_EXTERNAL_SERVICE:
+                    final Context context = ServiceCreator.this;
+                    final String pkgName = context.getPackageName();
+                    Intent intent = new Intent();
+                    intent.setComponent(new ComponentName(pkgName, pkgName+".ExternalService"));
+                    CreatorConnection conn = new CreatorConnection(msg.replyTo);
+                    boolean result = context.bindService(intent, conn,
+                            Context.BIND_AUTO_CREATE | Context.BIND_EXTERNAL_SERVICE);
+                    if (result) {
+                        mConnections.add(conn);
+                    } else {
+                        Message reply = Message.obtain();
+                        reply.what = ServiceMessages.MSG_CREATE_EXTERNAL_SERVICE_RESPONSE;
+                        try {
+                            msg.replyTo.send(reply);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "Failed to send MSG_CREATE_EXTERNAL_SERVICE_RESPONSE", e);
+                        }
+                    }
+            }
+            super.handleMessage(msg);
+        }
+    };
+
+    private final Messenger mMessenger = new Messenger(mHandler);
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        Log.d(TAG, "onBind " + intent);
+        return mMessenger.getBinder();
+    }
+
+    @Override
+    public void onDestroy() {
+        for (final CreatorConnection conn : mConnections) {
+            unbindService(conn);
+        }
+        super.onDestroy();
+    }
+
+    private class CreatorConnection implements ServiceConnection {
+        private IBinder mService = null;
+        private Messenger mReplyTo = null;
+
+        public CreatorConnection(Messenger replyTo) {
+            mReplyTo = replyTo;
+        }
+
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            Log.d(TAG, "onServiceConnected " + name);
+            Message msg =
+                    Message.obtain(null, ServiceMessages.MSG_CREATE_EXTERNAL_SERVICE_RESPONSE);
+            msg.obj = new Messenger(service);
+            try {
+                mReplyTo.send(msg);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to send MSG_CREATE_EXTERNAL_SERVICE_RESPONSE", e);
+            }
+            mReplyTo = null;
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            Log.d(TAG, "onServiceDisconnected " + name);
+            mService = null;
+        }
+    }
+}
diff --git a/tests/tests/externalservice/src/android/externalservice/cts/ExternalServiceTest.java b/tests/tests/externalservice/src/android/externalservice/cts/ExternalServiceTest.java
new file mode 100644
index 0000000..b80b2ff
--- /dev/null
+++ b/tests/tests/externalservice/src/android/externalservice/cts/ExternalServiceTest.java
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.externalservice.cts;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.ConditionVariable;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.Parcel;
+import android.os.Process;
+import android.os.RemoteException;
+import android.test.AndroidTestCase;
+import android.util.Log;
+import android.util.MutableInt;
+
+import android.externalservice.common.ServiceMessages;
+
+public class ExternalServiceTest extends AndroidTestCase {
+    private static final String TAG = "ExternalServiceTest";
+
+    static final String sServicePackage = "android.externalservice.service";
+
+    private Connection mConnection = new Connection();
+
+    private ConditionVariable mCondition = new ConditionVariable(false);
+
+    static final int CONDITION_TIMEOUT = 10 * 1000 /* 10 seconds */;
+
+    public void tearDown() {
+        if (mConnection.service != null)
+            getContext().unbindService(mConnection);
+    }
+
+    /** Tests that an isolatedProcess service cannot be bound to by an external package. */
+    public void testFailBindIsolated() {
+        Intent intent = new Intent();
+        intent.setComponent(new ComponentName(sServicePackage, sServicePackage+".IsolatedService"));
+        try {
+            getContext().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
+            fail("Should not be able to bind to non-exported, non-external service");
+        } catch (SecurityException e) {
+        }
+    }
+
+    /** Tests that BIND_EXTERNAL_SERVICE does not work with plain isolatedProcess services. */
+    public void testFailBindExternalIsolated() {
+        Intent intent = new Intent();
+        intent.setComponent(new ComponentName(sServicePackage, sServicePackage+".IsolatedService"));
+        try {
+            getContext().bindService(intent, mConnection,
+                    Context.BIND_AUTO_CREATE | Context.BIND_EXTERNAL_SERVICE);
+            fail("Should not be able to BIND_EXTERNAL_SERVICE to non-exported, non-external service");
+        } catch (SecurityException e) {
+        }
+    }
+
+    /** Tests that BIND_EXTERNAL_SERVICE does not work with exported, isolatedProcess services (
+     * requires externalService as well). */
+    public void testFailBindExternalExported() {
+        Intent intent = new Intent();
+        intent.setComponent(new ComponentName(sServicePackage, sServicePackage+".ExportedService"));
+        try {
+            getContext().bindService(intent, mConnection,
+                    Context.BIND_AUTO_CREATE | Context.BIND_EXTERNAL_SERVICE);
+            fail("Should not be able to BIND_EXTERNAL_SERVICE to non-external service");
+        } catch (SecurityException e) {
+        }
+    }
+
+    /** Tests that BIND_EXTERNAL_SERVICE requires that an externalService be exported. */
+    public void testFailBindExternalNonExported() {
+        Intent intent = new Intent();
+        intent.setComponent(
+                new ComponentName(sServicePackage, sServicePackage+".ExternalNonExportedService"));
+        try {
+            getContext().bindService(intent, mConnection,
+                    Context.BIND_AUTO_CREATE | Context.BIND_EXTERNAL_SERVICE);
+            fail("Should not be able to BIND_EXTERNAL_SERVICE to non-exported service");
+        } catch (SecurityException e) {
+        }
+    }
+
+    /** Tests that BIND_EXTERNAL_SERVICE requires the service be an isolatedProcess. */
+    public void testFailBindExternalNonIsolated() {
+        Intent intent = new Intent();
+        intent.setComponent(
+                new ComponentName(sServicePackage, sServicePackage+".ExternalNonIsolatedService"));
+        try {
+            getContext().bindService(intent, mConnection,
+                    Context.BIND_AUTO_CREATE | Context.BIND_EXTERNAL_SERVICE);
+            fail("Should not be able to BIND_EXTERNAL_SERVICE to non-isolated service");
+        } catch (SecurityException e) {
+        }
+    }
+
+    /** Tests that an externalService can only be bound with BIND_EXTERNAL_SERVICE. */
+    public void testFailBindWithoutBindExternal() {
+        Intent intent = new Intent();
+        intent.setComponent(new ComponentName(sServicePackage, sServicePackage+".ExternalService"));
+        try {
+            getContext().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
+            fail("Should not be able to bind to an external service without BIND_EXTERNAL_SERVICE");
+        } catch (SecurityException e) {
+        }
+    }
+
+    /** Tests that an external service can be bound, and that it runs as a different principal. */
+    public void testBindExternalService() {
+        // Start the service and wait for connection.
+        Intent intent = new Intent();
+        intent.setComponent(new ComponentName(sServicePackage, sServicePackage+".ExternalService"));
+
+        mCondition.close();
+        assertTrue(getContext().bindService(intent, mConnection,
+                    Context.BIND_AUTO_CREATE | Context.BIND_EXTERNAL_SERVICE));
+
+        assertTrue(mCondition.block(CONDITION_TIMEOUT));
+        assertEquals(getContext().getPackageName(), mConnection.name.getPackageName());
+        assertNotSame(sServicePackage, mConnection.name.getPackageName());
+
+        // Check the identity of the service.
+        Messenger remote = new Messenger(mConnection.service);
+        MutableInt uid = new MutableInt(0);
+        MutableInt pid = new MutableInt(0);
+        StringBuilder pkg = new StringBuilder();
+        assertTrue(identifyService(remote, uid, pid, pkg));
+
+        assertFalse(uid.value == 0 || pid.value == 0);
+        assertNotEquals(Process.myUid(), uid.value);
+        assertNotEquals(Process.myPid(), pid.value);
+        assertEquals(getContext().getPackageName(), pkg.toString());
+    }
+
+    /** Tests that the APK providing the externalService can bind the service itself, and that
+     * other APKs bind to a different instance of it. */
+    public void testBindExternalServiceWithRunningOwn() {
+        // Start the service that will create the externalService.
+        final Connection creatorConnection = new Connection();
+        Intent intent = new Intent();
+        intent.setComponent(new ComponentName(sServicePackage, sServicePackage+".ServiceCreator"));
+
+        mCondition.close();
+        assertTrue(getContext().bindService(intent, creatorConnection, Context.BIND_AUTO_CREATE));
+        assertTrue(mCondition.block(CONDITION_TIMEOUT));
+
+        // Get the identity of the creator.
+        Messenger remoteCreator = new Messenger(creatorConnection.service);
+        MutableInt creatorUid = new MutableInt(0);
+        MutableInt creatorPid = new MutableInt(0);
+        StringBuilder creatorPkg = new StringBuilder();
+        assertTrue(identifyService(remoteCreator, creatorUid, creatorPid, creatorPkg));
+        assertFalse(creatorUid.value == 0 || creatorPid.value == 0);
+
+        // Have the creator actually start its service.
+        final Message creatorMsg =
+                Message.obtain(null, ServiceMessages.MSG_CREATE_EXTERNAL_SERVICE);
+        Handler creatorHandler = new Handler(Looper.getMainLooper()) {
+            @Override
+            public void handleMessage(Message msg) {
+                Log.d(TAG, "Received message: " + msg);
+                switch (msg.what) {
+                    case ServiceMessages.MSG_CREATE_EXTERNAL_SERVICE_RESPONSE:
+                        creatorMsg.copyFrom(msg);
+                        mCondition.open();
+                        break;
+                }
+                super.handleMessage(msg);
+            }
+        };
+        Messenger localCreator = new Messenger(creatorHandler);
+        creatorMsg.replyTo = localCreator;
+        try {
+            mCondition.close();
+            remoteCreator.send(creatorMsg);
+        } catch (RemoteException e) {
+            fail("Unexpected remote exception" + e);
+            return;
+        }
+        assertTrue(mCondition.block(CONDITION_TIMEOUT));
+
+        // Get the connection to the creator's service.
+        assertNotNull(creatorMsg.obj);
+        Messenger remoteCreatorService = (Messenger) creatorMsg.obj;
+        MutableInt creatorServiceUid = new MutableInt(0);
+        MutableInt creatorServicePid = new MutableInt(0);
+        StringBuilder creatorServicePkg = new StringBuilder();
+        assertTrue(identifyService(remoteCreatorService, creatorServiceUid, creatorServicePid,
+                creatorServicePkg));
+        assertFalse(creatorServiceUid.value == 0 || creatorPid.value == 0);
+
+        // Create an external service from this (the test) process.
+        intent = new Intent();
+        intent.setComponent(new ComponentName(sServicePackage, sServicePackage+".ExternalService"));
+
+        mCondition.close();
+        assertTrue(getContext().bindService(intent, mConnection,
+                    Context.BIND_AUTO_CREATE | Context.BIND_EXTERNAL_SERVICE));
+        assertTrue(mCondition.block(CONDITION_TIMEOUT));
+        MutableInt serviceUid = new MutableInt(0);
+        MutableInt servicePid = new MutableInt(0);
+        StringBuilder servicePkg = new StringBuilder();
+        assertTrue(identifyService(new Messenger(mConnection.service), serviceUid, servicePid,
+                servicePkg));
+        assertFalse(serviceUid.value == 0 || servicePid.value == 0);
+
+        // Make sure that all the processes are unique.
+        int myUid = Process.myUid();
+        int myPid = Process.myPid();
+        String myPkg = getContext().getPackageName();
+
+        assertNotEquals(myUid, creatorUid.value);
+        assertNotEquals(myUid, creatorServiceUid.value);
+        assertNotEquals(myUid, serviceUid.value);
+        assertNotEquals(myPid, creatorPid.value);
+        assertNotEquals(myPid, creatorServicePid.value);
+        assertNotEquals(myPid, servicePid.value);
+
+        assertNotEquals(creatorUid.value, creatorServiceUid.value);
+        assertNotEquals(creatorUid.value, serviceUid.value);
+        assertNotEquals(creatorPid.value, creatorServicePid.value);
+        assertNotEquals(creatorPid.value, servicePid.value);
+
+        assertNotEquals(creatorServiceUid.value, serviceUid.value);
+        assertNotEquals(creatorServicePid.value, servicePid.value);
+
+        assertNotEquals(myPkg, creatorPkg.toString());
+        assertNotEquals(myPkg, creatorServicePkg.toString());
+        assertEquals(creatorPkg.toString(), creatorServicePkg.toString());
+        assertEquals(myPkg, servicePkg.toString());
+
+        getContext().unbindService(creatorConnection);
+    }
+
+    /** Tests that the binding to an externalService can be changed. */
+    public void testBindExternalAboveClient() {
+        // Start the service and wait for connection.
+        Intent intent = new Intent();
+        intent.setComponent(new ComponentName(sServicePackage, sServicePackage+".ExternalService"));
+
+        mCondition.close();
+        Connection initialConn = new Connection();
+        assertTrue(getContext().bindService(intent, initialConn,
+                    Context.BIND_AUTO_CREATE | Context.BIND_EXTERNAL_SERVICE));
+
+        assertTrue(mCondition.block(CONDITION_TIMEOUT));
+
+        MutableInt uidOne = new MutableInt(0);
+        MutableInt pidOne = new MutableInt(0);
+        StringBuilder pkgOne = new StringBuilder();
+        assertTrue(identifyService(new Messenger(initialConn.service), uidOne, pidOne, pkgOne));
+        assertFalse(uidOne.value == 0 || pidOne.value == 0);
+
+        // Bind the service with a different priority.
+        mCondition.close();
+        Connection prioConn = new Connection();
+        assertTrue(getContext().bindService(intent, prioConn,
+                    Context.BIND_AUTO_CREATE | Context.BIND_EXTERNAL_SERVICE |
+                            Context.BIND_ABOVE_CLIENT));
+
+        assertTrue(mCondition.block(CONDITION_TIMEOUT));
+
+        MutableInt uidTwo = new MutableInt(0);
+        MutableInt pidTwo = new MutableInt(0);
+        StringBuilder pkgTwo = new StringBuilder();
+        Messenger prioMessenger = new Messenger(prioConn.service);
+        assertTrue(identifyService(prioMessenger, uidTwo, pidTwo, pkgTwo));
+        assertFalse(uidTwo.value == 0 || pidTwo.value == 0);
+
+        assertEquals(uidOne.value, uidTwo.value);
+        assertEquals(pidOne.value, pidTwo.value);
+        assertEquals(pkgOne.toString(), pkgTwo.toString());
+        assertNotEquals(Process.myUid(), uidOne.value);
+        assertNotEquals(Process.myPid(), pidOne.value);
+        assertEquals(getContext().getPackageName(), pkgOne.toString());
+
+        getContext().unbindService(prioConn);
+        getContext().unbindService(initialConn);
+    }
+
+    /** Given a Messenger, this will message the service to retrieve its UID, PID, and package name,
+     * storing the results in the mutable parameters. */
+    private boolean identifyService(Messenger service, final MutableInt uid, final MutableInt pid,
+            final StringBuilder packageName) {
+        Handler handler = new Handler(Looper.getMainLooper()) {
+            @Override
+            public void handleMessage(Message msg) {
+                Log.d(TAG, "Received message: " + msg);
+                switch (msg.what) {
+                    case ServiceMessages.MSG_IDENTIFY_RESPONSE:
+                        uid.value = msg.arg1;
+                        pid.value = msg.arg2;
+                        packageName.append(
+                                msg.getData().getString(ServiceMessages.IDENTIFY_PACKAGE));
+                        mCondition.open();
+                        break;
+                }
+                super.handleMessage(msg);
+            }
+        };
+        Messenger local = new Messenger(handler);
+
+        Message msg = Message.obtain(null, ServiceMessages.MSG_IDENTIFY);
+        msg.replyTo = local;
+        try {
+            mCondition.close();
+            service.send(msg);
+        } catch (RemoteException e) {
+            fail("Unexpected remote exception: " + e);
+            return false;
+        }
+
+        return mCondition.block(CONDITION_TIMEOUT);
+    }
+
+    private class Connection implements ServiceConnection {
+        IBinder service = null;
+        ComponentName name = null;
+        boolean disconnected = false;
+
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            Log.d(TAG, "onServiceConnected " + name);
+            this.service = service;
+            this.name = name;
+            mCondition.open();
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            Log.d(TAG, "onServiceDisconnected " + name);
+        }
+    }
+
+    private <T> void assertNotEquals(T expected, T actual) {
+        assertFalse("Expected <" + expected + "> should not be equal to actual <" + actual + ">",
+                expected.equals(actual));
+    }
+}
diff --git a/tests/tests/graphics/res/color/fill_gradient_linear.xml b/tests/tests/graphics/res/color/fill_gradient_linear.xml
new file mode 100644
index 0000000..e0e3f03
--- /dev/null
+++ b/tests/tests/graphics/res/color/fill_gradient_linear.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:angle="90"
+          android:startColor="?android:attr/colorPrimary"
+          android:endColor="?android:attr/colorControlActivated"
+          android:centerColor="#00ff0000"
+          android:startX="0"
+          android:startY="0"
+          android:endX="100"
+          android:endY="100"
+          android:type="linear">
+</gradient>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/color/fill_gradient_linear_item.xml b/tests/tests/graphics/res/color/fill_gradient_linear_item.xml
new file mode 100644
index 0000000..cfb1236
--- /dev/null
+++ b/tests/tests/graphics/res/color/fill_gradient_linear_item.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:angle="90"
+          android:startColor="?android:attr/colorPrimary"
+          android:endColor="?android:attr/colorControlActivated"
+          android:centerColor="#f00"
+          android:startX="0"
+          android:startY="0"
+          android:endX="100"
+          android:endY="100"
+          android:type="linear">
+    <item android:offset="0.1" android:color="?android:attr/colorPrimary"/>
+    <item android:offset="0.4" android:color="#fff"/>
+    <item android:offset="0.9" android:color="?android:attr/colorControlActivated"/>
+</gradient>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/color/fill_gradient_linear_item_overlap.xml b/tests/tests/graphics/res/color/fill_gradient_linear_item_overlap.xml
new file mode 100644
index 0000000..18274b9
--- /dev/null
+++ b/tests/tests/graphics/res/color/fill_gradient_linear_item_overlap.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:angle="90"
+          android:startColor="?android:attr/colorPrimary"
+          android:endColor="?android:attr/colorControlActivated"
+          android:centerColor="#f00"
+          android:startX="0"
+          android:startY="0"
+          android:endX="100"
+          android:endY="100"
+          android:type="linear">
+    <item android:offset="0.1" android:color="?android:attr/colorPrimary"/>
+    <item android:offset="0.4" android:color="#f00"/>
+    <item android:offset="0.4" android:color="#fff"/>
+    <item android:offset="0.9" android:color="?android:attr/colorControlActivated"/>
+</gradient>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/color/fill_gradient_radial.xml b/tests/tests/graphics/res/color/fill_gradient_radial.xml
new file mode 100644
index 0000000..ef6fd70
--- /dev/null
+++ b/tests/tests/graphics/res/color/fill_gradient_radial.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:centerColor="#ff0000"
+          android:endColor="?android:attr/colorControlActivated"
+          android:centerX="300"
+          android:centerY="300"
+          android:gradientRadius="100"
+          android:startColor="?android:attr/colorPrimary"
+          android:type="radial">
+</gradient>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/color/fill_gradient_radial_item.xml b/tests/tests/graphics/res/color/fill_gradient_radial_item.xml
new file mode 100644
index 0000000..c6cea7c
--- /dev/null
+++ b/tests/tests/graphics/res/color/fill_gradient_radial_item.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:centerColor="#ff0000"
+          android:endColor="#ff0000ff"
+          android:centerX="300"
+          android:centerY="300"
+          android:gradientRadius="100"
+          android:startColor="#ffffffff"
+          android:type="radial">
+    <item android:offset="0.1" android:color="?android:attr/colorPrimary"/>
+    <item android:offset="0.4" android:color="#fff"/>
+    <item android:offset="0.9" android:color="?android:attr/colorControlActivated"/>
+</gradient>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/color/fill_gradient_radial_item_short.xml b/tests/tests/graphics/res/color/fill_gradient_radial_item_short.xml
new file mode 100644
index 0000000..fefbe9f
--- /dev/null
+++ b/tests/tests/graphics/res/color/fill_gradient_radial_item_short.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:centerX="300"
+          android:centerY="300"
+          android:gradientRadius="100"
+          android:type="radial">
+    <item android:offset="0.1" android:color="?android:attr/colorPrimary"/>
+    <item android:offset="0.9" android:color="?android:attr/colorControlActivated"/>
+</gradient>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/color/fill_gradient_sweep.xml b/tests/tests/graphics/res/color/fill_gradient_sweep.xml
new file mode 100644
index 0000000..e1fbd10
--- /dev/null
+++ b/tests/tests/graphics/res/color/fill_gradient_sweep.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:centerColor="#ff0000"
+          android:endColor="#ff0000ff"
+          android:centerX="500"
+          android:centerY="500"
+          android:gradientRadius="10"
+          android:startColor="#ffffffff"
+          android:type="sweep">
+</gradient>
diff --git a/tests/tests/graphics/res/color/fill_gradient_sweep_item.xml b/tests/tests/graphics/res/color/fill_gradient_sweep_item.xml
new file mode 100644
index 0000000..332b9389
--- /dev/null
+++ b/tests/tests/graphics/res/color/fill_gradient_sweep_item.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:centerColor="#ff0000"
+          android:endColor="#ff0000ff"
+          android:centerX="500"
+          android:centerY="500"
+          android:gradientRadius="10"
+          android:startColor="#ffffffff"
+          android:type="sweep">
+    <item android:offset="0.1" android:color="?android:attr/colorPrimary"/>
+    <item android:offset="0.4" android:color="#fff"/>
+    <item android:offset="0.9" android:color="?android:attr/colorControlActivated"/>
+</gradient>
diff --git a/tests/tests/graphics/res/color/fill_gradient_sweep_item_long.xml b/tests/tests/graphics/res/color/fill_gradient_sweep_item_long.xml
new file mode 100644
index 0000000..3931288
--- /dev/null
+++ b/tests/tests/graphics/res/color/fill_gradient_sweep_item_long.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:centerX="500"
+          android:centerY="500"
+          android:gradientRadius="10"
+          android:type="sweep">
+    <item android:offset="-0.3" android:color="#f00"/>
+    <item android:offset="0.1" android:color="?android:attr/colorPrimary"/>
+    <item android:offset="0.4" android:color="#0f0"/>
+    <item android:offset="0.6" android:color="#00f"/>
+    <item android:offset="0.7" android:color="?android:attr/colorControlActivated"/>
+    <item android:offset="1.5" android:color="#00f"/>
+</gradient>
diff --git a/tests/tests/graphics/res/color/stroke_gradient.xml b/tests/tests/graphics/res/color/stroke_gradient.xml
new file mode 100644
index 0000000..cb324c9
--- /dev/null
+++ b/tests/tests/graphics/res/color/stroke_gradient.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:angle="90"
+          android:centerColor="#7f7f7f"
+          android:endColor="#ffffff"
+          android:startColor="#000000"
+          android:startX="0"
+          android:endX="100"
+          android:startY="0"
+          android:endY="0"
+          android:type="linear">
+</gradient>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/color/stroke_gradient_item.xml b/tests/tests/graphics/res/color/stroke_gradient_item.xml
new file mode 100644
index 0000000..15d948c
--- /dev/null
+++ b/tests/tests/graphics/res/color/stroke_gradient_item.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:angle="90"
+          android:centerColor="#7f7f7f"
+          android:endColor="#ffffff"
+          android:startColor="#000000"
+          android:startX="0"
+          android:endX="100"
+          android:startY="0"
+          android:endY="0"
+          android:type="linear">
+    <item android:offset="0.1" android:color="#f00"/>
+    <item android:offset="0.2" android:color="#f0f"/>
+    <item android:offset="0.9" android:color="#f00f"/>
+</gradient>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/color/stroke_gradient_item_alpha.xml b/tests/tests/graphics/res/color/stroke_gradient_item_alpha.xml
new file mode 100644
index 0000000..fda2b88
--- /dev/null
+++ b/tests/tests/graphics/res/color/stroke_gradient_item_alpha.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:startX="0"
+          android:endX="100"
+          android:startY="0"
+          android:endY="0"
+          android:type="linear">
+    <item android:offset="0.1" android:color="#f00"/>
+    <item android:offset="0.2" android:color="#2f0f"/>
+    <item android:offset="0.9" android:color="#f00f"/>
+</gradient>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_1_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_1_golden.png
new file mode 100644
index 0000000..638802f
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_1_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_2_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_2_golden.png
new file mode 100644
index 0000000..1f248e3
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_2_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_3_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_3_golden.png
new file mode 100644
index 0000000..085e72a
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_gradient_3_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable/vector_icon_gradient_1.xml b/tests/tests/graphics/res/drawable/vector_icon_gradient_1.xml
new file mode 100644
index 0000000..d67aca7
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_gradient_1.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="400"
+        android:viewportWidth="400" >
+
+<group android:name="backgroundGroup"
+       android:scaleX="0.5"
+       android:scaleY="0.5">
+    <path
+            android:name="background1"
+            android:fillColor="@color/fill_gradient_linear"
+            android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+    <path
+            android:name="background2"
+            android:fillColor="@color/fill_gradient_radial"
+            android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+    <path
+            android:name="background3"
+            android:fillColor="@color/fill_gradient_sweep"
+            android:pathData="M 400,400 l 200,0 l 0, 200 l -200, 0 z" />
+</group>
+<group
+        android:name="translateToCenterGroup"
+        android:translateX="50.0"
+        android:translateY="90.0" >
+    <path
+            android:name="twoLines"
+            android:pathData="@string/twoLinePathData"
+            android:strokeColor="@color/stroke_gradient"
+            android:strokeWidth="20" />
+
+    <group
+            android:name="rotationGroup"
+            android:pivotX="0.0"
+            android:pivotY="0.0"
+            android:rotation="-45.0">
+        <path
+                android:name="twoLines1"
+                android:pathData="@string/twoLinePathData"
+                android:strokeColor="@color/stroke_gradient"
+                android:strokeWidth="20" />
+
+        <group
+                android:name="translateGroup"
+                android:translateX="130.0"
+                android:translateY="160.0">
+            <group android:name="scaleGroup" >
+                <path
+                        android:name="twoLines3"
+                        android:pathData="@string/twoLinePathData"
+                        android:strokeColor="@color/stroke_gradient"
+                        android:strokeWidth="20" />
+            </group>
+        </group>
+
+        <group
+                android:name="translateGroupHalf"
+                android:translateX="65.0"
+                android:translateY="80.0">
+            <group android:name="scaleGroup" >
+                <path
+                        android:name="twoLines2"
+                        android:pathData="@string/twoLinePathData"
+                        android:fillColor="@color/fill_gradient_linear"
+                        android:strokeColor="@color/stroke_gradient"
+                        android:strokeWidth="20" />
+            </group>
+        </group>
+    </group>
+</group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_gradient_2.xml b/tests/tests/graphics/res/drawable/vector_icon_gradient_2.xml
new file mode 100644
index 0000000..abf3c7a
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_gradient_2.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="400"
+        android:viewportWidth="400" >
+
+<group android:name="backgroundGroup"
+       android:scaleX="0.5"
+       android:scaleY="0.5">
+    <path
+            android:name="background1"
+            android:fillColor="@color/fill_gradient_linear_item"
+            android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+    <path
+            android:name="background2"
+            android:fillColor="@color/fill_gradient_radial_item"
+            android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+    <path
+            android:name="background3"
+            android:fillColor="@color/fill_gradient_sweep_item"
+            android:pathData="M 400,400 l 200,0 l 0, 200 l -200, 0 z" />
+</group>
+<group
+        android:name="translateToCenterGroup"
+        android:translateX="50.0"
+        android:translateY="90.0" >
+    <path
+            android:name="twoLines"
+            android:pathData="@string/twoLinePathData"
+            android:strokeColor="@color/stroke_gradient_item"
+            android:strokeWidth="20" />
+
+    <group
+            android:name="rotationGroup"
+            android:pivotX="0.0"
+            android:pivotY="0.0"
+            android:rotation="-45.0">
+        <path
+                android:name="twoLines1"
+                android:pathData="@string/twoLinePathData"
+                android:strokeColor="@color/stroke_gradient_item"
+                android:strokeWidth="20" />
+
+        <group
+                android:name="translateGroup"
+                android:translateX="130.0"
+                android:translateY="160.0">
+            <group android:name="scaleGroup" >
+                <path
+                        android:name="twoLines3"
+                        android:pathData="@string/twoLinePathData"
+                        android:strokeColor="@color/stroke_gradient_item"
+                        android:strokeWidth="20" />
+            </group>
+        </group>
+
+        <group
+                android:name="translateGroupHalf"
+                android:translateX="65.0"
+                android:translateY="80.0">
+            <group android:name="scaleGroup" >
+                <path
+                        android:name="twoLines2"
+                        android:pathData="@string/twoLinePathData"
+                        android:strokeColor="@color/stroke_gradient_item"
+                        android:strokeWidth="20" />
+            </group>
+        </group>
+    </group>
+</group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_gradient_3.xml b/tests/tests/graphics/res/drawable/vector_icon_gradient_3.xml
new file mode 100644
index 0000000..5f9726f
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_gradient_3.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="400"
+        android:viewportWidth="400" >
+
+<group android:name="backgroundGroup"
+       android:scaleX="0.5"
+       android:scaleY="0.5">
+    <path
+            android:name="background1"
+            android:fillColor="@color/fill_gradient_linear_item_overlap"
+            android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+    <path
+            android:name="background2"
+            android:fillColor="@color/fill_gradient_radial_item_short"
+            android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+    <path
+            android:name="background3"
+            android:fillColor="@color/fill_gradient_sweep_item_long"
+            android:pathData="M 400,400 l 200,0 l 0, 200 l -200, 0 z" />
+</group>
+<group
+        android:name="translateToCenterGroup"
+        android:translateX="50.0"
+        android:translateY="90.0" >
+    <path
+            android:name="twoLines"
+            android:pathData="@string/twoLinePathData"
+            android:strokeColor="@color/stroke_gradient_item_alpha"
+            android:strokeWidth="20" />
+
+    <group
+            android:name="rotationGroup"
+            android:pivotX="0.0"
+            android:pivotY="0.0"
+            android:rotation="-45.0">
+        <path
+                android:name="twoLines1"
+                android:pathData="@string/twoLinePathData"
+                android:strokeColor="@color/stroke_gradient_item_alpha"
+                android:strokeWidth="20" />
+
+        <group
+                android:name="translateGroup"
+                android:translateX="130.0"
+                android:translateY="160.0">
+            <group android:name="scaleGroup" >
+                <path
+                        android:name="twoLines3"
+                        android:pathData="@string/twoLinePathData"
+                        android:strokeColor="@color/stroke_gradient_item_alpha"
+                        android:strokeWidth="20" />
+            </group>
+        </group>
+
+        <group
+                android:name="translateGroupHalf"
+                android:translateX="65.0"
+                android:translateY="80.0">
+            <group android:name="scaleGroup" >
+                <path
+                        android:name="twoLines2"
+                        android:pathData="@string/twoLinePathData"
+                        android:strokeColor="@color/stroke_gradient_item_alpha"
+                        android:strokeWidth="20" />
+            </group>
+        </group>
+    </group>
+</group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/values/strings.xml b/tests/tests/graphics/res/values/strings.xml
index c167278..8208b19 100644
--- a/tests/tests/graphics/res/values/strings.xml
+++ b/tests/tests/graphics/res/values/strings.xml
@@ -176,4 +176,5 @@
 text, I would love to see the kind of devices you guys now use! Guys, maybe some devices need longer string!
 I think so, so how about double this string, like copy and paste! </string>
     <string name="rectangle200">"M 0,0 l 200,0 l 0, 200 l -200, 0 z"</string>
+    <string name="twoLinePathData">"M 0,0 v 100 M 0,0 h 100"</string>
 </resources>
diff --git a/tests/tests/graphics/src/android/graphics/cts/VulkanReservedTest.java b/tests/tests/graphics/src/android/graphics/cts/VulkanReservedTest.java
deleted file mode 100644
index bfd520e..0000000
--- a/tests/tests/graphics/src/android/graphics/cts/VulkanReservedTest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.graphics.cts;
-
-import android.cts.util.FileUtils;
-
-import junit.framework.TestCase;
-
-import java.io.File;
-
-public class VulkanReservedTest extends TestCase {
-
-    /**
-     * Assert that file with given path does not exist.
-     */
-    private static void assertNoFile(String filename) {
-        assertFalse(filename + " must not exist", new File(filename).exists());
-    }
-
-    /**
-     * Test that no vendor ships libvulkan.so before ratification and
-     * appropriate CTS coverage.
-     */
-    public void testNoVulkan() {
-        assertNoFile("/system/lib/libvulkan.so");
-        assertNoFile("/system/lib64/libvulkan.so");
-        assertNoFile("/vendor/lib/libvulkan.so");
-        assertNoFile("/vendor/lib64/libvulkan.so");
-    }
-}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java
index 8944d63..e5903d0 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java
@@ -103,6 +103,18 @@
             R.drawable.vector_icon_arcto_golden,
     };
 
+    private static final int[] GRADIENT_ICON_RES_IDS = new int[] {
+            R.drawable.vector_icon_gradient_1,
+            R.drawable.vector_icon_gradient_2,
+            R.drawable.vector_icon_gradient_3,
+    };
+
+    private static final int[] GRADIENT_GOLDEN_IMAGES = new int[] {
+            R.drawable.vector_icon_gradient_1_golden,
+            R.drawable.vector_icon_gradient_2_golden,
+            R.drawable.vector_icon_gradient_3_golden,
+    };
+
     private static final int[] STATEFUL_RES_IDS = new int[] {
             R.drawable.vector_icon_state_list
     };
@@ -151,6 +163,10 @@
         verifyVectorDrawables(ICON_RES_IDS, GOLDEN_IMAGES, null);
     }
 
+    public void testVectorDrawableGradient() throws XmlPullParserException, IOException {
+        verifyVectorDrawables(GRADIENT_ICON_RES_IDS, GRADIENT_GOLDEN_IMAGES, null);
+    }
+
     public void testColorStateList() throws XmlPullParserException, IOException {
         for (int i = 0; i < STATEFUL_STATE_SETS.length; i++) {
             verifyVectorDrawables(
@@ -175,7 +191,7 @@
                 throw new XmlPullParserException("No start tag found");
             }
 
-            mVectorDrawable.inflate(mResources, parser, attrs);
+            mVectorDrawable.inflate(mResources, parser, attrs, mContext.getTheme());
 
             if (stateSet != null) {
                 mVectorDrawable.setState(stateSet);
diff --git a/tests/tests/media/res/raw/image_exif_byte_order_ii.jpg b/tests/tests/media/res/raw/image_exif_byte_order_ii.jpg
new file mode 100644
index 0000000..477cd3a
--- /dev/null
+++ b/tests/tests/media/res/raw/image_exif_byte_order_ii.jpg
Binary files differ
diff --git a/tests/tests/media/res/raw/image_exif_byte_order_mm.jpg b/tests/tests/media/res/raw/image_exif_byte_order_mm.jpg
new file mode 100644
index 0000000..78ac703
--- /dev/null
+++ b/tests/tests/media/res/raw/image_exif_byte_order_mm.jpg
Binary files differ
diff --git a/tests/tests/media/res/raw/lg_g4_iso_800.dng b/tests/tests/media/res/raw/lg_g4_iso_800.dng
new file mode 100644
index 0000000..5fcc720
--- /dev/null
+++ b/tests/tests/media/res/raw/lg_g4_iso_800.dng
Binary files differ
diff --git a/tests/tests/media/res/raw/okgoogle123_good.wav b/tests/tests/media/res/raw/okgoogle123_good.wav
new file mode 100644
index 0000000..ffd5a7f
--- /dev/null
+++ b/tests/tests/media/res/raw/okgoogle123_good.wav
Binary files differ
diff --git a/tests/tests/media/res/values/exifinterface.xml b/tests/tests/media/res/values/exifinterface.xml
new file mode 100644
index 0000000..8fc6adc
--- /dev/null
+++ b/tests/tests/media/res/values/exifinterface.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <array name="exifbyteorderii_jpg">
+        <item>true</item>
+        <item>512</item>
+        <item>288</item>
+        <item>false</item>
+        <item>0.0</item>
+        <item>0.0</item>
+        <item>0.0</item>
+        <item>SAMSUNG</item>
+        <item>SM-N900S</item>
+        <item>2.200</item>
+        <item>2016:01:29 18:32:27</item>
+        <item>0.033</item>
+        <item>0</item>
+        <item>413/100</item>
+        <item />
+        <item />
+        <item />
+        <item />
+        <item />
+        <item />
+        <item />
+        <item />
+        <item />
+        <item>480</item>
+        <item>640</item>
+        <item>50</item>
+        <item>6</item>
+        <item>0</item>
+    </array>
+    <array name="exifbyteordermm_jpg">
+        <item>false</item>
+        <item>0</item>
+        <item>0</item>
+        <item>true</item>
+        <item>0.0</item>
+        <item>0.0</item>
+        <item>0.0</item>
+        <item>LGE</item>
+        <item>Nexus 5</item>
+        <item>2.400</item>
+        <item>2016:01:29 15:44:58</item>
+        <item>0.017</item>
+        <item>0</item>
+        <item>3970/1000</item>
+        <item>0/1000</item>
+        <item>0</item>
+        <item>1970:01:01</item>
+        <item>0/1,0/1,0/10000</item>
+        <item>N</item>
+        <item>0/1,0/1,0/10000</item>
+        <item>E</item>
+        <item>GPS</item>
+        <item>00:00:00</item>
+        <item>176</item>
+        <item>144</item>
+        <item>146</item>
+        <item>0</item>
+        <item>0</item>
+    </array>
+    <array name="lg_g4_iso_800_dng">
+        <item>false</item>
+        <item>0</item>
+        <item>0</item>
+        <item>true</item>
+        <item>53.834507</item>
+        <item>10.69585</item>
+        <item>0.0</item>
+        <item>LGE</item>
+        <item>LG-H815</item>
+        <item>1.800</item>
+        <item>2015:11:12 16:46:18</item>
+        <item>0.0040</item>
+        <item>0.0</item>
+        <item>442/100</item>
+        <item>0/1</item>
+        <item>0</item>
+        <item>1970:01:17</item>
+        <item>53/1,50/1,423/100</item>
+        <item>N</item>
+        <item>10/1,41/1,4506/100</item>
+        <item>E</item>
+        <item />
+        <item>18:08:10</item>
+        <item>337</item>
+        <item>600</item>
+        <item>800</item>
+        <item>1</item>
+        <item />
+    </array>
+</resources>
diff --git a/tests/tests/media/src/android/media/cts/EncoderTest.java b/tests/tests/media/src/android/media/cts/EncoderTest.java
index c8cea22..50ea672 100644
--- a/tests/tests/media/src/android/media/cts/EncoderTest.java
+++ b/tests/tests/media/src/android/media/cts/EncoderTest.java
@@ -23,9 +23,12 @@
 import android.media.MediaCodecInfo;
 import android.media.MediaCodecList;
 import android.media.MediaFormat;
+import android.media.MediaMuxer;
 import android.test.AndroidTestCase;
 import android.util.Log;
 
+import java.io.File;
+import java.io.InputStream;
 import java.nio.BufferOverflowException;
 import java.nio.ByteBuffer;
 import java.util.LinkedList;
@@ -42,6 +45,20 @@
     private static final int kNumInputBytes = 512 * 1024;
     private static final long kTimeoutUs = 100;
 
+    // not all combinations are valid
+    private static final int MODE_SILENT = 0;
+    private static final int MODE_RANDOM = 1;
+    private static final int MODE_RESOURCE = 2;
+    private static final int MODE_QUIET = 4;
+    private static final int MODE_SILENTLEAD = 8;
+
+    /*
+     * Set this to true to save the encoding results to /data/local/tmp
+     * You will need to make /data/local/tmp writeable, run "setenforce 0",
+     * and remove files left from a previous run.
+     */
+    private static boolean sSaveResults = false;
+
     @Override
     public void setContext(Context context) {
         super.setContext(context);
@@ -172,13 +189,26 @@
 
     private int queueInputBuffer(
             MediaCodec codec, ByteBuffer[] inputBuffers, int index,
-            boolean random, boolean zeroLead) {
+            InputStream istream, int mode) {
         ByteBuffer buffer = inputBuffers[index];
         buffer.rewind();
         int size = buffer.limit();
 
-        if (random) {
-            if (zeroLead) {
+        if ((mode & MODE_RESOURCE) != 0 && istream != null) {
+            while (buffer.hasRemaining()) {
+                try {
+                    int next = istream.read();
+                    if (next < 0) {
+                        break;
+                    }
+                    buffer.put((byte) next);
+                } catch (Exception ex) {
+                    Log.i(TAG, "caught exception writing: " + ex);
+                    break;
+                }
+            }
+        } else if ((mode & MODE_RANDOM) != 0) {
+            if ((mode & MODE_SILENTLEAD) != 0) {
                 buffer.putInt(0);
                 buffer.putInt(0);
                 buffer.putInt(0);
@@ -186,6 +216,7 @@
             }
             while (true) {
                 try {
+                    int next = mRandom.nextInt();
                     buffer.putInt(mRandom.nextInt());
                 } catch (BufferOverflowException ex) {
                     break;
@@ -196,6 +227,15 @@
             buffer.put(zeroes);
         }
 
+        if ((mode & MODE_QUIET) != 0) {
+            int n = buffer.limit();
+            for (int i = 0; i < n; i += 2) {
+                short s = buffer.getShort(i);
+                s /= 8;
+                buffer.putShort(i, s);
+            }
+        }
+
         codec.queueInputBuffer(index, 0 /* offset */, size, 0 /* timeUs */, 0);
 
         return size;
@@ -224,17 +264,47 @@
     private void testEncoder(String componentName, MediaFormat format) {
         Log.i(TAG, "testEncoder " + componentName + "/" + format);
         // test with all zeroes/silence
-        testEncoder(componentName, format, false, 0, false);
+        testEncoder(componentName, format, 0, -1, MODE_SILENT);
+
+        // test with pcm input file
+        testEncoder(componentName, format, 0, R.raw.okgoogle123_good, MODE_RESOURCE);
+        testEncoder(componentName, format, 0, R.raw.okgoogle123_good, MODE_RESOURCE | MODE_QUIET);
 
         // test with random data, with and without a few leading zeroes
         for (int i = 0; i < mBadSeeds.length; i++) {
-            testEncoder(componentName, format, true, mBadSeeds[i], false);
-            testEncoder(componentName, format, true, mBadSeeds[i], true);
+            testEncoder(componentName, format, mBadSeeds[i], -1, MODE_RANDOM);
+            testEncoder(componentName, format, mBadSeeds[i], -1, MODE_RANDOM | MODE_SILENTLEAD);
         }
     }
 
-    private void testEncoder(String componentName, MediaFormat format, boolean random,
-            long startSeed, boolean zeroLead) {
+    private void testEncoder(String componentName, MediaFormat format,
+            long startSeed, int resid, int mode) {
+
+        int sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
+        int channelCount = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
+        int inBitrate = sampleRate * channelCount * 16;  // bit/sec
+        int outBitrate = format.getInteger(MediaFormat.KEY_BIT_RATE);
+
+        MediaMuxer muxer = null;
+        int muxidx = -1;
+        if (sSaveResults) {
+            try {
+                String outFile = "/data/local/tmp/transcoded-" + componentName + "-" + outBitrate +
+                        "-" + mode + "-" + startSeed + ".mp4";
+                new File("outFile").delete();
+                muxer = new MediaMuxer(outFile, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
+                muxidx = muxer.addTrack(format);
+                muxer.start();
+            } catch (Exception e) {
+                Log.i(TAG, "couldn't create muxer: " + e);
+            }
+        }
+
+        InputStream istream = null;
+        if ((mode & MODE_RESOURCE) != 0) {
+            istream = mContext.getResources().openRawResource(resid);
+        }
+
         mRandom.setSeed(startSeed);
         MediaCodec codec;
         try {
@@ -283,7 +353,7 @@
                         doneSubmittingInput = true;
                     } else {
                         int size = queueInputBuffer(
-                                codec, codecInputBuffers, index, random, zeroLead);
+                                codec, codecInputBuffers, index, istream, mode);
 
                         numBytesSubmitted += size;
 
@@ -302,6 +372,10 @@
             } else if (index == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
                 codecOutputBuffers = codec.getOutputBuffers();
             } else {
+                if (muxer != null) {
+                    muxer.writeSampleData(muxidx, codec.getOutputBuffer(index), info);
+                }
+
                 dequeueOutputBuffer(codec, codecOutputBuffers, index, info);
 
                 numBytesDequeued += info.size;
@@ -324,11 +398,6 @@
                     + "dequeued " + numBytesDequeued + " bytes.");
         }
 
-        int sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
-        int channelCount = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
-        int inBitrate = sampleRate * channelCount * 16;  // bit/sec
-        int outBitrate = format.getInteger(MediaFormat.KEY_BIT_RATE);
-
         float desiredRatio = (float)outBitrate / (float)inBitrate;
         float actualRatio = (float)numBytesDequeued / (float)numBytesSubmitted;
 
@@ -339,6 +408,11 @@
 
         codec.release();
         codec = null;
+        if (muxer != null) {
+            muxer.stop();
+            muxer.release();
+            muxer = null;
+        }
     }
 }
 
diff --git a/tests/tests/media/src/android/media/cts/ExifInterfaceTest.java b/tests/tests/media/src/android/media/cts/ExifInterfaceTest.java
new file mode 100644
index 0000000..a51dd3d
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/ExifInterfaceTest.java
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.cts;
+
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.media.ExifInterface;
+import android.os.Environment;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.lang.reflect.Type;
+
+public class ExifInterfaceTest extends AndroidTestCase {
+    private static final String TAG = ExifInterface.class.getSimpleName();
+    private static final boolean VERBOSE = false;  // lots of logging
+
+    private static final double DIFFERENCE_TOLERANCE = .0001;
+    private static final int BUFFER_SIZE = 32768;
+
+    // List of files.
+    private static final String EXIF_BYTE_ORDER_II_JPEG = "ExifByteOrderII.jpg";
+    private static final String EXIF_BYTE_ORDER_MM_JPEG = "ExifByteOrderMM.jpg";
+    private static final String LG_G4_ISO_800_DNG = "lg_g4_iso_800.dng";
+    private static final int[] IMAGE_RESOURCES = new int[] {
+            R.raw.image_exif_byte_order_ii,  R.raw.image_exif_byte_order_mm, R.raw.lg_g4_iso_800 };
+    private static final String[] IMAGE_FILENAMES = new String[] {
+            EXIF_BYTE_ORDER_II_JPEG, EXIF_BYTE_ORDER_MM_JPEG, LG_G4_ISO_800_DNG };
+
+    private static final String[] EXIF_TAGS = {
+            ExifInterface.TAG_MAKE,
+            ExifInterface.TAG_MODEL,
+            ExifInterface.TAG_APERTURE,
+            ExifInterface.TAG_DATETIME,
+            ExifInterface.TAG_EXPOSURE_TIME,
+            ExifInterface.TAG_FLASH,
+            ExifInterface.TAG_FOCAL_LENGTH,
+            ExifInterface.TAG_GPS_ALTITUDE,
+            ExifInterface.TAG_GPS_ALTITUDE_REF,
+            ExifInterface.TAG_GPS_DATESTAMP,
+            ExifInterface.TAG_GPS_LATITUDE,
+            ExifInterface.TAG_GPS_LATITUDE_REF,
+            ExifInterface.TAG_GPS_LONGITUDE,
+            ExifInterface.TAG_GPS_LONGITUDE_REF,
+            ExifInterface.TAG_GPS_PROCESSING_METHOD,
+            ExifInterface.TAG_GPS_TIMESTAMP,
+            ExifInterface.TAG_IMAGE_LENGTH,
+            ExifInterface.TAG_IMAGE_WIDTH,
+            ExifInterface.TAG_ISO,
+            ExifInterface.TAG_ORIENTATION,
+            ExifInterface.TAG_WHITE_BALANCE
+    };
+
+    private static class ExpectedValue {
+        // Thumbnail information.
+        public final boolean hasThumbnail;
+        public final int thumbnailWidth;
+        public final int thumbnailHeight;
+
+        // GPS information.
+        public final boolean hasLatLong;
+        public final float latitude;
+        public final float longitude;
+        public final float altitude;
+
+        // Values.
+        public final String make;
+        public final String model;
+        public final float aperture;
+        public final String datetime;
+        public final float exposureTime;
+        public final float flash;
+        public final String focalLength;
+        public final String gpsAltitude;
+        public final String gpsAltitudeRef;
+        public final String gpsDatestamp;
+        public final String gpsLatitude;
+        public final String gpsLatitudeRef;
+        public final String gpsLongitude;
+        public final String gpsLongitudeRef;
+        public final String gpsProcessingMethod;
+        public final String gpsTimestamp;
+        public final String imageLength;
+        public final String imageWidth;
+        public final String iso;
+        public final String whiteBalance;
+        public final String orientation;
+
+        private static String getString(TypedArray typedArray, int index) {
+            String stringValue = typedArray.getString(index);
+            if (stringValue == null || stringValue.equals("")) {
+                return null;
+            }
+            return stringValue.trim();
+        }
+
+        public ExpectedValue(TypedArray typedArray) {
+            // Reads thumbnail information.
+            hasThumbnail = typedArray.getBoolean(0, false);
+            thumbnailWidth = typedArray.getInt(1, 0);
+            thumbnailHeight = typedArray.getInt(2, 0);
+
+            // Reads GPS information.
+            hasLatLong = typedArray.getBoolean(3, false);
+            latitude = typedArray.getFloat(4, 0f);
+            longitude = typedArray.getFloat(5, 0f);
+            altitude = typedArray.getFloat(6, 0f);
+
+            // Read values.
+            make = getString(typedArray, 7);
+            model = getString(typedArray, 8);
+            aperture = typedArray.getFloat(9, 0f);
+            datetime = getString(typedArray, 10);
+            exposureTime = typedArray.getFloat(11, 0f);
+            flash = typedArray.getFloat(12, 0f);
+            focalLength = getString(typedArray, 13);
+            gpsAltitude = getString(typedArray, 14);
+            gpsAltitudeRef = getString(typedArray, 15);
+            gpsDatestamp = getString(typedArray, 16);
+            gpsLatitude = getString(typedArray, 17);
+            gpsLatitudeRef = getString(typedArray, 18);
+            gpsLongitude = getString(typedArray, 19);
+            gpsLongitudeRef = getString(typedArray, 20);
+            gpsProcessingMethod = getString(typedArray, 21);
+            gpsTimestamp = getString(typedArray, 22);
+            imageLength = getString(typedArray, 23);
+            imageWidth = getString(typedArray, 24);
+            iso = getString(typedArray, 25);
+            orientation = getString(typedArray, 26);
+            whiteBalance = getString(typedArray, 27);
+
+            typedArray.recycle();
+        }
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        byte[] buffer = new byte[BUFFER_SIZE];
+
+        for (int i = 0; i < IMAGE_RESOURCES.length; ++i) {
+            String outputPath = new File(Environment.getExternalStorageDirectory(),
+                    IMAGE_FILENAMES[i]).getAbsolutePath();
+            try (InputStream inputStream = getContext().getResources().openRawResource(
+                    IMAGE_RESOURCES[i])) {
+                try (FileOutputStream outputStream = new FileOutputStream(outputPath)) {
+                    int amount;
+                    while ((amount = inputStream.read(buffer)) > 0) {
+                        outputStream.write(buffer, 0, amount);
+                    }
+                }
+            }
+        }
+        super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        for (int i = 0; i < IMAGE_RESOURCES.length; ++i) {
+            String imageFilePath = new File(Environment.getExternalStorageDirectory(),
+                    IMAGE_FILENAMES[i]).getAbsolutePath();
+            File imageFile = new File(imageFilePath);
+            if (imageFile.exists()) {
+                imageFile.delete();
+            }
+        }
+
+        super.tearDown();
+    }
+
+    private void printExifTagsAndValues(String fileName, ExifInterface exifInterface) {
+        // Prints thumbnail information.
+        if (exifInterface.hasThumbnail()) {
+            byte[] thumbnailBytes = exifInterface.getThumbnail();
+            if (thumbnailBytes != null) {
+                Log.v(TAG, fileName + " Thumbnail size = " + thumbnailBytes.length);
+                Bitmap bitmap = BitmapFactory.decodeByteArray(
+                        thumbnailBytes, 0, thumbnailBytes.length);
+                if (bitmap == null) {
+                    Log.e(TAG, fileName + " Corrupted thumbnail!");
+                } else {
+                    Log.v(TAG, fileName + " Thumbnail size: " + bitmap.getWidth() + ", "
+                            + bitmap.getHeight());
+                }
+            } else {
+                Log.e(TAG, fileName + " Corrupted image (no thumbnail)");
+            }
+        } else {
+            if (exifInterface.getThumbnail() != null) {
+                Log.e(TAG, fileName + " Corrupted image (a thumbnail exists)");
+            } else {
+                Log.v(TAG, fileName + " No thumbnail");
+            }
+        }
+
+        // Prints GPS information.
+        Log.v(TAG, fileName + " Altitude = " + exifInterface.getAltitude(.0));
+
+        float[] latLong = new float[2];
+        if (exifInterface.getLatLong(latLong)) {
+            Log.v(TAG, fileName + " Latitude = " + latLong[0]);
+            Log.v(TAG, fileName + " Longitude = " + latLong[1]);
+        } else {
+            Log.v(TAG, fileName + "No latlong data");
+        }
+
+        // Prints values.
+        for (String tagKey : EXIF_TAGS) {
+            String tagValue = exifInterface.getAttribute(tagKey);
+            Log.v(TAG, fileName + "Key{" + tagKey + "} = '" + tagValue + "'");
+        }
+    }
+
+    private void compareFloatTag(ExifInterface exifInterface, String tag, float expectedValue) {
+        String stringValue = exifInterface.getAttribute(tag);
+        float floatValue = 0f;
+
+        if (stringValue != null) {
+            floatValue = Float.parseFloat(stringValue);
+        }
+
+        assertEquals(expectedValue, floatValue, DIFFERENCE_TOLERANCE);
+    }
+
+    private void compareStringTag(ExifInterface exifInterface, String tag, String expectedValue) {
+        String stringValue = exifInterface.getAttribute(tag);
+        if (stringValue != null) {
+            stringValue = stringValue.trim();
+        }
+
+        assertEquals(expectedValue, stringValue);
+    }
+
+    private void compareWithExpectedValue(ExifInterface exifInterface,
+            ExpectedValue expectedValue) {
+        // Checks a thumbnail image.
+        assertEquals(expectedValue.hasThumbnail, exifInterface.hasThumbnail());
+        if (expectedValue.hasThumbnail) {
+            byte[] thumbnailBytes = exifInterface.getThumbnail();
+            assertNotNull(thumbnailBytes);
+            Bitmap thumbnailBitmap =
+                    BitmapFactory.decodeByteArray(thumbnailBytes, 0, thumbnailBytes.length);
+            assertNotNull(thumbnailBitmap);
+            assertEquals(expectedValue.thumbnailWidth, thumbnailBitmap.getWidth());
+            assertEquals(expectedValue.thumbnailHeight, thumbnailBitmap.getHeight());
+        } else {
+            assertNull(exifInterface.getThumbnail());
+        }
+
+        // Checks GPS information.
+        float[] latLong = new float[2];
+        assertEquals(expectedValue.hasLatLong, exifInterface.getLatLong(latLong));
+        if (expectedValue.hasLatLong) {
+            assertEquals(expectedValue.latitude, latLong[0], DIFFERENCE_TOLERANCE);
+            assertEquals(expectedValue.longitude, latLong[1], DIFFERENCE_TOLERANCE);
+        }
+        assertEquals(expectedValue.altitude, exifInterface.getAltitude(.0), DIFFERENCE_TOLERANCE);
+
+        // Checks values.
+        compareStringTag(exifInterface, ExifInterface.TAG_MAKE, expectedValue.make);
+        compareStringTag(exifInterface, ExifInterface.TAG_MODEL, expectedValue.model);
+        compareFloatTag(exifInterface, ExifInterface.TAG_APERTURE, expectedValue.aperture);
+        compareStringTag(exifInterface, ExifInterface.TAG_DATETIME, expectedValue.datetime);
+        compareFloatTag(exifInterface, ExifInterface.TAG_EXPOSURE_TIME, expectedValue.exposureTime);
+        compareFloatTag(exifInterface, ExifInterface.TAG_FLASH, expectedValue.flash);
+        compareStringTag(exifInterface, ExifInterface.TAG_FOCAL_LENGTH, expectedValue.focalLength);
+        compareStringTag(exifInterface, ExifInterface.TAG_GPS_ALTITUDE, expectedValue.gpsAltitude);
+        compareStringTag(exifInterface, ExifInterface.TAG_GPS_ALTITUDE_REF,
+                expectedValue.gpsAltitudeRef);
+        compareStringTag(exifInterface, ExifInterface.TAG_GPS_DATESTAMP,
+                expectedValue.gpsDatestamp);
+        compareStringTag(exifInterface, ExifInterface.TAG_GPS_LATITUDE, expectedValue.gpsLatitude);
+        compareStringTag(exifInterface, ExifInterface.TAG_GPS_LATITUDE_REF,
+                expectedValue.gpsLatitudeRef);
+        compareStringTag(exifInterface, ExifInterface.TAG_GPS_LONGITUDE,
+                expectedValue.gpsLongitude);
+        compareStringTag(exifInterface, ExifInterface.TAG_GPS_LONGITUDE_REF,
+                expectedValue.gpsLongitudeRef);
+        compareStringTag(exifInterface, ExifInterface.TAG_GPS_PROCESSING_METHOD,
+                expectedValue.gpsProcessingMethod);
+        compareStringTag(exifInterface, ExifInterface.TAG_GPS_TIMESTAMP,
+                expectedValue.gpsTimestamp);
+        compareStringTag(exifInterface, ExifInterface.TAG_IMAGE_LENGTH, expectedValue.imageLength);
+        compareStringTag(exifInterface, ExifInterface.TAG_IMAGE_WIDTH, expectedValue.imageWidth);
+        compareStringTag(exifInterface, ExifInterface.TAG_ISO, expectedValue.iso);
+        compareStringTag(exifInterface, ExifInterface.TAG_ORIENTATION, expectedValue.orientation);
+        compareStringTag(exifInterface, ExifInterface.TAG_WHITE_BALANCE,
+                expectedValue.whiteBalance);
+    }
+
+    private void testExifInterface(String fileName, int typedArrayResourceId) throws IOException {
+        ExifInterface exifInterface = new ExifInterface(new File(Environment
+                .getExternalStorageDirectory(), fileName).getAbsolutePath());
+
+        assertNotNull(exifInterface);
+        if (VERBOSE) {
+            printExifTagsAndValues(fileName, exifInterface);
+        }
+
+        compareWithExpectedValue(exifInterface, new ExpectedValue(
+                getContext().getResources().obtainTypedArray(typedArrayResourceId)));
+    }
+
+    public void testReadExifDataFromExifByteOrderIIJpeg() throws Throwable {
+        testExifInterface(EXIF_BYTE_ORDER_II_JPEG, R.array.exifbyteorderii_jpg);
+    }
+
+    public void testReadExifDataFromExifByteOrderMMJpeg() throws Throwable {
+        testExifInterface(EXIF_BYTE_ORDER_MM_JPEG, R.array.exifbyteordermm_jpg);
+    }
+
+    public void testReadExifDataFromLgG4Iso800Dng() throws Throwable {
+        testExifInterface(LG_G4_ISO_800_DNG, R.array.lg_g4_iso_800_dng);
+    }
+}
diff --git a/tests/tests/net/src/android/net/wifi/cts/ConcurrencyTest.java b/tests/tests/net/src/android/net/wifi/cts/ConcurrencyTest.java
index 343c1e6..a066ba8 100644
--- a/tests/tests/net/src/android/net/wifi/cts/ConcurrencyTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/ConcurrencyTest.java
@@ -20,12 +20,20 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
 import android.net.wifi.WifiManager;
 import android.net.wifi.p2p.WifiP2pManager;
 import static android.net.wifi.p2p.WifiP2pManager.WIFI_P2P_STATE_DISABLED;
 import static android.net.wifi.p2p.WifiP2pManager.WIFI_P2P_STATE_ENABLED;
 import android.test.AndroidTestCase;
 
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
 public class ConcurrencyTest extends AndroidTestCase {
     private class MySync {
         int expectedWifiState;
@@ -94,10 +102,7 @@
         }
         mContext.unregisterReceiver(mReceiver);
 
-        if (!mWifiManager.isWifiEnabled()) {
-            assertTrue(mWifiManager.setWifiEnabled(true));
-            Thread.sleep(DURATION);
-        }
+        enableWifi();
         super.tearDown();
     }
 
@@ -114,6 +119,33 @@
         }
     }
 
+    /*
+     * Enables Wifi and block until connection is established.
+     */
+    private void enableWifi() throws InterruptedException {
+        if (!mWifiManager.isWifiEnabled()) {
+            assertTrue(mWifiManager.setWifiEnabled(true));
+        }
+
+        ConnectivityManager cm =
+            (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
+        NetworkRequest request =
+            new NetworkRequest.Builder().addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+                                        .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+                                        .build();
+        final CountDownLatch latch = new CountDownLatch(1);
+        NetworkCallback networkCallback = new NetworkCallback() {
+            @Override
+            public void onAvailable(Network network) {
+                latch.countDown();
+            }
+        };
+        cm.registerNetworkCallback(request, networkCallback);
+        latch.await(DURATION, TimeUnit.MILLISECONDS);
+
+        cm.unregisterNetworkCallback(networkCallback);
+    }
+
     public void testConcurrency() {
         // Cannot support p2p alone
         if (!WifiFeature.isWifiSupported(getContext())) {
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiEnterpriseConfigTest.java b/tests/tests/net/src/android/net/wifi/cts/WifiEnterpriseConfigTest.java
index 2cc5951..f3eb4e9 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiEnterpriseConfigTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiEnterpriseConfigTest.java
@@ -25,6 +25,10 @@
 import android.net.wifi.WifiManager;
 import android.test.AndroidTestCase;
 
+import java.io.ByteArrayInputStream;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+
 public class WifiEnterpriseConfigTest extends AndroidTestCase {
     private  WifiManager mWifiManager;
 
@@ -39,6 +43,396 @@
     private static final String ANON_IDENTITY = "anonidentity";
     private static final int ENABLE_DELAY = 10000;
 
+    /*
+     * The keys and certificates below are generated with:
+     *
+     * openssl req -new -x509 -days 3650 -extensions v3_ca -keyout cakey.pem -out cacert.pem
+     * openssl ecparam -name prime256v1 -out ecparam.pem
+     * openssl req -newkey ec:ecparam.pem -keyout userkey.pem -nodes -days 3650 -out userkey.req
+     * mkdir -p demoCA/newcerts
+     * touch demoCA/index.txt
+     * echo "01" > demoCA/serial
+     * openssl ca -out usercert.pem -in userkey.req -cert cacert.pem -keyfile cakey.pem -days 3650
+     */
+
+    /**
+     * Generated from above and converted with:
+     *
+     * openssl x509 -outform d -in cacert.pem | xxd -i | sed 's/0x/(byte) 0x/g'
+     */
+
+    private static final byte[] FAKE_EC_1 = {
+        (byte) 0x30, (byte) 0x82, (byte) 0x04, (byte) 0x2f, (byte) 0x30, (byte) 0x82,
+        (byte) 0x03, (byte) 0x17, (byte) 0xa0, (byte) 0x03, (byte) 0x02, (byte) 0x01,
+        (byte) 0x02, (byte) 0x02, (byte) 0x09, (byte) 0x00, (byte) 0xa7, (byte) 0xe4,
+        (byte) 0x70, (byte) 0x50, (byte) 0x9b, (byte) 0xd2, (byte) 0x68, (byte) 0x68,
+        (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86,
+        (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01,
+        (byte) 0x0b, (byte) 0x05, (byte) 0x00, (byte) 0x30, (byte) 0x81, (byte) 0xad,
+        (byte) 0x31, (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03,
+        (byte) 0x55, (byte) 0x04, (byte) 0x06, (byte) 0x13, (byte) 0x02, (byte) 0x41,
+        (byte) 0x55, (byte) 0x31, (byte) 0x13, (byte) 0x30, (byte) 0x11, (byte) 0x06,
+        (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x08, (byte) 0x0c, (byte) 0x0a,
+        (byte) 0x53, (byte) 0x6f, (byte) 0x6d, (byte) 0x65, (byte) 0x2d, (byte) 0x53,
+        (byte) 0x74, (byte) 0x61, (byte) 0x74, (byte) 0x65, (byte) 0x31, (byte) 0x12,
+        (byte) 0x30, (byte) 0x10, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+        (byte) 0x07, (byte) 0x0c, (byte) 0x09, (byte) 0x53, (byte) 0x6f, (byte) 0x6d,
+        (byte) 0x65, (byte) 0x2d, (byte) 0x43, (byte) 0x69, (byte) 0x74, (byte) 0x79,
+        (byte) 0x31, (byte) 0x15, (byte) 0x30, (byte) 0x13, (byte) 0x06, (byte) 0x03,
+        (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x0c, (byte) 0x0c, (byte) 0x53,
+        (byte) 0x6f, (byte) 0x6d, (byte) 0x65, (byte) 0x2d, (byte) 0x43, (byte) 0x6f,
+        (byte) 0x6d, (byte) 0x70, (byte) 0x61, (byte) 0x6e, (byte) 0x79, (byte) 0x31,
+        (byte) 0x10, (byte) 0x30, (byte) 0x0e, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+        (byte) 0x04, (byte) 0x0b, (byte) 0x0c, (byte) 0x07, (byte) 0x53, (byte) 0x65,
+        (byte) 0x63, (byte) 0x74, (byte) 0x69, (byte) 0x6f, (byte) 0x6e, (byte) 0x31,
+        (byte) 0x21, (byte) 0x30, (byte) 0x1f, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+        (byte) 0x04, (byte) 0x03, (byte) 0x0c, (byte) 0x18, (byte) 0x57, (byte) 0x69,
+        (byte) 0x66, (byte) 0x69, (byte) 0x45, (byte) 0x6e, (byte) 0x74, (byte) 0x65,
+        (byte) 0x72, (byte) 0x70, (byte) 0x72, (byte) 0x69, (byte) 0x73, (byte) 0x65,
+        (byte) 0x43, (byte) 0x6f, (byte) 0x6e, (byte) 0x66, (byte) 0x69, (byte) 0x67,
+        (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x31, (byte) 0x29,
+        (byte) 0x30, (byte) 0x27, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86,
+        (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x09,
+        (byte) 0x01, (byte) 0x16, (byte) 0x1a, (byte) 0x61, (byte) 0x6e, (byte) 0x2d,
+        (byte) 0x65, (byte) 0x6d, (byte) 0x61, (byte) 0x69, (byte) 0x6c, (byte) 0x2d,
+        (byte) 0x61, (byte) 0x64, (byte) 0x72, (byte) 0x65, (byte) 0x73, (byte) 0x73,
+        (byte) 0x40, (byte) 0x64, (byte) 0x6f, (byte) 0x6d, (byte) 0x61, (byte) 0x69,
+        (byte) 0x6e, (byte) 0x2e, (byte) 0x63, (byte) 0x6f, (byte) 0x6d, (byte) 0x30,
+        (byte) 0x1e, (byte) 0x17, (byte) 0x0d, (byte) 0x31, (byte) 0x36, (byte) 0x30,
+        (byte) 0x31, (byte) 0x31, (byte) 0x35, (byte) 0x31, (byte) 0x31, (byte) 0x31,
+        (byte) 0x38, (byte) 0x35, (byte) 0x31, (byte) 0x5a, (byte) 0x17, (byte) 0x0d,
+        (byte) 0x32, (byte) 0x36, (byte) 0x30, (byte) 0x31, (byte) 0x31, (byte) 0x32,
+        (byte) 0x31, (byte) 0x31, (byte) 0x31, (byte) 0x38, (byte) 0x35, (byte) 0x31,
+        (byte) 0x5a, (byte) 0x30, (byte) 0x81, (byte) 0xad, (byte) 0x31, (byte) 0x0b,
+        (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+        (byte) 0x06, (byte) 0x13, (byte) 0x02, (byte) 0x41, (byte) 0x55, (byte) 0x31,
+        (byte) 0x13, (byte) 0x30, (byte) 0x11, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+        (byte) 0x04, (byte) 0x08, (byte) 0x0c, (byte) 0x0a, (byte) 0x53, (byte) 0x6f,
+        (byte) 0x6d, (byte) 0x65, (byte) 0x2d, (byte) 0x53, (byte) 0x74, (byte) 0x61,
+        (byte) 0x74, (byte) 0x65, (byte) 0x31, (byte) 0x12, (byte) 0x30, (byte) 0x10,
+        (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x07, (byte) 0x0c,
+        (byte) 0x09, (byte) 0x53, (byte) 0x6f, (byte) 0x6d, (byte) 0x65, (byte) 0x2d,
+        (byte) 0x43, (byte) 0x69, (byte) 0x74, (byte) 0x79, (byte) 0x31, (byte) 0x15,
+        (byte) 0x30, (byte) 0x13, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+        (byte) 0x0a, (byte) 0x0c, (byte) 0x0c, (byte) 0x53, (byte) 0x6f, (byte) 0x6d,
+        (byte) 0x65, (byte) 0x2d, (byte) 0x43, (byte) 0x6f, (byte) 0x6d, (byte) 0x70,
+        (byte) 0x61, (byte) 0x6e, (byte) 0x79, (byte) 0x31, (byte) 0x10, (byte) 0x30,
+        (byte) 0x0e, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x0b,
+        (byte) 0x0c, (byte) 0x07, (byte) 0x53, (byte) 0x65, (byte) 0x63, (byte) 0x74,
+        (byte) 0x69, (byte) 0x6f, (byte) 0x6e, (byte) 0x31, (byte) 0x21, (byte) 0x30,
+        (byte) 0x1f, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x03,
+        (byte) 0x0c, (byte) 0x18, (byte) 0x57, (byte) 0x69, (byte) 0x66, (byte) 0x69,
+        (byte) 0x45, (byte) 0x6e, (byte) 0x74, (byte) 0x65, (byte) 0x72, (byte) 0x70,
+        (byte) 0x72, (byte) 0x69, (byte) 0x73, (byte) 0x65, (byte) 0x43, (byte) 0x6f,
+        (byte) 0x6e, (byte) 0x66, (byte) 0x69, (byte) 0x67, (byte) 0x54, (byte) 0x65,
+        (byte) 0x73, (byte) 0x74, (byte) 0x31, (byte) 0x29, (byte) 0x30, (byte) 0x27,
+        (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86,
+        (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x09, (byte) 0x01, (byte) 0x16,
+        (byte) 0x1a, (byte) 0x61, (byte) 0x6e, (byte) 0x2d, (byte) 0x65, (byte) 0x6d,
+        (byte) 0x61, (byte) 0x69, (byte) 0x6c, (byte) 0x2d, (byte) 0x61, (byte) 0x64,
+        (byte) 0x72, (byte) 0x65, (byte) 0x73, (byte) 0x73, (byte) 0x40, (byte) 0x64,
+        (byte) 0x6f, (byte) 0x6d, (byte) 0x61, (byte) 0x69, (byte) 0x6e, (byte) 0x2e,
+        (byte) 0x63, (byte) 0x6f, (byte) 0x6d, (byte) 0x30, (byte) 0x82, (byte) 0x01,
+        (byte) 0x22, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a,
+        (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01,
+        (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x03, (byte) 0x82,
+        (byte) 0x01, (byte) 0x0f, (byte) 0x00, (byte) 0x30, (byte) 0x82, (byte) 0x01,
+        (byte) 0x0a, (byte) 0x02, (byte) 0x82, (byte) 0x01, (byte) 0x01, (byte) 0x00,
+        (byte) 0xb4, (byte) 0x6e, (byte) 0x66, (byte) 0x24, (byte) 0xe7, (byte) 0x5c,
+        (byte) 0xd8, (byte) 0x6f, (byte) 0x08, (byte) 0xd3, (byte) 0x80, (byte) 0xa3,
+        (byte) 0xb9, (byte) 0xaf, (byte) 0x90, (byte) 0xef, (byte) 0x1c, (byte) 0x2a,
+        (byte) 0x5f, (byte) 0x39, (byte) 0x0b, (byte) 0xbd, (byte) 0x75, (byte) 0x0d,
+        (byte) 0x3e, (byte) 0x19, (byte) 0x2e, (byte) 0x47, (byte) 0x1e, (byte) 0x14,
+        (byte) 0xc2, (byte) 0x1a, (byte) 0x59, (byte) 0xcc, (byte) 0x1b, (byte) 0xb6,
+        (byte) 0x9b, (byte) 0x46, (byte) 0x1f, (byte) 0x7f, (byte) 0x71, (byte) 0xdd,
+        (byte) 0x38, (byte) 0xbe, (byte) 0x89, (byte) 0x30, (byte) 0xba, (byte) 0x88,
+        (byte) 0xfb, (byte) 0x3f, (byte) 0x57, (byte) 0x35, (byte) 0xe7, (byte) 0xa7,
+        (byte) 0x2f, (byte) 0x2c, (byte) 0x8d, (byte) 0x7c, (byte) 0xe2, (byte) 0xd8,
+        (byte) 0x0c, (byte) 0x0a, (byte) 0xe6, (byte) 0x62, (byte) 0x46, (byte) 0x8c,
+        (byte) 0xf4, (byte) 0x51, (byte) 0xfc, (byte) 0x6a, (byte) 0x79, (byte) 0xdd,
+        (byte) 0x0a, (byte) 0x41, (byte) 0x23, (byte) 0xd3, (byte) 0xe9, (byte) 0x5e,
+        (byte) 0x91, (byte) 0xcd, (byte) 0xbd, (byte) 0x55, (byte) 0x28, (byte) 0x71,
+        (byte) 0xec, (byte) 0x52, (byte) 0x19, (byte) 0x85, (byte) 0x0c, (byte) 0x1b,
+        (byte) 0xfa, (byte) 0xbf, (byte) 0xfe, (byte) 0xae, (byte) 0x5c, (byte) 0x3b,
+        (byte) 0x99, (byte) 0x42, (byte) 0xd4, (byte) 0xe7, (byte) 0x17, (byte) 0xec,
+        (byte) 0x41, (byte) 0x22, (byte) 0x2c, (byte) 0x1e, (byte) 0x7b, (byte) 0x53,
+        (byte) 0xad, (byte) 0x02, (byte) 0xfd, (byte) 0xf6, (byte) 0x4a, (byte) 0xb1,
+        (byte) 0x6e, (byte) 0x6c, (byte) 0x87, (byte) 0xf5, (byte) 0x7d, (byte) 0x9b,
+        (byte) 0x34, (byte) 0x0e, (byte) 0x3b, (byte) 0x0e, (byte) 0xaa, (byte) 0xc5,
+        (byte) 0xc4, (byte) 0xef, (byte) 0xf2, (byte) 0x5a, (byte) 0xa9, (byte) 0xac,
+        (byte) 0x19, (byte) 0xce, (byte) 0x5f, (byte) 0xc5, (byte) 0xcc, (byte) 0x0d,
+        (byte) 0xee, (byte) 0x7f, (byte) 0x32, (byte) 0xb4, (byte) 0xfe, (byte) 0xc1,
+        (byte) 0xca, (byte) 0x9b, (byte) 0x3f, (byte) 0xad, (byte) 0x2c, (byte) 0x7a,
+        (byte) 0xc5, (byte) 0x8d, (byte) 0x48, (byte) 0xa1, (byte) 0xc9, (byte) 0x74,
+        (byte) 0xfe, (byte) 0x8a, (byte) 0xe3, (byte) 0xb0, (byte) 0x92, (byte) 0xee,
+        (byte) 0x73, (byte) 0x09, (byte) 0x0a, (byte) 0xbc, (byte) 0xc8, (byte) 0x63,
+        (byte) 0xba, (byte) 0x0e, (byte) 0x26, (byte) 0xab, (byte) 0x1e, (byte) 0xff,
+        (byte) 0xbc, (byte) 0x24, (byte) 0x12, (byte) 0x26, (byte) 0x11, (byte) 0xe0,
+        (byte) 0x04, (byte) 0xcb, (byte) 0x96, (byte) 0x7d, (byte) 0x41, (byte) 0xf7,
+        (byte) 0x79, (byte) 0x32, (byte) 0x05, (byte) 0x33, (byte) 0x19, (byte) 0x6e,
+        (byte) 0xb9, (byte) 0x75, (byte) 0xf3, (byte) 0x50, (byte) 0xa4, (byte) 0xc3,
+        (byte) 0x55, (byte) 0x9d, (byte) 0x8f, (byte) 0xb6, (byte) 0xab, (byte) 0x97,
+        (byte) 0xe7, (byte) 0xe2, (byte) 0xe8, (byte) 0x15, (byte) 0xfc, (byte) 0x35,
+        (byte) 0xbd, (byte) 0xce, (byte) 0x17, (byte) 0xbe, (byte) 0xe3, (byte) 0x73,
+        (byte) 0xd4, (byte) 0x88, (byte) 0x39, (byte) 0x27, (byte) 0x7e, (byte) 0x6d,
+        (byte) 0xa2, (byte) 0x27, (byte) 0xfa, (byte) 0x96, (byte) 0xe3, (byte) 0x38,
+        (byte) 0xc0, (byte) 0xa1, (byte) 0x55, (byte) 0xc6, (byte) 0xf3, (byte) 0x20,
+        (byte) 0xea, (byte) 0x50, (byte) 0x8d, (byte) 0x6c, (byte) 0x94, (byte) 0x9a,
+        (byte) 0x43, (byte) 0x74, (byte) 0xc0, (byte) 0xfa, (byte) 0xef, (byte) 0xe0,
+        (byte) 0xb1, (byte) 0x1c, (byte) 0x6d, (byte) 0x5e, (byte) 0x44, (byte) 0x08,
+        (byte) 0xef, (byte) 0xd5, (byte) 0x80, (byte) 0xad, (byte) 0x02, (byte) 0x03,
+        (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0xa3, (byte) 0x50, (byte) 0x30,
+        (byte) 0x4e, (byte) 0x30, (byte) 0x1d, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+        (byte) 0x1d, (byte) 0x0e, (byte) 0x04, (byte) 0x16, (byte) 0x04, (byte) 0x14,
+        (byte) 0xe9, (byte) 0xd0, (byte) 0x9e, (byte) 0x0e, (byte) 0x62, (byte) 0x31,
+        (byte) 0x02, (byte) 0x9a, (byte) 0x33, (byte) 0xd7, (byte) 0x4a, (byte) 0x93,
+        (byte) 0x0d, (byte) 0xf3, (byte) 0xd6, (byte) 0x74, (byte) 0xce, (byte) 0x69,
+        (byte) 0xe1, (byte) 0xef, (byte) 0x30, (byte) 0x1f, (byte) 0x06, (byte) 0x03,
+        (byte) 0x55, (byte) 0x1d, (byte) 0x23, (byte) 0x04, (byte) 0x18, (byte) 0x30,
+        (byte) 0x16, (byte) 0x80, (byte) 0x14, (byte) 0xe9, (byte) 0xd0, (byte) 0x9e,
+        (byte) 0x0e, (byte) 0x62, (byte) 0x31, (byte) 0x02, (byte) 0x9a, (byte) 0x33,
+        (byte) 0xd7, (byte) 0x4a, (byte) 0x93, (byte) 0x0d, (byte) 0xf3, (byte) 0xd6,
+        (byte) 0x74, (byte) 0xce, (byte) 0x69, (byte) 0xe1, (byte) 0xef, (byte) 0x30,
+        (byte) 0x0c, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x13,
+        (byte) 0x04, (byte) 0x05, (byte) 0x30, (byte) 0x03, (byte) 0x01, (byte) 0x01,
+        (byte) 0xff, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a,
+        (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01,
+        (byte) 0x01, (byte) 0x0b, (byte) 0x05, (byte) 0x00, (byte) 0x03, (byte) 0x82,
+        (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x52, (byte) 0x70, (byte) 0xb6,
+        (byte) 0x10, (byte) 0x7f, (byte) 0xaa, (byte) 0x86, (byte) 0x8f, (byte) 0x02,
+        (byte) 0xb0, (byte) 0x97, (byte) 0x89, (byte) 0xb9, (byte) 0x04, (byte) 0x1d,
+        (byte) 0x79, (byte) 0xa3, (byte) 0x74, (byte) 0x7c, (byte) 0xdf, (byte) 0xad,
+        (byte) 0x87, (byte) 0xe4, (byte) 0x00, (byte) 0xd3, (byte) 0x3a, (byte) 0x5c,
+        (byte) 0x48, (byte) 0x3b, (byte) 0xfe, (byte) 0x77, (byte) 0xfd, (byte) 0xbe,
+        (byte) 0xce, (byte) 0x5b, (byte) 0xd2, (byte) 0xea, (byte) 0x3e, (byte) 0x7f,
+        (byte) 0xef, (byte) 0x20, (byte) 0x0d, (byte) 0x0b, (byte) 0xc7, (byte) 0xc4,
+        (byte) 0x25, (byte) 0x20, (byte) 0xe1, (byte) 0x8f, (byte) 0xc5, (byte) 0x19,
+        (byte) 0x37, (byte) 0x9c, (byte) 0xa0, (byte) 0x9d, (byte) 0x02, (byte) 0x30,
+        (byte) 0x5f, (byte) 0x49, (byte) 0x4e, (byte) 0x56, (byte) 0xc4, (byte) 0xab,
+        (byte) 0xcb, (byte) 0x5c, (byte) 0xe6, (byte) 0x40, (byte) 0x93, (byte) 0x92,
+        (byte) 0xee, (byte) 0xa1, (byte) 0x69, (byte) 0x7d, (byte) 0x10, (byte) 0x6b,
+        (byte) 0xd4, (byte) 0xf7, (byte) 0xec, (byte) 0xd9, (byte) 0xa5, (byte) 0x29,
+        (byte) 0x63, (byte) 0x29, (byte) 0xd9, (byte) 0x27, (byte) 0x2d, (byte) 0x5e,
+        (byte) 0x34, (byte) 0x37, (byte) 0xa9, (byte) 0xba, (byte) 0x0a, (byte) 0x7b,
+        (byte) 0x99, (byte) 0x1a, (byte) 0x7d, (byte) 0xa7, (byte) 0xa7, (byte) 0xf0,
+        (byte) 0xbf, (byte) 0x40, (byte) 0x29, (byte) 0x5d, (byte) 0x2f, (byte) 0x2e,
+        (byte) 0x0f, (byte) 0x35, (byte) 0x90, (byte) 0xb5, (byte) 0xc3, (byte) 0xfd,
+        (byte) 0x1e, (byte) 0xe2, (byte) 0xb3, (byte) 0xae, (byte) 0xf9, (byte) 0xde,
+        (byte) 0x9d, (byte) 0x76, (byte) 0xe1, (byte) 0x20, (byte) 0xf5, (byte) 0x1c,
+        (byte) 0x30, (byte) 0x42, (byte) 0x80, (byte) 0x2a, (byte) 0x4f, (byte) 0x85,
+        (byte) 0x5c, (byte) 0xb4, (byte) 0x49, (byte) 0x68, (byte) 0x6c, (byte) 0x7c,
+        (byte) 0x2a, (byte) 0xc8, (byte) 0xbc, (byte) 0x15, (byte) 0xed, (byte) 0x88,
+        (byte) 0xfd, (byte) 0x8a, (byte) 0x63, (byte) 0xe0, (byte) 0x93, (byte) 0xfd,
+        (byte) 0x86, (byte) 0xab, (byte) 0xa9, (byte) 0xf6, (byte) 0x63, (byte) 0xa5,
+        (byte) 0x29, (byte) 0xaf, (byte) 0xdc, (byte) 0x8f, (byte) 0xca, (byte) 0xc2,
+        (byte) 0x28, (byte) 0xe7, (byte) 0x26, (byte) 0x89, (byte) 0x75, (byte) 0xf1,
+        (byte) 0x3e, (byte) 0x2e, (byte) 0x86, (byte) 0x11, (byte) 0x8b, (byte) 0xfa,
+        (byte) 0xf5, (byte) 0xb4, (byte) 0xb4, (byte) 0x04, (byte) 0x02, (byte) 0xa3,
+        (byte) 0x85, (byte) 0x81, (byte) 0xad, (byte) 0xb3, (byte) 0xec, (byte) 0x2d,
+        (byte) 0x4b, (byte) 0x40, (byte) 0x59, (byte) 0x61, (byte) 0x0d, (byte) 0x59,
+        (byte) 0x09, (byte) 0x09, (byte) 0xee, (byte) 0xc7, (byte) 0x51, (byte) 0xef,
+        (byte) 0x6f, (byte) 0xd6, (byte) 0x9a, (byte) 0xa5, (byte) 0x45, (byte) 0xa2,
+        (byte) 0x89, (byte) 0xc2, (byte) 0x97, (byte) 0x93, (byte) 0xbc, (byte) 0x5b,
+        (byte) 0x37, (byte) 0x55, (byte) 0x73, (byte) 0x55, (byte) 0x0c, (byte) 0x9c,
+        (byte) 0xcb, (byte) 0x10, (byte) 0xec, (byte) 0x76, (byte) 0xfe, (byte) 0xa7,
+        (byte) 0x70, (byte) 0x4e, (byte) 0x9a, (byte) 0xa2, (byte) 0xf9, (byte) 0x40,
+        (byte) 0xdd, (byte) 0x96, (byte) 0x7d, (byte) 0x67, (byte) 0x5c, (byte) 0x8e,
+        (byte) 0x43, (byte) 0x1a, (byte) 0x26, (byte) 0xaa, (byte) 0xee, (byte) 0x38,
+        (byte) 0x11, (byte) 0x26, (byte) 0x3d, (byte) 0x69, (byte) 0xc7, (byte) 0x6a,
+        (byte) 0xe7, (byte) 0xbd, (byte) 0x67, (byte) 0x70, (byte) 0x35, (byte) 0xff,
+        (byte) 0x72, (byte) 0x2c, (byte) 0x87, (byte) 0x82, (byte) 0x68, (byte) 0x3f,
+        (byte) 0x8d
+    };
+
+    private static final byte[] FAKE_EC_2 = {
+        (byte) 0x30, (byte) 0x82, (byte) 0x04, (byte) 0x4f, (byte) 0x30, (byte) 0x82,
+        (byte) 0x03, (byte) 0x37, (byte) 0xa0, (byte) 0x03, (byte) 0x02, (byte) 0x01,
+        (byte) 0x02, (byte) 0x02, (byte) 0x09, (byte) 0x00, (byte) 0xd9, (byte) 0xc4,
+        (byte) 0xe1, (byte) 0xfc, (byte) 0x3d, (byte) 0x02, (byte) 0x21, (byte) 0x1f,
+        (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86,
+        (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01,
+        (byte) 0x0b, (byte) 0x05, (byte) 0x00, (byte) 0x30, (byte) 0x81, (byte) 0xbd,
+        (byte) 0x31, (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03,
+        (byte) 0x55, (byte) 0x04, (byte) 0x06, (byte) 0x13, (byte) 0x02, (byte) 0x41,
+        (byte) 0x55, (byte) 0x31, (byte) 0x13, (byte) 0x30, (byte) 0x11, (byte) 0x06,
+        (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x08, (byte) 0x0c, (byte) 0x0a,
+        (byte) 0x53, (byte) 0x6f, (byte) 0x6d, (byte) 0x65, (byte) 0x2d, (byte) 0x53,
+        (byte) 0x74, (byte) 0x61, (byte) 0x74, (byte) 0x65, (byte) 0x31, (byte) 0x12,
+        (byte) 0x30, (byte) 0x10, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+        (byte) 0x07, (byte) 0x0c, (byte) 0x09, (byte) 0x53, (byte) 0x6f, (byte) 0x6d,
+        (byte) 0x65, (byte) 0x2d, (byte) 0x43, (byte) 0x69, (byte) 0x74, (byte) 0x79,
+        (byte) 0x31, (byte) 0x1b, (byte) 0x30, (byte) 0x19, (byte) 0x06, (byte) 0x03,
+        (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x0c, (byte) 0x12, (byte) 0x53,
+        (byte) 0x6f, (byte) 0x6d, (byte) 0x65, (byte) 0x2d, (byte) 0x4f, (byte) 0x74,
+        (byte) 0x68, (byte) 0x65, (byte) 0x72, (byte) 0x2d, (byte) 0x43, (byte) 0x6f,
+        (byte) 0x6d, (byte) 0x70, (byte) 0x61, (byte) 0x6e, (byte) 0x79, (byte) 0x31,
+        (byte) 0x15, (byte) 0x30, (byte) 0x13, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+        (byte) 0x04, (byte) 0x0b, (byte) 0x0c, (byte) 0x0c, (byte) 0x53, (byte) 0x6f,
+        (byte) 0x6d, (byte) 0x65, (byte) 0x2d, (byte) 0x53, (byte) 0x65, (byte) 0x63,
+        (byte) 0x74, (byte) 0x69, (byte) 0x6f, (byte) 0x6e, (byte) 0x31, (byte) 0x21,
+        (byte) 0x30, (byte) 0x1f, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+        (byte) 0x03, (byte) 0x0c, (byte) 0x18, (byte) 0x57, (byte) 0x69, (byte) 0x66,
+        (byte) 0x69, (byte) 0x45, (byte) 0x6e, (byte) 0x74, (byte) 0x65, (byte) 0x72,
+        (byte) 0x70, (byte) 0x72, (byte) 0x69, (byte) 0x73, (byte) 0x65, (byte) 0x43,
+        (byte) 0x6f, (byte) 0x6e, (byte) 0x66, (byte) 0x69, (byte) 0x67, (byte) 0x54,
+        (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x31, (byte) 0x2e, (byte) 0x30,
+        (byte) 0x2c, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48,
+        (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x09, (byte) 0x01,
+        (byte) 0x16, (byte) 0x1f, (byte) 0x61, (byte) 0x6e, (byte) 0x2d, (byte) 0x65,
+        (byte) 0x6d, (byte) 0x61, (byte) 0x69, (byte) 0x6c, (byte) 0x2d, (byte) 0x61,
+        (byte) 0x64, (byte) 0x72, (byte) 0x65, (byte) 0x73, (byte) 0x73, (byte) 0x40,
+        (byte) 0x73, (byte) 0x6f, (byte) 0x6d, (byte) 0x65, (byte) 0x2d, (byte) 0x64,
+        (byte) 0x6f, (byte) 0x6d, (byte) 0x61, (byte) 0x69, (byte) 0x6e, (byte) 0x2e,
+        (byte) 0x63, (byte) 0x6f, (byte) 0x6d, (byte) 0x30, (byte) 0x1e, (byte) 0x17,
+        (byte) 0x0d, (byte) 0x31, (byte) 0x36, (byte) 0x30, (byte) 0x31, (byte) 0x31,
+        (byte) 0x35, (byte) 0x31, (byte) 0x31, (byte) 0x33, (byte) 0x32, (byte) 0x34,
+        (byte) 0x36, (byte) 0x5a, (byte) 0x17, (byte) 0x0d, (byte) 0x32, (byte) 0x36,
+        (byte) 0x30, (byte) 0x31, (byte) 0x31, (byte) 0x32, (byte) 0x31, (byte) 0x31,
+        (byte) 0x33, (byte) 0x32, (byte) 0x34, (byte) 0x36, (byte) 0x5a, (byte) 0x30,
+        (byte) 0x81, (byte) 0xbd, (byte) 0x31, (byte) 0x0b, (byte) 0x30, (byte) 0x09,
+        (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x06, (byte) 0x13,
+        (byte) 0x02, (byte) 0x41, (byte) 0x55, (byte) 0x31, (byte) 0x13, (byte) 0x30,
+        (byte) 0x11, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x08,
+        (byte) 0x0c, (byte) 0x0a, (byte) 0x53, (byte) 0x6f, (byte) 0x6d, (byte) 0x65,
+        (byte) 0x2d, (byte) 0x53, (byte) 0x74, (byte) 0x61, (byte) 0x74, (byte) 0x65,
+        (byte) 0x31, (byte) 0x12, (byte) 0x30, (byte) 0x10, (byte) 0x06, (byte) 0x03,
+        (byte) 0x55, (byte) 0x04, (byte) 0x07, (byte) 0x0c, (byte) 0x09, (byte) 0x53,
+        (byte) 0x6f, (byte) 0x6d, (byte) 0x65, (byte) 0x2d, (byte) 0x43, (byte) 0x69,
+        (byte) 0x74, (byte) 0x79, (byte) 0x31, (byte) 0x1b, (byte) 0x30, (byte) 0x19,
+        (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x0c,
+        (byte) 0x12, (byte) 0x53, (byte) 0x6f, (byte) 0x6d, (byte) 0x65, (byte) 0x2d,
+        (byte) 0x4f, (byte) 0x74, (byte) 0x68, (byte) 0x65, (byte) 0x72, (byte) 0x2d,
+        (byte) 0x43, (byte) 0x6f, (byte) 0x6d, (byte) 0x70, (byte) 0x61, (byte) 0x6e,
+        (byte) 0x79, (byte) 0x31, (byte) 0x15, (byte) 0x30, (byte) 0x13, (byte) 0x06,
+        (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x0b, (byte) 0x0c, (byte) 0x0c,
+        (byte) 0x53, (byte) 0x6f, (byte) 0x6d, (byte) 0x65, (byte) 0x2d, (byte) 0x53,
+        (byte) 0x65, (byte) 0x63, (byte) 0x74, (byte) 0x69, (byte) 0x6f, (byte) 0x6e,
+        (byte) 0x31, (byte) 0x21, (byte) 0x30, (byte) 0x1f, (byte) 0x06, (byte) 0x03,
+        (byte) 0x55, (byte) 0x04, (byte) 0x03, (byte) 0x0c, (byte) 0x18, (byte) 0x57,
+        (byte) 0x69, (byte) 0x66, (byte) 0x69, (byte) 0x45, (byte) 0x6e, (byte) 0x74,
+        (byte) 0x65, (byte) 0x72, (byte) 0x70, (byte) 0x72, (byte) 0x69, (byte) 0x73,
+        (byte) 0x65, (byte) 0x43, (byte) 0x6f, (byte) 0x6e, (byte) 0x66, (byte) 0x69,
+        (byte) 0x67, (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x31,
+        (byte) 0x2e, (byte) 0x30, (byte) 0x2c, (byte) 0x06, (byte) 0x09, (byte) 0x2a,
+        (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01,
+        (byte) 0x09, (byte) 0x01, (byte) 0x16, (byte) 0x1f, (byte) 0x61, (byte) 0x6e,
+        (byte) 0x2d, (byte) 0x65, (byte) 0x6d, (byte) 0x61, (byte) 0x69, (byte) 0x6c,
+        (byte) 0x2d, (byte) 0x61, (byte) 0x64, (byte) 0x72, (byte) 0x65, (byte) 0x73,
+        (byte) 0x73, (byte) 0x40, (byte) 0x73, (byte) 0x6f, (byte) 0x6d, (byte) 0x65,
+        (byte) 0x2d, (byte) 0x64, (byte) 0x6f, (byte) 0x6d, (byte) 0x61, (byte) 0x69,
+        (byte) 0x6e, (byte) 0x2e, (byte) 0x63, (byte) 0x6f, (byte) 0x6d, (byte) 0x30,
+        (byte) 0x82, (byte) 0x01, (byte) 0x22, (byte) 0x30, (byte) 0x0d, (byte) 0x06,
+        (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7,
+        (byte) 0x0d, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00,
+        (byte) 0x03, (byte) 0x82, (byte) 0x01, (byte) 0x0f, (byte) 0x00, (byte) 0x30,
+        (byte) 0x82, (byte) 0x01, (byte) 0x0a, (byte) 0x02, (byte) 0x82, (byte) 0x01,
+        (byte) 0x01, (byte) 0x00, (byte) 0xa9, (byte) 0xa3, (byte) 0x21, (byte) 0xfd,
+        (byte) 0xa6, (byte) 0xc1, (byte) 0x04, (byte) 0x48, (byte) 0xc2, (byte) 0xc8,
+        (byte) 0x44, (byte) 0x50, (byte) 0xc4, (byte) 0x6d, (byte) 0x35, (byte) 0x24,
+        (byte) 0xf0, (byte) 0x6d, (byte) 0x69, (byte) 0xfb, (byte) 0xd1, (byte) 0xfc,
+        (byte) 0xde, (byte) 0xe9, (byte) 0xdb, (byte) 0xca, (byte) 0xee, (byte) 0x24,
+        (byte) 0x3d, (byte) 0x85, (byte) 0x8d, (byte) 0x84, (byte) 0xb4, (byte) 0x73,
+        (byte) 0xd1, (byte) 0x09, (byte) 0x37, (byte) 0x16, (byte) 0x80, (byte) 0x70,
+        (byte) 0x6b, (byte) 0x61, (byte) 0xcc, (byte) 0xf2, (byte) 0x98, (byte) 0xbd,
+        (byte) 0x53, (byte) 0x3a, (byte) 0x68, (byte) 0x60, (byte) 0x02, (byte) 0xba,
+        (byte) 0x0c, (byte) 0x53, (byte) 0x96, (byte) 0xfb, (byte) 0x80, (byte) 0xd1,
+        (byte) 0x5b, (byte) 0xc3, (byte) 0xcb, (byte) 0x7a, (byte) 0x81, (byte) 0x00,
+        (byte) 0x5d, (byte) 0x20, (byte) 0x72, (byte) 0xc0, (byte) 0xe4, (byte) 0x48,
+        (byte) 0x0e, (byte) 0xa2, (byte) 0xcd, (byte) 0xa2, (byte) 0x63, (byte) 0x8c,
+        (byte) 0x05, (byte) 0x7c, (byte) 0x63, (byte) 0x5b, (byte) 0xda, (byte) 0x0e,
+        (byte) 0xa7, (byte) 0x05, (byte) 0x09, (byte) 0x6d, (byte) 0xd5, (byte) 0xe4,
+        (byte) 0x3a, (byte) 0x4e, (byte) 0xa1, (byte) 0xf5, (byte) 0xfd, (byte) 0x47,
+        (byte) 0xee, (byte) 0x7b, (byte) 0xa3, (byte) 0x4c, (byte) 0x8c, (byte) 0xd3,
+        (byte) 0xbb, (byte) 0x58, (byte) 0x0f, (byte) 0x1c, (byte) 0x56, (byte) 0x80,
+        (byte) 0x80, (byte) 0xb5, (byte) 0xf9, (byte) 0x80, (byte) 0xc2, (byte) 0xd1,
+        (byte) 0x1d, (byte) 0x3f, (byte) 0xe8, (byte) 0x2a, (byte) 0x63, (byte) 0x0b,
+        (byte) 0x54, (byte) 0x5f, (byte) 0xd4, (byte) 0xcb, (byte) 0xb7, (byte) 0x94,
+        (byte) 0xe2, (byte) 0x35, (byte) 0x65, (byte) 0x59, (byte) 0xd1, (byte) 0x72,
+        (byte) 0xa4, (byte) 0xb8, (byte) 0xee, (byte) 0x82, (byte) 0x11, (byte) 0x7a,
+        (byte) 0x4c, (byte) 0x26, (byte) 0x66, (byte) 0x9b, (byte) 0x27, (byte) 0x3d,
+        (byte) 0x14, (byte) 0x4b, (byte) 0x4b, (byte) 0xc8, (byte) 0xf0, (byte) 0x6e,
+        (byte) 0x43, (byte) 0x8f, (byte) 0xee, (byte) 0x1f, (byte) 0xeb, (byte) 0x20,
+        (byte) 0xe2, (byte) 0x4c, (byte) 0x79, (byte) 0xbf, (byte) 0x21, (byte) 0x0d,
+        (byte) 0x36, (byte) 0xed, (byte) 0x5f, (byte) 0xcc, (byte) 0x70, (byte) 0x68,
+        (byte) 0x8a, (byte) 0x05, (byte) 0x7c, (byte) 0x2f, (byte) 0x1b, (byte) 0xe9,
+        (byte) 0xec, (byte) 0x83, (byte) 0x6e, (byte) 0x9a, (byte) 0x78, (byte) 0x31,
+        (byte) 0x3d, (byte) 0xf4, (byte) 0xde, (byte) 0x1b, (byte) 0xd2, (byte) 0x76,
+        (byte) 0x32, (byte) 0x6c, (byte) 0x1e, (byte) 0xc9, (byte) 0x90, (byte) 0x7f,
+        (byte) 0xc4, (byte) 0x30, (byte) 0xc0, (byte) 0xae, (byte) 0xab, (byte) 0x70,
+        (byte) 0x08, (byte) 0x78, (byte) 0xbf, (byte) 0x2e, (byte) 0x8b, (byte) 0x07,
+        (byte) 0xab, (byte) 0x8f, (byte) 0x03, (byte) 0xc5, (byte) 0xd3, (byte) 0xeb,
+        (byte) 0x98, (byte) 0x19, (byte) 0x50, (byte) 0x83, (byte) 0x52, (byte) 0xf7,
+        (byte) 0xff, (byte) 0xf5, (byte) 0x89, (byte) 0xe6, (byte) 0xe7, (byte) 0xa7,
+        (byte) 0xcb, (byte) 0xdf, (byte) 0x96, (byte) 0x9d, (byte) 0x14, (byte) 0x04,
+        (byte) 0x5e, (byte) 0x45, (byte) 0x82, (byte) 0xf7, (byte) 0x23, (byte) 0x1a,
+        (byte) 0xb6, (byte) 0x64, (byte) 0x57, (byte) 0xe8, (byte) 0x7e, (byte) 0xa1,
+        (byte) 0xaf, (byte) 0x58, (byte) 0x68, (byte) 0x70, (byte) 0xc5, (byte) 0x0f,
+        (byte) 0x8d, (byte) 0x54, (byte) 0xf3, (byte) 0x49, (byte) 0xa3, (byte) 0x97,
+        (byte) 0x32, (byte) 0xa7, (byte) 0x2a, (byte) 0x79, (byte) 0xbe, (byte) 0xcd,
+        (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0xa3,
+        (byte) 0x50, (byte) 0x30, (byte) 0x4e, (byte) 0x30, (byte) 0x1d, (byte) 0x06,
+        (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x0e, (byte) 0x04, (byte) 0x16,
+        (byte) 0x04, (byte) 0x14, (byte) 0xac, (byte) 0xf3, (byte) 0x73, (byte) 0x9a,
+        (byte) 0x25, (byte) 0x08, (byte) 0x01, (byte) 0x07, (byte) 0x86, (byte) 0x8b,
+        (byte) 0xc4, (byte) 0xed, (byte) 0xb1, (byte) 0x6b, (byte) 0x53, (byte) 0xa3,
+        (byte) 0x21, (byte) 0xb4, (byte) 0xb4, (byte) 0x46, (byte) 0x30, (byte) 0x1f,
+        (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x23, (byte) 0x04,
+        (byte) 0x18, (byte) 0x30, (byte) 0x16, (byte) 0x80, (byte) 0x14, (byte) 0xac,
+        (byte) 0xf3, (byte) 0x73, (byte) 0x9a, (byte) 0x25, (byte) 0x08, (byte) 0x01,
+        (byte) 0x07, (byte) 0x86, (byte) 0x8b, (byte) 0xc4, (byte) 0xed, (byte) 0xb1,
+        (byte) 0x6b, (byte) 0x53, (byte) 0xa3, (byte) 0x21, (byte) 0xb4, (byte) 0xb4,
+        (byte) 0x46, (byte) 0x30, (byte) 0x0c, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+        (byte) 0x1d, (byte) 0x13, (byte) 0x04, (byte) 0x05, (byte) 0x30, (byte) 0x03,
+        (byte) 0x01, (byte) 0x01, (byte) 0xff, (byte) 0x30, (byte) 0x0d, (byte) 0x06,
+        (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7,
+        (byte) 0x0d, (byte) 0x01, (byte) 0x01, (byte) 0x0b, (byte) 0x05, (byte) 0x00,
+        (byte) 0x03, (byte) 0x82, (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x16,
+        (byte) 0xf6, (byte) 0xd0, (byte) 0xe1, (byte) 0x14, (byte) 0x2d, (byte) 0x52,
+        (byte) 0x47, (byte) 0xa2, (byte) 0x89, (byte) 0xe6, (byte) 0x7f, (byte) 0xac,
+        (byte) 0x88, (byte) 0x04, (byte) 0x15, (byte) 0x21, (byte) 0x00, (byte) 0x72,
+        (byte) 0xf9, (byte) 0xee, (byte) 0xb2, (byte) 0x1b, (byte) 0x8e, (byte) 0x46,
+        (byte) 0x8b, (byte) 0x90, (byte) 0x20, (byte) 0x4f, (byte) 0xa7, (byte) 0xae,
+        (byte) 0x30, (byte) 0xb6, (byte) 0x24, (byte) 0xc5, (byte) 0x54, (byte) 0xaf,
+        (byte) 0x6c, (byte) 0x1e, (byte) 0xd6, (byte) 0x73, (byte) 0x22, (byte) 0x48,
+        (byte) 0x07, (byte) 0xb5, (byte) 0x13, (byte) 0x35, (byte) 0xbb, (byte) 0x9e,
+        (byte) 0xd9, (byte) 0x19, (byte) 0x79, (byte) 0xda, (byte) 0x76, (byte) 0x7f,
+        (byte) 0xf7, (byte) 0x87, (byte) 0xc9, (byte) 0xc3, (byte) 0x0b, (byte) 0x38,
+        (byte) 0x20, (byte) 0x26, (byte) 0xfc, (byte) 0x7f, (byte) 0x32, (byte) 0x2a,
+        (byte) 0xd5, (byte) 0x09, (byte) 0x87, (byte) 0xda, (byte) 0x23, (byte) 0x1f,
+        (byte) 0x71, (byte) 0x83, (byte) 0x00, (byte) 0x17, (byte) 0xf6, (byte) 0xb9,
+        (byte) 0x57, (byte) 0x21, (byte) 0xdf, (byte) 0x29, (byte) 0xcc, (byte) 0xdb,
+        (byte) 0xe9, (byte) 0x2c, (byte) 0xba, (byte) 0x86, (byte) 0x34, (byte) 0x53,
+        (byte) 0x29, (byte) 0x09, (byte) 0xc7, (byte) 0x3c, (byte) 0x8e, (byte) 0xa3,
+        (byte) 0x86, (byte) 0x81, (byte) 0x26, (byte) 0x7b, (byte) 0xa1, (byte) 0xbe,
+        (byte) 0xbc, (byte) 0xc9, (byte) 0x83, (byte) 0xb5, (byte) 0x36, (byte) 0x65,
+        (byte) 0x51, (byte) 0xb4, (byte) 0x41, (byte) 0xf0, (byte) 0x05, (byte) 0x78,
+        (byte) 0x3a, (byte) 0xa6, (byte) 0xad, (byte) 0x4b, (byte) 0x08, (byte) 0xd1,
+        (byte) 0xe4, (byte) 0xf1, (byte) 0x2e, (byte) 0xc7, (byte) 0x23, (byte) 0x6d,
+        (byte) 0xf0, (byte) 0x9d, (byte) 0x60, (byte) 0x6d, (byte) 0xe7, (byte) 0x11,
+        (byte) 0xaf, (byte) 0x41, (byte) 0x68, (byte) 0xee, (byte) 0x06, (byte) 0x76,
+        (byte) 0x82, (byte) 0x48, (byte) 0xee, (byte) 0x41, (byte) 0xc4, (byte) 0xf8,
+        (byte) 0xe1, (byte) 0x83, (byte) 0xbc, (byte) 0xa8, (byte) 0xbd, (byte) 0x9c,
+        (byte) 0x17, (byte) 0x45, (byte) 0xf4, (byte) 0x36, (byte) 0x67, (byte) 0x47,
+        (byte) 0x0e, (byte) 0x32, (byte) 0x13, (byte) 0x6e, (byte) 0xc1, (byte) 0x1e,
+        (byte) 0x08, (byte) 0xef, (byte) 0x10, (byte) 0xdf, (byte) 0x45, (byte) 0xbf,
+        (byte) 0x5a, (byte) 0xc4, (byte) 0x44, (byte) 0x4c, (byte) 0xd0, (byte) 0xd5,
+        (byte) 0x23, (byte) 0xde, (byte) 0xd7, (byte) 0x83, (byte) 0x1e, (byte) 0xb0,
+        (byte) 0x27, (byte) 0x4d, (byte) 0x57, (byte) 0xa3, (byte) 0xe8, (byte) 0x36,
+        (byte) 0x52, (byte) 0x1c, (byte) 0x48, (byte) 0x0a, (byte) 0xc4, (byte) 0xd8,
+        (byte) 0x32, (byte) 0xfc, (byte) 0xd0, (byte) 0x26, (byte) 0x6f, (byte) 0xa4,
+        (byte) 0x61, (byte) 0x2c, (byte) 0x3a, (byte) 0xa9, (byte) 0xfe, (byte) 0xa4,
+        (byte) 0x7a, (byte) 0x58, (byte) 0x54, (byte) 0x58, (byte) 0x96, (byte) 0x2b,
+        (byte) 0x6e, (byte) 0x9c, (byte) 0xc9, (byte) 0x00, (byte) 0xda, (byte) 0xc6,
+        (byte) 0xbb, (byte) 0x97, (byte) 0xc4, (byte) 0x95, (byte) 0x32, (byte) 0x6b,
+        (byte) 0x03, (byte) 0x6f, (byte) 0x33, (byte) 0x59, (byte) 0xd4, (byte) 0xa4,
+        (byte) 0x4a, (byte) 0x29, (byte) 0x29, (byte) 0x9a, (byte) 0xf4, (byte) 0x87,
+        (byte) 0x26, (byte) 0xe6, (byte) 0xee, (byte) 0x5c, (byte) 0x0b, (byte) 0xe9,
+        (byte) 0x98, (byte) 0x5d, (byte) 0xab, (byte) 0x31, (byte) 0xa1, (byte) 0x63,
+        (byte) 0xaa, (byte) 0x1a, (byte) 0xea, (byte) 0x61, (byte) 0x27, (byte) 0x5e,
+        (byte) 0x9e, (byte) 0x34, (byte) 0x73
+    };
+
+
     private boolean hasWifi() {
         return getContext().getPackageManager().hasSystemFeature(
                 PackageManager.FEATURE_WIFI);
@@ -57,7 +451,7 @@
         }
     }
 
-    public void testSettersAndGetters() {
+    public void testSettersAndGetters() throws Exception {
         if (!hasWifi()) {
             return;
         }
@@ -87,7 +481,17 @@
         assertTrue(config.getAnonymousIdentity().equals(ANON_IDENTITY));
         config.setPassword(PASSWORD);
         assertTrue(config.getPassword().equals(PASSWORD));
-        config.setCaCertificate(null);
+        CertificateFactory factory = CertificateFactory.getInstance("X.509");
+        X509Certificate cert1 = (X509Certificate) factory.generateCertificate(
+                new ByteArrayInputStream(FAKE_EC_1));
+        X509Certificate cert2 = (X509Certificate) factory.generateCertificate(
+                new ByteArrayInputStream(FAKE_EC_2));
+        config.setCaCertificate(cert1);
+        assertTrue(config.getCaCertificate().getSerialNumber().equals(cert1.getSerialNumber()));
+        config.setCaCertificates(new X509Certificate[]{cert1, cert2});
+        X509Certificate[] certs = config.getCaCertificates();
+        assertTrue(cert1.getSerialNumber().equals(certs[0].getSerialNumber()));
+        assertTrue(cert2.getSerialNumber().equals(certs[1].getSerialNumber()));
         config.setClientKeyEntry(null, null);
         config.setSubjectMatch(SUBJECT_MATCH);
         assertTrue(config.getSubjectMatch().equals(SUBJECT_MATCH));
diff --git a/tests/tests/os/src/android/os/cts/StrictModeTest.java b/tests/tests/os/src/android/os/cts/StrictModeTest.java
index 2407309..a345256 100644
--- a/tests/tests/os/src/android/os/cts/StrictModeTest.java
+++ b/tests/tests/os/src/android/os/cts/StrictModeTest.java
@@ -108,9 +108,9 @@
     }
 
     private boolean hasInternetConnection() {
-        // TODO: expand this to include devices with ethernet
         final PackageManager pm = getContext().getPackageManager();
         return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
-                || pm.hasSystemFeature(PackageManager.FEATURE_WIFI);
+                || pm.hasSystemFeature(PackageManager.FEATURE_WIFI)
+                || pm.hasSystemFeature(PackageManager.FEATURE_ETHERNET);
     }
 }
diff --git a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
index d20e550..14d5343 100644
--- a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
@@ -541,6 +541,7 @@
                     "/data/misc/bluetooth",
                     "/data/misc/dhcp",
                     "/data/misc/lockscreen",
+                    "/data/misc/sensor",
                     "/data/misc/webwidgets",
                     "/data/misc/webwidgets/chess",
                     "/data/misc/widgets",
diff --git a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
index fb3ef64..d1a102f 100644
--- a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
+++ b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
@@ -124,7 +124,7 @@
         List<PermissionInfo> permissions = new ArrayList<>();
         try (
                 InputStream in = getContext().getResources()
-                        .openRawResource(com.android.cts.permission2.R.raw.android_manifest)
+                        .openRawResource(android.permission2.cts.R.raw.android_manifest)
         ) {
             XmlPullParser parser = Xml.newPullParser();
             parser.setInput(in, null);
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStoreIntentsTest.java b/tests/tests/provider/src/android/provider/cts/MediaStoreIntentsTest.java
index a94e7f4..529b176 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStoreIntentsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStoreIntentsTest.java
@@ -71,7 +71,10 @@
         final String[] schemes = new String[] {
                 "file", "http", "https", "content" };
         final String[] mimes = new String[] {
-                "image/bmp", "image/jpeg", "image/png", "image/gif", "image/webp" };
+                "image/bmp", "image/jpeg", "image/png", "image/gif", "image/webp",
+                "image/x-adobe-dng", "image/x-canon-cr2", "image/x-nikon-nef", "image/x-nikon-nrw",
+                "image/x-sony-arw", "image/x-panasonic-rw2", "image/x-olympus-orf",
+                "image/x-fuji-raf", "image/x-pentax-pef", "image/x-samsung-srw" };
 
         for (String scheme : schemes) {
             for (String mime : mimes) {
diff --git a/tests/tests/security/src/android/security/cts/EncryptionTest.java b/tests/tests/security/src/android/security/cts/EncryptionTest.java
index bd9a458..b2e3991 100644
--- a/tests/tests/security/src/android/security/cts/EncryptionTest.java
+++ b/tests/tests/security/src/android/security/cts/EncryptionTest.java
@@ -76,8 +76,9 @@
     public void testConfig() throws Exception {
         if (cpuHasAes()) {
             // If CPU has AES CE, it must be enabled in kernel
-            assertTrue(crypto + " is missing xts-aes-ce",
-                hasKernelCrypto("xts-aes-ce"));
+            assertTrue(crypto + " is missing xts-aes-ce or xts-aes-aesni",
+                hasKernelCrypto("xts-aes-ce") ||
+                hasKernelCrypto("xts-aes-aesni"));
         } else if (cpuHasNeon()) {
             // Otherwise, if CPU has NEON, it must be enabled
             assertTrue(crypto + " is missing xts-aes-neon (or xts-aes-neonbs)",
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvInputServiceTest.java b/tests/tests/tv/src/android/media/tv/cts/TvInputServiceTest.java
index 2a3a713..4afb851 100644
--- a/tests/tests/tv/src/android/media/tv/cts/TvInputServiceTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/TvInputServiceTest.java
@@ -25,9 +25,11 @@
 import android.media.tv.TvContract;
 import android.media.tv.TvInputInfo;
 import android.media.tv.TvInputManager;
+import android.media.tv.TvRecordingClient;
 import android.media.tv.TvTrackInfo;
 import android.media.tv.TvView;
 import android.media.tv.cts.TvInputServiceTest.CountingTvInputService.CountingSession;
+import android.media.tv.cts.TvInputServiceTest.CountingTvInputService.CountingRecordingSession;
 import android.net.Uri;
 import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
@@ -57,6 +59,7 @@
             .setVideoWidth(1920).setVideoHeight(1080).setLanguage("und").build();
 
     private TvView mTvView;
+    private TvRecordingClient mTvRecordingClient;
     private Activity mActivity;
     private Instrumentation mInstrumentation;
     private TvInputManager mManager;
@@ -64,6 +67,7 @@
     private final StubCallback mCallback = new StubCallback();
     private final StubTimeShiftPositionCallback mTimeShiftPositionCallback =
             new StubTimeShiftPositionCallback();
+    private final StubRecordingCallback mRecordingCallback = new StubRecordingCallback();
 
     private static class StubCallback extends TvView.TvInputCallback {
         private int mChannelRetunedCount;
@@ -166,6 +170,8 @@
         mActivity = getActivity();
         mInstrumentation = getInstrumentation();
         mTvView = (TvView) mActivity.findViewById(R.id.tvview);
+        mTvRecordingClient = new TvRecordingClient(mActivity, "TvInputServiceTest",
+                mRecordingCallback, null);
         mManager = (TvInputManager) mActivity.getSystemService(Context.TV_INPUT_SERVICE);
         for (TvInputInfo info : mManager.getTvInputList()) {
             if (info.getServiceInfo().name.equals(CountingTvInputService.class.getName())) {
@@ -179,7 +185,7 @@
         CountingTvInputService.sSession = null;
     }
 
-    public void testTvInputService() throws Throwable {
+    public void testTvInputServiceSession() throws Throwable {
         if (!Utils.hasTvInputFramework(getActivity())) {
             return;
         }
@@ -218,7 +224,117 @@
         mInstrumentation.waitForIdleSync();
     }
 
+    public void testTvInputServiceRecordingSession() throws Throwable {
+        if (!Utils.hasTvInputFramework(getActivity())) {
+            return;
+        }
+        verifyCommandConnect();
+    }
+
+    public void verifyCommandConnect() {
+        resetCounts();
+        Uri fakeChannelUri = TvContract.buildChannelUri(0);
+        mTvRecordingClient.connect(mStubInfo.getId(), fakeChannelUri);
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                CountingRecordingSession session = CountingTvInputService.sRecordingSession;
+                return session != null && session.mConnectCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCommandDisconnect() {
+        resetCounts();
+        mTvRecordingClient.disconnect();
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                CountingRecordingSession session = CountingTvInputService.sRecordingSession;
+                return session != null && session.mDisconnectCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCommandStartRecording() {
+        resetCounts();
+        mTvRecordingClient.startRecording();
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                CountingRecordingSession session = CountingTvInputService.sRecordingSession;
+                return session != null && session.mStartRecordingCount> 0;
+            }
+        }.run();
+    }
+
+    public void verifyCommandStopRecording() {
+        resetCounts();
+        mTvRecordingClient.stopRecording();
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                CountingRecordingSession session = CountingTvInputService.sRecordingSession;
+                return session != null && session.mStopRecordingCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCallbackConnected() {
+        resetCounts();
+        CountingRecordingSession session = CountingTvInputService.sRecordingSession;
+        assertNotNull(session);
+        session.notifyConnected();
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                return mRecordingCallback.mConnectedCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCallbackError() {
+        resetCounts();
+        CountingRecordingSession session = CountingTvInputService.sRecordingSession;
+        assertNotNull(session);
+        session.notifyError(TvInputManager.RECORDING_ERROR_UNKNOWN);
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                return mRecordingCallback.mErrorCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCallbackRecordingStarted() {
+        resetCounts();
+        CountingRecordingSession session = CountingTvInputService.sRecordingSession;
+        assertNotNull(session);
+        session.notifyRecordingStarted();
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                return mRecordingCallback.mRecordingStartedCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCallbackRecordingStopped() {
+        resetCounts();
+        CountingRecordingSession session = CountingTvInputService.sRecordingSession;
+        assertNotNull(session);
+        Uri fakeChannelUri = TvContract.buildChannelUri(0);
+        session.notifyRecordingStopped(fakeChannelUri);
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                return mRecordingCallback.mRecordingStoppedCount > 0;
+            }
+        }.run();
+    }
+
     public void verifyCommandTune() {
+        resetCounts();
         Uri fakeChannelUri = TvContract.buildChannelUri(0);
         mTvView.tune(mStubInfo.getId(), fakeChannelUri);
         mInstrumentation.waitForIdleSync();
@@ -596,12 +712,17 @@
         if (CountingTvInputService.sSession != null) {
             CountingTvInputService.sSession.resetCounts();
         }
+        if (CountingTvInputService.sRecordingSession!= null) {
+            CountingTvInputService.sRecordingSession.resetCounts();
+        }
         mCallback.resetCounts();
         mTimeShiftPositionCallback.resetCounts();
+        mRecordingCallback.resetCounts();
     }
 
     public static class CountingTvInputService extends StubTvInputService {
         static CountingSession sSession;
+        static CountingRecordingSession sRecordingSession;
 
         @Override
         public Session onCreateSession(String inputId) {
@@ -610,6 +731,12 @@
             return sSession;
         }
 
+        @Override
+        public RecordingSession onCreateRecordingSession(String inputId) {
+            sRecordingSession = new CountingRecordingSession(this);
+            return sRecordingSession;
+        }
+
         public static class CountingSession extends Session {
             public volatile int mTuneCount;
             public volatile int mSetStreamVolumeCount;
@@ -771,5 +898,84 @@
                 mOverlayViewSizeChangedCount++;
             }
         }
+
+        public static class CountingRecordingSession extends RecordingSession {
+            public volatile int mConnectCount;
+            public volatile int mDisconnectCount;
+            public volatile int mStartRecordingCount;
+            public volatile int mStopRecordingCount;
+
+            CountingRecordingSession(Context context) {
+                super(context);
+            }
+
+            public void resetCounts() {
+                mConnectCount = 0;
+                mDisconnectCount = 0;
+                mStartRecordingCount = 0;
+                mStopRecordingCount = 0;
+            }
+
+            @Override
+            public void onConnect(Uri recordedProgramUri) {
+                mConnectCount++;
+            }
+
+            @Override
+            public void onDisconnect() {
+                mDisconnectCount++;
+            }
+
+            @Override
+            public void onStartRecording() {
+                mStartRecordingCount++;
+            }
+
+            @Override
+            public void onStopRecording() {
+                mStopRecordingCount++;
+            }
+        }
+    }
+
+    private static class StubRecordingCallback extends TvRecordingClient.RecordingCallback {
+        private int mConnectedCount;
+        private int mDisconnectedCount;
+        private int mRecordingStartedCount;
+        private int mRecordingStoppedCount;
+        private int mErrorCount;
+
+        @Override
+        public void onConnected() {
+            mConnectedCount++;
+        }
+
+        @Override
+        public void onDisconnected() {
+            mDisconnectedCount++;
+        }
+
+        @Override
+        public void onRecordingStarted() {
+            mRecordingStartedCount++;
+        }
+
+        @Override
+        public void onRecordingStopped(Uri recordedProgramUri) {
+            mRecordingStoppedCount++;
+        }
+
+        @Override
+        public void onError(int error) {
+            mErrorCount++;
+        }
+
+        public void resetCounts() {
+            mConnectedCount = 0;
+            mDisconnectedCount = 0;
+            mRecordingStartedCount = 0;
+            mRecordingStoppedCount = 0;
+            mErrorCount = 0;
+        }
     }
 }
diff --git a/tests/tests/view/Android.mk b/tests/tests/view/Android.mk
index e57e10e..1a290ac 100644
--- a/tests/tests/view/Android.mk
+++ b/tests/tests/view/Android.mk
@@ -24,12 +24,18 @@
 # Tag this module as a cts_v2 test artifact
 LOCAL_COMPATIBILITY_SUITE := cts_v2
 
+LOCAL_MULTILIB := both
+
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
 LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner mockito-target
 
+LOCAL_JNI_SHARED_LIBRARIES := libctsview_jni libnativehelper_compat_libc++
+
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsViewTestCases
 
 include $(BUILD_CTS_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/view/jni/Android.mk b/tests/tests/view/jni/Android.mk
new file mode 100644
index 0000000..ac7b844
--- /dev/null
+++ b/tests/tests/view/jni/Android.mk
@@ -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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libctsview_jni
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := \
+		CtsViewJniOnLoad.cpp \
+		android_view_cts_ChoreographerNativeTest.cpp
+
+LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
+
+LOCAL_SHARED_LIBRARIES := libandroid libnativehelper_compat_libc++ liblog
+
+LOCAL_CXX_STL := libc++_static
+
+LOCAL_CLANG := true
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/view/jni/CtsViewJniOnLoad.cpp b/tests/tests/view/jni/CtsViewJniOnLoad.cpp
new file mode 100644
index 0000000..2c1e643
--- /dev/null
+++ b/tests/tests/view/jni/CtsViewJniOnLoad.cpp
@@ -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.
+ *
+ */
+#include <jni.h>
+
+#include <utils/Log.h>
+#define LOG_TAG "CtsViewJniOnLoad"
+
+extern int register_android_view_cts_ChoreographerNativeTest(JNIEnv* env);
+
+jint JNI_OnLoad(JavaVM *vm, void *) {
+    JNIEnv *env = NULL;
+    if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) {
+        return JNI_ERR;
+    }
+    if (register_android_view_cts_ChoreographerNativeTest(env)) {
+        return JNI_ERR;
+    }
+    return JNI_VERSION_1_4;
+}
diff --git a/tests/tests/view/jni/android_view_cts_ChoreographerNativeTest.cpp b/tests/tests/view/jni/android_view_cts_ChoreographerNativeTest.cpp
new file mode 100644
index 0000000..45b82d6
--- /dev/null
+++ b/tests/tests/view/jni/android_view_cts_ChoreographerNativeTest.cpp
@@ -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.
+ *
+ */
+
+#include <android/choreographer.h>
+
+#include <jni.h>
+#include <sys/time.h>
+#include <time.h>
+
+#include <chrono>
+#include <cstdlib>
+#include <cstring>
+#include <mutex>
+#include <thread>
+
+#define LOG_TAG "ChoreographerNative"
+
+#define ASSERT(condition, format, args...) \
+        if (!(condition)) { \
+            fail(env, format, ## args); \
+            return; \
+        }
+
+
+using namespace std::chrono_literals;
+
+static constexpr std::chrono::nanoseconds NOMINAL_VSYNC_PERIOD{16ms};
+static constexpr std::chrono::nanoseconds DELAY_PERIOD{NOMINAL_VSYNC_PERIOD * 5};
+
+static std::mutex gLock;
+struct Callback {
+    int count{0};
+    std::chrono::nanoseconds frameTime{0};
+};
+
+static void frameCallback(long frameTimeNanos, void* data) {
+    std::lock_guard<std::mutex> _l(gLock);
+    Callback* cb = static_cast<Callback*>(data);
+    cb->count++;
+    cb->frameTime = std::chrono::nanoseconds{frameTimeNanos};
+}
+
+static std::chrono::nanoseconds now() {
+    return std::chrono::steady_clock::now().time_since_epoch();
+}
+
+static void fail(JNIEnv* env, const char* format, ...) {
+    va_list args;
+
+    va_start(args, format);
+    char *msg;
+    int rc = vasprintf(&msg, format, args);
+    va_end(args);
+
+    jclass exClass;
+    const char *className = "java/lang/AssertionError";
+    exClass = env->FindClass(className);
+    env->ThrowNew(exClass, msg);
+    free(msg);
+}
+
+static jlong android_view_cts_ChoreographerNativeTest_getChoreographer(JNIEnv*, jclass) {
+    std::lock_guard<std::mutex> _l{gLock};
+    return reinterpret_cast<jlong>(AChoreographer_getInstance());
+}
+
+static jboolean android_view_cts_ChoreographerNativeTest_prepareChoreographerTests(JNIEnv*, jclass,
+        jlong choreographerPtr) {
+    std::lock_guard<std::mutex> _l{gLock};
+    AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
+    return choreographer != nullptr;
+}
+
+static void android_view_cts_ChoreographerNativeTest_testPostCallbackWithoutDelayEventuallyRunsCallback(
+        JNIEnv* env, jclass, jlong choreographerPtr) {
+    AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
+    Callback* cb1 = new Callback();
+    Callback* cb2 = new Callback();
+    auto start = now();
+
+    AChoreographer_postFrameCallback(choreographer, frameCallback, cb1);
+    AChoreographer_postFrameCallback(choreographer, frameCallback, cb2);
+    std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
+    {
+        std::lock_guard<std::mutex> _l{gLock};
+        ASSERT(cb1->count == 1, "Choreographer failed to invoke callback 1");
+        ASSERT(cb1->frameTime - start < NOMINAL_VSYNC_PERIOD * 3,
+                "Callback 1 has incorect frame time on first invokation");
+        ASSERT(cb2->count == 1, "Choreographer failed to invoke callback 2");
+        ASSERT(cb2->frameTime - start < NOMINAL_VSYNC_PERIOD * 3,
+                "Callback 2 has incorect frame time on first invokation");
+        auto delta = cb2->frameTime - cb1->frameTime;
+        ASSERT(delta == delta.zero() || delta > delta.zero() && delta < NOMINAL_VSYNC_PERIOD * 2,
+                "Callback 1 and 2 have frame times too large of a delta in frame times");
+    }
+
+    AChoreographer_postFrameCallback(choreographer, frameCallback, cb1);
+    start = now();
+    std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
+    {
+        std::lock_guard<std::mutex> _l{gLock};
+        ASSERT(cb1->count == 2, "Choreographer failed to invoke callback 1 a second time");
+        ASSERT(cb1->frameTime - start < NOMINAL_VSYNC_PERIOD * 3,
+                "Callback 1 has incorect frame time on second invokation");
+        ASSERT(cb2->count == 1, "Choreographer invoked callback 2 when not posted");
+    }
+}
+
+static void android_view_cts_ChoreographerNativeTest_testPostCallbackWithDelayEventuallyRunsCallback(
+        JNIEnv* env, jclass, jlong choreographerPtr) {
+    AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
+    Callback* cb1 = new Callback();
+    auto start = now();
+
+    auto delay = std::chrono::duration_cast<std::chrono::milliseconds>(DELAY_PERIOD).count();
+    AChoreographer_postFrameCallbackDelayed(choreographer, frameCallback, cb1, delay);
+    std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
+    {
+        std::lock_guard<std::mutex> _l{gLock};
+        ASSERT(cb1->count == 0,
+                "Choreographer failed to delay callback for a sufficient period of time");
+    }
+    std::this_thread::sleep_for(DELAY_PERIOD);
+    {
+        std::lock_guard<std::mutex> _l{gLock};
+        ASSERT(cb1->count == 1, "Choreographer failed to invoke delayed callback");
+        ASSERT(cb1->frameTime - start < DELAY_PERIOD + NOMINAL_VSYNC_PERIOD * 3,
+                "Frametime on callback is incorrect")
+    }
+}
+
+static JNINativeMethod gMethods[] = {
+    {  "nativeGetChoreographer", "()J",
+            (void *) android_view_cts_ChoreographerNativeTest_getChoreographer},
+    {  "nativePrepareChoreographerTests", "(J)Z",
+            (void *) android_view_cts_ChoreographerNativeTest_prepareChoreographerTests},
+    {  "nativeTestPostCallbackWithoutDelayEventuallyRunsCallbacks", "(J)V",
+            (void *) android_view_cts_ChoreographerNativeTest_testPostCallbackWithoutDelayEventuallyRunsCallback},
+    {  "nativeTestPostCallbackWithDelayEventuallyRunsCallbacks", "(J)V",
+            (void *) android_view_cts_ChoreographerNativeTest_testPostCallbackWithDelayEventuallyRunsCallback},
+};
+
+int register_android_view_cts_ChoreographerNativeTest(JNIEnv* env)
+{
+    jclass clazz = env->FindClass("android/view/cts/ChoreographerNativeTest");
+    return env->RegisterNatives(clazz, gMethods,
+            sizeof(gMethods) / sizeof(JNINativeMethod));
+}
diff --git a/tests/tests/view/src/android/view/cts/ChoreographerNativeTest.java b/tests/tests/view/src/android/view/cts/ChoreographerNativeTest.java
new file mode 100644
index 0000000..38f351c
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/ChoreographerNativeTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.InstrumentationTestCase;
+import android.view.Choreographer;
+
+public class ChoreographerNativeTest extends InstrumentationTestCase {
+    private long mChoreographerPtr;
+    private Choreographer mChoreographer;
+
+    private static native long nativeGetChoreographer();
+    private static native boolean nativePrepareChoreographerTests(long ptr);
+    private static native void nativeTestPostCallbackWithoutDelayEventuallyRunsCallbacks(long ptr);
+    private static native void nativeTestPostCallbackWithDelayEventuallyRunsCallbacks(long ptr);
+
+    static {
+        System.loadLibrary("ctsview_jni");
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                mChoreographerPtr = nativeGetChoreographer();
+            }
+        });
+        if (!nativePrepareChoreographerTests(mChoreographerPtr)) {
+            fail("Failed to setup choreographer tests");
+        }
+    }
+
+    public void testPostCallbackWithoutDelayEventuallyRunsCallbacks() {
+        nativeTestPostCallbackWithoutDelayEventuallyRunsCallbacks(mChoreographerPtr);
+    }
+
+    public void testPostCallbackWithDelayEventuallyRunsCallbacks() {
+        nativeTestPostCallbackWithDelayEventuallyRunsCallbacks(mChoreographerPtr);
+    }
+}
diff --git a/tests/tests/view/src/android/view/cts/ViewTest.java b/tests/tests/view/src/android/view/cts/ViewTest.java
index 6e8c2a3..c3fe030 100644
--- a/tests/tests/view/src/android/view/cts/ViewTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewTest.java
@@ -1435,6 +1435,8 @@
 
     public void testPerformLongClickXY_WithListener() {
         OnLongClickListener listener = mock(OnLongClickListener.class);
+        when(listener.onLongClick(any(View.class))).thenReturn(true);
+
         MockViewParent parent = new MockViewParent(mActivity);
         MockView view = new MockView(mActivity);
 
diff --git a/tests/tests/view/src/android/view/cts/WindowTest.java b/tests/tests/view/src/android/view/cts/WindowTest.java
index a897af4..0e67c3e 100644
--- a/tests/tests/view/src/android/view/cts/WindowTest.java
+++ b/tests/tests/view/src/android/view/cts/WindowTest.java
@@ -1046,7 +1046,7 @@
         }
 
         @Override
-        public void onMultiWindowModeChanged() {
+        public void onMultiWindowChanged() {
         }
 
         @Override
diff --git a/tools/cts-tradefed/res/config/cts-preconditions.xml b/tools/cts-tradefed/res/config/cts-preconditions.xml
new file mode 100644
index 0000000..9f0a8c9
--- /dev/null
+++ b/tools/cts-tradefed/res/config/cts-preconditions.xml
@@ -0,0 +1,44 @@
+<?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.
+-->
+<configuration description="CTS precondition configs">
+
+    <option name="compatibility:plan" value="cts-preconditions" />
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="host" />
+        <option name="module-name" value="cts_v2"/>
+        <option name="version-name" value="1.0"/>
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.StayAwakePreparer" />
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkPreconditionCheck">
+        <option name="apk" value="CtsPreconditions.apk"/>
+        <option name="package" value="com.android.preconditions.cts"/>
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="run-command" value="rm -rf /sdcard/device-info-files" />
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DeviceInfoCollector">
+        <option name="apk" value="CtsDeviceInfo.apk"/>
+        <option name="package" value="com.android.compatibility.common.deviceinfo"/>
+        <option name="src-dir" value="/sdcard/device-info-files/"/>
+        <option name="dest-dir" value="device-info-files/"/>
+    </target_preparer>
+
+</configuration>
diff --git a/tools/cts-tradefed/res/config/cts.xml b/tools/cts-tradefed/res/config/cts.xml
index e6a75a0..8e34297 100644
--- a/tools/cts-tradefed/res/config/cts.xml
+++ b/tools/cts-tradefed/res/config/cts.xml
@@ -16,6 +16,7 @@
 <configuration description="Runs CTS from a pre-existing CTS installation">
 
     <include name="everything" />
+    <include name="cts-preconditions" />
 
     <option name="compatibility:plan" value="cts" />
 
@@ -24,17 +25,10 @@
     <!-- Exclude sample test cases -->
     <option name="compatibility:exclude-filter" value="CtsSampleDeviceTestCases" />
     <option name="compatibility:exclude-filter" value="CtsSampleHostTestCases" />
+
     <!-- Exclude automotive only test cases for now -->
     <option name="compatibility:exclude-filter" value="CtsAutomotiveTestCases" />
 
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
-        <option name="target" value="host" />
-        <option name="module-name" value="cts_v2"/>
-        <option name="version-name" value="1.0"/>
-    </target_preparer>
-
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.StayAwakePreparer" />
-
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.PropertyCheck">
         <option name="property-name" value="ro.build.type" />
         <option name="expected-value" value="user"/> <!-- Device should have user build -->
@@ -47,20 +41,4 @@
         <option name="throw-error" value="false"/> <!-- Only print warning if not en-US -->
     </target_preparer>
 
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkPreconditionCheck">
-        <option name="apk" value="CtsPreconditions.apk"/>
-        <option name="package" value="com.android.preconditions.cts"/>
-    </target_preparer>
-
-    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-        <option name="run-command" value="rm -rf /sdcard/device-info-files" />
-    </target_preparer>
-
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DeviceInfoCollector">
-        <option name="apk" value="CtsDeviceInfo.apk"/>
-        <option name="package" value="com.android.compatibility.common.deviceinfo"/>
-        <option name="src-dir" value="/sdcard/device-info-files/"/>
-        <option name="dest-dir" value="device-info-files/"/>
-    </target_preparer>
-
 </configuration>