Move android.test classes from core/java to legacy-test/src

(cherry picked from 2395179afb2ea957a9ba66404021c14160361611)

Bug: 30188076
Test: make checkbuild
Merged-In: Ifa291909fcf47da788627b496bd72f54efd78ed7
Change-Id: Ie20dceb9f89df245ed6da5fc2fb06185bd7b104b
diff --git a/legacy-test/Android.mk b/legacy-test/Android.mk
index 0011002..7bab189 100644
--- a/legacy-test/Android.mk
+++ b/legacy-test/Android.mk
@@ -21,10 +21,11 @@
 # This contains the junit.framework classes that were in Android API level 25.
 include $(CLEAR_VARS)
 
-LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_STATIC_JAVA_LIBRARIES := core-junit-static
-
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_MODULE := legacy-test
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVA_LIBRARIES := core-oj core-libart framework
+LOCAL_STATIC_JAVA_LIBRARIES := core-junit-static
 
 include $(BUILD_JAVA_LIBRARY)
 
@@ -34,7 +35,7 @@
 # This contains the android.test.PerformanceTestCase class only
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES := ../core/java/android/test/PerformanceTestCase.java
+LOCAL_SRC_FILES := src/android/test/PerformanceTestCase.java
 LOCAL_MODULE := legacy-performance-test-hostdex
 
 include $(BUILD_HOST_DALVIK_JAVA_LIBRARY)
