Merge "Add KeySet key-rotation CTS tests." into lmp-dev
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index 6eda314..2215600 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -24,6 +24,17 @@
     CtsSharedUidInstallDiffCert \
     CtsSimpleAppInstall \
     CtsSimpleAppInstallDiffCert \
+    CtsSplitApp \
+    CtsSplitApp_x86 \
+    CtsSplitApp_x86_64 \
+    CtsSplitApp_armeabi-v7a \
+    CtsSplitApp_armeabi \
+    CtsSplitApp_arm64-v8a \
+    CtsSplitApp_mips64 \
+    CtsSplitApp_mips \
+    CtsSplitAppDiffVersion \
+    CtsSplitAppDiffCert \
+    CtsSplitAppFeature \
     CtsTargetInstrumentationApp \
     CtsUsePermissionDiffCert \
     CtsWriteExternalStorageApp \
@@ -140,6 +151,7 @@
     CtsTvTestCases \
     CtsUiAutomationTestCases \
     CtsUiRenderingTestCases \
+    CtsUsageStatsTestCases \
     CtsUtilTestCases \
     CtsViewTestCases \
     CtsWebkitTestCases \
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 55ce851..f37e1fa 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -18,10 +18,9 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="com.android.cts.verifier"
       android:versionCode="3"
-      android:versionName="L_r0">
+      android:versionName="5.0_r0.5">
 
-    <!-- Using 10+ for more complete NFC support... -->
-    <uses-sdk android:minSdkVersion="20" android:targetSdkVersion="20"/>
+    <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="21"/>
 
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
@@ -107,6 +106,8 @@
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_device_admin" />
+            <meta-data android:name="test_excluded_features"
+                       android:value="android.hardware.type.television:android.software.leanback" />
         </activity>
 
         <receiver android:name=".admin.TestDeviceAdminReceiver"
@@ -443,6 +444,8 @@
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_security" />
+            <meta-data android:name="test_excluded_features"
+                       android:value="android.hardware.type.television:android.software.leanback" />
         </activity>
 
         <activity android:name=".streamquality.StreamingVideoActivity"
@@ -871,6 +874,8 @@
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_location" />
+            <meta-data android:name="test_excluded_features"
+                       android:value="android.hardware.type.television:android.software.leanback" />
         </activity>
         <activity android:name=".location.LocationModeBatterySavingTestActivity"
                 android:label="@string/location_mode_battery_saving_test">
@@ -887,6 +892,8 @@
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_location" />
+            <meta-data android:name="test_excluded_features"
+                       android:value="android.hardware.type.television:android.software.leanback" />
         </activity>
 
         <activity android:name=".camera.formats.CameraFormatsActivity"
@@ -998,6 +1005,8 @@
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_sensors" />
+            <meta-data android:name="test_excluded_features"
+                       android:value="android.hardware.type.television:android.software.leanback" />
         </activity>
 
         <activity android:name=".p2p.P2pTestListActivity"
@@ -1137,6 +1146,8 @@
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_sensors" />
+            <meta-data android:name="test_excluded_features"
+                       android:value="android.hardware.type.television:android.software.leanback" />
         </activity>
 
         <activity
@@ -1152,6 +1163,8 @@
             <meta-data
                 android:name="test_category"
                 android:value="@string/test_category_sensors" />
+            <meta-data android:name="test_excluded_features"
+                       android:value="android.hardware.type.television:android.software.leanback" />
         </activity>
 
         <receiver android:name=".widget.WidgetCtsProvider">
@@ -1234,6 +1247,7 @@
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_managed_provisioning" />
+            <meta-data android:name="test_required_features" android:value="android.software.managed_users:android.software.device_admin" />
         </activity>
 
 
@@ -1249,6 +1263,7 @@
                 <category android:name="android.intent.category.DEFAULT"></category>
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_managed_provisioning" />
+            <meta-data android:name="test_required_features" android:value="android.software.managed_users:android.software.device_admin" />
         </activity>
 
         <activity android:name=".managedprovisioning.ByodHelperActivity">
@@ -1259,6 +1274,13 @@
             </intent-filter>
         </activity>
 
+        <activity android:name=".managedprovisioning.CrossProfileTestActivity">
+            <intent-filter>
+                <action android:name="com.android.cts.verifier.managedprovisioning.CROSS_PROFILE" />
+                <category android:name="android.intent.category.DEFAULT"></category>
+            </intent-filter>
+        </activity>
+
         <receiver android:name=".managedprovisioning.DeviceAdminTestReceiver"
                 android:label="@string/provisioning_byod_device_admin"
                 android:permission="android.permission.BIND_DEVICE_ADMIN">
diff --git a/apps/CtsVerifier/res/layout/provisioning_byod.xml b/apps/CtsVerifier/res/layout/provisioning_byod.xml
index 5e59558..989266f 100644
--- a/apps/CtsVerifier/res/layout/provisioning_byod.xml
+++ b/apps/CtsVerifier/res/layout/provisioning_byod.xml
@@ -41,7 +41,7 @@
     <ListView
         android:id="@id/android:list"
         android:layout_width="match_parent"
-        android:layout_height="258dp" />
+        android:layout_height="wrap_content" />
 
     <include layout="@layout/pass_fail_buttons" />
 
diff --git a/apps/CtsVerifier/res/layout/provisioning_cross_profile.xml b/apps/CtsVerifier/res/layout/provisioning_cross_profile.xml
new file mode 100644
index 0000000..345e99d
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/provisioning_cross_profile.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:orientation="vertical" >
+    <TextView android:id="@+id/text"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              android:textAppearance="?android:attr/textAppearanceLarge" />
+
+    <Button
+        android:id="@+id/button_finish"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/provisioning_button_finish" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index bb755cd..22e0cff 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -1215,6 +1215,19 @@
     <string name="provisioning_byod_profile_visible">Work profile visible in Settings</string>
     <string name="provisioning_byod_admin_visible">Device administrator visible in Settings</string>
     <string name="provisioning_byod_workapps_visible">Badged work apps visible in Launcher</string>
+    <string name="provisioning_byod_cross_profile">Open app cross profiles</string>
+    <string name="provisioning_byod_cross_profile_app_personal">
+        You selected the CTS Verifier option.
+    </string>
+    <string name="provisioning_byod_cross_profile_app_work">You selected the Work option.</string>
+    <string name="provisioning_byod_cross_profile_instruction">
+        Please press the Go button to start an action.\n
+        \n
+        You should be asked to choose either \"CTS Verifier\" or \"Work\" to complete the action.
+        Pressing either should bring up a page stating your choice.\n
+        \n
+        Verify that you are prompted with the above choices and both options work as intended. Then mark this test accordingly.
+    </string>
     <string name="provisioning_byod_profile_visible_instruction">
         Please press the Go button to open the Settings page.
         Navigate to Accounts and confirm that:\n
@@ -1247,6 +1260,8 @@
     <string name="provisioning_byod_profile_deleted">Work profile deleted.</string>
     <string name="provisioning_byod_disabled">Device provisioning is not enabled.</string>
     <string name="provisioning_byod_go">Go</string>
+    <string name="provisioning_button_finish">Finish</string>
+    <string name="provisioning_cross_profile_chooser">Choose an app to complete action</string>
 
     <!-- Strings for DeviceOwnerProvisioningTest -->
     <string name="provisioning_device_owner">Device Owner Provisioning</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/ManifestTestListAdapter.java b/apps/CtsVerifier/src/com/android/cts/verifier/ManifestTestListAdapter.java
index 1f19cbe..2f42e81 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/ManifestTestListAdapter.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/ManifestTestListAdapter.java
@@ -67,6 +67,14 @@
  *             <meta-data android:name="test_required_features" android:value="android.hardware.sensor.accelerometer" />
  *         </pre>
  *     </li>
+ *     <li>OPTIONAL: Add a meta data attribute to indicate features such that, if any present, the
+ *         test gets excluded from being shown. If the device has any of the excluded features then
+ *         the test will not appear in the test list. Use a colon (:) to specify multiple features
+ *         to exclude for the test. Note that the colon means "or" in this case.
+ *         <pre>
+ *             <meta-data android:name="test_excluded_features" android:value="android.hardware.type.television" />
+ *         </pre>
+ *     </li>
  *
  * </ol>
  */
@@ -78,6 +86,8 @@
 
     private static final String TEST_REQUIRED_FEATURES_META_DATA = "test_required_features";
 
+    private static final String TEST_EXCLUDED_FEATURES_META_DATA = "test_excluded_features";
+
     private Context mContext;
 
     private String mTestParent;
@@ -152,7 +162,9 @@
             String testName = info.activityInfo.name;
             Intent intent = getActivityIntent(info.activityInfo);
             String[] requiredFeatures = getRequiredFeatures(info.activityInfo.metaData);
-            TestListItem item = TestListItem.newTest(title, testName, intent, requiredFeatures);
+            String[] excludedFeatures = getExcludedFeatures(info.activityInfo.metaData);
+            TestListItem item = TestListItem.newTest(title, testName, intent,
+                                                     requiredFeatures, excludedFeatures);
 
             String testCategory = getTestCategory(mContext, info.activityInfo.metaData);
             addTestToCategory(testsByCategory, testCategory, item);
@@ -190,6 +202,19 @@
         }
     }
 
