Merge "Deleting native opengl tests as these are covered by DEQP."
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index 35c976f..72034a4 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -127,9 +127,7 @@
 # Test packages that require an associated test package XML.
 cts_test_packages := \
     CtsIcuTestCases \
-    CtsDeviceSimpleCpu \
     CtsDeviceVideoPerf \
-    CtsDeviceTvProviderPerf \
     CtsAccelerationTestCases \
     CtsAccountManagerTestCases \
     CtsAccessibilityServiceTestCases \
@@ -184,10 +182,12 @@
     CtsProviderTestCases \
     CtsRenderscriptTestCases \
     CtsRenderscriptLegacyTestCases \
+    CtsRsBlasTestCases \
     CtsRsCppTestCases \
     CtsSaxTestCases \
     CtsSecurityTestCases \
     CtsSignatureTestCases \
+    CtsSimpleCpuTestCases \
     CtsSpeechTestCases \
     CtsSystemUiTestCases \
     CtsTelecomTestCases \
@@ -197,6 +197,7 @@
     CtsTextureViewTestCases \
     CtsThemeDeviceTestCases \
     CtsTransitionTestCases \
+    CtsTvProviderTestCases \
     CtsTvTestCases \
     CtsUiAutomationTestCases \
     CtsUiRenderingTestCases \
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/screenpinning/ScreenPinningTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/screenpinning/ScreenPinningTestActivity.java
index 8e72ebb..0728fb5 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/screenpinning/ScreenPinningTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/screenpinning/ScreenPinningTestActivity.java
@@ -31,6 +31,8 @@
 
     private static final String TAG = "ScreenPinningTestActivity";
     private static final String KEY_CURRENT_TEST = "keyCurrentTest";
+    private static final long TASK_MODE_CHECK_DELAY = 200;
+    private static final int MAX_TASK_MODE_CHECK_COUNT = 5;
 
     private Test[] mTests;
     private int mTestIndex;
@@ -203,10 +205,18 @@
                 return;
             }
             stopLockTask();
-            if (!mActivityManager.isInLockTaskMode()) {
-                succeed();
-            } else {
-                error(R.string.error_screen_pinning_couldnt_exit);
+            for (int retry = MAX_TASK_MODE_CHECK_COUNT; retry > 0; retry--) {
+                try {
+                    Thread.sleep(TASK_MODE_CHECK_DELAY);
+                } catch (InterruptedException e) {
+                }
+                Log.d(TAG, "Check unpin ... " + retry);
+                if (!mActivityManager.isInLockTaskMode()) {
+                    succeed();
+                    break;
+                } else if (retry == 1) {
+                    error(R.string.error_screen_pinning_couldnt_exit);
+                }
             }
         };
     };
diff --git a/build/device_info_package.mk b/build/device_info_package.mk
index 0aaa8aa..85593d2 100644
--- a/build/device_info_package.mk
+++ b/build/device_info_package.mk
@@ -17,7 +17,7 @@
 #
 
 DEVICE_INFO_PACKAGE := com.android.compatibility.common.deviceinfo
-DEVICE_INFO_INSTRUMENT := com.android.compatibility.common.deviceinfo.DeviceInfoInstrument
+DEVICE_INFO_INSTRUMENT := android.support.test.runner.AndroidJUnitRunner
 DEVICE_INFO_PERMISSIONS += android.permission.WRITE_EXTERNAL_STORAGE
 DEVICE_INFO_ACTIVITIES += $(DEVICE_INFO_PACKAGE).GenericDeviceInfo $(DEVICE_INFO_PACKAGE).PackageDeviceInfo
 
diff --git a/common/device-side/device-info/Android.mk b/common/device-side/device-info/Android.mk
index 8c5052b..c04b51d 100644
--- a/common/device-side/device-info/Android.mk
+++ b/common/device-side/device-info/Android.mk
@@ -24,6 +24,8 @@
 
 LOCAL_SDK_VERSION := current
 
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfoActivity.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfo.java
similarity index 81%
rename from common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfoActivity.java
rename to common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfo.java
index ed2587a..929fe2d 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfoActivity.java
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfo.java
@@ -16,10 +16,12 @@
 package com.android.compatibility.common.deviceinfo;
 
 import android.app.Activity;
-import android.content.Intent;
-import android.net.Uri;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.os.Environment;
+import android.test.InstrumentationTestCase;
 import android.text.TextUtils;
 import android.util.JsonWriter;
 import android.util.Log;
@@ -29,58 +31,76 @@
 import java.io.OutputStreamWriter;
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
-import java.util.concurrent.CountDownLatch;
+import java.util.HashSet;
+import java.util.Set;
 
 /**
  * Collect device information on target device and write to a JSON file.
  */