diff --git a/legacy-test/src/android/test/AndroidTestCase.java b/legacy-test/src/android/test/AndroidTestCase.java
new file mode 100644
index 0000000..1e6bd9c
--- /dev/null
+++ b/legacy-test/src/android/test/AndroidTestCase.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.test;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.test.suitebuilder.annotation.Suppress;
+
+import junit.framework.TestCase;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+/**
+ * Extend this if you need to access Resources or other things that depend on Activity Context.
+ *
+ * @deprecated Use
+ * <a href="{@docRoot}reference/android/support/test/InstrumentationRegistry.html">
+ * InstrumentationRegistry</a> instead. New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
+ */
+@Deprecated
+public class AndroidTestCase extends TestCase {
+
+    protected Context mContext;
+    private Context mTestContext;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    @Suppress
+    public void testAndroidTestCaseSetupProperly() {
+        assertNotNull("Context is null. setContext should be called before tests are run",
+                mContext);
+    }
+
+    public void setContext(Context context) {
+        mContext = context;
+    }
+
+    public Context getContext() {
+        return mContext;
+    }
+
+    /**
+     * Test context can be used to access resources from the test's own package
+     * as opposed to the resources from the test target package. Access to the
+     * latter is provided by the context set with the {@link #setContext}
+     * method.
+     *
+     * @hide
+     */
+    public void setTestContext(Context context) {
+        mTestContext = context;
+    }
+
+    /**
+     * @hide
+     */
+    public Context getTestContext() {
+        return mTestContext;
+    }
+
+    /**
+     * Asserts that launching a given activity is protected by a particular permission by
+     * attempting to start the activity and validating that a {@link SecurityException}
+     * is thrown that mentions the permission in its error message.
+     *
+     * Note that an instrumentation isn't needed because all we are looking for is a security error
+     * and we don't need to wait for the activity to launch and get a handle to the activity.
+     *
+     * @param packageName The package name of the activity to launch.
+     * @param className The class of the activity to launch.
+     * @param permission The name of the permission.
+     */
+    public void assertActivityRequiresPermission(
+            String packageName, String className, String permission) {
+        final Intent intent = new Intent();
+        intent.setClassName(packageName, className);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+        try {
+            getContext().startActivity(intent);
+            fail("expected security exception for " + permission);
+        } catch (SecurityException expected) {
+            assertNotNull("security exception's error message.", expected.getMessage());
+            assertTrue("error message should contain " + permission + ".",
+                    expected.getMessage().contains(permission));
+        }
+    }
+
+
+    /**
+     * Asserts that reading from the content uri requires a particular permission by querying the
+     * uri and ensuring a {@link SecurityException} is thrown mentioning the particular permission.
+     *
+     * @param uri The uri that requires a permission to query.
+     * @param permission The permission that should be required.
+     */
+    public void assertReadingContentUriRequiresPermission(Uri uri, String permission) {
+        try {
+            getContext().getContentResolver().query(uri, null, null, null, null);
+            fail("expected SecurityException requiring " + permission);
+        } catch (SecurityException expected) {
+            assertNotNull("security exception's error message.", expected.getMessage());
+            assertTrue("error message should contain " + permission + ".",
+                    expected.getMessage().contains(permission));
+        }
+    }
+
+    /**
+     * Asserts that writing to the content uri requires a particular permission by inserting into
+     * the uri and ensuring a {@link SecurityException} is thrown mentioning the particular
+     * permission.
+     *
+     * @param uri The uri that requires a permission to query.
+     * @param permission The permission that should be required.
+     */
+    public void assertWritingContentUriRequiresPermission(Uri uri, String permission) {
+        try {
+            getContext().getContentResolver().insert(uri, new ContentValues());
+            fail("expected SecurityException requiring " + permission);
+        } catch (SecurityException expected) {
+            assertNotNull("security exception's error message.", expected.getMessage());
+            assertTrue("error message should contain \"" + permission + "\". Got: \""
+                    + expected.getMessage() + "\".",
+                    expected.getMessage().contains(permission));
+        }
+    }
+
+    /**
+     * This function is called by various TestCase implementations, at tearDown() time, in order
+     * to scrub out any class variables.  This protects against memory leaks in the case where a
+     * test case creates a non-static inner class (thus referencing the test case) and gives it to
+     * someone else to hold onto.
+     *
+     * @param testCaseClass The class of the derived TestCase implementation.
+     *
+     * @throws IllegalAccessException
+     */
+    protected void scrubClass(final Class<?> testCaseClass)
+            throws IllegalAccessException {
+        final Field[] fields = getClass().getDeclaredFields();
+        for (Field field : fields) {
+            if (!field.getType().isPrimitive() &&
+                    !Modifier.isStatic(field.getModifiers())) {
+                try {
+                    field.setAccessible(true);
+                    field.set(this, null);
+                } catch (Exception e) {
+                    android.util.Log.d("TestCase", "Error: Could not nullify field!");
+                }
+
+                if (field.get(this) != null) {
+                    android.util.Log.d("TestCase", "Error: Could not nullify field!");
+                }
+            }
+        }
+    }
+}
diff --git a/legacy-test/src/android/test/FlakyTest.java b/legacy-test/src/android/test/FlakyTest.java
new file mode 100644
index 0000000..4e5c4e3
--- /dev/null
+++ b/legacy-test/src/android/test/FlakyTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.test;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+/**
+ * This annotation can be used on an {@link android.test.InstrumentationTestCase}'s
+ * test methods. When the annotation is present, the test method is re-executed if
+ * the test fails. The total number of executions is specified by the tolerance and
+ * defaults to 1.
+ *
+ * @deprecated Use
+ * <a href="{@docRoot}reference/android/support/test/filters/FlakyTest.html">
+ * FlakyTest</a> instead. New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
+ */
+@Deprecated
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface FlakyTest {
+    /**
+     * Indicates how many times a test can run and fail before being reported
+     * as a failed test. If the tolerance factor is less than 1, the test runs
+     * only once.
+     *
+     * @return The total number of allowed run, the default is 1.
+     */
+    int tolerance() default 1;
+}
diff --git a/legacy-test/src/android/test/InstrumentationTestCase.java b/legacy-test/src/android/test/InstrumentationTestCase.java
new file mode 100644
index 0000000..6b79314
--- /dev/null
+++ b/legacy-test/src/android/test/InstrumentationTestCase.java
@@ -0,0 +1,369 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.test;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.KeyEvent;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import junit.framework.TestCase;
+
+/**
+ * A test case that has access to {@link Instrumentation}.
+ *
+ * @deprecated Use
+ * <a href="{@docRoot}reference/android/support/test/InstrumentationRegistry.html">
+ * InstrumentationRegistry</a> instead. New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
+ */
+@Deprecated
+public class InstrumentationTestCase extends TestCase {
+
+    private Instrumentation mInstrumentation;
+
+    /**
+     * Injects instrumentation into this test case. This method is
+     * called by the test runner during test setup.
+     *
+     * @param instrumentation the instrumentation to use with this instance
+     */
+    public void injectInstrumentation(Instrumentation instrumentation) {
+        mInstrumentation = instrumentation;
+    }
+
+    /**
+     * Injects instrumentation into this test case. This method is
+     * called by the test runner during test setup.
+     *
+     * @param instrumentation the instrumentation to use with this instance
+     *
+     * @deprecated Incorrect spelling,
+     * use {@link #injectInstrumentation(android.app.Instrumentation)} instead.
+     */
+    @Deprecated
+    public void injectInsrumentation(Instrumentation instrumentation) {
+        injectInstrumentation(instrumentation);
+    }
+
+    /**
+     * Inheritors can access the instrumentation using this.
+     * @return instrumentation
+     */
+    public Instrumentation getInstrumentation() {
+        return mInstrumentation;
+    }
+
+    /**
+     * Utility method for launching an activity.  
+     * 
+     * <p>The {@link Intent} used to launch the Activity is:
+     *  action = {@link Intent#ACTION_MAIN}
+     *  extras = null, unless a custom bundle is provided here
+     * All other fields are null or empty.
+     * 
+     * <p><b>NOTE:</b> The parameter <i>pkg</i> must refer to the package identifier of the
+     * package hosting the activity to be launched, which is specified in the AndroidManifest.xml
+     * file.  This is not necessarily the same as the java package name.
+     *
+     * @param pkg The package hosting the activity to be launched.
+     * @param activityCls The activity class to launch.
+     * @param extras Optional extra stuff to pass to the activity.
+     * @return The activity, or null if non launched.
+     */
+    public final <T extends Activity> T launchActivity(
+            String pkg,
+            Class<T> activityCls,
+            Bundle extras) {
+        Intent intent = new Intent(Intent.ACTION_MAIN);
+        if (extras != null) {
+            intent.putExtras(extras);
+        }
+        return launchActivityWithIntent(pkg, activityCls, intent);
+    }
+
+    /**
+     * Utility method for launching an activity with a specific Intent.
+     * 
+     * <p><b>NOTE:</b> The parameter <i>pkg</i> must refer to the package identifier of the
+     * package hosting the activity to be launched, which is specified in the AndroidManifest.xml
+     * file.  This is not necessarily the same as the java package name.
+     *
+     * @param pkg The package hosting the activity to be launched.
+     * @param activityCls The activity class to launch.
+     * @param intent The intent to launch with
+     * @return The activity, or null if non launched.
+     */
+    @SuppressWarnings("unchecked")
+    public final <T extends Activity> T launchActivityWithIntent(
+            String pkg,
+            Class<T> activityCls,
+            Intent intent) {
+        intent.setClassName(pkg, activityCls.getName());
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        T activity = (T) getInstrumentation().startActivitySync(intent);
+        getInstrumentation().waitForIdleSync();
+        return activity;
+    }
+    
+    /**
+     * Helper for running portions of a test on the UI thread.
+     * 
+     * Note, in most cases it is simpler to annotate the test method with 
+     * {@link android.test.UiThreadTest}, which will run the entire test method on the UI thread.
+     * Use this method if you need to switch in and out of the UI thread to perform your test.
+     * 
+     * @param r runnable containing test code in the {@link Runnable#run()} method
+     */
+    public void runTestOnUiThread(final Runnable r) throws Throwable {
+        final Throwable[] exceptions = new Throwable[1];
+        getInstrumentation().runOnMainSync(new Runnable() {
+            public void run() {
+                try {
+                    r.run();
+                } catch (Throwable throwable) {
+                    exceptions[0] = throwable;
+                }
+            }
+        });
+        if (exceptions[0] != null) {
+            throw exceptions[0];
+        }
+    }
+
+    /**
+     * Runs the current unit test. If the unit test is annotated with
+     * {@link android.test.UiThreadTest}, the test is run on the UI thread.
+     */
+    @Override
+    protected void runTest() throws Throwable {
+        String fName = getName();
+        assertNotNull(fName);
+        Method method = null;
+        try {
+            // use getMethod to get all public inherited
+            // methods. getDeclaredMethods returns all
+            // methods of this class but excludes the
+            // inherited ones.
+            method = getClass().getMethod(fName, (Class[]) null);
+        } catch (NoSuchMethodException e) {
+            fail("Method \""+fName+"\" not found");
+        }
+
+        if (!Modifier.isPublic(method.getModifiers())) {
+            fail("Method \""+fName+"\" should be public");
+        }
+
+        int runCount = 1;
+        boolean isRepetitive = false;
+        if (method.isAnnotationPresent(FlakyTest.class)) {
+            runCount = method.getAnnotation(FlakyTest.class).tolerance();
+        } else if (method.isAnnotationPresent(RepetitiveTest.class)) {
+            runCount = method.getAnnotation(RepetitiveTest.class).numIterations();
+            isRepetitive = true;
+        }
+
+        if (method.isAnnotationPresent(UiThreadTest.class)) {
+            final int tolerance = runCount;
+            final boolean repetitive = isRepetitive;
+            final Method testMethod = method;
+            final Throwable[] exceptions = new Throwable[1];
+            getInstrumentation().runOnMainSync(new Runnable() {
+                public void run() {
+                    try {
+                        runMethod(testMethod, tolerance, repetitive);
+                    } catch (Throwable throwable) {
+                        exceptions[0] = throwable;
+                    }
+                }
+            });
+            if (exceptions[0] != null) {
+                throw exceptions[0];
+            }
+        } else {
+            runMethod(method, runCount, isRepetitive);
+        }
+    }
+
+    // For backwards-compatibility after adding isRepetitive
+    private void runMethod(Method runMethod, int tolerance) throws Throwable {
+        runMethod(runMethod, tolerance, false);
+    }
+
+    private void runMethod(Method runMethod, int tolerance, boolean isRepetitive) throws Throwable {
+        Throwable exception = null;
+
+        int runCount = 0;
+        do {
+            try {
+                runMethod.invoke(this, (Object[]) null);
+                exception = null;
+            } catch (InvocationTargetException e) {
+                e.fillInStackTrace();
+                exception = e.getTargetException();
+            } catch (IllegalAccessException e) {
+                e.fillInStackTrace();
+                exception = e;
+            } finally {
+                runCount++;
+                // Report current iteration number, if test is repetitive
+                if (isRepetitive) {
+                    Bundle iterations = new Bundle();
+                    iterations.putInt("currentiterations", runCount);
+                    getInstrumentation().sendStatus(2, iterations);
+                }
+            }
+        } while ((runCount < tolerance) && (isRepetitive || exception != null));
+
+        if (exception != null) {
+            throw exception;
+        }
+    }
+
+    /**
+     * Sends a series of key events through instrumentation and waits for idle. The sequence
+     * of keys is a string containing the key names as specified in KeyEvent, without the
+     * KEYCODE_ prefix. For instance: sendKeys("DPAD_LEFT A B C DPAD_CENTER"). Each key can
+     * be repeated by using the N* prefix. For instance, to send two KEYCODE_DPAD_LEFT, use
+     * the following: sendKeys("2*DPAD_LEFT").
+     *
+     * @param keysSequence The sequence of keys.
+     */
+    public void sendKeys(String keysSequence) {
+        final String[] keys = keysSequence.split(" ");
+        final int count = keys.length;
+
+        final Instrumentation instrumentation = getInstrumentation();
+
+        for (int i = 0; i < count; i++) {
+            String key = keys[i];
+            int repeater = key.indexOf('*');
+
+            int keyCount;
+            try {
+                keyCount = repeater == -1 ? 1 : Integer.parseInt(key.substring(0, repeater));
+            } catch (NumberFormatException e) {
+                Log.w("ActivityTestCase", "Invalid repeat count: " + key);
+                continue;
+            }
+
+            if (repeater != -1) {
+                key = key.substring(repeater + 1);
+            }
+
+            for (int j = 0; j < keyCount; j++) {
+                try {
+                    final Field keyCodeField = KeyEvent.class.getField("KEYCODE_" + key);
+                    final int keyCode = keyCodeField.getInt(null);
+                    try {
+                        instrumentation.sendKeyDownUpSync(keyCode);
+                    } catch (SecurityException e) {
+                        // Ignore security exceptions that are now thrown
+                        // when trying to send to another app, to retain
+                        // compatibility with existing tests.
+                    }
+                } catch (NoSuchFieldException e) {
+                    Log.w("ActivityTestCase", "Unknown keycode: KEYCODE_" + key);
+                    break;
+                } catch (IllegalAccessException e) {
+                    Log.w("ActivityTestCase", "Unknown keycode: KEYCODE_" + key);
+                    break;
+                }
+            }
+        }
+
+        instrumentation.waitForIdleSync();
+    }
+
+    /**
+     * Sends a series of key events through instrumentation and waits for idle. For instance:
+     * sendKeys(KEYCODE_DPAD_LEFT, KEYCODE_DPAD_CENTER).
+     *
+     * @param keys The series of key codes to send through instrumentation.
+     */
+    public void sendKeys(int... keys) {
+        final int count = keys.length;
+        final Instrumentation instrumentation = getInstrumentation();
+
+        for (int i = 0; i < count; i++) {
+            try {
+                instrumentation.sendKeyDownUpSync(keys[i]);
+            } catch (SecurityException e) {
+                // Ignore security exceptions that are now thrown
+                // when trying to send to another app, to retain
+                // compatibility with existing tests.
+            }
+        }
+
+        instrumentation.waitForIdleSync();
+    }
+
+    /**
+     * Sends a series of key events through instrumentation and waits for idle. Each key code
+     * must be preceded by the number of times the key code must be sent. For instance:
+     * sendRepeatedKeys(1, KEYCODE_DPAD_CENTER, 2, KEYCODE_DPAD_LEFT).
+     *
+     * @param keys The series of key repeats and codes to send through instrumentation.
+     */
+    public void sendRepeatedKeys(int... keys) {
+        final int count = keys.length;
+        if ((count & 0x1) == 0x1) {
+            throw new IllegalArgumentException("The size of the keys array must "
+                    + "be a multiple of 2");
+        }
+
+        final Instrumentation instrumentation = getInstrumentation();
+
+        for (int i = 0; i < count; i += 2) {
+            final int keyCount = keys[i];
+            final int keyCode = keys[i + 1];
+            for (int j = 0; j < keyCount; j++) {
+                try {
+                    instrumentation.sendKeyDownUpSync(keyCode);
+                } catch (SecurityException e) {
+                    // Ignore security exceptions that are now thrown
+                    // when trying to send to another app, to retain
+                    // compatibility with existing tests.
+                }
+            }
+        }
+
+        instrumentation.waitForIdleSync();
+    }
+    
+    /**
+     * Make sure all resources are cleaned up and garbage collected before moving on to the next
+     * test. Subclasses that override this method should make sure they call super.tearDown()
+     * at the end of the overriding method.
+     * 
+     * @throws Exception
+     */
+    @Override
+    protected void tearDown() throws Exception {
+        Runtime.getRuntime().gc();
+        Runtime.getRuntime().runFinalization();
+        Runtime.getRuntime().gc();
+        super.tearDown();
+    }
+}
\ No newline at end of file
diff --git a/legacy-test/src/android/test/InstrumentationTestSuite.java b/legacy-test/src/android/test/InstrumentationTestSuite.java
new file mode 100644
index 0000000..a53fa26
--- /dev/null
+++ b/legacy-test/src/android/test/InstrumentationTestSuite.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.test;
+
+import android.app.Instrumentation;
+
+import junit.framework.TestSuite;
+import junit.framework.Test;
+import junit.framework.TestResult;
+
+/**
+ * A {@link junit.framework.TestSuite} that injects {@link android.app.Instrumentation} into
+ * {@link InstrumentationTestCase} before running them.
+ *
+ * @deprecated Use
+ * <a href="{@docRoot}reference/android/support/test/InstrumentationRegistry.html">
+ * InstrumentationRegistry</a> instead. New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
+ */
+@Deprecated
+public class InstrumentationTestSuite extends TestSuite {
+
+    private final Instrumentation mInstrumentation;
+
+    /**
+     * @param instr The instrumentation that will be injected into each
+     *   test before running it.
+     */
+    public InstrumentationTestSuite(Instrumentation instr) {
+        mInstrumentation = instr;
+    }
+
+
+    public InstrumentationTestSuite(String name, Instrumentation instr) {
+        super(name);
+        mInstrumentation = instr;
+    }
+
+    /**
+     * @param theClass Inspected for methods starting with 'test'
+     * @param instr The instrumentation to inject into each test before
+     *   running.
+     */
+    public InstrumentationTestSuite(final Class theClass, Instrumentation instr) {
+        super(theClass);
+        mInstrumentation = instr;
+    }
+
+
+    @Override
+    public void addTestSuite(Class testClass) {
+        addTest(new InstrumentationTestSuite(testClass, mInstrumentation));
+    }
+
+
+    @Override
+    public void runTest(Test test, TestResult result) {
+
+        if (test instanceof InstrumentationTestCase) {
+            ((InstrumentationTestCase) test).injectInstrumentation(mInstrumentation);
+        }
+
+        // run the test as usual
+        super.runTest(test, result);
+    }
+}
diff --git a/legacy-test/src/android/test/PerformanceTestCase.java b/legacy-test/src/android/test/PerformanceTestCase.java
new file mode 100644
index 0000000..65bd4a4
--- /dev/null
+++ b/legacy-test/src/android/test/PerformanceTestCase.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.test;
+
+/**
+ * More complex interface performance for test cases.
+ *
+ * If you want your test to be used as a performance test, you must
+ * implement this interface.
+ */
+@Deprecated
+public interface PerformanceTestCase
+{
+    /**
+     * Callbacks for {@link PerformanceTestCase}.
+     */
+    public interface Intermediates
+    {
+        void setInternalIterations(int count);
+        void startTiming(boolean realTime);
+        void addIntermediate(String name);
+        void addIntermediate(String name, long timeInNS);
+        void finishTiming(boolean realTime);
+    }
+
+    /**
+     * Set up to begin performance tests. The 'intermediates' is a
+     * communication channel to send back intermediate performance numbers --
+     * if you use it, you will probably want to ensure your test is only
+     * executed once by returning 1.  Otherwise, return 0 to allow the test
+     * harness to decide the number of iterations.
+     *
+     * <p>If you return a non-zero iteration count, you should call
+     * {@link Intermediates#startTiming intermediates.startTiming} and
+     * {@link Intermediates#finishTiming intermediates.endTiming} to report the
+     * duration of the test whose performance should actually be measured.
+     *
+     * @param intermediates Callback for sending intermediate results.
+     *
+     * @return int Maximum number of iterations to run, or 0 to let the caller
+     * decide.
+     */
+    int startPerformance(Intermediates intermediates);
+
+    /**
+     * This method is used to determine what modes this test case can run in.
+     *
+     * @return true if this test case can only be run in performance mode.
+     */
+    boolean isPerformanceOnly();
+}
+
diff --git a/legacy-test/src/android/test/RepetitiveTest.java b/legacy-test/src/android/test/RepetitiveTest.java
new file mode 100644
index 0000000..6a7130e
--- /dev/null
+++ b/legacy-test/src/android/test/RepetitiveTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.test;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation can be used on an {@link android.test.InstrumentationTestCase}'s test methods.
+ * When the annotation is present, the test method is executed the number of times specified by
+ * numIterations and defaults to 1.
+ *
+ * {@hide} Not needed for public API.
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface RepetitiveTest {
+    /**
+     * Indicates the number of times a test case should be run.
+     *
+     * @return The total number of iterations, the default is 1.
+     */
+    int numIterations() default 1;
+}
\ No newline at end of file
diff --git a/legacy-test/src/android/test/UiThreadTest.java b/legacy-test/src/android/test/UiThreadTest.java
new file mode 100644
index 0000000..cd06ab8
--- /dev/null
+++ b/legacy-test/src/android/test/UiThreadTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.test;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+/**
+ * This annotation can be used on an {@link InstrumentationTestCase}'s test methods.
+ * When the annotation is present, the test method is executed on the application's
+ * main thread (or UI thread.) Note that instrumentation methods may not be used
+ * when this annotation is present.
+ *
+ * @deprecated Use
+ * <a href="{@docRoot}reference/android/support/test/annotation/UiThreadTest.html">
+ * UiThreadTest</a> instead. New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
+ */
+@Deprecated
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface UiThreadTest {
+}
diff --git a/legacy-test/src/android/test/package.html b/legacy-test/src/android/test/package.html
new file mode 100644
index 0000000..5be5135
--- /dev/null
+++ b/legacy-test/src/android/test/package.html
@@ -0,0 +1,10 @@
+<HTML>
+<BODY>
+<p>A framework for writing Android test cases and suites.</p>
+
+<p>For more information, see the
+<a href="{@docRoot}tools/testing/index.html">Testing</a> developer guide.</p>
+{@more}
+
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/legacy-test/src/android/test/suitebuilder/annotation/LargeTest.java b/legacy-test/src/android/test/suitebuilder/annotation/LargeTest.java
new file mode 100644
index 0000000..dc77ee6
--- /dev/null
+++ b/legacy-test/src/android/test/suitebuilder/annotation/LargeTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.test.suitebuilder.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Marks a test that should run as part of the large tests.
+ *
+ * @deprecated Use
+ * <a href="{@docRoot}reference/android/support/test/filters/LargeTest.html">
+ * LargeTest</a> instead. New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
+ */
+@Deprecated
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface LargeTest {
+}
diff --git a/legacy-test/src/android/test/suitebuilder/annotation/MediumTest.java b/legacy-test/src/android/test/suitebuilder/annotation/MediumTest.java
new file mode 100644
index 0000000..b941da0
--- /dev/null
+++ b/legacy-test/src/android/test/suitebuilder/annotation/MediumTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.test.suitebuilder.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Marks a test that should run as part of the medium tests.
+ *
+ * @deprecated Use
+ * <a href="{@docRoot}reference/android/support/test/filters/MediumTest.html">
+ * MediumTest</a> instead. New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
+ */
+@Deprecated
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface MediumTest {
+}
diff --git a/legacy-test/src/android/test/suitebuilder/annotation/SmallTest.java b/legacy-test/src/android/test/suitebuilder/annotation/SmallTest.java
new file mode 100644
index 0000000..d3c74f0
--- /dev/null
+++ b/legacy-test/src/android/test/suitebuilder/annotation/SmallTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.test.suitebuilder.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Marks a test that should run as part of the small tests.
+ *
+ * @deprecated Use
+ * <a href="{@docRoot}reference/android/support/test/filters/SmallTest.html">
+ * SmallTest</a> instead. New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
+ */
+@Deprecated
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface SmallTest {
+}
diff --git a/legacy-test/src/android/test/suitebuilder/annotation/Smoke.java b/legacy-test/src/android/test/suitebuilder/annotation/Smoke.java
new file mode 100644
index 0000000..aac2937
--- /dev/null
+++ b/legacy-test/src/android/test/suitebuilder/annotation/Smoke.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.test.suitebuilder.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Marks a test that should run as part of the smoke tests.
+ * The <code>android.test.suitebuilder.SmokeTestSuiteBuilder</code>
+ * will run all tests with this annotation.
+ *
+ * @see android.test.suitebuilder.SmokeTestSuiteBuilder
+ *
+ * @deprecated New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
+ */
+@Deprecated
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface Smoke {
+}
diff --git a/legacy-test/src/android/test/suitebuilder/annotation/Suppress.java b/legacy-test/src/android/test/suitebuilder/annotation/Suppress.java
new file mode 100644
index 0000000..629a3cf
--- /dev/null
+++ b/legacy-test/src/android/test/suitebuilder/annotation/Suppress.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.test.suitebuilder.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+/**
+ * Use this annotation on test classes or test methods that should not be included in a test
+ * suite. If the annotation appears on the class then no tests in that class will be included. If
+ * the annotation appears only on a test method then only that method will be excluded.
+ *
+ * @deprecated Use
+ * <a href="{@docRoot}reference/android/support/test/filters/Suppress.html">
+ * Suppress</a> instead. New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
+ */
+@Deprecated
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface Suppress {
+}