+    static String[] getExcludedFeatures(Bundle metaData) {
+        if (metaData == null) {
+            return null;
+        } else {
+            String value = metaData.getString(TEST_EXCLUDED_FEATURES_META_DATA);
+            if (value == null) {
+                return null;
+            } else {
+                return value.split(":");
+            }
+        }
+    }
+
     static String getTitle(Context context, ActivityInfo activityInfo) {
         if (activityInfo.labelRes != 0) {
             return context.getString(activityInfo.labelRes);
@@ -216,22 +241,39 @@
         tests.add(item);
     }
 
-    List<TestListItem> filterTests(List<TestListItem> tests) {
-        List<TestListItem> filteredTests = new ArrayList<TestListItem>(tests);
-        PackageManager packageManager = mContext.getPackageManager();
-        Iterator<TestListItem> iterator = filteredTests.iterator();
-        while (iterator.hasNext()) {
-            TestListItem item = iterator.next();
-            String[] requiredFeatures = item.requiredFeatures;
-            if (requiredFeatures != null) {
-                for (int i = 0; i < requiredFeatures.length; i++) {
-                    if (!packageManager.hasSystemFeature(requiredFeatures[i])) {
-                        iterator.remove();
-                        break;
-                    }
+    private boolean hasAnyFeature(String[] features) {
+        if (features != null) {
+            PackageManager packageManager = mContext.getPackageManager();
+            for (String feature : features) {
+                if (packageManager.hasSystemFeature(feature)) {
+                    return true;
                 }
             }
         }
+        return false;
+    }
+
+    private boolean hasAllFeatures(String[] features) {
+        if (features != null) {
+            PackageManager packageManager = mContext.getPackageManager();
+            for (String feature : features) {
+                if (!packageManager.hasSystemFeature(feature)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    List<TestListItem> filterTests(List<TestListItem> tests) {
+        List<TestListItem> filteredTests = new ArrayList<TestListItem>();
+        for (TestListItem test : tests) {
+            String[] excludedFeatures = test.excludedFeatures;
+            String[] requiredFeatures = test.requiredFeatures;
+            if (!hasAnyFeature(excludedFeatures) && hasAllFeatures(requiredFeatures)) {
+                filteredTests.add(test);
+            }
+        }
         return filteredTests;
     }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java
index 2cc79fb..0d9985c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java
@@ -83,14 +83,29 @@
         /** Features necessary to run this test. */
         final String[] requiredFeatures;
 
+        /** Features such that, if any present, the test gets excluded from being shown. */
+        final String[] excludedFeatures;
+
+        public static TestListItem newTest(Context context, int titleResId, String testName,
+                Intent intent, String[] requiredFeatures, String[] excludedFeatures) {
+            return newTest(context.getString(titleResId), testName, intent,
+                           requiredFeatures, excludedFeatures);
+        }
+
         public static TestListItem newTest(Context context, int titleResId, String testName,
                 Intent intent, String[] requiredFeatures) {
-            return newTest(context.getString(titleResId), testName, intent, requiredFeatures);
+            return newTest(context.getString(titleResId), testName, intent,
+                           requiredFeatures, null);
+        }
+
+        public static TestListItem newTest(String title, String testName, Intent intent,
+                String[] requiredFeatures, String[] excludedFeatures) {
+            return new TestListItem(title, testName, intent, requiredFeatures, excludedFeatures);
         }
 
         public static TestListItem newTest(String title, String testName, Intent intent,
                 String[] requiredFeatures) {
-            return new TestListItem(title, testName, intent, requiredFeatures);
+            return new TestListItem(title, testName, intent, requiredFeatures, null);
         }
 
         public static TestListItem newCategory(Context context, int titleResId) {
@@ -98,15 +113,16 @@
         }
 
         public static TestListItem newCategory(String title) {
-            return new TestListItem(title, null, null, null);
+            return new TestListItem(title, null, null, null, null);
         }
 
         private TestListItem(String title, String testName, Intent intent,
-                String[] requiredFeatures) {
+                String[] requiredFeatures, String[] excludedFeatures) {
             this.title = title;
             this.testName = testName;
             this.intent = intent;
             this.requiredFeatures = requiredFeatures;
+            this.excludedFeatures = excludedFeatures;
         }
 
         boolean isTest() {
@@ -366,4 +382,4 @@
 
         }
     }
-}
\ No newline at end of file
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java
index d71dca2..178a811 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java
@@ -69,7 +69,7 @@
     private List<SelectableResolution> mSupportedResolutions;
     private ArrayAdapter<SelectableResolution> mAdapter;
 
-    private int mCameraId;
+    private SelectableResolution mSelectedResolution;
     private Camera mCamera;
     private Size mSurfaceSize;
     private boolean mCameraInitialized = false;
@@ -165,12 +165,7 @@
                     AdapterView<?> parent, View view, int position, long id) {
                 if (mSupportedResolutions != null) {
                     SelectableResolution resolution = mSupportedResolutions.get(position);
-
-                    switchToCamera(resolution.cameraId, false);
-
-                    Camera.Parameters params = mCamera.getParameters();
-                    params.setPictureSize(resolution.width, resolution.height);
-                    mCamera.setParameters(params);
+                    switchToCamera(resolution, false);
 
                     // It should be guaranteed that the FOV is correctly updated after setParameters().
                     mReportedFovPrePictureTaken = mCamera.getParameters().getHorizontalViewAngle();
@@ -376,7 +371,7 @@
                     public void onCancel(DialogInterface arg0) {
                         // User cancelled preview size selection.
                         mPreviewSizes = null;
-                        switchToCamera(mCameraId, true);
+                        switchToCamera(mSelectedResolution, true);
                     }
                 }).
                 setSingleChoiceItems(choices, 0, new DialogInterface.OnClickListener() {
@@ -389,7 +384,7 @@
 
                         if (mPreviewSizeCamerasToProcess.isEmpty()) {
                             // We're done, re-initialize camera.
-                            switchToCamera(mCameraId, true);
+                            switchToCamera(mSelectedResolution, true);
                         } else {
                             // Process other cameras.
                             showNextDialogToChoosePreviewSize();
@@ -415,7 +410,7 @@
 
         // Either use chosen preview size for current camera or automatically
         // choose preview size based on view dimensions.
-        Size selectedPreviewSize = (mPreviewSizes != null) ? mPreviewSizes[mCameraId] :
+        Size selectedPreviewSize = (mPreviewSizes != null) ? mPreviewSizes[mSelectedResolution.cameraId] :
             getBestPreviewSize(mSurfaceSize.width, mSurfaceSize.height, params);
         if (selectedPreviewSize != null) {
             params.setPreviewSize(selectedPreviewSize.width, selectedPreviewSize.height);
@@ -427,19 +422,20 @@
 
     private void startPreview() {
         if (mCameraInitialized && mCamera != null) {
-            setCameraDisplayOrientation(this, mCameraId, mCamera);
+            setCameraDisplayOrientation(this, mSelectedResolution.cameraId, mCamera);
             mCamera.startPreview();
             mPreviewActive = true;
         }
     }
 
-    private void switchToCamera(int cameraId, boolean initializeCamera) {
+    private void switchToCamera(SelectableResolution resolution, boolean initializeCamera) {
         if (mCamera != null) {
             mCamera.stopPreview();
             mCamera.release();
         }
-        mCameraId = cameraId;
-        mCamera = Camera.open(cameraId);
+
+        mSelectedResolution = resolution;
+        mCamera = Camera.open(mSelectedResolution.cameraId);
 
         if (initializeCamera){
           initializeCamera();
@@ -472,7 +468,7 @@
      * Set the common camera parameters on the given camera and returns the
      * parameter object for further modification, if needed.
      */
-    private static Camera.Parameters setCameraParams(Camera camera) {
+    private Camera.Parameters setCameraParams(Camera camera) {
         // The picture size is taken and set from the spinner selection
         // callback.
         Camera.Parameters params = camera.getParameters();
@@ -480,6 +476,7 @@
         params.setJpegQuality(100);
         params.setFocusMode(getFocusMode(camera));
         params.setZoom(0);
+        params.setPictureSize(mSelectedResolution.width, mSelectedResolution.height);
         return params;
     }
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureSummaryActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureSummaryActivity.java
index 20ccd81..032442b 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureSummaryActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureSummaryActivity.java
@@ -229,7 +229,7 @@
 
         // add features from latest to last so that the latest requirements are put in the set first
         int apiVersion = Build.VERSION.SDK_INT;
-        if (apiVersion >= Build.VERSION_CODES.L) {
+        if (apiVersion >= Build.VERSION_CODES.LOLLIPOP) {
             Collections.addAll(features, ALL_LMP_FEATURES);
         }
         if (apiVersion >= Build.VERSION_CODES.KITKAT_WATCH) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
index 69071f6..da823e8 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
@@ -73,6 +73,7 @@
     private TestItem mProfileVisibleTest;
     private TestItem mDeviceAdminVisibleTest;
     private TestItem mWorkAppVisibleTest;
+    private TestItem mCrossProfileIntentFiltersTest;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -173,11 +174,19 @@
                 R.string.provisioning_byod_workapps_visible_instruction,
                 new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME));
 
+        Intent intent = new Intent(CrossProfileTestActivity.ACTION_CROSS_PROFILE);
+        Intent chooser = Intent.createChooser(intent, getResources().getString(R.string.provisioning_cross_profile_chooser));
+        mCrossProfileIntentFiltersTest = new TestItem(this,
+                R.string.provisioning_byod_cross_profile,
+                R.string.provisioning_byod_cross_profile_instruction,
+                chooser);
+
         mTests.add(mDiskEncryptionTest);
         mTests.add(mProfileOwnerInstalled);
         mTests.add(mProfileVisibleTest);
         mTests.add(mDeviceAdminVisibleTest);
         mTests.add(mWorkAppVisibleTest);
+        mTests.add(mCrossProfileIntentFiltersTest);
     }
 
     @Override
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CrossProfileTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CrossProfileTestActivity.java
new file mode 100644
index 0000000..6c38e12
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CrossProfileTestActivity.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.managedprovisioning;
+//package com.android.cts.verifier.managedprovisioning;
+
+import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.UserManager;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.TextView;
+
+import com.android.cts.verifier.R;
+
+/**
+ * Test activity for cross profile intents.
+ */
+public class CrossProfileTestActivity extends Activity {
+    // Intent for app in both profiles
+    public static final String ACTION_CROSS_PROFILE = "com.android.cts.verifier.managedprovisioning.CROSS_PROFILE";
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.provisioning_cross_profile);
+        TextView textView = (TextView) findViewById(R.id.text);
+
+        // Check if we are running in the work or personal side, by testing if currently we are the
+        // profile owner or not.
+        textView.setText(isProfileOwner() ? R.string.provisioning_byod_cross_profile_app_work
+                : R.string.provisioning_byod_cross_profile_app_personal);
+
+        findViewById(R.id.button_finish).setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                CrossProfileTestActivity.this.finish();
+            }
+        });
+    }
+
+    private boolean isProfileOwner() {
+        ComponentName adminReceiver = new ComponentName(this, DeviceAdminTestReceiver.class.getName());
+        DevicePolicyManager dpm = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
+        return dpm.isAdminActive(adminReceiver) && dpm.isProfileOwnerApp(adminReceiver.getPackageName());
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
index 861bca2..8dccac3 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
@@ -26,6 +26,8 @@
 import android.util.Log;
 import android.widget.Toast;
 
+import com.android.cts.verifier.managedprovisioning.ByodHelperActivity;
+
 /**
  * Profile owner receiver for BYOD flow test.
  * Setup cross-profile intent filter after successful provisioning.
@@ -48,6 +50,7 @@
             IntentFilter filter = new IntentFilter();
             filter.addAction(ByodHelperActivity.ACTION_QUERY_PROFILE_OWNER);
             filter.addAction(ByodHelperActivity.ACTION_REMOVE_PROFILE_OWNER);
+            filter.addAction(CrossProfileTestActivity.ACTION_CROSS_PROFILE);
             dpm.addCrossProfileIntentFilter(getWho(context), filter,
                     DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT);
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceEmulatorTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceEmulatorTestActivity.java
index 3029796..87fa3d1 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceEmulatorTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceEmulatorTestActivity.java
@@ -103,7 +103,7 @@
                     OnAndOffHostEmulatorActivity.class.getName(),
                     new Intent(this, OnAndOffHostEmulatorActivity.class), null));
 
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.L) {
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                 adapter.add(TestListItem.newTest(this, R.string.nfc_hce_payment_dynamic_aids_emulator,
                         DynamicAidEmulatorActivity.class.getName(),
                         new Intent(this, DynamicAidEmulatorActivity.class), null));
diff --git a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/SplitTests.java b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/SplitTests.java
new file mode 100644
index 0000000..b9bc768
--- /dev/null
+++ b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/SplitTests.java
@@ -0,0 +1,397 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.appsecurity;
+
+import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.cts.util.AbiUtils;
+import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.ddmlib.testrunner.TestResult;
+import com.android.ddmlib.testrunner.TestResult.TestStatus;
+import com.android.ddmlib.testrunner.TestRunResult;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Tests that verify installing of various split APKs from host side.
+ */
+public class SplitTests extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
+    private static final String PKG = "com.android.cts.splitapp";
+
+    private static final String APK = "CtsSplitApp.apk";
+
+    private static final String APK_mdpi = "CtsSplitApp_mdpi-v4.apk";
+    private static final String APK_hdpi = "CtsSplitApp_hdpi-v4.apk";
+    private static final String APK_xhdpi = "CtsSplitApp_xhdpi-v4.apk";
+    private static final String APK_xxhdpi = "CtsSplitApp_xxhdpi-v4.apk";
+
+    private static final String APK_v7 = "CtsSplitApp_v7.apk";
+    private static final String APK_fr = "CtsSplitApp_fr.apk";
+    private static final String APK_de = "CtsSplitApp_de.apk";
+
+    private static final String APK_x86 = "CtsSplitApp_x86.apk";
+    private static final String APK_x86_64 = "CtsSplitApp_x86_64.apk";
+    private static final String APK_armeabi_v7a = "CtsSplitApp_armeabi-v7a.apk";
+    private static final String APK_armeabi = "CtsSplitApp_armeabi.apk";
+    private static final String APK_arm64_v8a = "CtsSplitApp_arm64-v8a.apk";
+    private static final String APK_mips64 = "CtsSplitApp_mips64.apk";
+    private static final String APK_mips = "CtsSplitApp_mips.apk";
+
+    private static final String APK_DIFF_VERSION_v7 = "CtsSplitAppDiffVersion_v7.apk";
+    private static final String APK_DIFF_CERT_v7 = "CtsSplitAppDiffCert_v7.apk";
+
+    private static final String APK_FEATURE = "CtsSplitAppFeature.apk";
+    private static final String APK_FEATURE_v7 = "CtsSplitAppFeature_v7.apk";
+
+    private static final HashMap<String, String> ABI_TO_APK = new HashMap<>();
+
+    static {
+        ABI_TO_APK.put("x86", APK_x86);
+        ABI_TO_APK.put("x86_64", APK_x86_64);
+        ABI_TO_APK.put("armeabi-v7a", APK_armeabi_v7a);
+        ABI_TO_APK.put("armeabi", APK_armeabi);
+        ABI_TO_APK.put("arm64-v8a", APK_arm64_v8a);
+        ABI_TO_APK.put("mips64", APK_mips64);
+        ABI_TO_APK.put("mips", APK_mips);
+    }
+
+    private IAbi mAbi;
+    private CtsBuildHelper mCtsBuild;
+
+    @Override
+    public void setAbi(IAbi abi) {
+        mAbi = abi;
+    }
+
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        assertNotNull(mAbi);
+        assertNotNull(mCtsBuild);
+
+        getDevice().uninstallPackage(PKG);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+
+        getDevice().uninstallPackage(PKG);
+    }
+
+    public void testSingleBase() throws Exception {
+        new InstallMultiple().addApk(APK).run();
+        runDeviceTests(PKG, ".SplitAppTest", "testSingleBase");
+    }
+
+    public void testDensitySingle() throws Exception {
+        new InstallMultiple().addApk(APK).addApk(APK_mdpi).run();
+        runDeviceTests(PKG, ".SplitAppTest", "testDensitySingle");
+    }
+
+    public void testDensityAll() throws Exception {
+        new InstallMultiple().addApk(APK).addApk(APK_mdpi).addApk(APK_hdpi).addApk(APK_xhdpi)
+                .addApk(APK_xxhdpi).run();
+        runDeviceTests(PKG, ".SplitAppTest", "testDensityAll");
+    }
+
+    /**
+     * Install first with low-resolution resources, then add a split that offers
+     * higher-resolution resources.
+     */
+    public void testDensityBest() throws Exception {
+        new InstallMultiple().addApk(APK).addApk(APK_mdpi).run();
+        runDeviceTests(PKG, ".SplitAppTest", "testDensityBest1");
+
+        // Now splice in an additional split which offers better resources
+        new InstallMultiple().inheritFrom(PKG).addApk(APK_xxhdpi).run();
+        runDeviceTests(PKG, ".SplitAppTest", "testDensityBest2");
+    }
+
+    /**
+     * Verify that an API-based split can change enabled/disabled state of
+     * manifest elements.
+     */
+    public void testApi() throws Exception {
+        new InstallMultiple().addApk(APK).addApk(APK_v7).run();
+        runDeviceTests(PKG, ".SplitAppTest", "testApi");
+    }
+
+    public void testLocale() throws Exception {
+        new InstallMultiple().addApk(APK).addApk(APK_de).addApk(APK_fr).run();
+        runDeviceTests(PKG, ".SplitAppTest", "testLocale");
+    }
+
+    /**
+     * Install test app with <em>single</em> split that exactly matches the
+     * currently active ABI. This also explicitly forces ABI when installing.
+     */
+    public void testNativeSingle() throws Exception {
+        final String abi = mAbi.getName();
+        final String apk = ABI_TO_APK.get(abi);
+        assertNotNull("Failed to find APK for ABI " + abi, apk);
+
+        new InstallMultiple().addApk(APK).addApk(apk).run();
+        runDeviceTests(PKG, ".SplitAppTest", "testNative");
+    }
+
+    /**
+     * Install test app with <em>single</em> split that exactly matches the
+     * currently active ABI. This variant <em>does not</em> force the ABI when
+     * installing, instead exercising the system's ability to choose the ABI
+     * through inspection of the installed app.
+     */
+    public void testNativeSingleNatural() throws Exception {
+        final String abi = mAbi.getName();
+        final String apk = ABI_TO_APK.get(abi);
+        assertNotNull("Failed to find APK for ABI " + abi, apk);
+
+        new InstallMultiple().useNaturalAbi().addApk(APK).addApk(apk).run();
+        runDeviceTests(PKG, ".SplitAppTest", "testNative");
+    }
+
+    /**
+     * Install test app with <em>all</em> possible ABI splits. This also
+     * explicitly forces ABI when installing.
+     */
+    public void testNativeAll() throws Exception {
+        final InstallMultiple inst = new InstallMultiple().addApk(APK);
+        for (String apk : ABI_TO_APK.values()) {
+            inst.addApk(apk);
+        }
+        inst.run();
+        runDeviceTests(PKG, ".SplitAppTest", "testNative");
+    }
+
+    /**
+     * Install test app with <em>all</em> possible ABI splits. This variant
+     * <em>does not</em> force the ABI when installing, instead exercising the
+     * system's ability to choose the ABI through inspection of the installed
+     * app.
+     */
+    public void testNativeAllNatural() throws Exception {
+        final InstallMultiple inst = new InstallMultiple().useNaturalAbi().addApk(APK);
+        for (String apk : ABI_TO_APK.values()) {
+            inst.addApk(apk);
+        }
+        inst.run();
+        runDeviceTests(PKG, ".SplitAppTest", "testNative");
+    }
+
+    public void testDuplicateBase() throws Exception {
+        new InstallMultiple().addApk(APK).addApk(APK).runExpectingFailure();
+    }
+
+    public void testDuplicateSplit() throws Exception {
+        new InstallMultiple().addApk(APK).addApk(APK_v7).addApk(APK_v7).runExpectingFailure();
+    }
+
+    public void testDiffCert() throws Exception {
+        new InstallMultiple().addApk(APK).addApk(APK_DIFF_CERT_v7).runExpectingFailure();
+    }
+
+    public void testDiffCertInherit() throws Exception {
+        new InstallMultiple().addApk(APK).run();
+        // TODO: remove this once we fix 17900178
+        runDeviceTests(PKG, ".SplitAppTest", "testSingleBase");
+        new InstallMultiple().inheritFrom(PKG).addApk(APK_DIFF_CERT_v7).runExpectingFailure();
+    }
+
+    public void testDiffVersion() throws Exception {
+        new InstallMultiple().addApk(APK).addApk(APK_DIFF_VERSION_v7).runExpectingFailure();
+    }
+
+    public void testDiffVersionInherit() throws Exception {
+        new InstallMultiple().addApk(APK).run();
+        // TODO: remove this once we fix 17900178
+        runDeviceTests(PKG, ".SplitAppTest", "testSingleBase");
+        new InstallMultiple().inheritFrom(PKG).addApk(APK_DIFF_VERSION_v7).runExpectingFailure();
+    }
+
+    public void testFeatureBase() throws Exception {
+        new InstallMultiple().addApk(APK).addApk(APK_FEATURE).run();
+        runDeviceTests(PKG, ".SplitAppTest", "testFeatureBase");
+    }
+
+    public void testFeatureApi() throws Exception {
+        new InstallMultiple().addApk(APK).addApk(APK_FEATURE).addApk(APK_FEATURE_v7).run();
+        runDeviceTests(PKG, ".SplitAppTest", "testFeatureApi");
+    }
+
+    public void testInheritUpdatedBase() throws Exception {
+        // TODO: flesh out this test
+    }
+
+    public void testInheritUpdatedSplit() throws Exception {
+        // TODO: flesh out this test
+    }
+
+    class InstallMultiple {
+        private List<String> mArgs = new ArrayList<>();
+        private List<File> mApks = new ArrayList<>();
+        private boolean mUseNaturalAbi;
+
+        InstallMultiple addArg(String arg) {
+            mArgs.add(arg);
+            return this;
+        }
+
+        InstallMultiple addApk(String apk) throws FileNotFoundException {
+            mApks.add(mCtsBuild.getTestApp(apk));
+            return this;
+        }
+
+        InstallMultiple inheritFrom(String packageName) {
+            addArg("-r");
+            addArg("-p " + packageName);
+            return this;
+        }
+
+        InstallMultiple useNaturalAbi() {
+            mUseNaturalAbi = true;
+            return this;
+        }
+
+        void run() throws DeviceNotAvailableException {
+            run(true);
+        }
+
+        void runExpectingFailure() throws DeviceNotAvailableException {
+            run(false);
+        }
+
+        private void run(boolean expectingSuccess) throws DeviceNotAvailableException {
+            final ITestDevice device = getDevice();
+
+            // Create an install session
+            final StringBuilder cmd = new StringBuilder();
+            cmd.append("pm install-create");
+            for (String arg : mArgs) {
+                cmd.append(' ').append(arg);
+            }
+            if (!mUseNaturalAbi) {
+                cmd.append(' ').append(AbiUtils.createAbiFlag(mAbi.getName()));
+            }
+
+            String result = device.executeShellCommand(cmd.toString());
+            assertTrue(result, result.startsWith("Success"));
+
+            final int start = result.lastIndexOf("[");
+            final int end = result.lastIndexOf("]");
+            int sessionId = -1;
+            try {
+                if (start != -1 && end != -1 && start < end) {
+                    sessionId = Integer.parseInt(result.substring(start + 1, end));
+                }
+            } catch (NumberFormatException e) {
+            }
+            if (sessionId == -1) {
+                throw new IllegalStateException("Failed to create install session: " + result);
+            }
+
+            // Push our files into session. Ideally we'd use stdin streaming,
+            // but ddmlib doesn't support it yet.
+            for (int i = 0; i < mApks.size(); i++) {
+                final File apk = mApks.get(i);
+                final String remotePath = "/data/local/tmp/" + i + "_" + apk.getName();
+                if (!device.pushFile(apk, remotePath)) {
+                    throw new IllegalStateException("Failed to push " + apk);
+                }
+
+                cmd.setLength(0);
+                cmd.append("pm install-write");
+                cmd.append(' ').append(sessionId);
+                cmd.append(' ').append(i + "_" + apk.getName());
+                cmd.append(' ').append(remotePath);
+
+                result = device.executeShellCommand(cmd.toString());
+                assertTrue(result, result.startsWith("Success"));
+            }
+
+            // Everything staged; let's pull trigger
+            cmd.setLength(0);
+            cmd.append("pm install-commit");
+            cmd.append(' ').append(sessionId);
+
+            result = device.executeShellCommand(cmd.toString());
+            if (expectingSuccess) {
+                assertTrue(result, result.startsWith("Success"));
+            } else {
+                assertFalse(result, result.startsWith("Success"));
+            }
+        }
+    }
+
+    public void runDeviceTests(String packageName) throws DeviceNotAvailableException {
+        runDeviceTests(packageName, null, null);
+    }
+
+    public void runDeviceTests(String packageName, String testClassName, String testMethodName)
+            throws DeviceNotAvailableException {
+        if (testClassName != null && testClassName.startsWith(".")) {
+            testClassName = packageName + testClassName;
+        }
+
+        RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(packageName,
+                "android.support.test.runner.AndroidJUnitRunner", getDevice().getIDevice());
+        if (testClassName != null && testMethodName != null) {
+            testRunner.setMethodName(testClassName, testMethodName);
+        }
+
+        final CollectingTestListener listener = new CollectingTestListener();
+        getDevice().runInstrumentationTests(testRunner, listener);
+
+        final TestRunResult result = listener.getCurrentRunResults();
+        if (result.isRunFailure()) {
+            fail("Failed to successfully run device tests for " + result.getName() + ": "
+                    + result.getRunFailureMessage());
+        }
+
+        if (result.hasFailedTests()) {
+            // build a meaningful error message
+            StringBuilder errorBuilder = new StringBuilder("on-device tests failed:\n");
+            for (Map.Entry<TestIdentifier, TestResult> resultEntry :
+                result.getTestResults().entrySet()) {
+                if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
+                    errorBuilder.append(resultEntry.getKey().toString());
+                    errorBuilder.append(":\n");
+                    errorBuilder.append(resultEntry.getValue().getStackTrace());
+                }
+            }
+            fail(errorBuilder.toString());
+        }
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/Android.mk
new file mode 100644
index 0000000..bc3acaf
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/Android.mk
@@ -0,0 +1,89 @@
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsSplitApp
+LOCAL_PACKAGE_SPLITS := mdpi-v4 hdpi-v4 xhdpi-v4 xxhdpi-v4 v7 fr de
+
+LOCAL_ASSET_DIR := $(LOCAL_PATH)/assets
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+LOCAL_AAPT_FLAGS := --version-code 100 --version-name OneHundred --replace-version -c mdpi
+
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+
+################################################
+# Define a variant with a different version code
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsSplitAppDiffVersion
+LOCAL_PACKAGE_SPLITS := v7
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+LOCAL_AAPT_FLAGS := --version-code 101 --version-name OneHundredOne --replace-version -c mdpi
+
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+
+################################################
+# Define a variant with a different signature
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsSplitAppDiffCert
+LOCAL_PACKAGE_SPLITS := v7
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey2
+LOCAL_AAPT_FLAGS := --version-code 100 --version-name OneHundred --replace-version -c mdpi
+
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+
+ifeq (,$(ONE_SHOT_MAKEFILE))
+include $(LOCAL_PATH)/libs/Android.mk $(LOCAL_PATH)/feature/Android.mk
+endif
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml
new file mode 100644
index 0000000..dba384c
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.cts.splitapp">
+
+    <uses-permission android:name="android.permission.CAMERA" />
+
+    <application android:label="SplitApp">
+        <activity android:name=".MyActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+            <meta-data android:name="android.service.wallpaper" android:resource="@xml/my_activity_meta" />
+        </activity>
+        <receiver android:name=".MyReceiver"
+                android:enabled="@bool/my_receiver_enabled">
+            <intent-filter>
+                <action android:name="android.intent.action.DATE_CHANGED" />
+            </intent-filter>
+        </receiver>
+
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.cts.splitapp" />
+
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/NativeTemplate.mk b/hostsidetests/appsecurity/test-apps/SplitApp/NativeTemplate.mk
new file mode 100644
index 0000000..b61c5d6
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/NativeTemplate.mk
@@ -0,0 +1,28 @@
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsSplitApp_ARCHARCH
+
+LOCAL_JAVA_RESOURCE_DIRS := raw
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/README b/hostsidetests/appsecurity/test-apps/SplitApp/README
new file mode 100644
index 0000000..480289e
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/README
@@ -0,0 +1,7 @@
+
+The entire libs/ directory is built and constructed automatically with
+the build_libs.sh script.  Don't attempt to modify manually.  To rebuild
+the native code, make the following change to the NDK to pass through
+the target architecture, and then run build_libs.sh:
+
+build/core/build-binary.mk:LOCAL_CFLAGS := -DANDROID -D__ANDROID_ARCH__=\"$(TARGET_ARCH_ABI)\" $(LOCAL_CFLAGS)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/assets/dir/dirfile1.txt b/hostsidetests/appsecurity/test-apps/SplitApp/assets/dir/dirfile1.txt
new file mode 100644
index 0000000..8fba750
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/assets/dir/dirfile1.txt
@@ -0,0 +1 @@
+DIRFILE1
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/assets/file1.txt b/hostsidetests/appsecurity/test-apps/SplitApp/assets/file1.txt
new file mode 100644
index 0000000..cb4ee5e
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/assets/file1.txt
@@ -0,0 +1 @@
+FILE1
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/build_libs.sh b/hostsidetests/appsecurity/test-apps/SplitApp/build_libs.sh
new file mode 100755
index 0000000..6090374
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/build_libs.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+NDK_BUILD="$HOME/android-ndk-r10b/ndk-build"
+
+# Go build everything
+rm -rf libs
+cd jni/
+$NDK_BUILD clean
+$NDK_BUILD
+cd ../
+
+for arch in `ls libs/`;
+do
+    (
+    mkdir -p tmp/$arch/raw/lib/$arch/
+    mv libs/$arch/* tmp/$arch/raw/lib/$arch/
+
+    echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>
+<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"
+        package=\"com.android.cts.splitapp\"
+        split=\"lib_${arch//[^a-zA-Z0-9_]/_}\">
+    <application android:hasCode=\"false\" />
+</manifest>" > tmp/$arch/AndroidManifest.xml
+
+    cp NativeTemplate.mk tmp/$arch/Android.mk
+    sed -i -r "s/ARCHARCH/$arch/" tmp/$arch/Android.mk
+
+    )
+done
+
+echo "include \$(call all-subdir-makefiles)" > tmp/Android.mk
+
+rm -rf libs
+rm -rf obj
+
+mv tmp libs
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/feature/Android.mk
new file mode 100644
index 0000000..9965f60
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/Android.mk
@@ -0,0 +1,38 @@
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_PACKAGE_NAME := CtsSplitAppFeature
+LOCAL_PACKAGE_SPLITS := v7
+
+LOCAL_ASSET_DIR := $(LOCAL_PATH)/assets
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+LOCAL_AAPT_FLAGS := --version-code 100 --version-name OneHundred --replace-version -c mdpi
+
+LOCAL_MODULE_TAGS := tests
+
+featureOf := CtsSplitApp
+featureOfApk := $(call intermediates-dir-for,APPS,$(featureOf))/package.apk
+localRStamp := $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),,COMMON)/src/R.stamp
+$(localRStamp): $(featureOfApk)
+
+LOCAL_AAPT_FLAGS += --feature-of $(featureOfApk)
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/feature/AndroidManifest.xml
new file mode 100644
index 0000000..8ba3c2f
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/AndroidManifest.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.cts.splitapp"
+        featureName="feature">
+
+    <!-- New permission should be ignored -->
+    <uses-permission android:name="android.permission.INTERNET" />
+
+    <!-- New application flag should be ignored -->
+    <application android:largeHeap="true">
+        <activity android:name=".FeatureActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+            <meta-data android:name="android.service.wallpaper" android:resource="@xml/my_activity_meta" />
+        </activity>
+        <receiver android:name=".FeatureReceiver"
+                android:enabled="@bool/feature_receiver_enabled">
+            <intent-filter>
+                <action android:name="android.intent.action.DATE_CHANGED" />
+            </intent-filter>
+        </receiver>
+        <service android:name=".FeatureService">
+            <intent-filter>
+                <action android:name="com.android.cts.splitapp.service" />
+            </intent-filter>
+        </service>
+        <provider android:name=".FeatureProvider" android:authorities="com.android.cts.splitapp.provider" />
+    </application>
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/assets/dir/dirfile2.txt b/hostsidetests/appsecurity/test-apps/SplitApp/feature/assets/dir/dirfile2.txt
new file mode 100644
index 0000000..c4a2fff
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/assets/dir/dirfile2.txt
@@ -0,0 +1 @@
+DIRFILE2
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/assets/file2.txt b/hostsidetests/appsecurity/test-apps/SplitApp/feature/assets/file2.txt
new file mode 100644
index 0000000..d77231c
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/assets/file2.txt
@@ -0,0 +1 @@
+FILE2
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/res/values-v7/values.xml b/hostsidetests/appsecurity/test-apps/SplitApp/feature/res/values-v7/values.xml
new file mode 100644
index 0000000..8d91234
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/res/values-v7/values.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <bool name="feature_receiver_enabled">false</bool>
+    <integer name="feature_integer">321</integer>
+</resources>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/res/values/values.xml b/hostsidetests/appsecurity/test-apps/SplitApp/feature/res/values/values.xml
new file mode 100644
index 0000000..7d670cf
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/res/values/values.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <bool name="feature_receiver_enabled">true</bool>
+    <string name="feature_string">red</string>
+    <integer name="feature_integer">123</integer>
+</resources>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureActivity.java b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureActivity.java
new file mode 100644
index 0000000..a4df004
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureActivity.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.splitapp;
+
+import android.app.Activity;
+
+public class FeatureActivity extends Activity {
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureLogic.java b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureLogic.java
new file mode 100644
index 0000000..0481546
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureLogic.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.splitapp;
+
+import android.util.Log;
+
+public class FeatureLogic {
+    private static final String TAG = "FeatureLogic";
+
+    public static int mult(int a, int b) {
+        Log.d(TAG, "FeatureLogic.mult(" + a + ", " + b + ")");
+        return a * b;
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureProvider.java b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureProvider.java
new file mode 100644
index 0000000..087aeb7
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureProvider.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.splitapp;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.util.Log;
+
+import java.lang.reflect.Field;
+
+public class FeatureProvider extends ContentProvider {
+    private static final String TAG = "FeatureProvider";
+
+    public static boolean sCreated = false;
+
+    @Override
+    public boolean onCreate() {
+        Log.d(TAG, "FeatureProvider.onCreate()");
+
+        sCreated = true;
+
+        try {
+            // Just reach out and touch
+            final Class<?> test = Class.forName("com.android.cts.splitapp.SplitAppTest");
+            final Field touched = test.getDeclaredField("sFeatureTouched");
+            touched.set(null, true);
+
+            // Also make sure we can read a resource from the base; we just
+            // stash the value we saw over on the test for them to verify.
+            final Class<?> baseR = Class.forName("com.android.cts.splitapp.BaseR");
+            final int stringId = (int) baseR.getDeclaredField("my_string1").get(null);
+            final Field value = test.getDeclaredField("sFeatureValue");
+            value.set(null, getContext().getResources().getString(stringId));
+
+        } catch (Throwable t) {
+            // We're okay if anything above fails, since the test later verifies
+            // that we actually touched the boolean.
+            Log.e(TAG, "Failed to communicate back to base", t);
+        }
+
+        return true;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+            String sortOrder) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+        throw new UnsupportedOperationException();
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureR.java b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureR.java
new file mode 100644
index 0000000..3dbd83b
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureR.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.splitapp;
+
+public class FeatureR {
+    public static final int feature_receiver_enabled = R.bool.feature_receiver_enabled;
+    public static final int feature_integer = R.integer.feature_integer;
+    public static final int feature_string = R.string.feature_string;
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureReceiver.java b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureReceiver.java
new file mode 100644
index 0000000..49559f3
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureReceiver.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.splitapp;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public class FeatureReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        // Ignored
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureService.java b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureService.java
new file mode 100644
index 0000000..b07297f
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureService.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.splitapp;
+
+import android.app.IntentService;
+import android.content.Intent;
+
+public class FeatureService extends IntentService {
+    public FeatureService() {
+        super("Feature1Service");
+    }
+
+    @Override
+    protected void onHandleIntent(Intent intent) {
+        // Ignored
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/jni/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/jni/Android.mk
new file mode 100644
index 0000000..507b13a
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/jni/Android.mk
@@ -0,0 +1,26 @@
+#
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libsplitappjni
+LOCAL_SRC_FILES := com_android_cts_splitapp_Native.cpp
+
+LOCAL_LDLIBS += -llog
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/jni/Application.mk b/hostsidetests/appsecurity/test-apps/SplitApp/jni/Application.mk
new file mode 100644
index 0000000..a304c8f
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/jni/Application.mk
@@ -0,0 +1,2 @@
+APP_ABI := all
+APP_PLATFORM := android-10
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/jni/com_android_cts_splitapp_Native.cpp b/hostsidetests/appsecurity/test-apps/SplitApp/jni/com_android_cts_splitapp_Native.cpp
new file mode 100644
index 0000000..01302f5
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/jni/com_android_cts_splitapp_Native.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "SplitApp"
+
+#include <android/log.h>
+#include <stdio.h>
+
+#include "jni.h"
+
+#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
+#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
+
+
+static jint add(JNIEnv *env, jobject thiz, jint a, jint b) {
+    int result = a + b;
+    LOGI("%d + %d = %d", a, b, result);
+    return result;
+}
+
+static jstring arch(JNIEnv *env, jobject thiz) {
+    return env->NewStringUTF(__ANDROID_ARCH__);
+}
+
+static const char *classPathName = "com/android/cts/splitapp/Native";
+
+static JNINativeMethod methods[] = {
+    {"add", "(II)I", (void*)add },
+    {"arch", "()Ljava/lang/String;", (void*)arch },
+};
+
+static int registerNativeMethods(JNIEnv* env, const char* className, JNINativeMethod* gMethods, int numMethods) {
+    jclass clazz;
+
+    clazz = env->FindClass(className);
+    if (clazz == NULL) {
+        LOGE("Native registration unable to find class '%s'", className);
+        return JNI_FALSE;
+    }
+    if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
+        LOGE("RegisterNatives failed for '%s'", className);
+        return JNI_FALSE;
+    }
+
+    return JNI_TRUE;
+}
+
+static int registerNatives(JNIEnv* env) {
+    if (!registerNativeMethods(env, classPathName, methods, sizeof(methods) / sizeof(methods[0]))) {
+        return JNI_FALSE;
+    }
+
+    return JNI_TRUE;
+}
+
+typedef union {
+    JNIEnv* env;
+    void* venv;
+} UnionJNIEnvToVoid;
+
+jint JNI_OnLoad(JavaVM* vm, void* reserved) {
+    UnionJNIEnvToVoid uenv;
+    uenv.venv = NULL;
+    jint result = -1;
+    JNIEnv* env = NULL;
+
+    LOGI("JNI_OnLoad");
+
+    if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) {
+        LOGE("ERROR: GetEnv failed");
+        goto bail;
+    }
+    env = uenv.env;
+
+    if (registerNatives(env) != JNI_TRUE) {
+        LOGE("ERROR: registerNatives failed");
+        goto bail;
+    }
+
+    result = JNI_VERSION_1_4;
+
+bail:
+    return result;
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/Android.mk
new file mode 100644
index 0000000..5053e7d
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/Android.mk
@@ -0,0 +1 @@
+include $(call all-subdir-makefiles)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/Android.mk
new file mode 100644
index 0000000..543e4ac
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/Android.mk
@@ -0,0 +1,28 @@
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsSplitApp_arm64-v8a
+
+LOCAL_JAVA_RESOURCE_DIRS := raw
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/AndroidManifest.xml
new file mode 100644
index 0000000..206e207
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.cts.splitapp"
+        split="lib_arm64_v8a">
+    <application android:hasCode="false" />
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/raw/lib/arm64-v8a/libsplitappjni.so b/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/raw/lib/arm64-v8a/libsplitappjni.so
new file mode 100755
index 0000000..bcc8f51
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/raw/lib/arm64-v8a/libsplitappjni.so
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/Android.mk
new file mode 100644
index 0000000..7cdef62
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/Android.mk
@@ -0,0 +1,28 @@
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsSplitApp_armeabi-v7a
+
+LOCAL_JAVA_RESOURCE_DIRS := raw
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/AndroidManifest.xml
new file mode 100644
index 0000000..1d19420
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.cts.splitapp"
+        split="lib_armeabi_v7a">
+    <application android:hasCode="false" />
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/raw/lib/armeabi-v7a/libsplitappjni.so b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/raw/lib/armeabi-v7a/libsplitappjni.so
new file mode 100755
index 0000000..010c372
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/raw/lib/armeabi-v7a/libsplitappjni.so
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/Android.mk
new file mode 100644
index 0000000..26ec5bd
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/Android.mk
@@ -0,0 +1,28 @@
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsSplitApp_armeabi
+
+LOCAL_JAVA_RESOURCE_DIRS := raw
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/AndroidManifest.xml
new file mode 100644
index 0000000..95fdb23
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.cts.splitapp"
+        split="lib_armeabi">
+    <application android:hasCode="false" />
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/raw/lib/armeabi/libsplitappjni.so b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/raw/lib/armeabi/libsplitappjni.so
new file mode 100755
index 0000000..8977e70
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/raw/lib/armeabi/libsplitappjni.so
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/Android.mk
new file mode 100644
index 0000000..fea0603
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/Android.mk
@@ -0,0 +1,28 @@
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsSplitApp_mips
+
+LOCAL_JAVA_RESOURCE_DIRS := raw
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/AndroidManifest.xml
new file mode 100644
index 0000000..53ea38f
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.cts.splitapp"
+        split="lib_mips">
+    <application android:hasCode="false" />
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/raw/lib/mips/libsplitappjni.so b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/raw/lib/mips/libsplitappjni.so
new file mode 100755
index 0000000..45b8382
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/raw/lib/mips/libsplitappjni.so
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/Android.mk
new file mode 100644
index 0000000..3cc5609
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/Android.mk
@@ -0,0 +1,28 @@
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsSplitApp_mips64
+
+LOCAL_JAVA_RESOURCE_DIRS := raw
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/AndroidManifest.xml
new file mode 100644
index 0000000..0b75613
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.cts.splitapp"
+        split="lib_mips64">
+    <application android:hasCode="false" />
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/raw/lib/mips64/libsplitappjni.so b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/raw/lib/mips64/libsplitappjni.so
new file mode 100755
index 0000000..8c29904
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/raw/lib/mips64/libsplitappjni.so
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/Android.mk
new file mode 100644
index 0000000..d45ca8f
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/Android.mk
@@ -0,0 +1,28 @@
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsSplitApp_x86
+
+LOCAL_JAVA_RESOURCE_DIRS := raw
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/AndroidManifest.xml
new file mode 100644
index 0000000..4219791
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.cts.splitapp"
+        split="lib_x86">
+    <application android:hasCode="false" />
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/raw/lib/x86/libsplitappjni.so b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/raw/lib/x86/libsplitappjni.so
new file mode 100755
index 0000000..2993d92
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/raw/lib/x86/libsplitappjni.so
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/Android.mk
new file mode 100644
index 0000000..fa0e488
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/Android.mk
@@ -0,0 +1,28 @@
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsSplitApp_x86_64
+
+LOCAL_JAVA_RESOURCE_DIRS := raw
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/AndroidManifest.xml
new file mode 100644
index 0000000..e697d5c
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.cts.splitapp"
+        split="lib_x86_64">
+    <application android:hasCode="false" />
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/raw/lib/x86_64/libsplitappjni.so b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/raw/lib/x86_64/libsplitappjni.so
new file mode 100755
index 0000000..23f4169
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/raw/lib/x86_64/libsplitappjni.so
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/res/drawable-hdpi/image.png b/hostsidetests/appsecurity/test-apps/SplitApp/res/drawable-hdpi/image.png
new file mode 100644
index 0000000..b5f1a13
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/res/drawable-hdpi/image.png
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/res/drawable-mdpi/image.png b/hostsidetests/appsecurity/test-apps/SplitApp/res/drawable-mdpi/image.png
new file mode 100644
index 0000000..2d67c8f
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/res/drawable-mdpi/image.png
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/res/drawable-xhdpi/image.png b/hostsidetests/appsecurity/test-apps/SplitApp/res/drawable-xhdpi/image.png
new file mode 100644
index 0000000..2540371
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/res/drawable-xhdpi/image.png
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/res/drawable-xxhdpi/image.png b/hostsidetests/appsecurity/test-apps/SplitApp/res/drawable-xxhdpi/image.png
new file mode 100644
index 0000000..18a3443
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/res/drawable-xxhdpi/image.png
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/res/values-de/values.xml b/hostsidetests/appsecurity/test-apps/SplitApp/res/values-de/values.xml
new file mode 100644
index 0000000..88b6f84
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/res/values-de/values.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <string name="my_string1">blau</string>
+</resources>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/res/values-fr/values.xml b/hostsidetests/appsecurity/test-apps/SplitApp/res/values-fr/values.xml
new file mode 100644
index 0000000..c372f6a
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/res/values-fr/values.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <string name="my_string2">pourpre</string>
+</resources>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/res/values-sw600dp/values.xml b/hostsidetests/appsecurity/test-apps/SplitApp/res/values-sw600dp/values.xml
new file mode 100644
index 0000000..edf4525
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/res/values-sw600dp/values.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <dimen name="my_dimen">46dp</dimen>
+</resources>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/res/values-v7/values.xml b/hostsidetests/appsecurity/test-apps/SplitApp/res/values-v7/values.xml
new file mode 100644
index 0000000..d0a0db9
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/res/values-v7/values.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <bool name="my_receiver_enabled">true</bool>
+</resources>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/res/values/values.xml b/hostsidetests/appsecurity/test-apps/SplitApp/res/values/values.xml
new file mode 100644
index 0000000..3118fde
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/res/values/values.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <bool name="my_receiver_enabled">false</bool>
+
+    <string name="my_string1">blue</string>
+    <string name="my_string2">purple</string>
+
+    <string-array name="my_string_array">
+        <item>@string/my_string1</item>
+        <item>@string/my_string2</item>
+    </string-array>
+
+    <color name="my_color">#00FF00</color>
+    <dimen name="my_dimen">23dp</dimen>
+    <integer name="my_integer">123</integer>
+</resources>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/res/xml-v7/my_activity_meta.xml b/hostsidetests/appsecurity/test-apps/SplitApp/res/xml-v7/my_activity_meta.xml
new file mode 100644
index 0000000..50cb6ec
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/res/xml-v7/my_activity_meta.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<tag value="v7" />
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/res/xml/my_activity_meta.xml b/hostsidetests/appsecurity/test-apps/SplitApp/res/xml/my_activity_meta.xml
new file mode 100644
index 0000000..58f2a6a
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/res/xml/my_activity_meta.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<tag value="base" />
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/BaseActivity.java b/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/BaseActivity.java
new file mode 100644
index 0000000..efd1843
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/BaseActivity.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.splitapp;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TextView;
+
+public class BaseActivity extends Activity {
+    /** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        TextView tv = new TextView(this);
+        int sum = Native.add(2, 3);
+        tv.setText("2 + 3 = " + Integer.toString(sum));
+        setContentView(tv);
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/BaseR.java b/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/BaseR.java
new file mode 100644
index 0000000..ecf6975
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/BaseR.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.splitapp;
+
+public class BaseR {
+    public static final int my_string1 = R.string.my_string1;
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/Native.java b/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/Native.java
new file mode 100644
index 0000000..080053a
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/Native.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.splitapp;
+
+public class Native {
+    static {
+        System.loadLibrary("splitappjni");
+    }
+
+    public static native int add(int a, int b);
+    public static native String arch();
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/SplitAppTest.java b/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/SplitAppTest.java
new file mode 100644
index 0000000..277a1a2
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/SplitAppTest.java
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.splitapp;
+
+import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
+import static org.xmlpull.v1.XmlPullParser.START_TAG;
+
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
+import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.test.AndroidTestCase;
+import android.util.DisplayMetrics;
+import android.util.Log;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Locale;
+
+public class SplitAppTest extends AndroidTestCase {
+    private static final String TAG = "SplitAppTest";
+    private static final String PKG = "com.android.cts.splitapp";
+
+    public static boolean sFeatureTouched = false;
+    public static String sFeatureValue = null;
+
+    public void testSingleBase() throws Exception {
+        final Resources r = getContext().getResources();
+        final PackageManager pm = getContext().getPackageManager();
+
+        // Should have untouched resources from base
+        assertEquals(false, r.getBoolean(R.bool.my_receiver_enabled));
+
+        assertEquals("blue", r.getString(R.string.my_string1));
+        assertEquals("purple", r.getString(R.string.my_string2));
+
+        assertEquals(0xff00ff00, r.getColor(R.color.my_color));
+        assertEquals(123, r.getInteger(R.integer.my_integer));
+
+        assertEquals("base", getXmlTestValue(r.getXml(R.xml.my_activity_meta)));
+
+        // We know about drawable IDs, but they're stripped from base
+        try {
+            r.getDrawable(R.drawable.image);
+            fail("Unexpected drawable in base");
+        } catch (Resources.NotFoundException expected) {
+        }
+
+        // Should have base assets
+        assertAssetContents(r, "file1.txt", "FILE1");
+        assertAssetContents(r, "dir/dirfile1.txt", "DIRFILE1");
+
+        try {
+            assertAssetContents(r, "file2.txt", null);
+            fail("Unexpected asset file2");
+        } catch (IOException expected) {
+        }
+
+        // Should only have base manifest items
+        Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.addCategory(Intent.CATEGORY_LAUNCHER);
+        intent.setPackage(PKG);
+
+        List<ResolveInfo> result = pm.queryIntentActivities(intent, 0);
+        assertEquals(1, result.size());
+        assertEquals("com.android.cts.splitapp.MyActivity", result.get(0).activityInfo.name);
+
+        // Receiver disabled by default in base
+        intent = new Intent(Intent.ACTION_DATE_CHANGED);
+        intent.setPackage(PKG);
+
+        result = pm.queryBroadcastReceivers(intent, 0);
+        assertEquals(0, result.size());
+
+        // We shouldn't have any native code in base
+        try {
+            Native.add(2, 4);
+            fail("Unexpected native code in base");
+        } catch (UnsatisfiedLinkError expected) {
+        }
+    }
+
+    public void testDensitySingle() throws Exception {
+        final Resources r = getContext().getResources();
+
+        // We should still have base resources
+        assertEquals("blue", r.getString(R.string.my_string1));
+        assertEquals("purple", r.getString(R.string.my_string2));
+
+        // Now we know about drawables, but only mdpi
+        final Drawable d = r.getDrawable(R.drawable.image);
+        assertEquals(0xff7e00ff, getDrawableColor(d));
+    }
+
+    public void testDensityAll() throws Exception {
+        final Resources r = getContext().getResources();
+
+        // We should still have base resources
+        assertEquals("blue", r.getString(R.string.my_string1));
+        assertEquals("purple", r.getString(R.string.my_string2));
+
+        // Pretend that we're at each density
+        updateDpi(r, DisplayMetrics.DENSITY_MEDIUM);
+        assertEquals(0xff7e00ff, getDrawableColor(r.getDrawable(R.drawable.image)));
+
+        updateDpi(r, DisplayMetrics.DENSITY_HIGH);
+        assertEquals(0xff00fcff, getDrawableColor(r.getDrawable(R.drawable.image)));
+
+        updateDpi(r, DisplayMetrics.DENSITY_XHIGH);
+        assertEquals(0xff80ff00, getDrawableColor(r.getDrawable(R.drawable.image)));
+
+        updateDpi(r, DisplayMetrics.DENSITY_XXHIGH);
+        assertEquals(0xffff0000, getDrawableColor(r.getDrawable(R.drawable.image)));
+    }
+
+    public void testDensityBest1() throws Exception {
+        final Resources r = getContext().getResources();
+
+        // Pretend that we're really high density, but we only have mdpi installed
+        updateDpi(r, DisplayMetrics.DENSITY_XXHIGH);
+        assertEquals(0xff7e00ff, getDrawableColor(r.getDrawable(R.drawable.image)));
+    }
+
+    public void testDensityBest2() throws Exception {
+        final Resources r = getContext().getResources();
+
+        // Pretend that we're really high density, and now we have better match
+        updateDpi(r, DisplayMetrics.DENSITY_XXHIGH);
+        assertEquals(0xffff0000, getDrawableColor(r.getDrawable(R.drawable.image)));
+    }
+
+    public void testApi() throws Exception {
+        final Resources r = getContext().getResources();
+        final PackageManager pm = getContext().getPackageManager();
+
+        // We should have updated boolean, different from base
+        assertEquals(true, r.getBoolean(R.bool.my_receiver_enabled));
+
+        // Receiver should be enabled now
+        Intent intent = new Intent(Intent.ACTION_DATE_CHANGED);
+        intent.setPackage(PKG);
+
+        List<ResolveInfo> result = pm.queryBroadcastReceivers(intent, 0);
+        assertEquals(1, result.size());
+        assertEquals("com.android.cts.splitapp.MyReceiver", result.get(0).activityInfo.name);
+    }
+
+    public void testLocale() throws Exception {
+        final Resources r = getContext().getResources();
+
+        updateLocale(r, Locale.ENGLISH);
+        assertEquals("blue", r.getString(R.string.my_string1));
+        assertEquals("purple", r.getString(R.string.my_string2));
+
+        updateLocale(r, Locale.GERMAN);
+        assertEquals("blau", r.getString(R.string.my_string1));
+        assertEquals("purple", r.getString(R.string.my_string2));
+
+        updateLocale(r, Locale.FRENCH);
+        assertEquals("blue", r.getString(R.string.my_string1));
+        assertEquals("pourpre", r.getString(R.string.my_string2));
+    }
+
+    public void testNative() throws Exception {
+        Log.d(TAG, "testNative() thinks it's using ABI " + Native.arch());
+
+        // Make sure we can do the maths
+        assertEquals(11642, Native.add(4933, 6709));
+    }
+
+    public void testFeatureBase() throws Exception {
+        final Resources r = getContext().getResources();
+        final PackageManager pm = getContext().getPackageManager();
+
+        // Should have untouched resources from base
+        assertEquals(false, r.getBoolean(R.bool.my_receiver_enabled));
+
+        assertEquals("blue", r.getString(R.string.my_string1));
+        assertEquals("purple", r.getString(R.string.my_string2));
+
+        assertEquals(0xff00ff00, r.getColor(R.color.my_color));
+        assertEquals(123, r.getInteger(R.integer.my_integer));
+
+        assertEquals("base", getXmlTestValue(r.getXml(R.xml.my_activity_meta)));
+
+        // And that we can access resources from feature
+        // TODO: enable these once 17924027 is fixed
+//        assertEquals("red", r.getString(r.getIdentifier("feature_string", "string", PKG)));
+//        assertEquals(123, r.getInteger(r.getIdentifier("feature_integer", "integer", PKG)));
+
+        final Class<?> featR = Class.forName("com.android.cts.splitapp.FeatureR");
+        final int boolId = (int) featR.getDeclaredField("feature_receiver_enabled").get(null);
+        final int intId = (int) featR.getDeclaredField("feature_integer").get(null);
+        final int stringId = (int) featR.getDeclaredField("feature_string").get(null);
+        assertEquals(true, r.getBoolean(boolId));
+        assertEquals(123, r.getInteger(intId));
+        assertEquals("red", r.getString(stringId));
+
+        // Should have both base and feature assets
+        assertAssetContents(r, "file1.txt", "FILE1");
+        assertAssetContents(r, "file2.txt", "FILE2");
+        assertAssetContents(r, "dir/dirfile1.txt", "DIRFILE1");
+        assertAssetContents(r, "dir/dirfile2.txt", "DIRFILE2");
+
+        // Should have both base and feature components
+        Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.addCategory(Intent.CATEGORY_LAUNCHER);
+        intent.setPackage(PKG);
+        List<ResolveInfo> result = pm.queryIntentActivities(intent, 0);
+        assertEquals(2, result.size());
+        assertEquals("com.android.cts.splitapp.MyActivity", result.get(0).activityInfo.name);
+        assertEquals("com.android.cts.splitapp.FeatureActivity", result.get(1).activityInfo.name);
+
+        // Receiver only enabled in feature
+        intent = new Intent(Intent.ACTION_DATE_CHANGED);
+        intent.setPackage(PKG);
+        result = pm.queryBroadcastReceivers(intent, 0);
+        assertEquals(1, result.size());
+        assertEquals("com.android.cts.splitapp.FeatureReceiver", result.get(0).activityInfo.name);
+
+        // And we should have a service
+        intent = new Intent("com.android.cts.splitapp.service");
+        intent.setPackage(PKG);
+        result = pm.queryIntentServices(intent, 0);
+        assertEquals(1, result.size());
+        assertEquals("com.android.cts.splitapp.FeatureService", result.get(0).serviceInfo.name);
+
+        // And a provider too
+        ProviderInfo info = pm.resolveContentProvider("com.android.cts.splitapp.provider", 0);
+        assertEquals("com.android.cts.splitapp.FeatureProvider", info.name);
+
+        // And assert that we spun up the provider in this process
+        final Class<?> provider = Class.forName("com.android.cts.splitapp.FeatureProvider");
+        final Field field = provider.getDeclaredField("sCreated");
+        assertTrue("Expected provider to have been created", (boolean) field.get(null));
+        assertTrue("Expected provider to have touched us", sFeatureTouched);
+        assertEquals(r.getString(R.string.my_string1), sFeatureValue);
+
+        // Finally ensure that we can execute some code from split
+        final Class<?> logic = Class.forName("com.android.cts.splitapp.FeatureLogic");
+        final Method method = logic.getDeclaredMethod("mult", new Class[] {
+                Integer.TYPE, Integer.TYPE });
+        assertEquals(72, (int) method.invoke(null, 12, 6));
+
+        // Make sure we didn't get an extra flag from feature split
+        assertTrue("Someone parsed application flag!",
+                (getContext().getApplicationInfo().flags & ApplicationInfo.FLAG_LARGE_HEAP) == 0);
+
+        // Make sure we have permission from base APK
+        getContext().enforceCallingOrSelfPermission(android.Manifest.permission.CAMERA, null);
+
+        try {
+            // But no new permissions from the feature APK
+            getContext().enforceCallingOrSelfPermission(android.Manifest.permission.INTERNET, null);
+            fail("Whaaa, we somehow gained permission from feature?");
+        } catch (SecurityException expected) {
+        }
+    }
+
+    public void testFeatureApi() throws Exception {
+        final Resources r = getContext().getResources();
+        final PackageManager pm = getContext().getPackageManager();
+
+        // Should have untouched resources from base
+        assertEquals(false, r.getBoolean(R.bool.my_receiver_enabled));
+
+        // And that we can access resources from feature
+        // TODO: enable these once 17924027 is fixed
+//        assertEquals(321, r.getInteger(r.getIdentifier("feature_integer", "integer", PKG)));
+
+        final Class<?> featR = Class.forName("com.android.cts.splitapp.FeatureR");
+        final int boolId = (int) featR.getDeclaredField("feature_receiver_enabled").get(null);
+        final int intId = (int) featR.getDeclaredField("feature_integer").get(null);
+        final int stringId = (int) featR.getDeclaredField("feature_string").get(null);
+        assertEquals(false, r.getBoolean(boolId));
+        assertEquals(321, r.getInteger(intId));
+        assertEquals("red", r.getString(stringId));
+
+        // And now both receivers should be disabled
+        Intent intent = new Intent(Intent.ACTION_DATE_CHANGED);
+        intent.setPackage(PKG);
+        List<ResolveInfo> result = pm.queryBroadcastReceivers(intent, 0);
+        assertEquals(0, result.size());
+    }
+
+    private static void updateDpi(Resources r, int densityDpi) {
+        final Configuration c = new Configuration(r.getConfiguration());
+        c.densityDpi = densityDpi;
+        r.updateConfiguration(c, r.getDisplayMetrics());
+    }
+
+    private static void updateLocale(Resources r, Locale locale) {
+        final Configuration c = new Configuration(r.getConfiguration());
+        c.locale = locale;
+        r.updateConfiguration(c, r.getDisplayMetrics());
+    }
+
+    private static int getDrawableColor(Drawable d) {
+        final Bitmap bitmap = Bitmap.createBitmap(d.getIntrinsicWidth(), d.getIntrinsicHeight(),
+                Bitmap.Config.ARGB_8888);
+        final Canvas canvas = new Canvas(bitmap);
+        d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
+        d.draw(canvas);
+        return bitmap.getPixel(0, 0);
+    }
+
+    private static String getXmlTestValue(XmlPullParser in) throws XmlPullParserException,
+            IOException {
+        int type;
+        while ((type = in.next()) != END_DOCUMENT) {
+            if (type == START_TAG) {
+                final String tag = in.getName();
+                if ("tag".equals(tag)) {
+                    return in.getAttributeValue(null, "value");
+                }
+            }
+        }
+        return null;
+    }
+
+    private static void assertAssetContents(Resources r, String path, String expected)
+            throws IOException {
+        BufferedReader in = null;
+        try {
+            in = new BufferedReader(new InputStreamReader(r.getAssets().open(path)));
+            assertEquals(expected, in.readLine());
+        } finally {
+            if (in != null) in.close();
+        }
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/LockTaskTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/LockTaskTest.java
index c0ca8e2..42aa847 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/LockTaskTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/LockTaskTest.java
@@ -30,6 +30,9 @@
 
     private static final String TEST_PACKAGE = "com.google.android.example.somepackage";
 
+    private static final int ACTIVITY_RESUMED_TIMEOUT_MILLIS = 60000;  // 60 seconds
+    private static final int ACTIVITY_RUNNING_TIMEOUT_MILLIS = 20000;  // 20 seconds
+
     /**
      * The tests below need to keep detailed track of the state of the activity
      * that is started and stopped frequently.  To do this it sends a number of
@@ -139,52 +142,49 @@
     // This test has the UtilityActivity trigger starting another activity (settings)
     // this should be permitted as a part of lock task (since it isn't a new task).
     // As a result onPause should be called as it goes to a new activity.
-// TODO: Reinstate once we make this test not flaky (if fails on Nexus 7 v2 most of the time,
-//       especially if testCannotStartActivityOutsideTask() is commented out.
-//    public void testStartActivityWithinTask() {
-//        mDevicePolicyManager.setLockTaskPackages(getWho(), new String[] { PACKAGE_NAME });
-//        startLockTask();
-//        waitForResume();
-//
-//        Intent launchIntent = new Intent(Settings.ACTION_SETTINGS);
-//        Intent lockTaskUtility = getLockTaskUtility();
-//        lockTaskUtility.putExtra(LockTaskUtilityActivity.START_ACTIVITY, launchIntent);
-//        mContext.startActivity(lockTaskUtility);
-//
-//        synchronized (mActivityResumedLock) {
-//            if (mIsActivityResumed) {
-//                try {
-//                    mActivityResumedLock.wait(60000);
-//                } catch (InterruptedException e) {
-//                }
-//                assertFalse(mIsActivityResumed);
-//            }
-//        }
-//        stopAndFinish(null);
-//    }
+    public void testStartActivityWithinTask() {
+        mDevicePolicyManager.setLockTaskPackages(getWho(), new String[] { PACKAGE_NAME });
+        startLockTask();
+        waitForResume();
+
+        Intent launchIntent = new Intent(Settings.ACTION_SETTINGS);
+        Intent lockTaskUtility = getLockTaskUtility();
+        lockTaskUtility.putExtra(LockTaskUtilityActivity.START_ACTIVITY, launchIntent);
+        mContext.startActivity(lockTaskUtility);
+
+        synchronized (mActivityResumedLock) {
+            if (mIsActivityResumed) {
+                try {
+                    mActivityResumedLock.wait(ACTIVITY_RESUMED_TIMEOUT_MILLIS);
+                } catch (InterruptedException e) {
+                }
+                assertFalse(mIsActivityResumed);
+            }
+        }
+        stopAndFinish(null);
+    }
 
     // This launches an activity that is not part of the current task and therefore
     // should be blocked.  This is verified by making sure that the activity does
     // not get a call to onPause.
-// TODO: Reinstate once we make this test not flaky (if fails on Nexus 7 v2 most of the time) 
-//    public void testCannotStartActivityOutsideTask() {
-//        mDevicePolicyManager.setLockTaskPackages(getWho(), new String[] { PACKAGE_NAME });
-//        startLockTask();
-//        waitForResume();
-//
-//        Intent launchIntent = new Intent(Settings.ACTION_SETTINGS);
-//        launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-//        mContext.startActivity(launchIntent);
-//
-//        synchronized (mActivityResumedLock) {
-//            try {
-//                mActivityResumedLock.wait(90000);
-//            } catch (InterruptedException e) {
-//            }
-//            assertTrue(mIsActivityResumed);
-//        }
-//        stopAndFinish(null);
-//    }
+    public void testCannotStartActivityOutsideTask() {
+        mDevicePolicyManager.setLockTaskPackages(getWho(), new String[] { PACKAGE_NAME });
+        startLockTask();
+        waitForResume();
+
+        Intent launchIntent = new Intent(Settings.ACTION_SETTINGS);
+        launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mContext.startActivity(launchIntent);
+
+        synchronized (mActivityResumedLock) {
+            try {
+                mActivityResumedLock.wait(ACTIVITY_RESUMED_TIMEOUT_MILLIS);
+            } catch (InterruptedException e) {
+            }
+            assertTrue(mIsActivityResumed);
+        }
+        stopAndFinish(null);
+    }
 
     /**
      * Call stopLockTask and finish on the LockTaskUtilityActivity.
@@ -212,7 +212,7 @@
             finish();
             if (mIsActivityRunning) {
                 try {
-                    mActivityRunningLock.wait(20000);
+                    mActivityRunningLock.wait(ACTIVITY_RUNNING_TIMEOUT_MILLIS);
                 } catch (InterruptedException e) {
                 }
             }
@@ -227,7 +227,7 @@
         synchronized (mActivityResumedLock) {
             if (!mIsActivityResumed) {
                 try {
-                    mActivityResumedLock.wait(20000);
+                    mActivityResumedLock.wait(ACTIVITY_RESUMED_TIMEOUT_MILLIS);
                 } catch (InterruptedException e) {
                 }
             }
@@ -272,7 +272,7 @@
             mContext.startActivity(intent);
             // Give 20 secs to finish.
             try {
-                wait(20000);
+                wait(ACTIVITY_RUNNING_TIMEOUT_MILLIS);
             } catch (InterruptedException e) {
             }
             assertTrue(mIntentHandled);
diff --git a/hostsidetests/devicepolicy/app/IntentReceiver/AndroidManifest.xml b/hostsidetests/devicepolicy/app/IntentReceiver/AndroidManifest.xml
index ab01ffb..e1f6886 100644
--- a/hostsidetests/devicepolicy/app/IntentReceiver/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/IntentReceiver/AndroidManifest.xml
@@ -19,11 +19,14 @@
 
     <uses-sdk android:minSdkVersion="19"/>
 
+    <uses-permission android:name="com.android.cts.managedprofile.permission.SAMPLE"/>
+
     <application>
         <activity android:name="com.android.cts.intent.receiver.IntentReceiverActivity">
             <intent-filter>
                 <action android:name="com.android.cts.action.READ_FROM_URI" />
                 <action android:name="com.android.cts.action.WRITE_TO_URI" />
+                <action android:name="com.android.cts.action.TAKE_PERSISTABLE_URI_PERMISSION" />
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
         </activity>
diff --git a/hostsidetests/devicepolicy/app/IntentReceiver/src/com/android/cts/intent/receiver/IntentReceiverActivity.java b/hostsidetests/devicepolicy/app/IntentReceiver/src/com/android/cts/intent/receiver/IntentReceiverActivity.java
index 2389402..17dc3f1 100644
--- a/hostsidetests/devicepolicy/app/IntentReceiver/src/com/android/cts/intent/receiver/IntentReceiverActivity.java
+++ b/hostsidetests/devicepolicy/app/IntentReceiver/src/com/android/cts/intent/receiver/IntentReceiverActivity.java
@@ -40,24 +40,48 @@
 
     private static final String ACTION_WRITE_TO_URI = "com.android.cts.action.WRITE_TO_URI";
 
+    private static final String ACTION_TAKE_PERSISTABLE_URI_PERMISSION =
+            "com.android.cts.action.TAKE_PERSISTABLE_URI_PERMISSION";
+
+    private static final String EXTRA_CAUGHT_SECURITY_EXCEPTION = "extra_caught_security_exception";
+
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         Intent received = getIntent();
         String action = received.getAction();
-
+        Uri uri = getIntent().getClipData().getItemAt(0).getUri();
         if (ACTION_READ_FROM_URI.equals(action)) {
             Intent result = new Intent();
-            String message = getFirstLineFromUri(getIntent().getClipData().getItemAt(0).getUri());
-            Log.i(TAG, "message received in reading test: " + message);
+            String message = null;
+            try {
+                message = getFirstLineFromUri(uri);
+            } catch (SecurityException e) {
+                Log.i(TAG, "Caught a SecurityException while trying to read " + uri, e);
+                result.putExtra(EXTRA_CAUGHT_SECURITY_EXCEPTION, true);
+            } catch (IOException e) {
+                Log.i(TAG, "Caught a IOException while trying to read " + uri, e);
+            }
+            Log.i(TAG, "Message received in reading test: " + message);
             result.putExtra("extra_response", message);
-            setResult(message != null ? Activity.RESULT_OK : Activity.RESULT_CANCELED, result);
+            setResult(Activity.RESULT_OK, result);
         } else if (ACTION_WRITE_TO_URI.equals(action)) {
             Intent result = new Intent();
             String message = received.getStringExtra("extra_message");
-            Log.i(TAG, "message received in writing test: " + message);
-            Uri uri = getIntent().getClipData().getItemAt(0).getUri();
-            boolean succeded = writeToUri(uri, message);
-            setResult(succeded ? Activity.RESULT_OK : Activity.RESULT_CANCELED);
+            Log.i(TAG, "Message received in writing test: " + message);
+            try {
+                writeToUri(uri, message);
+            } catch (SecurityException e) {
+                Log.i(TAG, "Caught a SecurityException while trying to write to " + uri, e);
+                result.putExtra(EXTRA_CAUGHT_SECURITY_EXCEPTION, true);
+            } catch (IOException e) {
+                Log.i(TAG, "Caught a IOException while trying to write to " + uri, e);
+            }
+            setResult(Activity.RESULT_OK, result);
+        } else if (ACTION_TAKE_PERSISTABLE_URI_PERMISSION.equals(action)) {
+            Log.i(TAG, "Taking persistable uri permission to " + uri);
+            getContentResolver().takePersistableUriPermission(uri,
+                    Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            setResult(Activity.RESULT_OK);
         }
         finish();
     }
@@ -65,28 +89,17 @@
     /**
      * Returns the first line of the file associated with uri.
      */
-    private String getFirstLineFromUri(Uri uri) {
-        try {
-            InputStream is = getContentResolver().openInputStream(uri);
-            BufferedReader r = new BufferedReader(new InputStreamReader(is));
-            return r.readLine();
-        } catch (IOException e) {
-            Log.e(TAG, "could not read the uri " + uri, e);
-            return null;
-        }
+    private String getFirstLineFromUri(Uri uri) throws IOException {
+        InputStream is = getContentResolver().openInputStream(uri);
+        BufferedReader r = new BufferedReader(new InputStreamReader(is));
+        return r.readLine();
     }
 
-    private boolean writeToUri(Uri uri, String text) {
-        try {
-            OutputStreamWriter writer = new OutputStreamWriter(
-                    getContentResolver().openOutputStream(uri));
-            writer.write(text);
-            writer.flush();
-            writer.close();
-            return true;
-        } catch (IOException e) {
-            Log.e(TAG, "could not write to the uri " + uri, e);
-            return false;
-        }
+    private void writeToUri(Uri uri, String text) throws IOException {
+        OutputStreamWriter writer = new OutputStreamWriter(
+                getContentResolver().openOutputStream(uri));
+        writer.write(text);
+        writer.flush();
+        writer.close();
     }
 }
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
index 643400b..56b3671 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
@@ -19,6 +19,9 @@
 
     <uses-sdk android:minSdkVersion="20"/>
 
+    <permission android:name="com.android.cts.managedprofile.permission.SAMPLE"
+                android:label="Sample Permission"/>
+
     <application>
         <uses-library android:name="android.test.runner" />
         <receiver
@@ -67,6 +70,13 @@
                 <action android:name="android.intent.action.MAIN"/>
             </intent-filter>
         </activity>
+        <activity android:name=".UserRestrictionActivity" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+        </activity>
+        <activity android:name=".TestActivity" />
         <provider
             android:name="android.support.v4.content.FileProvider"
             android:authorities="com.android.cts.managedprofile.fileprovider"
@@ -76,7 +86,13 @@
                 android:name="android.support.FILE_PROVIDER_PATHS"
                 android:resource="@xml/filepaths" />
         </provider>
-        <activity android:name=".TestActivity" />
+        <provider
+            android:name="com.android.cts.managedprofile.crossprofilecontent.BasicContentProvider"
+            android:authorities="com.android.cts.managedprofile.basiccontentProvider"
+            android:grantUriPermissions="true"
+            android:exported="true"
+            android:permission="com.android.cts.managedprofile.permission.SAMPLE"
+            />
     </application>
 
     <instrumentation android:name="android.test.InstrumentationTestRunner"
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/UserRestrictionActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/UserRestrictionActivity.java
new file mode 100644
index 0000000..e8decf8
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/UserRestrictionActivity.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.managedprofile;
+
+import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Process;
+import android.util.Log;
+
+import com.android.cts.managedprofile.BaseManagedProfileTest;
+
+/**
+ * Simple activity that adds or clears a user restriction depending on the value of the extras.
+ */
+public class UserRestrictionActivity extends Activity {
+
+    private static final String TAG = UserRestrictionActivity.class.getName();
+
+    private static final String EXTRA_RESTRICTION_KEY = "extra-restriction-key";
+    private static final String EXTRA_COMMAND = "extra-command";
+
+    private static final String ADD_COMMAND = "add-restriction";
+    private static final String CLEAR_COMMAND = "clear-restriction";
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        handleIntent(getIntent());
+    }
+
+    // Overriding this method in case another intent is sent to this activity before finish()
+    @Override
+    public void onNewIntent(Intent intent) {
+        super.onNewIntent(intent);
+        handleIntent(intent);
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        // Calling finish() here because doing it in onCreate(), onStart() or onResume() makes
+        // "adb shell am start" timeout if using the -W option.
+        finish();
+    }
+
+    private void handleIntent(Intent intent) {
+        DevicePolicyManager dpm = (DevicePolicyManager)
+                getSystemService(Context.DEVICE_POLICY_SERVICE);
+        String restrictionKey = intent.getStringExtra(EXTRA_RESTRICTION_KEY);
+        String command = intent.getStringExtra(EXTRA_COMMAND);
+        Log.i(TAG, "Command: \"" + command + "\". Restriction: \"" + restrictionKey + "\"");
+
+        if (ADD_COMMAND.equals(command)) {
+            dpm.addUserRestriction(BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT, restrictionKey);
+            Log.i(TAG, "Added user restriction " + restrictionKey
+                    + " for user " + Process.myUserHandle());
+        } else if (CLEAR_COMMAND.equals(command)) {
+            dpm.clearUserRestriction(
+                    BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT, restrictionKey);
+            Log.i(TAG, "Cleared user restriction " + restrictionKey
+                    + " for user " + Process.myUserHandle());
+        } else {
+            Log.e(TAG, "Invalid command: " + command);
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/BasicContentProvider.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/BasicContentProvider.java
new file mode 100644
index 0000000..f91d404
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/BasicContentProvider.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.managedprofile.crossprofilecontent;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+/**
+ * Empty content provider, all permissions are enforced in manifest
+ */
+public class BasicContentProvider extends ContentProvider {
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        // do nothing
+        return 0;
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        return "";
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        return null;
+    }
+
+    @Override
+    public boolean onCreate() {
+        return false;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection,
+            String[] selectionArgs, String sortOrder) {
+        return null;
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection,
+            String[] selectionArgs) {
+        return 0;
+    }
+
+    @Override
+    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+        return ParcelFileDescriptor.open(
+                new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
+    }
+}
+
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/CrossProfileContentTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/CrossProfileContentTest.java
index aa9506b..85e7d1b 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/CrossProfileContentTest.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/CrossProfileContentTest.java
@@ -18,33 +18,194 @@
 import static com.android.cts.managedprofile.BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT;
 
 import android.app.admin.DevicePolicyManager;
+import android.content.ClipData;
+import android.content.ContentResolver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+import android.support.v4.content.FileProvider;
 import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
 
 public class CrossProfileContentTest extends
         ActivityInstrumentationTestCase2<IntentSenderActivity> {
 
     private static final String MESSAGE = "Sample Message";
 
+    private static final String ACTION_READ_FROM_URI = "com.android.cts.action.READ_FROM_URI";
+
+    private static final String ACTION_WRITE_TO_URI = "com.android.cts.action.WRITE_TO_URI";
+
+    private static final String ACTION_TAKE_PERSISTABLE_URI_PERMISSION =
+            "com.android.cts.action.TAKE_PERSISTABLE_URI_PERMISSION";
+
+    private static final String TAG = "CrossProfileContentTest";
+
+    private static final String BASIC_CONTENT_PROVIDER_AUTHORITY =
+            "com.android.cts.managedprofile.basiccontentProvider";
+
+
+    private DevicePolicyManager mDpm;
+
+    private Context mContext;
+
     public CrossProfileContentTest() {
         super(IntentSenderActivity.class);
     }
 
     @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mContext = getInstrumentation().getTargetContext();
+        mDpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(ACTION_READ_FROM_URI);
+        intentFilter.addAction(ACTION_WRITE_TO_URI);
+        intentFilter.addAction(ACTION_TAKE_PERSISTABLE_URI_PERMISSION);
+        mDpm.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT, intentFilter,
+                DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED);
+    }
+
+    @Override
     protected void tearDown() throws Exception {
-        DevicePolicyManager dpm = (DevicePolicyManager)
-               getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE);
-        dpm.clearCrossProfileIntentFilters(ADMIN_RECEIVER_COMPONENT);
+        mDpm.clearCrossProfileIntentFilters(ADMIN_RECEIVER_COMPONENT);
         super.tearDown();
     }
 
+    /**
+     * This method will send an intent to a receiver in another profile.
+     * This intent will have, in the ClipData, a uri whose associated file stores a message.
+     * The receiver will read the message from the uri, and put it inside the result intent.
+     */
     public void testReceiverCanRead() {
-        String response = getActivity().testReceiverCanRead(MESSAGE);
-        assertEquals(response, MESSAGE);
+        Uri uri = getUriWithTextInFile("reading_test", MESSAGE);
+        assertTrue(uri != null);
+        Intent intent = new Intent(ACTION_READ_FROM_URI);
+        intent.setClipData(ClipData.newRawUri("", uri));
+        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        Intent result = getActivity().getResultForIntent(intent);
+        assertTrue(result != null);
+        assertEquals(MESSAGE, result.getStringExtra("extra_response"));
     }
 
+    /**
+     * This method will send an intent to a receiver in another profile.
+     * This intent will have a message in an extra, and a uri specified by the ClipData.
+     * The receiver will read the message from the extra, and write it to the uri in
+     * the ClipData.
+     */
     public void testReceiverCanWrite() {
-        String response = getActivity().testReceiverCanWrite(MESSAGE);
-        assertEquals(response, MESSAGE);
+        // It's the receiver of the intent that should write to the uri, not us. So, for now, we
+        // write an empty string.
+        Uri uri = getUriWithTextInFile("writing_test", "");
+        assertTrue(uri != null);
+        Intent intent = new Intent(ACTION_WRITE_TO_URI);
+        intent.setClipData(ClipData.newRawUri("", uri));
+        intent.putExtra("extra_message", MESSAGE);
+        intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+                | Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        getActivity().getResultForIntent(intent);
+        assertEquals(MESSAGE, getFirstLineFromUri(uri));
+    }
+
+    public void testPersistablePermission() {
+        Uri uri = getUriWithTextInFile("persistable_test", MESSAGE);
+        grantPersistableReadPermission(uri);
+
+        // Now checking if the receiver can read this uri, without re-granting the read permission.
+        Intent intent = new Intent(ACTION_READ_FROM_URI);
+        intent.setClipData(ClipData.newRawUri("", uri));
+        Intent result = getActivity().getResultForIntent(intent);
+        assertTrue(result != null);
+        assertEquals(MESSAGE, result.getStringExtra("extra_response"));
+    }
+
+    /**
+     * The intent receiver will try to read uriNotGranted.
+     * Inside the same user, this uri can be read if the receiver has the
+     * com.android.cts.managedprofile.permission.SAMPLE permission. But since we cross
+     * user-boundaries, it should not be able to (only uri grants work accross users for apps
+     * without special permission).
+     * We also grant uriGranted to the receiver (this uri belongs to the same content provider as
+     * uriNotGranted), to enforce that even if an app has permission to one uri of a
+     * ContentProvider, it still cannot access a uri it does not have access to.
+     */
+    public void testAppPermissionsDontWorkAcrossProfiles() {
+        // The FileProvider does not allow to use app permissions. So we need to use another
+        // ContentProvider.
+        Uri uriGranted = getBasicContentProviderUri("uri_granted");
+        Uri uriNotGranted = getBasicContentProviderUri("uri_not_granted");
+
+        // Granting uriGranted to the receiver
+        // Using a persistable permission so that it is kept even after we restart the receiver
+        // activity with another intent.
+        grantPersistableReadPermission(uriGranted);
+
+        Intent notGrant = new Intent(ACTION_READ_FROM_URI);
+        notGrant.setClipData(ClipData.newRawUri("", uriNotGranted));
+
+        Intent result = getActivity().getResultForIntent(notGrant);
+        assertTrue(result != null);
+        // The receiver did not have permission to read the uri. So it should have caught a security
+        // exception.
+        assertTrue(result.getBooleanExtra("extra_caught_security_exception", false));
+    }
+
+    private void grantPersistableReadPermission(Uri uri) {
+        Intent grantPersistable = new Intent(ACTION_TAKE_PERSISTABLE_URI_PERMISSION);
+        grantPersistable.setClipData(ClipData.newRawUri("", uri));
+        grantPersistable.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
+        getActivity().getResultForIntent(grantPersistable);
+    }
+
+    private Uri getBasicContentProviderUri(String path) {
+        // The uris created here are not associated with any data. But this does not prevent us from
+        // granting these uris to other apps, or these apps from trying to access these uris.
+        return new Uri.Builder()
+                .scheme(ContentResolver.SCHEME_CONTENT)
+                .authority(BASIC_CONTENT_PROVIDER_AUTHORITY)
+                .path(path)
+                .build();
+    }
+
+    private Uri getUriWithTextInFile(String name, String text) {
+        String filename = mContext.getFilesDir() + File.separator + "texts" + File.separator
+                + name + ".txt";
+        Log.i(TAG, "Creating file " + filename + " with text \"" + text + "\"");
+        final File file = new File(filename);
+        file.getParentFile().mkdirs(); // If the folder doesn't exists it is created
+        try {
+            FileWriter writer = new FileWriter(file);
+            writer.write(text);
+            writer.close();
+        } catch(IOException e) {
+            Log.e(TAG, "Could not create file " + filename + " with text " + text);
+            return null;
+        }
+        return FileProvider.getUriForFile(mContext, "com.android.cts.managedprofile.fileprovider",
+                file);
+    }
+
+    /**
+     * Returns the first line of the file associated with uri.
+     */
+    private String getFirstLineFromUri(Uri uri) {
+        try {
+            InputStream is = mContext.getContentResolver().openInputStream(uri);
+            BufferedReader r = new BufferedReader(new InputStreamReader(is));
+            return r.readLine();
+        } catch (IOException e) {
+            Log.e(TAG, "could not read the uri " + uri);
+            return null;
+        }
     }
 }
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/IntentSenderActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/IntentSenderActivity.java
index 6c8020f..e4c8ddf 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/IntentSenderActivity.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/IntentSenderActivity.java
@@ -17,152 +17,36 @@
 
 import static com.android.cts.managedprofile.BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT;
 
-import android.app.admin.DevicePolicyManager;
 import android.app.Activity;
-import android.content.ClipData;
-import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.Uri;
-import android.os.Bundle;
 import android.util.Log;
-import android.support.v4.content.FileProvider;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileWriter;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.IOException;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
 public class IntentSenderActivity extends Activity {
 
-    private final static String TAG = "IntentSenderActivity";
-
-    private final CountDownLatch mLatch = new CountDownLatch(1);
-
-    private static final String ACTION_READ_FROM_URI = "com.android.cts.action.READ_FROM_URI";
-
-    private static final String ACTION_WRITE_TO_URI = "com.android.cts.action.WRITE_TO_URI";
-
-    private static final int TEST_RECEIVER_CAN_READ = 1;
-    private static final int TEST_RECEIVER_CAN_WRITE = 2;
+    private CountDownLatch mLatch;
 
     private static final int WAIT_FOR_RESPONSE_TIMEOUT_SECONDS = 5;
 
-    private String mResponse;
+    private Intent mResult;
 
-    private Uri mUriToWrite;
-
-    private DevicePolicyManager mDevicePolicyManager;
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        mDevicePolicyManager = (DevicePolicyManager)
-                getSystemService(Context.DEVICE_POLICY_SERVICE);
-    }
-
-    /**
-     * This method will send an intent to a receiver in another profile.
-     * This intent will have, in the ClipData, a uri whose associated file stores this message.
-     * The receiver will read the message from the uri, and put it inside the result intent.
-     * This method returns the response in the result intent, or null if no response was received.
-     */
-    String testReceiverCanRead(String message) {
-        IntentFilter testIntentFilter = new IntentFilter();
-        testIntentFilter.addAction(ACTION_READ_FROM_URI);
-        mDevicePolicyManager.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT, testIntentFilter,
-                DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED);
-
-        Intent intent = new Intent(ACTION_READ_FROM_URI);
-        intent.setClipData(ClipData.newRawUri("", getUriWithTextInFile("reading_test", message)));
-        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-        startActivityForResult(intent, TEST_RECEIVER_CAN_READ);
+    Intent getResultForIntent(Intent intent) {
+        mLatch = new CountDownLatch(1);
+        mResult = null;
+        startActivityForResult(intent, 0);
         try {
             mLatch.await(WAIT_FOR_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
         } catch (InterruptedException e) {
-            return null;
         }
-        return mResponse;
-    }
-
-    /**
-     * This method will send an intent to a receiver in another profile.
-     * This intent will have a message in an extra, and a uri specified by the ClipData.
-     * The receiver will read the message from the extra, and write it to the uri in
-     * the ClipData.
-     * This method returns what has been written in the uri.
-     */
-    String testReceiverCanWrite(String message) {
-        IntentFilter testIntentFilter = new IntentFilter();
-        testIntentFilter.addAction(ACTION_WRITE_TO_URI);
-        mDevicePolicyManager.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT, testIntentFilter,
-                DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED);
-        // It's the receiver of the intent that should write to the uri, not us. So, for now, we
-        // write an empty string.
-        mUriToWrite = getUriWithTextInFile("writing_test", "");
-        Intent intent = new Intent(ACTION_WRITE_TO_URI);
-        intent.setClipData(ClipData.newRawUri("", mUriToWrite));
-        intent.putExtra("extra_message", message);
-        intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION
-                | Intent.FLAG_GRANT_READ_URI_PERMISSION);
-        startActivityForResult(intent, TEST_RECEIVER_CAN_WRITE);
-        try {
-            mLatch.await(WAIT_FOR_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
-        } catch (InterruptedException e) {
-            return null;
-        }
-        return mResponse;
+        return mResult;
     }
 
     @Override
-    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-        if (requestCode == TEST_RECEIVER_CAN_READ) {
-            if (resultCode == Activity.RESULT_OK) {
-                mResponse = data.getStringExtra("extra_response");
-                Log.i(TAG, "response received in reading test: " + mResponse);
-            }
-        } else if (requestCode == TEST_RECEIVER_CAN_WRITE) {
-            if (resultCode == Activity.RESULT_OK) {
-                mResponse = getFirstLineFromUri(mUriToWrite);
-                Log.i(TAG, "response received in writing test: " + mResponse);
-            }
+    protected void onActivityResult(int requestCode, int resultCode, Intent result) {
+        if (resultCode == Activity.RESULT_OK) {
+            mResult = result;
         }
         mLatch.countDown();
-        finish();
-    }
-
-    private Uri getUriWithTextInFile(String name, String text) {
-        String filename = getFilesDir() + File.separator + "texts" + File.separator + name + ".txt";
-        Log.i(TAG, "Creating file " + filename + " with text \"" + text + "\"");
-        final File file = new File(filename);
-        file.getParentFile().mkdirs(); // If the folder doesn't exists it is created
-        try {
-            FileWriter writer = new FileWriter(file);
-            writer.write(text);
-            writer.close();
-        } catch(IOException e) {
-            Log.e(TAG, "Could not create file " + filename + " with text " + text);
-            return null;
-        }
-        return FileProvider.getUriForFile(this,
-                "com.android.cts.managedprofile.fileprovider", file);
-    }
-
-    /**
-     * Returns the first line of the file associated with uri.
-     */
-    private String getFirstLineFromUri(Uri uri) {
-        try {
-            InputStream is = getContentResolver().openInputStream(uri);
-            BufferedReader r = new BufferedReader(new InputStreamReader(is));
-            return r.readLine();
-        } catch (IOException e) {
-            Log.e(TAG, "could not read the uri " + uri);
-            return null;
-        }
     }
 }
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
index 4e57b28..88a3b70 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
@@ -124,16 +124,55 @@
         }
     }
 
+    // TODO: This test is not specific to managed profiles, but applies to multi-user in general.
+    // Move it to a MultiUserTest class when there is one. Should probably move
+    // UserRestrictionActivity to a more generic apk too as it might be useful for different kinds
+    // of tests (same applies to ComponentDisablingActivity).
+    public void testNoDebuggingFeaturesRestriction() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        String restriction = "no_debugging_features";  // UserManager.DISALLOW_DEBUGGING_FEATURES
+        String command = "add-restriction";
+
+        String addRestrictionCommandOutput =
+                changeUserRestrictionForUser(restriction, command, mUserId);
+        assertTrue("Command was expected to succeed " + addRestrictionCommandOutput,
+                addRestrictionCommandOutput.contains("Status: ok"));
+
+        // This should now fail, as the shell is not available to start activities under a different
+        // user once the restriction is in place.
+        addRestrictionCommandOutput =
+                changeUserRestrictionForUser(restriction, command, mUserId);
+        assertTrue(
+                "Expected SecurityException when starting the activity "
+                        + addRestrictionCommandOutput,
+                addRestrictionCommandOutput.contains("SecurityException"));
+    }
+
     private void disableActivityForUser(String activityName, int userId)
             throws DeviceNotAvailableException {
         String command = "am start -W --user " + userId
                 + " --es extra-package " + MANAGED_PROFILE_PKG
-                + " --es extra-class-name " + MANAGED_PROFILE_PKG + "." + activityName + " "
-                + MANAGED_PROFILE_PKG + "/.ComponentDisablingActivity ";
+                + " --es extra-class-name " + MANAGED_PROFILE_PKG + "." + activityName
+                + " " + MANAGED_PROFILE_PKG + "/.ComponentDisablingActivity ";
         CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": "
                 + getDevice().executeShellCommand(command));
     }
 
+    private String changeUserRestrictionForUser(String key, String command, int userId)
+            throws DeviceNotAvailableException {
+        String adbCommand = "am start -W --user " + userId
+                + " -c android.intent.category.DEFAULT "
+                + " --es extra-command " + command
+                + " --es extra-restriction-key " + key
+                + " " + MANAGED_PROFILE_PKG + "/.UserRestrictionActivity";
+        String commandOutput = getDevice().executeShellCommand(adbCommand);
+        CLog.logAndDisplay(LogLevel.INFO,
+                "Output for command " + adbCommand + ": " + commandOutput);
+        return commandOutput;
+    }
+
     private int createManagedProfile() throws DeviceNotAvailableException {
         String command =
                 "pm create-user --profileOf 0 --managed TestProfile_" + System.currentTimeMillis();
diff --git a/libs/deviceutil/Android.mk b/libs/deviceutil/Android.mk
index d5a2c57..8c81ee4 100644
--- a/libs/deviceutil/Android.mk
+++ b/libs/deviceutil/Android.mk
@@ -29,3 +29,5 @@
 LOCAL_SDK_VERSION := current
 
 include $(BUILD_STATIC_JAVA_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libs/deviceutil/jni/Android.mk b/libs/deviceutil/jni/Android.mk
new file mode 100644
index 0000000..b801a4d
--- /dev/null
+++ b/libs/deviceutil/jni/Android.mk
@@ -0,0 +1,32 @@
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 := libcts_jni
+
+# Don't include this package in any configuration by default.
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := \
+		CtsJniOnLoad.cpp \
+		android_cts_FileUtils.cpp
+
+LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
+
+LOCAL_SHARED_LIBRARIES := libnativehelper liblog libdl
+
+include $(BUILD_SHARED_LIBRARY)
\ No newline at end of file
diff --git a/libs/deviceutil/jni/CtsJniOnLoad.cpp b/libs/deviceutil/jni/CtsJniOnLoad.cpp
new file mode 100644
index 0000000..abf8e01
--- /dev/null
+++ b/libs/deviceutil/jni/CtsJniOnLoad.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <stdio.h>
+
+extern int register_android_cts_FileUtils(JNIEnv*);
+
+jint JNI_OnLoad(JavaVM *vm, void *reserved) {
+    JNIEnv *env = NULL;
+
+    if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
+        return JNI_ERR;
+    }
+
+    if (register_android_cts_FileUtils(env)) {
+      return JNI_ERR;
+    }
+
+    return JNI_VERSION_1_4;
+}
diff --git a/tests/tests/security/jni/android_security_cts_FileUtils.cpp b/libs/deviceutil/jni/android_cts_FileUtils.cpp
similarity index 80%
rename from tests/tests/security/jni/android_security_cts_FileUtils.cpp
rename to libs/deviceutil/jni/android_cts_FileUtils.cpp
index 8009c04..91b74bf 100644
--- a/tests/tests/security/jni/android_security_cts_FileUtils.cpp
+++ b/libs/deviceutil/jni/android_cts_FileUtils.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2011 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -40,12 +40,12 @@
 
 /*
  * Native methods used by
- * cts/tests/src/android/security/cts/FileUtils.java
+ * cts/libs/deviceutil/src/android/cts/util/FileUtils.java
  *
- * Copied from hidden API: frameworks/base/core/jni/android_security_FileUtils.cpp
+ * Copied from hidden API: frameworks/base/core/jni/android_FileUtils.cpp
  */
 
-jboolean android_security_cts_FileUtils_getFileStatus(JNIEnv* env, jobject thiz,
+jboolean android_cts_FileUtils_getFileStatus(JNIEnv* env, jobject thiz,
         jstring path, jobject fileStatus, jboolean statLinks)
 {
     const char* pathStr = env->GetStringUTFChars(path, NULL);
@@ -77,21 +77,21 @@
     return ret;
 }
 
-jstring android_security_cts_FileUtils_getUserName(JNIEnv* env, jobject thiz,
+jstring android_cts_FileUtils_getUserName(JNIEnv* env, jobject thiz,
         jint uid)
 {
     struct passwd *pwd = getpwuid(uid);
     return env->NewStringUTF(pwd->pw_name);
 }
 
-jstring android_security_cts_FileUtils_getGroupName(JNIEnv* env, jobject thiz,
+jstring android_cts_FileUtils_getGroupName(JNIEnv* env, jobject thiz,
         jint gid)
 {
     struct group *grp = getgrgid(gid);
     return env->NewStringUTF(grp->gr_name);
 }
 
-jint android_security_cts_FileUtils_setPermissions(JNIEnv* env, jobject clazz,
+jint android_cts_FileUtils_setPermissions(JNIEnv* env, jobject clazz,
         jstring file, jint mode)
 {
     const char *fileStr = env->GetStringUTFChars(file, NULL);
@@ -110,22 +110,22 @@
 }
 
 static JNINativeMethod gMethods[] = {
-    {  "getFileStatus", "(Ljava/lang/String;Landroid/security/cts/FileUtils$FileStatus;Z)Z",
-            (void *) android_security_cts_FileUtils_getFileStatus  },
+    {  "getFileStatus", "(Ljava/lang/String;Landroid/cts/util/FileUtils$FileStatus;Z)Z",
+            (void *) android_cts_FileUtils_getFileStatus  },
     {  "getUserName", "(I)Ljava/lang/String;",
-            (void *) android_security_cts_FileUtils_getUserName  },
+            (void *) android_cts_FileUtils_getUserName  },
     {  "getGroupName", "(I)Ljava/lang/String;",
-            (void *) android_security_cts_FileUtils_getGroupName  },
+            (void *) android_cts_FileUtils_getGroupName  },
     {  "setPermissions", "(Ljava/lang/String;I)I",
-            (void *) android_security_cts_FileUtils_setPermissions },
+            (void *) android_cts_FileUtils_setPermissions },
 };
 
-int register_android_security_cts_FileUtils(JNIEnv* env)
+int register_android_cts_FileUtils(JNIEnv* env)
 {
-    jclass clazz = env->FindClass("android/security/cts/FileUtils");
+    jclass clazz = env->FindClass("android/cts/util/FileUtils");
     assert(clazz != null);
 
-    gFileStatusClass = env->FindClass("android/security/cts/FileUtils$FileStatus");
+    gFileStatusClass = env->FindClass("android/cts/util/FileUtils$FileStatus");
     assert(gFileStatusClass != null);
     gFileStatusDevFieldID = env->GetFieldID(gFileStatusClass, "dev", "I");
     gFileStatusInoFieldID = env->GetFieldID(gFileStatusClass, "ino", "I");
diff --git a/libs/deviceutil/src/android/app/cts/CTSResult.java b/libs/deviceutil/src/android/cts/util/CTSResult.java
similarity index 96%
rename from libs/deviceutil/src/android/app/cts/CTSResult.java
rename to libs/deviceutil/src/android/cts/util/CTSResult.java
index ae4dbfd..c780f57 100644
--- a/libs/deviceutil/src/android/app/cts/CTSResult.java
+++ b/libs/deviceutil/src/android/cts/util/CTSResult.java
@@ -14,7 +14,7 @@
  * the License.
  */
 
-package android.app.cts;
+package android.cts.util;
 
 public interface CTSResult {
     public static final int RESULT_OK = 1;
diff --git a/libs/deviceutil/src/android/provider/cts/FileCopyHelper.java b/libs/deviceutil/src/android/cts/util/FileCopyHelper.java
similarity index 98%
rename from libs/deviceutil/src/android/provider/cts/FileCopyHelper.java
rename to libs/deviceutil/src/android/cts/util/FileCopyHelper.java
index 507eb06..e84e920 100644
--- a/libs/deviceutil/src/android/provider/cts/FileCopyHelper.java
+++ b/libs/deviceutil/src/android/cts/util/FileCopyHelper.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.provider.cts;
+package android.cts.util;
 
 import android.content.Context;
 
diff --git a/tests/tests/os/src/android/os/cts/FileUtils.java b/libs/deviceutil/src/android/cts/util/FileUtils.java
similarity index 98%
rename from tests/tests/os/src/android/os/cts/FileUtils.java
rename to libs/deviceutil/src/android/cts/util/FileUtils.java
index 8600d8b..055f2d6 100644
--- a/tests/tests/os/src/android/os/cts/FileUtils.java
+++ b/libs/deviceutil/src/android/cts/util/FileUtils.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.os.cts;
+package android.cts.util;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -54,7 +54,7 @@
     public static final int S_IXOTH = 00001;
 
     static {
-        System.loadLibrary("ctsos_jni");
+        System.loadLibrary("cts_jni");
     }
 
     public static class FileStatus {
diff --git a/tests/tests/os/src/android/os/cts/IBinderParcelable.java b/libs/deviceutil/src/android/cts/util/IBinderParcelable.java
similarity index 97%
rename from tests/tests/os/src/android/os/cts/IBinderParcelable.java
rename to libs/deviceutil/src/android/cts/util/IBinderParcelable.java
index e48f58a..c80716e 100644
--- a/tests/tests/os/src/android/os/cts/IBinderParcelable.java
+++ b/libs/deviceutil/src/android/cts/util/IBinderParcelable.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.os.cts;
+package android.cts.util;
 
 import android.os.IBinder;
 import android.os.Parcel;
diff --git a/tests/tests/widget/src/android/widget/cts/NullWebViewUtils.java b/libs/deviceutil/src/android/cts/util/NullWebViewUtils.java
similarity index 98%
rename from tests/tests/widget/src/android/widget/cts/NullWebViewUtils.java
rename to libs/deviceutil/src/android/cts/util/NullWebViewUtils.java
index d7a73fa..e1b23f7 100644
--- a/tests/tests/widget/src/android/widget/cts/NullWebViewUtils.java
+++ b/libs/deviceutil/src/android/cts/util/NullWebViewUtils.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.widget.cts;
+package android.cts.util;
 
 import android.content.Context;
 import android.content.pm.PackageManager;
diff --git a/tests/tests/os/src/android/os/cts/ReadElf.java b/libs/deviceutil/src/android/cts/util/ReadElf.java
similarity index 99%
rename from tests/tests/os/src/android/os/cts/ReadElf.java
rename to libs/deviceutil/src/android/cts/util/ReadElf.java
index 4a20031..559cbd0 100644
--- a/tests/tests/os/src/android/os/cts/ReadElf.java
+++ b/libs/deviceutil/src/android/cts/util/ReadElf.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.os.cts;
+package android.cts.util;
 
 import java.io.File;
 import java.io.IOException;
diff --git a/tests/tests/telephony/src/android/telephony/cts/TestThread.java b/libs/deviceutil/src/android/cts/util/TestThread.java
similarity index 98%
rename from tests/tests/telephony/src/android/telephony/cts/TestThread.java
rename to libs/deviceutil/src/android/cts/util/TestThread.java
index 9bf40de..14df61c 100644
--- a/tests/tests/telephony/src/android/telephony/cts/TestThread.java
+++ b/libs/deviceutil/src/android/cts/util/TestThread.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.telephony.cts;
+package android.cts.util;
 
 /**
  * Thread class for executing a Runnable containing assertions in a separate thread.
diff --git a/tests/tests/view/src/android/view/cts/WidgetTestUtils.java b/libs/deviceutil/src/android/cts/util/WidgetTestUtils.java
similarity index 98%
rename from tests/tests/view/src/android/view/cts/WidgetTestUtils.java
rename to libs/deviceutil/src/android/cts/util/WidgetTestUtils.java
index e82e9df..813672e 100644
--- a/tests/tests/view/src/android/view/cts/WidgetTestUtils.java
+++ b/libs/deviceutil/src/android/cts/util/WidgetTestUtils.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.view.cts;
+package android.cts.util;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
diff --git a/libs/deviceutillegacy/Android.mk b/libs/deviceutillegacy/Android.mk
new file mode 100644
index 0000000..852ce38
--- /dev/null
+++ b/libs/deviceutillegacy/Android.mk
@@ -0,0 +1,30 @@
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil
+
+LOCAL_SRC_FILES := \
+    $(call all-java-files-under, src)
+
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE := ctsdeviceutillegacy
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewOnUiThread.java b/libs/deviceutillegacy/src/android/webkit/cts/WebViewOnUiThread.java
similarity index 99%
rename from tests/tests/webkit/src/android/webkit/cts/WebViewOnUiThread.java
rename to libs/deviceutillegacy/src/android/webkit/cts/WebViewOnUiThread.java
index 9b2d803..b9d3af1 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewOnUiThread.java
+++ b/libs/deviceutillegacy/src/android/webkit/cts/WebViewOnUiThread.java
@@ -17,6 +17,7 @@
 package android.webkit.cts;
 
 import android.cts.util.PollingCheck;
+import android.cts.util.TestThread;
 import android.graphics.Bitmap;
 import android.graphics.Picture;
 import android.graphics.Rect;
diff --git a/suite/cts/deviceTests/dram/Android.mk b/suite/cts/deviceTests/dram/Android.mk
index 13de747..879d151 100644
--- a/suite/cts/deviceTests/dram/Android.mk
+++ b/suite/cts/deviceTests/dram/Android.mk
@@ -18,6 +18,9 @@
 # don't include this package in any target
 LOCAL_MODULE_TAGS := tests
 
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
 LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
 
 LOCAL_JNI_SHARED_LIBRARIES := libctsdram_jni
diff --git a/suite/cts/deviceTests/opengl/Android.mk b/suite/cts/deviceTests/opengl/Android.mk
index 7e93dd7..0708efb 100644
--- a/suite/cts/deviceTests/opengl/Android.mk
+++ b/suite/cts/deviceTests/opengl/Android.mk
@@ -18,6 +18,9 @@
 # don't include this package in any target
 LOCAL_MODULE_TAGS := tests
 
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
 LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
 
 LOCAL_JNI_SHARED_LIBRARIES := libctsopengl_jni
diff --git a/suite/cts/deviceTests/simplecpu/Android.mk b/suite/cts/deviceTests/simplecpu/Android.mk
index cc25223..17e7506 100644
--- a/suite/cts/deviceTests/simplecpu/Android.mk
+++ b/suite/cts/deviceTests/simplecpu/Android.mk
@@ -18,6 +18,9 @@
 # don't include this package in any target
 LOCAL_MODULE_TAGS := tests
 
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
 LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
 
 LOCAL_JNI_SHARED_LIBRARIES := libctscpu_jni
diff --git a/tests/app/src/android/app/cts/CTSActivityTestCaseBase.java b/tests/app/src/android/app/cts/CTSActivityTestCaseBase.java
index 9ab1965..efe693a 100644
--- a/tests/app/src/android/app/cts/CTSActivityTestCaseBase.java
+++ b/tests/app/src/android/app/cts/CTSActivityTestCaseBase.java
@@ -16,6 +16,7 @@
 
 package android.app.cts;
 
+import android.cts.util.CTSResult;
 import android.test.InstrumentationTestCase;
 
 public class CTSActivityTestCaseBase extends InstrumentationTestCase implements CTSResult {
diff --git a/tests/app/src/android/app/cts/IBinderParcelable.java b/tests/app/src/android/app/cts/IBinderParcelable.java
deleted file mode 100644
index 228097f..0000000
--- a/tests/app/src/android/app/cts/IBinderParcelable.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.app.cts;
-
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-public class IBinderParcelable implements Parcelable {
-    public IBinder binder;
-
-    public IBinderParcelable(IBinder source) {
-        binder = source;
-    }
-
-    public int describeContents() {
-        return 0;
-    }
-
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeStrongBinder(binder);
-    }
-
-    public static final Parcelable.Creator<IBinderParcelable>
-        CREATOR = new Parcelable.Creator<IBinderParcelable>() {
-
-        public IBinderParcelable createFromParcel(Parcel source) {
-            return new IBinderParcelable(source);
-        }
-
-        public IBinderParcelable[] newArray(int size) {
-            return new IBinderParcelable[size];
-        }
-    };
-
-    private IBinderParcelable(Parcel source) {
-        binder = source.readStrongBinder();
-    }
-}
diff --git a/tests/app/src/android/app/cts/LocalActivityManagerTestHelper.java b/tests/app/src/android/app/cts/LocalActivityManagerTestHelper.java
index 76af648..70764e4 100644
--- a/tests/app/src/android/app/cts/LocalActivityManagerTestHelper.java
+++ b/tests/app/src/android/app/cts/LocalActivityManagerTestHelper.java
@@ -21,9 +21,9 @@
 import android.app.ActivityGroup;
 import android.app.LocalActivityManager;
 import android.content.Intent;
+import android.cts.util.CTSResult;
 import android.os.Bundle;
 import android.view.Window;
-import android.app.cts.CTSResult;
 
 public class LocalActivityManagerTestHelper extends ActivityGroup {
 
diff --git a/tests/app/src/android/app/cts/LocalService.java b/tests/app/src/android/app/cts/LocalService.java
index 22273b0..6c4ae99 100644
--- a/tests/app/src/android/app/cts/LocalService.java
+++ b/tests/app/src/android/app/cts/LocalService.java
@@ -18,6 +18,7 @@
 
 import android.app.Service;
 import android.content.Intent;
+import android.cts.util.IBinderParcelable;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Parcel;
diff --git a/tests/app/src/android/app/cts/SearchManagerStubActivity.java b/tests/app/src/android/app/cts/SearchManagerStubActivity.java
index 6385fef..0dbd832 100644
--- a/tests/app/src/android/app/cts/SearchManagerStubActivity.java
+++ b/tests/app/src/android/app/cts/SearchManagerStubActivity.java
@@ -20,6 +20,7 @@
 import android.app.SearchManager;
 import android.content.ComponentName;
 import android.content.Context;
+import android.cts.util.CTSResult;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index 9ec1f61..40a66d2 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -1,5 +1,12 @@
 [
 {
+  description: "signature test stil needs more work",
+  names: [
+    "android.signature.cts.SignatureTest#testSignature"
+  ],
+  bug: 17894722
+},
+{
   description: "Not all jdwp features are currently supported. These tests will fail",
   names: [
     "org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowDebuggerLaunchTest#testDebuggerLaunch001",
@@ -84,19 +91,6 @@
   bug: 17496766
 },
 {
-  description: "As per new CTS test case adding policy",
-  names: [
-    "com.android.cts.managedprofile.PrimaryUserTest#testAddCrossProfileIntentFilter_primary",
-    "com.android.cts.managedprofile.PrimaryUserTest#testAddCrossProfileIntentFilter_all",
-    "com.android.cts.managedprofile.PrimaryUserTest#testAddCrossProfileIntentFilter_managed",
-    "com.android.cts.managedprofile.ManagedProfile#testClearCrossProfileIntentFilters",
-    "com.android.cts.managedprofile.ManagedProfile#testAddCrossProfileIntentFilter_primary",
-    "com.android.cts.managedprofile.ManagedProfile#testAddCrossProfileIntentFilter_all",
-    "com.android.cts.managedprofile.ManagedProfile#testAddCrossProfileIntentFilter_managed"
-  ],
-  bug: 15900074
-},
-{
   description: "these tests locks the screen with an emtpy password or swipe-to-unlock, blocking subsequent test to dismiss keyguard",
   names: [
     "com.android.cts.devicepolicy.DeviceOwnerTest#testKeyManagement"
@@ -111,6 +105,28 @@
   bug: 17508787
 },
 {
+  description: "New tests recently added for Android Enterprise. To be moved out of CTS-staging as soon as they show that they are stable",
+  names: [
+    "com.android.cts.devicepolicy.DeviceOwnerTest#testApplicationRestrictions",
+    "com.android.cts.devicepolicy.DeviceOwnerTest#testCaCertManagement",
+    "com.android.cts.devicepolicy.DeviceOwnerTest#testDeviceOwnerSetup",
+    "com.android.cts.devicepolicy.DeviceOwnerTest#testPersistentIntentResolving",
+    "com.android.cts.devicepolicy.DeviceOwnerTest#testScreenCaptureDisabled",
+    "com.android.cts.devicepolicy.ManagedProfileTest#testManagedProfileSetup",
+    "com.android.cts.devicepolicy.ManagedProfileTest#testWipeData",
+    "com.android.cts.devicepolicy.ManagedProfileTest#testCrossProfileIntentFilters",
+    "com.android.cts.devicepolicy.ManagedProfileTest#testCrossProfileContent",
+    "com.android.cts.devicepolicy.ManagedProfileTest#testNoDebuggingFeaturesRestriction"
+  ]
+},
+{
+  description: "Flaky test which ocassionally fails",
+  names: [
+    "com.android.cts.devicepolicy.DeviceOwnerTest#testLockTask"
+  ],
+  bug: 17890673
+},
+{
 
   description: "These tests fail on some devices.",
   names: [
@@ -299,5 +315,12 @@
     "android.hardware.cts.SensorTest#testBatchAndFlushWithHandler"
   ],
   bug: 17675466
+},
+{
+  description: "This test failed on hw decoder that doesn't output frame with the configured format.",
+  names: [
+    "android.meida.cts.ImageReaderDecoderTest#testHwAVCDecode360pForFlexibleYuv"
+  ],
+  bug: 17144778
 }
 ]
diff --git a/tests/tests/app/src/android/app/cts/LocalActivityManagerTest.java b/tests/tests/app/src/android/app/cts/LocalActivityManagerTest.java
index 1b40476..db3baba 100644
--- a/tests/tests/app/src/android/app/cts/LocalActivityManagerTest.java
+++ b/tests/tests/app/src/android/app/cts/LocalActivityManagerTest.java
@@ -20,6 +20,7 @@
 import android.app.Instrumentation;
 import android.app.LocalActivityManager;
 import android.content.Intent;
+import android.cts.util.CTSResult;
 import android.test.InstrumentationTestCase;
 import android.test.UiThreadTest;
 
diff --git a/tests/tests/app/src/android/app/cts/SearchManagerTest.java b/tests/tests/app/src/android/app/cts/SearchManagerTest.java
index 8e465e8..1cece76 100644
--- a/tests/tests/app/src/android/app/cts/SearchManagerTest.java
+++ b/tests/tests/app/src/android/app/cts/SearchManagerTest.java
@@ -17,6 +17,7 @@
 package android.app.cts;
 
 import android.content.Intent;
+import android.cts.util.CTSResult;
 
 public class SearchManagerTest extends CTSActivityTestCaseBase {
 
diff --git a/tests/tests/app/src/android/app/cts/ServiceTest.java b/tests/tests/app/src/android/app/cts/ServiceTest.java
index 675b7ae..b66f4c8 100644
--- a/tests/tests/app/src/android/app/cts/ServiceTest.java
+++ b/tests/tests/app/src/android/app/cts/ServiceTest.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.cts.util.IBinderParcelable;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
diff --git a/tests/tests/content/AndroidManifest.xml b/tests/tests/content/AndroidManifest.xml
index f7080ae..d54bc02 100644
--- a/tests/tests/content/AndroidManifest.xml
+++ b/tests/tests/content/AndroidManifest.xml
@@ -205,7 +205,6 @@
             android:value="com.android.cts.runner.CtsTestRunListener" />
     </instrumentation>
 
-    <!--Test for PackageManager, please put this at the very beginning-->
     <instrumentation android:name="android.content.pm.cts.TestPmInstrumentation"
         android:targetPackage="android"
         android:label="PackageManager Instrumentation Test" />
diff --git a/tests/tests/content/src/android/content/pm/cts/ComponentInfoTest.java b/tests/tests/content/src/android/content/pm/cts/ComponentInfoTest.java
index 361bfe4..14a42c0 100644
--- a/tests/tests/content/src/android/content/pm/cts/ComponentInfoTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/ComponentInfoTest.java
@@ -20,6 +20,7 @@
 import android.content.pm.ComponentInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.cts.util.WidgetTestUtils;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Parcel;
diff --git a/tests/tests/content/src/android/content/pm/cts/WidgetTestUtils.java b/tests/tests/content/src/android/content/pm/cts/WidgetTestUtils.java
deleted file mode 100644
index 6efd8b1..0000000
--- a/tests/tests/content/src/android/content/pm/cts/WidgetTestUtils.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm.cts;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-
-import java.io.IOException;
-
-import junit.framework.Assert;
-
-/**
- * The useful methods for widget test.
- */
-public class WidgetTestUtils {
-    /**
-     * Assert that two bitmaps are equal.
-     *
-     * @param Bitmap b1 the first bitmap which needs to compare.
-     * @param Bitmap b2 the second bitmap which needs to compare.
-     */
-    public static void assertEquals(Bitmap b1, Bitmap b2) {
-        if (b1 == b2) {
-            return;
-        }
-
-        if (b1 == null || b2 == null) {
-            Assert.fail("the bitmaps are not equal");
-        }
-
-        // b1 and b2 are all not null.
-        if (b1.getWidth() != b2.getWidth() || b1.getHeight() != b2.getHeight()
-            || b1.getConfig() != b2.getConfig()) {
-            Assert.fail("the bitmaps are not equal");
-        }
-
-        int w = b1.getWidth();
-        int h = b1.getHeight();
-        int s = w * h;
-        int[] pixels1 = new int[s];
-        int[] pixels2 = new int[s];
-
-        b1.getPixels(pixels1, 0, w, 0, 0, w, h);
-        b2.getPixels(pixels2, 0, w, 0, 0, w, h);
-
-        for (int i = 0; i < s; i++) {
-            if (pixels1[i] != pixels2[i]) {
-                Assert.fail("the bitmaps are not equal");
-            }
-        }
-    }
-
-    /**
-     * Find beginning of the special element.
-     * @param parser XmlPullParser will be parsed.
-     * @param firstElementName the target element name.
-     *
-     * @throws XmlPullParserException if XML Pull Parser related faults occur.
-     * @throws IOException if I/O-related error occur when parsing.
-     */
-    public static final void beginDocument(XmlPullParser parser, String firstElementName)
-            throws XmlPullParserException, IOException {
-        Assert.assertNotNull(parser);
-        Assert.assertNotNull(firstElementName);
-
-        int type;
-        while ((type = parser.next()) != XmlPullParser.START_TAG
-                && type != XmlPullParser.END_DOCUMENT) {
-            ;
-        }
-
-        if (!parser.getName().equals(firstElementName)) {
-            throw new XmlPullParserException("Unexpected start tag: found " + parser.getName()
-                    + ", expected " + firstElementName);
-        }
-    }
-
-    /**
-     * Compare the expected pixels with actual, scaling for the target context density
-     *
-     * @throws AssertionFailedError
-     */
-    public static void assertScaledPixels(int expected, int actual, Context context) {
-        Assert.assertEquals(expected * context.getResources().getDisplayMetrics().density,
-                actual, 3);
-    }
-
-    /** Converts dips into pixels using the {@link Context}'s density. */
-    public static int convertDipToPixels(Context context, int dip) {
-      float density = context.getResources().getDisplayMetrics().density;
-      return Math.round(density * dip);
-    }
-
-    /**
-     * Retrieve a bitmap that can be used for comparison on any density
-     * @param resources
-     * @return the {@link Bitmap} or <code>null</code>
-     */
-    public static Bitmap getUnscaledBitmap(Resources resources, int resId) {
-        BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inScaled = false;
-        return BitmapFactory.decodeResource(resources, resId, options);
-    }
-
-    /**
-     * Retrieve a dithered bitmap that can be used for comparison on any density
-     * @param resources
-     * @param config the preferred config for the returning bitmap
-     * @return the {@link Bitmap} or <code>null</code>
-     */
-    public static Bitmap getUnscaledAndDitheredBitmap(Resources resources,
-            int resId, Bitmap.Config config) {
-        BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inDither = true;
-        options.inScaled = false;
-        options.inPreferredConfig = config;
-        return BitmapFactory.decodeResource(resources, resId, options);
-    }
-}
diff --git a/tests/tests/dpi/Android.mk b/tests/tests/dpi/Android.mk
index fde990b..4c05ecf 100644
--- a/tests/tests/dpi/Android.mk
+++ b/tests/tests/dpi/Android.mk
@@ -44,6 +44,4 @@
 
 LOCAL_MODULE := android.cts.dpi
 
-LOCAL_SDK_VERSION := current
-
 include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tests/tests/drm/Android.mk b/tests/tests/drm/Android.mk
index 74422a0..6272e9c 100644
--- a/tests/tests/drm/Android.mk
+++ b/tests/tests/drm/Android.mk
@@ -16,6 +16,9 @@
 
 include $(CLEAR_VARS)
 
+# Include both the 32 and 64 bit versions of libs
+LOCAL_MULTILIB := both
+
 LOCAL_MODULE_TAGS := tests
 
 # and when built explicitly put it in the data partition
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java
index 4ea89c7..f58b871 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java
@@ -19,6 +19,7 @@
 
 
 import android.content.res.Resources;
+import android.cts.util.WidgetTestUtils;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
diff --git a/tests/tests/graphics/src/android/graphics/cts/MovieTest.java b/tests/tests/graphics/src/android/graphics/cts/MovieTest.java
index 2facdc9..b18b800 100644
--- a/tests/tests/graphics/src/android/graphics/cts/MovieTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/MovieTest.java
@@ -24,12 +24,12 @@
 import java.io.OutputStream;
 
 import android.content.Context;
+import android.cts.util.WidgetTestUtils;
 import android.graphics.Canvas;
 import android.graphics.Movie;
 import android.graphics.Paint;
 import android.test.ActivityInstrumentationTestCase2;
 
-
 public class MovieTest extends ActivityInstrumentationTestCase2<MockActivity> {
     private Movie mMovie;
     private final int MOVIE = com.android.cts.graphics.R.drawable.animated;
diff --git a/tests/tests/graphics/src/android/graphics/cts/WidgetTestUtils.java b/tests/tests/graphics/src/android/graphics/cts/WidgetTestUtils.java
deleted file mode 100644
index 63bafac..0000000
--- a/tests/tests/graphics/src/android/graphics/cts/WidgetTestUtils.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics.cts;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-
-import java.io.IOException;
-
-import junit.framework.Assert;
-
-/**
- * The useful methods for widget test.
- */
-public class WidgetTestUtils {
-    /**
-     * Assert that two bitmaps are equal.
-     *
-     * @param Bitmap b1 the first bitmap which needs to compare.
-     * @param Bitmap b2 the second bitmap which needs to compare.
-     */
-    public static void assertEquals(Bitmap b1, Bitmap b2) {
-        if (b1 == b2) {
-            return;
-        }
-
-        if (b1 == null || b2 == null) {
-            Assert.fail("the bitmaps are not equal");
-        }
-
-        // b1 and b2 are all not null.
-        if (b1.getWidth() != b2.getWidth() || b1.getHeight() != b2.getHeight()
-            || b1.getConfig() != b2.getConfig()) {
-            Assert.fail("the bitmaps are not equal");
-        }
-
-        int w = b1.getWidth();
-        int h = b1.getHeight();
-        int s = w * h;
-        int[] pixels1 = new int[s];
-        int[] pixels2 = new int[s];
-
-        b1.getPixels(pixels1, 0, w, 0, 0, w, h);
-        b2.getPixels(pixels2, 0, w, 0, 0, w, h);
-
-        for (int i = 0; i < s; i++) {
-            if (pixels1[i] != pixels2[i]) {
-                Assert.fail("the bitmaps are not equal");
-            }
-        }
-    }
-
-    /**
-     * Find beginning of the special element.
-     * @param parser XmlPullParser will be parsed.
-     * @param firstElementName the target element name.
-     *
-     * @throws XmlPullParserException if XML Pull Parser related faults occur.
-     * @throws IOException if I/O-related error occur when parsing.
-     */
-    public static final void beginDocument(XmlPullParser parser, String firstElementName)
-            throws XmlPullParserException, IOException {
-        Assert.assertNotNull(parser);
-        Assert.assertNotNull(firstElementName);
-
-        int type;
-        while ((type = parser.next()) != XmlPullParser.START_TAG
-                && type != XmlPullParser.END_DOCUMENT) {
-            ;
-        }
-
-        if (!parser.getName().equals(firstElementName)) {
-            throw new XmlPullParserException("Unexpected start tag: found " + parser.getName()
-                    + ", expected " + firstElementName);
-        }
-    }
-
-    /**
-     * Compare the expected pixels with actual, scaling for the target context density
-     *
-     * @throws AssertionFailedError
-     */
-    public static void assertScaledPixels(int expected, int actual, Context context) {
-        Assert.assertEquals(expected * context.getResources().getDisplayMetrics().density,
-                actual, 3);
-    }
-
-    /** Converts dips into pixels using the {@link Context}'s density. */
-    public static int convertDipToPixels(Context context, int dip) {
-      float density = context.getResources().getDisplayMetrics().density;
-      return Math.round(density * dip);
-    }
-
-    /**
-     * Retrieve a bitmap that can be used for comparison on any density
-     * @param resources
-     * @return the {@link Bitmap} or <code>null</code>
-     */
-    public static Bitmap getUnscaledBitmap(Resources resources, int resId) {
-        BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inScaled = false;
-        return BitmapFactory.decodeResource(resources, resId, options);
-    }
-
-    /**
-     * Retrieve a dithered bitmap that can be used for comparison on any density
-     * @param resources
-     * @param config the preferred config for the returning bitmap
-     * @return the {@link Bitmap} or <code>null</code>
-     */
-    public static Bitmap getUnscaledAndDitheredBitmap(Resources resources,
-            int resId, Bitmap.Config config) {
-        BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inDither = true;
-        options.inScaled = false;
-        options.inPreferredConfig = config;
-        return BitmapFactory.decodeResource(resources, resId, options);
-    }
-}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
index eef99a2..0c36832 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -413,7 +413,13 @@
 
         int offset = 0;
         data = new byte[width * height * ImageFormat.getBitsPerPixel(format) / 8];
-        byte[] rowData = new byte[planes[0].getRowStride()];
+        int maxRowSize = planes[0].getRowStride();
+        for (int i = 0; i < planes.length; i++) {
+            if (maxRowSize < planes[i].getRowStride()) {
+                maxRowSize = planes[i].getRowStride();
+            }
+        }
+        byte[] rowData = new byte[maxRowSize];
         if(VERBOSE) Log.v(TAG, "get data from " + planes.length + " planes");
         for (int i = 0; i < planes.length; i++) {
             buffer = planes[i].getBuffer();
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
index 00dd24d..5346ae1 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
@@ -1494,17 +1494,19 @@
             verifyCaptureResultForKey(CaptureResult.CONTROL_AWB_MODE, mode, listener,
                     NUM_FRAMES_VERIFIED);
 
-            // Verify color correction transform and gains stay unchanged after a lock.
-            requestBuilder.set(CaptureRequest.CONTROL_AWB_LOCK, true);
-            listener = new SimpleCaptureCallback();
-            mSession.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
-            waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+            if (mode == CameraMetadata.CONTROL_AWB_MODE_AUTO) {
+                // Verify color correction transform and gains stay unchanged after a lock.
+                requestBuilder.set(CaptureRequest.CONTROL_AWB_LOCK, true);
+                listener = new SimpleCaptureCallback();
+                mSession.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
+                waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
 
-            if (mStaticInfo.areKeysAvailable(CaptureResult.CONTROL_AWB_STATE)) {
-                waitForResultValue(listener, CaptureResult.CONTROL_AWB_STATE,
-                        CaptureResult.CONTROL_AWB_STATE_LOCKED, NUM_RESULTS_WAIT_TIMEOUT);
+                if (mStaticInfo.areKeysAvailable(CaptureResult.CONTROL_AWB_STATE)) {
+                    waitForResultValue(listener, CaptureResult.CONTROL_AWB_STATE,
+                            CaptureResult.CONTROL_AWB_STATE_LOCKED, NUM_RESULTS_WAIT_TIMEOUT);
+                }
+
             }
-
             verifyAwbCaptureResultUnchanged(listener, NUM_FRAMES_VERIFIED);
         }
     }
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/ImageReaderTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/ImageReaderTest.java
index a68f78d..61f25fb 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/ImageReaderTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/ImageReaderTest.java
@@ -88,6 +88,10 @@
             try {
                 Log.v(TAG, "Testing jpeg capture for Camera " + id);
                 openDevice(id);
+                if (mStaticInfo.isHardwareLevelLegacy()) {
+                    Log.i(TAG, "Skipping test on legacy devices");
+                    continue;
+                }
                 bufferFormatTestByCamera(ImageFormat.JPEG, /*repeating*/false);
             } finally {
                 closeDevice(id);
@@ -113,6 +117,10 @@
             try {
                 Log.v(TAG, "Testing repeating jpeg capture for Camera " + id);
                 openDevice(id);
+                if (mStaticInfo.isHardwareLevelLegacy()) {
+                    Log.i(TAG, "Skipping test on legacy devices");
+                    continue;
+                }
                 bufferFormatTestByCamera(ImageFormat.JPEG, /*repeating*/true);
             } finally {
                 closeDevice(id);
@@ -148,7 +156,10 @@
             try {
                 Log.v(TAG, "YUV and JPEG testing for camera " + id);
                 openDevice(id);
-
+                if (mStaticInfo.isHardwareLevelLegacy()) {
+                    Log.i(TAG, "Skipping test on legacy devices");
+                    continue;
+                }
                 bufferFormatWithYuvTestByCamera(ImageFormat.JPEG);
             } finally {
                 closeDevice(id);
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java
index 7a6e088..ea15c19 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java
@@ -497,6 +497,11 @@
 
                     openDevice(id);
 
+                    if (mStaticInfo.isHardwareLevelLegacy()) {
+                        Log.i(TAG, "Skipping test on legacy devices");
+                        continue;
+                    }
+
                     initSupportedVideoSize(id);
 
                     videoSnapshotTestByCamera(burstTest);
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/RobustnessTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/RobustnessTest.java
index 11ba02c..7960200 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/RobustnessTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/RobustnessTest.java
@@ -185,6 +185,11 @@
 
             final StaticMetadata staticInfo = new StaticMetadata(cc);
 
+            if (staticInfo.isHardwareLevelLegacy()) {
+                Log.i(TAG, "Skipping test on legacy devices");
+                continue;
+            }
+
             openDevice(id);
 
             // Always run legacy-level tests
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/StaticMetadata.java b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
index 11d7ac0..fb2001f 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
@@ -1282,7 +1282,7 @@
         if (isHardwareLevelLimitedOrBetter()) {
             float compensationStepF =
                     (float) compensationStep.getNumerator() / compensationStep.getDenominator();
-            checkTrueForKey(key, " value must be no more than 1/2", compensationStepF < 0.5f);
+            checkTrueForKey(key, " value must be no more than 1/2", compensationStepF <= 0.5f);
         }
 
         return compensationStep;
diff --git a/tests/tests/jni/Android.mk b/tests/tests/jni/Android.mk
index 8b3edd2..1aeb8b7 100644
--- a/tests/tests/jni/Android.mk
+++ b/tests/tests/jni/Android.mk
@@ -21,6 +21,9 @@
 # Don't include this package in any target.
 LOCAL_MODULE_TAGS := optional
 
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
 # When built, explicitly put it in the data partition.
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
diff --git a/tests/tests/media/Android.mk b/tests/tests/media/Android.mk
index 936a35e..15237a8 100644
--- a/tests/tests/media/Android.mk
+++ b/tests/tests/media/Android.mk
@@ -21,6 +21,9 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
+# include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
 LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestserver ctstestrunner
 
 LOCAL_JNI_SHARED_LIBRARIES := libctsmediacodec_jni
diff --git a/tests/tests/media/src/android/media/cts/AudioManagerStub.java b/tests/tests/media/src/android/media/cts/AudioManagerStub.java
index baae5fc..290b866 100644
--- a/tests/tests/media/src/android/media/cts/AudioManagerStub.java
+++ b/tests/tests/media/src/android/media/cts/AudioManagerStub.java
@@ -19,7 +19,7 @@
 import com.android.cts.media.R;
 
 import android.app.Activity;
-import android.app.cts.CTSResult;
+import android.cts.util.CTSResult;
 import android.content.Context;
 import android.content.Intent;
 import android.media.AudioManager;
diff --git a/tests/tests/media/src/android/media/cts/ImageReaderDecoderTest.java b/tests/tests/media/src/android/media/cts/ImageReaderDecoderTest.java
index f115b63..d620995 100644
--- a/tests/tests/media/src/android/media/cts/ImageReaderDecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/ImageReaderDecoderTest.java
@@ -27,6 +27,7 @@
 import android.media.ImageReader;
 import android.media.MediaCodec;
 import android.media.MediaCodecInfo;
+import android.media.MediaCodecInfo.CodecCapabilities;
 import android.media.MediaCodecList;
 import android.media.MediaExtractor;
 import android.media.MediaFormat;
@@ -166,6 +167,8 @@
                 vidFD.getLength());
 
         MediaFormat mediaFmt = extractor.getTrackFormat(0);
+        mediaFmt.setInteger(MediaFormat.KEY_COLOR_FORMAT,
+                            CodecCapabilities.COLOR_FormatYUV420Flexible);
         String mime = mediaFmt.getString(MediaFormat.KEY_MIME);
         try {
             // Create decoder
@@ -191,10 +194,10 @@
             throws Exception, InterruptedException {
         ByteBuffer[] decoderInputBuffers;
         ByteBuffer[] decoderOutputBuffers;
-        // Get decoder output ImageFormat, will be used to create ImageReader
-        int codecImageFormat = getImageFormatFromCodecType(mime);
-        assertEquals("Codec image format should match image reader format",
-                imageFormat, codecImageFormat);
+        if (!imageFormatSupported(decoder, imageFormat, mime)) {
+            // TODO: SKIPPING TEST
+            return;
+        }
         createImageReader(width, height, imageFormat, MAX_NUM_IMAGES, mImageListener);
 
         // Configure decoder.
@@ -293,74 +296,19 @@
         }
     }
 
-    private int getImageFormatFromCodecType(String mimeType) {
-        // TODO: Need pick a codec first, then get the codec info, will revisit for future.
-        MediaCodecInfo codecInfo = getCodecInfoByType(mimeType);
-        if (VERBOSE) Log.v(TAG, "found decoder: " + codecInfo.getName());
-
-        int colorFormat = selectDecoderOutputColorFormat(codecInfo, mimeType);
-        if (VERBOSE) Log.v(TAG, "found decoder output color format: " + colorFormat);
-        switch (colorFormat) {
-            case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar:
-                // TODO: This is fishy, OMX YUV420P is not identical as YV12, U and V planes are
-                // swapped actually. It should give YV12 if producer is setup first, that is, after
-                // Configuring the Surface (provided by ImageReader object) into codec, but this
-                // is Chicken-egg issue, do the translation on behalf of driver here:)
-                return ImageFormat.YV12;
-            case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar:
-                // same as above.
-                return ImageFormat.NV21;
-            default:
-                return colorFormat;
+    private boolean imageFormatSupported(MediaCodec decoder, int imageFormat, String mime) {
+        MediaCodecInfo codecInfo = decoder.getCodecInfo();
+        if (codecInfo == null) {
+            return false;
         }
-    }
-
-    private static MediaCodecInfo getCodecInfoByType(String mimeType) {
-        int numCodecs = MediaCodecList.getCodecCount();
-        for (int i = 0; i < numCodecs; i++) {
-            MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
-
-            if (codecInfo.isEncoder()) {
-                continue;
-            }
-
-            String[] types = codecInfo.getSupportedTypes();
-            for (int j = 0; j < types.length; j++) {
-                if (types[j].equalsIgnoreCase(mimeType)) {
-                    return codecInfo;
-                }
-            }
-        }
-        return null;
-    }
-
-    private static int selectDecoderOutputColorFormat(MediaCodecInfo codecInfo, String mimeType) {
-        MediaCodecInfo.CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(mimeType);
-        for (int i = 0; i < capabilities.colorFormats.length; i++) {
-            int colorFormat = capabilities.colorFormats[i];
-            if (isRecognizedFormat(colorFormat)) {
-                return colorFormat;
-            }
-        }
-        fail("couldn't find a good color format for " + codecInfo.getName() + " / " + mimeType);
-        return 0;   // not reached
-    }
-
-    // Need make this function simple, may be merge into above functions.
-    private static boolean isRecognizedFormat(int colorFormat) {
-        if (VERBOSE) Log.v(TAG, "colorformat: " + colorFormat);
-        switch (colorFormat) {
-            // these are the formats we know how to handle for this test
-            case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar:
-            case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar:
-            case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar:
-            case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedSemiPlanar:
-            case MediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanar:
-            case ImageFormat.YUV_420_888:
+        MediaCodecInfo.CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(mime);
+        for (int colorFormat : capabilities.colorFormats) {
+            if (colorFormat == CodecCapabilities.COLOR_FormatYUV420Flexible
+                    && imageFormat == ImageFormat.YUV_420_888) {
                 return true;
-            default:
-                return false;
+            }
         }
+        return false;
     }
 
     private MediaCodec createDecoder(String mime, boolean useHw) throws Exception {
@@ -404,7 +352,7 @@
     private static void validateYuvData(byte[] yuvData, int width, int height, int format,
             long ts, String fileName) {
 
-        assertTrue("YUV format must be one of the YUV420_888, NV21, or YV12",
+        assertTrue("YUV format must be one of the YUV_420_888, NV21, or YV12",
                 format == ImageFormat.YUV_420_888 ||
                 format == ImageFormat.NV21 ||
                 format == ImageFormat.YV12);
diff --git a/tests/tests/media/src/android/media/cts/MediaScannerConnectionTest.java b/tests/tests/media/src/android/media/cts/MediaScannerConnectionTest.java
index 4234a5b..ddf87b8 100644
--- a/tests/tests/media/src/android/media/cts/MediaScannerConnectionTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaScannerConnectionTest.java
@@ -21,12 +21,12 @@
 
 import android.content.ComponentName;
 import android.content.Context;
+import android.cts.util.FileCopyHelper;
 import android.cts.util.PollingCheck;
 import android.media.MediaScannerConnection;
 import android.media.MediaScannerConnection.MediaScannerConnectionClient;
 import android.net.Uri;
 import android.os.IBinder;
-import android.provider.cts.FileCopyHelper;
 import android.test.AndroidTestCase;
 
 import java.io.File;
diff --git a/tests/tests/media/src/android/media/cts/MediaScannerTest.java b/tests/tests/media/src/android/media/cts/MediaScannerTest.java
index b537467..4b42690 100644
--- a/tests/tests/media/src/android/media/cts/MediaScannerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaScannerTest.java
@@ -26,6 +26,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.res.AssetFileDescriptor;
+import android.cts.util.FileCopyHelper;
 import android.cts.util.PollingCheck;
 import android.database.Cursor;
 import android.media.MediaMetadataRetriever;
@@ -38,7 +39,6 @@
 import android.os.IBinder;
 import android.os.SystemClock;
 import android.provider.MediaStore;
-import android.provider.cts.FileCopyHelper;
 import android.test.AndroidTestCase;
 import android.util.Log;
 
diff --git a/tests/tests/mediastress/Android.mk b/tests/tests/mediastress/Android.mk
index 5c4930b..5bb23d0 100644
--- a/tests/tests/mediastress/Android.mk
+++ b/tests/tests/mediastress/Android.mk
@@ -20,6 +20,9 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner ctsdeviceutil
 
 LOCAL_JNI_SHARED_LIBRARIES := libctsmediastress_jni
diff --git a/tests/tests/nativeopengl/Android.mk b/tests/tests/nativeopengl/Android.mk
index 672eb5c..d2192ad 100644
--- a/tests/tests/nativeopengl/Android.mk
+++ b/tests/tests/nativeopengl/Android.mk
@@ -24,6 +24,9 @@
 # When built, explicitly put it in the data partition.
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner ctswrappedgtest
 
 LOCAL_JNI_SHARED_LIBRARIES := libnativeopengltests
diff --git a/tests/tests/net/Android.mk b/tests/tests/net/Android.mk
index da19a4d..46d4d81 100644
--- a/tests/tests/net/Android.mk
+++ b/tests/tests/net/Android.mk
@@ -21,6 +21,9 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
 LOCAL_JAVA_LIBRARIES := voip-common conscrypt
 
 LOCAL_JNI_SHARED_LIBRARIES := libnativedns_jni
diff --git a/tests/tests/opengl/Android.mk b/tests/tests/opengl/Android.mk
index a14ee7a..3844807 100644
--- a/tests/tests/opengl/Android.mk
+++ b/tests/tests/opengl/Android.mk
@@ -21,6 +21,9 @@
 # Don't include this package in any target.
 LOCAL_MODULE_TAGS := optional
 
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
 # When built, explicitly put it in the data partition.
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
diff --git a/tests/tests/openglperf/Android.mk b/tests/tests/openglperf/Android.mk
index 1d57263..7be16e8 100644
--- a/tests/tests/openglperf/Android.mk
+++ b/tests/tests/openglperf/Android.mk
@@ -21,6 +21,9 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner ctsdeviceutil
 
 LOCAL_JNI_SHARED_LIBRARIES := libctsopenglperf_jni
diff --git a/tests/tests/os/Android.mk b/tests/tests/os/Android.mk
index f0fb88a..9dfb86e 100644
--- a/tests/tests/os/Android.mk
+++ b/tests/tests/os/Android.mk
@@ -21,11 +21,12 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_PROGUARD_ENABLED := disabled
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
 
 LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner guava
 
-LOCAL_JNI_SHARED_LIBRARIES := libctsos_jni
+LOCAL_JNI_SHARED_LIBRARIES := libcts_jni libctsos_jni
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) \
         src/android/os/cts/IParcelFileDescriptorPeer.aidl \
diff --git a/tests/tests/os/jni/Android.mk b/tests/tests/os/jni/Android.mk
index a39b5d1..3d3bc33 100644
--- a/tests/tests/os/jni/Android.mk
+++ b/tests/tests/os/jni/Android.mk
@@ -25,8 +25,7 @@
 		CtsOsJniOnLoad.cpp \
 		android_os_cts_CpuInstructions.cpp.arm \
 		android_os_cts_TaggedPointer.cpp \
-		android_os_cts_OSFeatures.cpp \
-		android_os_cts_FileUtils.cpp \
+		android_os_cts_OSFeatures.cpp
 
 LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
 
diff --git a/tests/tests/os/jni/CtsOsJniOnLoad.cpp b/tests/tests/os/jni/CtsOsJniOnLoad.cpp
index ef69732..c6b88f5 100644
--- a/tests/tests/os/jni/CtsOsJniOnLoad.cpp
+++ b/tests/tests/os/jni/CtsOsJniOnLoad.cpp
@@ -25,8 +25,6 @@
 
 extern int register_android_os_cts_OSFeatures(JNIEnv*);
 
-extern int register_android_os_cts_FileUtils(JNIEnv*);
-
 jint JNI_OnLoad(JavaVM *vm, void *reserved) {
     JNIEnv *env = NULL;
 
@@ -50,9 +48,5 @@
         return JNI_ERR;
     }
 
-    if (register_android_os_cts_FileUtils(env)) {
-      return JNI_ERR;
-    }
-
     return JNI_VERSION_1_4;
 }
diff --git a/tests/tests/os/jni/android_os_cts_FileUtils.cpp b/tests/tests/os/jni/android_os_cts_FileUtils.cpp
deleted file mode 100644
index 2b7e282..0000000
--- a/tests/tests/os/jni/android_os_cts_FileUtils.cpp
+++ /dev/null
@@ -1,145 +0,0 @@
-/* 
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 <grp.h>
-#include <jni.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <assert.h>
-
-static jclass gFileStatusClass;
-static jfieldID gFileStatusDevFieldID;
-static jfieldID gFileStatusInoFieldID;
-static jfieldID gFileStatusModeFieldID;
-static jfieldID gFileStatusNlinkFieldID;
-static jfieldID gFileStatusUidFieldID;
-static jfieldID gFileStatusGidFieldID;
-static jfieldID gFileStatusSizeFieldID;
-static jfieldID gFileStatusBlksizeFieldID;
-static jfieldID gFileStatusBlocksFieldID;
-static jfieldID gFileStatusAtimeFieldID;
-static jfieldID gFileStatusMtimeFieldID;
-static jfieldID gFileStatusCtimeFieldID;
-
-/*
- * Native methods used by
- * cts/tests/src/android/os/cts/FileUtils.java
- *
- * Copied from hidden API: frameworks/base/core/jni/android_os_FileUtils.cpp
- */
-
-jboolean android_os_cts_FileUtils_getFileStatus(JNIEnv* env, jobject thiz,
-        jstring path, jobject fileStatus, jboolean statLinks)
-{
-    const char* pathStr = env->GetStringUTFChars(path, NULL);
-    jboolean ret = false;
-    struct stat s;
-
-    int res = statLinks == true ? lstat(pathStr, &s) : stat(pathStr, &s);
-
-    if (res == 0) {
-        ret = true;
-        if (fileStatus != NULL) {
-            env->SetIntField(fileStatus, gFileStatusDevFieldID, s.st_dev);
-            env->SetIntField(fileStatus, gFileStatusInoFieldID, s.st_ino);
-            env->SetIntField(fileStatus, gFileStatusModeFieldID, s.st_mode);
-            env->SetIntField(fileStatus, gFileStatusNlinkFieldID, s.st_nlink);
-            env->SetIntField(fileStatus, gFileStatusUidFieldID, s.st_uid);
-            env->SetIntField(fileStatus, gFileStatusGidFieldID, s.st_gid);
-            env->SetLongField(fileStatus, gFileStatusSizeFieldID, s.st_size);
-            env->SetIntField(fileStatus, gFileStatusBlksizeFieldID, s.st_blksize);
-            env->SetLongField(fileStatus, gFileStatusBlocksFieldID, s.st_blocks);
-            env->SetLongField(fileStatus, gFileStatusAtimeFieldID, s.st_atime);
-            env->SetLongField(fileStatus, gFileStatusMtimeFieldID, s.st_mtime);
-            env->SetLongField(fileStatus, gFileStatusCtimeFieldID, s.st_ctime);
-        }
-    }
-
-    env->ReleaseStringUTFChars(path, pathStr);
-
-    return ret;
-}
-
-jstring android_os_cts_FileUtils_getUserName(JNIEnv* env, jobject thiz,
-        jint uid)
-{
-    struct passwd *pwd = getpwuid(uid);
-    return env->NewStringUTF(pwd->pw_name);
-}
-
-jstring android_os_cts_FileUtils_getGroupName(JNIEnv* env, jobject thiz,
-        jint gid)
-{
-    struct group *grp = getgrgid(gid);
-    return env->NewStringUTF(grp->gr_name);
-}
-
-jint android_os_cts_FileUtils_setPermissions(JNIEnv* env, jobject clazz,
-        jstring file, jint mode)
-{
-    const char *fileStr = env->GetStringUTFChars(file, NULL);
-    if (fileStr == NULL) {
-        return -1;
-    }
-
-    if (strlen(fileStr) <= 0) {
-        env->ReleaseStringUTFChars(file, fileStr);
-        return ENOENT;
-    } 
-
-    jint returnValue = chmod(fileStr, mode) == 0 ? 0 : errno;
-    env->ReleaseStringUTFChars(file, fileStr);
-    return returnValue;
-}
-
-static JNINativeMethod gMethods[] = {
-    {  "getFileStatus", "(Ljava/lang/String;Landroid/os/cts/FileUtils$FileStatus;Z)Z",
-            (void *) android_os_cts_FileUtils_getFileStatus  },
-    {  "getUserName", "(I)Ljava/lang/String;",
-            (void *) android_os_cts_FileUtils_getUserName  },
-    {  "getGroupName", "(I)Ljava/lang/String;",
-            (void *) android_os_cts_FileUtils_getGroupName  },
-    {  "setPermissions", "(Ljava/lang/String;I)I",
-            (void *) android_os_cts_FileUtils_setPermissions },
-};
-
-int register_android_os_cts_FileUtils(JNIEnv* env)
-{
-    jclass clazz = env->FindClass("android/os/cts/FileUtils");
-    assert(clazz != null);
-
-    gFileStatusClass = env->FindClass("android/os/cts/FileUtils$FileStatus");
-    assert(gFileStatusClass != null);
-    gFileStatusDevFieldID = env->GetFieldID(gFileStatusClass, "dev", "I");
-    gFileStatusInoFieldID = env->GetFieldID(gFileStatusClass, "ino", "I");
-    gFileStatusModeFieldID = env->GetFieldID(gFileStatusClass, "mode", "I");
-    gFileStatusNlinkFieldID = env->GetFieldID(gFileStatusClass, "nlink", "I");
-    gFileStatusUidFieldID = env->GetFieldID(gFileStatusClass, "uid", "I");
-    gFileStatusGidFieldID = env->GetFieldID(gFileStatusClass, "gid", "I");
-    gFileStatusSizeFieldID = env->GetFieldID(gFileStatusClass, "size", "J");
-    gFileStatusBlksizeFieldID = env->GetFieldID(gFileStatusClass, "blksize", "I");
-    gFileStatusBlocksFieldID = env->GetFieldID(gFileStatusClass, "blocks", "J");
-    gFileStatusAtimeFieldID = env->GetFieldID(gFileStatusClass, "atime", "J");
-    gFileStatusMtimeFieldID = env->GetFieldID(gFileStatusClass, "mtime", "J");
-    gFileStatusCtimeFieldID = env->GetFieldID(gFileStatusClass, "ctime", "J");
-
-    return env->RegisterNatives(clazz, gMethods, 
-            sizeof(gMethods) / sizeof(JNINativeMethod)); 
-}
diff --git a/tests/tests/os/src/android/os/cts/AbiTest.java b/tests/tests/os/src/android/os/cts/AbiTest.java
index a342669..ee2c168 100644
--- a/tests/tests/os/src/android/os/cts/AbiTest.java
+++ b/tests/tests/os/src/android/os/cts/AbiTest.java
@@ -16,7 +16,7 @@
 
 package android.os.cts;
 
-import android.os.cts.ReadElf;
+import android.cts.util.ReadElf;
 
 import java.io.File;
 
diff --git a/tests/tests/os/src/android/os/cts/BuildVersionTest.java b/tests/tests/os/src/android/os/cts/BuildVersionTest.java
index e7ad28e..6069ee6 100644
--- a/tests/tests/os/src/android/os/cts/BuildVersionTest.java
+++ b/tests/tests/os/src/android/os/cts/BuildVersionTest.java
@@ -28,9 +28,8 @@
 public class BuildVersionTest extends TestCase {
 
     private static final String LOG_TAG = "BuildVersionTest";
-    private static final Set<String> EXPECTED_RELEASES =
-        new HashSet<String>(Arrays.asList("4.4W.1", "4.4W", "4.4", "4.4.1", "4.4.2", "4.4.3"));
-    private static final int EXPECTED_SDK = 20;
+    private static final Set<String> EXPECTED_RELEASES = new HashSet<String>(Arrays.asList("5.0"));
+    private static final int EXPECTED_SDK = 21;
     private static final String EXPECTED_BUILD_VARIANT = "user";
     private static final String EXPECTED_TAG = "release-keys";
 
@@ -38,8 +37,8 @@
     public void testReleaseVersion() {
         // Applications may rely on the exact release version
         assertAnyOf("BUILD.VERSION.RELEASE", Build.VERSION.RELEASE, EXPECTED_RELEASES);
-        assertEquals("" + EXPECTED_SDK, Build.VERSION.SDK);
-        assertEquals(EXPECTED_SDK, Build.VERSION.SDK_INT);
+        assertEquals("Build.VERSION.SDK", "" + EXPECTED_SDK, Build.VERSION.SDK);
+        assertEquals("Build.VERSION.SDK_INT", EXPECTED_SDK, Build.VERSION.SDK_INT);
     }
 
     public void testIncremental() {
diff --git a/tests/tests/os/src/android/os/cts/ConditionVariableTest.java b/tests/tests/os/src/android/os/cts/ConditionVariableTest.java
index 559f890..cad9dec 100644
--- a/tests/tests/os/src/android/os/cts/ConditionVariableTest.java
+++ b/tests/tests/os/src/android/os/cts/ConditionVariableTest.java
@@ -16,6 +16,7 @@
 package android.os.cts;
 
 import junit.framework.TestCase;
+import android.cts.util.TestThread;
 import android.os.ConditionVariable;
 
 public class ConditionVariableTest extends TestCase {
diff --git a/tests/tests/os/src/android/os/cts/DebugTest.java b/tests/tests/os/src/android/os/cts/DebugTest.java
index c05c78a..c097240 100644
--- a/tests/tests/os/src/android/os/cts/DebugTest.java
+++ b/tests/tests/os/src/android/os/cts/DebugTest.java
@@ -22,6 +22,7 @@
 import java.util.logging.Logger;
 
 import android.content.Context;
+import android.cts.util.TestThread;
 import android.os.Debug;
 import android.test.AndroidTestCase;
 import dalvik.system.VMDebug;
diff --git a/tests/tests/os/src/android/os/cts/HandlerTest.java b/tests/tests/os/src/android/os/cts/HandlerTest.java
index fc775e4..7183d7e 100644
--- a/tests/tests/os/src/android/os/cts/HandlerTest.java
+++ b/tests/tests/os/src/android/os/cts/HandlerTest.java
@@ -17,6 +17,7 @@
 package android.os.cts;
 
 import junit.framework.TestCase;
+import android.cts.util.TestThread;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
diff --git a/tests/tests/os/src/android/os/cts/LocalService.java b/tests/tests/os/src/android/os/cts/LocalService.java
index 0353c23..cc427f8 100644
--- a/tests/tests/os/src/android/os/cts/LocalService.java
+++ b/tests/tests/os/src/android/os/cts/LocalService.java
@@ -18,6 +18,7 @@
 
 import android.app.Service;
 import android.content.Intent;
+import android.cts.util.IBinderParcelable;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Parcel;
diff --git a/tests/tests/os/src/android/os/cts/LooperTest.java b/tests/tests/os/src/android/os/cts/LooperTest.java
index e71b752..79a55c6 100644
--- a/tests/tests/os/src/android/os/cts/LooperTest.java
+++ b/tests/tests/os/src/android/os/cts/LooperTest.java
@@ -16,6 +16,7 @@
 
 package android.os.cts;
 
+import android.cts.util.TestThread;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
diff --git a/tests/tests/os/src/android/os/cts/SeccompTest.java b/tests/tests/os/src/android/os/cts/SeccompTest.java
index e2ddcc2..6c49337 100644
--- a/tests/tests/os/src/android/os/cts/SeccompTest.java
+++ b/tests/tests/os/src/android/os/cts/SeccompTest.java
@@ -21,8 +21,8 @@
 public class SeccompTest extends TestCase {
 
     public void testSeccomp() {
-        if (CpuFeatures.isArm64Cpu()) {
-            return; // seccomp not supported on arm64
+        if (CpuFeatures.isArm64Cpu() || CpuFeatures.isArm64CpuIn32BitMode()) {
+            return; // seccomp not yet supported on arm64
         }
         if (OSFeatures.needsSeccompSupport()) {
             assertTrue("Please enable seccomp support "
diff --git a/tests/tests/os/src/android/os/cts/TestThread.java b/tests/tests/os/src/android/os/cts/TestThread.java
deleted file mode 100644
index 1a28a20..0000000
--- a/tests/tests/os/src/android/os/cts/TestThread.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.os.cts;
-
-/**
- * Thread class for executing a Runnable containing assertions in a separate thread.
- * Uncaught exceptions in the Runnable are rethrown in the context of the the thread
- * calling the <code>runTest()</code> method.
- */
-public final class TestThread extends Thread {
-    private Throwable mThrowable;
-    private Runnable mTarget;
-
-    public TestThread(Runnable target) {
-        mTarget = target;
-    }
-
-    @Override
-    public final void run() {
-        try {
-            mTarget.run();
-        } catch (Throwable t) {
-            mThrowable = t;
-        }
-    }
-
-    /**
-     * Run the target Runnable object and wait until the test finish or throw
-     * out Exception if test fail.
-     *
-     * @param runTime
-     * @throws Throwable
-     */
-    public void runTest(long runTime) throws Throwable {
-        start();
-        joinAndCheck(runTime);
-    }
-
-    /**
-     * Get the Throwable object which is thrown when test running
-     * @return  The Throwable object
-     */
-    public Throwable getThrowable() {
-        return mThrowable;
-    }
-
-    /**
-     * Set the Throwable object which is thrown when test running
-     * @param t The Throwable object
-     */
-    public void setThrowable(Throwable t) {
-        mThrowable = t;
-    }
-
-    /**
-     * Wait for the test thread to complete and throw the stored exception if there is one.
-     *
-     * @param runTime The time to wait for the test thread to complete.
-     * @throws Throwable
-     */
-    public void joinAndCheck(long runTime) throws Throwable {
-        this.join(runTime);
-        if (this.isAlive()) {
-            this.interrupt();
-            this.join(runTime);
-            throw new Exception("Thread did not finish within allotted time.");
-        }
-        checkException();
-    }
-
-    /**
-     * Check whether there is an exception when running Runnable object.
-     * @throws Throwable
-     */
-    public void checkException() throws Throwable {
-        if (mThrowable != null) {
-            throw mThrowable;
-        }
-    }
-}
diff --git a/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java b/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java
index 7d2d4ff..a8e8e64 100644
--- a/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java
+++ b/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java
@@ -22,7 +22,7 @@
 import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
 import android.os.Environment;
-import android.os.cts.FileUtils;
+import android.cts.util.FileUtils;
 import android.os.storage.OnObbStateChangeListener;
 import android.os.storage.StorageManager;
 import android.test.AndroidTestCase;
diff --git a/tests/tests/permission/Android.mk b/tests/tests/permission/Android.mk
index 6d60499..6a7da5f 100644
--- a/tests/tests/permission/Android.mk
+++ b/tests/tests/permission/Android.mk
@@ -19,6 +19,9 @@
 
 LOCAL_MODULE_TAGS := tests
 
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
 LOCAL_JAVA_LIBRARIES := telephony-common
 
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner guava android-ex-camera2
diff --git a/tests/tests/permission/src/android/permission/cts/NoLocationPermissionTest.java b/tests/tests/permission/src/android/permission/cts/NoLocationPermissionTest.java
index 93e26ac..8fd4a59 100644
--- a/tests/tests/permission/src/android/permission/cts/NoLocationPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NoLocationPermissionTest.java
@@ -23,7 +23,6 @@
 import android.location.Location;
 import android.location.LocationListener;
 import android.location.LocationManager;
-import android.os.Build;
 import android.os.Bundle;
 import android.os.Looper;
 import android.telephony.PhoneStateListener;
@@ -288,7 +287,7 @@
      * {@link LocationManager#isProviderEnabled(String)} with given
      * provider completes without an exception. (Note that under the conditions
      * of these tests, that method threw SecurityException on OS levels before
-     * {@link android.os.Build.VERSION_CODES#L}. See the method's javadoc for
+     * {@link android.os.Build.VERSION_CODES#LOLLIPOP}. See the method's javadoc for
      * details.)
      *
      * @param provider the String provider name.
diff --git a/tests/tests/provider/Android.mk b/tests/tests/provider/Android.mk
index 81ff9ee..58a7516 100644
--- a/tests/tests/provider/Android.mk
+++ b/tests/tests/provider/Android.mk
@@ -18,6 +18,10 @@
 
 # don't include this package in any target
 LOCAL_MODULE_TAGS := optional
+
+# Include both the 32 and 64 bit versions of libs
+LOCAL_MULTILIB := both
+
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
@@ -25,6 +29,8 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
 
+LOCAL_JNI_SHARED_LIBRARIES := libcts_jni
+
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsProviderTestCases
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_PhotoTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_PhotoTest.java
index 45ba8b8..8c97c22 100644
--- a/tests/tests/provider/src/android/provider/cts/ContactsContract_PhotoTest.java
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_PhotoTest.java
@@ -19,6 +19,7 @@
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.cts.util.FileUtils;
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.CommonDataKinds.Photo;
 import android.provider.ContactsContract.Contacts;
diff --git a/tests/tests/provider/src/android/provider/cts/FileUtils.java b/tests/tests/provider/src/android/provider/cts/FileUtils.java
deleted file mode 100644
index 0766e6d..0000000
--- a/tests/tests/provider/src/android/provider/cts/FileUtils.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider.cts;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/** Bits and pieces copied from hidden API of android.os.FileUtils. */
-public class FileUtils {
-
-    /**
-     * Copy data from a source stream to destFile.
-     * Return true if succeed, return false if failed.
-     */
-    public static boolean copyToFile(InputStream inputStream, File destFile) {
-        try {
-            if (destFile.exists()) {
-                destFile.delete();
-            }
-            FileOutputStream out = new FileOutputStream(destFile);
-            try {
-                byte[] buffer = new byte[4096];
-                int bytesRead;
-                while ((bytesRead = inputStream.read(buffer)) >= 0) {
-                    out.write(buffer, 0, bytesRead);
-                }
-            } finally {
-                out.flush();
-                try {
-                    out.getFD().sync();
-                } catch (IOException e) {
-                }
-                out.close();
-            }
-            return true;
-        } catch (IOException e) {
-            return false;
-        }
-    }
-
-    public static void createFile(File file, int numBytes) throws IOException {
-        File parentFile = file.getParentFile();
-        if (parentFile != null) {
-            parentFile.mkdirs();
-        }
-        byte[] buffer = new byte[numBytes];
-        FileOutputStream output = new FileOutputStream(file);
-        try {
-            output.write(buffer);
-        } finally {
-            output.close();
-        }
-    }
-
-    public static byte[] readInputStreamFully(InputStream is) {
-        ByteArrayOutputStream os = new ByteArrayOutputStream();
-        byte[] buffer = new byte[32768];
-        int count;
-        try {
-            while ((count = is.read(buffer)) != -1) {
-                os.write(buffer, 0, count);
-            }
-            is.close();
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-        return os.toByteArray();
-    }
-}
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_AlbumsTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_AlbumsTest.java
index bad1108..84da62a 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_AlbumsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_AlbumsTest.java
@@ -21,6 +21,7 @@
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.res.AssetFileDescriptor;
+import android.cts.util.FileCopyHelper;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Environment;
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java
index 67396d4..0eae82b 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java
@@ -22,6 +22,7 @@
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
+import android.cts.util.FileCopyHelper;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Environment;
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Images_MediaTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Images_MediaTest.java
index bc86b0a..7469f8e 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Images_MediaTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Images_MediaTest.java
@@ -21,6 +21,8 @@
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
+import android.cts.util.FileCopyHelper;
+import android.cts.util.FileUtils;
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Images_ThumbnailsTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Images_ThumbnailsTest.java
index f161407..ec9db8b 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Images_ThumbnailsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Images_ThumbnailsTest.java
@@ -22,6 +22,7 @@
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
+import android.cts.util.FileCopyHelper;
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_VideoTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_VideoTest.java
index 2c9ebd1..89de9c6 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_VideoTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_VideoTest.java
@@ -21,6 +21,7 @@
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
+import android.cts.util.FileCopyHelper;
 import android.database.Cursor;
 import android.net.Uri;
 import android.provider.MediaStore.Video;
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Video_MediaTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Video_MediaTest.java
index c3f5070..f84b75c 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Video_MediaTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Video_MediaTest.java
@@ -22,6 +22,8 @@
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
+import android.cts.util.FileCopyHelper;
+import android.cts.util.FileUtils;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Environment;
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Video_ThumbnailsTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Video_ThumbnailsTest.java
index e74cce4..b6175be 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Video_ThumbnailsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Video_ThumbnailsTest.java
@@ -21,6 +21,7 @@
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
+import android.cts.util.FileCopyHelper;
 import android.database.Cursor;
 import android.media.MediaCodecInfo;
 import android.media.MediaCodecList;
diff --git a/tests/tests/provider/src/android/provider/cts/PhotoUtil.java b/tests/tests/provider/src/android/provider/cts/PhotoUtil.java
index 3f5f873..ec4fdef 100644
--- a/tests/tests/provider/src/android/provider/cts/PhotoUtil.java
+++ b/tests/tests/provider/src/android/provider/cts/PhotoUtil.java
@@ -19,6 +19,7 @@
 import com.android.cts.provider.R;
 
 import android.content.Context;
+import android.cts.util.FileUtils;
 
 import java.io.InputStream;
 
diff --git a/tests/tests/renderscript/Android.mk b/tests/tests/renderscript/Android.mk
index 81434ee..245c5b9 100644
--- a/tests/tests/renderscript/Android.mk
+++ b/tests/tests/renderscript/Android.mk
@@ -22,6 +22,9 @@
 # Don't include this package in any target.
 LOCAL_MODULE_TAGS := optional
 
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
 # When built, explicitly put it in the data partition.
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
diff --git a/tests/tests/rscpp/Android.mk b/tests/tests/rscpp/Android.mk
index f7d586f..60adc05 100644
--- a/tests/tests/rscpp/Android.mk
+++ b/tests/tests/rscpp/Android.mk
@@ -22,6 +22,9 @@
 # Don't include this package in any target.
 LOCAL_MODULE_TAGS := optional
 
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
 # When built, explicitly put it in the data partition.
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
diff --git a/tests/tests/security/Android.mk b/tests/tests/security/Android.mk
index 10ad5f8..de58783 100644
--- a/tests/tests/security/Android.mk
+++ b/tests/tests/security/Android.mk
@@ -18,11 +18,14 @@
 
 LOCAL_MODULE_TAGS := tests
 
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestserver ctstestrunner ctsdeviceutil guava
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_JNI_SHARED_LIBRARIES := libctssecurity_jni
+LOCAL_JNI_SHARED_LIBRARIES := libctssecurity_jni libcts_jni
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)\
                    src/android/security/cts/activity/ISecureRandomService.aidl
diff --git a/tests/tests/security/jni/Android.mk b/tests/tests/security/jni/Android.mk
index 84f62c0..fa862c1 100644
--- a/tests/tests/security/jni/Android.mk
+++ b/tests/tests/security/jni/Android.mk
@@ -31,7 +31,6 @@
 		android_security_cts_SeccompDeathTestService.cpp \
 		android_security_cts_SELinuxTest.cpp \
 		android_security_cts_MMapExecutableTest.cpp \
-		android_security_cts_FileUtils.cpp \
 		android_security_cts_NetlinkSocket.cpp
 
 LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
diff --git a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
index d9a5f28..0e91b4e 100644
--- a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
+++ b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
@@ -26,7 +26,6 @@
 extern int register_android_security_cts_SeccompDeathTestService(JNIEnv*);
 extern int register_android_security_cts_SELinuxTest(JNIEnv*);
 extern int register_android_security_cts_MMapExecutableTest(JNIEnv* env);
-extern int register_android_security_cts_FileUtils(JNIEnv*);
 
 jint JNI_OnLoad(JavaVM *vm, void *reserved) {
     JNIEnv *env = NULL;
@@ -67,10 +66,6 @@
         return JNI_ERR;
     }
 
-    if (register_android_security_cts_FileUtils(env)) {
-        return JNI_ERR;
-    }
-
     if (register_android_security_cts_NetlinkSocket(env)) {
         return JNI_ERR;
     }
diff --git a/tests/tests/security/src/android/security/cts/AslrTest.java b/tests/tests/security/src/android/security/cts/AslrTest.java
index f1552f6..913b49b 100644
--- a/tests/tests/security/src/android/security/cts/AslrTest.java
+++ b/tests/tests/security/src/android/security/cts/AslrTest.java
@@ -24,7 +24,7 @@
 import java.io.FileReader;
 import java.io.IOException;
 
-import android.security.cts.ReadElf;
+import android.cts.util.ReadElf;
 
 /**
  * Verify that ASLR is properly enabled on Android Compatible devices.
diff --git a/tests/tests/security/src/android/security/cts/BannedFilesTest.java b/tests/tests/security/src/android/security/cts/BannedFilesTest.java
index a71dcce..8076f8e 100644
--- a/tests/tests/security/src/android/security/cts/BannedFilesTest.java
+++ b/tests/tests/security/src/android/security/cts/BannedFilesTest.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.security.cts.FileUtils;
+import android.cts.util.FileUtils;
 
 import junit.framework.TestCase;
 
diff --git a/tests/tests/security/src/android/security/cts/FileUtils.java b/tests/tests/security/src/android/security/cts/FileUtils.java
deleted file mode 100644
index 3708f68..0000000
--- a/tests/tests/security/src/android/security/cts/FileUtils.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.cts;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/** Bits and pieces copied from hidden API of android.os.FileUtils. */
-public class FileUtils {
-
-    public static final int S_IFMT  = 0170000;
-    public static final int S_IFSOCK = 0140000;
-    public static final int S_IFLNK = 0120000;
-    public static final int S_IFREG = 0100000;
-    public static final int S_IFBLK = 0060000;
-    public static final int S_IFDIR = 0040000;
-    public static final int S_IFCHR = 0020000;
-    public static final int S_IFIFO = 0010000;
-
-    public static final int S_ISUID = 0004000;
-    public static final int S_ISGID = 0002000;
-    public static final int S_ISVTX = 0001000;
-
-    public static final int S_IRWXU = 00700;
-    public static final int S_IRUSR = 00400;
-    public static final int S_IWUSR = 00200;
-    public static final int S_IXUSR = 00100;
-
-    public static final int S_IRWXG = 00070;
-    public static final int S_IRGRP = 00040;
-    public static final int S_IWGRP = 00020;
-    public static final int S_IXGRP = 00010;
-
-    public static final int S_IRWXO = 00007;
-    public static final int S_IROTH = 00004;
-    public static final int S_IWOTH = 00002;
-    public static final int S_IXOTH = 00001;
-
-    static {
-        System.loadLibrary("ctssecurity_jni");
-    }
-
-    public static class FileStatus {
-
-        public int dev;
-        public int ino;
-        public int mode;
-        public int nlink;
-        public int uid;
-        public int gid;
-        public int rdev;
-        public long size;
-        public int blksize;
-        public long blocks;
-        public long atime;
-        public long mtime;
-        public long ctime;
-
-        public boolean hasModeFlag(int flag) {
-            if (((S_IRWXU | S_IRWXG | S_IRWXO) & flag) != flag) {
-                throw new IllegalArgumentException("Inappropriate flag " + flag);
-            }
-            return (mode & flag) == flag;
-        }
-
-        public boolean isOfType(int type) {
-            if ((type & S_IFMT) != type) {
-                throw new IllegalArgumentException("Unknown type " + type);
-            }
-            return (mode & S_IFMT) == type;
-        }
-    }
-
-    /**
-     * @param path of the file to stat
-     * @param status object to set the fields on
-     * @param statLinks or don't stat links (lstat vs stat)
-     * @return whether or not we were able to stat the file
-     */
-    public native static boolean getFileStatus(String path, FileStatus status, boolean statLinks);
-
-    public native static String getUserName(int uid);
-
-    public native static String getGroupName(int gid);
-
-    public native static int setPermissions(String file, int mode);
-
-    /**
-     * Copy data from a source stream to destFile.
-     * Return true if succeed, return false if failed.
-     */
-    public static boolean copyToFile(InputStream inputStream, File destFile) {
-        try {
-            if (destFile.exists()) {
-                destFile.delete();
-            }
-            FileOutputStream out = new FileOutputStream(destFile);
-            try {
-                byte[] buffer = new byte[4096];
-                int bytesRead;
-                while ((bytesRead = inputStream.read(buffer)) >= 0) {
-                    out.write(buffer, 0, bytesRead);
-                }
-            } finally {
-                out.flush();
-                try {
-                    out.getFD().sync();
-                } catch (IOException e) {
-                }
-                out.close();
-            }
-            return true;
-        } catch (IOException e) {
-            return false;
-        }
-    }
-
-    public static void createFile(File file, int numBytes) throws IOException {
-        File parentFile = file.getParentFile();
-        if (parentFile != null) {
-            parentFile.mkdirs();
-        }
-        byte[] buffer = new byte[numBytes];
-        FileOutputStream output = new FileOutputStream(file);
-        try {
-            output.write(buffer);
-        } finally {
-            output.close();
-        }
-    }
-
-    public static byte[] readInputStreamFully(InputStream is) {
-        ByteArrayOutputStream os = new ByteArrayOutputStream();
-        byte[] buffer = new byte[32768];
-        int count;
-        try {
-            while ((count = is.read(buffer)) != -1) {
-                os.write(buffer, 0, count);
-            }
-            is.close();
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-        return os.toByteArray();
-    }
-}
diff --git a/tests/tests/security/src/android/security/cts/ReadElf.java b/tests/tests/security/src/android/security/cts/ReadElf.java
deleted file mode 100644
index a9a4e3c..0000000
--- a/tests/tests/security/src/android/security/cts/ReadElf.java
+++ /dev/null
@@ -1,523 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.cts;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * A poor man's implementation of the readelf command. This program is
- * designed to parse ELF (Executable and Linkable Format) files.
- */
-public class ReadElf implements AutoCloseable {
-    /** The magic values for the ELF identification. */
-    private static final byte[] ELF_IDENT = {
-            (byte) 0x7F, (byte) 'E', (byte) 'L', (byte) 'F',
-    };
-
-    private static final int EI_CLASS = 4;
-    private static final int EI_DATA = 5;
-
-    private static final int EM_386 = 3;
-    private static final int EM_MIPS = 8;
-    private static final int EM_ARM = 40;
-    // http://en.wikipedia.org/wiki/Qualcomm_Hexagon
-    private static final int EM_QDSP6 = 164;
-
-    /** Size of the e_ident[] structure in the ELF header. */
-    private static final int EI_NIDENT = 16;
-
-    /** Offset from end of ident structure in half-word sizes. */
-    private static final int OFFSET_TYPE = 0;
-
-    /** Machine type. */
-    private static final int OFFSET_MACHINE = 1;
-
-    /** ELF version. */
-    private static final int OFFSET_VERSION = 2;
-
-    /**
-     * The offset to which the system transfers control. e.g., the first thing
-     * executed.
-     */
-    private static final int OFFSET_ENTRY = 4;
-
-    /** Program header offset in bytes. */
-    private static final int OFFSET_PHOFF = 6;
-
-    /** Segment header offset in bytes. */
-    private static final int OFFSET_SHOFF = 8;
-
-    /** Processor-specific flags for binary. */
-    private static final int OFFSET_FLAGS = 10;
-
-    /** ELF header size in bytes. */
-    private static final int OFFSET_EHSIZE = 12;
-
-    /** All program headers entry size in bytes. */
-    private static final int OFFSET_PHENTSIZE = 13;
-
-    /** Number of program headers in ELF. */
-    private static final int OFFSET_PHNUM = 14;
-
-    /** All segment headers entry size in bytes. */
-    private static final int OFFSET_SHENTSIZE = 15;
-
-    /** Number of segment headers in ELF. */
-    private static final int OFFSET_SHNUM = 16;
-
-    /** The section header index that refers to string table. */
-    private static final int OFFSET_SHSTRNDX = 17;
-
-    /** Program header offset for type of this program header. */
-    private static final int PHOFF_TYPE = 0;
-
-    /** Program header offset for absolute offset in file. */
-    private static final int PHOFF_OFFSET = 2;
-
-    /** Program header offset for virtual address. */
-    private static final int PHOFF_VADDR = 4;
-
-    /** Program header offset for physical address. */
-    private static final int PHOFF_PADDR = 6;
-
-    /** Program header offset for file size in bytes. */
-    private static final int PHOFF_FILESZ = 8;
-
-    /** Program header offset for memory size in bytes. */
-    private static final int PHOFF_MEMSZ = 10;
-
-    /** Program header offset for flags. */
-    private static final int PHOFF_FLAGS = 12;
-
-    /**
-     * Program header offset for required alignment. 0 or 1 means no alignment
-     * necessary.
-     */
-    private static final int PHOFF_ALIGN = 14;
-
-    /** Index into string pool for segment name. */
-    private static final long SHOFF_NAME = 0;
-
-    /** Segment header offset for type (half-words) */
-    private static final long SHOFF_TYPE = 2;
-
-    /** Segment header offset for offset (meta!) (half-words) */
-    private static final long SHOFF_OFFSET = 8;
-
-    /** Segment header offset for size (half-words) */
-    private static final long SHOFF_SIZE = 10;
-
-    /** Data is presented in LSB format. */
-    private static final int ELFDATA2LSB = 1;
-
-    /** Date is presented in MSB format. */
-    private static final int ELFDATA2MSB = 2;
-
-    private static final int ELFCLASS32 = 1;
-
-    private static final int ELFCLASS64 = 2;
-
-    private static final long PT_LOAD = 1;
-
-    /** Section Type: Symbol Table */
-    private static final int SHT_SYMTAB = 2;
-
-    /** Section Type: String Table */
-    private static final int SHT_STRTAB = 3;
-
-    /** Section Type: Dynamic **/
-    private static final int SHT_DYNAMIC = 6;
-
-    /** Section Type: Dynamic Symbol Table */
-    private static final int SHT_DYNSYM = 11;
-
-    /** Symbol Table Entry: Name offset */
-    private static final int SYMTAB_NAME = 0;
-
-    /** Symbol Table Entry: SymTab Info */
-    private static final int SYMTAB_ST_INFO = 6;
-
-    /** Symbol Table Entry size (half-words) */
-    private static final int SYMTAB_ENTRY_HALFWORD_SIZE = 7;
-
-    /**
-     * Symbol Table Entry size (extra in bytes) to cover "st_info" and
-     * "st_other"
-     */
-    private static final int SYMTAB_ENTRY_BYTE_EXTRA_SIZE = 2;
-
-    public static class Symbol {
-        public static final int STB_LOCAL = 0;
-
-        public static final int STB_GLOBAL = 1;
-
-        public static final int STB_WEAK = 2;
-
-        public static final int STB_LOPROC = 13;
-
-        public static final int STB_HIPROC = 15;
-
-        public final String name;
-
-        public final int bind;
-
-        public final int type;
-
-        Symbol(String name, int st_info) {
-            this.name = name;
-            this.bind = (st_info >> 4) & 0x0F;
-            this.type = st_info & 0x0F;
-        }
-    };
-
-    private final String mPath;
-    private final RandomAccessFile mFile;
-    private final byte[] mBuffer = new byte[512];
-    private int mEndian;
-    private boolean mIsDynamic;
-    private boolean mIsPIE;
-    private int mType;
-    private int mWordSize;
-    private int mHalfWordSize;
-
-    /** Symbol Table offset */
-    private long mSymTabOffset;
-
-    /** Symbol Table size */
-    private long mSymTabSize;
-
-    /** Dynamic Symbol Table offset */
-    private long mDynSymOffset;
-
-    /** Dynamic Symbol Table size */
-    private long mDynSymSize;
-
-    /** Section Header String Table offset */
-    private long mShStrTabOffset;
-
-    /** Section Header String Table size */
-    private long mShStrTabSize;
-
-    /** String Table offset */
-    private long mStrTabOffset;
-
-    /** String Table size */
-    private long mStrTabSize;
-
-    /** Dynamic String Table offset */
-    private long mDynStrOffset;
-
-    /** Dynamic String Table size */
-    private long mDynStrSize;
-
-    /** Symbol Table symbol names */
-    private Map<String, Symbol> mSymbols;
-
-    /** Dynamic Symbol Table symbol names */
-    private Map<String, Symbol> mDynamicSymbols;
-
-    public static ReadElf read(File file) throws IOException {
-        return new ReadElf(file);
-    }
-
-    public boolean isDynamic() {
-        return mIsDynamic;
-    }
-
-    public int getType() {
-        return mType;
-    }
-
-    public boolean isPIE() {
-        return mIsPIE;
-    }
-
-    private ReadElf(File file) throws IOException {
-        mPath = file.getPath();
-        mFile = new RandomAccessFile(file, "r");
-
-        if (mFile.length() < EI_NIDENT) {
-            throw new IllegalArgumentException("Too small to be an ELF file: " + file);
-        }
-
-        readIdent();
-        readHeader();
-    }
-
-    public void close() {
-        try {
-            mFile.close();
-        } catch (IOException ignored) {
-        }
-    }
-
-    protected void finalize() throws Throwable {
-        try {
-            close();
-        } finally {
-            super.finalize();
-        }
-    }
-
-    private void readHeader() throws IOException {
-        mType = readHalf(getHeaderOffset(OFFSET_TYPE));
-        int e_machine = readHalf(getHeaderOffset(OFFSET_MACHINE));
-        if (e_machine != EM_386 && e_machine != EM_MIPS && e_machine != EM_ARM &&
-                e_machine != EM_QDSP6) {
-            throw new IOException("Invalid ELF e_machine: " + e_machine + ": " + mPath);
-        }
-
-        final long shOffset = readWord(getHeaderOffset(OFFSET_SHOFF));
-        final int shNumber = readHalf(getHeaderOffset(OFFSET_SHNUM));
-        final int shSize = readHalf(getHeaderOffset(OFFSET_SHENTSIZE));
-        final int shStrIndex = readHalf(getHeaderOffset(OFFSET_SHSTRNDX));
-
-        readSectionHeaders(shOffset, shNumber, shSize, shStrIndex);
-
-        final long phOffset = readWord(getHeaderOffset(OFFSET_PHOFF));
-        final int phNumber = readHalf(getHeaderOffset(OFFSET_PHNUM));
-        final int phSize = readHalf(getHeaderOffset(OFFSET_PHENTSIZE));
-
-        readProgramHeaders(phOffset, phNumber, phSize);
-    }
-
-    private void readSectionHeaders(long tableOffset, int shNumber, int shSize, int shStrIndex)
-            throws IOException {
-        // Read the Section Header String Table offset first.
-        {
-            final long shStrTabShOffset = tableOffset + shStrIndex * shSize;
-            final long type = readWord(shStrTabShOffset + mHalfWordSize * SHOFF_TYPE);
-
-            if (type == SHT_STRTAB) {
-                mShStrTabOffset = readWord(shStrTabShOffset + mHalfWordSize * SHOFF_OFFSET);
-                mShStrTabSize = readWord(shStrTabShOffset + mHalfWordSize * SHOFF_SIZE);
-            }
-        }
-
-        for (int i = 0; i < shNumber; i++) {
-            // Don't bother to re-read the Section Header StrTab.
-            if (i == shStrIndex) {
-                continue;
-            }
-
-            final long shOffset = tableOffset + i * shSize;
-
-            final long type = readWord(shOffset + mHalfWordSize * SHOFF_TYPE);
-            if ((type == SHT_SYMTAB) || (type == SHT_DYNSYM)) {
-                final long nameOffset = readWord(shOffset + mHalfWordSize * SHOFF_NAME);
-                final long offset = readWord(shOffset + mHalfWordSize * SHOFF_OFFSET);
-                final long size = readWord(shOffset + mHalfWordSize * SHOFF_SIZE);
-
-                final String symTabName = readShStrTabEntry(nameOffset);
-                if (".symtab".equals(symTabName)) {
-                    mSymTabOffset = offset;
-                    mSymTabSize = size;
-                } else if (".dynsym".equals(symTabName)) {
-                    mDynSymOffset = offset;
-                    mDynSymSize = size;
-                }
-            } else if (type == SHT_STRTAB) {
-                final long nameOffset = readWord(shOffset + mHalfWordSize * SHOFF_NAME);
-                final long offset = readWord(shOffset + mHalfWordSize * SHOFF_OFFSET);
-                final long size = readWord(shOffset + mHalfWordSize * SHOFF_SIZE);
-
-                final String strTabName = readShStrTabEntry(nameOffset);
-                if (".strtab".equals(strTabName)) {
-                    mStrTabOffset = offset;
-                    mStrTabSize = size;
-                } else if (".dynstr".equals(strTabName)) {
-                    mDynStrOffset = offset;
-                    mDynStrSize = size;
-                }
-            } else if (type == SHT_DYNAMIC) {
-                mIsDynamic = true;
-            }
-        }
-    }
-
-    private void readProgramHeaders(long phOffset, int phNumber, int phSize) throws IOException {
-        for (int i = 0; i < phNumber; i++) {
-            final long baseOffset = phOffset + i * phSize;
-            final long type = readWord(baseOffset);
-            if (type == PT_LOAD) {
-                final long virtAddress = readWord(baseOffset + mHalfWordSize * PHOFF_VADDR);
-                if (virtAddress == 0) {
-                    mIsPIE = true;
-                }
-            }
-        }
-    }
-
-    private void readSymbolTable(Map<String, Symbol> symbolMap, long symStrOffset, long symStrSize,
-            long symOffset, long symSize) throws IOException {
-        final long symEnd = symOffset + symSize;
-        for (long off = symOffset; off < symEnd; off += SYMTAB_ENTRY_HALFWORD_SIZE * mHalfWordSize
-                + SYMTAB_ENTRY_BYTE_EXTRA_SIZE) {
-            long strOffset = readWord(off + SYMTAB_NAME);
-            if (strOffset == 0) {
-                continue;
-            }
-
-            final String symName = readStrTabEntry(symStrOffset, symStrSize, strOffset);
-            if (symName != null) {
-                final int st_info = readByte(off + SYMTAB_ST_INFO);
-                symbolMap.put(symName, new Symbol(symName, st_info));
-            }
-        }
-    }
-
-    private String readShStrTabEntry(long strOffset) throws IOException {
-        if ((mShStrTabOffset == 0) || (strOffset < 0) || (strOffset >= mShStrTabSize)) {
-            return null;
-        }
-
-        return readString(mShStrTabOffset + strOffset);
-    }
-
-    private String readStrTabEntry(long tableOffset, long tableSize, long strOffset)
-            throws IOException {
-        if ((tableOffset == 0) || (strOffset < 0) || (strOffset >= tableSize)) {
-            return null;
-        }
-
-        return readString(tableOffset + strOffset);
-    }
-
-    private int getHeaderOffset(int halfWorldOffset) {
-        return EI_NIDENT + halfWorldOffset * mHalfWordSize;
-    }
-
-    private int readByte(long offset) throws IOException {
-        mFile.seek(offset);
-        mFile.readFully(mBuffer, 0, 1);
-
-        return mBuffer[0] & 0xff;
-    }
-
-    private int readHalf(long offset) throws IOException {
-        mFile.seek(offset);
-        mFile.readFully(mBuffer, 0, mWordSize);
-
-        final int answer;
-        if (mEndian == ELFDATA2LSB) {
-            answer = mBuffer[1] << 8 | (mBuffer[0] & 0xff);
-        } else {
-            answer = mBuffer[0] << 8 | (mBuffer[1] & 0xff);
-        }
-
-        return answer;
-    }
-
-    private long readWord(long offset) throws IOException {
-        mFile.seek(offset);
-        mFile.readFully(mBuffer, 0, mWordSize);
-
-        int answer = 0;
-        if (mEndian == ELFDATA2LSB) {
-            for (int i = mWordSize - 1; i >= 0; i--) {
-                answer = (answer << 8) | (mBuffer[i] & 0xff);
-            }
-        } else {
-            final int N = mWordSize - 1;
-            for (int i = 0; i <= N; i++) {
-                answer = (answer << 8) | (mBuffer[i] & 0xff);
-            }
-        }
-
-        return answer;
-    }
-
-    private String readString(long offset) throws IOException {
-        mFile.seek(offset);
-        mFile.readFully(mBuffer, 0, (int) Math.min(mBuffer.length, mFile.length() - offset));
-
-        for (int i = 0; i < mBuffer.length; i++) {
-            if (mBuffer[i] == 0) {
-                return new String(mBuffer, 0, i);
-            }
-        }
-
-        return null;
-    }
-
-    private void readIdent() throws IOException {
-        mFile.seek(0);
-        mFile.readFully(mBuffer, 0, EI_NIDENT);
-
-        if ((mBuffer[0] != ELF_IDENT[0]) || (mBuffer[1] != ELF_IDENT[1])
-                || (mBuffer[2] != ELF_IDENT[2]) || (mBuffer[3] != ELF_IDENT[3])) {
-            throw new IllegalArgumentException("Invalid ELF file: " + mPath);
-        }
-
-        int elfClass = mBuffer[EI_CLASS];
-        if (elfClass == ELFCLASS32) {
-            mWordSize = 4;
-            mHalfWordSize = 2;
-        } else if (elfClass == ELFCLASS64) {
-            throw new IOException("Unsupported ELFCLASS64 file: " + mPath);
-        } else {
-            throw new IOException("Invalid ELF EI_CLASS: " + elfClass + ": " + mPath);
-        }
-
-        mEndian = mBuffer[EI_DATA];
-        if (mEndian == ELFDATA2LSB) {
-        } else if (mEndian == ELFDATA2MSB) {
-            throw new IOException("Unsupported ELFDATA2MSB file: " + mPath);
-        } else {
-            throw new IOException("Invalid ELF EI_DATA: " + mEndian + ": " + mPath);
-        }
-    }
-
-    public Symbol getSymbol(String name) {
-        if ((mSymTabOffset == 0) && (mSymTabSize == 0)) {
-            return null;
-        }
-
-        if (mSymbols == null) {
-            mSymbols = new HashMap<String, Symbol>();
-            try {
-                readSymbolTable(mSymbols, mStrTabOffset, mStrTabSize, mSymTabOffset, mSymTabSize);
-            } catch (IOException e) {
-                return null;
-            }
-        }
-
-        return mSymbols.get(name);
-    }
-
-    public Symbol getDynamicSymbol(String name) {
-        if ((mDynSymOffset == 0) && (mDynSymSize == 0)) {
-            return null;
-        }
-
-        if (mDynamicSymbols == null) {
-            mDynamicSymbols = new HashMap<String, Symbol>();
-            try {
-                readSymbolTable(mDynamicSymbols, mDynStrOffset, mDynStrSize, mDynSymOffset,
-                        mDynSymSize);
-            } catch (IOException e) {
-                return null;
-            }
-        }
-
-        return mDynamicSymbols.get(name);
-    }
-}
diff --git a/tests/tests/telephony/Android.mk b/tests/tests/telephony/Android.mk
index e15d0d5..85864f9 100644
--- a/tests/tests/telephony/Android.mk
+++ b/tests/tests/telephony/Android.mk
@@ -24,7 +24,7 @@
 
 LOCAL_JAVA_LIBRARIES := telephony-common
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner ctsdeviceutil
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/telephony/src/android/telephony/cts/CellLocationTest.java b/tests/tests/telephony/src/android/telephony/cts/CellLocationTest.java
index 00c9844..c1f5757 100644
--- a/tests/tests/telephony/src/android/telephony/cts/CellLocationTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/CellLocationTest.java
@@ -17,6 +17,8 @@
 
 
 import android.content.Context;
+import android.cts.util.ReadElf;
+import android.cts.util.TestThread;
 import android.os.Looper;
 import android.net.ConnectivityManager;
 import android.telephony.CellLocation;
diff --git a/tests/tests/telephony/src/android/telephony/cts/PhoneStateListenerTest.java b/tests/tests/telephony/src/android/telephony/cts/PhoneStateListenerTest.java
index 9d8f842..f0f977a 100644
--- a/tests/tests/telephony/src/android/telephony/cts/PhoneStateListenerTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/PhoneStateListenerTest.java
@@ -16,6 +16,8 @@
 package android.telephony.cts;
 
 import android.content.Context;
+import android.cts.util.ReadElf;
+import android.cts.util.TestThread;
 import android.os.Looper;
 import android.telephony.CellLocation;
 import android.telephony.PhoneStateListener;
diff --git a/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
index b9c720c..8575c32 100644
--- a/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
@@ -19,6 +19,8 @@
 import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.cts.util.ReadElf;
+import android.cts.util.TestThread;
 import android.net.ConnectivityManager;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
@@ -86,13 +88,11 @@
                     }
                 };
                 mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_CELL_LOCATION);
-
+                CellLocation.requestLocationUpdate();
                 Looper.loop();
             }
         });
         t.start();
-
-        CellLocation.requestLocationUpdate();
         synchronized (mLock) {
             while (!mOnCellLocationChangedCalled) {
                 mLock.wait();
@@ -104,24 +104,21 @@
         t = new TestThread(new Runnable() {
             public void run() {
                 Looper.prepare();
-
                 // unregister the listener
                 mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE);
                 mOnCellLocationChangedCalled = false;
                 // unregister again, to make sure doing so does not call the listener
                 mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE);
-
+                CellLocation.requestLocationUpdate();
                 Looper.loop();
             }
         });
-        t.start();
 
-        CellLocation.requestLocationUpdate();
+        t.start();
         synchronized (mLock) {
             mLock.wait(TOLERANCE);
         }
-        //Fix me: unregister for listener is not support today. Will be added soon
-        //assertFalse(mOnCellLocationChangedCalled);
+        assertFalse(mOnCellLocationChangedCalled);
     }
 
     /**
diff --git a/tests/tests/text/Android.mk b/tests/tests/text/Android.mk
index df2d324..7b2def1 100644
--- a/tests/tests/text/Android.mk
+++ b/tests/tests/text/Android.mk
@@ -23,7 +23,7 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctsdeviceutillegacy ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/text/AndroidManifest.xml b/tests/tests/text/AndroidManifest.xml
index f247f82..99a6ad5 100644
--- a/tests/tests/text/AndroidManifest.xml
+++ b/tests/tests/text/AndroidManifest.xml
@@ -64,14 +64,6 @@
             </intent-filter>
         </activity>
 
-        <activity android:name="android.text.method.cts.CtsActivity"
-            android:label="CtsActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
     </application>
 
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/text/src/android/text/cts/EmojiCtsActivity.java b/tests/tests/text/src/android/text/cts/EmojiCtsActivity.java
index eb88426..195bdf1 100644
--- a/tests/tests/text/src/android/text/cts/EmojiCtsActivity.java
+++ b/tests/tests/text/src/android/text/cts/EmojiCtsActivity.java
@@ -20,6 +20,7 @@
 
 import android.app.Activity;
 import android.os.Bundle;
+import android.cts.util.NullWebViewUtils;
 import android.webkit.WebView;
 
 public class EmojiCtsActivity extends Activity {
diff --git a/tests/tests/text/src/android/text/cts/EmojiTest.java b/tests/tests/text/src/android/text/cts/EmojiTest.java
index b753739..e1249f3 100644
--- a/tests/tests/text/src/android/text/cts/EmojiTest.java
+++ b/tests/tests/text/src/android/text/cts/EmojiTest.java
@@ -17,6 +17,7 @@
 package android.text.cts;
 
 import android.content.Context;
+import android.cts.util.NullWebViewUtils;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Paint;
@@ -27,6 +28,7 @@
 import android.view.View;
 import android.widget.TextView;
 import android.widget.EditText;
+import android.webkit.cts.WebViewOnUiThread;
 
 public class EmojiTest extends ActivityInstrumentationTestCase2<EmojiCtsActivity> {
 
diff --git a/tests/tests/text/src/android/text/cts/NullWebViewUtils.java b/tests/tests/text/src/android/text/cts/NullWebViewUtils.java
deleted file mode 100644
index 86d0843..0000000
--- a/tests/tests/text/src/android/text/cts/NullWebViewUtils.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.cts;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-
-/**
- * Utilities to enable the android.webkit.* CTS tests (and others that rely on a functioning
- * android.webkit.WebView implementation) to determine whether a functioning WebView is present
- * on the device or not.
- *
- * Test cases that require android.webkit.* classes should wrap their first usage of WebView in a
- * try catch block, and pass any exception that is thrown to
- * NullWebViewUtils.determineIfWebViewAvailable. The return value of
- * NullWebViewUtils.isWebViewAvailable will then determine if the test should expect to be able to
- * use a WebView.
- */
-public class NullWebViewUtils {
-
-    private static boolean sWebViewUnavailable;
-
-    /**
-     * @param context Current Activity context, used to query the PackageManager.
-     * @param t       An exception thrown by trying to invoke android.webkit.* APIs.
-     */
-    public static void determineIfWebViewAvailable(Context context, Throwable t) {
-        sWebViewUnavailable = !hasWebViewFeature(context) && checkCauseWasUnsupportedOperation(t);
-    }
-
-    /**
-     * After calling determineIfWebViewAvailable, this returns whether a WebView is available on the
-     * device and wheter the test can rely on it.
-     * @return True iff. PackageManager determined that there is no WebView on the device and the
-     *         exception thrown from android.webkit.* was UnsupportedOperationException.
-     */
-    public static boolean isWebViewAvailable() {
-        return !sWebViewUnavailable;
-    }
-
-    private static boolean hasWebViewFeature(Context context) {
-        // Query the system property that determins if there is a functional WebView on the device.
-        PackageManager pm = context.getPackageManager();
-        return pm.hasSystemFeature(PackageManager.FEATURE_WEBVIEW);
-    }
-
-    private static boolean checkCauseWasUnsupportedOperation(Throwable t) {
-        if (t == null) return false;
-        while (t.getCause() != null) {
-            t = t.getCause();
-        }
-        return t instanceof UnsupportedOperationException;
-    }
-
-    /**
-     * Some CTS tests (by design) first use android.webkit.* from a background thread. This helper
-     * allows the test to catch the UnsupportedOperationException from that background thread, and
-     * then query the result from the test main thread.
-     */
-    public static class NullWebViewFromThreadExceptionHandler
-            implements Thread.UncaughtExceptionHandler {
-        private Throwable mPendingException;
-
-        @Override
-        public void uncaughtException(Thread t, Throwable e) {
-            mPendingException = e;
-        }
-
-        public boolean isWebViewAvailable(Context context) {
-            return hasWebViewFeature(context) ||
-                    !checkCauseWasUnsupportedOperation(mPendingException);
-        }
-    }
-}
\ No newline at end of file
diff --git a/tests/tests/text/src/android/text/cts/WebViewOnUiThread.java b/tests/tests/text/src/android/text/cts/WebViewOnUiThread.java
deleted file mode 100644
index 3d62ce4..0000000
--- a/tests/tests/text/src/android/text/cts/WebViewOnUiThread.java
+++ /dev/null
@@ -1,980 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.cts;
-
-import android.cts.util.PollingCheck;
-import android.graphics.Bitmap;
-import android.graphics.Picture;
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.os.Looper;
-import android.os.Message;
-import android.os.SystemClock;
-import android.print.PrintDocumentAdapter;
-import android.test.InstrumentationTestCase;
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewParent;
-import android.webkit.DownloadListener;
-import android.webkit.CookieManager;
-import android.webkit.ValueCallback;
-import android.webkit.WebBackForwardList;
-import android.webkit.WebChromeClient;
-import android.webkit.WebSettings;
-import android.webkit.WebView.HitTestResult;
-import android.webkit.WebView.PictureListener;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-
-import junit.framework.Assert;
-
-import java.io.File;
-import java.util.concurrent.Callable;
-import java.util.Map;
-
-/**
- * Many tests need to run WebView code in the UI thread. This class
- * wraps a WebView so that calls are ensured to arrive on the UI thread.
- *
- * All methods may be run on either the UI thread or test thread.
- */
-public class WebViewOnUiThread {
-    /**
-     * The maximum time, in milliseconds (10 seconds) to wait for a load
-     * to be triggered.
-     */
-    private static final long LOAD_TIMEOUT = 10000;
-
-    /**
-     * Set to true after onPageFinished is called.
-     */
-    private boolean mLoaded;
-
-    /**
-     * Set to true after onNewPicture is called. Reset when onPageStarted
-     * is called.
-     */
-    private boolean mNewPicture;
-
-    /**
-     * The progress, in percentage, of the page load. Valid values are between
-     * 0 and 100.
-     */
-    private int mProgress;
-
-    /**
-     * The test that this class is being used in. Used for runTestOnUiThread.
-     */
-    private InstrumentationTestCase mTest;
-
-    /**
-     * The WebView that calls will be made on.
-     */
-    private WebView mWebView;
-
-    /**
-     * Initializes the webView with a WebViewClient, WebChromeClient,
-     * and PictureListener to prepare for loadUrlAndWaitForCompletion.
-     *
-     * A new WebViewOnUiThread should be called during setUp so as to
-     * reinitialize between calls.
-     *
-     * @param test The test in which this is being run.
-     * @param webView The webView that the methods should call.
-     * @see loadUrlAndWaitForCompletion
-     */
-    public WebViewOnUiThread(InstrumentationTestCase test, WebView webView) {
-        mTest = test;
-        mWebView = webView;
-        final WebViewClient webViewClient = new WaitForLoadedClient(this);
-        final WebChromeClient webChromeClient = new WaitForProgressClient(this);
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.setWebViewClient(webViewClient);
-                mWebView.setWebChromeClient(webChromeClient);
-                mWebView.setPictureListener(new WaitForNewPicture());
-            }
-        });
-    }
-
-    /**
-     * Called after a test is complete and the WebView should be disengaged from
-     * the tests.
-     */
-    public void cleanUp() {
-        clearHistory();
-        clearCache(true);
-        setPictureListener(null);
-        setWebChromeClient(null);
-        setWebViewClient(null);
-    }
-
-    /**
-     * Called from WaitForNewPicture, this is used to indicate that
-     * the page has been drawn.
-     */
-    synchronized public void onNewPicture() {
-        mNewPicture = true;
-        this.notifyAll();
-    }
-
-    /**
-     * Called from WaitForLoadedClient, this is used to clear the picture
-     * draw state so that draws before the URL begins loading don't count.
-     */
-    synchronized public void onPageStarted() {
-        mNewPicture = false; // Earlier paints won't count.
-    }
-
-    /**
-     * Called from WaitForLoadedClient, this is used to indicate that
-     * the page is loaded, but not drawn yet.
-     */
-    synchronized public void onPageFinished() {
-        mLoaded = true;
-        this.notifyAll();
-    }
-
-    /**
-     * Called from the WebChrome client, this sets the current progress
-     * for a page.
-     * @param progress The progress made so far between 0 and 100.
-     */
-    synchronized public void onProgressChanged(int progress) {
-        mProgress = progress;
-        this.notifyAll();
-    }
-
-    public void setWebViewClient(final WebViewClient webViewClient) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.setWebViewClient(webViewClient);
-            }
-        });
-    }
-
-    public void setWebChromeClient(final WebChromeClient webChromeClient) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.setWebChromeClient(webChromeClient);
-            }
-        });
-    }
-
-    public void setPictureListener(final PictureListener pictureListener) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.setPictureListener(pictureListener);
-            }
-        });
-    }
-
-    public void setNetworkAvailable(final boolean available) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.setNetworkAvailable(available);
-            }
-        });
-    }
-
-    public void setDownloadListener(final DownloadListener listener) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.setDownloadListener(listener);
-            }
-        });
-    }
-
-    public void setBackgroundColor(final int color) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.setBackgroundColor(color);
-            }
-        });
-    }
-
-    public void clearCache(final boolean includeDiskFiles) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.clearCache(includeDiskFiles);
-            }
-        });
-    }
-
-    public void clearHistory() {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.clearHistory();
-            }
-        });
-    }
-
-    public void requestFocus() {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.requestFocus();
-            }
-        });
-    }
-
-    public boolean canZoomIn() {
-        return getValue(new ValueGetter<Boolean>() {
-            @Override
-            public Boolean capture() {
-                return mWebView.canZoomIn();
-            }
-        });
-    }
-
-    public boolean zoomIn() {
-        return getValue(new ValueGetter<Boolean>() {
-            @Override
-            public Boolean capture() {
-                return mWebView.zoomIn();
-            }
-        });
-    }
-
-    public boolean zoomOut() {
-        return getValue(new ValueGetter<Boolean>() {
-            @Override
-            public Boolean capture() {
-                return mWebView.zoomOut();
-            }
-        });
-    }
-
-    public void setFindListener(final WebView.FindListener listener) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.setFindListener(listener);
-            }
-        });
-    }
-
-    public void removeJavascriptInterface(final String interfaceName) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.removeJavascriptInterface(interfaceName);
-            }
-        });
-    }
-
-    public void addJavascriptInterface(final Object object, final String name) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.addJavascriptInterface(object, name);
-            }
-        });
-    }
-
-    public void flingScroll(final int vx, final int vy) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.flingScroll(vx, vy);
-            }
-        });
-    }
-
-    public void requestFocusNodeHref(final Message hrefMsg) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.requestFocusNodeHref(hrefMsg);
-            }
-        });
-    }
-
-    public void requestImageRef(final Message msg) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.requestImageRef(msg);
-            }
-        });
-    }
-
-    public void setInitialScale(final int scaleInPercent) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.setInitialScale(scaleInPercent);
-            }
-        });
-    }
-
-    public void clearSslPreferences() {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.clearSslPreferences();
-            }
-        });
-    }
-
-    public void clearClientCertPreferences(final Runnable onCleared) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                WebView.clearClientCertPreferences(onCleared);
-            }
-        });
-    }
-
-    public void resumeTimers() {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.resumeTimers();
-            }
-        });
-    }
-
-    public void findNext(final boolean forward) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.findNext(forward);
-            }
-        });
-    }
-
-    public void clearMatches() {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.clearMatches();
-            }
-        });
-    }
-
-    /**
-     * Calls loadUrl on the WebView and then waits onPageFinished,
-     * onNewPicture and onProgressChange to reach 100.
-     * Test fails if the load timeout elapses.
-     * @param url The URL to load.
-     */
-    public void loadUrlAndWaitForCompletion(final String url) {
-        callAndWait(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.loadUrl(url);
-            }
-        });
-    }
-
-    /**
-     * Calls loadUrl on the WebView and then waits onPageFinished,
-     * onNewPicture and onProgressChange to reach 100.
-     * Test fails if the load timeout elapses.
-     * @param url The URL to load.
-     * @param extraHeaders The additional headers to be used in the HTTP request.
-     */
-    public void loadUrlAndWaitForCompletion(final String url,
-            final Map<String, String> extraHeaders) {
-        callAndWait(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.loadUrl(url, extraHeaders);
-            }
-        });
-    }
-
-    public void loadUrl(final String url) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.loadUrl(url);
-            }
-        });
-    }
-
-    public void stopLoading() {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.stopLoading();
-            }
-        });
-    }
-
-    public void postUrlAndWaitForCompletion(final String url, final byte[] postData) {
-        callAndWait(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.postUrl(url, postData);
-            }
-        });
-    }
-
-    public void loadDataAndWaitForCompletion(final String data,
-            final String mimeType, final String encoding) {
-        callAndWait(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.loadData(data, mimeType, encoding);
-            }
-        });
-    }
-
-    public void loadDataWithBaseURLAndWaitForCompletion(final String baseUrl,
-            final String data, final String mimeType, final String encoding,
-            final String historyUrl) {
-        callAndWait(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.loadDataWithBaseURL(baseUrl, data, mimeType, encoding,
-                        historyUrl);
-            }
-        });
-    }
-
-    /**
-     * Reloads a page and waits for it to complete reloading. Use reload
-     * if it is a form resubmission and the onFormResubmission responds
-     * by telling WebView not to resubmit it.
-     */
-    public void reloadAndWaitForCompletion() {
-        callAndWait(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.reload();
-            }
-        });
-    }
-
-    /**
-     * Reload the previous URL. Use reloadAndWaitForCompletion unless
-     * it is a form resubmission and the onFormResubmission responds
-     * by telling WebView not to resubmit it.
-     */
-    public void reload() {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.reload();
-            }
-        });
-    }
-
-    /**
-     * Use this only when JavaScript causes a page load to wait for the
-     * page load to complete. Otherwise use loadUrlAndWaitForCompletion or
-     * similar functions.
-     */
-    public void waitForLoadCompletion() {
-        waitForCriteria(LOAD_TIMEOUT,
-                new Callable<Boolean>() {
-                    @Override
-                    public Boolean call() {
-                        return isLoaded();
-                    }
-                });
-        clearLoad();
-    }
-
-    private void waitForCriteria(long timeout, Callable<Boolean> doneCriteria) {
-        if (isUiThread()) {
-            waitOnUiThread(timeout, doneCriteria);
-        } else {
-            waitOnTestThread(timeout, doneCriteria);
-        }
-    }
-
-    public String getTitle() {
-        return getValue(new ValueGetter<String>() {
-            @Override
-            public String capture() {
-                return mWebView.getTitle();
-            }
-        });
-    }
-
-    public WebSettings getSettings() {
-        return getValue(new ValueGetter<WebSettings>() {
-            @Override
-            public WebSettings capture() {
-                return mWebView.getSettings();
-            }
-        });
-    }
-
-    public WebBackForwardList copyBackForwardList() {
-        return getValue(new ValueGetter<WebBackForwardList>() {
-            @Override
-            public WebBackForwardList capture() {
-                return mWebView.copyBackForwardList();
-            }
-        });
-    }
-
-    public Bitmap getFavicon() {
-        return getValue(new ValueGetter<Bitmap>() {
-            @Override
-            public Bitmap capture() {
-                return mWebView.getFavicon();
-            }
-        });
-    }
-
-    public String getUrl() {
-        return getValue(new ValueGetter<String>() {
-            @Override
-            public String capture() {
-                return mWebView.getUrl();
-            }
-        });
-    }
-
-    public int getProgress() {
-        return getValue(new ValueGetter<Integer>() {
-            @Override
-            public Integer capture() {
-                return mWebView.getProgress();
-            }
-        });
-    }
-
-    public int getHeight() {
-        return getValue(new ValueGetter<Integer>() {
-            @Override
-            public Integer capture() {
-                return mWebView.getHeight();
-            }
-        });
-    }
-
-    public int getContentHeight() {
-        return getValue(new ValueGetter<Integer>() {
-            @Override
-            public Integer capture() {
-                return mWebView.getContentHeight();
-            }
-        });
-    }
-
-    public boolean savePicture(final Bundle b, final File dest) {
-        return getValue(new ValueGetter<Boolean>() {
-            @Override
-            public Boolean capture() {
-                return mWebView.savePicture(b, dest);
-            }
-        });
-    }
-
-    public boolean pageUp(final boolean top) {
-        return getValue(new ValueGetter<Boolean>() {
-            @Override
-            public Boolean capture() {
-                return mWebView.pageUp(top);
-            }
-        });
-    }
-
-    public boolean pageDown(final boolean bottom) {
-        return getValue(new ValueGetter<Boolean>() {
-            @Override
-            public Boolean capture() {
-                return mWebView.pageDown(bottom);
-            }
-        });
-    }
-
-    public int[] getLocationOnScreen() {
-        final int[] location = new int[2];
-        return getValue(new ValueGetter<int[]>() {
-            @Override
-            public int[] capture() {
-                mWebView.getLocationOnScreen(location);
-                return location;
-            }
-        });
-    }
-
-    public float getScale() {
-        return getValue(new ValueGetter<Float>() {
-            @Override
-            public Float capture() {
-                return mWebView.getScale();
-            }
-        });
-    }
-
-    public boolean requestFocus(final int direction,
-            final Rect previouslyFocusedRect) {
-        return getValue(new ValueGetter<Boolean>() {
-            @Override
-            public Boolean capture() {
-                return mWebView.requestFocus(direction, previouslyFocusedRect);
-            }
-        });
-    }
-
-    public HitTestResult getHitTestResult() {
-        return getValue(new ValueGetter<HitTestResult>() {
-            @Override
-            public HitTestResult capture() {
-                return mWebView.getHitTestResult();
-            }
-        });
-    }
-
-    public int getScrollX() {
-        return getValue(new ValueGetter<Integer>() {
-            @Override
-            public Integer capture() {
-                return mWebView.getScrollX();
-            }
-        });
-    }
-
-    public int getScrollY() {
-        return getValue(new ValueGetter<Integer>() {
-            @Override
-            public Integer capture() {
-                return mWebView.getScrollY();
-            }
-        });
-    }
-
-    public final DisplayMetrics getDisplayMetrics() {
-        return getValue(new ValueGetter<DisplayMetrics>() {
-            @Override
-            public DisplayMetrics capture() {
-                return mWebView.getContext().getResources().getDisplayMetrics();
-            }
-        });
-    }
-
-    public boolean requestChildRectangleOnScreen(final View child,
-            final Rect rect,
-            final boolean immediate) {
-        return getValue(new ValueGetter<Boolean>() {
-            @Override
-            public Boolean capture() {
-                return mWebView.requestChildRectangleOnScreen(child, rect,
-                        immediate);
-            }
-        });
-    }
-
-    public int findAll(final String find) {
-        return getValue(new ValueGetter<Integer>() {
-            @Override
-            public Integer capture() {
-                return mWebView.findAll(find);
-            }
-        });
-    }
-
-    public Picture capturePicture() {
-        return getValue(new ValueGetter<Picture>() {
-            @Override
-            public Picture capture() {
-                return mWebView.capturePicture();
-            }
-        });
-    }
-
-    public void evaluateJavascript(final String script, final ValueCallback<String> result) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.evaluateJavascript(script, result);
-            }
-        });
-    }
-
-    public WebView createWebView() {
-        return getValue(new ValueGetter<WebView>() {
-            @Override
-            public WebView capture() {
-                return new WebView(mWebView.getContext());
-            }
-        });
-    }
-
-    public PrintDocumentAdapter createPrintDocumentAdapter() {
-        return getValue(new ValueGetter<PrintDocumentAdapter>() {
-            @Override
-            public PrintDocumentAdapter capture() {
-                return mWebView.createPrintDocumentAdapter();
-            }
-        });
-    }
-
-    public void setLayoutHeightToMatchParent() {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                ViewParent parent = mWebView.getParent();
-                if (parent instanceof ViewGroup) {
-                    ((ViewGroup) parent).getLayoutParams().height =
-                        ViewGroup.LayoutParams.MATCH_PARENT;
-                }
-                mWebView.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
-                mWebView.requestLayout();
-            }
-        });
-    }
-
-    public void setAcceptThirdPartyCookies(final boolean accept) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                CookieManager.getInstance().setAcceptThirdPartyCookies(mWebView, accept);
-            }
-        });
-    }
-
-    public boolean acceptThirdPartyCookies() {
-        return getValue(new ValueGetter<Boolean>() {
-            @Override
-            public Boolean capture() {
-                return CookieManager.getInstance().acceptThirdPartyCookies(mWebView);
-            }
-        });
-    }
-
-    /**
-     * Helper for running code on the UI thread where an exception is
-     * a test failure. If this is already the UI thread then it runs
-     * the code immediately.
-     *
-     * @see runTestOnUiThread
-     * @param r The code to run in the UI thread
-     */
-    public void runOnUiThread(Runnable r) {
-        try {
-            if (isUiThread()) {
-                r.run();
-            } else {
-                mTest.runTestOnUiThread(r);
-            }
-        } catch (Throwable t) {
-            Assert.fail("Unexpected error while running on UI thread: "
-                    + t.getMessage());
-        }
-    }
-
-    /**
-     * Accessor for underlying WebView.
-     * @return The WebView being wrapped by this class.
-     */
-    public WebView getWebView() {
-        return mWebView;
-    }
-
-    private<T> T getValue(ValueGetter<T> getter) {
-        runOnUiThread(getter);
-        return getter.getValue();
-    }
-
-    private abstract class ValueGetter<T> implements Runnable {
-        private T mValue;
-
-        @Override
-        public void run() {
-            mValue = capture();
-        }
-
-        protected abstract T capture();
-
-        public T getValue() {
-           return mValue;
-        }
-    }
-
-    /**
-     * Returns true if the current thread is the UI thread based on the
-     * Looper.
-     */
-    private static boolean isUiThread() {
-        return (Looper.myLooper() == Looper.getMainLooper());
-    }
-
-    /**
-     * @return Whether or not the load has finished.
-     */
-    private synchronized boolean isLoaded() {
-        return mLoaded && mNewPicture && mProgress == 100;
-    }
-
-    /**
-     * Makes a WebView call, waits for completion and then resets the
-     * load state in preparation for the next load call.
-     * @param call The call to make on the UI thread prior to waiting.
-     */
-    private void callAndWait(Runnable call) {
-        Assert.assertTrue("WebViewOnUiThread.load*AndWaitForCompletion calls "
-                + "may not be mixed with load* calls directly on WebView "
-                + "without calling waitForLoadCompletion after the load",
-                !isLoaded());
-        clearLoad(); // clear any extraneous signals from a previous load.
-        runOnUiThread(call);
-        waitForLoadCompletion();
-    }
-
-    /**
-     * Called whenever a load has been completed so that a subsequent call to
-     * waitForLoadCompletion doesn't return immediately.
-     */
-    synchronized private void clearLoad() {
-        mLoaded = false;
-        mNewPicture = false;
-        mProgress = 0;
-    }
-
-    /**
-     * Uses a polling mechanism, while pumping messages to check when the
-     * criteria is met.
-     */
-    private void waitOnUiThread(long timeout, final Callable<Boolean> doneCriteria) {
-        new PollingCheck(timeout) {
-            @Override
-            protected boolean check() {
-                pumpMessages();
-                try {
-                    return doneCriteria.call();
-                } catch (Exception e) {
-                    Assert.fail("Unexpected error while checking the criteria: "
-                            + e.getMessage());
-                    return true;
-                }
-            }
-        }.run();
-    }
-
-    /**
-     * Uses a wait/notify to check when the criteria is met.
-     */
-    private synchronized void waitOnTestThread(long timeout, Callable<Boolean> doneCriteria) {
-        try {
-            long waitEnd = SystemClock.uptimeMillis() + timeout;
-            long timeRemaining = timeout;
-            while (!doneCriteria.call() && timeRemaining > 0) {
-                this.wait(timeRemaining);
-                timeRemaining = waitEnd - SystemClock.uptimeMillis();
-            }
-            Assert.assertTrue("Action failed to complete before timeout", doneCriteria.call());
-        } catch (InterruptedException e) {
-            // We'll just drop out of the loop and fail
-        } catch (Exception e) {
-            Assert.fail("Unexpected error while checking the criteria: "
-                    + e.getMessage());
-        }
-    }
-
-    /**
-     * Pumps all currently-queued messages in the UI thread and then exits.
-     * This is useful to force processing while running tests in the UI thread.
-     */
-    private void pumpMessages() {
-        class ExitLoopException extends RuntimeException {
-        }
-
-        // Force loop to exit when processing this. Loop.quit() doesn't
-        // work because this is the main Loop.
-        mWebView.getHandler().post(new Runnable() {
-            @Override
-            public void run() {
-                throw new ExitLoopException(); // exit loop!
-            }
-        });
-        try {
-            // Pump messages until our message gets through.
-            Looper.loop();
-        } catch (ExitLoopException e) {
-        }
-    }
-
-    /**
-     * A WebChromeClient used to capture the onProgressChanged for use
-     * in waitFor functions. If a test must override the WebChromeClient,
-     * it can derive from this class or call onProgressChanged
-     * directly.
-     */
-    public static class WaitForProgressClient extends WebChromeClient {
-        private WebViewOnUiThread mOnUiThread;
-
-        public WaitForProgressClient(WebViewOnUiThread onUiThread) {
-            mOnUiThread = onUiThread;
-        }
-
-        @Override
-        public void onProgressChanged(WebView view, int newProgress) {
-            super.onProgressChanged(view, newProgress);
-            mOnUiThread.onProgressChanged(newProgress);
-        }
-    }
-
-    /**
-     * A WebViewClient that captures the onPageFinished for use in
-     * waitFor functions. Using initializeWebView sets the WaitForLoadedClient
-     * into the WebView. If a test needs to set a specific WebViewClient and
-     * needs the waitForCompletion capability then it should derive from
-     * WaitForLoadedClient or call WebViewOnUiThread.onPageFinished.
-     */
-    public static class WaitForLoadedClient extends WebViewClient {
-        private WebViewOnUiThread mOnUiThread;
-
-        public WaitForLoadedClient(WebViewOnUiThread onUiThread) {
-            mOnUiThread = onUiThread;
-        }
-
-        @Override
-        public void onPageFinished(WebView view, String url) {
-            super.onPageFinished(view, url);
-            mOnUiThread.onPageFinished();
-        }
-
-        @Override
-        public void onPageStarted(WebView view, String url, Bitmap favicon) {
-            super.onPageStarted(view, url, favicon);
-            mOnUiThread.onPageStarted();
-        }
-    }
-
-    /**
-     * A PictureListener that captures the onNewPicture for use in
-     * waitForLoadCompletion. Using initializeWebView sets the PictureListener
-     * into the WebView. If a test needs to set a specific PictureListener and
-     * needs the waitForCompletion capability then it should call
-     * WebViewOnUiThread.onNewPicture.
-     */
-    private class WaitForNewPicture implements PictureListener {
-        @Override
-        public void onNewPicture(WebView view, Picture picture) {
-            WebViewOnUiThread.this.onNewPicture();
-        }
-    }
-}
diff --git a/tests/tests/text/src/android/text/cts/WidgetTestUtils.java b/tests/tests/text/src/android/text/cts/WidgetTestUtils.java
deleted file mode 100644
index d41b242..0000000
--- a/tests/tests/text/src/android/text/cts/WidgetTestUtils.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text.cts;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-
-import java.io.IOException;
-
-import junit.framework.Assert;
-
-/**
- * The useful methods for widget test.
- */
-public class WidgetTestUtils {
-    /**
-     * Assert that two bitmaps are equal.
-     *
-     * @param Bitmap b1 the first bitmap which needs to compare.
-     * @param Bitmap b2 the second bitmap which needs to compare.
-     */
-    public static void assertEquals(Bitmap b1, Bitmap b2) {
-        if (b1 == b2) {
-            return;
-        }
-
-        if (b1 == null || b2 == null) {
-            Assert.fail("the bitmaps are not equal");
-        }
-
-        // b1 and b2 are all not null.
-        if (b1.getWidth() != b2.getWidth() || b1.getHeight() != b2.getHeight()
-            || b1.getConfig() != b2.getConfig()) {
-            Assert.fail("the bitmaps are not equal");
-        }
-
-        int w = b1.getWidth();
-        int h = b1.getHeight();
-        int s = w * h;
-        int[] pixels1 = new int[s];
-        int[] pixels2 = new int[s];
-
-        b1.getPixels(pixels1, 0, w, 0, 0, w, h);
-        b2.getPixels(pixels2, 0, w, 0, 0, w, h);
-
-        for (int i = 0; i < s; i++) {
-            if (pixels1[i] != pixels2[i]) {
-                Assert.fail("the bitmaps are not equal");
-            }
-        }
-    }
-
-    /**
-     * Find beginning of the special element.
-     * @param parser XmlPullParser will be parsed.
-     * @param firstElementName the target element name.
-     *
-     * @throws XmlPullParserException if XML Pull Parser related faults occur.
-     * @throws IOException if I/O-related error occur when parsing.
-     */
-    public static final void beginDocument(XmlPullParser parser, String firstElementName)
-            throws XmlPullParserException, IOException {
-        Assert.assertNotNull(parser);
-        Assert.assertNotNull(firstElementName);
-
-        int type;
-        while ((type = parser.next()) != XmlPullParser.START_TAG
-                && type != XmlPullParser.END_DOCUMENT) {
-            ;
-        }
-
-        if (!parser.getName().equals(firstElementName)) {
-            throw new XmlPullParserException("Unexpected start tag: found " + parser.getName()
-                    + ", expected " + firstElementName);
-        }
-    }
-
-    /**
-     * Compare the expected pixels with actual, scaling for the target context density
-     *
-     * @throws AssertionFailedError
-     */
-    public static void assertScaledPixels(int expected, int actual, Context context) {
-        Assert.assertEquals(expected * context.getResources().getDisplayMetrics().density,
-                actual, 3);
-    }
-
-    /** Converts dips into pixels using the {@link Context}'s density. */
-    public static int convertDipToPixels(Context context, int dip) {
-      float density = context.getResources().getDisplayMetrics().density;
-      return Math.round(density * dip);
-    }
-
-    /**
-     * Retrieve a bitmap that can be used for comparison on any density
-     * @param resources
-     * @return the {@link Bitmap} or <code>null</code>
-     */
-    public static Bitmap getUnscaledBitmap(Resources resources, int resId) {
-        BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inScaled = false;
-        return BitmapFactory.decodeResource(resources, resId, options);
-    }
-
-    /**
-     * Retrieve a dithered bitmap that can be used for comparison on any density
-     * @param resources
-     * @param config the preferred config for the returning bitmap
-     * @return the {@link Bitmap} or <code>null</code>
-     */
-    public static Bitmap getUnscaledAndDitheredBitmap(Resources resources,
-            int resId, Bitmap.Config config) {
-        BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inDither = true;
-        options.inScaled = false;
-        options.inPreferredConfig = config;
-        return BitmapFactory.decodeResource(resources, resId, options);
-    }
-}
diff --git a/tests/tests/text/src/android/text/method/cts/ScrollingMovementMethodTest.java b/tests/tests/text/src/android/text/method/cts/ScrollingMovementMethodTest.java
index c186cde..73fd763 100644
--- a/tests/tests/text/src/android/text/method/cts/ScrollingMovementMethodTest.java
+++ b/tests/tests/text/src/android/text/method/cts/ScrollingMovementMethodTest.java
@@ -18,6 +18,7 @@
 
 import dalvik.annotation.KnownFailure;
 