-public abstract class DeviceInfoActivity extends Activity {
+public abstract class DeviceInfo extends InstrumentationTestCase {
 
-    /** Device info result code: collector failed to complete. */
-    private static final int DEVICE_INFO_RESULT_FAILED = -2;
-    /** Device info result code: collector completed with error. */
-    private static final int DEVICE_INFO_RESULT_ERROR = -1;
-    /** Device info result code: collector has started but not completed. */
-    private static final int DEVICE_INFO_RESULT_STARTED = 0;
-    /** Device info result code: collector completed success. */
-    private static final int DEVICE_INFO_RESULT_OK = 1;
+    private enum ResultCode {
+        // Collection started.
+        STARTED,
+        // Collection completed.
+        COMPLETED,
+        // Collection completed with error.
+        ERROR,
+        // Collection failed to complete.
+        FAILED
+    }
 
     private static final int MAX_STRING_VALUE_LENGTH = 1000;
     private static final int MAX_ARRAY_LENGTH = 1000;
 
-    private static final String LOG_TAG = "DeviceInfoActivity";
+    private static final String LOG_TAG = "ExtendedDeviceInfo";
 
-    private CountDownLatch mDone = new CountDownLatch(1);
     private JsonWriter mJsonWriter = null;
     private String mResultFilePath = null;
-    private String mErrorMessage = "Collector has started.";
-    private int mResultCode = DEVICE_INFO_RESULT_STARTED;
+    private String mErrorMessage = null;
+    private ResultCode mResultCode = ResultCode.STARTED;
 
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
+    Set<String> mActivityList = new HashSet<String>();
+
+    public void testCollectDeviceInfo() {
+        if (!mActivityList.contains(getClass().getName())) {
+            return;
+        }
+
         if (createFilePath()) {
             createJsonWriter();
             startJsonWriter();
             collectDeviceInfo();
             closeJsonWriter();
 
-            if (mResultCode == DEVICE_INFO_RESULT_STARTED) {
-                mResultCode = DEVICE_INFO_RESULT_OK;
+            if (mResultCode == ResultCode.STARTED) {
+                mResultCode = ResultCode.COMPLETED;
             }
         }
 
-        Intent data = new Intent();
-        if (mResultCode == DEVICE_INFO_RESULT_OK) {
-            data.setData(Uri.parse(mResultFilePath));
-            setResult(RESULT_OK, data);
-        } else {
-            data.setData(Uri.parse(mErrorMessage));
-            setResult(RESULT_CANCELED, data);
+        sendStatus();
+
+        String message = getClass().getSimpleName() + " collection completed.";
+        assertEquals(message, ResultCode.COMPLETED, mResultCode);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        // Build the list of supported activities that can run collection.
+        ActivityInfo[] activities = null;
+        try {
+            activities = getContext().getPackageManager().getPackageInfo(
+                getContext().getPackageName(), PackageManager.GET_ACTIVITIES).activities;
+        } catch (Exception e) {
+            Log.e(LOG_TAG, "Exception occurred while getting activities.", e);
+            return;
         }
 
-        mDone.countDown();
-        finish();
+        for (ActivityInfo activityInfo : activities) {
+            mActivityList.add(activityInfo.name);
+        }
     }
 
     /**
@@ -88,42 +108,43 @@
      */
     protected abstract void collectDeviceInfo();
 
-    void waitForActivityToFinish() {
-        try {
-            mDone.await();
-        } catch (Exception e) {
-            failed("Exception while waiting for activity to finish: " + e.getMessage());
-        }
+    protected Context getContext() {
+        return getInstrumentation().getContext();
     }
 
     /**
-     * Returns the error message if collector did not complete successfully.
+     * Sends status to instrumentation.
      */
-    String getErrorMessage() {
-        if (mResultCode == DEVICE_INFO_RESULT_OK) {
-            return null;
+    void sendStatus() {
+        Bundle bundle = new Bundle();
+        String className = getClass().getSimpleName();
+        if (this instanceof GenericDeviceInfo) {
+            ((GenericDeviceInfo) this).putDeviceInfo(bundle);
         }
-        return mErrorMessage;
+        if (!TextUtils.isEmpty(mErrorMessage)) {
+            bundle.putString("DEVICE_INFO_ERROR_" + className, mErrorMessage);
+        }
+        if (mResultCode == ResultCode.COMPLETED) {
+            bundle.putString("DEVICE_INFO_FILE_" + className, mResultFilePath);
+        }
+        getInstrumentation().sendStatus(Activity.RESULT_OK, bundle);
     }
 
     /**
      * Returns the path to the json file if collector completed successfully.
      */
     String getResultFilePath() {
-        if (mResultCode == DEVICE_INFO_RESULT_OK) {
-            return mResultFilePath;
-        }
-        return null;
+        return mResultFilePath;
     }
 
     private void error(String message) {
-        mResultCode = DEVICE_INFO_RESULT_ERROR;
+        mResultCode = ResultCode.ERROR;
         mErrorMessage = message;
         Log.e(LOG_TAG, message);
     }
 
     private void failed(String message) {
-        mResultCode = DEVICE_INFO_RESULT_FAILED;
+        mResultCode = ResultCode.FAILED;
         mErrorMessage = message;
         Log.e(LOG_TAG, message);
     }
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfoInstrument.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfoInstrument.java
deleted file mode 100644
index 655e627..0000000
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/DeviceInfoInstrument.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.compatibility.common.deviceinfo;
-
-import android.app.Activity;
-import android.app.Instrumentation;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * An instrumentation that runs all activities that extends DeviceInfoActivity.
- */
-public class DeviceInfoInstrument extends Instrumentation {
-
-    private static final String LOG_TAG = "ExtendedDeviceInfo";
-    private static final String COLLECTOR = "collector";
-
-    // List of collectors to run. If null or empty, all collectors will run.
-    private Set<String> mCollectorSet = new HashSet<String>();
-
-    // Results sent to the caller when this istrumentation completes.
-    private Bundle mBundle = new Bundle();
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        if (savedInstanceState != null) {
-            String collectorList = savedInstanceState.getString(COLLECTOR);
-            if (!TextUtils.isEmpty(collectorList)) {
-                for (String collector : TextUtils.split(collectorList, ",")) {
-                  if (!TextUtils.isEmpty(collector)) {
-                    mCollectorSet.add(collector);
-                  }
-                }
-            }
-        }
-        start();
-    }
-
-    @Override
-    public void onStart() {
-        try {
-            Context context = getContext();
-            ActivityInfo[] activities = context.getPackageManager().getPackageInfo(
-                    context.getPackageName(), PackageManager.GET_ACTIVITIES).activities;
-            for (ActivityInfo activityInfo : activities) {
-                runActivity(activityInfo.name);
-            }
-        } catch (Exception e) {
-            Log.e(LOG_TAG, "Exception occurred while running activities.", e);
-            // Returns INSTRUMENTATION_CODE: 0
-            finish(Activity.RESULT_CANCELED, mBundle);
-        }
-        // Returns INSTRUMENTATION_CODE: -1
-        finish(Activity.RESULT_OK, mBundle);
-    }
-
-    /**
-     * Returns true if the activity meets the criteria to run; otherwise, false.
-     */
-    private boolean isActivityRunnable(Class activityClass) {
-        // Don't run the base DeviceInfoActivity class.
-        if (DeviceInfoActivity.class == activityClass) {
-            return false;
-        }
-        // Don't run anything that doesn't extends DeviceInfoActivity.
-        if (!DeviceInfoActivity.class.isAssignableFrom(activityClass)) {
-            return false;
-        }
-        // Only run activity if mCollectorSet is empty or contains it.
-        if (mCollectorSet != null && mCollectorSet.size() > 0) {
-            return mCollectorSet.contains(activityClass.getName());
-        }
-        // Run anything that makes it here.
-        return true;
-    }
-
-    /**
-     * Runs a device info activity and return the file path where the results are written to.
-     */
-    private void runActivity(String activityName) throws Exception {
-        Class activityClass = null;
-        try {
-            activityClass = Class.forName(activityName);
-        } catch (ClassNotFoundException e) {
-            return;
-        }
-
-        if (activityClass == null || !isActivityRunnable(activityClass)) {
-            return;
-        }
-
-        Intent intent = new Intent();
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        intent.setClassName(this.getContext(), activityName);
-
-        DeviceInfoActivity activity = (DeviceInfoActivity) startActivitySync(intent);
-        waitForIdleSync();
-        activity.waitForActivityToFinish();
-
-        String className = activityClass.getSimpleName();
-        String errorMessage = activity.getErrorMessage();
-        if (TextUtils.isEmpty(errorMessage)) {
-            mBundle.putString(className, activity.getResultFilePath());
-            if (activity instanceof GenericDeviceInfo) {
-                ((GenericDeviceInfo) activity).putDeviceInfo(mBundle);
-            }
-        } else {
-            mBundle.putString(className, errorMessage);
-            throw new Exception(errorMessage);
-        }
-    }
-}
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GenericDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GenericDeviceInfo.java
index 44c0b5f..6f79301 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GenericDeviceInfo.java
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GenericDeviceInfo.java
@@ -47,14 +47,14 @@
 import java.util.Scanner;
 import java.util.Set;
 
-import com.android.compatibility.common.deviceinfo.DeviceInfoActivity;
+import com.android.compatibility.common.deviceinfo.DeviceInfo;
 
 /**
  * Generic device info collector.
  */
-public class GenericDeviceInfo extends DeviceInfoActivity {
+public class GenericDeviceInfo extends DeviceInfo {
 
-    public static final String DEVICE_INFO = "DEVICE_INFO_%s";
+    public static final String DEVICE_INFO_GENERIC = "DEVICE_INFO_GENERIC_%s";
     public static final String BUILD_ID = "build_id";
     public static final String BUILD_PRODUCT = "build_product";
     public static final String BUILD_DEVICE = "build_device";
@@ -76,11 +76,6 @@
     private final Map<String, String> mDeviceInfo = new HashMap<>();
 
     @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-    }
-
-    @Override
     protected void collectDeviceInfo() {
         addDeviceInfo(BUILD_ID, Build.ID);
         addDeviceInfo(BUILD_PRODUCT, Build.PRODUCT);
@@ -108,7 +103,7 @@
 
     protected void putDeviceInfo(Bundle bundle) {
         for (Entry<String, String> entry : mDeviceInfo.entrySet()) {
-            bundle.putString(String.format(DEVICE_INFO, entry.getKey()), entry.getValue());
+            bundle.putString(String.format(DEVICE_INFO_GENERIC, entry.getKey()), entry.getValue());
         }
     }
 }
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java
index 4d9ad46..0dd24be 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java
@@ -19,12 +19,12 @@
 import android.content.pm.PackageManager;
 import android.os.Bundle;
 
-import com.android.compatibility.common.deviceinfo.DeviceInfoActivity;
+import com.android.compatibility.common.deviceinfo.DeviceInfo;
 
 /**
  * PackageDeviceInfo collector.
  */
-public class PackageDeviceInfo extends DeviceInfoActivity {
+public class PackageDeviceInfo extends DeviceInfo {
 
     private static final String PACKAGE = "package";
     private static final String NAME = "name";
@@ -34,7 +34,7 @@
 
     @Override
     protected void collectDeviceInfo() {
-        PackageManager pm = this.getPackageManager();
+        PackageManager pm = getContext().getPackageManager();
         startArray(PACKAGE);
         for (PackageInfo pkg : pm.getInstalledPackages(0)) {
             startGroup();
diff --git a/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/DeviceInfoActivityTest.java b/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/DeviceInfoTest.java
similarity index 68%
rename from common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/DeviceInfoActivityTest.java
rename to common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/DeviceInfoTest.java
index 5b834c7..3459d59 100644
--- a/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/DeviceInfoActivityTest.java
+++ b/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/DeviceInfoTest.java
@@ -15,6 +15,7 @@
  */
 package com.android.compatibility.common.deviceinfo;
 
+import android.test.AndroidTestCase;
 import android.test.ActivityInstrumentationTestCase2;
 
 import java.io.BufferedReader;
@@ -23,39 +24,19 @@
 import java.io.InputStreamReader;
 
 /**
- * Test for {@link DeviceInfoActivity}.
+ * Test for {@link DeviceInfo}.
  */
-public class DeviceInfoActivityTest extends ActivityInstrumentationTestCase2<TestDeviceInfo> {
+public class DeviceInfoTest extends AndroidTestCase {
 
     private static final String EXPECTED_FILE_PATH =
             "/storage/emulated/0/device-info-files/TestDeviceInfo.deviceinfo.json";
 
-    private TestDeviceInfo mActivity;
+    private TestDeviceInfo testDeviceInfo = new TestDeviceInfo();
 
-    public DeviceInfoActivityTest() {
-        super(TestDeviceInfo.class);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        // Start the activity and get a reference to it.
-        mActivity = getActivity();
-        // Wait for the activity to finish.
-        mActivity.waitForActivityToFinish();
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        mActivity = null;
-        super.tearDown();
-    }
-
-    public void testJsonFile() throws IOException {
-        String errorMessage = mActivity.getErrorMessage();
-        // Check no errors
-        assertEquals("Expected no errors", null, errorMessage);
-        String resultFilePath = mActivity.getResultFilePath();
+    public void testJsonFile() throws Exception {
+        testDeviceInfo.setUp();
+        testDeviceInfo.testCollectDeviceInfo();
+        String resultFilePath = testDeviceInfo.getResultFilePath();
         // Check file path exist
         assertNotNull("Expected a non-null resultFilePath", resultFilePath);
         // Check file path location
diff --git a/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/ExampleObjects.java b/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/ExampleObjects.java
index 570bdd5..9411cd2 100644
--- a/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/ExampleObjects.java
+++ b/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/ExampleObjects.java
@@ -16,12 +16,12 @@
 package com.android.compatibility.common.deviceinfo;
 
 /**
- * Example Objects for {@link DeviceInfoActivity} test package.
+ * Example Objects for {@link DeviceInfo} test package.
  */
 public final class ExampleObjects {
 
-    // Must match DeviceInfoActivity.MAX_STRING_VALUE_LENGTH and
-    // DeviceInfoActivity.MAX_ARRAY_LENGTH
+    // Must match DeviceInfo.MAX_STRING_VALUE_LENGTH and
+    // DeviceInfo.MAX_ARRAY_LENGTH
     private static final int MAX_LENGTH = 1000;
 
     private static final String TEST_DEVICE_INFO_JSON = "{\n" +
diff --git a/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/TestDeviceInfo.java b/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/TestDeviceInfo.java
index 7f82942..1360312 100644
--- a/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/TestDeviceInfo.java
+++ b/common/device-side/device-info/tests/src/com/android/compatibility/common/deviceinfo/TestDeviceInfo.java
@@ -18,15 +18,17 @@
 import android.os.Bundle;
 
 import java.lang.StringBuilder;
+import java.util.HashSet;
 
 /**
- * Collector for testing DeviceInfoActivity
+ * Collector for testing DeviceInfo
  */
-public class TestDeviceInfo extends DeviceInfoActivity {
+public class TestDeviceInfo extends DeviceInfo {
 
     @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
+    protected void setUp() throws Exception {
+        mActivityList = new HashSet<String>();
+        mActivityList.add(getClass().getName());
     }
 
     @Override
@@ -82,4 +84,7 @@
         addResult("max_length_string", sb.toString());
         addArray("max_num_ints", arr);
     }
+
+    @Override
+    void sendStatus() {}
 }
diff --git a/common/device-side/preconditions/src/com/android/compatibility/common/preconditions/ExternalStorageHelper.java b/common/device-side/preconditions/src/com/android/compatibility/common/preconditions/ExternalStorageHelper.java
new file mode 100644
index 0000000..f398ea8
--- /dev/null
+++ b/common/device-side/preconditions/src/com/android/compatibility/common/preconditions/ExternalStorageHelper.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compatibility.common.preconditions;
+
+import android.os.Environment;
+
+/**
+ * ExternalStorageHelper is used to check whether the device's external storage is readable
+ * and writeable.
+ */
+public class ExternalStorageHelper {
+
+    /* Checks if external storage is available for read and write */
+    public static boolean isExternalStorageWritable() {
+        String state = Environment.getExternalStorageState();
+        return Environment.MEDIA_MOUNTED.equals(state);
+    }
+
+    /* Checks if external storage is available to at least read */
+    public static boolean isExternalStorageReadable() {
+        String state = Environment.getExternalStorageState();
+        return (Environment.MEDIA_MOUNTED.equals(state) ||
+                Environment.MEDIA_MOUNTED_READ_ONLY.equals(state));
+    }
+
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java
index 12e6cdd..0b948ad85 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java
@@ -54,9 +54,7 @@
        ITestSummaryListener {
 
     private static final String RESULT_KEY = "COMPATIBILITY_TEST_RESULT";
-    private static final String DEVICE_INFO = "DEVICE_INFO_";
-    private static final String DEVICE_INFO_EXT = ".deviceinfo.json";
-    private static final String DEVICE_INFO_PACKAGE = "com.android.compatibility.common.deviceinfo";
+    private static final String DEVICE_INFO_GENERIC = "DEVICE_INFO_GENERIC_";
     private static final String[] RESULT_RESOURCES = {
         "compatibility_result.css",
         "compatibility_result.xsd",
@@ -89,7 +87,6 @@
     private File mResultDir = null;
     private File mLogDir = null;
     private long mStartTime;
-    private boolean mIsDeviceInfoRun;
     private ResultUploader mUploader;
     private String mReferenceUrl;
     private IModuleResult mCurrentModuleResult;
@@ -173,10 +170,6 @@
     @Override
     public void testRunStarted(String id, int numTests) {
         logResult("Starting %s with %d tests", id, numTests);
-        mIsDeviceInfoRun = AbiUtils.parseTestName(id).equals(DEVICE_INFO_PACKAGE);
-        if (mIsDeviceInfoRun) {
-            return;
-        }
         mCurrentModuleResult = mResult.getOrCreateModule(id);
         mResult.addDeviceSerial(mDeviceSerial);
     }
@@ -186,9 +179,6 @@
      */
     @Override
     public void testStarted(TestIdentifier test) {
-        if (mIsDeviceInfoRun) {
-            return;
-        }
         mCurrentCaseResult = mCurrentModuleResult.getOrCreateResult(test.getClassName());
         mCurrentResult = mCurrentCaseResult.getOrCreateResult(test.getTestName());
         // Reset the result
@@ -200,9 +190,6 @@
      */
     @Override
     public void testEnded(TestIdentifier test, Map<String, String> metrics) {
-        if (mIsDeviceInfoRun) {
-            return;
-        }
         if (mCurrentResult.getResultStatus() == TestStatus.FAIL) {
             // Test has already failed.
             return;
@@ -239,9 +226,6 @@
      */
     @Override
     public void testFailed(TestIdentifier test, String trace) {
-        if (mIsDeviceInfoRun) {
-            return;
-        }
         mCurrentResult.failed(trace);
         logResult("%s failed: %s", test, trace);
     }
@@ -251,9 +235,6 @@
      */
     @Override
     public void testAssumptionFailure(TestIdentifier test, String trace) {
-        if (mIsDeviceInfoRun) {
-            return;
-        }
         mCurrentResult.failed(trace);
         logResult("%s failed assumption: %s", test, trace);
     }
@@ -272,26 +253,21 @@
      */
     @Override
     public void testRunEnded(long elapsedTime, Map<String, String> metrics) {
-        if (mIsDeviceInfoRun) {
-            for (Map.Entry<String, String> metricEntry : metrics.entrySet()) {
-                String key = metricEntry.getKey();
-                String value = metricEntry.getValue();
-                if (key.startsWith(DEVICE_INFO)) {
-                    // Device info needs to be in the report
-                    mResult.addBuildInfo(key.substring(DEVICE_INFO.length()), value);
-                } else if (!value.endsWith(DEVICE_INFO_EXT)) {
-                    Log.logAndDisplay(LogLevel.INFO, mDeviceSerial,
-                            String.format("%s failed: %s", metricEntry.getKey(), value));
-                }
+        // Check build attributes to add generic device info to report.
+        Map<String, String> buildAttributes = mBuild.getBuildAttributes();
+        for (Map.Entry<String, String> attributeEntry : buildAttributes.entrySet()) {
+            String key = attributeEntry.getKey();
+            String value = attributeEntry.getValue();
+            if (key.startsWith(DEVICE_INFO_GENERIC)) {
+                mResult.addBuildInfo(key.substring(DEVICE_INFO_GENERIC.length()), value);
             }
-        } else {
-            logResult("%s completed in %dms. %d passed, %d failed, %d non executed",
-                    mCurrentModuleResult.getId(),
-                    elapsedTime,
-                    mCurrentModuleResult.countResults(TestStatus.PASS),
-                    mCurrentModuleResult.countResults(TestStatus.FAIL),
-                    mCurrentModuleResult.countResults(TestStatus.NOT_EXECUTED));
         }
+        logResult("%s completed in %dms. %d passed, %d failed, %d non executed",
+                mCurrentModuleResult.getId(),
+                elapsedTime,
+                mCurrentModuleResult.countResults(TestStatus.PASS),
+                mCurrentModuleResult.countResults(TestStatus.FAIL),
+                mCurrentModuleResult.countResults(TestStatus.NOT_EXECUTED));
     }
 
     /**
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ApkInstrumentationPreparer.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ApkInstrumentationPreparer.java
index 7671bc1..34a528e 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ApkInstrumentationPreparer.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ApkInstrumentationPreparer.java
@@ -38,13 +38,14 @@
 import java.io.FileNotFoundException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * Target preparer that instruments an APK.
  */
 @OptionClass(alias="apk-instrumentation-preparer")
-public class ApkInstrumentationPreparer extends PreconditionCheck implements ITargetCleaner {
+public class ApkInstrumentationPreparer extends PreconditionPreparer implements ITargetCleaner {
 
     @Option(name = "apk", description = "Name of the apk to instrument", mandatory = true)
     protected String mApkFileName = null;
@@ -69,6 +70,8 @@
     @Option(name = "when", description = "When to instrument the apk", mandatory = true)
     protected When mWhen = null;
 
+    protected ConcurrentHashMap<TestIdentifier, Map<String, String>> testMetrics =
+            new ConcurrentHashMap<>();
     private ConcurrentHashMap<TestIdentifier, String> testFailures = new ConcurrentHashMap<>();
 
     /**
@@ -142,6 +145,11 @@
     public class TargetPreparerListener extends NoOpTestInvocationListener {
 
         @Override
+        public void testEnded(TestIdentifier test, Map<String, String> metrics) {
+            testMetrics.put(test, metrics);
+        }
+
+        @Override
         public void testFailed(TestIdentifier test, String trace) {
             testFailures.put(test, trace);
         }
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/BuildCheck.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/BuildCheck.java
index a6a83a7..cc7b671 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/BuildCheck.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/BuildCheck.java
@@ -28,7 +28,7 @@
  * Checks that the device's build type is as expected
  */
 @OptionClass(alias="build-check")
-public class BuildCheck extends PreconditionCheck {
+public class BuildCheck extends PreconditionPreparer {
 
     public enum BuildType {
         USER,
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java
new file mode 100644
index 0000000..7a86168
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compatibility.common.tradefed.targetprep;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.compatibility.common.tradefed.testtype.CompatibilityTest;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.build.IFolderBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.targetprep.BuildError;
+import com.android.tradefed.targetprep.ITargetPreparer;
+import com.android.tradefed.targetprep.TargetSetupError;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.Map;
+
+/**
+ * An {@link ApkInstrumentationPreparer} that collects device info.
+ */
+public class DeviceInfoCollector extends ApkInstrumentationPreparer {
+
+    private static String LOG_TAG = "DeviceInfoCollector";
+    private static String DEVICE_INFO_CLASS = "com.android.compatibility.common.deviceinfo";
+    private static String DEVICE_INFO_GENERIC = "DEVICE_INFO_GENERIC_";
+    private static String DEVICE_INFO_ERROR = "DEVICE_INFO_ERROR_";
+
+    @Option(name = CompatibilityTest.SKIP_DEVICE_INFO_OPTION, description =
+            "Whether device info collection should be skipped")
+    private boolean mSkipDeviceInfo = false;
+
+    @Option(name= "src-dir", description = "The directory to copy to the results dir")
+    private String mSrcDir;
+
+    @Option(name = "dest-dir", description = "The directory under the result to store the files")
+    private String mDestDir;
+
+    public DeviceInfoCollector() {
+        mWhen = When.BEFORE;
+    }
+
+    @Override
+    public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
+            BuildError, DeviceNotAvailableException {
+        if (mSkipDeviceInfo) {
+            return;
+        }
+
+        run(device, buildInfo);
+
+        // Check test metrics for errors and copy generic device info results to build attribute.
+        for (Map.Entry<TestIdentifier, Map<String, String>> metricEntry : testMetrics.entrySet()) {
+            if (!metricEntry.getKey().getClassName().startsWith(DEVICE_INFO_CLASS)) {
+                continue;
+            }
+            for (Map.Entry<String, String> testEntry : metricEntry.getValue().entrySet()) {
+                String key = testEntry.getKey();
+                String value = testEntry.getValue();
+                if (key.startsWith(DEVICE_INFO_ERROR)) {
+                    throw new TargetSetupError(String.format("[%s] %s", key, value));
+                }
+                if (key.startsWith(DEVICE_INFO_GENERIC)) {
+                    buildInfo.addBuildAttribute(key, value);
+                }
+            }
+        }
+
+        getDeviceInfoFiles(device, buildInfo);
+    }
+
+    private void getDeviceInfoFiles(ITestDevice device, IBuildInfo buildInfo) {
+        CompatibilityBuildHelper buildHelper =
+                new CompatibilityBuildHelper((IFolderBuildInfo) buildInfo);
+        try {
+            File resultDir = buildHelper.getResultDir();
+            if (mDestDir != null) {
+                resultDir = new File(resultDir, mDestDir);
+            }
+            resultDir.mkdirs();
+            if (!resultDir.isDirectory()) {
+                CLog.e(LOG_TAG, String.format("% is not a directory", resultDir.getAbsolutePath()));
+                return;
+            }
+            String resultPath = resultDir.getAbsolutePath();
+            pull(device, mSrcDir, resultPath);
+        } catch (FileNotFoundException fnfe) {
+            fnfe.printStackTrace();
+        }
+    }
+
+    private void pull(ITestDevice device, String src, String dest) {
+        String command = String.format("adb -s %s pull %s %s", device.getSerialNumber(), src, dest);
+        try {
+            Process p = Runtime.getRuntime().exec(new String[] {"/bin/bash", "-c", command});
+            if (p.waitFor() != 0) {
+                CLog.e(LOG_TAG, String.format("Failed to run %s", command));
+            }
+        } catch (Exception e) {
+            CLog.e(LOG_TAG, e);
+        }
+    }
+}
\ No newline at end of file
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/LocaleCheck.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/LocaleCheck.java
index 96ee770..cbb7410 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/LocaleCheck.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/LocaleCheck.java
@@ -27,7 +27,7 @@
  * Checks that the device's locale is as expected
  */
 @OptionClass(alias="locale-check")
-public class LocaleCheck extends PreconditionCheck {
+public class LocaleCheck extends PreconditionPreparer {
 
     @Option(name = "expected-locale", description = "The device's expected locale",
             mandatory = true)
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PreconditionCheck.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PreconditionCheck.java
deleted file mode 100644
index 8413397..0000000
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PreconditionCheck.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.compatibility.common.tradefed.targetprep;
-
-import com.android.compatibility.common.tradefed.testtype.CompatibilityTest;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.config.Option;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.targetprep.BuildError;
-import com.android.tradefed.targetprep.ITargetPreparer;
-import com.android.tradefed.targetprep.TargetSetupError;
-
-/**
- * An {@link ITargetPreparer} that checks whether the device is ready for CTS.
- */
-public abstract class PreconditionCheck implements ITargetPreparer {
-
-    @Option(name = CompatibilityTest.SKIP_PRECONDITION_CHECKS_OPTION, description =
-            "Whether precondition checks should be skipped")
-    private boolean mSkipPreconditionChecks = false;
-
-    @Override
-    public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
-            BuildError, DeviceNotAvailableException {
-        if (!mSkipPreconditionChecks) {
-            run(device, buildInfo);
-        }
-    }
-
-    public abstract void run(ITestDevice device, IBuildInfo buildInfo)
-            throws TargetSetupError, BuildError, DeviceNotAvailableException;
-}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PreconditionTask.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PreconditionPreparer.java
similarity index 78%
rename from common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PreconditionTask.java
rename to common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PreconditionPreparer.java
index 03b2206..5c94c27 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PreconditionTask.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/PreconditionPreparer.java
@@ -26,18 +26,19 @@
 import com.android.tradefed.targetprep.TargetSetupError;
 
 /**
- * An {@link ITargetPreparer} that performs a task to set the device up to run the test.
+ * An {@link ITargetPreparer} that performs checks and/or tasks to ensure the 
+ * the device is ready to run the test suite.
  */
-public abstract class PreconditionTask implements ITargetPreparer {
+public abstract class PreconditionPreparer implements ITargetPreparer {
 
-    @Option(name = CompatibilityTest.SKIP_PRECONDITION_TASKS_OPTION, description =
-            "Whether precondition setup tasks should be skipped")
-    private boolean mSkipPreconditionTasks = false;
+    @Option(name = CompatibilityTest.SKIP_PRECONDITIONS_OPTION, description =
+            "Whether preconditions should be skipped")
+    private boolean mSkipPreconditions = false;
 
     @Override
     public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
             BuildError, DeviceNotAvailableException {
-        if (!mSkipPreconditionTasks) {
+        if (!mSkipPreconditions) {
             run(device, buildInfo);
         }
     }
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/SettingsCheck.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/SettingsCheck.java
deleted file mode 100644
index 9313d8f..0000000
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/SettingsCheck.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.compatibility.common.tradefed.targetprep;
-
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.config.Option;
-import com.android.tradefed.config.OptionClass;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.targetprep.BuildError;
-import com.android.tradefed.targetprep.TargetSetupError;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Checks that a given setting on the device is one of the given values
- */
-@OptionClass(alias="settings-check")
-public class SettingsCheck extends PreconditionCheck {
-
-    public enum SettingType {
-        SECURE,
-        GLOBAL,
-        SYSTEM;
-    }
-
-    @Option(name = "device-setting", description = "The setting on the device to be checked",
-            mandatory = true)
-    protected String mSettingName = null;
-
-    @Option(name = "expected-values", description = "The set of expected values of the setting")
-    protected List<String> mExpectedSettingValues = new ArrayList<String>();
-
-    @Option(name = "setting-type",
-            description = "If the setting is 'secure', 'global', or 'system'", mandatory = true)
-    protected SettingType mSettingType = null;
-
-    @Override
-    public void run(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
-            BuildError, DeviceNotAvailableException {
-
-        String shellCmd = String.format("settings get %s %s", mSettingType, mSettingName);
-        String actualSettingValue = device.executeShellCommand(shellCmd).trim();
-        if (!mExpectedSettingValues.contains(actualSettingValue)) {
-            throw new TargetSetupError(
-                    String.format("Device setting \"%s\" returned \"%s\", not found in %s",
-                    mSettingName, actualSettingValue, mExpectedSettingValues.toString()));
-        }
-    }
-
-}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/SettingsPreparer.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/SettingsPreparer.java
new file mode 100644
index 0000000..6d82f7a
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/SettingsPreparer.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.compatibility.common.tradefed.targetprep;
+
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.config.OptionClass;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.targetprep.BuildError;
+import com.android.tradefed.targetprep.TargetSetupError;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Checks that a given setting on the device is one of the given values
+ */
+@OptionClass(alias="settings-preparer")
+public class SettingsPreparer extends PreconditionPreparer {
+
+    public enum SettingType {
+        SECURE,
+        GLOBAL,
+        SYSTEM;
+    }
+
+    @Option(name = "device-setting", description = "The setting on the device to be checked",
+            mandatory = true)
+    protected String mSettingName = null;
+
+    @Option(name = "setting-type",
+            description = "If the setting is 'secure', 'global', or 'system'", mandatory = true)
+    protected SettingType mSettingType = null;
+
+    @Option(name = "set-value", description = "The value to be set for the setting")
+    protected String mSetValue = null;
+
+    @Option(name = "expected-values", description = "The set of expected values of the setting")
+    protected List<String> mExpectedSettingValues = new ArrayList<String>();
+
+    @Override
+    public void run(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
+            BuildError, DeviceNotAvailableException {
+
+        /* At least one of the options "set-value" and "expected-values" must be set */
+        if (mSetValue == null && mExpectedSettingValues.isEmpty()) {
+            throw new TargetSetupError("At least one of the options \"set-value\" and " +
+                    "\"expected-values\" must be set");
+        }
+
+        String shellCmdGet = (!mExpectedSettingValues.isEmpty()) ?
+                String.format("settings get %s %s", mSettingType, mSettingName) : "";
+        String shellCmdPut = (mSetValue != null) ?
+                String.format("settings put %s %s %s", mSettingType, mSettingName, mSetValue) : "";
+
+
+        /* Case 1: Both expected-values and set-value are given */
+        if (mSetValue != null && !mExpectedSettingValues.isEmpty()) {
+            // first ensure that the set-value given can be found in expected-values
+            if (!mExpectedSettingValues.contains(mSetValue)) {
+                throw new TargetSetupError(String.format(
+                        "set-value for %s is %s, but value not found in expected-values: %s",
+                        mSettingName, mSetValue, mExpectedSettingValues.toString()));
+            }
+            String currentSettingValue = device.executeShellCommand(shellCmdGet).trim();
+            // only change unexpected setting value
+            if (!mExpectedSettingValues.contains(currentSettingValue)) {
+                device.executeShellCommand(shellCmdPut);
+            }
+            return;
+        }
+
+        /* Case 2: Only set-value given */
+        if (mSetValue != null) {
+            device.executeShellCommand(shellCmdPut);
+            return;
+        }
+
+        /* Case 3: Only expected-values given */
+        String currentSettingValue = device.executeShellCommand(shellCmdGet).trim();
+        if (!mExpectedSettingValues.contains(currentSettingValue)) {
+            throw new TargetSetupError(
+                    String.format("Device setting \"%s\" returned \"%s\", not found in %s",
+                    mSettingName, currentSettingValue, mExpectedSettingValues.toString()));
+        }
+    }
+
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/SettingsTask.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/SettingsTask.java
deleted file mode 100644
index 7165ad3..0000000
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/SettingsTask.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.compatibility.common.tradefed.targetprep;
-
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.config.Option;
-import com.android.tradefed.config.OptionClass;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.targetprep.BuildError;
-import com.android.tradefed.targetprep.TargetSetupError;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Checks that a given setting on the device is one of the given values
- */
-@OptionClass(alias="settings-task")
-public class SettingsTask extends PreconditionTask {
-
-    public enum SettingType {
-        SECURE,
-        GLOBAL,
-        SYSTEM;
-    }
-
-    @Option(name = "device-setting", description = "The setting on the device to be checked",
-            mandatory = true)
-    protected String mSettingName = null;
-
-    @Option(name = "setting-type",
-            description = "If the setting is 'secure', 'global' or 'system'", mandatory = true)
-    protected SettingType mSettingType = null;
-
-    @Option(name = "set-value",
-            description = "The value to be set for the setting", mandatory = true)
-    protected String mSetValue = null;
-
-    @Override
-    public void run(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
-            BuildError, DeviceNotAvailableException {
-        device.executeShellCommand(
-            String.format("settings put %s %s %s", mSettingType, mSettingName, mSetValue));
-    }
-
-}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/WifiCheck.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/WifiCheck.java
new file mode 100644
index 0000000..b13a2a8
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/WifiCheck.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.compatibility.common.tradefed.targetprep;
+
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.config.OptionClass;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.targetprep.BuildError;
+import com.android.tradefed.targetprep.TargetSetupError;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This preparer ensures that the device is connected to a network.
+ * The options "wifi-ssid" and "wifi-psk" allow users of the preparer to attempt connection
+ * to a network. If the options are provided, the preparer disconnects any existing network
+ * connection, and attempts to connect with the options provided.
+ *
+ * @throws TargetSetupError if device is not connected to a network and no options are given, or
+ * if the device fails to connect to the network specified in the options
+ */
+@OptionClass(alias="wifi-check")
+public class WifiCheck extends PreconditionPreparer {
+
+    @Option(name = "wifi-ssid", description = "Name of the WiFi network with which to connect")
+    protected String mWifiSsid = null;
+
+    @Option(name = "wifi-psk",
+            description = "The WPA-PSK associated with the wifi-ssid option")
+    protected String mWifiPsk = null;
+
+    @Override
+    public void run(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
+            BuildError, DeviceNotAvailableException {
+        if (mWifiSsid == null) { // no connection to create, check for existing connectivity
+            if (!device.checkConnectivity()) {
+                throw new TargetSetupError("Device has no network connection, no ssid provided");
+            }  
+        } else { // network provided in options, attempt to create new connection
+            CLog.logAndDisplay(LogLevel.INFO, "Attempting connection to \"%s\"", mWifiSsid);
+            if (device.connectToWifiNetwork(mWifiSsid, mWifiPsk)) { // attempt connection
+                CLog.logAndDisplay(LogLevel.INFO, "Connection successful");
+            } else {
+                throw new TargetSetupError(String.format(
+                        "Unable to connect to network \"%s\", some modules of CTS" +
+                        "require an active network connection", mWifiSsid));
+            }
+        }
+    }
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java
index ad58661..1454aa0 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java
@@ -65,9 +65,8 @@
     public static final String RETRY_OPTION = "retry";
     private static final String ABI_OPTION = "abi";
     private static final String SHARD_OPTION = "shard";
-    private static final String SKIP_DEVICE_INFO_OPTION = "skip-device-info";
-    public static final String SKIP_PRECONDITION_CHECKS_OPTION = "skip-precondition-checks";
-    public static final String SKIP_PRECONDITION_TASKS_OPTION = "skip-precondition-tasks";
+    public static final String SKIP_DEVICE_INFO_OPTION = "skip-device-info";
+    public static final String SKIP_PRECONDITIONS_OPTION = "skip-preconditions";
     private static final String URL = "dynamic-config-url";
 
     private static final TestStatus[] RETRY_TEST_STATUS = new TestStatus[] {
@@ -126,13 +125,9 @@
             "Whether device info collection should be skipped")
     private boolean mSkipDeviceInfo = false;
 
-    @Option(name = SKIP_PRECONDITION_CHECKS_OPTION, description =
-            "Whether precondition checks should be skipped")
-    private boolean mSkipPreconditionChecks = false;
-
-    @Option(name = SKIP_PRECONDITION_TASKS_OPTION, description =
-            "Whether precondition setup tasks should be skipped")
-    private boolean mSkipPreconditionTasks = false;
+    @Option(name = SKIP_PRECONDITIONS_OPTION, description =
+            "Whether preconditions should be skipped")
+    private boolean mSkipPreconditions = false;
 
     @Option(name = "bugreport-on-failure", description =
             "Take a bugreport on every test failure. " +
@@ -238,7 +233,7 @@
                 IModuleDef module = mModules.get(i);
                 module.setBuild(mBuild);
                 module.setDevice(mDevice);
-                module.runPreconditions(mSkipPreconditionChecks, mSkipPreconditionTasks);
+                module.prepare(mSkipPreconditions);
             }
             // Run the tests
             for (int i = mLastModuleIndex; i < moduleCount; i++) {
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleDef.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleDef.java
index 25d47a3..432b865 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleDef.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleDef.java
@@ -79,6 +79,6 @@
     /**
      * Runs the module's precondition checks and setup tasks.
      */
-    void runPreconditions(boolean skipChecks, boolean skipSetup) throws DeviceNotAvailableException;
+    void prepare(boolean skipPrep) throws DeviceNotAvailableException;
 
 }
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleDef.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleDef.java
index ba5550d..1b5f915 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleDef.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleDef.java
@@ -17,8 +17,7 @@
 
 import com.android.compatibility.common.tradefed.result.IModuleListener;
 import com.android.compatibility.common.tradefed.result.ModuleListener;
-import com.android.compatibility.common.tradefed.targetprep.PreconditionCheck;
-import com.android.compatibility.common.tradefed.targetprep.PreconditionTask;
+import com.android.compatibility.common.tradefed.targetprep.PreconditionPreparer;
 import com.android.compatibility.common.util.AbiUtils;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.config.ConfigurationException;
@@ -68,7 +67,7 @@
         mTests = tests;
         for (ITargetPreparer preparer : preparers) {
             // Separate preconditions from target preparers.
-            if (preparer instanceof PreconditionCheck || preparer instanceof PreconditionTask) {
+            if (preparer instanceof PreconditionPreparer) {
                 mPreconditions.add(preparer);
             } else {
                 mPreparers.add(preparer);
@@ -234,21 +233,14 @@
      * {@inheritDoc}
      */
     @Override
-    public void runPreconditions(boolean skipChecks, boolean skipSetup)
-            throws DeviceNotAvailableException {
+    public void prepare(boolean skipPrep) throws DeviceNotAvailableException {
         for (ITargetPreparer preparer : mPreconditions) {
             CLog.d("Preparer: %s", preparer.getClass().getSimpleName());
             if (preparer instanceof IAbiReceiver) {
                 ((IAbiReceiver) preparer).setAbi(mAbi);
             }
-            if (preparer instanceof PreconditionCheck) {
-                setOption(preparer, CompatibilityTest.SKIP_PRECONDITION_CHECKS_OPTION,
-                        Boolean.toString(skipChecks));
-            }
-            if (preparer instanceof PreconditionTask) {
-                setOption(preparer, CompatibilityTest.SKIP_PRECONDITION_TASKS_OPTION,
-                        Boolean.toString(skipSetup));
-            }
+            setOption(preparer, CompatibilityTest.SKIP_PRECONDITIONS_OPTION,
+                    Boolean.toString(skipPrep));
             try {
                 preparer.setUp(mDevice, mBuild);
             } catch (BuildError e) {
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/UnitTests.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/UnitTests.java
index c2c961c..8b8426d 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/UnitTests.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/UnitTests.java
@@ -20,8 +20,7 @@
 import com.android.compatibility.common.tradefed.result.ResultReporterTest;
 import com.android.compatibility.common.tradefed.targetprep.BuildCheckTest;
 import com.android.compatibility.common.tradefed.targetprep.LocaleCheckTest;
-import com.android.compatibility.common.tradefed.targetprep.SettingsCheckTest;
-import com.android.compatibility.common.tradefed.targetprep.SettingsTaskTest;
+import com.android.compatibility.common.tradefed.targetprep.SettingsPreparerTest;
 import com.android.compatibility.common.tradefed.testtype.CompatibilityTestTest;
 import com.android.compatibility.common.tradefed.testtype.ModuleDefTest;
 import com.android.compatibility.common.tradefed.testtype.ModuleRepoTest;
@@ -46,8 +45,7 @@
         addTestSuite(ModuleRepoTest.class);
         addTestSuite(BuildCheckTest.class);
         addTestSuite(LocaleCheckTest.class);
-        addTestSuite(SettingsCheckTest.class);
-        addTestSuite(SettingsTaskTest.class);
+        addTestSuite(SettingsPreparerTest.class);
     }
 
     public static Test suite() {
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/targetprep/SettingsCheckTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/targetprep/SettingsCheckTest.java
deleted file mode 100644
index bd247a0..0000000
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/targetprep/SettingsCheckTest.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.compatibility.common.tradefed.targetprep;
-
-import com.android.tradefed.build.DeviceBuildInfo;
-import com.android.tradefed.build.BuildInfo;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.config.OptionSetter;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.targetprep.TargetSetupError;
-
-import junit.framework.TestCase;
-
-import org.easymock.EasyMock;
-
-public class SettingsCheckTest extends TestCase {
-
-    private SettingsCheck mSettingsCheck;
-    private IBuildInfo mMockBuildInfo;
-    private ITestDevice mMockDevice;
-    private OptionSetter mOptionSetter;
-
-    private static final String SHELL_CMD = "settings get GLOBAL stay_on_while_plugged_in";
-
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        mSettingsCheck = new SettingsCheck();
-        mMockDevice = EasyMock.createMock(ITestDevice.class);
-        mMockBuildInfo = new BuildInfo("0", "", "");
-        mOptionSetter = new OptionSetter(mSettingsCheck);
-        mOptionSetter.setOptionValue("device-setting", "stay_on_while_plugged_in");
-        mOptionSetter.setOptionValue("setting-type", "global");
-    }
-
-    public void testCorrectOneExpected() throws Exception {
-        EasyMock.expect(mMockDevice.executeShellCommand(SHELL_CMD)).andReturn("\n3\n").once();
-        mOptionSetter.setOptionValue("expected-values", "3");
-        EasyMock.replay(mMockDevice);
-        mSettingsCheck.run(mMockDevice, mMockBuildInfo);
-    }
-
-    public void testCorrectManyExpected() throws Exception {
-        EasyMock.expect(mMockDevice.executeShellCommand(SHELL_CMD)).andReturn("\n3\n").once();
-        mOptionSetter.setOptionValue("expected-values", "2");
-        mOptionSetter.setOptionValue("expected-values", "3");
-        mOptionSetter.setOptionValue("expected-values", "6");
-        mOptionSetter.setOptionValue("expected-values", "7");
-        EasyMock.replay(mMockDevice);
-        mSettingsCheck.run(mMockDevice, mMockBuildInfo);
-    }
-
-    public void testIncorrectOneExpected() throws Exception {
-        EasyMock.expect(mMockDevice.executeShellCommand(SHELL_CMD)).andReturn("\n0\n").once();
-        mOptionSetter.setOptionValue("expected-values", "3");
-        EasyMock.replay(mMockDevice);
-        try {
-            mSettingsCheck.run(mMockDevice, mMockBuildInfo);
-            fail("TargetSetupError expected");
-        } catch (TargetSetupError e) {
-            //Expected
-        }
-    }
-
-    public void testIncorrectManyExpected() throws Exception {
-        EasyMock.expect(mMockDevice.executeShellCommand(SHELL_CMD)).andReturn("\n0\n").once();
-        mOptionSetter.setOptionValue("expected-values", "2");
-        mOptionSetter.setOptionValue("expected-values", "3");
-        mOptionSetter.setOptionValue("expected-values", "6");
-        mOptionSetter.setOptionValue("expected-values", "7");
-        EasyMock.replay(mMockDevice);
-        try {
-            mSettingsCheck.run(mMockDevice, mMockBuildInfo);
-            fail("TargetSetupError expected");
-        } catch (TargetSetupError e) {
-            //Expected
-        }
-    }
-
-}
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/targetprep/SettingsPreparerTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/targetprep/SettingsPreparerTest.java
new file mode 100644
index 0000000..739662e
--- /dev/null
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/targetprep/SettingsPreparerTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compatibility.common.tradefed.targetprep;
+
+import com.android.tradefed.build.DeviceBuildInfo;
+import com.android.tradefed.build.BuildInfo;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.OptionSetter;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.targetprep.TargetSetupError;
+
+import junit.framework.TestCase;
+
+import org.easymock.EasyMock;
+
+public class SettingsPreparerTest extends TestCase {
+
+    private SettingsPreparer mSettingsPreparer;
+    private IBuildInfo mMockBuildInfo;
+    private ITestDevice mMockDevice;
+    private OptionSetter mOptionSetter;
+
+    private static final String SHELL_CMD_GET = "settings get GLOBAL stay_on_while_plugged_in";
+    private static final String SHELL_CMD_PUT_7 = "settings put GLOBAL stay_on_while_plugged_in 7";
+    private static final String SHELL_CMD_PUT_8 = "settings put GLOBAL stay_on_while_plugged_in 8";
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mSettingsPreparer = new SettingsPreparer();
+        mMockDevice = EasyMock.createMock(ITestDevice.class);
+        mMockBuildInfo = new BuildInfo("0", "", "");
+        mOptionSetter = new OptionSetter(mSettingsPreparer);
+        mOptionSetter.setOptionValue("device-setting", "stay_on_while_plugged_in");
+        mOptionSetter.setOptionValue("setting-type", "global");
+    }
+
+    public void testCorrectOneExpected() throws Exception {
+        EasyMock.expect(mMockDevice.executeShellCommand(SHELL_CMD_GET)).andReturn("\n3\n").once();
+        mOptionSetter.setOptionValue("expected-values", "3");
+        EasyMock.replay(mMockDevice);
+        mSettingsPreparer.run(mMockDevice, mMockBuildInfo);
+    }
+
+    public void testCorrectManyExpected() throws Exception {
+        EasyMock.expect(mMockDevice.executeShellCommand(SHELL_CMD_GET)).andReturn("\n3\n").once();
+        mOptionSetter.setOptionValue("expected-values", "2");
+        mOptionSetter.setOptionValue("expected-values", "3");
+        mOptionSetter.setOptionValue("expected-values", "6");
+        mOptionSetter.setOptionValue("expected-values", "7");
+        EasyMock.replay(mMockDevice);
+        mSettingsPreparer.run(mMockDevice, mMockBuildInfo);
+    }
+
+    public void testIncorrectOneExpected() throws Exception {
+        EasyMock.expect(mMockDevice.executeShellCommand(SHELL_CMD_GET)).andReturn("\n0\n").once();
+        mOptionSetter.setOptionValue("expected-values", "3");
+        EasyMock.replay(mMockDevice);
+        try {
+            mSettingsPreparer.run(mMockDevice, mMockBuildInfo);
+            fail("TargetSetupError expected");
+        } catch (TargetSetupError e) {
+            //Expected
+        }
+    }
+
+    public void testIncorrectManyExpected() throws Exception {
+        EasyMock.expect(mMockDevice.executeShellCommand(SHELL_CMD_GET)).andReturn("\n0\n").once();
+        mOptionSetter.setOptionValue("expected-values", "2");
+        mOptionSetter.setOptionValue("expected-values", "3");
+        mOptionSetter.setOptionValue("expected-values", "6");
+        mOptionSetter.setOptionValue("expected-values", "7");
+        EasyMock.replay(mMockDevice);
+        try {
+            mSettingsPreparer.run(mMockDevice, mMockBuildInfo);
+            fail("TargetSetupError expected");
+        } catch (TargetSetupError e) {
+            //Expected
+        }
+    }
+
+    public void testCommandRun() throws Exception {
+        EasyMock.expect(mMockDevice.executeShellCommand(SHELL_CMD_PUT_7)).andReturn("\n");
+        mOptionSetter.setOptionValue("set-value", "7");
+        EasyMock.replay(mMockDevice);
+        mSettingsPreparer.run(mMockDevice, mMockBuildInfo);
+    }
+
+    public void testCommandRunWrongSetValue() throws Exception {
+        EasyMock.expect(mMockDevice.executeShellCommand(SHELL_CMD_PUT_8)).andReturn("\n");
+        mOptionSetter.setOptionValue("set-value", "8");
+        mOptionSetter.setOptionValue("expected-values", "7");
+        EasyMock.replay(mMockDevice);
+        try {
+            mSettingsPreparer.run(mMockDevice, mMockBuildInfo);
+            fail("TargetSetupError expected");
+        } catch (TargetSetupError e) {
+            //Expected
+        }
+    }
+
+    public void testIncorrectOneExpectedCommandRun() throws Exception {
+        EasyMock.expect(mMockDevice.executeShellCommand(SHELL_CMD_GET)).andReturn("\n0\n").once();
+        EasyMock.expect(mMockDevice.executeShellCommand(SHELL_CMD_PUT_7)).andReturn("\n");
+        mOptionSetter.setOptionValue("set-value", "7");
+        mOptionSetter.setOptionValue("expected-values", "7");
+    }
+
+}
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/targetprep/SettingsTaskTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/targetprep/SettingsTaskTest.java
deleted file mode 100644
index eab1c89..0000000
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/targetprep/SettingsTaskTest.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.compatibility.common.tradefed.targetprep;
-
-import com.android.tradefed.build.DeviceBuildInfo;
-import com.android.tradefed.build.BuildInfo;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.config.OptionSetter;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.targetprep.TargetSetupError;
-
-import junit.framework.TestCase;
-
-import org.easymock.EasyMock;
-
-public class SettingsTaskTest extends TestCase {
-
-    private SettingsTask mSettingsTask;
-    private IBuildInfo mMockBuildInfo;
-    private ITestDevice mMockDevice;
-
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        mSettingsTask = new SettingsTask();
-        mMockDevice = EasyMock.createMock(ITestDevice.class);
-        mMockBuildInfo = new BuildInfo("0", "", "");
-    }
-
-    public void testCommandRun() throws Exception {
-        EasyMock.expect(mMockDevice.executeShellCommand(
-                "settings put GLOBAL stay_on_while_plugged_in 7")).andReturn("\n");
-        OptionSetter optionSetter = new OptionSetter(mSettingsTask);
-        optionSetter.setOptionValue("device-setting", "stay_on_while_plugged_in");
-        optionSetter.setOptionValue("setting-type", "global");
-        optionSetter.setOptionValue("set-value", "7");
-        EasyMock.replay(mMockDevice);
-        mSettingsTask.run(mMockDevice, mMockBuildInfo);
-    }
-
-}
diff --git a/hostsidetests/dumpsys/src/android/dumpsys/cts/DumpsysHostTest.java b/hostsidetests/dumpsys/src/android/dumpsys/cts/DumpsysHostTest.java
index 0daae03..f7c5219 100644
--- a/hostsidetests/dumpsys/src/android/dumpsys/cts/DumpsysHostTest.java
+++ b/hostsidetests/dumpsys/src/android/dumpsys/cts/DumpsysHostTest.java
@@ -486,6 +486,8 @@
                     case "ctr":
                         checkChargeTimeRemain(parts);
                         break;
+                    case "cpu":
+                        checkUidCpuUsage(parts);
                     default:
                         break;
                 }
@@ -814,6 +816,12 @@
         assertInteger(parts[4]); // chargeTimeRemaining
     }
 
+    private void checkUidCpuUsage(String[] parts) {
+        assertTrue(parts.length >= 6);
+        assertInteger(parts[4]); // user time
+        assertInteger(parts[5]); // system time
+    }
+
     /**
      * Tests the output of "dumpsys gfxinfo framestats".
      *
diff --git a/run_unit_tests.sh b/run_unit_tests.sh
index 882cef8..4d0480f 100755
--- a/run_unit_tests.sh
+++ b/run_unit_tests.sh
@@ -36,6 +36,9 @@
     fi;
 fi;
 
+############### Build the tests ###############
+make compatibility-common-util-tests compatibility-host-util-tests compatibility-device-util-tests compatibility-tradefed-tests cts-tradefed-tests_v2 compatibility-device-info-tests compatibility-manifest-generator-tests compatibility-host-media-preconditions-tests CompatibilityTestApp -j32
+
 ############### Run the device side tests ###############
 JAR_DIR=${ANDROID_HOST_OUT}/framework
 JARS="
@@ -125,3 +128,23 @@
 for CLASS in ${TEST_CLASSES}; do
     java $RDBG_FLAG -cp ${JAR_PATH} ${TF_CONSOLE} run singleCommand host -n --class ${CLASS} "$@"
 done
+
+############### Run precondition tests ###############
+JARS="
+    tradefed-prebuilt\
+    compatibility-host-util\
+    cts-tradefed_v2\
+    compatibility-host-media-preconditions\
+    compatibility-host-media-preconditions-tests"
+JAR_PATH=
+for JAR in $JARS; do
+    checkFile ${JAR_DIR}/${JAR}.jar
+    JAR_PATH=${JAR_PATH}:${JAR_DIR}/${JAR}.jar
+done
+
+TEST_CLASSES="
+    android.mediastress.cts.preconditions.MediaPreparerTest"
+
+for CLASS in ${TEST_CLASSES}; do
+    java $RDBG_FLAG -cp ${JAR_PATH} ${TF_CONSOLE} run singleCommand host -n --class ${CLASS} "$@"
+done
diff --git a/tests/accessibilityservice/res/layout/accessibility_text_traversal_test.xml b/tests/accessibilityservice/res/layout/accessibility_text_traversal_test.xml
index 229dbfe..9906227 100644
--- a/tests/accessibilityservice/res/layout/accessibility_text_traversal_test.xml
+++ b/tests/accessibilityservice/res/layout/accessibility_text_traversal_test.xml
@@ -42,13 +42,13 @@
 
    <EditText
        android:id="@+id/edit"
-       android:layout_width="64dip"
+       android:layout_width="80dip"
        android:layout_height="80dip"
        android:maxLines="1000"
        android:scrollbars="vertical"
        android:focusable="false"
        android:includeFontPadding="false"
-       android:textSize="8dip"
+       android:textSize="10dip"
        android:textStyle="normal"
        android:fontFamily="sans-serif"
        android:visibility="gone"
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
index 2b9e0a9..1bd4e0a 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
@@ -332,6 +332,9 @@
                 .setTicker(message)
                 .setContentTitle("")
                 .setContentText("")
+                // Mark the notification as "interruptive" by specifying a vibration pattern. This
+                // ensures it's announced properly on watch-type devices.
+                .setVibrate(new long[] {})
                 .build();
 
         // create and populate the expected event
diff --git a/suite/cts/deviceTests/simplecpu/Android.mk b/tests/simplecpu/Android.mk
similarity index 89%
rename from suite/cts/deviceTests/simplecpu/Android.mk
rename to tests/simplecpu/Android.mk
index 0a0be45..707a380 100644
--- a/suite/cts/deviceTests/simplecpu/Android.mk
+++ b/tests/simplecpu/Android.mk
@@ -27,7 +27,10 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_PACKAGE_NAME := CtsDeviceSimpleCpu
+LOCAL_PACKAGE_NAME := CtsSimpleCpuTestCases
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
 
 LOCAL_SDK_VERSION := 16
 
diff --git a/suite/cts/deviceTests/simplecpu/AndroidManifest.xml b/tests/simplecpu/AndroidManifest.xml
similarity index 86%
rename from suite/cts/deviceTests/simplecpu/AndroidManifest.xml
rename to tests/simplecpu/AndroidManifest.xml
index e5c1c2b..4b5febf 100644
--- a/suite/cts/deviceTests/simplecpu/AndroidManifest.xml
+++ b/tests/simplecpu/AndroidManifest.xml
@@ -15,7 +15,7 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.cts.simplecpu">
+        package="android.simplecpu.cts">
 
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
@@ -24,6 +24,6 @@
         <uses-library android:name="android.test.runner" />
     </application>
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
-            android:targetPackage="com.android.cts.simplecpu"
-            android:label="Very simple CPU benchmarking" />
+            android:targetPackage="android.simplecpu.cts"
+            android:label="CTS tests for simple CPU" />
 </manifest>
diff --git a/tests/simplecpu/AndroidTest.xml b/tests/simplecpu/AndroidTest.xml
new file mode 100644
index 0000000..e514a9c
--- /dev/null
+++ b/tests/simplecpu/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for CTS File System test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsSimpleCpuTestCases.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.simplecpu.cts" />
+    </test>
+</configuration>
diff --git a/suite/cts/deviceTests/simplecpu/jni/Android.mk b/tests/simplecpu/jni/Android.mk
similarity index 91%
rename from suite/cts/deviceTests/simplecpu/jni/Android.mk
rename to tests/simplecpu/jni/Android.mk
index 946aa37..7f9ce24 100644
--- a/suite/cts/deviceTests/simplecpu/jni/Android.mk
+++ b/tests/simplecpu/jni/Android.mk
@@ -26,6 +26,9 @@
 
 LOCAL_SHARED_LIBRARIES := libnativehelper
 
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
 LOCAL_SDK_VERSION := 14
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/suite/cts/deviceTests/simplecpu/jni/CpuNativeJni.cpp b/tests/simplecpu/jni/CpuNativeJni.cpp
similarity index 97%
rename from suite/cts/deviceTests/simplecpu/jni/CpuNativeJni.cpp
rename to tests/simplecpu/jni/CpuNativeJni.cpp
index e0be7f3..4ea0dc0 100644
--- a/suite/cts/deviceTests/simplecpu/jni/CpuNativeJni.cpp
+++ b/tests/simplecpu/jni/CpuNativeJni.cpp
@@ -182,7 +182,7 @@
     return *(int*)p1 - *(int*)p2;
 }
 
-extern "C" JNIEXPORT jdouble JNICALL Java_com_android_cts_simplecpu_CpuNative_runSort(JNIEnv* env,
+extern "C" JNIEXPORT jdouble JNICALL Java_android_simplecpu_cts_CpuNative_runSort(JNIEnv* env,
         jclass clazz, jint numberElements, jint repetition)
 {
     int* data = new int[numberElements];
@@ -239,7 +239,7 @@
     }
 }
 
-extern "C" JNIEXPORT jdouble JNICALL Java_com_android_cts_simplecpu_CpuNative_runMatrixMultiplication(
+extern "C" JNIEXPORT jdouble JNICALL Java_android_simplecpu_cts_CpuNative_runMatrixMultiplication(
         JNIEnv* env, jclass clazz, jint n, jint repetition)
 {
     // C = A x B
diff --git a/suite/cts/deviceTests/simplecpu/src/com/android/cts/simplecpu/CpuNative.java b/tests/simplecpu/src/android/simplecpu/cts/CpuNative.java
similarity index 96%
rename from suite/cts/deviceTests/simplecpu/src/com/android/cts/simplecpu/CpuNative.java
rename to tests/simplecpu/src/android/simplecpu/cts/CpuNative.java
index 8b48623..231cba6 100644
--- a/suite/cts/deviceTests/simplecpu/src/com/android/cts/simplecpu/CpuNative.java
+++ b/tests/simplecpu/src/android/simplecpu/cts/CpuNative.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.cts.simplecpu;
+package android.simplecpu.cts;
 
 public class CpuNative {
     static {
diff --git a/suite/cts/deviceTests/simplecpu/src/com/android/cts/simplecpu/SimpleCpuTest.java b/tests/simplecpu/src/android/simplecpu/cts/SimpleCpuTest.java
similarity index 98%
rename from suite/cts/deviceTests/simplecpu/src/com/android/cts/simplecpu/SimpleCpuTest.java
rename to tests/simplecpu/src/android/simplecpu/cts/SimpleCpuTest.java
index 520ae79..fa7f402 100644
--- a/suite/cts/deviceTests/simplecpu/src/com/android/cts/simplecpu/SimpleCpuTest.java
+++ b/tests/simplecpu/src/android/simplecpu/cts/SimpleCpuTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.cts.simplecpu;
+package android.simplecpu.cts;
 
 import android.cts.util.CtsAndroidTestCase;
 import android.util.Log;
diff --git a/tests/tests/animation/AndroidManifest.xml b/tests/tests/animation/AndroidManifest.xml
index 70f9de0..3744a2a 100644
--- a/tests/tests/animation/AndroidManifest.xml
+++ b/tests/tests/animation/AndroidManifest.xml
@@ -21,7 +21,9 @@
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
     <application>
         <activity android:name="android.animation.cts.AnimationActivity"
-            android:label="AnimationActivity"/>
+                  android:label="AnimationActivity"/>
+        <activity android:name="android.animation.cts.ButtonViewActivity"
+                  android:label="ButtonViewActivity"/>
         <activity
            android:name="android.animation.cts.LayoutAnimationActivity" />
         <uses-library android:name="android.test.runner" />
diff --git a/tests/tests/animation/res/animator/object_animator.xml b/tests/tests/animation/res/animator/object_animator.xml
new file mode 100644
index 0000000..17fcd60
--- /dev/null
+++ b/tests/tests/animation/res/animator/object_animator.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+          android:propertyName="x" android:valueFrom="0" android:valueTo="1">
+
+</objectAnimator>
\ No newline at end of file
diff --git a/tests/tests/animation/res/animator/object_animator_pvh1.xml b/tests/tests/animation/res/animator/object_animator_pvh1.xml
new file mode 100644
index 0000000..7e16bc8
--- /dev/null
+++ b/tests/tests/animation/res/animator/object_animator_pvh1.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android">
+    <propertyValuesHolder android:propertyName="x" android:valueFrom="0" android:valueTo="1"/>
+    <propertyValuesHolder android:propertyName="y" android:valueFrom="10" android:valueTo="11"/>
+</objectAnimator>
\ No newline at end of file
diff --git a/tests/tests/animation/res/animator/object_animator_pvh_kf1.xml b/tests/tests/animation/res/animator/object_animator_pvh_kf1.xml
new file mode 100644
index 0000000..b99b819
--- /dev/null
+++ b/tests/tests/animation/res/animator/object_animator_pvh_kf1.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android">
+    <propertyValuesHolder android:propertyName="x" android:valueFrom="0" android:valueTo="1"/>
+    <propertyValuesHolder android:propertyName="y" >
+        <keyframe android:fraction="0" android:value="10"/>
+        <keyframe android:fraction="1" android:value="11"/>
+    </propertyValuesHolder>
+</objectAnimator>
\ No newline at end of file
diff --git a/tests/tests/animation/res/animator/value_animator.xml b/tests/tests/animation/res/animator/value_animator.xml
new file mode 100644
index 0000000..4c1abfe
--- /dev/null
+++ b/tests/tests/animation/res/animator/value_animator.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<animator xmlns:android="http://schemas.android.com/apk/res/android"
+        android:valueFrom="0" android:valueTo="1">
+
+</animator>
\ No newline at end of file
diff --git a/tests/tests/animation/res/animator/value_animator_pvh1.xml b/tests/tests/animation/res/animator/value_animator_pvh1.xml
new file mode 100644
index 0000000..30540ec
--- /dev/null
+++ b/tests/tests/animation/res/animator/value_animator_pvh1.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<animator xmlns:android="http://schemas.android.com/apk/res/android">
+    <propertyValuesHolder android:valueFrom="0" android:valueTo="1"/>
+
+</animator>
\ No newline at end of file
diff --git a/tests/tests/animation/res/animator/value_animator_pvh2.xml b/tests/tests/animation/res/animator/value_animator_pvh2.xml
new file mode 100644
index 0000000..2c07b4e
--- /dev/null
+++ b/tests/tests/animation/res/animator/value_animator_pvh2.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<animator xmlns:android="http://schemas.android.com/apk/res/android">
+    <propertyValuesHolder android:valueFrom="0" android:valueTo="1"></propertyValuesHolder>
+
+</animator>
\ No newline at end of file
diff --git a/tests/tests/animation/res/animator/value_animator_pvh_kf1.xml b/tests/tests/animation/res/animator/value_animator_pvh_kf1.xml
new file mode 100644
index 0000000..e8fb9cc
--- /dev/null
+++ b/tests/tests/animation/res/animator/value_animator_pvh_kf1.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<animator xmlns:android="http://schemas.android.com/apk/res/android">
+    <propertyValuesHolder>
+        <keyframe android:fraction="0" android:value="0"/>
+        <keyframe android:fraction="1" android:value="1"/>
+    </propertyValuesHolder>
+</animator>
\ No newline at end of file
diff --git a/tests/tests/animation/res/animator/value_animator_pvh_kf2.xml b/tests/tests/animation/res/animator/value_animator_pvh_kf2.xml
new file mode 100644
index 0000000..be8184f
--- /dev/null
+++ b/tests/tests/animation/res/animator/value_animator_pvh_kf2.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<animator xmlns:android="http://schemas.android.com/apk/res/android">
+    <propertyValuesHolder>
+        <keyframe android:fraction="0" android:value="0"></keyframe>
+        <keyframe android:fraction="1" android:value="1"/>
+    </propertyValuesHolder>
+</animator>
\ No newline at end of file
diff --git a/tests/tests/animation/res/animator/value_animator_pvh_kf3.xml b/tests/tests/animation/res/animator/value_animator_pvh_kf3.xml
new file mode 100644
index 0000000..5d6dd4b
--- /dev/null
+++ b/tests/tests/animation/res/animator/value_animator_pvh_kf3.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<animator xmlns:android="http://schemas.android.com/apk/res/android">
+    <propertyValuesHolder>
+        <keyframe android:fraction="0" android:value="0"></keyframe>
+        <keyframe android:fraction=".4" android:value=".2"/>
+        <keyframe android:fraction=".6" android:value=".2"/>
+        <keyframe android:fraction="1" android:value="1"/>
+    </propertyValuesHolder>
+</animator>
\ No newline at end of file
diff --git a/tests/tests/animation/res/animator/value_animator_pvh_kf4.xml b/tests/tests/animation/res/animator/value_animator_pvh_kf4.xml
new file mode 100644
index 0000000..a59fb84
--- /dev/null
+++ b/tests/tests/animation/res/animator/value_animator_pvh_kf4.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<animator xmlns:android="http://schemas.android.com/apk/res/android">
+    <propertyValuesHolder>
+        <keyframe android:value="0"></keyframe>
+        <keyframe android:value=".2"/>
+        <keyframe android:value=".2"/>
+        <keyframe android:value="1"/>
+    </propertyValuesHolder>
+</animator>
\ No newline at end of file
diff --git a/tests/tests/animation/res/layout/button_view.xml b/tests/tests/animation/res/layout/button_view.xml
new file mode 100644
index 0000000..349fedf
--- /dev/null
+++ b/tests/tests/animation/res/layout/button_view.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="vertical"
+              android:layout_width="fill_parent"
+              android:layout_height="fill_parent"
+              android:id="@+id/container">
+    <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/button"
+            android:id="@+id/button"/>
+    <View
+            android:layout_width="200dp"
+            android:layout_height="200dp"
+            android:background="#fff"
+            android:id="@+id/square"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/tests/animation/res/values/strings.xml b/tests/tests/animation/res/values/strings.xml
index 8d167fd..587930b 100644
--- a/tests/tests/animation/res/values/strings.xml
+++ b/tests/tests/animation/res/values/strings.xml
@@ -15,4 +15,5 @@
 -->
 <resources>
     <string name="add_button">Add Button</string>
+    <string name="button">Button</string>
 </resources>
diff --git a/tests/tests/animation/src/android/animation/cts/ButtonViewActivity.java b/tests/tests/animation/src/android/animation/cts/ButtonViewActivity.java
new file mode 100644
index 0000000..fe66951
--- /dev/null
+++ b/tests/tests/animation/src/android/animation/cts/ButtonViewActivity.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 android.animation.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import android.animation.cts.R;
+
+public class ButtonViewActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.button_view);
+    }
+}
diff --git a/tests/tests/animation/src/android/animation/cts/CreationTest.java b/tests/tests/animation/src/android/animation/cts/CreationTest.java
new file mode 100644
index 0000000..f45f64b
--- /dev/null
+++ b/tests/tests/animation/src/android/animation/cts/CreationTest.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.animation.cts;
+
+import android.animation.AnimatorInflater;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.ValueAnimator;
+import android.os.Debug;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+
+import android.animation.cts.R;
+
+public class CreationTest extends ActivityInstrumentationTestCase2<ButtonViewActivity> {
+
+    private ButtonViewActivity mActivity;
+
+    public CreationTest() {
+        super(ButtonViewActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        setActivityInitialTouchMode(false);
+        mActivity = getActivity();
+    }
+
+    @UiThreadTest
+    public void testValueAnimatorCreation() {
+        ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
+        verifyValues(animator, 0, 1);
+    }
+
+    @UiThreadTest
+    public void testValueAnimatorResourceCreation() {
+        ValueAnimator animator = (ValueAnimator)
+                AnimatorInflater.loadAnimator(mActivity, R.animator.value_animator);
+        verifyValues(animator, 0, 1);
+    }
+
+    @UiThreadTest
+    public void testValueAnimatorPvh1() {
+        ValueAnimator animator = (ValueAnimator)
+                AnimatorInflater.loadAnimator(mActivity, R.animator.value_animator_pvh1);
+        verifyValues(animator, 0, 1);
+    }
+
+    @UiThreadTest
+    public void testValueAnimatorPvh2() {
+        ValueAnimator animator = (ValueAnimator)
+                AnimatorInflater.loadAnimator(mActivity, R.animator.value_animator_pvh2);
+        verifyValues(animator, 0, 1);
+    }
+
+    @UiThreadTest
+    public void testValueAnimatorPvhKf1() {
+        ValueAnimator animator = (ValueAnimator)
+                AnimatorInflater.loadAnimator(mActivity, R.animator.value_animator_pvh_kf1);
+        verifyValues(animator, 0, 1);
+    }
+
+    @UiThreadTest
+    public void testValueAnimatorPvhKf2() {
+        ValueAnimator animator = (ValueAnimator)
+                AnimatorInflater.loadAnimator(mActivity, R.animator.value_animator_pvh_kf2);
+        verifyValues(animator, 0, 1);
+    }
+
+    @UiThreadTest
+    public void testValueAnimatorPvhKf3() {
+        ValueAnimator animator = (ValueAnimator)
+                AnimatorInflater.loadAnimator(mActivity, R.animator.value_animator_pvh_kf3);
+        verifyValues(animator, 0, .2f, 1);
+    }
+
+    @UiThreadTest
+    public void testValueAnimatorPvhKf4() {
+        ValueAnimator animator = (ValueAnimator)
+                AnimatorInflater.loadAnimator(mActivity, R.animator.value_animator_pvh_kf4);
+        verifyValues(animator, 0, .2f, 1);
+    }
+
+    @UiThreadTest
+    public void testObjectAnimator() {
+        ObjectAnimator animator = (ObjectAnimator)
+                AnimatorInflater.loadAnimator(mActivity, R.animator.object_animator);
+        animator.setTarget(new DummyAnimatorTarget());
+        verifyValues(animator, "x", 0, 1);
+    }
+
+    @UiThreadTest
+    public void testObjectAnimatorPvh1() {
+        ObjectAnimator animator = (ObjectAnimator)
+                AnimatorInflater.loadAnimator(mActivity, R.animator.object_animator_pvh1);
+        animator.setTarget(new DummyAnimatorTarget());
+        verifyValues(animator, "x", 0, 1);
+        verifyValues(animator, "y", 10, 11);
+    }
+
+    @UiThreadTest
+    public void testObjectAnimatorPvhKf1() {
+        ObjectAnimator animator = (ObjectAnimator)
+                AnimatorInflater.loadAnimator(mActivity, R.animator.object_animator_pvh_kf1);
+        animator.setTarget(new DummyAnimatorTarget());
+        verifyValues(animator, "x", 0, 1);
+        verifyValues(animator, "y", 10, 11);
+    }
+
+    class DummyAnimatorTarget {
+        public float getX() {
+            return 0;
+        }
+
+        public void setX(float x) {
+        }
+
+        public float getY() {
+            return 0;
+        }
+
+        public void setY(float y) {
+        }
+    }
+
+    private void assertRoughlyEqual(float checkValue, float correctValue) {
+        // use epsilon for float compares
+        final float epsilon = .0001f;
+        assertTrue(checkValue > correctValue - epsilon && checkValue < correctValue + epsilon);
+    }
+
+    private void verifyValues(ValueAnimator animator, float... values) {
+        animator.setCurrentFraction(0);
+        assertRoughlyEqual((Float) animator.getAnimatedValue(), values[0]);
+        for (int i = 1; i < values.length - 1; ++i) {
+            animator.setCurrentFraction((float) i / (values.length - 1));
+            assertRoughlyEqual((Float) animator.getAnimatedValue(), values[i]);
+        }
+        animator.setCurrentFraction(1);
+        assertRoughlyEqual((Float) animator.getAnimatedValue(), values[values.length - 1]);
+    }
+
+    private void verifyValues(ObjectAnimator animator, String propertyName, float... values) {
+        animator.setCurrentFraction(0);
+        assertRoughlyEqual((Float) animator.getAnimatedValue(propertyName), values[0]);
+        for (int i = 1; i < values.length - 1; ++i) {
+            animator.setCurrentFraction((float) i / (values.length - 1));
+            assertRoughlyEqual((Float) animator.getAnimatedValue(propertyName), values[i]);
+        }
+        animator.setCurrentFraction(1);
+        assertRoughlyEqual((Float) animator.getAnimatedValue(propertyName),
+                values[values.length - 1]);
+    }
+}
diff --git a/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java b/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java
index 60532f0..7c85710 100644
--- a/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java
+++ b/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java
@@ -82,13 +82,121 @@
         assertEquals(startDelay, mValueAnimator.getStartDelay());
     }
 
-    public void testCurrentPlayTime() throws Throwable {
+    public void testGetCurrentPlayTime() throws Throwable {
         startAnimation(mValueAnimator);
         Thread.sleep(100);
         long currentPlayTime = mValueAnimator.getCurrentPlayTime();
         assertTrue(currentPlayTime  >  0);
     }
 
+    /**
+     * Test for equality within some epsilon. This accounts for minor differences
+     * due to floating-point accuracy.
+     */
+    private void assertRoughlyEqual(float expected, float actual) {
+        final float epsilon = .001f;
+        assertTrue(actual > (expected - epsilon) && actual < (expected + epsilon));
+    }
+
+    public void testSetCurrentPlayTime() throws Throwable {
+        final ValueAnimator anim = ValueAnimator.ofFloat(0, 100).setDuration(mDuration);
+        final ValueAnimator delayedAnim = ValueAnimator.ofFloat(0, 100).setDuration(mDuration);
+        delayedAnim.setStartDelay(mDuration);
+        final long proposedCurrentPlayTime = mDuration / 2;
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                anim.setCurrentPlayTime(mDuration / 2);
+                long currentPlayTime = anim.getCurrentPlayTime();
+                float currentFraction = anim.getAnimatedFraction();
+                float currentValue = (Float) anim.getAnimatedValue();
+                assertEquals(proposedCurrentPlayTime, currentPlayTime);
+                assertRoughlyEqual(.5f, currentFraction);
+                assertRoughlyEqual(50, currentValue);
+
+                delayedAnim.setCurrentPlayTime(mDuration / 2);
+                currentPlayTime = delayedAnim.getCurrentPlayTime();
+                currentFraction = delayedAnim.getAnimatedFraction();
+                currentValue = (Float) delayedAnim.getAnimatedValue();
+                assertEquals(proposedCurrentPlayTime, currentPlayTime);
+                assertRoughlyEqual(.5f, currentFraction);
+                assertRoughlyEqual(50, currentValue);
+            }
+        });
+        // Now make sure that it's still true a little later, to test that we're
+        // getting a result based on the seek time, not the wall clock time
+        Thread.sleep(100);
+        long currentPlayTime = anim.getCurrentPlayTime();
+        float currentFraction = anim.getAnimatedFraction();
+        float currentValue = (Float) anim.getAnimatedValue();
+        assertEquals(proposedCurrentPlayTime, currentPlayTime);
+        assertRoughlyEqual(.5f, currentFraction);
+        assertRoughlyEqual(50, currentValue);
+
+        currentPlayTime = delayedAnim.getCurrentPlayTime();
+        currentFraction = delayedAnim.getAnimatedFraction();
+        currentValue = (Float) delayedAnim.getAnimatedValue();
+        assertEquals(proposedCurrentPlayTime, currentPlayTime);
+        assertRoughlyEqual(.5f, currentFraction);
+        assertRoughlyEqual(50, currentValue);
+
+        // Finally, start() the delayed animation and check that the play time was
+        // not affected by playing during the delay
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                delayedAnim.start();
+                long currentPlayTime = delayedAnim.getCurrentPlayTime();
+                float currentFraction = delayedAnim.getAnimatedFraction();
+                float currentValue = (Float) delayedAnim.getAnimatedValue();
+                assertEquals(proposedCurrentPlayTime, currentPlayTime);
+                assertRoughlyEqual(.5f, currentFraction);
+                assertRoughlyEqual(50, currentValue);
+            }
+        });
+
+        Thread.sleep(100);
+        currentPlayTime = delayedAnim.getCurrentPlayTime();
+        currentFraction = delayedAnim.getAnimatedFraction();
+        currentValue = (Float) delayedAnim.getAnimatedValue();
+        assertEquals(proposedCurrentPlayTime, currentPlayTime);
+        assertRoughlyEqual(.5f, currentFraction);
+        assertRoughlyEqual(50, currentValue);
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                delayedAnim.cancel();
+            }
+        });
+    }
+
+    public void testSetCurrentFraction() throws Throwable {
+        final ValueAnimator anim = ValueAnimator.ofFloat(0, 100).setDuration(mDuration);
+        final long proposedCurrentPlayTime = mDuration / 2;
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                anim.setCurrentFraction(.5f);
+                long currentPlayTime = anim.getCurrentPlayTime();
+                float currentFraction = anim.getAnimatedFraction();
+                float currentValue = (Float) anim.getAnimatedValue();
+                assertEquals(proposedCurrentPlayTime, currentPlayTime);
+                assertRoughlyEqual(.5f, currentFraction);
+                assertRoughlyEqual(50, currentValue);
+            }
+        });
+        // Now make sure that it's still true a little later, to test that we're
+        // getting a result based on the seek time, not the wall clock time
+        Thread.sleep(100);
+        long currentPlayTime = anim.getCurrentPlayTime();
+        float currentFraction = anim.getAnimatedFraction();
+        float currentValue = (Float) anim.getAnimatedValue();
+        assertEquals(proposedCurrentPlayTime, currentPlayTime);
+        assertRoughlyEqual(.5f, currentFraction);
+        assertRoughlyEqual(50, currentValue);
+    }
+
     public void testGetFrameDelay() throws Throwable {
         final long frameDelay = 10;
         runTestOnUiThread(new Runnable() {
diff --git a/tests/tests/app.usage/Android.mk b/tests/tests/app.usage/Android.mk
index f245e5f..52118bc 100644
--- a/tests/tests/app.usage/Android.mk
+++ b/tests/tests/app.usage/Android.mk
@@ -30,4 +30,7 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/app.usage/AndroidTest.xml b/tests/tests/app.usage/AndroidTest.xml
new file mode 100644
index 0000000..75ff17e
--- /dev/null
+++ b/tests/tests/app.usage/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Configuration for app.usage Tests">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsUsageStatsTestCases.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.InstrumentationTest" >
+        <option name="package" value="android.app.usage.cts" />
+        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/content/Android.mk b/tests/tests/content/Android.mk
index 4937814..0b3b19f 100644
--- a/tests/tests/content/Android.mk
+++ b/tests/tests/content/Android.mk
@@ -38,5 +38,3 @@
 LOCAL_COMPATIBILITY_SUITE := cts_v2
 
 include $(BUILD_CTS_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/content/AndroidTest.xml b/tests/tests/content/AndroidTest.xml
index 33f9013..4cca518 100644
--- a/tests/tests/content/AndroidTest.xml
+++ b/tests/tests/content/AndroidTest.xml
@@ -14,10 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Content test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkPreconditionCheck">
-        <option name="apk" value="CtsContentPreconditions.apk"/>
-        <option name="package" value="android.content.preconditions"/>
-    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.WifiCheck" />
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsContentTestCases.apk" />
diff --git a/tests/tests/content/preconditions/Android.mk b/tests/tests/content/preconditions/Android.mk
deleted file mode 100644
index 8ffb7ea..0000000
--- a/tests/tests/content/preconditions/Android.mk
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-# and when built explicitly put it in the data partition
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test compatibility-device-preconditions
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsContentPreconditions
-
-# Tag this module as a cts_v2 test artifact
-LOCAL_COMPATIBILITY_SUITE := cts_v2
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
diff --git a/tests/tests/content/preconditions/AndroidManifest.xml b/tests/tests/content/preconditions/AndroidManifest.xml
deleted file mode 100644
index 1304b81..0000000
--- a/tests/tests/content/preconditions/AndroidManifest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.content.preconditions">
-    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <!--  self-instrumenting test package. -->
-    <instrumentation
-        android:name="android.support.test.runner.AndroidJUnitRunner"
-        android:label="CTS preconditions test for 'content' module"
-        android:targetPackage="android.content.preconditions" >
-    </instrumentation>
-</manifest>
diff --git a/tests/tests/content/preconditions/src/android/content/preconditions/PreconditionsTest.java b/tests/tests/content/preconditions/src/android/content/preconditions/PreconditionsTest.java
deleted file mode 100644
index d4b3b1d..0000000
--- a/tests/tests/content/preconditions/src/android/content/preconditions/PreconditionsTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.content.preconditions;
-
-import android.test.AndroidTestCase;
-
-import com.android.compatibility.common.preconditions.WifiHelper;
-
-/**
- * A test to verify that device-side preconditions are met for the content module of CTS
- */
-public class PreconditionsTest extends AndroidTestCase {
-
-    /**
-     * Test if device is connected to WiFi
-     * @throws Exception
-     */
-    public void testWifiConnected() throws Exception {
-        assertTrue("Device must have active network connection",
-                WifiHelper.isWifiConnected(this.getContext()));
-    }
-
-}
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 e0a1d4e..dd4e3e3 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
@@ -1712,9 +1712,10 @@
         // video stabilization test.
         List<Key<?>> keys = mStaticInfo.getCharacteristics().getKeys();
 
-        int[] videoStabModes = (keys.contains(CameraCharacteristics.
+        Integer[] videoStabModes = (keys.contains(CameraCharacteristics.
                 CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES)) ?
-                mStaticInfo.getAvailableVideoStabilizationModesChecked() : new int[0];
+                CameraTestUtils.toObject(mStaticInfo.getAvailableVideoStabilizationModesChecked()) :
+                    new Integer[0];
         int[] opticalStabModes = (keys.contains(
                 CameraCharacteristics.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION)) ?
                 mStaticInfo.getAvailableOpticalStabilizationChecked() : new int[0];
@@ -1725,13 +1726,14 @@
         SimpleCaptureCallback listener = new SimpleCaptureCallback();
         startPreview(requestBuilder, maxPreviewSize, listener);
 
-        for (int mode : videoStabModes) {
+        for (Integer mode : videoStabModes) {
             listener = new SimpleCaptureCallback();
             requestBuilder.set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE, mode);
             mSession.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
             waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
-            verifyCaptureResultForKey(CaptureResult.CONTROL_VIDEO_STABILIZATION_MODE, mode,
-                    listener, NUM_FRAMES_VERIFIED);
+            // Video stabilization could return any modes.
+            verifyAnyCaptureResultForKey(CaptureResult.CONTROL_VIDEO_STABILIZATION_MODE,
+                    videoStabModes, listener, NUM_FRAMES_VERIFIED);
         }
 
         for (int mode : opticalStabModes) {
@@ -2162,6 +2164,30 @@
     }
 
     /**
+     * Basic verification that the value of a capture result key should be one of the expected
+     * values.
+     *
+     * @param key The capture result key to be verified against
+     * @param expectedModes The list of any possible expected modes for this result
+     * @param listener The capture listener to get capture results
+     * @param numFramesVerified The number of capture results to be verified
+     */
+    private <T> void verifyAnyCaptureResultForKey(CaptureResult.Key<T> key, T[] expectedModes,
+            SimpleCaptureCallback listener, int numFramesVerified) {
+        for (int i = 0; i < numFramesVerified; i++) {
+            CaptureResult result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+            validatePipelineDepth(result);
+            T resultMode = getValueNotNull(result, key);
+            if (VERBOSE) {
+                Log.v(TAG, "Expect values: " + Arrays.toString(expectedModes) + " result value: "
+                        + resultMode.toString());
+            }
+            // Capture result should be one of the expected values.
+            mCollector.expectContains(expectedModes, resultMode);
+        }
+    }
+
+    /**
      * Verify if the fps is slow down for given input request with certain
      * controls inside.
      * <p>
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 155f9dd..f1115c4 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/ImageReaderTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/ImageReaderTest.java
@@ -794,7 +794,7 @@
                                     getValueNotNull(result, CaptureResult.SENSOR_EXPOSURE_TIME),
                                     TEST_EXPOSURE_TIME_NS),
                             exposureTimeDiff < EXPOSURE_TIME_ERROR_MARGIN_NS &&
-                            exposureTimeDiff > 0);
+                            exposureTimeDiff >= 0);
 
                     mCollector.expectTrue(
                             String.format("Long processing frame %d format %d size %s " +
diff --git a/tests/tests/media/AndroidTest.xml b/tests/tests/media/AndroidTest.xml
index ac23ef2..0465bf1 100644
--- a/tests/tests/media/AndroidTest.xml
+++ b/tests/tests/media/AndroidTest.xml
@@ -26,4 +26,4 @@
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.media.cts" />
     </test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/tests/tests/media/res/raw/video_1920x1080_mp4_h264_20480kbps_60fps_aac_stereo_128kbps_44100hz.mp4 b/tests/tests/media/res/raw/video_1920x1080_mp4_h264_20480kbps_60fps_aac_stereo_128kbps_44100hz.mp4
old mode 100644
new mode 100755
index b837dc2..f88fe7a
--- a/tests/tests/media/res/raw/video_1920x1080_mp4_h264_20480kbps_60fps_aac_stereo_128kbps_44100hz.mp4
+++ b/tests/tests/media/res/raw/video_1920x1080_mp4_h264_20480kbps_60fps_aac_stereo_128kbps_44100hz.mp4
Binary files differ
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
index 4c2d442..bcc1e8d 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
@@ -295,6 +295,43 @@
         }
     }
 
+    public void testPlayAudioLooping() throws Exception {
+        final int resid = R.raw.testmp3;
+
+        MediaPlayer mp = MediaPlayer.create(mContext, resid);
+        try {
+            mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
+            mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
+            mp.setLooping(true);
+            mOnCompletionCalled.reset();
+            mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+                @Override
+                public void onCompletion(MediaPlayer mp) {
+                    Log.i("@@@", "got oncompletion");
+                    mOnCompletionCalled.signal();
+                }
+            });
+
+            assertFalse(mp.isPlaying());
+            mp.start();
+            assertTrue(mp.isPlaying());
+
+            int duration = mp.getDuration();
+            Thread.sleep(duration * 4); // allow for several loops
+            assertTrue(mp.isPlaying());
+            assertEquals("wrong number of completion signals", 0, mOnCompletionCalled.getNumSignal());
+            mp.setLooping(false);
+
+            // wait for playback to finish
+            while(mp.isPlaying()) {
+                Thread.sleep(SLEEP_TIME);
+            }
+            assertEquals("wrong number of completion signals", 1, mOnCompletionCalled.getNumSignal());
+        } finally {
+            mp.release();
+        }
+    }
+
     public void testPlayMidi() throws Exception {
         final int resid = R.raw.midi8sec;
         final int midiDuration = 8000;
diff --git a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
index a6c80ad..a1f380c 100644
--- a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
@@ -295,6 +295,11 @@
     }
 
     public void testPlayHlsStreamWithTimedId3() throws Throwable {
+        if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
+            Log.d(TAG, "Device doesn't have video codec, skipping test");
+            return;
+        }
+
         mServer = new CtsTestServer(mContext);
         try {
             // counter must be final if we want to access it inside onTimedMetaData;
diff --git a/tests/tests/mediastress/Android.mk b/tests/tests/mediastress/Android.mk
index afa9dd5..38d8bf6 100644
--- a/tests/tests/mediastress/Android.mk
+++ b/tests/tests/mediastress/Android.mk
@@ -28,6 +28,8 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner ctsdeviceutil
 
+LOCAL_HOST_SHARED_LIBRARIES := compatibility-device-media-preconditions
+
 LOCAL_JNI_SHARED_LIBRARIES := libctsmediastress_jni
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/mediastress/AndroidTest.xml b/tests/tests/mediastress/AndroidTest.xml
index fd434f1..43eae94 100644
--- a/tests/tests/mediastress/AndroidTest.xml
+++ b/tests/tests/mediastress/AndroidTest.xml
@@ -14,6 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Media Stress test cases">
+    <target_preparer class="android.mediastress.cts.preconditions.MediaPreparer" />
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsMediaStressTestCases.apk" />
@@ -21,4 +22,4 @@
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.mediastress.cts" />
     </test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/tests/tests/text/preconditions/Android.mk b/tests/tests/mediastress/preconditions/Android.mk
similarity index 63%
copy from tests/tests/text/preconditions/Android.mk
copy to tests/tests/mediastress/preconditions/Android.mk
index c91de75..5838386 100644
--- a/tests/tests/text/preconditions/Android.mk
+++ b/tests/tests/mediastress/preconditions/Android.mk
@@ -4,7 +4,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+# http://www.apache.org/licenses/LICENSE-2.0
 #
 # Unless required by applicable law or agreed to in writing, software
 # distributed under the License is distributed on an "AS IS" BASIS,
@@ -12,28 +12,23 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-LOCAL_PATH:= $(call my-dir)
+LOCAL_PATH := $(call my-dir)
 
 include $(CLEAR_VARS)
 
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-# and when built explicitly put it in the data partition
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test compatibility-device-preconditions
-
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_PACKAGE_NAME := CtsTextPreconditions
+LOCAL_JAVA_LIBRARIES := compatibility-host-util cts-tradefed_v2 tradefed-prebuilt
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE := compatibility-host-media-preconditions
 
 # Tag this module as a cts_v2 test artifact
 LOCAL_COMPATIBILITY_SUITE := cts_v2
 
 LOCAL_SDK_VERSION := current
 
-include $(BUILD_PACKAGE)
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/mediastress/preconditions/src/android/mediastress/cts/preconditions/MediaPreparer.java b/tests/tests/mediastress/preconditions/src/android/mediastress/cts/preconditions/MediaPreparer.java
new file mode 100644
index 0000000..08097f9
--- /dev/null
+++ b/tests/tests/mediastress/preconditions/src/android/mediastress/cts/preconditions/MediaPreparer.java
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.mediastress.cts.preconditions;
+
+import com.android.compatibility.common.tradefed.targetprep.PreconditionPreparer;
+import com.android.ddmlib.IDevice;
+import com.android.ddmlib.Log;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.config.OptionClass;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.targetprep.BuildError;
+import com.android.tradefed.targetprep.TargetSetupError;
+import com.android.tradefed.util.FileUtil;
+import com.android.tradefed.util.ZipUtil;
+
+import java.awt.Dimension;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.zip.ZipFile;
+
+/**
+ * Ensures that the appropriate media files exist on the device
+ */
+@OptionClass(alias="media-preparer")
+public class MediaPreparer extends PreconditionPreparer {
+
+    @Option(name = "local-media-path",
+            description = "Absolute path of the media files directory, containing" +
+            "'bbb_short' and 'bbb_full' directories")
+    protected String mLocalMediaPath = null;
+
+    @Option(name = "skip-media-download",
+            description = "Whether to skip the media files precondition")
+    protected boolean mSkipMediaDownload = false;
+
+    /*
+     * The default name of local directory into which media files will be downloaded, if option
+     * "local-media-path" is not provided. This directory will live inside the temp directory.
+     */
+    protected static final String MEDIA_FOLDER_NAME = "android-cts-media";
+
+    /*
+     * The URL from which to download the compressed media files
+     * TODO: Find a way to retrieve this programmatically
+     */
+    private static final String MEDIA_URL_STRING =
+            "https://dl.google.com/dl/android/cts/android-cts-media-1.1.zip";
+
+    /*
+     * The message printed when the maximum video playback resolution cannot be found in the
+     * output of 'dumpsys'. When this is the case, media files of all resolutions must be pushed
+     * to the device.
+     */
+    private static final String MAX_PLAYBACK_RES_FAILURE_MSG =
+            "Unable to parse maximum video playback resolution, pushing all media files";
+
+    private static final String LOG_TAG = MediaPreparer.class.getSimpleName();
+
+    /* Constants identifying resolutions of the media files to be copied */
+    protected static final int RES_176_144 = 0; // 176x144 resolution
+    protected static final int RES_DEFAULT = 1; // default max video playback resolution, 480x360
+    protected static final int RES_720_480 = 2; // 720x480 resolution
+    protected static final int RES_1280_720 = 3; // 1280x720 resolution
+    protected static final int RES_1920_1080 = 4; // 1920x1080 resolution
+
+    protected static final Dimension[] resolutions = { // indices meant to align with constants above
+            new Dimension(176, 144),
+            new Dimension(480, 360),
+            new Dimension(720, 480),
+            new Dimension(1280, 720),
+            new Dimension(1920, 1080)
+    };
+
+    /*
+     * The pathnames of the device's directories that hold media files for the tests.
+     * These depend on the device's mount point, which is retrieved in the MediaPreparer's run
+     * method.
+     *
+     * These fields are exposed for unit testing
+     */
+    protected String baseDeviceShortDir;
+    protected String baseDeviceFullDir;
+
+    /*
+     * Returns a string representation of the dimension
+     * For dimension of width = 480 and height = 360, the resolution string is "480x360"
+     */
+    private static String resolutionString(Dimension resolution) {
+        return String.format("%dx%d", resolution.width, resolution.height);
+    }
+
+    /*
+     * Loops through the predefined maximum video playback resolutions from largest to smallest,
+     * And returns the greatest resolution that is strictly smaller than the width and height
+     * provided in the arguments
+     */
+    private Dimension getMaxVideoPlaybackResolution(int width, int height) {
+        for (int resIndex = resolutions.length - 1; resIndex >= RES_DEFAULT; resIndex--) {
+            Dimension resolution = resolutions[resIndex];
+            if (width >= resolution.width && height >= resolution.height) {
+                return resolution;
+            }
+        }
+        return resolutions[RES_DEFAULT];
+    }
+
+    /*
+     * Returns the maximum video playback resolution of the device, in the form of a Dimension
+     * object. This method parses dumpsys output to find resolutions listed under the
+     * 'mBaseDisplayInfo' field. The value for 'smallest app' is used as an estimate for
+     * maximum video playback resolution, and is rounded down to the nearest dimension in the
+     * resolutions array.
+     *
+     * This method is exposed for unit testing.
+     */
+    protected Dimension getMaxVideoPlaybackResolution(ITestDevice device)
+            throws DeviceNotAvailableException {
+        String dumpsysOutput =
+                device.executeShellCommand("dumpsys display | grep mBaseDisplayInfo");
+        Pattern pattern = Pattern.compile("smallest app (\\d+) x (\\d+)");
+        Matcher matcher = pattern.matcher(dumpsysOutput);
+        if(!matcher.find()) {
+            // could not find resolution in dumpsysOutput, return largest max playback resolution
+            // so that preparer copies all media files
+            CLog.e(MAX_PLAYBACK_RES_FAILURE_MSG);
+            return resolutions[RES_1920_1080];
+        }
+
+        int first;
+        int second;
+        try {
+            first = Integer.parseInt(matcher.group(1));
+            second = Integer.parseInt(matcher.group(2));
+        } catch (NumberFormatException e) {
+            CLog.e(MAX_PLAYBACK_RES_FAILURE_MSG);
+            return resolutions[RES_1920_1080];
+        }
+        // dimensions in dumpsys output seem consistently reversed
+        // here we make note of which dimension is the larger of the two
+        int height = Math.min(first, second);
+        int width = Math.max(first, second);
+        return getMaxVideoPlaybackResolution(width, height);
+    }
+
+    /*
+     * Returns true if all necessary media files exist on the device, and false otherwise.
+     *
+     * This method is exposed for unit testing.
+     */
+    protected boolean mediaFilesExistOnDevice(ITestDevice device, Dimension mvpr)
+            throws DeviceNotAvailableException{
+        int resIndex = RES_176_144;
+        while (resIndex <= RES_1920_1080) {
+            Dimension copiedResolution = resolutions[resIndex];
+            if (copiedResolution.width > mvpr.width || copiedResolution.height > mvpr.height) {
+                break; // we don't need to check for resolutions greater than or equal to this
+            }
+            String resString = resolutionString(copiedResolution);
+            String deviceShortFilePath = baseDeviceShortDir + resString;
+            String deviceFullFilePath = baseDeviceFullDir + resString;
+            if (!device.doesFileExist(deviceShortFilePath) ||
+                    !device.doesFileExist(deviceFullFilePath)) { // media files must be copied
+                return false;
+            }
+            resIndex++;
+        }
+        return true;
+    }
+
+    /* A simple helper to print messages to the tradefed console */
+    private static void printInfo(String info) {
+        LogUtil.printLog(Log.LogLevel.INFO, LOG_TAG, info);
+    }
+
+    /*
+     * After downloading and unzipping the media files, mLocalMediaPath must be the path to the
+     * directory containing 'bbb_short' and 'bbb_full' directories, as it is defined in its
+     * description as an option.
+     * After extraction, this directory exists one level below the the directory 'mediaFolder'.
+     * If the 'mediaFolder' contains anything other than exactly one subdirectory, a
+     * TargetSetupError is thrown. Otherwise, the mLocalMediaPath variable is set to the path of
+     * this subdirectory.
+     */
+    private void updateLocalMediaPath(File mediaFolder) throws TargetSetupError {
+        String[] subDirs = mediaFolder.list();
+        if (subDirs.length != 1) {
+            throw new TargetSetupError(String.format(
+                    "Unexpected contents in directory %s", mLocalMediaPath));
+        }
+        File newMediaFolder = new File(mediaFolder, subDirs[0]);
+        mLocalMediaPath = newMediaFolder.toString();
+    }
+
+    /*
+     * Copies the media files to the host from a predefined URL
+     * Updates mLocalMediaPath to be the pathname of the directory containing bbb_short and
+     * bbb_full media directories.
+     */
+    private void downloadMediaToHost() throws TargetSetupError {
+
+        URL url;
+        try {
+            url = new URL(MEDIA_URL_STRING);
+        } catch (MalformedURLException e) {
+            throw new TargetSetupError(
+                    String.format("Trouble finding android media files at %s", MEDIA_URL_STRING));
+        }
+
+        File mediaFolder = new File(mLocalMediaPath);
+        File mediaFolderZip = new File(mediaFolder.getName() + ".zip");
+        try {
+
+            mediaFolder.mkdirs();
+            mediaFolderZip.createNewFile();
+
+            URLConnection conn = url.openConnection();
+            InputStream in = conn.getInputStream();
+            BufferedOutputStream out =
+                    new BufferedOutputStream(new FileOutputStream(mediaFolderZip));
+            byte[] buffer = new byte[1024];
+            int count;
+            printInfo("Downloading media files to host");
+            while ((count = in.read(buffer)) >= 0) {
+                out.write(buffer, 0, count);
+            }
+            out.flush();
+            out.close();
+            in.close();
+
+            printInfo("Unzipping media files");
+            ZipUtil.extractZip(new ZipFile(mediaFolderZip), mediaFolder);
+
+        } catch (IOException e) {
+            FileUtil.recursiveDelete(mediaFolder);
+            FileUtil.recursiveDelete(mediaFolderZip);
+            throw new TargetSetupError("Failed to open media files on host");
+        }
+    }
+
+    /*
+     * Pushes directories containing media files to the device for all directories that:
+     * - are not already present on the device
+     * - contain video files of a resolution less than or equal to the device's
+     *       max video playback resolution
+     *
+     * This method is exposed for unit testing.
+     */
+    protected void copyMediaFiles(ITestDevice device, Dimension mvpr)
+            throws DeviceNotAvailableException {
+
+        int resIndex = RES_176_144;
+        while (resIndex <= RES_1920_1080) {
+            Dimension copiedResolution = resolutions[resIndex];
+            String resString = resolutionString(copiedResolution);
+            if (copiedResolution.width > mvpr.width || copiedResolution.height > mvpr.height) {
+                printInfo(String.format(
+                        "Device cannot support resolutions %s and larger, media copying complete",
+                        resString));
+                return;
+            }
+            String deviceShortFilePath = baseDeviceShortDir + resString;
+            String deviceFullFilePath = baseDeviceFullDir + resString;
+            if (!device.doesFileExist(deviceShortFilePath) ||
+                    !device.doesFileExist(deviceFullFilePath)) {
+                printInfo(String.format("Copying files of resolution %s to device", resString));
+                String localShortDirName = "bbb_short/" + resString;
+                String localFullDirName = "bbb_full/" + resString;
+                File localShortDir = new File(mLocalMediaPath, localShortDirName);
+                File localFullDir = new File(mLocalMediaPath, localFullDirName);
+                // push short directory of given resolution, if not present on device
+                if(!device.doesFileExist(deviceShortFilePath)) {
+                    device.pushDir(localShortDir, deviceShortFilePath);
+                }
+                // push full directory of given resolution, if not present on device
+                if(!device.doesFileExist(deviceFullFilePath)) {
+                    device.pushDir(localFullDir, deviceFullFilePath);
+                }
+            }
+            resIndex++;
+        }
+    }
+
+    // Initialize directory strings where media files live on device
+    protected void setMountPoint(ITestDevice device) {
+        String mountPoint = device.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
+        baseDeviceShortDir = String.format("%s/test/bbb_short/", mountPoint);
+        baseDeviceFullDir = String.format("%s/test/bbb_full/", mountPoint);
+    }
+
+    @Override
+    public void run(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
+            BuildError, DeviceNotAvailableException {
+
+        if (mSkipMediaDownload) {
+            // skip this precondition
+            return;
+        }
+
+        setMountPoint(device);
+        Dimension mvpr = getMaxVideoPlaybackResolution(device);
+        if (mediaFilesExistOnDevice(device, mvpr)) {
+            // if files already on device, do nothing
+            printInfo("Media files found on the device");
+            return;
+        }
+
+        File mediaFolder;
+        if (mLocalMediaPath == null) {
+            // Option 'local-media-path' has not been defined
+            try {
+                // find system's temp directory, create folder MEDIA_FOLDER_NAME inside
+                File tmpFile = File.createTempFile(MEDIA_FOLDER_NAME, null);
+                String tmpDir = tmpFile.getParent();
+                mediaFolder = new File(tmpDir, MEDIA_FOLDER_NAME);
+                // delete temp file used for locating temp directory
+                tmpFile.delete();
+            } catch (IOException e) {
+                throw new TargetSetupError("Unable to create host temp directory for media files");
+            }
+            mLocalMediaPath = mediaFolder.getAbsolutePath();
+            if(!mediaFolder.exists()){
+                // directory has not been created by previous runs of MediaPreparer
+                // download media into mLocalMediaPath
+                downloadMediaToHost();
+            }
+            updateLocalMediaPath(mediaFolder);
+        }
+
+        printInfo(String.format("Media files located on host at: %s", mLocalMediaPath));
+        copyMediaFiles(device, mvpr);
+    }
+
+}
diff --git a/tests/tests/text/preconditions/Android.mk b/tests/tests/mediastress/preconditions/tests/Android.mk
similarity index 63%
rename from tests/tests/text/preconditions/Android.mk
rename to tests/tests/mediastress/preconditions/tests/Android.mk
index c91de75..67eaf5d 100644
--- a/tests/tests/text/preconditions/Android.mk
+++ b/tests/tests/mediastress/preconditions/tests/Android.mk
@@ -4,7 +4,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+# http://www.apache.org/licenses/LICENSE-2.0
 #
 # Unless required by applicable law or agreed to in writing, software
 # distributed under the License is distributed on an "AS IS" BASIS,
@@ -12,28 +12,23 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-LOCAL_PATH:= $(call my-dir)
+LOCAL_PATH := $(call my-dir)
 
 include $(CLEAR_VARS)
 
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-# and when built explicitly put it in the data partition
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test compatibility-device-preconditions
-
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_PACKAGE_NAME := CtsTextPreconditions
+LOCAL_STATIC_JAVA_LIBRARIES := easymock
+
+LOCAL_JAVA_LIBRARIES := compatibility-host-util cts-tradefed_v2 tradefed-prebuilt compatibility-host-media-preconditions
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE := compatibility-host-media-preconditions-tests
 
 # Tag this module as a cts_v2 test artifact
 LOCAL_COMPATIBILITY_SUITE := cts_v2
 
 LOCAL_SDK_VERSION := current
 
-include $(BUILD_PACKAGE)
+include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/tests/tests/mediastress/preconditions/tests/src/android/mediastress/cts/preconditions/MediaPreparerTest.java b/tests/tests/mediastress/preconditions/tests/src/android/mediastress/cts/preconditions/MediaPreparerTest.java
new file mode 100644
index 0000000..54ab025
--- /dev/null
+++ b/tests/tests/mediastress/preconditions/tests/src/android/mediastress/cts/preconditions/MediaPreparerTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.mediastress.cts.preconditions;
+
+import com.android.ddmlib.IDevice;
+import com.android.tradefed.build.BuildInfo;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.OptionSetter;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.targetprep.TargetSetupError;
+
+import java.awt.Dimension;
+
+import junit.framework.TestCase;
+
+import org.easymock.EasyMock;
+
+public class MediaPreparerTest extends TestCase {
+
+    private MediaPreparer mMediaPreparer;
+    private IBuildInfo mMockBuildInfo;
+    private ITestDevice mMockDevice;
+    private OptionSetter mOptionSetter;
+
+    private final Dimension DEFAULT_DIMENSION =
+            MediaPreparer.resolutions[MediaPreparer.RES_DEFAULT];
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mMediaPreparer = new MediaPreparer();
+        mMockDevice = EasyMock.createMock(ITestDevice.class);
+        mMockBuildInfo = new BuildInfo("0", "", "");
+        mOptionSetter = new OptionSetter(mMediaPreparer);
+    }
+
+    public void testSetMountPoint() throws Exception {
+        EasyMock.expect(mMockDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE)).andReturn(
+                "/sdcard").once();
+        EasyMock.replay(mMockDevice);
+        mMediaPreparer.setMountPoint(mMockDevice);
+        assertEquals(mMediaPreparer.baseDeviceShortDir, "/sdcard/test/bbb_short/");
+        assertEquals(mMediaPreparer.baseDeviceFullDir, "/sdcard/test/bbb_full/");
+    }
+
+    public void testCopyMediaFiles() throws Exception {
+        // by jumping directly into copyMediaFiles, the baseDeviceShortDir variable won't be set
+        // thus, the string "null" replaces the variable
+        EasyMock.expect(mMockDevice.doesFileExist("null176x144")).andReturn(true).anyTimes();
+        EasyMock.expect(mMockDevice.doesFileExist("null480x360")).andReturn(true).anyTimes();
+        EasyMock.replay(mMockDevice);
+        mMediaPreparer.copyMediaFiles(mMockDevice, DEFAULT_DIMENSION);
+    }
+
+    public void testMediaFilesExistOnDeviceTrue() throws Exception {
+        // by jumping directly into copyMediaFiles, the baseDeviceShortDir variable won't be set
+        // thus, the string "null" replaces the variable
+        EasyMock.expect(mMockDevice.doesFileExist("null176x144")).andReturn(true).anyTimes();
+        EasyMock.expect(mMockDevice.doesFileExist("null480x360")).andReturn(true).anyTimes();
+        EasyMock.replay(mMockDevice);
+        assertTrue(mMediaPreparer.mediaFilesExistOnDevice(mMockDevice, DEFAULT_DIMENSION));
+    }
+
+    public void testMediaFilesExistOnDeviceFalse() throws Exception {
+        // by jumping directly into copyMediaFiles, the baseDeviceShortDir variable won't be set
+        // thus, the string "null" replaces the variable
+        EasyMock.expect(mMockDevice.doesFileExist("null176x144")).andReturn(false).anyTimes();
+        EasyMock.expect(mMockDevice.doesFileExist("null480x360")).andReturn(true).anyTimes();
+        EasyMock.replay(mMockDevice);
+        assertFalse(mMediaPreparer.mediaFilesExistOnDevice(mMockDevice, DEFAULT_DIMENSION));
+    }
+
+    public void testGetMaxVideoPlaybackResolutionFound() throws Exception {
+        String mockDumpsysOutput = "mBaseDisplayInfo=DisplayInfo{\"Built-in Screen\", uniqueId " +
+                "\"local:0\", app 1440 x 2560, real 1440 x 2560, largest app 1440 x 2560, " +
+                "smallest app 360 x 480, mode 1, defaultMode 1, modes [{id=1, width=1440, " +
+                "height=2560, fps=60.0}], rotation 0, density 560 (494.27 x 492.606) dpi, " +
+                "layerStack 0, appVsyncOff 2500000, presDeadline 17666667, type BUILT_IN, state " +
+                "ON, FLAG_SECURE, FLAG_SUPPORTS_PROTECTED_BUFFERS}\n";
+        EasyMock.expect(mMockDevice.executeShellCommand(
+                "dumpsys display | grep mBaseDisplayInfo")).andReturn(mockDumpsysOutput).once();
+        EasyMock.replay(mMockDevice);
+        Dimension result = mMediaPreparer.getMaxVideoPlaybackResolution(mMockDevice);
+        assertEquals(result, DEFAULT_DIMENSION);
+    }
+
+    public void testGetMaxVideoPlaybackResolutionNotFound() throws Exception {
+        String mockDumpsysOutput = "incorrect output";
+        EasyMock.expect(mMockDevice.executeShellCommand(
+                "dumpsys display | grep mBaseDisplayInfo")).andReturn(mockDumpsysOutput).once();
+        EasyMock.replay(mMockDevice);
+        Dimension result = mMediaPreparer.getMaxVideoPlaybackResolution(mMockDevice);
+        assertEquals(result, MediaPreparer.resolutions[MediaPreparer.RES_1920_1080]);
+    }
+
+    public void testSkipMediaDownload() throws Exception {
+        mOptionSetter.setOptionValue("skip-media-download", "true");
+        EasyMock.replay();
+        mMediaPreparer.run(mMockDevice, mMockBuildInfo);
+    }
+
+}
diff --git a/tests/tests/net/AndroidTest.xml b/tests/tests/net/AndroidTest.xml
index 5d38c64..1509256 100644
--- a/tests/tests/net/AndroidTest.xml
+++ b/tests/tests/net/AndroidTest.xml
@@ -13,10 +13,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Net test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkPreconditionCheck">
-        <option name="apk" value="CtsNetPreconditions.apk"/>
-        <option name="package" value="android.net.preconditions"/>
-    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.WifiCheck" />
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsNetTestCases.apk" />
diff --git a/tests/tests/net/preconditions/Android.mk b/tests/tests/net/preconditions/Android.mk
deleted file mode 100644
index d689e96..0000000
--- a/tests/tests/net/preconditions/Android.mk
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-# and when built explicitly put it in the data partition
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test compatibility-device-preconditions
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsNetPreconditions
-
-# Tag this module as a cts_v2 test artifact
-LOCAL_COMPATIBILITY_SUITE := cts_v2
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
diff --git a/tests/tests/net/preconditions/AndroidManifest.xml b/tests/tests/net/preconditions/AndroidManifest.xml
deleted file mode 100644
index 59db7a7..0000000
--- a/tests/tests/net/preconditions/AndroidManifest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.net.preconditions">
-    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <!--  self-instrumenting test package. -->
-    <instrumentation
-        android:name="android.support.test.runner.AndroidJUnitRunner"
-        android:label="CTS preconditions test for 'net' module"
-        android:targetPackage="android.net.preconditions" >
-    </instrumentation>
-</manifest>
diff --git a/tests/tests/net/preconditions/src/android/net/preconditions/PreconditionsTest.java b/tests/tests/net/preconditions/src/android/net/preconditions/PreconditionsTest.java
deleted file mode 100644
index 4e132cb..0000000
--- a/tests/tests/net/preconditions/src/android/net/preconditions/PreconditionsTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.net.preconditions;
-
-import android.test.AndroidTestCase;
-
-import com.android.compatibility.common.preconditions.WifiHelper;
-
-/**
- * A test to verify that device-side preconditions are met for the net module of CTS
- */
-public class PreconditionsTest extends AndroidTestCase {
-
-    /**
-     * Test if device is connected to WiFi
-     * @throws Exception
-     */
-    public void testWifiConnected() throws Exception {
-        assertTrue("Device must have active network connection",
-                WifiHelper.isWifiConnected(this.getContext()));
-    }
-
-}
diff --git a/tests/tests/os/src/android/os/cts/MessengerTest.java b/tests/tests/os/src/android/os/cts/MessengerTest.java
index 72bf247..5bf9428 100644
--- a/tests/tests/os/src/android/os/cts/MessengerTest.java
+++ b/tests/tests/os/src/android/os/cts/MessengerTest.java
@@ -30,6 +30,7 @@
 import android.os.Messenger;
 import android.os.Parcel;
 import android.os.RemoteException;
+import android.os.ResultReceiver;
 import android.test.AndroidTestCase;
 
 import java.io.FileDescriptor;
@@ -88,6 +89,11 @@
         public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException {
         }
 
+        @Override
+        public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+                String[] args, ResultReceiver resultReceiver) {
+        }
+
     };
 
     // Create another messenger to send msg.
diff --git a/tests/tests/print/src/android/print/cts/BasePrintTest.java b/tests/tests/print/src/android/print/cts/BasePrintTest.java
index 1378bdb..c4dd026 100644
--- a/tests/tests/print/src/android/print/cts/BasePrintTest.java
+++ b/tests/tests/print/src/android/print/cts/BasePrintTest.java
@@ -549,6 +549,7 @@
     }
 
     protected boolean supportsPrinting() {
-        return getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_PRINTING);
+        return getInstrumentation().getContext().getPackageManager()
+                .hasSystemFeature(PackageManager.FEATURE_PRINTING);
     }
 }
diff --git a/tests/tests/renderscript/Android.mk b/tests/tests/renderscript/Android.mk
index f693f2c..9f196ca 100644
--- a/tests/tests/renderscript/Android.mk
+++ b/tests/tests/renderscript/Android.mk
@@ -29,7 +29,7 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner xmp_toolkit
-LOCAL_JNI_SHARED_LIBRARIES := libcoremathtestcpp_jni libbnnmdata_jni
+LOCAL_JNI_SHARED_LIBRARIES := libcoremathtestcpp_jni
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
@@ -37,5 +37,8 @@
 
 LOCAL_SDK_VERSION := current
 
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
 include $(BUILD_CTS_PACKAGE)
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/renderscript/AndroidManifest.xml b/tests/tests/renderscript/AndroidManifest.xml
index 6e67f9e..c6b3891 100644
--- a/tests/tests/renderscript/AndroidManifest.xml
+++ b/tests/tests/renderscript/AndroidManifest.xml
@@ -19,7 +19,7 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.cts.renderscript">
+    package="android.renderscript.cts">
 
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
@@ -30,7 +30,7 @@
 
     <!-- This is a self-instrumenting test package. -->
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
-                     android:targetPackage="com.android.cts.renderscript"
+                     android:targetPackage="android.renderscript.cts"
                      android:label="CTS tests of Renderscript component">
         <meta-data android:name="listener"
             android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/renderscript/AndroidTest.xml b/tests/tests/renderscript/AndroidTest.xml
new file mode 100644
index 0000000..cfcc322
--- /dev/null
+++ b/tests/tests/renderscript/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Configuration for Renderscript Tests">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsRenderscriptTestCases.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.InstrumentationTest" >
+        <option name="package" value="android.renderscript.cts" />
+        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+    </test>
+</configuration>
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/refocus/RefocusTest.java b/tests/tests/renderscript/src/android/renderscript/cts/refocus/RefocusTest.java
index 7ed027b..f7cea35 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/refocus/RefocusTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/refocus/RefocusTest.java
@@ -25,7 +25,7 @@
 import android.renderscript.cts.RSBaseCompute;
 import android.util.Log;
 
-import com.android.cts.renderscript.R;
+import android.renderscript.cts.R;
 
 import java.io.IOException;
 
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/verify.rs b/tests/tests/renderscript/src/android/renderscript/cts/verify.rs
index c3ae802..4527f1e 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/verify.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/verify.rs
@@ -18,8 +18,6 @@
 
 int gAllowedIntError = 0;
 float gAllowedFloatError = 0.0001f;
-double gAllowedFloatMatError = 0.00000001;
-double gAllowedDoubleMatError = 0.00000000001;
 static bool hadError = false;
 static int2 errorLoc = {0,0};
 
@@ -303,135 +301,6 @@
     }
 }
 
-
-static bool verify_CMatrix(rs_allocation in1, rs_allocation in2, double l2Norm, bool isUpperMatrix) {
-    uint32_t w = rsAllocationGetDimX(in1);
-    uint32_t h = rsAllocationGetDimY(in1);
-    for (uint32_t y = 0; y < h; y++) {
-        uint32_t xStart = 0;
-        if (isUpperMatrix) {
-            // Just test the upper matrix for certain BLAS routines
-            xStart = y;
-        }
-        for (uint32_t x = xStart; x < w; x++) {
-            float2 pref = rsGetElementAt_float2(in1, x, y);
-            float2 ptst = rsGetElementAt_float2(in2, x, y);
-            double absErr = (pref.x - ptst.x) * (pref.x - ptst.x) + (pref.y - ptst.y) * (pref.y - ptst.y);
-            if (absErr > l2Norm * gAllowedFloatMatError) {
-                errorLoc.x = x;
-                errorLoc.y = y;
-                hadError = true;
-                return false;
-            }
-        }
-    }
-    return true;
-}
-
-static bool verify_SMatrix(rs_allocation in1, rs_allocation in2, double l2Norm, bool isUpperMatrix) {
-    uint32_t w = rsAllocationGetDimX(in1);
-    uint32_t h = rsAllocationGetDimY(in1);
-    for (uint32_t y = 0; y < h; y++) {
-        uint32_t xStart = 0;
-        if (isUpperMatrix) {
-            // Just test the upper matrix for certain BLAS routines
-            xStart = y;
-        }
-        for (uint32_t x = xStart; x < w; x++) {
-            float pref = rsGetElementAt_float(in1, x, y);
-            float ptst = rsGetElementAt_float(in2, x, y);
-            double absErr = (pref - ptst) * (pref - ptst);
-            if (absErr > l2Norm * gAllowedFloatMatError) {
-                errorLoc.x = x;
-                errorLoc.y = y;
-                hadError = true;
-                return false;
-            }
-        }
-    }
-    return true;
-}
-
-static bool verify_ZMatrix(rs_allocation in1, rs_allocation in2, double l2Norm, bool isUpperMatrix) {
-    uint32_t w = rsAllocationGetDimX(in1);
-    uint32_t h = rsAllocationGetDimY(in1);
-    for (uint32_t y = 0; y < h; y++) {
-        uint32_t xStart = 0;
-        if (isUpperMatrix) {
-            // Just test the upper matrix for certain BLAS routines
-            xStart = y;
-        }
-        for (uint32_t x = xStart; x < w; x++) {
-            double2 pref = rsGetElementAt_double2(in1, x, y);
-            double2 ptst = rsGetElementAt_double2(in2, x, y);
-            double absErr = (pref.x - ptst.x) * (pref.x - ptst.x) + (pref.y - ptst.y) * (pref.y - ptst.y);
-            if (absErr > l2Norm * gAllowedDoubleMatError) {
-                errorLoc.x = x;
-                errorLoc.y = y;
-                hadError = true;
-                return false;
-            }
-        }
-    }
-    return true;
-}
-
-static bool verify_DMatrix(rs_allocation in1, rs_allocation in2, double l2Norm, bool isUpperMatrix) {
-    uint32_t w = rsAllocationGetDimX(in1);
-    uint32_t h = rsAllocationGetDimY(in1);
-    for (uint32_t y = 0; y < h; y++) {
-        uint32_t xStart = 0;
-        if (isUpperMatrix) {
-            // Just test the upper matrix for certain BLAS routines
-            xStart = y;
-        }
-        for (uint32_t x = xStart; x < w; x++) {
-            double pref = rsGetElementAt_double(in1, x, y);
-            double ptst = rsGetElementAt_double(in2, x, y);
-            double absErr = (pref - ptst) * (pref - ptst);
-            if (absErr > l2Norm * gAllowedDoubleMatError) {
-                errorLoc.x = x;
-                errorLoc.y = y;
-                hadError = true;
-                return false;
-            }
-        }
-    }
-    return true;
-}
-
-void verifyMatrix(rs_allocation ref_in, rs_allocation tst_in, double l2Norm, bool isUpperMatrix) {
-    rs_element e = rsAllocationGetElement(ref_in);
-    rs_data_type dt = rsElementGetDataType(e);
-    uint32_t vs = rsElementGetVectorSize(e);
-    bool valid = false;
-
-    if (dt == RS_TYPE_FLOAT_32) {
-        switch(vs) {
-        case 2:
-            valid = verify_CMatrix(ref_in, tst_in, l2Norm, isUpperMatrix);
-            break;
-        case 1:
-            valid = verify_SMatrix(ref_in, tst_in, l2Norm, isUpperMatrix);
-            break;
-        }
-    } else if (dt == RS_TYPE_FLOAT_64) {
-        switch(vs) {
-        case 2:
-            valid = verify_ZMatrix(ref_in, tst_in, l2Norm, isUpperMatrix);
-            break;
-        case 1:
-            valid = verify_DMatrix(ref_in, tst_in, l2Norm, isUpperMatrix);
-            break;
-        }
-    }
-    if (!valid) {
-        rsDebug("verify failure at xy", errorLoc);
-        printCell("Expected value ", ref_in, errorLoc);
-        printCell("Actual value   ", tst_in, errorLoc);
-    }
-}
-
 void checkError()
 {
     if (hadError) {
diff --git a/tests/tests/renderscriptlegacy/Android.mk b/tests/tests/renderscriptlegacy/Android.mk
index 31d8ed9..6aca19b 100644
--- a/tests/tests/renderscriptlegacy/Android.mk
+++ b/tests/tests/renderscriptlegacy/Android.mk
@@ -30,4 +30,7 @@
 
 LOCAL_SDK_VERSION := 19
 
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/renderscriptlegacy/AndroidManifest.xml b/tests/tests/renderscriptlegacy/AndroidManifest.xml
index 0c0498a..bd1184f 100644
--- a/tests/tests/renderscriptlegacy/AndroidManifest.xml
+++ b/tests/tests/renderscriptlegacy/AndroidManifest.xml
@@ -19,7 +19,7 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.cts.renderscriptlegacy">
+    package="android.renderscriptlegacy.cts">
 
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
     <application>
@@ -28,7 +28,7 @@
 
     <!-- This is a self-instrumenting test package. -->
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
-                     android:targetPackage="com.android.cts.renderscriptlegacy"
+                     android:targetPackage="android.renderscriptlegacy.cts"
                      android:label="CTS tests of Renderscript component">
         <meta-data android:name="listener"
             android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/renderscriptlegacy/AndroidTest.xml b/tests/tests/renderscriptlegacy/AndroidTest.xml
new file mode 100644
index 0000000..c11c0a6
--- /dev/null
+++ b/tests/tests/renderscriptlegacy/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Configuration for Renderscript legacy Tests">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsRenderscriptLegacyTestCases.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.InstrumentationTest" >
+        <option name="package" value="android.renderscript.cts" />
+        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+    </test>
+</configuration>
diff --git a/tests/tests/rsblas/Android.mk b/tests/tests/rsblas/Android.mk
new file mode 100644
index 0000000..b3edfac
--- /dev/null
+++ b/tests/tests/rsblas/Android.mk
@@ -0,0 +1,40 @@
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsRsBlasTestCases
+
+# 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)
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_JNI_SHARED_LIBRARIES := libbnnmdata_jni
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
+
+LOCAL_RENDERSCRIPT_FLAGS := -Wno-error=deprecated-declarations
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/suite/cts/deviceTests/simplecpu/AndroidManifest.xml b/tests/tests/rsblas/AndroidManifest.xml
similarity index 66%
copy from suite/cts/deviceTests/simplecpu/AndroidManifest.xml
copy to tests/tests/rsblas/AndroidManifest.xml
index e5c1c2b..f6099fb 100644
--- a/suite/cts/deviceTests/simplecpu/AndroidManifest.xml
+++ b/tests/tests/rsblas/AndroidManifest.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
+<!-- Copyright (C) 2015 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -15,15 +15,22 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.cts.simplecpu">
+    package="com.android.cts.rsblas">
 
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <application>
         <uses-library android:name="android.test.runner" />
     </application>
+
+    <!-- This is a self-instrumenting test package. -->
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
-            android:targetPackage="com.android.cts.simplecpu"
-            android:label="Very simple CPU benchmarking" />
+                     android:targetPackage="com.android.cts.rsblas"
+                     android:label="CTS tests of RenderScript IntrinsicBLAS">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
+
 </manifest>
+
diff --git a/tests/tests/renderscript/assets/BLASData.txt b/tests/tests/rsblas/assets/BLASData.txt
similarity index 100%
rename from tests/tests/renderscript/assets/BLASData.txt
rename to tests/tests/rsblas/assets/BLASData.txt
diff --git a/tests/tests/renderscript/assets/blas_gen.py b/tests/tests/rsblas/assets/blas_gen.py
similarity index 100%
rename from tests/tests/renderscript/assets/blas_gen.py
rename to tests/tests/rsblas/assets/blas_gen.py
diff --git a/tests/tests/renderscript/libbnnmdata/Android.mk b/tests/tests/rsblas/libbnnmdata/Android.mk
similarity index 100%
rename from tests/tests/renderscript/libbnnmdata/Android.mk
rename to tests/tests/rsblas/libbnnmdata/Android.mk
diff --git a/tests/tests/renderscript/libbnnmdata/test_data.cpp b/tests/tests/rsblas/libbnnmdata/test_data.cpp
similarity index 99%
rename from tests/tests/renderscript/libbnnmdata/test_data.cpp
rename to tests/tests/rsblas/libbnnmdata/test_data.cpp
index 91222c2..a7dbd1a 100644
--- a/tests/tests/renderscript/libbnnmdata/test_data.cpp
+++ b/tests/tests/rsblas/libbnnmdata/test_data.cpp
@@ -56569,12 +56569,12 @@
 
 
 extern "C" JNIEXPORT void JNICALL
-Java_android_renderscript_cts_BNNMTest_getData(JNIEnv * env,
-                                                                      jclass,
-                                                                      jbyteArray a,
-                                                                      jbyteArray b,
-                                                                      jbyteArray c
-                                                                      )
+Java_android_cts_rsblas_BNNMTest_getData(JNIEnv * env,
+                                         jclass,
+                                         jbyteArray a,
+                                         jbyteArray b,
+                                         jbyteArray c
+                                         )
 {
     jbyte * a_byte = (jbyte *) env->GetPrimitiveArrayCritical(a, 0);
     jbyte * b_byte = (jbyte *) env->GetPrimitiveArrayCritical(b, 0);
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/BLASData.java b/tests/tests/rsblas/src/android/renderscript/cts/BLASData.java
similarity index 99%
rename from tests/tests/renderscript/src/android/renderscript/cts/BLASData.java
rename to tests/tests/rsblas/src/android/renderscript/cts/BLASData.java
index def0352..786290e 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/BLASData.java
+++ b/tests/tests/rsblas/src/android/renderscript/cts/BLASData.java
@@ -17,7 +17,7 @@
 /* Don't edit this file alone!
  * The array names need to match the data generated by blas_gen.py. */
 
-package android.renderscript.cts;
+package android.cts.rsblas;
 
 import android.content.res.AssetManager;
 import android.content.Context;
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/BNNMTest.java b/tests/tests/rsblas/src/android/renderscript/cts/BNNMTest.java
similarity index 99%
rename from tests/tests/renderscript/src/android/renderscript/cts/BNNMTest.java
rename to tests/tests/rsblas/src/android/renderscript/cts/BNNMTest.java
index 1822f6a..f95ad3c 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/BNNMTest.java
+++ b/tests/tests/rsblas/src/android/renderscript/cts/BNNMTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.renderscript.cts;
+package android.cts.rsblas;
 
 import android.renderscript.*;
 import android.util.Log;
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicBLAS.java b/tests/tests/rsblas/src/android/renderscript/cts/IntrinsicBLAS.java
similarity index 99%
rename from tests/tests/renderscript/src/android/renderscript/cts/IntrinsicBLAS.java
rename to tests/tests/rsblas/src/android/renderscript/cts/IntrinsicBLAS.java
index 17f546b..a5fc80d 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicBLAS.java
+++ b/tests/tests/rsblas/src/android/renderscript/cts/IntrinsicBLAS.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.renderscript.cts;
+package android.cts.rsblas;
 
 import android.renderscript.*;
 import android.util.Log;
diff --git a/tests/tests/rsblas/src/android/renderscript/cts/IntrinsicBase.java b/tests/tests/rsblas/src/android/renderscript/cts/IntrinsicBase.java
new file mode 100644
index 0000000..5ab52b0
--- /dev/null
+++ b/tests/tests/rsblas/src/android/renderscript/cts/IntrinsicBase.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.cts.rsblas;
+
+import android.util.Log;
+import android.renderscript.RenderScript;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Type;
+import android.renderscript.Script;
+
+public class IntrinsicBase extends RSBaseCompute {
+    protected final String TAG = "Img";
+
+    protected Allocation mAllocSrc;
+    protected Allocation mAllocRef;
+    protected Allocation mAllocDst;
+    protected ScriptC_verify mVerify;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mVerify = new ScriptC_verify(mRS);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mVerify != null) {
+            mVerify.destroy();
+            mVerify = null;
+        }
+        super.tearDown();
+    }
+
+    protected void checkError() {
+        mRS.finish();
+        mVerify.invoke_checkError();
+        waitForMessage();
+        checkForErrors();
+    }
+}
diff --git a/tests/tests/rsblas/src/android/renderscript/cts/RSBase.java b/tests/tests/rsblas/src/android/renderscript/cts/RSBase.java
new file mode 100644
index 0000000..7057fd9
--- /dev/null
+++ b/tests/tests/rsblas/src/android/renderscript/cts/RSBase.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.cts.rsblas;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.RenderScript.RSErrorHandler;
+import android.renderscript.RenderScript.RSMessageHandler;
+import android.renderscript.RSRuntimeException;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+/**
+ * Base RenderScript test class. This class provides a message handler and a
+ * convenient way to wait for compute scripts to complete their execution.
+ */
+public class RSBase extends AndroidTestCase {
+
+    Context mCtx;
+    Resources mRes;
+
+    private int result;
+    // msgHandled is used to synchronize between waitForMessage() and the
+    // RSMessageHandler thread.
+    private volatile boolean msgHandled;
+
+    protected static final int RS_MSG_TEST_PASSED = 100;
+    protected static final int RS_MSG_TEST_FAILED = 101;
+    protected static final int RS_MSG_TEST_FLUSH = 102;
+
+    RSMessageHandler mRsMessage = new RSMessageHandler() {
+        public void run() {
+            if (result == 0) {
+                switch (mID) {
+                    case RS_MSG_TEST_PASSED:
+                    case RS_MSG_TEST_FAILED:
+                        result = mID;
+                        break;
+                    case RS_MSG_TEST_FLUSH:
+                        break;
+                    default:
+                        fail("Got unexpected RS message");
+                        return;
+                }
+            }
+            msgHandled = true;
+        }
+    };
+
+    protected void waitForMessage() {
+        while (!msgHandled) {
+            Thread.yield();
+        }
+    }
+
+    protected boolean FoundError = false;
+    protected RSErrorHandler mRsError = new RSErrorHandler() {
+        public void run() {
+            FoundError = true;
+            Log.e("RenderscriptCTS", mErrorMessage);
+            throw new RSRuntimeException("Received error " + mErrorNum +
+                                         " message " + mErrorMessage);
+        }
+    };
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        result = 0;
+        msgHandled = false;
+        mCtx = getContext();
+        mRes = mCtx.getResources();
+    }
+
+    /**
+     * Verify that we didn't fail on the control or script side of things.
+     */
+    protected void checkForErrors() {
+        assertFalse(FoundError);
+        assertTrue(result != RS_MSG_TEST_FAILED);
+    }
+}
diff --git a/tests/tests/rsblas/src/android/renderscript/cts/RSBaseCompute.java b/tests/tests/rsblas/src/android/renderscript/cts/RSBaseCompute.java
new file mode 100644
index 0000000..d548a70
--- /dev/null
+++ b/tests/tests/rsblas/src/android/renderscript/cts/RSBaseCompute.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.cts.rsblas;
+
+import android.renderscript.RenderScript;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RSRuntimeException;
+import android.util.Log;
+
+/**
+ * Base RenderScript test class. This class provides a message handler and a
+ * convenient way to wait for compute scripts to complete their execution.
+ */
+public class RSBaseCompute extends RSBase {
+    RenderScript mRS;
+    protected int INPUTSIZE = 512;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mRS = RenderScript.create(mCtx);
+        mRS.setMessageHandler(mRsMessage);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+}
diff --git a/tests/tests/rsblas/src/android/renderscript/cts/shared.rsh b/tests/tests/rsblas/src/android/renderscript/cts/shared.rsh
new file mode 100644
index 0000000..d20fd34
--- /dev/null
+++ b/tests/tests/rsblas/src/android/renderscript/cts/shared.rsh
@@ -0,0 +1,26 @@
+#pragma version(1)
+#pragma rs java_package_name(android.cts.rsblas)
+
+static int64_t g_time;
+
+static inline void start(void) {
+    g_time = rsUptimeMillis();
+}
+
+static inline float end(void) {
+    int64_t t = rsUptimeMillis() - g_time;
+    return ((float)t) / 1000.f;
+}
+
+#define _RS_ASSERT(b) \
+do { \
+    if (!(b)) { \
+        failed = true; \
+        rsDebug(#b " FAILED", 0); \
+    } \
+\
+} while (0)
+
+/* These constants must match those in UnitTest.java */
+static const int RS_MSG_TEST_PASSED = 100;
+static const int RS_MSG_TEST_FAILED = 101;
diff --git a/tests/tests/rsblas/src/android/renderscript/cts/verify.rs b/tests/tests/rsblas/src/android/renderscript/cts/verify.rs
new file mode 100644
index 0000000..ea3cff6
--- /dev/null
+++ b/tests/tests/rsblas/src/android/renderscript/cts/verify.rs
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "shared.rsh"
+
+double gAllowedFloatMatError = 0.00000001;
+double gAllowedDoubleMatError = 0.00000000001;
+static bool hadError = false;
+static int2 errorLoc = {0,0};
+
+#define printCell(txt, a, xy) \
+{                       \
+    rs_element e = rsAllocationGetElement(a); \
+    rs_data_type dt = rsElementGetDataType(e); \
+    uint32_t vs = rsElementGetVectorSize(e); \
+ \
+    if (dt == RS_TYPE_UNSIGNED_8) { \
+        switch(vs) { \
+        case 4: \
+            rsDebug(txt, rsGetElementAt_uchar4(a, xy.x, xy.y)); \
+            break; \
+        case 3: \
+            rsDebug(txt, rsGetElementAt_uchar3(a, xy.x, xy.y)); \
+            break; \
+        case 2: \
+            rsDebug(txt, rsGetElementAt_uchar2(a, xy.x, xy.y)); \
+            break; \
+        case 1: \
+            rsDebug(txt, rsGetElementAt_uchar(a, xy.x, xy.y)); \
+            break; \
+        } \
+    } else if (dt == RS_TYPE_FLOAT_32) { \
+        switch(vs) { \
+        case 4: \
+            rsDebug(txt, rsGetElementAt_float4(a, xy.x, xy.y)); \
+            break; \
+        case 3: \
+            rsDebug(txt, rsGetElementAt_float3(a, xy.x, xy.y)); \
+            break; \
+        case 2: \
+            rsDebug(txt, rsGetElementAt_float2(a, xy.x, xy.y)); \
+            break; \
+        case 1: \
+            rsDebug(txt, rsGetElementAt_float(a, xy.x, xy.y)); \
+            break; \
+        } \
+    } else if (dt == RS_TYPE_FLOAT_64) { \
+        switch(vs) { \
+        case 4: \
+            rsDebug(txt, rsGetElementAt_double4(a, xy.x, xy.y)); \
+            break; \
+        case 3: \
+            rsDebug(txt, rsGetElementAt_double3(a, xy.x, xy.y)); \
+            break; \
+        case 2: \
+            rsDebug(txt, rsGetElementAt_double2(a, xy.x, xy.y)); \
+            break; \
+        case 1: \
+            rsDebug(txt, rsGetElementAt_double(a, xy.x, xy.y)); \
+        } \
+    } \
+}
+
+static bool verify_CMatrix(rs_allocation in1, rs_allocation in2, double l2Norm, bool isUpperMatrix) {
+    uint32_t w = rsAllocationGetDimX(in1);
+    uint32_t h = rsAllocationGetDimY(in1);
+    for (uint32_t y = 0; y < h; y++) {
+        uint32_t xStart = 0;
+        if (isUpperMatrix) {
+            // Just test the upper matrix for certain BLAS routines
+            xStart = y;
+        }
+        for (uint32_t x = xStart; x < w; x++) {
+            float2 pref = rsGetElementAt_float2(in1, x, y);
+            float2 ptst = rsGetElementAt_float2(in2, x, y);
+            double absErr = (pref.x - ptst.x) * (pref.x - ptst.x) + (pref.y - ptst.y) * (pref.y - ptst.y);
+            if (absErr > l2Norm * gAllowedFloatMatError) {
+                errorLoc.x = x;
+                errorLoc.y = y;
+                hadError = true;
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+static bool verify_SMatrix(rs_allocation in1, rs_allocation in2, double l2Norm, bool isUpperMatrix) {
+    uint32_t w = rsAllocationGetDimX(in1);
+    uint32_t h = rsAllocationGetDimY(in1);
+    for (uint32_t y = 0; y < h; y++) {
+        uint32_t xStart = 0;
+        if (isUpperMatrix) {
+            // Just test the upper matrix for certain BLAS routines
+            xStart = y;
+        }
+        for (uint32_t x = xStart; x < w; x++) {
+            float pref = rsGetElementAt_float(in1, x, y);
+            float ptst = rsGetElementAt_float(in2, x, y);
+            double absErr = (pref - ptst) * (pref - ptst);
+            if (absErr > l2Norm * gAllowedFloatMatError) {
+                errorLoc.x = x;
+                errorLoc.y = y;
+                hadError = true;
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+static bool verify_ZMatrix(rs_allocation in1, rs_allocation in2, double l2Norm, bool isUpperMatrix) {
+    uint32_t w = rsAllocationGetDimX(in1);
+    uint32_t h = rsAllocationGetDimY(in1);
+    for (uint32_t y = 0; y < h; y++) {
+        uint32_t xStart = 0;
+        if (isUpperMatrix) {
+            // Just test the upper matrix for certain BLAS routines
+            xStart = y;
+        }
+        for (uint32_t x = xStart; x < w; x++) {
+            double2 pref = rsGetElementAt_double2(in1, x, y);
+            double2 ptst = rsGetElementAt_double2(in2, x, y);
+            double absErr = (pref.x - ptst.x) * (pref.x - ptst.x) + (pref.y - ptst.y) * (pref.y - ptst.y);
+            if (absErr > l2Norm * gAllowedDoubleMatError) {
+                errorLoc.x = x;
+                errorLoc.y = y;
+                hadError = true;
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+static bool verify_DMatrix(rs_allocation in1, rs_allocation in2, double l2Norm, bool isUpperMatrix) {
+    uint32_t w = rsAllocationGetDimX(in1);
+    uint32_t h = rsAllocationGetDimY(in1);
+    for (uint32_t y = 0; y < h; y++) {
+        uint32_t xStart = 0;
+        if (isUpperMatrix) {
+            // Just test the upper matrix for certain BLAS routines
+            xStart = y;
+        }
+        for (uint32_t x = xStart; x < w; x++) {
+            double pref = rsGetElementAt_double(in1, x, y);
+            double ptst = rsGetElementAt_double(in2, x, y);
+            double absErr = (pref - ptst) * (pref - ptst);
+            if (absErr > l2Norm * gAllowedDoubleMatError) {
+                errorLoc.x = x;
+                errorLoc.y = y;
+                hadError = true;
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+void verifyMatrix(rs_allocation ref_in, rs_allocation tst_in, double l2Norm, bool isUpperMatrix) {
+    rs_element e = rsAllocationGetElement(ref_in);
+    rs_data_type dt = rsElementGetDataType(e);
+    uint32_t vs = rsElementGetVectorSize(e);
+    bool valid = false;
+
+    if (dt == RS_TYPE_FLOAT_32) {
+        switch(vs) {
+        case 2:
+            valid = verify_CMatrix(ref_in, tst_in, l2Norm, isUpperMatrix);
+            break;
+        case 1:
+            valid = verify_SMatrix(ref_in, tst_in, l2Norm, isUpperMatrix);
+            break;
+        }
+    } else if (dt == RS_TYPE_FLOAT_64) {
+        switch(vs) {
+        case 2:
+            valid = verify_ZMatrix(ref_in, tst_in, l2Norm, isUpperMatrix);
+            break;
+        case 1:
+            valid = verify_DMatrix(ref_in, tst_in, l2Norm, isUpperMatrix);
+            break;
+        }
+    }
+    if (!valid) {
+        rsDebug("verify failure at xy", errorLoc);
+        printCell("Expected value ", ref_in, errorLoc);
+        printCell("Actual value   ", tst_in, errorLoc);
+    }
+}
+
+void checkError()
+{
+    if (hadError) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    } else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
diff --git a/tests/tests/security/jni/Android.mk b/tests/tests/security/jni/Android.mk
index b651cae..07bad55 100644
--- a/tests/tests/security/jni/Android.mk
+++ b/tests/tests/security/jni/Android.mk
@@ -34,11 +34,12 @@
 		android_security_cts_EncryptionTest.cpp \
 		android_security_cts_AudioFlingerBinderTest.cpp \
 		android_security_cts_AudioEffectBinderTest.cpp \
-		android_security_cts_MediaPlayerInfoLeakTest.cpp
+		android_security_cts_MediaPlayerInfoLeakTest.cpp \
+		android_security_cts_StagefrightFoundationTest.cpp
 
 LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
 
-LOCAL_SHARED_LIBRARIES := libnativehelper liblog libbinder libutils libmedia libselinux libdl libcutils libcrypto
+LOCAL_SHARED_LIBRARIES := libnativehelper liblog libbinder libutils libmedia libselinux libdl libcutils libcrypto libstagefright_foundation
 
 LOCAL_C_INCLUDES += ndk/sources/cpufeatures
 LOCAL_STATIC_LIBRARIES := cpufeatures
diff --git a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
index 6ccc4099..99ceda2 100644
--- a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
+++ b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
@@ -29,6 +29,7 @@
 extern int register_android_security_cts_EncryptionTest(JNIEnv* env);
 extern int register_android_security_cts_AudioEffectBinderTest(JNIEnv* env);
 extern int register_android_security_cts_MediaPlayerInfoLeakTest(JNIEnv* env);
+extern int register_android_security_cts_StagefrightFoundationTest(JNIEnv* env);
 
 jint JNI_OnLoad(JavaVM *vm, void *reserved) {
     JNIEnv *env = NULL;
@@ -89,5 +90,9 @@
         return JNI_ERR;
     }
 
+    if (register_android_security_cts_StagefrightFoundationTest(env)) {
+        return JNI_ERR;
+    }
+
     return JNI_VERSION_1_4;
 }
diff --git a/tests/tests/security/jni/android_security_cts_StagefrightFoundationTest.cpp b/tests/tests/security/jni/android_security_cts_StagefrightFoundationTest.cpp
new file mode 100644
index 0000000..d16bd38
--- /dev/null
+++ b/tests/tests/security/jni/android_security_cts_StagefrightFoundationTest.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AudioEffectBinderTest-JNI"
+
+#include <cstdio>
+#include <jni.h>
+#include <binder/Parcel.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+using namespace android;
+
+/*
+ * Native methods used by
+ * cts/tests/tests/security/src/android/security/cts/StagefrightFoundationTest.java
+ */
+
+static jboolean android_security_cts_StagefrightFoundation_test_aMessageFromParcel(
+        JNIEnv* env __unused, jobject thiz __unused)
+{
+    const int kMaxNumItems = 64;
+    const int kNumItems = kMaxNumItems + 1 + 1000;
+    char name[128];
+
+    Parcel data;
+    data.writeInt32(0);  // what
+    data.writeInt32(kNumItems);  // numItems
+    for (int i = 0; i < kMaxNumItems; ++i) {
+        snprintf(name, sizeof(name), "item-%d", i);
+        data.writeCString(name);  // name
+        data.writeInt32(0);  // kTypeInt32
+        data.writeInt32(i);  // value
+    }
+    data.writeCString("evil");  // name
+    data.writeInt32(0);  // kTypeInt32
+    data.writeInt32(0);  // value
+    // NOTE: This could overwrite mNumItems!
+
+    for (int i = 0; i < 1000; ++i) {
+        snprintf(name, sizeof(name), "evil-%d", i);
+        data.writeCString(name);  // name
+        data.writeInt32(0);  // kTypeInt32
+        data.writeInt32(0);  // value
+    }
+
+    data.setDataPosition(0);
+    sp<AMessage> msg = AMessage::FromParcel(data);
+
+    for (int i = 0; i < kMaxNumItems; ++i) {
+        snprintf(name, sizeof(name), "item-%d", i);
+        int32_t value;
+        if (!msg->findInt32(name, &value)) {
+            ALOGE("cannot find value for %s", name);
+            return JNI_FALSE;
+        }
+        if (value != i) {
+            ALOGE("value is changed: expected %d actual %d", i, value);
+            return JNI_FALSE;
+        }
+    }
+    return JNI_TRUE;
+}
+
+int register_android_security_cts_StagefrightFoundationTest(JNIEnv *env)
+{
+    static JNINativeMethod methods[] = {
+        { "native_test_aMessageFromParcel", "()Z",
+                (void *) android_security_cts_StagefrightFoundation_test_aMessageFromParcel},
+    };
+
+    jclass clazz = env->FindClass("android/security/cts/StagefrightFoundationTest");
+    return env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0]));
+}
diff --git a/tests/tests/security/src/android/security/cts/AslrTest.java b/tests/tests/security/src/android/security/cts/AslrTest.java
index 913b49b..774df87 100644
--- a/tests/tests/security/src/android/security/cts/AslrTest.java
+++ b/tests/tests/security/src/android/security/cts/AslrTest.java
@@ -16,20 +16,89 @@
 
 package android.security.cts;
 
+import android.test.InstrumentationTestCase;
 import junit.framework.TestCase;
 
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileReader;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
 import java.io.IOException;
+import java.util.HashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import android.cts.util.ReadElf;
 
 /**
  * Verify that ASLR is properly enabled on Android Compatible devices.
  */
-public class AslrTest extends TestCase {
+public class AslrTest extends InstrumentationTestCase {
+
+    private static final int aslrMinEntropyBits = 8;
+
+    private static final String TAG = "AslrTest";
+
+    private String readMappingAddress(String mappingName) throws Exception {
+        ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation()
+                .executeShellCommand("/system/bin/cat /proc/self/maps");
+
+        BufferedReader reader = new BufferedReader(
+                new InputStreamReader(new FileInputStream(pfd.getFileDescriptor())));
+
+        Pattern p = Pattern.compile("^([a-f0-9]+)\\-.+\\[" + mappingName + "\\]$");
+        String line;
+
+        while ((line = reader.readLine()) != null) {
+            Matcher m = p.matcher(line);
+
+            if (m.matches()) {
+                return m.group(1);
+            }
+        }
+
+        return null;
+    }
+
+    private int calculateEntropyBits(String mappingName) throws Exception {
+        HashMap<String, Integer> addresses = new HashMap<String, Integer>();
+
+        // Sufficient number of iterations to ensure we should see at least
+        // aslrMinEntropyBits 
+        for (int i = 0; i < 2 * (1 << aslrMinEntropyBits); i++) {
+            addresses.put(readMappingAddress(mappingName), 1);
+        }
+
+        double entropy = Math.log(addresses.size()) / Math.log(2);
+
+        Log.i(TAG, String.format("%.1f", entropy) +
+            " bits of entropy for " + mappingName);
+
+        return (int) Math.round(entropy);
+    }
+
+    private void testMappingEntropy(String mappingName) throws Exception {
+        if (readMappingAddress(mappingName) == null) {
+            Log.i(TAG, mappingName + " does not exist");
+            return;
+        }
+
+        int entropy = calculateEntropyBits(mappingName);
+
+        assertTrue("Insufficient " + mappingName + " randomization (" +
+            entropy + " bits, >= " + aslrMinEntropyBits + " required)",
+            entropy >= aslrMinEntropyBits);
+    }
+
+    public void testRandomization() throws Exception {
+        testMappingEntropy("stack");
+        testMappingEntropy("heap");
+        testMappingEntropy("anon:libc_malloc");
+    }
 
     public void testOneExecutableIsPie() throws IOException {
         assertTrue(ReadElf.read(new File("/system/bin/cat")).isPIE());
@@ -51,5 +120,4 @@
             }
         }
     }
-
 }
diff --git a/tests/tests/security/src/android/security/cts/ListeningPortsTest.java b/tests/tests/security/src/android/security/cts/ListeningPortsTest.java
index 76c53c1..54fa406 100644
--- a/tests/tests/security/src/android/security/cts/ListeningPortsTest.java
+++ b/tests/tests/security/src/android/security/cts/ListeningPortsTest.java
@@ -18,11 +18,14 @@
 
 import android.content.pm.PackageManager;
 import android.test.AndroidTestCase;
+import android.util.Log;
 import junit.framework.AssertionFailedError;
 
 import java.io.File;
 import java.io.IOException;
 import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -37,6 +40,9 @@
  * is considered a security best practice.
  */
 public class ListeningPortsTest extends AndroidTestCase {
+    private static final String TAG = "ListeningPortsTest";
+
+    private static final int CONN_TIMEOUT_IN_MS = 5000;
 
     /** Ports that are allowed to be listening. */
     private static final List<String> EXCEPTION_PATTERNS = new ArrayList<String>(6);
@@ -202,8 +208,12 @@
             String addrPortUid = addrPort + ' ' + entry.uid;
 
             if (isPortListening(entry.state, isTcp)
-                && !(isException(addrPort) || isException(addrUid) || isException(addrPortUid))
-                && (!entry.localAddress.isLoopbackAddress() ^ loopback)) {
+                    && !(isException(addrPort) || isException(addrUid) || isException(addrPortUid))
+                    && (!entry.localAddress.isLoopbackAddress() ^ loopback)) {
+                if (isTcp && !isTcpConnectable(entry.localAddress, entry.port)) {
+                    continue;
+                }
+
                 errors += "\nFound port listening on addr="
                         + entry.localAddress.getHostAddress() + ", port="
                         + entry.port + ", UID=" + entry.uid
@@ -225,6 +235,33 @@
         return Arrays.asList(packages).toString();
     }
 
+    private boolean isTcpConnectable(InetAddress address, int port) {
+        Socket socket = new Socket();
+
+        try {
+            if (Log.isLoggable(TAG, Log.DEBUG)) {
+                Log.d(TAG, "Trying to connect " + address + ":" + port);
+            }
+            socket.connect(new InetSocketAddress(address, port), CONN_TIMEOUT_IN_MS);
+        } catch (IOException ioe) {
+            if (Log.isLoggable(TAG, Log.DEBUG)) {
+                Log.d(TAG, "Unable to connect:" + ioe);
+            }
+            return false;
+        } finally {
+            try {
+                socket.close();
+            } catch (IOException closeError) {
+                Log.e(TAG, "Unable to close socket: " + closeError);
+            }
+        }
+
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
+            Log.d(TAG, address + ":" + port + " is connectable.");
+        }
+        return true;
+    }
+
     private static boolean isException(String localAddress) {
         return isPatternMatch(EXCEPTION_PATTERNS, localAddress);
     }
diff --git a/tests/tests/security/src/android/security/cts/StagefrightFoundationTest.java b/tests/tests/security/src/android/security/cts/StagefrightFoundationTest.java
new file mode 100644
index 0000000..9999d88
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/StagefrightFoundationTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import junit.framework.TestCase;
+
+public class StagefrightFoundationTest extends TestCase {
+
+    static {
+        System.loadLibrary("ctssecurity_jni");
+    }
+
+    /**
+     * Checks that IEffect::command() cannot leak data.
+     */
+    public void test_aMessageFromParcel() throws Exception {
+        assertTrue(native_test_aMessageFromParcel());
+    }
+
+    private static native boolean native_test_aMessageFromParcel();
+}
diff --git a/tests/tests/telecom/Android.mk b/tests/tests/telecom/Android.mk
index 51d97f5..fc03b68 100644
--- a/tests/tests/telecom/Android.mk
+++ b/tests/tests/telecom/Android.mk
@@ -30,4 +30,7 @@
 
 LOCAL_SDK_VERSION := current
 
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/telecom/AndroidManifest.xml b/tests/tests/telecom/AndroidManifest.xml
index b57e0b6..b4d44db 100644
--- a/tests/tests/telecom/AndroidManifest.xml
+++ b/tests/tests/telecom/AndroidManifest.xml
@@ -15,7 +15,7 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.cts.telecom">
+    package="android.telecom.cts">
     <uses-sdk android:minSdkVersion="21" />
     <uses-permission android:name="android.permission.CALL_PHONE" />>
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
@@ -81,7 +81,7 @@
     </application>
 
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
-                     android:targetPackage="com.android.cts.telecom"
+                     android:targetPackage="android.telecom.cts"
                      android:label="CTS tests for android.telecom package">
         <meta-data android:name="listener"
             android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/telecom/AndroidTest.xml b/tests/tests/telecom/AndroidTest.xml
new file mode 100644
index 0000000..841bd6e
--- /dev/null
+++ b/tests/tests/telecom/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Configuration for telecom Tests">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsTelecomTestCases.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.InstrumentationTest" >
+        <option name="package" value="android.telecom.cts" />
+        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+    </test>
+</configuration>
diff --git a/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java b/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java
index 879c995..67586ce 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java
@@ -35,8 +35,6 @@
 import android.telecom.StatusHints;
 import android.telecom.TelecomManager;
 
-import com.android.cts.telecom.R;
-
 /**
  * Suites of tests that verifies the various Call details.
  */
diff --git a/tests/tests/telecom/src/android/telecom/cts/DataObjectUnitTests.java b/tests/tests/telecom/src/android/telecom/cts/DataObjectUnitTests.java
index 1fbe0d5..a088951 100644
--- a/tests/tests/telecom/src/android/telecom/cts/DataObjectUnitTests.java
+++ b/tests/tests/telecom/src/android/telecom/cts/DataObjectUnitTests.java
@@ -39,8 +39,6 @@
 import android.telecom.VideoProfile;
 import android.test.InstrumentationTestCase;
 
-import com.android.cts.telecom.R;
-
 import java.util.Arrays;
 import java.util.List;
 
diff --git a/tests/tests/telecom/src/android/telecom/cts/TestUtils.java b/tests/tests/telecom/src/android/telecom/cts/TestUtils.java
index 4936209..3d9536e 100644
--- a/tests/tests/telecom/src/android/telecom/cts/TestUtils.java
+++ b/tests/tests/telecom/src/android/telecom/cts/TestUtils.java
@@ -36,7 +36,7 @@
 
     // Non-final to allow modification by tests not in this package (e.g. permission-related
     // tests in the Telecom2 test package.
-    public static String PACKAGE = "com.android.cts.telecom";
+    public static String PACKAGE = "android.telecom.cts";
     public static final String COMPONENT = "android.telecom.cts.CtsConnectionService";
     public static final String REMOTE_COMPONENT = "android.telecom.cts.CtsRemoteConnectionService";
     public static final String ACCOUNT_ID = "xtstest_CALL_PROVIDER_ID";
diff --git a/tests/tests/telecom2/Android.mk b/tests/tests/telecom2/Android.mk
index 71edb7b..0932292 100644
--- a/tests/tests/telecom2/Android.mk
+++ b/tests/tests/telecom2/Android.mk
@@ -38,9 +38,12 @@
 
 LOCAL_AAPT_FLAGS := \
     --auto-add-overlay \
-    --extra-packages com.android.cts.telecom \
-    --rename-manifest-package com.android.cts.telecom2 \
+    --extra-packages android.telecom.cts \
+    --rename-manifest-package android.telecom2.cts \
 
 LOCAL_SDK_VERSION := current
 
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/telecom2/AndroidManifest.xml b/tests/tests/telecom2/AndroidManifest.xml
index e618768..50c6945 100644
--- a/tests/tests/telecom2/AndroidManifest.xml
+++ b/tests/tests/telecom2/AndroidManifest.xml
@@ -15,7 +15,7 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.cts.telecom2">
+    package="android.telecom2.cts">
     <uses-sdk android:minSdkVersion="21" />
 
     <!--
@@ -74,7 +74,7 @@
     </application>
 
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
-                     android:targetPackage="com.android.cts.telecom2"
+                     android:targetPackage="android.telecom2.cts"
                      android:label="CTS tests for android.telecom package">
         <meta-data android:name="listener"
             android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/telecom2/AndroidTest.xml b/tests/tests/telecom2/AndroidTest.xml
new file mode 100644
index 0000000..75b33cd
--- /dev/null
+++ b/tests/tests/telecom2/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Configuration for telecom2 Tests">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsTelecomTestCases2.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.InstrumentationTest" >
+        <option name="package" value="android.telecom2.cts" />
+        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+    </test>
+</configuration>
diff --git a/tests/tests/text/Android.mk b/tests/tests/text/Android.mk
index eb8e7ea..8e80da8 100644
--- a/tests/tests/text/Android.mk
+++ b/tests/tests/text/Android.mk
@@ -36,5 +36,3 @@
 #LOCAL_SDK_VERSION := current
 
 include $(BUILD_CTS_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/text/AndroidTest.xml b/tests/tests/text/AndroidTest.xml
index 789b220..ef9f86e 100644
--- a/tests/tests/text/AndroidTest.xml
+++ b/tests/tests/text/AndroidTest.xml
@@ -14,10 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Text test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkPreconditionCheck">
-        <option name="apk" value="CtsTextPreconditions.apk"/>
-        <option name="package" value="android.text.preconditions"/>
-    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.WifiCheck" />
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsTextTestCases.apk" />
@@ -25,4 +22,4 @@
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.text.cts" />
     </test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/tests/tests/text/preconditions/AndroidManifest.xml b/tests/tests/text/preconditions/AndroidManifest.xml
deleted file mode 100644
index d5dbbed..0000000
--- a/tests/tests/text/preconditions/AndroidManifest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.text.preconditions">
-    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <!--  self-instrumenting test package. -->
-    <instrumentation
-        android:name="android.support.test.runner.AndroidJUnitRunner"
-        android:label="CTS preconditions test for 'text' module"
-        android:targetPackage="android.text.preconditions" >
-    </instrumentation>
-</manifest>
diff --git a/tests/tests/text/preconditions/src/android/text/preconditions/PreconditionsTest.java b/tests/tests/text/preconditions/src/android/text/preconditions/PreconditionsTest.java
deleted file mode 100644
index 41ab70b..0000000
--- a/tests/tests/text/preconditions/src/android/text/preconditions/PreconditionsTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.text.preconditions;
-
-import android.test.AndroidTestCase;
-
-import com.android.compatibility.common.preconditions.WifiHelper;
-
-/**
- * A test to verify that device-side preconditions are met for the text module of CTS
- */
-public class PreconditionsTest extends AndroidTestCase {
-
-    /**
-     * Test if device is connected to WiFi
-     * @throws Exception
-     */
-    public void testWifiConnected() throws Exception {
-        assertTrue("Device must have active network connection",
-                WifiHelper.isWifiConnected(this.getContext()));
-    }
-
-}
diff --git a/tests/tests/view/src/android/view/cts/MotionEventTest.java b/tests/tests/view/src/android/view/cts/MotionEventTest.java
index cdedca4..10ea33a 100644
--- a/tests/tests/view/src/android/view/cts/MotionEventTest.java
+++ b/tests/tests/view/src/android/view/cts/MotionEventTest.java
@@ -180,6 +180,40 @@
         assertEquals(mMotionEvent2.getDeviceId(), motionEvent.getDeviceId());
     }
 
+    public void testReadFromParcelWithInvalidPointerCountSize() {
+        Parcel parcel = Parcel.obtain();
+        mMotionEvent2.writeToParcel(parcel, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+
+        // Move to pointer id count.
+        parcel.setDataPosition(4);
+        parcel.writeInt(17);
+
+        parcel.setDataPosition(0);
+        try {
+            MotionEvent.CREATOR.createFromParcel(parcel);
+            fail("deserialized invalid parcel");
+        } catch (RuntimeException e) {
+            // Expected.
+        }
+    }
+
+    public void testReadFromParcelWithInvalidSampleSize() {
+        Parcel parcel = Parcel.obtain();
+        mMotionEvent2.writeToParcel(parcel, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+
+        // Move to sample count.
+        parcel.setDataPosition(2 * 4);
+        parcel.writeInt(0x000f0000);
+
+        parcel.setDataPosition(0);
+        try {
+            MotionEvent.CREATOR.createFromParcel(parcel);
+            fail("deserialized invalid parcel");
+        } catch (RuntimeException e) {
+            // Expected.
+        }
+    }
+
     public void testToString() {
         // make sure this method never throw exception.
         mMotionEvent2.toString();
diff --git a/tests/tests/view/src/android/view/cts/ViewGroupTest.java b/tests/tests/view/src/android/view/cts/ViewGroupTest.java
index 8cb7928..48afc2b 100644
--- a/tests/tests/view/src/android/view/cts/ViewGroupTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewGroupTest.java
@@ -59,6 +59,7 @@
 import android.view.animation.Animation.AnimationListener;
 import android.widget.TextView;
 
+import java.lang.IndexOutOfBoundsException;
 import java.util.ArrayList;
 
 public class ViewGroupTest extends InstrumentationTestCase implements CTSResult{
@@ -338,23 +339,23 @@
 
         Canvas canvas = new Canvas();
         MockViewGroup vg = new MockViewGroup(mContext);
-        MockViewGroup son = new MockViewGroup(mContext);
-        son.setAnimation(new MockAnimation());
-        vg.addView(son);
+        MockViewGroup child = new MockViewGroup(mContext);
+        child.setAnimation(new MockAnimation());
+        vg.addView(child);
         assertEquals(1, vg.getChildCount());
 
-        assertNotNull(son.getAnimation());
+        assertNotNull(child.getAnimation());
         vg.dispatchDraw(canvas);
         assertEquals(1, vg.drawChildCalledTime);
 
-        son.setAnimation(new MockAnimation());
+        child.setAnimation(new MockAnimation());
         vg.removeAllViewsInLayout();
 
         vg.drawChildCalledTime = 0;
         vg.dispatchDraw(canvas);
         assertEquals(1, vg.drawChildCalledTime);
 
-        son.setAnimation(new MockAnimation());
+        child.setAnimation(new MockAnimation());
         vg.clearDisappearingChildren();
 
         vg.drawChildCalledTime = 0;
@@ -683,11 +684,11 @@
 
     public void testFocusableViewAvailable() {
         MockViewGroup vg = new MockViewGroup(mContext);
-        MockView son = new MockView(mContext);
-        vg.addView(son);
+        MockView child = new MockView(mContext);
+        vg.addView(child);
 
-        son.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
-        son.focusableViewAvailable(vg);
+        child.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
+        child.focusableViewAvailable(vg);
 
         assertTrue(vg.isFocusableViewAvailable);
     }
@@ -695,11 +696,11 @@
     public void testFocusSearch() {
         MockViewGroup vg = new MockViewGroup(mContext);
         MockTextView textView = new MockTextView(mContext);
-        MockView son = new MockView(mContext);
-        vg.addView(son);
-        son.addView(textView);
-        assertNotNull(son.focusSearch(textView, 1));
-        assertSame(textView, son.focusSearch(textView, 1));
+        MockView child = new MockView(mContext);
+        vg.addView(child);
+        child.addView(textView);
+        assertNotNull(child.focusSearch(textView, 1));
+        assertSame(textView, child.focusSearch(textView, 1));
     }
 
     public void testGatherTransparentRegion() {
@@ -924,18 +925,18 @@
         final int width = 100;
         final int height = 200;
         MockViewGroup vg = new MockViewGroup(mContext);
-        MockView son = new MockView(mContext);
-        son.setLayoutParams(new LayoutParams(width, height));
-        son.forceLayout();
-        vg.addView(son);
+        MockView child = new MockView(mContext);
+        child.setLayoutParams(new LayoutParams(width, height));
+        child.forceLayout();
+        vg.addView(child);
 
         final int parentWidthMeasureSpec = 1;
         final int parentHeightMeasureSpec = 2;
-        vg.measureChild(son, parentWidthMeasureSpec, parentHeightMeasureSpec);
+        vg.measureChild(child, parentWidthMeasureSpec, parentHeightMeasureSpec);
         assertEquals(ViewGroup.getChildMeasureSpec(parentWidthMeasureSpec, 0, width),
-                son.mWidthMeasureSpec);
+                child.mWidthMeasureSpec);
         assertEquals(ViewGroup.getChildMeasureSpec(parentHeightMeasureSpec, 0, height),
-                son.mHeightMeasureSpec);
+                child.mHeightMeasureSpec);
     }
 
     public void testMeasureChildren() {
@@ -966,24 +967,24 @@
         final int parentHeightMeasureSpec = 3;
         final int heightUsed = 4;
         MockViewGroup vg = new MockViewGroup(mContext);
-        MockView son = new MockView(mContext);
+        MockView child = new MockView(mContext);
 
-        vg.addView(son);
-        son.setLayoutParams(new ViewGroup.LayoutParams(width, height));
+        vg.addView(child);
+        child.setLayoutParams(new ViewGroup.LayoutParams(width, height));
         try {
-            vg.measureChildWithMargins(son, parentWidthMeasureSpec, widthUsed,
+            vg.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed,
                     parentHeightMeasureSpec, heightUsed);
             fail("measureChildWithMargins should throw out class cast exception");
         } catch (RuntimeException e) {
         }
-        son.setLayoutParams(new ViewGroup.MarginLayoutParams(width, height));
+        child.setLayoutParams(new ViewGroup.MarginLayoutParams(width, height));
 
-        vg.measureChildWithMargins(son, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec,
+        vg.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec,
                 heightUsed);
         assertEquals(ViewGroup.getChildMeasureSpec(parentWidthMeasureSpec, parentHeightMeasureSpec,
-                width), son.mWidthMeasureSpec);
+                width), child.mWidthMeasureSpec);
         assertEquals(ViewGroup.getChildMeasureSpec(widthUsed, heightUsed, height),
-                son.mHeightMeasureSpec);
+                child.mHeightMeasureSpec);
     }
 
     public void testOffsetDescendantRectToMyCoords() {
@@ -1032,16 +1033,16 @@
 
     public void testOnAnimationEnd() {
         // this function is a call back function it should be tested in ViewGroup#drawChild.
-        MockViewGroup father = new MockViewGroup(mContext);
-        MockViewGroup son = new MockViewGroup(mContext);
-        son.setAnimation(new MockAnimation());
+        MockViewGroup parent = new MockViewGroup(mContext);
+        MockViewGroup child = new MockViewGroup(mContext);
+        child.setAnimation(new MockAnimation());
         // this call will make mPrivateFlags |= ANIMATION_STARTED;
-        son.onAnimationStart();
-        father.addView(son);
+        child.onAnimationStart();
+        parent.addView(child);
 
         MockCanvas canvas = new MockCanvas();
-        assertFalse(father.drawChild(canvas, son, 100));
-        assertTrue(son.isOnAnimationEndCalled);
+        assertFalse(parent.drawChild(canvas, child, 100));
+        assertTrue(child.isOnAnimationEndCalled);
     }
 
     private class MockAnimation extends Animation {
@@ -1062,22 +1063,22 @@
 
     public void testOnAnimationStart() {
         // This is a call back method. It should be tested in ViewGroup#drawChild.
-        MockViewGroup father = new MockViewGroup(mContext);
-        MockViewGroup son = new MockViewGroup(mContext);
+        MockViewGroup parent = new MockViewGroup(mContext);
+        MockViewGroup child = new MockViewGroup(mContext);
 
-        father.addView(son);
+        parent.addView(child);
 
         MockCanvas canvas = new MockCanvas();
         try {
-            assertFalse(father.drawChild(canvas, son, 100));
-            assertFalse(son.isOnAnimationStartCalled);
+            assertFalse(parent.drawChild(canvas, child, 100));
+            assertFalse(child.isOnAnimationStartCalled);
         } catch (Exception e) {
             // expected
         }
 
-        son.setAnimation(new MockAnimation());
-        assertFalse(father.drawChild(canvas, son, 100));
-        assertTrue(son.isOnAnimationStartCalled);
+        child.setAnimation(new MockAnimation());
+        assertFalse(parent.drawChild(canvas, child, 100));
+        assertTrue(child.isOnAnimationStartCalled);
     }
 
     public void testOnCreateDrawableState() {
@@ -1132,35 +1133,35 @@
     }
 
     public void testRemoveAllViewsInLayout() {
-        MockViewGroup father = new MockViewGroup(mContext);
-        MockViewGroup son = new MockViewGroup(mContext);
+        MockViewGroup parent = new MockViewGroup(mContext);
+        MockViewGroup child = new MockViewGroup(mContext);
         MockTextView textView = new MockTextView(mContext);
 
-        assertEquals(0, father.getChildCount());
+        assertEquals(0, parent.getChildCount());
 
-        son.addView(textView);
-        father.addView(son);
-        assertEquals(1, father.getChildCount());
+        child.addView(textView);
+        parent.addView(child);
+        assertEquals(1, parent.getChildCount());
 
-        father.removeAllViewsInLayout();
-        assertEquals(0, father.getChildCount());
-        assertEquals(1, son.getChildCount());
-        assertNull(son.getParent());
-        assertSame(son, textView.getParent());
+        parent.removeAllViewsInLayout();
+        assertEquals(0, parent.getChildCount());
+        assertEquals(1, child.getChildCount());
+        assertNull(child.getParent());
+        assertSame(child, textView.getParent());
     }
 
     public void testRemoveDetachedView() {
-        MockViewGroup father = new MockViewGroup(mContext);
-        MockViewGroup son1 = new MockViewGroup(mContext);
-        MockViewGroup son2 = new MockViewGroup(mContext);
+        MockViewGroup parent = new MockViewGroup(mContext);
+        MockViewGroup child1 = new MockViewGroup(mContext);
+        MockViewGroup child2 = new MockViewGroup(mContext);
         MockOnHierarchyChangeListener listener = new MockOnHierarchyChangeListener();
-        father.setOnHierarchyChangeListener(listener);
-        father.addView(son1);
-        father.addView(son2);
+        parent.setOnHierarchyChangeListener(listener);
+        parent.addView(child1);
+        parent.addView(child2);
 
-        father.removeDetachedView(son1, false);
-        assertSame(father, listener.sParent);
-        assertSame(son1, listener.sChild);
+        parent.removeDetachedView(child1, false);
+        assertSame(parent, listener.sParent);
+        assertSame(child1, listener.sChild);
     }
 
     static class MockOnHierarchyChangeListener implements OnHierarchyChangeListener {
@@ -1178,93 +1179,123 @@
     }
 
     public void testRemoveView() {
-        MockViewGroup father = new MockViewGroup(mContext);
-        MockViewGroup son = new MockViewGroup(mContext);
+        MockViewGroup parent = new MockViewGroup(mContext);
+        MockViewGroup child = new MockViewGroup(mContext);
 
-        assertEquals(0, father.getChildCount());
+        assertEquals(0, parent.getChildCount());
 
-        father.addView(son);
-        assertEquals(1, father.getChildCount());
+        parent.addView(child);
+        assertEquals(1, parent.getChildCount());
 
-        father.removeView(son);
-        assertEquals(0, father.getChildCount());
-        assertNull(son.getParent());
+        parent.removeView(child);
+        assertEquals(0, parent.getChildCount());
+        assertNull(child.getParent());
     }
 
     public void testRemoveViewAt() {
-        MockViewGroup father = new MockViewGroup(mContext);
-        MockViewGroup son = new MockViewGroup(mContext);
+        MockViewGroup parent = new MockViewGroup(mContext);
+        MockViewGroup child = new MockViewGroup(mContext);
 
-        assertEquals(0, father.getChildCount());
+        assertEquals(0, parent.getChildCount());
 
-        father.addView(son);
-        assertEquals(1, father.getChildCount());
+        parent.addView(child);
+        assertEquals(1, parent.getChildCount());
 
         try {
-            father.removeViewAt(2);
+            parent.removeViewAt(2);
             fail("should throw out null pointer exception");
         } catch (RuntimeException e) {
             // expected
         }
-        assertEquals(1, father.getChildCount());
+        assertEquals(1, parent.getChildCount());
 
-        father.removeViewAt(0);
-        assertEquals(0, father.getChildCount());
-        assertNull(son.getParent());
+        parent.removeViewAt(0);
+        assertEquals(0, parent.getChildCount());
+        assertNull(child.getParent());
     }
 
     public void testRemoveViewInLayout() {
-        MockViewGroup father = new MockViewGroup(mContext);
-        MockViewGroup son = new MockViewGroup(mContext);
+        MockViewGroup parent = new MockViewGroup(mContext);
+        MockViewGroup child = new MockViewGroup(mContext);
 
-        assertEquals(0, father.getChildCount());
+        assertEquals(0, parent.getChildCount());
 
-        father.addView(son);
-        assertEquals(1, father.getChildCount());
+        parent.addView(child);
+        assertEquals(1, parent.getChildCount());
 
-        father.removeViewInLayout(son);
-        assertEquals(0, father.getChildCount());
-        assertNull(son.getParent());
+        parent.removeViewInLayout(child);
+        assertEquals(0, parent.getChildCount());
+        assertNull(child.getParent());
     }
 
     public void testRemoveViews() {
-        MockViewGroup father = new MockViewGroup(mContext);
-        MockViewGroup son1 = new MockViewGroup(mContext);
-        MockViewGroup son2 = new MockViewGroup(mContext);
+        MockViewGroup parent = new MockViewGroup(mContext);
+        MockViewGroup child1 = new MockViewGroup(mContext);
+        MockViewGroup child2 = new MockViewGroup(mContext);
 
-        assertEquals(0, father.getChildCount());
+        assertEquals(0, parent.getChildCount());
+        parent.addView(child1);
+        parent.addView(child2);
+        assertEquals(2, parent.getChildCount());
 
-        father.addView(son1);
-        father.addView(son2);
-        assertEquals(2, father.getChildCount());
+        try {
+            parent.removeViews(-1, 1); // negative begin
+            fail("should fail with IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {}
 
-        father.removeViews(0, 1);
-        assertEquals(1, father.getChildCount());
-        assertNull(son1.getParent());
+        try {
+            parent.removeViews(0, -1); // negative count
+            fail("should fail with IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {}
 
-        father.removeViews(0, 1);
-        assertEquals(0, father.getChildCount());
-        assertNull(son2.getParent());
+        try {
+            parent.removeViews(1, 2); // past end
+            fail("should fail with IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {}
+        assertEquals(2, parent.getChildCount()); // child list unmodified
+
+        parent.removeViews(0, 1);
+        assertEquals(1, parent.getChildCount());
+        assertNull(child1.getParent());
+
+        parent.removeViews(0, 1);
+        assertEquals(0, parent.getChildCount());
+        assertNull(child2.getParent());
     }
 
     public void testRemoveViewsInLayout() {
-        MockViewGroup father = new MockViewGroup(mContext);
-        MockViewGroup son1 = new MockViewGroup(mContext);
-        MockViewGroup son2 = new MockViewGroup(mContext);
+        MockViewGroup parent = new MockViewGroup(mContext);
+        MockViewGroup child1 = new MockViewGroup(mContext);
+        MockViewGroup child2 = new MockViewGroup(mContext);
 
-        assertEquals(0, father.getChildCount());
+        assertEquals(0, parent.getChildCount());
+        parent.addView(child1);
+        parent.addView(child2);
+        assertEquals(2, parent.getChildCount());
 
-        father.addView(son1);
-        father.addView(son2);
-        assertEquals(2, father.getChildCount());
+        try {
+            parent.removeViewsInLayout(-1, 1); // negative begin
+            fail("should fail with IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {}
 
-        father.removeViewsInLayout(0, 1);
-        assertEquals(1, father.getChildCount());
-        assertNull(son1.getParent());
+        try {
+            parent.removeViewsInLayout(0, -1); // negative count
+            fail("should fail with IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {}
 
-        father.removeViewsInLayout(0, 1);
-        assertEquals(0, father.getChildCount());
-        assertNull(son2.getParent());
+        try {
+            parent.removeViewsInLayout(1, 2); // past end
+            fail("should fail with IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {}
+        assertEquals(2, parent.getChildCount()); // child list unmodified
+
+        parent.removeViewsInLayout(0, 1);
+        assertEquals(1, parent.getChildCount());
+        assertNull(child1.getParent());
+
+        parent.removeViewsInLayout(0, 1);
+        assertEquals(0, parent.getChildCount());
+        assertNull(child2.getParent());
     }
 
     public void testRequestChildFocus() {
@@ -1286,13 +1317,13 @@
     }
 
     public void testRequestDisallowInterceptTouchEvent() {
-        MockViewGroup father = new MockViewGroup(mContext);
-        MockView son = new MockView(mContext);
+        MockViewGroup parent = new MockViewGroup(mContext);
+        MockView child = new MockView(mContext);
 
-        father.addView(son);
-        son.requestDisallowInterceptTouchEvent(true);
-        son.requestDisallowInterceptTouchEvent(false);
-        assertTrue(father.isRequestDisallowInterceptTouchEventCalled);
+        parent.addView(child);
+        child.requestDisallowInterceptTouchEvent(true);
+        child.requestDisallowInterceptTouchEvent(false);
+        assertTrue(parent.isRequestDisallowInterceptTouchEventCalled);
     }
 
     public void testRequestFocus() {
@@ -1303,13 +1334,13 @@
     }
 
     public void testRequestTransparentRegion() {
-        MockViewGroup father = new MockViewGroup(mContext);
-        MockView son1 = new MockView(mContext);
-        MockView son2 = new MockView(mContext);
-        son1.addView(son2);
-        father.addView(son1);
-        son1.requestTransparentRegion(son2);
-        assertTrue(father.isRequestTransparentRegionCalled);
+        MockViewGroup parent = new MockViewGroup(mContext);
+        MockView child1 = new MockView(mContext);
+        MockView child2 = new MockView(mContext);
+        child1.addView(child2);
+        parent.addView(child1);
+        child1.requestTransparentRegion(child2);
+        assertTrue(parent.isRequestTransparentRegionCalled);
     }
 
     public void testScheduleLayoutAnimation() {
@@ -1476,15 +1507,15 @@
     }
 
     public void testSetOnHierarchyChangeListener() {
-        MockViewGroup father = new MockViewGroup(mContext);
-        MockViewGroup son = new MockViewGroup(mContext);
+        MockViewGroup parent = new MockViewGroup(mContext);
+        MockViewGroup child = new MockViewGroup(mContext);
         MockOnHierarchyChangeListener listener = new MockOnHierarchyChangeListener();
-        father.setOnHierarchyChangeListener(listener);
-        father.addView(son);
+        parent.setOnHierarchyChangeListener(listener);
+        parent.addView(child);
 
-        father.removeDetachedView(son, false);
-        assertSame(father, listener.sParent);
-        assertSame(son, listener.sChild);
+        parent.removeDetachedView(child, false);
+        assertSame(parent, listener.sParent);
+        assertSame(child, listener.sChild);
     }
 
     public void testSetPadding() {
@@ -1595,12 +1626,12 @@
     }
 
     public void testShowContextMenuForChild() {
-        MockViewGroup father = new MockViewGroup(mContext);
-        MockViewGroup son = new MockViewGroup(mContext);
-        father.addView(son);
+        MockViewGroup parent = new MockViewGroup(mContext);
+        MockViewGroup child = new MockViewGroup(mContext);
+        parent.addView(child);
 
-        son.showContextMenuForChild(null);
-        assertTrue(father.isShowContextMenuForChildCalled);
+        child.showContextMenuForChild(null);
+        assertTrue(parent.isShowContextMenuForChildCalled);
     }
 
     public void testStartLayoutAnimation() {
@@ -1616,24 +1647,24 @@
     }
 
     public void testUpdateViewLayout() {
-        MockViewGroup father = new MockViewGroup(mContext);
-        MockViewGroup son = new MockViewGroup(mContext);
+        MockViewGroup parent = new MockViewGroup(mContext);
+        MockViewGroup child = new MockViewGroup(mContext);
 
-        father.addView(son);
+        parent.addView(child);
         LayoutParams param = new LayoutParams(100, 200);
-        father.updateViewLayout(son, param);
-        assertEquals(param.width, son.getLayoutParams().width);
-        assertEquals(param.height, son.getLayoutParams().height);
+        parent.updateViewLayout(child, param);
+        assertEquals(param.width, child.getLayoutParams().width);
+        assertEquals(param.height, child.getLayoutParams().height);
     }
 
     public void testDebug() {
         final int EXPECTED = 100;
-        MockViewGroup father = new MockViewGroup(mContext);
-        MockViewGroup son = new MockViewGroup(mContext);
-        father.addView(son);
+        MockViewGroup parent = new MockViewGroup(mContext);
+        MockViewGroup child = new MockViewGroup(mContext);
+        parent.addView(child);
 
-        father.debug(EXPECTED);
-        assertEquals(EXPECTED + 1, son.debugDepth);
+        parent.debug(EXPECTED);
+        assertEquals(EXPECTED + 1, child.debugDepth);
     }
 
     public void testDispatchKeyEventPreIme() {
diff --git a/tests/tests/webkit/Android.mk b/tests/tests/webkit/Android.mk
index 3d6cbde..85377ae 100644
--- a/tests/tests/webkit/Android.mk
+++ b/tests/tests/webkit/Android.mk
@@ -36,5 +36,3 @@
 #LOCAL_SDK_VERSION := current
 
 include $(BUILD_CTS_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/webkit/AndroidTest.xml b/tests/tests/webkit/AndroidTest.xml
index 35940b0..0b2d748 100644
--- a/tests/tests/webkit/AndroidTest.xml
+++ b/tests/tests/webkit/AndroidTest.xml
@@ -14,10 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Webkit test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkPreconditionCheck">
-        <option name="apk" value="CtsWebkitPreconditions.apk"/>
-        <option name="package" value="android.webkit.preconditions"/>
-    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.WifiCheck" />
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsWebkitTestCases.apk" />
diff --git a/tests/tests/webkit/preconditions/Android.mk b/tests/tests/webkit/preconditions/Android.mk
deleted file mode 100644
index 0709b2d..0000000
--- a/tests/tests/webkit/preconditions/Android.mk
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-# and when built explicitly put it in the data partition
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test compatibility-device-preconditions
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsWebkitPreconditions
-
-# Tag this module as a cts_v2 test artifact
-LOCAL_COMPATIBILITY_SUITE := cts_v2
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
diff --git a/tests/tests/webkit/preconditions/AndroidManifest.xml b/tests/tests/webkit/preconditions/AndroidManifest.xml
deleted file mode 100644
index a987975..0000000
--- a/tests/tests/webkit/preconditions/AndroidManifest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.webkit.preconditions">
-    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <!--  self-instrumenting test package. -->
-    <instrumentation
-        android:name="android.support.test.runner.AndroidJUnitRunner"
-        android:label="CTS preconditions test for 'webkit' module"
-        android:targetPackage="android.webkit.preconditions" >
-    </instrumentation>
-</manifest>
diff --git a/tests/tests/webkit/preconditions/src/android/webkit/preconditions/PreconditionsTest.java b/tests/tests/webkit/preconditions/src/android/webkit/preconditions/PreconditionsTest.java
deleted file mode 100644
index 6a4e0e2..0000000
--- a/tests/tests/webkit/preconditions/src/android/webkit/preconditions/PreconditionsTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.webkit.preconditions;
-
-import android.test.AndroidTestCase;
-
-import com.android.compatibility.common.preconditions.WifiHelper;
-
-/**
- * A test to verify that device-side preconditions are met for the webkit module of CTS
- */
-public class PreconditionsTest extends AndroidTestCase {
-
-    /**
-     * Test if device is connected to WiFi
-     * @throws Exception
-     */
-    public void testWifiConnected() throws Exception {
-        assertTrue("Device must have active network connection",
-                WifiHelper.isWifiConnected(this.getContext()));
-    }
-
-}
diff --git a/tests/tests/widget/Android.mk b/tests/tests/widget/Android.mk
index 47fd0be..888c0e6 100644
--- a/tests/tests/widget/Android.mk
+++ b/tests/tests/widget/Android.mk
@@ -33,5 +33,3 @@
 LOCAL_COMPATIBILITY_SUITE := cts_v2
 
 include $(BUILD_CTS_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/widget/AndroidTest.xml b/tests/tests/widget/AndroidTest.xml
index ef4e24e..8891f43 100644
--- a/tests/tests/widget/AndroidTest.xml
+++ b/tests/tests/widget/AndroidTest.xml
@@ -14,10 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Widget test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkPreconditionCheck">
-        <option name="apk" value="CtsWidgetPreconditions.apk"/>
-        <option name="package" value="android.widget.preconditions"/>
-    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.WifiCheck" />
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsWidgetTestCases.apk" />
diff --git a/tests/tests/widget/preconditions/Android.mk b/tests/tests/widget/preconditions/Android.mk
deleted file mode 100644
index 7fe5744..0000000
--- a/tests/tests/widget/preconditions/Android.mk
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-# and when built explicitly put it in the data partition
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test compatibility-device-preconditions
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsWidgetPreconditions
-
-# Tag this module as a cts_v2 test artifact
-LOCAL_COMPATIBILITY_SUITE := cts_v2
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
diff --git a/tests/tests/widget/preconditions/AndroidManifest.xml b/tests/tests/widget/preconditions/AndroidManifest.xml
deleted file mode 100644
index fd6c512..0000000
--- a/tests/tests/widget/preconditions/AndroidManifest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.widget.preconditions">
-    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <!--  self-instrumenting test package. -->
-    <instrumentation
-        android:name="android.support.test.runner.AndroidJUnitRunner"
-        android:label="CTS preconditions test for 'widget' module"
-        android:targetPackage="android.widget.preconditions" >
-    </instrumentation>
-</manifest>
diff --git a/tests/tests/widget/preconditions/src/android/widget/preconditions/PreconditionsTest.java b/tests/tests/widget/preconditions/src/android/widget/preconditions/PreconditionsTest.java
deleted file mode 100644
index 945ea46..0000000
--- a/tests/tests/widget/preconditions/src/android/widget/preconditions/PreconditionsTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.widget.preconditions;
-
-import android.test.AndroidTestCase;
-
-import com.android.compatibility.common.preconditions.WifiHelper;
-
-/**
- * A test to verify that device-side preconditions are met for the widget module of CTS
- */
-public class PreconditionsTest extends AndroidTestCase {
-
-    /**
-     * Test if device is connected to WiFi
-     * @throws Exception
-     */
-    public void testWifiConnected() throws Exception {
-        assertTrue("Device must have active network connection",
-                WifiHelper.isWifiConnected(this.getContext()));
-    }
-
-}
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index efa4aeb..0ada600 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -24,6 +24,7 @@
 import android.app.Instrumentation;
 import android.app.Instrumentation.ActivityMonitor;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.content.res.ColorStateList;
 import android.content.res.Resources.NotFoundException;
 import android.cts.util.PollingCheck;
@@ -4452,9 +4453,18 @@
     public void testSetGetBreakStrategy() {
         TextView tv = new TextView(mActivity);
 
+        final PackageManager pm = getInstrumentation().getTargetContext().getPackageManager();
+
         // The default value is from the theme, here the default is BREAK_STRATEGY_HIGH_QUALITY for
-        // TextView.
-        assertEquals(Layout.BREAK_STRATEGY_HIGH_QUALITY, tv.getBreakStrategy());
+        // TextView except for Android Wear. The default value for Android Wear is
+        // BREAK_STRATEGY_BALANCED.
+        if (pm.hasSystemFeature(PackageManager.FEATURE_WATCH)) {
+            // Android Wear
+            assertEquals(Layout.BREAK_STRATEGY_BALANCED, tv.getBreakStrategy());
+        } else {
+            // All other form factor.
+            assertEquals(Layout.BREAK_STRATEGY_HIGH_QUALITY, tv.getBreakStrategy());
+        }
 
         tv.setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE);
         assertEquals(Layout.BREAK_STRATEGY_SIMPLE, tv.getBreakStrategy());
diff --git a/suite/cts/deviceTests/tvproviderperf/Android.mk b/tests/tvprovider/Android.mk
similarity index 87%
rename from suite/cts/deviceTests/tvproviderperf/Android.mk
rename to tests/tvprovider/Android.mk
index 8e865fb2..acf4bb9 100644
--- a/suite/cts/deviceTests/tvproviderperf/Android.mk
+++ b/tests/tvprovider/Android.mk
@@ -22,7 +22,11 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_PACKAGE_NAME := CtsDeviceTvProviderPerf
+LOCAL_PACKAGE_NAME := CtsTvProviderTestCases
+
+# Tag this module as a cts_v2 test artifact
+LOCAL_COMPATIBILITY_SUITE := cts_v2
+
 
 LOCAL_SDK_VERSION := current
 
diff --git a/suite/cts/deviceTests/tvproviderperf/AndroidManifest.xml b/tests/tvprovider/AndroidManifest.xml
similarity index 86%
rename from suite/cts/deviceTests/tvproviderperf/AndroidManifest.xml
rename to tests/tvprovider/AndroidManifest.xml
index d345ab2..326d64b 100644
--- a/suite/cts/deviceTests/tvproviderperf/AndroidManifest.xml
+++ b/tests/tvprovider/AndroidManifest.xml
@@ -15,7 +15,7 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.cts.tvproviderperf">
+        package="android.tvprovider.cts">
 
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
     <uses-permission android:name="com.android.providers.tv.permission.READ_EPG_DATA" />
@@ -26,6 +26,6 @@
     </application>
 
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
-            android:targetPackage="com.android.cts.tvproviderperf"
-            android:label="TvProvider performance measurement" />
+            android:targetPackage="android.tvprovider.cts"
+            android:label="CTS tests for TV Provider tests" />
 </manifest>
diff --git a/tests/tvprovider/AndroidTest.xml b/tests/tvprovider/AndroidTest.xml
new file mode 100644
index 0000000..f92b37d
--- /dev/null
+++ b/tests/tvprovider/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for CTS TV Provider test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsTvProviderTestCases.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.tvprovider.cts" />
+    </test>
+</configuration>
diff --git a/suite/cts/deviceTests/tvproviderperf/src/com/android/cts/tvproviderperf/TvProviderPerfTest.java b/tests/tvprovider/src/android/tvprovider/cts/TvProviderPerfTest.java
similarity index 99%
rename from suite/cts/deviceTests/tvproviderperf/src/com/android/cts/tvproviderperf/TvProviderPerfTest.java
rename to tests/tvprovider/src/android/tvprovider/cts/TvProviderPerfTest.java
index cb56755..dd8b2f9 100644
--- a/suite/cts/deviceTests/tvproviderperf/src/com/android/cts/tvproviderperf/TvProviderPerfTest.java
+++ b/tests/tvprovider/src/android/tvprovider/cts/TvProviderPerfTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.cts.tvproviderperf;
+package android.tvprovider.cts;
 
 import android.content.ComponentName;
 import android.content.ContentProviderOperation;
diff --git a/tools/cts-device-info/AndroidTest.xml b/tools/cts-device-info/AndroidTest.xml
deleted file mode 100644
index dd750cf..0000000
--- a/tools/cts-device-info/AndroidTest.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<configuration description="Config for CTS Extensible Device Info Collector">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
-        <option name="cleanup-apks" value="true" />
-        <option name="test-file-name" value="CtsDeviceInfo.apk" />
-    </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-        <option name="run-command" value="rm /sdcard/device-info-files" />
-    </target_preparer>
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ResultFilePuller">
-        <option name="src-dir" value="/sdcard/device-info-files/"/>
-        <option name="dest-dir" value="device-info-files/"/>
-    </target_preparer>
-    <test class="com.android.tradefed.testtype.InstrumentationTest" >
-        <!-- TODO(agathaman): Remove when b/23488971 is closed -->
-        <option name="rerun" value="false" />
-        <option name="package" value="com.android.compatibility.common.deviceinfo" />
-        <option name="runner" value="com.android.compatibility.common.deviceinfo.DeviceInfoInstrument" />
-    </test>
-</configuration>
diff --git a/tools/cts-device-info/src/com/android/cts/deviceinfo/SampleDeviceInfo.java b/tools/cts-device-info/src/com/android/cts/deviceinfo/SampleDeviceInfo.java
index 2bd5959..a645585 100644
--- a/tools/cts-device-info/src/com/android/cts/deviceinfo/SampleDeviceInfo.java
+++ b/tools/cts-device-info/src/com/android/cts/deviceinfo/SampleDeviceInfo.java
@@ -17,17 +17,12 @@
 
 import android.os.Bundle;
 
-import com.android.compatibility.common.deviceinfo.DeviceInfoActivity;
+import com.android.compatibility.common.deviceinfo.DeviceInfo;
 
 /**
  * Sample device info collector.
  */
-public class SampleDeviceInfo extends DeviceInfoActivity {
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-    }
+public class SampleDeviceInfo extends DeviceInfo {
 
     @Override
     protected void collectDeviceInfo() {
diff --git a/tools/cts-preconditions/src/com/android/preconditions/cts/PreconditionsTest.java b/tools/cts-preconditions/src/com/android/preconditions/cts/PreconditionsTest.java
index 7c99e0b..b3162b9 100644
--- a/tools/cts-preconditions/src/com/android/preconditions/cts/PreconditionsTest.java
+++ b/tools/cts-preconditions/src/com/android/preconditions/cts/PreconditionsTest.java
@@ -18,6 +18,7 @@
 import android.content.Context;
 import android.test.AndroidTestCase;
 
+import com.android.compatibility.common.preconditions.ExternalStorageHelper;
 import com.android.compatibility.common.preconditions.ScreenLockHelper;
 
 /**
@@ -34,4 +35,15 @@
                 ScreenLockHelper.isDeviceSecure(this.getContext()));
     }
 
+    /**
+     * Test if device has accessible external storage
+     * @throws Exception
+     */
+    public void testExternalStoragePresent() throws Exception {
+        assertTrue("Device must have external storage mounted in order to run CTS",
+                ExternalStorageHelper.isExternalStorageReadable());
+        assertTrue("Device external storage must be writable in order to run CTS",
+                ExternalStorageHelper.isExternalStorageWritable());
+    }
+
 }
diff --git a/tools/cts-tradefed/res/config/cts.xml b/tools/cts-tradefed/res/config/cts.xml
index dba91e1..4c2f5f3 100644
--- a/tools/cts-tradefed/res/config/cts.xml
+++ b/tools/cts-tradefed/res/config/cts.xml
@@ -25,21 +25,21 @@
     -->
     <option name="compatibility-test:plan" value="cts" />
 
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.SettingsTask">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.SettingsPreparer">
         <option name="device-setting" value="install_non_market_apps"/>
         <option name="setting-type" value="secure"/>
         <option name="set-value" value="1"/> <!-- Installs from non-market apps allowed -->
     </target_preparer>
 
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.SettingsTask">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.SettingsPreparer">
         <option name="device-setting" value="stay_on_while_plugged_in"/>
         <option name="setting-type" value="global"/>
         <!-- The following values encode the conditions in which the device stays awake -->
-        <option name="set-value" value="2"/> <!-- Stay awake when charging via USB only -->
-        <!-- other acceptable values for CTS include:
-                - "3" - Stay awake when charging via USB or AC
-                - "6" - Stay awake when charging via USB or Wireless
-                - "7" - Stay awkae when charging via USB or AC or Wireless -->
+        <option name="expected-values" value="2" /> <!-- Stay awake when charging via USB only -->
+        <option name="expected-values" value="3" /> <!-- Stay awake when charging via USB or AC -->
+        <option name="expected-values" value="6" /> <!-- Stay awake when charging via USB or Wireless -->
+        <option name="expected-values" value="7" /> <!-- Stay awake when charging via USB or AC or Wireless -->
+        <option name="set-value" value="2"/> 
     </target_preparer>
 
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.BuildCheck">
@@ -52,6 +52,17 @@
         <option name="package" value="com.android.preconditions.cts"/>
     </target_preparer>
 
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="run-command" value="rm -rf /sdcard/device-info-files" />
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DeviceInfoCollector">
+        <option name="apk" value="CtsDeviceInfo.apk"/>
+        <option name="package" value="com.android.compatibility.common.deviceinfo"/>
+        <option name="src-dir" value="/sdcard/device-info-files/"/>
+        <option name="dest-dir" value="device-info-files/"/>
+    </target_preparer>
+
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.LocaleCheck">
         <option name="expected-locale" value="en-US"/> <!-- Device locale must be US English -->
     </target_preparer>
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/device/DeviceInfoCollector.java b/tools/tradefed-host/src/com/android/cts/tradefed/device/DeviceInfoCollector.java
index 6dee016..0ab70a7 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/device/DeviceInfoCollector.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/device/DeviceInfoCollector.java
@@ -48,7 +48,7 @@
     public static final String EXTENDED_APP_PACKAGE_NAME =
             "com.android.compatibility.common.deviceinfo";
     private static final String EXTENDED_INSTRUMENTATION_NAME =
-            "com.android.compatibility.common.deviceinfo.DeviceInfoInstrument";
+            "android.support.test.runner.AndroidJUnitRunner";
     private static final String DEVICE_INFO_FILES = "device-info-files";
 
     public static final Set<String> IDS = new HashSet<String>();
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsTestLogReporter.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsTestLogReporter.java
index 71eb8f5..785bb60 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsTestLogReporter.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsTestLogReporter.java
@@ -84,6 +84,9 @@
      */
     @Override
     public void testStarted(TestIdentifier test) {
+        if (mIsExtendedDeviceInfoRun) {
+            return;
+        }
         mCurrentPkgResult.insertTest(test);
     }
 
@@ -92,6 +95,9 @@
      */
     @Override
     public void testFailed(TestIdentifier test, String trace) {
+        if (mIsExtendedDeviceInfoRun) {
+            return;
+        }
         mCurrentPkgResult.reportTestFailure(test, CtsTestStatus.FAIL, trace);
     }
 
@@ -100,6 +106,9 @@
      */
     @Override
     public void testAssumptionFailure(TestIdentifier test, String trace) {
+        if (mIsExtendedDeviceInfoRun) {
+            return;
+        }
         // TODO: do something different here?
         mCurrentPkgResult.reportTestFailure(test, CtsTestStatus.FAIL, trace);
     }
@@ -109,6 +118,9 @@
      */
     @Override
     public void testEnded(TestIdentifier test, Map<String, String> testMetrics) {
+        if (mIsExtendedDeviceInfoRun) {
+            return;
+        }
         mCurrentPkgResult.reportTestEnded(test, testMetrics);
         Test result = mCurrentPkgResult.findTest(test);
         String stack = result.getStackTrace() == null ? "" : "\n" + result.getStackTrace();
@@ -121,6 +133,9 @@
      */
     @Override
     public void invocationEnded(long elapsedTime) {
+        if (mIsExtendedDeviceInfoRun) {
+            return;
+        }
         // display the results of the last completed run
         if (mCurrentPkgResult != null) {
             logCompleteRun(mCurrentPkgResult);
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/targetprep/CtsRootDeviceSetup.java b/tools/tradefed-host/src/com/android/cts/tradefed/targetprep/CtsRootDeviceSetup.java
index 0e768e2..f75a99e 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/targetprep/CtsRootDeviceSetup.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/targetprep/CtsRootDeviceSetup.java
@@ -41,7 +41,7 @@
  */
 public class CtsRootDeviceSetup implements ITargetPreparer {
 
-    private static final String DEVICE_ADMIN_APK_FILE_NAME = "CtsDeviceAdmin.apk";
+    private static final String DEVICE_ADMIN_APK_FILE_NAME = "CtsAdminApp.apk";
 
     /**
      * {@inheritDoc}
diff --git a/tools/utils/buildCts.py b/tools/utils/buildCts.py
index 9e0a260..22f2f01 100755
--- a/tools/utils/buildCts.py
+++ b/tools/utils/buildCts.py
@@ -362,6 +362,7 @@
       'android.rsg' : [],
       'android.sax' : [],
       'android.signature' : [],
+      'android.simplecpu' : [],
       'android.speech' : [],
       'android.tests.appsecurity' : [],
       'android.text' : [],
@@ -372,7 +373,6 @@
       'com.android.cts.jank' : [],
       'com.android.cts.jank2' : [],
       'com.android.cts.opengl' : [],
-      'com.android.cts.simplecpu' : [],
       'com.android.cts.ui' : [],
       'com.android.cts.uihost' : [],
       'com.android.cts.videoperf' : [],
diff --git a/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java b/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java
index 0e31884..a25fce2 100644
--- a/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java
+++ b/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java
@@ -19,6 +19,7 @@
 import com.android.dex.util.FileUtils;
 
 import dot.junit.AllTests;
+import util.build.BuildStep.BuildFile;
 
 import junit.framework.TestCase;
 import junit.framework.TestResult;
@@ -56,6 +57,8 @@
  */
 public class BuildDalvikSuite {
 
+    public static final String TARGET_MAIN_FILE = "mains.jar";
+
     public static boolean DEBUG = true;
 
     private static String JAVASRC_FOLDER = "";
@@ -257,14 +260,10 @@
         final String targetCoreJarPath = String.format("%s/dot/junit/dexcore.jar",
                 TARGET_JAR_ROOT_PATH);
 
-        // push class with Main jar.
-        String mjar = "Main_" + method + ".jar";
-        String pPath = pName.replaceAll("\\.","/");
-        String mainJar = String.format("%s/%s/%s", TARGET_JAR_ROOT_PATH, pPath, mjar);
+        String mainsJar = String.format("%s/%s", TARGET_JAR_ROOT_PATH, TARGET_MAIN_FILE);
 
-        String cp = String.format("%s:%s", targetCoreJarPath, mainJar);
+        String cp = String.format("%s:%s", targetCoreJarPath, mainsJar);
         for (String depFqcn : dependentTestClassNames) {
-            int lastDotPos = depFqcn.lastIndexOf('.');
             String sourceName = depFqcn.replaceAll("\\.", "/") + ".jar";
             String targetName= String.format("%s/%s", TARGET_JAR_ROOT_PATH,
                     sourceName);
@@ -289,7 +288,13 @@
         hostJunitBuildStep = new JavacBuildStep(
             HOSTJUNIT_CLASSES_OUTPUT_FOLDER, CLASS_PATH);
 
-        srcBuildStep = new JavacBuildStep(CLASSES_OUTPUT_FOLDER, CLASS_PATH);
+        String mainsJar = OUTPUT_FOLDER + File.separator + TARGET_MAIN_FILE;
+        if (useJack) {
+            srcBuildStep = new JackBuildStep(mainsJar,
+            CLASS_PATH);
+        } else {
+            srcBuildStep = new JavacBuildStep(CLASSES_OUTPUT_FOLDER, CLASS_PATH);
+        }
 
         for (Entry<String, List<String>> entry : map.entrySet()) {
 
@@ -355,23 +360,7 @@
                 File sourceFile = getFileFromPackage(pName, method);
 
                 writeToFile(sourceFile, content);
-                if (useJack) {
-                    File jackFile = new File(CLASSES_OUTPUT_FOLDER + "/" +
-                            getFileName(pName, method, ".jack"));
-                    JackBuildStep step = new JackBuildStep(jackFile.getAbsolutePath(), CLASS_PATH);
-                    step.addSourceFile(sourceFile.getAbsolutePath());
-                    if (!step.build()) {
-                        System.out.println("main src dalvik-cts-buildutil build step failed");
-                        System.exit(1);
-                    }
-                } else {
-                    srcBuildStep.addSourceFile(sourceFile.getAbsolutePath());
-                }
-
-                BuildStep dexBuildStep = generateDexBuildStep(
-                        CLASSES_OUTPUT_FOLDER, getFileName(pName, method, ""), null);
-                targets.add(dexBuildStep);
-
+                srcBuildStep.addSourceFile(sourceFile.getAbsolutePath());
 
                 // prepare the entry in the data file for the bash script.
                 // e.g.
@@ -459,6 +448,15 @@
 
         }
 
+        if (!useJack) {
+          DxBuildStep dexBuildStep = new DxBuildStep(
+              new BuildStep.BuildFile(new File(CLASSES_OUTPUT_FOLDER)),
+              new BuildStep.BuildFile(new File(mainsJar)),
+              false);
+
+          targets.add(dexBuildStep);
+        }
+
         // write latest HOSTJUNIT generated file.
         flushHostJunitFile();
 
@@ -471,12 +469,11 @@
             System.exit(1);
         }
 
-        if (!useJack) {
-            if (!srcBuildStep.build()) {
-                System.out.println("main src dalvik-cts-buildutil build step failed");
-                System.exit(1);
-            }
+        if (!srcBuildStep.build()) {
+            System.out.println("main src dalvik-cts-buildutil build step failed");
+            System.exit(1);
         }
+
         for (BuildStep buildStep : targets) {
             if (!buildStep.build()) {
                 System.out.println("building failed. buildStep: " +
@@ -541,15 +538,17 @@
 
         File srcFile = new File(sourceFolder, fileName + ".java");
         if (srcFile.exists()) {
-            JackBuildStep jackBuildStep = null;
+            BuildStep dexBuildStep;
             if (useJack) {
-                jackBuildStep = new JackBuildStep(
-                        COMPILED_CLASSES_FOLDER + File.separator + fileName + ".jack",
+                JackBuildStep jackBuildStep = new JackBuildStep(
+                    OUTPUT_FOLDER + File.separator + fileName + ".jar",
                         CLASS_PATH);
                 jackBuildStep.addSourceFile(srcFile.getAbsolutePath());
+                dexBuildStep = jackBuildStep;
+            } else {
+              dexBuildStep = generateDexBuildStep(
+                COMPILED_CLASSES_FOLDER, fileName, null);
             }
-            BuildStep dexBuildStep = generateDexBuildStep(
-                COMPILED_CLASSES_FOLDER, fileName, jackBuildStep);
             targets.add(dexBuildStep);
             return;
         }
diff --git a/tools/vm-tests-tf/src/util/build/BuildStep.java b/tools/vm-tests-tf/src/util/build/BuildStep.java
index dbc6bca..e3349bd 100644
--- a/tools/vm-tests-tf/src/util/build/BuildStep.java
+++ b/tools/vm-tests-tf/src/util/build/BuildStep.java
@@ -37,6 +37,10 @@
             this.folder = new File(folder);
             this.fileName = new File(this.folder, fileName);
         }
+        BuildFile(File file) {
+          this.folder = file.getParentFile();
+          this.fileName = file;
+      }
 
         String getPath() {
             return fileName.getAbsolutePath();
@@ -70,7 +74,8 @@
         this.outputFile = outputFile;
     }
 
-    BuildStep() {
+    BuildStep(File output) {
+        this.outputFile = new BuildFile(output);
     }
 
     private Set<BuildStep> children;
@@ -117,8 +122,7 @@
     }
 
     public int compareTo(BuildStep o) {
-        return (inputFile == o.inputFile ? 0 : (inputFile != null
-                ? (o.inputFile != null ? inputFile.getPath().compareTo(
-                        o.inputFile.getPath()) : 1) : -1));
+        return (outputFile == o.outputFile ? 0 : outputFile.getPath().compareTo(
+                        o.outputFile.getPath()));
     }
 }
diff --git a/tools/vm-tests-tf/src/util/build/JackBuildStep.java b/tools/vm-tests-tf/src/util/build/JackBuildStep.java
index dabef17..061ff07 100644
--- a/tools/vm-tests-tf/src/util/build/JackBuildStep.java
+++ b/tools/vm-tests-tf/src/util/build/JackBuildStep.java
@@ -18,10 +18,14 @@
 
 import com.android.jack.CLILogConfiguration;
 import com.android.jack.CLILogConfiguration.LogConfigurationException;
+
+import util.build.BuildStep.BuildFile;
+
 import com.android.jack.Jack;
 import com.android.jack.Main;
 import com.android.jack.Options;
 import java.io.File;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -42,6 +46,7 @@
     private final Set<String> sourceFiles = new HashSet<String>();
 
     public JackBuildStep(String destPath, String classPath) {
+        super(new File(destPath));
         this.destPath = destPath;
         this.classPath = classPath;
     }
@@ -64,23 +69,44 @@
                         + outDir.getAbsolutePath());
                 return false;
             }
-            List<String> commandLine = new ArrayList(4 + sourceFiles.size());
-            commandLine.add("--verbose");
-            commandLine.add("error");
-            commandLine.add("--classpath");
-            commandLine.add(classPath);
-            commandLine.add("--output-jack");
-            commandLine.add(destPath);
-            commandLine.addAll(sourceFiles);
+
+            File tmpOutDir = new File(outDir, outputFile.fileName.getName() + ".dexTmp");
+            if (!tmpOutDir.exists() && !tmpOutDir.mkdirs()) {
+                System.err.println("failed to create temp dir: "
+                        + tmpOutDir.getAbsolutePath());
+                return false;
+            }
+            File tmpDex = new File(tmpOutDir, "classes.dex");
 
             try {
+                List<String> commandLine = new ArrayList<String>(6 + sourceFiles.size());
+                commandLine.add("--verbose");
+                commandLine.add("error");
+                commandLine.add("--classpath");
+                commandLine.add(classPath);
+                commandLine.add("--output-dex");
+                commandLine.add(tmpOutDir.getAbsolutePath());
+                commandLine.addAll(sourceFiles);
+
                 Options options = Main.parseCommandLine(commandLine);
                 Jack.checkAndRun(options);
+
+                JarBuildStep jarStep = new JarBuildStep(
+                    new BuildFile(tmpDex),
+                    "classes.dex",
+                    outputFile,
+                    /* deleteInputFileAfterBuild = */ true);
+                if (!jarStep.build()) {
+                  throw new IOException("Failed to make jar: " + outputFile.getPath());
+                }
+                return true;
             } catch (Throwable ex) {
                 ex.printStackTrace();
                 return false;
+            } finally {
+              tmpDex.delete();
+              tmpOutDir.delete();
             }
-            return true;
         }
         return false;
     }
diff --git a/tools/vm-tests-tf/src/util/build/JackDexBuildStep.java b/tools/vm-tests-tf/src/util/build/JackDexBuildStep.java
index 304eaa0..8734cf0 100644
--- a/tools/vm-tests-tf/src/util/build/JackDexBuildStep.java
+++ b/tools/vm-tests-tf/src/util/build/JackDexBuildStep.java
@@ -21,6 +21,7 @@
 import com.android.jack.Options;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -41,7 +42,7 @@
             String outputFilePath = outputFile.fileName.getAbsolutePath();
             if (outputFilePath.endsWith(".dex")) {
               throw new AssertionError(
-                  "DexBuildStep does not support dex output outside of an archive");
+                  "JackDexBuildStep does not support dex output outside of an archive");
             }
 
             File outDir = outputFile.fileName.getParentFile();
@@ -51,17 +52,34 @@
                 return false;
             }
 
-            List<String> commandLine = new ArrayList<String>(4);
-            commandLine.add("--verbose");
-            commandLine.add("error");
-            commandLine.add("--output-dex-zip");
-            commandLine.add(outputFilePath);
-            commandLine.add("--import");
-            commandLine.add(inputFile.fileName.getAbsolutePath());
+            File tmpOutDir = new File(outDir, outputFile.fileName.getName() + ".dexTmp");
+            if (!tmpOutDir.exists() && !tmpOutDir.mkdirs()) {
+                System.err.println("failed to create temp dir: "
+                        + tmpOutDir.getAbsolutePath());
+                return false;
+            }
+            File tmpDex = new File(tmpOutDir, "classes.dex");
 
             try {
-               Options options = Main.parseCommandLine(commandLine);
-               Jack.checkAndRun(options);
+                List<String> commandLine = new ArrayList<String>(4);
+                commandLine.add("--verbose");
+                commandLine.add("error");
+                commandLine.add("--output-dex");
+                commandLine.add(tmpOutDir.getAbsolutePath());
+                commandLine.add("--import");
+                commandLine.add(inputFile.fileName.getAbsolutePath());
+
+                Options options = Main.parseCommandLine(commandLine);
+                Jack.checkAndRun(options);
+
+                JarBuildStep jarStep = new JarBuildStep(
+                    new BuildFile(tmpDex),
+                    "classes.dex",
+                    outputFile,
+                    /* deleteInputFileAfterBuild = */ true);
+                if (!jarStep.build()) {
+                  throw new IOException("Failed to make jar: " + outputFile.getPath());
+                }
                 if (deleteInputFileAfterBuild) {
                     inputFile.fileName.delete();
                 }
@@ -71,6 +89,9 @@
                         + inputFile.fileName.getAbsolutePath() + " to "
                         + outputFile.fileName.getAbsolutePath());
                 ex.printStackTrace();
+            } finally {
+              tmpDex.delete();
+              tmpOutDir.delete();
             }
         }
         return false;
diff --git a/tools/vm-tests-tf/src/util/build/JavacBuildStep.java b/tools/vm-tests-tf/src/util/build/JavacBuildStep.java
index a07bb69..a1cde1f 100644
--- a/tools/vm-tests-tf/src/util/build/JavacBuildStep.java
+++ b/tools/vm-tests-tf/src/util/build/JavacBuildStep.java
@@ -29,6 +29,7 @@
     private final String classPath;
     private final Set<String> sourceFiles = new HashSet<String>();
     public JavacBuildStep(String destPath, String classPath) {
+        super(new File(destPath));
         this.destPath = destPath;
         this.classPath = classPath;
     }
diff --git a/tools/vm-tests-tf/src/util/build/SourceBuildStep.java b/tools/vm-tests-tf/src/util/build/SourceBuildStep.java
index 4a68a05..9f9142d 100644
--- a/tools/vm-tests-tf/src/util/build/SourceBuildStep.java
+++ b/tools/vm-tests-tf/src/util/build/SourceBuildStep.java
@@ -16,8 +16,14 @@
 
 package util.build;
 
+import java.io.File;
+
 public abstract class SourceBuildStep extends BuildStep {
 
+  SourceBuildStep(File destFile) {
+    super(destFile);
+  }
+
   public abstract void addSourceFile(String sourceFile);
 
 }