+import android.cts.util.WidgetTestUtils;
 import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
 import android.text.Layout;
@@ -33,7 +34,6 @@
 import android.view.ViewGroup.LayoutParams;
 import android.widget.TextView;
 import android.widget.TextView.BufferType;
-import android.text.cts.WidgetTestUtils;
 
 /**
  * Test {@link ScrollingMovementMethod}. The class is an implementation of interface
diff --git a/tests/tests/text/src/android/text/style/cts/ImageSpanTest.java b/tests/tests/text/src/android/text/style/cts/ImageSpanTest.java
index a98c748..6f056d0 100644
--- a/tests/tests/text/src/android/text/style/cts/ImageSpanTest.java
+++ b/tests/tests/text/src/android/text/style/cts/ImageSpanTest.java
@@ -20,6 +20,7 @@
 
 
 import android.content.Context;
+import android.cts.util.WidgetTestUtils;
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
@@ -27,7 +28,6 @@
 import android.test.AndroidTestCase;
 import android.text.style.DynamicDrawableSpan;
 import android.text.style.ImageSpan;
-import android.text.cts.WidgetTestUtils;
 
 public class ImageSpanTest extends AndroidTestCase {
     public void testConstructor() {
diff --git a/tests/tests/usage/Android.mk b/tests/tests/usage/Android.mk
new file mode 100644
index 0000000..f245e5f
--- /dev/null
+++ b/tests/tests/usage/Android.mk
@@ -0,0 +1,33 @@
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsUsageStatsTestCases
+
+# 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_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/usage/AndroidManifest.xml b/tests/tests/usage/AndroidManifest.xml
new file mode 100644
index 0000000..11065d4
--- /dev/null
+++ b/tests/tests/usage/AndroidManifest.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.app.usage.cts">
+
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
+    <uses-permission android:name="android.permission.SET_TIME" />
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+
+        <activity android:name=".Activities$ActivityOne" />
+        <activity android:name=".Activities$ActivityTwo" />
+        <activity android:name=".Activities$ActivityThree" />
+        <activity android:name=".Activities$ActivityFour" />
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="android.app.usage.cts"
+                     android:label="CTS tests of android.app.usage">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
+
+</manifest>
+
diff --git a/tests/tests/usage/src/android/app/usage/cts/Activities.java b/tests/tests/usage/src/android/app/usage/cts/Activities.java
new file mode 100644
index 0000000..35c7904
--- /dev/null
+++ b/tests/tests/usage/src/android/app/usage/cts/Activities.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package android.app.usage.cts;
+
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.WindowManager;
+
+public final class Activities {
+    private static class KeepScreenOnActivity extends Activity {
+        @Override
+        protected void onCreate(@Nullable Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+        }
+    }
+
+    public static class ActivityOne extends KeepScreenOnActivity {}
+    public static class ActivityTwo extends KeepScreenOnActivity {}
+    public static class ActivityThree extends KeepScreenOnActivity {}
+    public static class ActivityFour extends KeepScreenOnActivity {}
+
+    private Activities() {}
+}
diff --git a/tests/tests/usage/src/android/app/usage/cts/UsageStatsTest.java b/tests/tests/usage/src/android/app/usage/cts/UsageStatsTest.java
new file mode 100644
index 0000000..5b1909a
--- /dev/null
+++ b/tests/tests/usage/src/android/app/usage/cts/UsageStatsTest.java
@@ -0,0 +1,304 @@
+/**
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package android.app.usage.cts;
+
+import android.app.Activity;
+import android.app.AppOpsManager;
+import android.app.Instrumentation;
+import android.app.usage.UsageEvents;
+import android.app.usage.UsageStats;
+import android.app.usage.UsageStatsManager;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
+import android.os.SystemClock;
+import android.test.InstrumentationTestCase;
+
+import java.io.FileInputStream;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import android.util.SparseLongArray;
+import junit.framework.AssertionFailedError;
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+import org.junit.Ignore;
+
+/**
+ * Test the UsageStats API. It is difficult to test the entire surface area
+ * of the API, as a lot of the testing depends on what data is already present
+ * on the device and for how long that data has been aggregating.
+ *
+ * These tests perform simple checks that each interval is of the correct duration,
+ * and that events do appear in the event log.
+ *
+ * Tests to add that are difficult to add now:
+ * - Invoking a device configuration change and then watching for it in the event log.
+ * - Changing the system time and verifying that all data has been correctly shifted
+ *   along with the new time.
+ * - Proper eviction of old data.
+ */
+public class UsageStatsTest extends InstrumentationTestCase {
+    private static final String APPOPS_SET_SHELL_COMMAND = "appops set {0} " +
+            AppOpsManager.OPSTR_GET_USAGE_STATS + " {1}";
+
+    private static final long MINUTE = 1000 * 60;
+    private static final long DAY = MINUTE * 60 * 24;
+    private static final long WEEK = 7 * DAY;
+    private static final long MONTH = 30 * DAY;
+    private static final long YEAR = 365 * DAY;
+    private static final long TIME_DIFF_THRESHOLD = 200;
+
+    private UsageStatsManager mUsageStatsManager;
+    private String mTargetPackage;
+    private ArrayList<Activity> mStartedActivities = new ArrayList<>();
+
+    @Override
+    protected void setUp() throws Exception {
+        mUsageStatsManager = (UsageStatsManager) getInstrumentation().getContext()
+                .getSystemService(Context.USAGE_STATS_SERVICE);
+        mTargetPackage = getInstrumentation().getContext().getPackageName();
+
+        setAppOpsMode("allow");
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        for (Activity activity : mStartedActivities) {
+            activity.finish();
+        }
+    }
+
+    private static void assertLessThan(long left, long right) {
+        if (left >= right) {
+            throw new AssertionFailedError("Expected " + left + " to be less than " + right);
+        }
+    }
+
+    private static void assertLessThanOrEqual(long left, long right) {
+        if (left > right) {
+            throw new AssertionFailedError("Expected " + left + " to be less than or equal to " + right);
+        }
+    }
+
+    private void setAppOpsMode(String mode) throws Exception {
+        final String command = MessageFormat.format(APPOPS_SET_SHELL_COMMAND,
+                getInstrumentation().getContext().getPackageName(), mode);
+        ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation()
+                .executeShellCommand(command);
+        try {
+            Streams.readFully(new FileInputStream(pfd.getFileDescriptor()));
+        } finally {
+            IoUtils.closeQuietly(pfd.getFileDescriptor());
+        }
+    }
+
+    private void launchSubActivity(Class<? extends Activity> clazz) {
+        final Instrumentation.ActivityResult result = new Instrumentation.ActivityResult(0, new Intent());
+        final Instrumentation.ActivityMonitor monitor = new Instrumentation.ActivityMonitor(clazz.getName(), result, false);
+        getInstrumentation().addMonitor(monitor);
+        launchActivity(mTargetPackage, clazz, null);
+        mStartedActivities.add(monitor.waitForActivity());
+    }
+
+    private void launchSubActivities(Class<? extends Activity>[] activityClasses) {
+        for (Class<? extends Activity> clazz : activityClasses) {
+            launchSubActivity(clazz);
+        }
+    }
+
+    public void testOrderedActivityLaunchSequenceInEventLog() throws Exception {
+        @SuppressWarnings("unchecked")
+        Class<? extends Activity>[] activitySequence = new Class[] {
+                Activities.ActivityOne.class,
+                Activities.ActivityTwo.class,
+                Activities.ActivityThree.class,
+        };
+
+        // Launch the series of Activities.
+        launchSubActivities(activitySequence);
+
+        final long endTime = System.currentTimeMillis();
+        final long startTime = endTime - DAY;
+        UsageEvents events = mUsageStatsManager.queryEvents(startTime, endTime);
+
+        // Consume all the events.
+        ArrayList<UsageEvents.Event> eventList = new ArrayList<>();
+        while (events.hasNextEvent()) {
+            UsageEvents.Event event = new UsageEvents.Event();
+            assertTrue(events.getNextEvent(event));
+            eventList.add(event);
+        }
+
+        // We expect 2 events per Activity launched (foreground + background)
+        // except for the last Activity, which was in the foreground when
+        // we queried the event log.
+        assertTrue(eventList.size() >= (activitySequence.length * 2) - 1);
+        final int offset = eventList.size() - ((activitySequence.length * 2) - 1);
+
+        final int activityCount = activitySequence.length;
+        for (int i = 0; i < activityCount; i++) {
+            int index = offset + (i * 2);
+
+            // Check for foreground event.
+            UsageEvents.Event event = eventList.get(index);
+            assertEquals(mTargetPackage, event.getPackageName());
+            assertEquals(activitySequence[i].getName(), event.getClassName());
+            assertEquals(UsageEvents.Event.MOVE_TO_FOREGROUND, event.getEventType());
+
+            index += 1;
+            if (i < activityCount - 1) {
+                // Check for background event.
+                event = eventList.get(index);
+                assertEquals(mTargetPackage, event.getPackageName());
+                assertEquals(activitySequence[i].getName(), event.getClassName());
+                assertEquals(UsageEvents.Event.MOVE_TO_BACKGROUND, event.getEventType());
+            }
+        }
+    }
+
+    /**
+     * We can't run this test because we are unable to change the system time.
+     * It would be nice to add a shell command or other to allow the shell user
+     * to set the time, thereby allowing this test to set the time using the UIAutomator.
+     */
+    @Ignore
+    public void ignore_testStatsAreShiftedInTimeWhenSystemTimeChanges() throws Exception {
+        launchSubActivity(Activities.ActivityOne.class);
+
+        long endTime = System.currentTimeMillis();
+        long startTime = endTime - MINUTE;
+        Map<String, UsageStats> statsMap = mUsageStatsManager.queryAndAggregateUsageStats(startTime, endTime);
+        assertFalse(statsMap.isEmpty());
+        assertTrue(statsMap.containsKey(mTargetPackage));
+        final UsageStats before = statsMap.get(mTargetPackage);
+
+        SystemClock.setCurrentTimeMillis(System.currentTimeMillis() - (DAY / 2));
+        try {
+            endTime = System.currentTimeMillis();
+            startTime = endTime - MINUTE;
+            statsMap = mUsageStatsManager.queryAndAggregateUsageStats(startTime, endTime);
+            assertFalse(statsMap.isEmpty());
+            assertTrue(statsMap.containsKey(mTargetPackage));
+            final UsageStats after = statsMap.get(mTargetPackage);
+            assertEquals(before.getPackageName(), after.getPackageName());
+
+            long diff = before.getFirstTimeStamp() - after.getFirstTimeStamp();
+            assertLessThan(Math.abs(diff - (DAY / 2)), TIME_DIFF_THRESHOLD);
+
+            assertEquals(before.getLastTimeStamp() - before.getFirstTimeStamp(),
+                    after.getLastTimeStamp() - after.getFirstTimeStamp());
+            assertEquals(before.getLastTimeUsed() - before.getFirstTimeStamp(),
+                    after.getLastTimeUsed() - after.getFirstTimeStamp());
+            assertEquals(before.getTotalTimeInForeground(), after.getTotalTimeInForeground());
+        } finally {
+            SystemClock.setCurrentTimeMillis(System.currentTimeMillis() + (DAY / 2));
+        }
+    }
+
+    public void testUsageEventsParceling() throws Exception {
+        final long startTime = System.currentTimeMillis();
+
+        @SuppressWarnings("unchecked")
+        Class<? extends Activity>[] activityClasses = new Class[] {
+                Activities.ActivityOne.class,
+                Activities.ActivityThree.class,
+                Activities.ActivityTwo.class,
+        };
+        launchSubActivities(activityClasses);
+
+        final long endTime = System.currentTimeMillis();
+        UsageEvents events = mUsageStatsManager.queryEvents(startTime - TIME_DIFF_THRESHOLD, endTime);
+        assertTrue(events.getNextEvent(new UsageEvents.Event()));
+
+        Parcel p = Parcel.obtain();
+        p.setDataPosition(0);
+        events.writeToParcel(p, 0);
+        p.setDataPosition(0);
+
+        UsageEvents reparceledEvents = UsageEvents.CREATOR.createFromParcel(p);
+
+        UsageEvents.Event e1 = new UsageEvents.Event();
+        UsageEvents.Event e2 = new UsageEvents.Event();
+        while (events.hasNextEvent() && reparceledEvents.hasNextEvent()) {
+            events.getNextEvent(e1);
+            reparceledEvents.getNextEvent(e2);
+            assertEquals(e1.getPackageName(), e2.getPackageName());
+            assertEquals(e1.getClassName(), e2.getClassName());
+            assertEquals(e1.getConfiguration(), e2.getConfiguration());
+            assertEquals(e1.getEventType(), e2.getEventType());
+            assertEquals(e1.getTimeStamp(), e2.getTimeStamp());
+        }
+
+        assertEquals(events.hasNextEvent(), reparceledEvents.hasNextEvent());
+    }
+
+    public void testPackageUsageStatsIntervals() throws Exception {
+        final long beforeTime = System.currentTimeMillis();
+
+        // Launch an Activity.
+        launchSubActivity(Activities.ActivityFour.class);
+
+        final long endTime = System.currentTimeMillis();
+
+        final SparseLongArray intervalLengths = new SparseLongArray();
+        intervalLengths.put(UsageStatsManager.INTERVAL_DAILY, DAY);
+        intervalLengths.put(UsageStatsManager.INTERVAL_WEEKLY, WEEK);
+        intervalLengths.put(UsageStatsManager.INTERVAL_MONTHLY, MONTH);
+        intervalLengths.put(UsageStatsManager.INTERVAL_YEARLY, YEAR);
+
+        final int intervalCount = intervalLengths.size();
+        for (int i = 0; i < intervalCount; i++) {
+            final int intervalType = intervalLengths.keyAt(i);
+            final long intervalDuration = intervalLengths.valueAt(i);
+            final long startTime = endTime - (2 * intervalDuration);
+            final List<UsageStats> statsList = mUsageStatsManager.queryUsageStats(intervalType, startTime, endTime);
+            assertFalse(statsList.isEmpty());
+
+            boolean foundPackage = false;
+            for (UsageStats stats : statsList) {
+                // Verify that each period is a day long.
+                assertLessThanOrEqual(stats.getLastTimeStamp() - stats.getFirstTimeStamp(), intervalDuration);
+                if (stats.getPackageName().equals(mTargetPackage) &&
+                        stats.getLastTimeUsed() >= beforeTime - TIME_DIFF_THRESHOLD) {
+                    foundPackage = true;
+                }
+            }
+
+            assertTrue("Did not find package " + mTargetPackage + " in interval " + intervalType, foundPackage);
+        }
+    }
+
+    public void testNoAccessSilentlyFails() throws Exception {
+        launchSubActivity(Activities.ActivityOne.class);
+
+        final long endTime = System.currentTimeMillis();
+        final long startTime = endTime - MINUTE;
+        List<UsageStats> stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_BEST,
+                startTime, endTime);
+        assertFalse(stats.isEmpty());
+
+        setAppOpsMode("default");
+
+        stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_BEST,
+                startTime, endTime);
+        assertTrue(stats.isEmpty());
+    }
+}
diff --git a/tests/tests/view/src/android/view/cts/ChoreographerTest.java b/tests/tests/view/src/android/view/cts/ChoreographerTest.java
index 3a34b2c..6862fac 100644
--- a/tests/tests/view/src/android/view/cts/ChoreographerTest.java
+++ b/tests/tests/view/src/android/view/cts/ChoreographerTest.java
@@ -16,16 +16,27 @@
 
 package android.view.cts;
 
-import android.test.AndroidTestCase;
+import android.test.InstrumentationTestCase;
 import android.view.Choreographer;
 
-public class ChoreographerTest extends AndroidTestCase {
+public class ChoreographerTest extends InstrumentationTestCase {
     private static final long NOMINAL_VSYNC_PERIOD = 16;
     private static final long DELAY_PERIOD = NOMINAL_VSYNC_PERIOD * 5;
     private static final long NANOS_PER_MS = 1000000;
     private static final Object TOKEN = new Object();
 
-    private Choreographer mChoreographer = Choreographer.getInstance();
+    private Choreographer mChoreographer;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                mChoreographer = Choreographer.getInstance();
+            }
+        });
+    }
 
     public void testFrameDelay() {
         assertTrue(Choreographer.getFrameDelay() > 0);
diff --git a/tests/tests/view/src/android/view/cts/MenuInflaterTest.java b/tests/tests/view/src/android/view/cts/MenuInflaterTest.java
index bd483f9..40d1d3d 100644
--- a/tests/tests/view/src/android/view/cts/MenuInflaterTest.java
+++ b/tests/tests/view/src/android/view/cts/MenuInflaterTest.java
@@ -23,6 +23,7 @@
 import android.app.Activity;
 import android.content.Context;
 import android.content.res.Resources;
+import android.cts.util.WidgetTestUtils;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.drawable.BitmapDrawable;
diff --git a/tests/tests/view/src/android/view/cts/ViewGroupCtsActivity.java b/tests/tests/view/src/android/view/cts/ViewGroupCtsActivity.java
index 71bb28c..880a450 100644
--- a/tests/tests/view/src/android/view/cts/ViewGroupCtsActivity.java
+++ b/tests/tests/view/src/android/view/cts/ViewGroupCtsActivity.java
@@ -17,7 +17,7 @@
 package android.view.cts;
 
 import android.app.Activity;
-import android.app.cts.CTSResult;
+import android.cts.util.CTSResult;
 import android.os.Bundle;
 import android.os.Handler;
 import android.widget.TextView;
diff --git a/tests/tests/view/src/android/view/cts/ViewGroupTest.java b/tests/tests/view/src/android/view/cts/ViewGroupTest.java
index 55428de..f1064a7 100644
--- a/tests/tests/view/src/android/view/cts/ViewGroupTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewGroupTest.java
@@ -19,9 +19,9 @@
 import com.android.internal.util.XmlUtils;
 
 
-import android.app.cts.CTSResult;
 import android.content.Context;
 import android.content.Intent;
+import android.cts.util.CTSResult;
 import android.content.res.XmlResourceParser;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
diff --git a/tests/tests/webkit/Android.mk b/tests/tests/webkit/Android.mk
index 1d593df..c2d8c3c 100644
--- a/tests/tests/webkit/Android.mk
+++ b/tests/tests/webkit/Android.mk
@@ -23,7 +23,7 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestserver ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctsdeviceutillegacy ctstestserver ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/webkit/src/android/webkit/cts/CookieManagerTest.java b/tests/tests/webkit/src/android/webkit/cts/CookieManagerTest.java
index 9db7c21..c612886 100644
--- a/tests/tests/webkit/src/android/webkit/cts/CookieManagerTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/CookieManagerTest.java
@@ -16,6 +16,7 @@
 
 package android.webkit.cts;
 
+import android.cts.util.NullWebViewUtils;
 import android.cts.util.PollingCheck;
 import android.test.ActivityInstrumentationTestCase2;
 import android.webkit.CookieManager;
diff --git a/tests/tests/webkit/src/android/webkit/cts/CookieSyncManagerCtsActivity.java b/tests/tests/webkit/src/android/webkit/cts/CookieSyncManagerCtsActivity.java
index 51eeed3..e623405 100644
--- a/tests/tests/webkit/src/android/webkit/cts/CookieSyncManagerCtsActivity.java
+++ b/tests/tests/webkit/src/android/webkit/cts/CookieSyncManagerCtsActivity.java
@@ -17,6 +17,7 @@
 package android.webkit.cts;
 
 import android.app.Activity;
+import android.cts.util.NullWebViewUtils;
 import android.os.Bundle;
 import android.webkit.CookieSyncManager;
 import android.webkit.WebView;
diff --git a/tests/tests/webkit/src/android/webkit/cts/CookieTest.java b/tests/tests/webkit/src/android/webkit/cts/CookieTest.java
index bc5e3b0..555266b 100644
--- a/tests/tests/webkit/src/android/webkit/cts/CookieTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/CookieTest.java
@@ -16,6 +16,7 @@
 
 package android.webkit.cts;
 
+import android.cts.util.NullWebViewUtils;
 import android.test.ActivityInstrumentationTestCase2;
 import android.webkit.CookieManager;
 import android.webkit.CookieSyncManager;
diff --git a/tests/tests/webkit/src/android/webkit/cts/GeolocationTest.java b/tests/tests/webkit/src/android/webkit/cts/GeolocationTest.java
index 63990bf..ba0e0e9 100644
--- a/tests/tests/webkit/src/android/webkit/cts/GeolocationTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/GeolocationTest.java
@@ -17,6 +17,7 @@
 package android.webkit.cts;
 
 import android.content.Context;
+import android.cts.util.NullWebViewUtils;
 import android.cts.util.PollingCheck;
 import android.graphics.Bitmap;
 import android.location.Criteria;
diff --git a/tests/tests/webkit/src/android/webkit/cts/HttpAuthHandlerTest.java b/tests/tests/webkit/src/android/webkit/cts/HttpAuthHandlerTest.java
index fbda04b..5c86987 100644
--- a/tests/tests/webkit/src/android/webkit/cts/HttpAuthHandlerTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/HttpAuthHandlerTest.java
@@ -16,6 +16,7 @@
 
 package android.webkit.cts;
 
+import android.cts.util.NullWebViewUtils;
 import android.test.ActivityInstrumentationTestCase2;
 import android.webkit.HttpAuthHandler;
 import android.webkit.WebView;
diff --git a/tests/tests/webkit/src/android/webkit/cts/NullWebViewUtils.java b/tests/tests/webkit/src/android/webkit/cts/NullWebViewUtils.java
deleted file mode 100644
index c52219f..0000000
--- a/tests/tests/webkit/src/android/webkit/cts/NullWebViewUtils.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.webkit.cts;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-
-/**
- * Utilities to enable the android.webkit.* CTS tests (and others that rely on a functioning
- * android.webkit.WebView implementation) to determine whether a functioning WebView is present
- * on the device or not.
- *
- * Test cases that require android.webkit.* classes should wrap their first usage of WebView in a
- * try catch block, and pass any exception that is thrown to
- * NullWebViewUtils.determineIfWebViewAvailable. The return value of
- * NullWebViewUtils.isWebViewAvailable will then determine if the test should expect to be able to
- * use a WebView.
- */
-public class NullWebViewUtils {
-
-    private static boolean sWebViewUnavailable;
-
-    /**
-     * @param context Current Activity context, used to query the PackageManager.
-     * @param t       An exception thrown by trying to invoke android.webkit.* APIs.
-     */
-    public static void determineIfWebViewAvailable(Context context, Throwable t) {
-        sWebViewUnavailable = !hasWebViewFeature(context) && checkCauseWasUnsupportedOperation(t);
-    }
-
-    /**
-     * After calling determineIfWebViewAvailable, this returns whether a WebView is available on the
-     * device and wheter the test can rely on it.
-     * @return True iff. PackageManager determined that there is no WebView on the device and the
-     *         exception thrown from android.webkit.* was UnsupportedOperationException.
-     */
-    public static boolean isWebViewAvailable() {
-        return !sWebViewUnavailable;
-    }
-
-    private static boolean hasWebViewFeature(Context context) {
-        // Query the system property that determins if there is a functional WebView on the device.
-        PackageManager pm = context.getPackageManager();
-        return pm.hasSystemFeature(PackageManager.FEATURE_WEBVIEW);
-    }
-
-    private static boolean checkCauseWasUnsupportedOperation(Throwable t) {
-        if (t == null) return false;
-        while (t.getCause() != null) {
-            t = t.getCause();
-        }
-        return t instanceof UnsupportedOperationException;
-    }
-
-    /**
-     * Some CTS tests (by design) first use android.webkit.* from a background thread. This helper
-     * allows the test to catch the UnsupportedOperationException from that background thread, and
-     * then query the result from the test main thread.
-     */
-    public static class NullWebViewFromThreadExceptionHandler
-            implements Thread.UncaughtExceptionHandler {
-        private Throwable mPendingException;
-
-        @Override
-        public void uncaughtException(Thread t, Throwable e) {
-            mPendingException = e;
-        }
-
-        public boolean isWebViewAvailable(Context context) {
-            return hasWebViewFeature(context) ||
-                    !checkCauseWasUnsupportedOperation(mPendingException);
-        }
-    }
-}
\ No newline at end of file
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebBackForwardListTest.java b/tests/tests/webkit/src/android/webkit/cts/WebBackForwardListTest.java
index 21a5b98..7d25b84 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebBackForwardListTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebBackForwardListTest.java
@@ -16,6 +16,7 @@
 
 package android.webkit.cts;
 
+import android.cts.util.NullWebViewUtils;
 import android.cts.util.PollingCheck;
 import android.test.ActivityInstrumentationTestCase2;
 import android.webkit.WebBackForwardList;
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebChromeClientTest.java b/tests/tests/webkit/src/android/webkit/cts/WebChromeClientTest.java
index 6a94a99..150fd86 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebChromeClientTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebChromeClientTest.java
@@ -16,6 +16,7 @@
 
 package android.webkit.cts;
 
+import android.cts.util.NullWebViewUtils;
 import android.cts.util.PollingCheck;
 import android.graphics.Bitmap;
 import android.os.Message;
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebHistoryItemTest.java b/tests/tests/webkit/src/android/webkit/cts/WebHistoryItemTest.java
index d4f326b..a6b647d 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebHistoryItemTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebHistoryItemTest.java
@@ -16,6 +16,7 @@
 
 package android.webkit.cts;
 
+import android.cts.util.NullWebViewUtils;
 import android.cts.util.PollingCheck;
 import android.graphics.Bitmap;
 import android.test.ActivityInstrumentationTestCase2;
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java b/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
index 3e7a592..33a9cee 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
@@ -16,6 +16,7 @@
 package android.webkit.cts;
 
 import android.content.Context;
+import android.cts.util.NullWebViewUtils;
 import android.cts.util.PollingCheck;
 import android.graphics.Bitmap;
 import android.net.http.SslError;
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
index 2430c8c..5b906ba 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
@@ -17,6 +17,7 @@
 package android.webkit.cts;
 
 import android.cts.util.EvaluateJsResultPollingCheck;
+import android.cts.util.NullWebViewUtils;
 import android.cts.util.PollingCheck;
 import android.graphics.Bitmap;
 import android.os.Message;
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewCtsActivity.java b/tests/tests/webkit/src/android/webkit/cts/WebViewCtsActivity.java
index d809a42..9af7266 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewCtsActivity.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewCtsActivity.java
@@ -19,6 +19,7 @@
 import com.android.cts.webkit.R;
 
 import android.app.Activity;
+import android.cts.util.NullWebViewUtils;
 import android.os.Bundle;
 import android.view.ViewGroup;
 import android.view.ViewParent;
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewSslTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewSslTest.java
index 8aa0145..378bf6e 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewSslTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewSslTest.java
@@ -16,6 +16,7 @@
 
 package android.webkit.cts;
 
+import android.cts.util.NullWebViewUtils;
 import android.cts.util.PollingCheck;
 import android.net.Uri;
 import android.net.http.SslCertificate;
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java
index 8f4dcc2..776cfab 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java
@@ -18,6 +18,7 @@
 
 
 import android.content.Context;
+import android.cts.util.NullWebViewUtils;
 import android.cts.util.PollingCheck;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
index 1d8a02a..ef64f4d 100755
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.res.AssetManager;
 import android.cts.util.EvaluateJsResultPollingCheck;
+import android.cts.util.NullWebViewUtils;
 import android.cts.util.PollingCheck;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.Config;
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebView_WebViewTransportTest.java b/tests/tests/webkit/src/android/webkit/cts/WebView_WebViewTransportTest.java
index 0c04706..1db7fca 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebView_WebViewTransportTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebView_WebViewTransportTest.java
@@ -16,6 +16,7 @@
 
 package android.webkit.cts;
 
+import android.cts.util.NullWebViewUtils;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
 import android.webkit.WebView;
diff --git a/tests/tests/widget/res/layout/autocompletetextview_layout.xml b/tests/tests/widget/res/layout/autocompletetextview_layout.xml
index 7fd183c..25a8541 100644
--- a/tests/tests/widget/res/layout/autocompletetextview_layout.xml
+++ b/tests/tests/widget/res/layout/autocompletetextview_layout.xml
@@ -28,5 +28,6 @@
         android:completionThreshold="1"
         android:completionHint="@string/tabs_1"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content" />
+        android:layout_height="wrap_content"
+        android:inputType="none"/>
 </LinearLayout>
diff --git a/tests/tests/widget/res/layout/popupwindow.xml b/tests/tests/widget/res/layout/popupwindow.xml
index e6b0aed..2508115 100644
--- a/tests/tests/widget/res/layout/popupwindow.xml
+++ b/tests/tests/widget/res/layout/popupwindow.xml
@@ -16,17 +16,16 @@
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                 android:layout_width="match_parent"
-                android:layout_height="wrap_content"
+                android:layout_height="match_parent"
                 android:orientation="vertical">
 
     <TextView android:id="@+id/anchor_upper"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:text="@string/text_view_hint"
-        android:layout_weight="1"/>
+        android:text="@string/text_view_hint" />
 
     <LinearLayout android:layout_width="match_parent"
-                android:layout_height="wrap_content"
+                android:layout_height="0dp"
                 android:layout_weight="1">
 
         <TextView android:id="@+id/anchor_middle_left"
@@ -46,7 +45,6 @@
     <TextView android:id="@+id/anchor_lower"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:text="@string/text_view_hint"
-        android:layout_weight="1"/>
+        android:text="@string/text_view_hint" />
 
 </LinearLayout>
diff --git a/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java b/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java
index b6a96fb..9d8c7d2 100644
--- a/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java
@@ -25,6 +25,7 @@
 import android.app.Instrumentation;
 import android.content.Context;
 import android.cts.util.PollingCheck;
+import android.cts.util.WidgetTestUtils;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Rect;
diff --git a/tests/tests/widget/src/android/widget/cts/AbsListView_LayoutParamsTest.java b/tests/tests/widget/src/android/widget/cts/AbsListView_LayoutParamsTest.java
index 413bc2a..305a9e2 100644
--- a/tests/tests/widget/src/android/widget/cts/AbsListView_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AbsListView_LayoutParamsTest.java
@@ -21,6 +21,7 @@
 
 import org.xmlpull.v1.XmlPullParser;
 
+import android.cts.util.WidgetTestUtils;
 import android.test.AndroidTestCase;
 import android.util.AttributeSet;
 import android.util.Xml;
diff --git a/tests/tests/widget/src/android/widget/cts/AbsoluteLayoutTest.java b/tests/tests/widget/src/android/widget/cts/AbsoluteLayoutTest.java
index 053f42b..bac2479 100644
--- a/tests/tests/widget/src/android/widget/cts/AbsoluteLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AbsoluteLayoutTest.java
@@ -24,6 +24,7 @@
 
 import android.app.Activity;
 import android.content.Context;
+import android.cts.util.WidgetTestUtils;
 import android.test.ActivityInstrumentationTestCase2;
 import android.util.AttributeSet;
 import android.util.Xml;
diff --git a/tests/tests/widget/src/android/widget/cts/AbsoluteLayout_LayoutParamsTest.java b/tests/tests/widget/src/android/widget/cts/AbsoluteLayout_LayoutParamsTest.java
index 685f2d3..ebc4e74 100644
--- a/tests/tests/widget/src/android/widget/cts/AbsoluteLayout_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AbsoluteLayout_LayoutParamsTest.java
@@ -22,6 +22,7 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
+import android.cts.util.WidgetTestUtils;
 import android.test.AndroidTestCase;
 import android.util.AttributeSet;
 import android.util.Xml;
diff --git a/tests/tests/widget/src/android/widget/cts/CursorAdapterTest.java b/tests/tests/widget/src/android/widget/cts/CursorAdapterTest.java
index 8cc0754..0916e59 100644
--- a/tests/tests/widget/src/android/widget/cts/CursorAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/CursorAdapterTest.java
@@ -20,6 +20,8 @@
 
 import android.content.Context;
 import android.cts.util.PollingCheck;
+import android.cts.util.ReadElf;
+import android.cts.util.TestThread;
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.database.DataSetObserver;
diff --git a/tests/tests/widget/src/android/widget/cts/FilterTest.java b/tests/tests/widget/src/android/widget/cts/FilterTest.java
index 76de481..2c598dd 100644
--- a/tests/tests/widget/src/android/widget/cts/FilterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/FilterTest.java
@@ -18,6 +18,8 @@
 
 
 import android.cts.util.PollingCheck;
+import android.cts.util.ReadElf;
+import android.cts.util.TestThread;
 import android.os.Looper;
 import android.test.ActivityInstrumentationTestCase2;
 import android.widget.Filter;
diff --git a/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java b/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java
index dcab088..31d9fff 100644
--- a/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java
@@ -17,6 +17,7 @@
 package android.widget.cts;
 
 import android.content.res.ColorStateList;
+import android.cts.util.WidgetTestUtils;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.ColorFilter;
diff --git a/tests/tests/widget/src/android/widget/cts/FrameLayout_LayoutParamsTest.java b/tests/tests/widget/src/android/widget/cts/FrameLayout_LayoutParamsTest.java
index d8f1296..1e7082f 100644
--- a/tests/tests/widget/src/android/widget/cts/FrameLayout_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/FrameLayout_LayoutParamsTest.java
@@ -22,6 +22,7 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
+import android.cts.util.WidgetTestUtils;
 import android.test.AndroidTestCase;
 import android.util.AttributeSet;
 import android.util.Xml;
diff --git a/tests/tests/widget/src/android/widget/cts/GalleryTest.java b/tests/tests/widget/src/android/widget/cts/GalleryTest.java
index a2deab9..2813965 100644
--- a/tests/tests/widget/src/android/widget/cts/GalleryTest.java
+++ b/tests/tests/widget/src/android/widget/cts/GalleryTest.java
@@ -26,6 +26,7 @@
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.content.Context;
+import android.cts.util.WidgetTestUtils;
 import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
diff --git a/tests/tests/widget/src/android/widget/cts/Gallery_LayoutParamsTest.java b/tests/tests/widget/src/android/widget/cts/Gallery_LayoutParamsTest.java
index de90ed3..0502e38 100644
--- a/tests/tests/widget/src/android/widget/cts/Gallery_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/Gallery_LayoutParamsTest.java
@@ -22,6 +22,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import android.content.res.XmlResourceParser;
+import android.cts.util.WidgetTestUtils;
 import android.test.AndroidTestCase;
 import android.widget.Gallery.LayoutParams;
 
diff --git a/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java b/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java
index 2862865..36398c3 100644
--- a/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java
@@ -24,6 +24,7 @@
 import android.app.Activity;
 import android.content.Context;
 import android.cts.util.PollingCheck;
+import android.cts.util.WidgetTestUtils;
 import android.graphics.Rect;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
diff --git a/tests/tests/widget/src/android/widget/cts/ImageSwitcherTest.java b/tests/tests/widget/src/android/widget/cts/ImageSwitcherTest.java
index c0e606c..eb75557 100644
--- a/tests/tests/widget/src/android/widget/cts/ImageSwitcherTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ImageSwitcherTest.java
@@ -23,6 +23,7 @@
 
 import android.content.Context;
 import android.content.res.Resources;
+import android.cts.util.WidgetTestUtils;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.drawable.BitmapDrawable;
diff --git a/tests/tests/widget/src/android/widget/cts/ImageViewTest.java b/tests/tests/widget/src/android/widget/cts/ImageViewTest.java
index 7b0b65a..c93d4a1 100644
--- a/tests/tests/widget/src/android/widget/cts/ImageViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ImageViewTest.java
@@ -29,6 +29,7 @@
 
 import android.app.Activity;
 import android.content.Context;
+import android.cts.util.WidgetTestUtils;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
diff --git a/tests/tests/widget/src/android/widget/cts/RemoteViewsActivityTest.java b/tests/tests/widget/src/android/widget/cts/RemoteViewsActivityTest.java
index a03edce..ab109b1 100644
--- a/tests/tests/widget/src/android/widget/cts/RemoteViewsActivityTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RemoteViewsActivityTest.java
@@ -17,6 +17,7 @@
 package android.widget.cts;
 
 import android.app.Activity;
+import android.cts.util.NullWebViewUtils;
 import android.os.Parcel;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.MediumTest;
diff --git a/tests/tests/widget/src/android/widget/cts/RemoteViewsCtsActivity.java b/tests/tests/widget/src/android/widget/cts/RemoteViewsCtsActivity.java
index 6826eb3..4da5aa2 100644
--- a/tests/tests/widget/src/android/widget/cts/RemoteViewsCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/RemoteViewsCtsActivity.java
@@ -19,6 +19,7 @@
 import com.android.cts.widget.R;
 
 import android.app.Activity;
+import android.cts.util.NullWebViewUtils;
 import android.os.Bundle;
 import android.widget.RemoteViews;
 
diff --git a/tests/tests/widget/src/android/widget/cts/RemoteViewsTest.java b/tests/tests/widget/src/android/widget/cts/RemoteViewsTest.java
index 8d1cddf..328f9f3 100644
--- a/tests/tests/widget/src/android/widget/cts/RemoteViewsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RemoteViewsTest.java
@@ -26,6 +26,7 @@
 import android.app.Instrumentation.ActivityMonitor;
 import android.content.Intent;
 import android.content.res.ColorStateList;
+import android.cts.util.WidgetTestUtils;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.drawable.BitmapDrawable;
diff --git a/tests/tests/widget/src/android/widget/cts/SimpleAdapterTest.java b/tests/tests/widget/src/android/widget/cts/SimpleAdapterTest.java
index 90ff617..c530293 100644
--- a/tests/tests/widget/src/android/widget/cts/SimpleAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SimpleAdapterTest.java
@@ -20,6 +20,7 @@
 
 
 import android.content.Context;
+import android.cts.util.WidgetTestUtils;
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.test.InstrumentationTestCase;
diff --git a/tests/tests/widget/src/android/widget/cts/SimpleCursorAdapterTest.java b/tests/tests/widget/src/android/widget/cts/SimpleCursorAdapterTest.java
index f19dce7..13184de 100644
--- a/tests/tests/widget/src/android/widget/cts/SimpleCursorAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SimpleCursorAdapterTest.java
@@ -20,6 +20,7 @@
 
 
 import android.content.Context;
+import android.cts.util.WidgetTestUtils;
 import android.database.Cursor;
 import android.database.MatrixCursor;
 import android.graphics.Bitmap;
diff --git a/tests/tests/widget/src/android/widget/cts/SimpleCursorTreeAdapterTest.java b/tests/tests/widget/src/android/widget/cts/SimpleCursorTreeAdapterTest.java
index 0db5322..c9fdbc3 100644
--- a/tests/tests/widget/src/android/widget/cts/SimpleCursorTreeAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SimpleCursorTreeAdapterTest.java
@@ -20,6 +20,7 @@
 
 
 import android.content.Context;
+import android.cts.util.WidgetTestUtils;
 import android.database.Cursor;
 import android.database.MatrixCursor;
 import android.graphics.Bitmap;
diff --git a/tests/tests/widget/src/android/widget/cts/TabHostTest.java b/tests/tests/widget/src/android/widget/cts/TabHostTest.java
index 3af8d9c..00ecd40 100644
--- a/tests/tests/widget/src/android/widget/cts/TabHostTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TabHostTest.java
@@ -22,6 +22,7 @@
 import android.app.Activity;
 import android.app.ActivityGroup;
 import android.content.Intent;
+import android.cts.util.WidgetTestUtils;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
 import android.view.View;
diff --git a/tests/tests/widget/src/android/widget/cts/TestThread.java b/tests/tests/widget/src/android/widget/cts/TestThread.java
deleted file mode 100644
index 78295b9..0000000
--- a/tests/tests/widget/src/android/widget/cts/TestThread.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.widget.cts;
-
-/**
- * Thread class for executing a Runnable containing assertions in a separate thread.
- * Uncaught exceptions in the Runnable are rethrown in the context of the the thread
- * calling the <code>runTest()</code> method.
- */
-public final class TestThread extends Thread {
-    private Throwable mThrowable;
-    private Runnable mTarget;
-
-    public TestThread(Runnable target) {
-        mTarget = target;
-    }
-
-    @Override
-    public final void run() {
-        try {
-            mTarget.run();
-        } catch (Throwable t) {
-            mThrowable = t;
-        }
-    }
-
-    /**
-     * Run the target Runnable object and wait until the test finish or throw
-     * out Exception if test fail.
-     *
-     * @param runTime
-     * @throws Throwable
-     */
-    public void runTest(long runTime) throws Throwable {
-        start();
-        joinAndCheck(runTime);
-    }
-
-    /**
-     * Get the Throwable object which is thrown when test running
-     * @return  The Throwable object
-     */
-    public Throwable getThrowable() {
-        return mThrowable;
-    }
-
-    /**
-     * Set the Throwable object which is thrown when test running
-     * @param t The Throwable object
-     */
-    public void setThrowable(Throwable t) {
-        mThrowable = t;
-    }
-
-    /**
-     * Wait for the test thread to complete and throw the stored exception if there is one.
-     *
-     * @param runTime The time to wait for the test thread to complete.
-     * @throws Throwable
-     */
-    public void joinAndCheck(long runTime) throws Throwable {
-        this.join(runTime);
-        if (this.isAlive()) {
-            this.interrupt();
-            this.join(runTime);
-            throw new Exception("Thread did not finish within allotted time.");
-        }
-        checkException();
-    }
-
-    /**
-     * Check whether there is an exception when running Runnable object.
-     * @throws Throwable
-     */
-    public void checkException() throws Throwable {
-        if (mThrowable != null) {
-            throw mThrowable;
-        }
-    }
-}
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index c5d9985..72193e7 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -28,6 +28,7 @@
 import android.content.res.ColorStateList;
 import android.content.res.Resources.NotFoundException;
 import android.cts.util.PollingCheck;
+import android.cts.util.WidgetTestUtils;
 import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.graphics.Paint;
diff --git a/tests/tests/widget/src/android/widget/cts/ViewGroupCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ViewGroupCtsActivity.java
index 378395e..4e14fc2 100644
--- a/tests/tests/widget/src/android/widget/cts/ViewGroupCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/ViewGroupCtsActivity.java
@@ -17,7 +17,7 @@
 package android.widget.cts;
 
 import android.app.Activity;
-import android.app.cts.CTSResult;
+import android.cts.util.CTSResult;
 import android.os.Bundle;
 import android.os.Handler;
 import android.widget.TextView;
diff --git a/tests/tests/widget/src/android/widget/cts/WidgetTestUtils.java b/tests/tests/widget/src/android/widget/cts/WidgetTestUtils.java
deleted file mode 100644
index 2df6629..0000000
--- a/tests/tests/widget/src/android/widget/cts/WidgetTestUtils.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget.cts;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-
-import java.io.IOException;
-
-import junit.framework.Assert;
-
-/**
- * The useful methods for widget test.
- */
-public class WidgetTestUtils {
-    /**
-     * Assert that two bitmaps are equal.
-     *
-     * @param Bitmap b1 the first bitmap which needs to compare.
-     * @param Bitmap b2 the second bitmap which needs to compare.
-     */
-    public static void assertEquals(Bitmap b1, Bitmap b2) {
-        if (b1 == b2) {
-            return;
-        }
-
-        if (b1 == null || b2 == null) {
-            Assert.fail("the bitmaps are not equal");
-        }
-
-        // b1 and b2 are all not null.
-        if (b1.getWidth() != b2.getWidth() || b1.getHeight() != b2.getHeight()
-            || b1.getConfig() != b2.getConfig()) {
-            Assert.fail("the bitmaps are not equal");
-        }
-
-        int w = b1.getWidth();
-        int h = b1.getHeight();
-        int s = w * h;
-        int[] pixels1 = new int[s];
-        int[] pixels2 = new int[s];
-
-        b1.getPixels(pixels1, 0, w, 0, 0, w, h);
-        b2.getPixels(pixels2, 0, w, 0, 0, w, h);
-
-        for (int i = 0; i < s; i++) {
-            if (pixels1[i] != pixels2[i]) {
-                Assert.fail("the bitmaps are not equal");
-            }
-        }
-    }
-
-    /**
-     * Find beginning of the special element.
-     * @param parser XmlPullParser will be parsed.
-     * @param firstElementName the target element name.
-     *
-     * @throws XmlPullParserException if XML Pull Parser related faults occur.
-     * @throws IOException if I/O-related error occur when parsing.
-     */
-    public static final void beginDocument(XmlPullParser parser, String firstElementName)
-            throws XmlPullParserException, IOException {
-        Assert.assertNotNull(parser);
-        Assert.assertNotNull(firstElementName);
-
-        int type;
-        while ((type = parser.next()) != XmlPullParser.START_TAG
-                && type != XmlPullParser.END_DOCUMENT) {
-            ;
-        }
-
-        if (!parser.getName().equals(firstElementName)) {
-            throw new XmlPullParserException("Unexpected start tag: found " + parser.getName()
-                    + ", expected " + firstElementName);
-        }
-    }
-
-    /**
-     * Compare the expected pixels with actual, scaling for the target context density
-     *
-     * @throws AssertionFailedError
-     */
-    public static void assertScaledPixels(int expected, int actual, Context context) {
-        Assert.assertEquals(expected * context.getResources().getDisplayMetrics().density,
-                actual, 3);
-    }
-
-    /** Converts dips into pixels using the {@link Context}'s density. */
-    public static int convertDipToPixels(Context context, int dip) {
-      float density = context.getResources().getDisplayMetrics().density;
-      return Math.round(density * dip);
-    }
-
-    /**
-     * Retrieve a bitmap that can be used for comparison on any density
-     * @param resources
-     * @return the {@link Bitmap} or <code>null</code>
-     */
-    public static Bitmap getUnscaledBitmap(Resources resources, int resId) {
-        BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inScaled = false;
-        return BitmapFactory.decodeResource(resources, resId, options);
-    }
-
-    /**
-     * Retrieve a dithered bitmap that can be used for comparison on any density
-     * @param resources
-     * @param config the preferred config for the returning bitmap
-     * @return the {@link Bitmap} or <code>null</code>
-     */
-    public static Bitmap getUnscaledAndDitheredBitmap(Resources resources,
-            int resId, Bitmap.Config config) {
-        BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inDither = true;
-        options.inScaled = false;
-        options.inPreferredConfig = config;
-        return BitmapFactory.decodeResource(resources, resId, options);
-    }
-}
diff --git a/tests/webgl/src/android/webgl/WebGLActivity.java b/tests/webgl/src/android/webgl/WebGLActivity.java
index e88de16..3f911c4 100644
--- a/tests/webgl/src/android/webgl/WebGLActivity.java
+++ b/tests/webgl/src/android/webgl/WebGLActivity.java
@@ -19,9 +19,9 @@
 import android.app.Activity;
 import android.content.Context;
 import android.content.res.Resources;
+import android.cts.util.NullWebViewUtils;
 import android.os.Bundle;
 import android.util.Log;
-import android.webgl.cts.NullWebViewUtils;
 import android.webgl.cts.R;
 import android.webkit.WebView;
 import android.webkit.JavascriptInterface;
diff --git a/tests/webgl/src/android/webgl/cts/NullWebViewUtils.java b/tests/webgl/src/android/webgl/cts/NullWebViewUtils.java
deleted file mode 100644
index 861cc22..0000000
--- a/tests/webgl/src/android/webgl/cts/NullWebViewUtils.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.webgl.cts;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-
-/**
- * Utilities to enable the android.webkit.* CTS tests (and others that rely on a functioning
- * android.webkit.WebView implementation) to determine whether a functioning WebView is present
- * on the device or not.
- *
- * Test cases that require android.webkit.* classes should wrap their first usage of WebView in a
- * try catch block, and pass any exception that is thrown to
- * NullWebViewUtils.determineIfWebViewAvailable. The return value of
- * NullWebViewUtils.isWebViewAvailable will then determine if the test should expect to be able to
- * use a WebView.
- */
-public class NullWebViewUtils {
-
-    private static boolean sWebViewUnavailable;
-
-    /**
-     * @param context Current Activity context, used to query the PackageManager.
-     * @param t       An exception thrown by trying to invoke android.webkit.* APIs.
-     */
-    public static void determineIfWebViewAvailable(Context context, Throwable t) {
-        sWebViewUnavailable = !hasWebViewFeature(context) && checkCauseWasUnsupportedOperation(t);
-    }
-
-    /**
-     * After calling determineIfWebViewAvailable, this returns whether a WebView is available on the
-     * device and wheter the test can rely on it.
-     * @return True iff. PackageManager determined that there is no WebView on the device and the
-     *         exception thrown from android.webkit.* was UnsupportedOperationException.
-     */
-    public static boolean isWebViewAvailable() {
-        return !sWebViewUnavailable;
-    }
-
-    private static boolean hasWebViewFeature(Context context) {
-        // Query the system property that determins if there is a functional WebView on the device.
-        PackageManager pm = context.getPackageManager();
-        return pm.hasSystemFeature(PackageManager.FEATURE_WEBVIEW);
-    }
-
-    private static boolean checkCauseWasUnsupportedOperation(Throwable t) {
-        if (t == null) return false;
-        while (t.getCause() != null) {
-            t = t.getCause();
-        }
-        return t instanceof UnsupportedOperationException;
-    }
-
-    /**
-     * Some CTS tests (by design) first use android.webkit.* from a background thread. This helper
-     * allows the test to catch the UnsupportedOperationException from that background thread, and
-     * then query the result from the test main thread.
-     */
-    public static class NullWebViewFromThreadExceptionHandler
-            implements Thread.UncaughtExceptionHandler {
-        private Throwable mPendingException;
-
-        @Override
-        public void uncaughtException(Thread t, Throwable e) {
-            mPendingException = e;
-        }
-
-        public boolean isWebViewAvailable(Context context) {
-            return hasWebViewFeature(context) ||
-                    !checkCauseWasUnsupportedOperation(mPendingException);
-        }
-    }
-}
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsApiCoverage.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsApiCoverage.java
index 2109bbf..d596cba 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsApiCoverage.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsApiCoverage.java
@@ -176,8 +176,15 @@
         DexDepsXmlHandler dexDepsXmlHandler = new DexDepsXmlHandler(apiCoverage);
         xmlReader.setContentHandler(dexDepsXmlHandler);
 
-        Process process = new ProcessBuilder(dexdeps, "--format=xml", testApk.getPath()).start();
-        xmlReader.parse(new InputSource(process.getInputStream()));
+        String apkPath = testApk.getPath();
+        Process process = new ProcessBuilder(dexdeps, "--format=xml", apkPath).start();
+        try {
+            xmlReader.parse(new InputSource(process.getInputStream()));
+        } catch (SAXException e) {
+          // Catch this exception, but continue. SAXException is acceptable in cases
+          // where the apk does not contain a classes.dex and therefore parsing won't work.
+          System.err.println("warning: dexdeps failed for: " + apkPath);
+        }
     }
 
     private static void outputCoverageReport(ApiCoverage apiCoverage, List<File> testApks,
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
index e7b72ac..27f9135 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
@@ -31,7 +31,7 @@
     @Option(name="cts-install-path", description="the path to the cts installation to use")
     private String mCtsRootDirPath = System.getProperty("CTS_ROOT");
 
-    public static final String CTS_BUILD_VERSION = "L_r0";
+    public static final String CTS_BUILD_VERSION = "5.0_r0.5";
 
     /**
      * {@inheritDoc}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DeqpTestRunner.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DeqpTestRunner.java
index 35b8a66..8eb1621 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DeqpTestRunner.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DeqpTestRunner.java
@@ -77,6 +77,17 @@
     }
 
     /**
+     * Set the CTS build container.
+     * <p/>
+     * Exposed so unit tests can mock the provided build.
+     *
+     * @param buildHelper
+     */
+    public void setBuildHelper(CtsBuildHelper buildHelper) {
+        mCtsBuild = buildHelper;
+    }
+
+    /**
      * Enable or disable raw dEQP test log collection.
      */
     public void setCollectLogs(boolean logData) {
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/WrappedGTest.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/WrappedGTest.java
index a5c3e4c..e3ff825 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/WrappedGTest.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/WrappedGTest.java
@@ -113,7 +113,7 @@
         WrappedGTestResultParser resultParser = new WrappedGTestResultParser(id, listener);
         resultParser.setFakePackagePrefix(mPackageName + ".");
         try {
-            String options = mAbi == null ? "" : String.format("--abi %s ", mAbi);
+            String options = mAbi == null ? "" : String.format("--abi %s ", mAbi.getName());
             String command = String.format("am instrument -w %s%s/.%s", options, mAppNameSpace, mRunner);
             mDevice.executeShellCommand(command, resultParser, mMaxTestTimeMs, 0);
         } catch (DeviceNotAvailableException e) {
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/DeqpTestRunnerTest.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/DeqpTestRunnerTest.java
index cd9c738..c41793f 100644
--- a/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/DeqpTestRunnerTest.java
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/DeqpTestRunnerTest.java
@@ -15,6 +15,7 @@
  */
 package com.android.cts.tradefed.testtype;
 
+import com.android.cts.tradefed.build.StubCtsBuildHelper;
 import com.android.cts.tradefed.UnitTests;
 import com.android.cts.util.AbiUtils;
 import com.android.ddmlib.IShellOutputReceiver;
@@ -29,6 +30,7 @@
 import org.easymock.EasyMock;
 import org.easymock.IAnswer;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Map;
@@ -43,6 +45,8 @@
     private static final String LOG_FILE_NAME = "/sdcard/TestLog.qpa";
     private static final String INSTRUMENTATION_NAME =
             "com.drawelements.deqp/com.drawelements.deqp.testercore.DeqpInstrumentation";
+    private static final String DEQP_ONDEVICE_APK = "com.drawelements.deqp.apk";
+    private static final String DEQP_ONDEVICE_PKG = "com.drawelements.deqp";
 
     /**
      * {@inheritDoc}
@@ -118,6 +122,13 @@
         if (majorVersion > requiredMajorVersion
                 || (majorVersion == requiredMajorVersion && minorVersion >= requiredMinorVersion)) {
 
+            EasyMock.expect(mockDevice.uninstallPackage(EasyMock.eq(DEQP_ONDEVICE_PKG)))
+                    .andReturn("").once();
+            EasyMock.expect(mockDevice.installPackage(EasyMock.<File>anyObject(),
+                    EasyMock.eq(true),
+                    EasyMock.eq(AbiUtils.createAbiFlag(UnitTests.ABI.getName()))))
+                    .andReturn(null).once();
+
             EasyMock.expect(mockDevice.executeShellCommand(
                     EasyMock.eq("rm " + CASE_LIST_FILE_NAME))).andReturn("").once();
 
@@ -129,7 +140,7 @@
 
             String command = String.format(
                     "am instrument %s -w -e deqpLogFileName \"%s\" -e deqpCmdLine \""
-                        + "--deqp-caselist-file=%s --deqp-gl-config-name=rgba8888d24s8\""
+                        + "--deqp-caselist-file=%s --deqp-gl-config-name=rgba8888d24s8\" "
                         + "-e deqpLogData \"%s\" %s",
                     AbiUtils.createAbiFlag(UnitTests.ABI.getName()), LOG_FILE_NAME,
                     CASE_LIST_FILE_NAME, false, INSTRUMENTATION_NAME);
@@ -149,6 +160,9 @@
                     return null;
                 }
             });
+
+            EasyMock.expect(mockDevice.uninstallPackage(EasyMock.eq(DEQP_ONDEVICE_PKG)))
+                    .andReturn("").once();
         }
 
         mockListener.testRunStarted(ID, 1);
@@ -167,6 +181,7 @@
         EasyMock.replay(mockListener);
 
         deqpTest.setDevice(mockDevice);
+        deqpTest.setBuildHelper(new StubCtsBuildHelper());
         deqpTest.run(mockListener);
 
         EasyMock.verify(mockListener);
@@ -223,6 +238,13 @@
         EasyMock.expect(mockDevice.getProperty("ro.opengles.version"))
                 .andReturn(Integer.toString(version)).atLeastOnce();
 
+        EasyMock.expect(mockDevice.uninstallPackage(EasyMock.eq(DEQP_ONDEVICE_PKG))).andReturn("")
+                .once();
+
+        EasyMock.expect(mockDevice.installPackage(EasyMock.<File>anyObject(),
+                EasyMock.eq(true), EasyMock.eq(AbiUtils.createAbiFlag(UnitTests.ABI.getName()))))
+                .andReturn(null).once();
+
         EasyMock.expect(mockDevice.executeShellCommand(EasyMock.eq("rm " + CASE_LIST_FILE_NAME)))
                 .andReturn("").once();
 
@@ -234,7 +256,7 @@
 
         String command = String.format(
                 "am instrument %s -w -e deqpLogFileName \"%s\" -e deqpCmdLine \""
-                    + "--deqp-caselist-file=%s --deqp-gl-config-name=rgba8888d24s8\""
+                    + "--deqp-caselist-file=%s --deqp-gl-config-name=rgba8888d24s8\" "
                     + "-e deqpLogData \"%s\" %s",
                 AbiUtils.createAbiFlag(UnitTests.ABI.getName()), LOG_FILE_NAME,
                 CASE_LIST_FILE_NAME, false, INSTRUMENTATION_NAME);
@@ -263,7 +285,7 @@
 
         if (!pass) {
             mockListener.testFailed(testId,
-                    resultCode + ":Detail" + resultCode);
+                    resultCode + ": Detail" + resultCode);
 
             EasyMock.expectLastCall().once();
         }
@@ -274,10 +296,14 @@
         mockListener.testRunEnded(EasyMock.anyLong(), EasyMock.<Map<String, String>>notNull());
         EasyMock.expectLastCall().once();
 
+        EasyMock.expect(mockDevice.uninstallPackage(EasyMock.eq(DEQP_ONDEVICE_PKG))).andReturn("")
+                .once();
+
         EasyMock.replay(mockDevice);
         EasyMock.replay(mockListener);
 
         deqpTest.setDevice(mockDevice);
+        deqpTest.setBuildHelper(new StubCtsBuildHelper());
         deqpTest.run(mockListener);
 
         EasyMock.verify(mockListener);
@@ -287,7 +313,7 @@
     /**
      * Test running multiple test cases.
      */
-    public void testRun_multipleTets() throws Exception {
+    public void testRun_multipleTests() throws Exception {
         /* MultiLineReceiver expects "\r\n" line ending. */
         final String output = "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=releaseName\r\n"
                 + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
@@ -398,6 +424,12 @@
         EasyMock.expect(mockDevice.getProperty("ro.opengles.version"))
                 .andReturn(Integer.toString(version)).atLeastOnce();
 
+        EasyMock.expect(mockDevice.uninstallPackage(EasyMock.eq(DEQP_ONDEVICE_PKG))).andReturn("")
+                .once();
+        EasyMock.expect(mockDevice.installPackage(EasyMock.<File>anyObject(),
+                EasyMock.eq(true), EasyMock.eq(AbiUtils.createAbiFlag(UnitTests.ABI.getName()))))
+                .andReturn(null).once();
+
         EasyMock.expect(mockDevice.executeShellCommand(EasyMock.eq("rm " + CASE_LIST_FILE_NAME)))
                 .andReturn("").once();
 
@@ -409,7 +441,7 @@
 
         String command = String.format(
                 "am instrument %s -w -e deqpLogFileName \"%s\" -e deqpCmdLine \""
-                    + "--deqp-caselist-file=%s --deqp-gl-config-name=rgba8888d24s8\""
+                    + "--deqp-caselist-file=%s --deqp-gl-config-name=rgba8888d24s8\" "
                     + "-e deqpLogData \"%s\" %s",
                 AbiUtils.createAbiFlag(UnitTests.ABI.getName()), LOG_FILE_NAME,
                 CASE_LIST_FILE_NAME, false, INSTRUMENTATION_NAME);
@@ -446,10 +478,14 @@
         mockListener.testRunEnded(EasyMock.anyLong(), EasyMock.<Map<String, String>>notNull());
         EasyMock.expectLastCall().once();
 
+        EasyMock.expect(mockDevice.uninstallPackage(EasyMock.eq(DEQP_ONDEVICE_PKG))).andReturn("")
+                .once();
+
         EasyMock.replay(mockDevice);
         EasyMock.replay(mockListener);
 
         deqpTest.setDevice(mockDevice);
+        deqpTest.setBuildHelper(new StubCtsBuildHelper());
         deqpTest.run(mockListener);
 
         EasyMock.verify(mockListener);
diff --git a/tools/utils/buildCts.py b/tools/utils/buildCts.py
index 85adb0c..4a1b2f3 100755
--- a/tools/utils/buildCts.py
+++ b/tools/utils/buildCts.py
@@ -158,6 +158,7 @@
     # CTS Stable plan
     plan = tools.TestPlan(packages)
     plan.Exclude(r'com\.android\.cts\.browserbench')
+    plan.Exclude(r'com\.android\.cts\.filesystemperf\.RandomRWTest$')
     for package, test_list in flaky_tests.iteritems():
       plan.ExcludeTests(package, test_list)
     self.__WritePlan(plan, 'CTS-stable')
@@ -166,6 +167,7 @@
     plan = tools.TestPlan(packages)
     plan.Exclude('.*')
     plan.Include(r'com\.android\.cts\.browserbench')
+    plan.Include(r'com\.android\.cts\.filesystemperf\.RandomRWTest$')
     for package, test_list in flaky_tests.iteritems():
       plan.Include(package+'$')
       plan.IncludeTests(package, test_list)
@@ -180,6 +182,8 @@
     plan.Exclude('.*')
     for package, test_list in small_tests.iteritems():
       plan.Include(package+'$')
+    plan.Exclude(r'com\.android\.cts\.browserbench')
+    plan.Exclude(r'com\.android\.cts\.filesystemperf\.RandomRWTest$')
     for package, test_list in flaky_tests.iteritems():
       plan.ExcludeTests(package, test_list)
     self.__WritePlan(plan, 'CTS-kitkat-small')
@@ -189,6 +193,8 @@
     plan.Exclude('.*')
     for package, test_list in medium_tests.iteritems():
       plan.Include(package+'$')
+    plan.Exclude(r'com\.android\.cts\.browserbench')
+    plan.Exclude(r'com\.android\.cts\.filesystemperf\.RandomRWTest$')
     for package, test_list in flaky_tests.iteritems():
       plan.ExcludeTests(package, test_list)
     self.__WritePlan(plan, 'CTS-kitkat-medium')
@@ -197,6 +203,8 @@
     plan = tools.TestPlan(packages)
     plan.Exclude('.*')
     plan.Include(r'android\.hardware$')
+    plan.Exclude(r'com\.android\.cts\.browserbench')
+    plan.Exclude(r'com\.android\.cts\.filesystemperf\.RandomRWTest$')
     for package, test_list in flaky_tests.iteritems():
       plan.ExcludeTests(package, test_list)
     self.__WritePlan(plan, 'CTS-hardware')
@@ -205,6 +213,8 @@
     plan = tools.TestPlan(packages)
     plan.Exclude('.*')
     plan.Include(r'android\.media$')
+    plan.Exclude(r'com\.android\.cts\.browserbench')
+    plan.Exclude(r'com\.android\.cts\.filesystemperf\.RandomRWTest$')
     for package, test_list in flaky_tests.iteritems():
       plan.ExcludeTests(package, test_list)
     self.__WritePlan(plan, 'CTS-media')
@@ -213,6 +223,8 @@
     plan = tools.TestPlan(packages)
     plan.Exclude('.*')
     plan.Include(r'android\.mediastress$')
+    plan.Exclude(r'com\.android\.cts\.browserbench')
+    plan.Exclude(r'com\.android\.cts\.filesystemperf\.RandomRWTest$')
     for package, test_list in flaky_tests.iteritems():
       plan.ExcludeTests(package, test_list)
     self.__WritePlan(plan, 'CTS-mediastress')
@@ -222,6 +234,8 @@
     plan.Exclude('.*')
     for package, test_list in new_test_packages.iteritems():
       plan.Include(package+'$')
+    plan.Exclude(r'com\.android\.cts\.browserbench')
+    plan.Exclude(r'com\.android\.cts\.filesystemperf\.RandomRWTest$')
     for package, test_list in flaky_tests.iteritems():
       plan.ExcludeTests(package, test_list)
     self.__WritePlan(plan, 'CTS-l-tests')
@@ -237,6 +251,8 @@
     plan.Exclude(r'android\.hardware$')
     plan.Exclude(r'android\.media$')
     plan.Exclude(r'android\.mediastress$')
+    plan.Exclude(r'com\.android\.cts\.browserbench')
+    plan.Exclude(r'com\.android\.cts\.filesystemperf\.RandomRWTest$')
     for package, test_list in flaky_tests.iteritems():
       plan.ExcludeTests(package, test_list)
     self.__WritePlan(plan, 'CTS-staging')
@@ -270,6 +286,7 @@
       'android.host.security' : [],
       'android.net' : [],
       'android.os' : [],
+      'android.permission2' : [],
       'android.security' : [],
       'android.telephony' : [],
       'android.webkit' : [],
@@ -313,7 +330,6 @@
       'android.opengl' : [],
       'android.openglperf' : [],
       'android.permission' : [],
-      'android.permission2' : [],
       'android.preference' : [],
       'android.preference2' : [],
       'android.provider' : [],
@@ -375,17 +391,10 @@
       that are known to be flaky. """
   return {
       'android.app' : [
-          'cts.ActivityManagerTest#testIsRunningInTestHarness',
-          'cts.AlertDialogTest#testAlertDialogCancelable',
-          'cts.ExpandableListActivityTest#testCallback',],
+          'cts.ActivityManagerTest#testIsRunningInTestHarness',],
       'android.dpi' : [
           'cts.DefaultManifestAttributesSdkTest#testPackageHasExpectedSdkVersion',],
       'android.hardware' : [
-          'camera2.cts.CameraDeviceTest#testCameraDeviceRepeatingRequest',
-          'camera2.cts.ImageReaderTest#testImageReaderFromCameraJpeg',
-          'cts.CameraTest#testImmediateZoom',
-          'cts.CameraTest#testPreviewCallback',
-          'cts.CameraTest#testSmoothZoom',
           'cts.CameraTest#testVideoSnapshot',
           'cts.CameraGLTest#testCameraToSurfaceTextureMetadata',
           'cts.CameraGLTest#testSetPreviewTextureBothCallbacks',
@@ -393,8 +402,6 @@
       'android.media' : [
           'cts.DecoderTest#testCodecResetsH264WithSurface',
           'cts.StreamingMediaPlayerTest#testHLS',],
-      'android.mediastress' : [
-          'cts.NativeMediaTest#test480pPlay',],
       'android.net' : [
           'cts.ConnectivityManagerTest#testStartUsingNetworkFeature_enableHipri',
           'cts.DnsTest#testDnsWorks',
@@ -403,9 +410,7 @@
           'cts.SSLCertificateSocketFactoryTest#test_createSocket_simple',
           'cts.SSLCertificateSocketFactoryTest#test_createSocket_wrapping',
           'cts.TrafficStatsTest#testTrafficStatsForLocalhost',
-          'wifi.cts.NsdManagerTest#testAndroidTestCaseSetupProperly',
-          'wifi.cts.ScanResultTest#testAndroidTestCaseSetupProperly',
-          'wifi.cts.ScanResultTest#testScanResultTimeStamp',],
+          'wifi.cts.NsdManagerTest#testAndroidTestCaseSetupProperly',],
       'android.os' : [
           'cts.BuildVersionTest#testReleaseVersion',
           'cts.BuildTest#testIsSecureUserBuild',],
@@ -414,16 +419,11 @@
           'cts.BannedFilesTest#testNoSuInPath',
           'cts.ListeningPortsTest#testNoRemotelyAccessibleListeningUdp6Ports',
           'cts.ListeningPortsTest#testNoRemotelyAccessibleListeningUdpPorts',
-          'cts.PackageSignatureTest#testPackageSignatures',],
+          'cts.PackageSignatureTest#testPackageSignatures',
+          'cts.SELinuxDomainTest#testSuDomain',
+          'cts.SELinuxHostTest#testAllEnforcing',],
       'android.webkit' : [
-          'cts.WebViewClientTest#testDoUpdateVisitedHistory',
-          'cts.WebViewClientTest#testLoadPage',
-          'cts.WebViewClientTest#testOnFormResubmission',
-          'cts.WebViewClientTest#testOnReceivedError',
-          'cts.WebViewClientTest#testOnReceivedHttpAuthRequest',
-          'cts.WebViewClientTest#testOnScaleChanged',
-          'cts.WebViewClientTest#testOnUnhandledKeyEvent',
-          'cts.WebViewTest#testSetInitialScale',]}
+          'cts.WebViewClientTest#testOnUnhandledKeyEvent',]}
 
 def LogGenerateDescription(name):
   print 'Generating test description for package %s' % name