Merge "fix CTS issue for case testSetOnScrollListener"
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index 060e824..c4b892e 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -22,7 +22,9 @@
 	CtsSimpleAppInstall \
 	CtsSimpleAppInstallDiffCert \
 	CtsTargetInstrumentationApp \
-	CtsUsePermissionDiffCert
+	CtsUsePermissionDiffCert \
+	CtsMonkeyApp \
+	CtsMonkeyApp2 \
 
 # These test cases will be analyzed by the CTS API coverage tools. 
 CTS_COVERAGE_TEST_CASE_LIST := \
@@ -31,27 +33,34 @@
 	CtsAccessibilityServiceTestCases \
 	CtsAccountManagerTestCases \
 	CtsAdminTestCases \
+	CtsAnimationTestCases \
 	CtsAppTestCases \
 	CtsBluetoothTestCases \
 	CtsContentTestCases \
 	CtsDatabaseTestCases \
+	CtsDelegatingAccessibilityService \
+	CtsDeviceAdmin \
 	CtsDpiTestCases \
 	CtsDpiTestCases2 \
 	CtsDrmTestCases \
 	CtsExampleTestCases \
 	CtsGestureTestCases \
 	CtsGraphicsTestCases \
+	CtsGraphics2TestCases \
 	CtsHardwareTestCases \
 	CtsHoloTestCases \
 	CtsJniTestCases \
 	CtsLocationTestCases \
+	CtsMediaStressTestCases \
 	CtsMediaTestCases \
 	CtsNdefTestCases \
 	CtsNetTestCases \
+	CtsOpenGlPerfTestCases \
 	CtsOsTestCases \
 	CtsPermissionTestCases \
 	CtsPermission2TestCases \
 	CtsPreferenceTestCases \
+	CtsPreference2TestCases \
 	CtsProviderTestCases \
 	CtsRenderscriptTestCases \
 	CtsSaxTestCases \
@@ -60,20 +69,20 @@
 	CtsTelephonyTestCases \
 	CtsTestStubs \
 	CtsTextTestCases \
+	CtsTextureViewTestCases \
 	CtsUtilTestCases \
 	CtsViewTestCases \
 	CtsWebkitTestCases \
-	CtsWidgetTestCases
+	CtsWidgetTestCases \
+	SignatureTest \
+	TestDeviceSetup \
+	$(CTS_SECURITY_APPS_LIST)
 
 CTS_TEST_CASE_LIST := \
-	TestDeviceSetup \
-	CtsDelegatingAccessibilityService \
-	CtsDeviceAdmin \
-	SignatureTest \
+	com.replica.replicaisland \
 	ApiDemos \
 	ApiDemosReferenceTest \
 	$(CTS_COVERAGE_TEST_CASE_LIST) \
-	$(CTS_SECURITY_APPS_LIST)
 
 CTS_NATIVE_EXES := \
 	CtsNativeMediaTestCases
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index e5c52fb..945419b 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -18,7 +18,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="com.android.cts.verifier"
       android:versionCode="1"
-      android:versionName="4.0_r1">
+      android:versionName="4.0.3_r1">
 
     <!-- Using 10 for more complete NFC support... -->
     <uses-sdk android:minSdkVersion="10"></uses-sdk>
diff --git a/apps/CtsVerifier/jni/audioquality/Android.mk b/apps/CtsVerifier/jni/audioquality/Android.mk
index 8e827f7..787128a 100644
--- a/apps/CtsVerifier/jni/audioquality/Android.mk
+++ b/apps/CtsVerifier/jni/audioquality/Android.mk
@@ -20,11 +20,13 @@
 
 LOCAL_MODULE_TAGS := optional
 
-
+LOCAL_SHARED_LIBRARIES := \
+	libcutils
 
 LOCAL_MODULE    := libaudioquality
 LOCAL_SRC_FILES := Fft.cpp Window.cpp GlitchTest.cpp MeasureRms.cpp \
    OverflowCheck.cpp LinearityTest.cpp CompareSpectra.cpp \
-   GenerateSinusoid.cpp Wrapper.cpp
+   GenerateSinusoid.cpp Wrapper.cpp LinearityTestRms.cpp
+
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/apps/CtsVerifier/jni/audioquality/LinearityTest.h b/apps/CtsVerifier/jni/audioquality/LinearityTest.h
index d92566a..1aac4b6 100644
--- a/apps/CtsVerifier/jni/audioquality/LinearityTest.h
+++ b/apps/CtsVerifier/jni/audioquality/LinearityTest.h
@@ -17,6 +17,22 @@
 #ifndef LINEARITY_TEST_H
 #define LINEARITY_TEST_H
 
+/* error codes returned */
+// The input signals or sample counts are missing.
+const int ERROR_INPUT_SIGNAL_MISSING       = -1;
+// The number of input signals is < 2.
+const int ERROR_INPUT_SIGNAL_NUMBERS       = -2;
+// The specified sample rate is <= 4000.0
+const int ERROR_SAMPLE_RATE_TOO_LOW        = -3;
+// The dB step size for the increase in stimulus level is <= 0.0
+const int ERROR_NEGATIVE_STEP_SIZE         = -4;
+// The specified reference stimulus number is out of range.
+const int ERROR_STIMULUS_NUMBER            = -5;
+// One or more of the stimuli is too short in duration.
+const int ERROR_STIMULI_TOO_SHORT          = -6;
+// cannot find linear fitting for the given data
+const int ERROR_LINEAR_FITTING             = -7;
+
 /* There are numSignals int16 signals in pcms.  sampleCounts is an
    integer array of length numSignals containing their respective
    lengths in samples.  They are all sampled at sampleRate.  The pcms
@@ -27,16 +43,15 @@
    normal speaking levels).  The maximum deviation in linearity found
    (in dB) is returned in maxDeviation.  The function returns 1 if
    the measurements could be made, or a negative number that
-   indicates the error, as follows:
-      -1 The input signals or sample counts are missing.
-      -2 The number of input signals is < 2.
-      -3 The specified sample rate is <= 4000.0
-      -4 The dB step size for the increase in stimulus level is <= 0.0/
-      -5 The specified reverence stimulus number is out of range.
-      -6 One or more of the stimuli is too short in duration. */
+   indicates the error, as defined above. */
 int linearityTest(short** pcms, int* sampleCounts, int numSignals,
                   float sampleRate, float dbStepSize,
                   int referenceStim, float* maxDeviation);
 
+/* a version using RMS of the whole signal and linear fitting */
+int linearityTestRms(short** pcms, int* sampleCounts, int numSignals,
+                  float sampleRate, float dbStepSize,
+                  float* maxDeviation);
+
 
 #endif /* LINEARITY_TEST_H */
diff --git a/apps/CtsVerifier/jni/audioquality/LinearityTestRms.cpp b/apps/CtsVerifier/jni/audioquality/LinearityTestRms.cpp
new file mode 100644
index 0000000..cf47ec7
--- /dev/null
+++ b/apps/CtsVerifier/jni/audioquality/LinearityTestRms.cpp
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+/* This test accepts a collection of N speech waveforms collected as
+   part of N recognition attempts.  The waveforms are ordered by
+   increasing presentation level.  The test determines the extent to
+   which the peak amplitudes in the waveforms track the change in
+   presentation level.  Failure to track the presentation level within
+   some reasonable margin is an indication of clipping or of automatic
+   gain control in the signal path.
+
+   RMS of each level is used as a parameter for deciding lienairy.
+   For each level, RMS is calculated, and a line fitting into RMS vs level
+   will be calculated. Then for each level, residual error of measurement
+   vs line fitting will be calculated, and the residual error is normalized
+   with each measurement. The test failes if residual error is bigger than
+   2dB.
+
+   This test will be robust to background noise as long as it is persistent.
+   But background noise which appears shortly with enough strength can
+   mess up the result.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <cutils/log.h>
+#include "LinearityTest.h"
+
+#define LOG_TAG "LinearityTestRms"
+
+// vectorDot, vectorNorm, and solveLeastSquares
+// copied from frameworks/base/libs/ui/Input.cpp
+
+static inline float vectorDot(const float* a, const float* b, uint32_t m) {
+    float r = 0;
+    while (m--) {
+        r += *(a++) * *(b++);
+    }
+    return r;
+}
+
+static inline float vectorNorm(const float* a, uint32_t m) {
+    float r = 0;
+    while (m--) {
+        float t = *(a++);
+        r += t * t;
+    }
+    return sqrtf(r);
+}
+
+/**
+ * Solves a linear least squares problem to obtain a N degree polynomial that fits
+ * the specified input data as nearly as possible.
+ *
+ * Returns true if a solution is found, false otherwise.
+ *
+ * The input consists of two vectors of data points X and Y with indices 0..m-1.
+ * The output is a vector B with indices 0..n-1 that describes a polynomial
+ * that fits the data, such the sum of abs(Y[i] - (B[0] + B[1] X[i] + B[2] X[i]^2 ... B[n] X[i]^n))
+ * for all i between 0 and m-1 is minimized.
+ *
+ * That is to say, the function that generated the input data can be approximated
+ * by y(x) ~= B[0] + B[1] x + B[2] x^2 + ... + B[n] x^n.
+ *
+ * The coefficient of determination (R^2) is also returned to describe the goodness
+ * of fit of the model for the given data.  It is a value between 0 and 1, where 1
+ * indicates perfect correspondence.
+ *
+ * This function first expands the X vector to a m by n matrix A such that
+ * A[i][0] = 1, A[i][1] = X[i], A[i][2] = X[i]^2, ..., A[i][n] = X[i]^n.
+ *
+ * Then it calculates the QR decomposition of A yielding an m by m orthonormal matrix Q
+ * and an m by n upper triangular matrix R.  Because R is upper triangular (lower
+ * part is all zeroes), we can simplify the decomposition into an m by n matrix
+ * Q1 and a n by n matrix R1 such that A = Q1 R1.
+ *
+ * Finally we solve the system of linear equations given by R1 B = (Qtranspose Y)
+ * to find B.
+ *
+ * For efficiency, we lay out A and Q column-wise in memory because we frequently
+ * operate on the column vectors.  Conversely, we lay out R row-wise.
+ *
+ * http://en.wikipedia.org/wiki/Numerical_methods_for_linear_least_squares
+ * http://en.wikipedia.org/wiki/Gram-Schmidt
+ */
+static bool solveLeastSquares(const float* x, const float* y, uint32_t m, uint32_t n,
+        float* outB, float* outDet) {
+#if DEBUG_LEAST_SQUARES
+    LOGD("solveLeastSquares: m=%d, n=%d, x=%s, y=%s", int(m), int(n),
+            vectorToString(x, m).string(), vectorToString(y, m).string());
+#endif
+
+    // Expand the X vector to a matrix A.
+    float a[n][m]; // column-major order
+    for (uint32_t h = 0; h < m; h++) {
+        a[0][h] = 1;
+        for (uint32_t i = 1; i < n; i++) {
+            a[i][h] = a[i - 1][h] * x[h];
+        }
+    }
+#if DEBUG_LEAST_SQUARES
+    LOGD("  - a=%s", matrixToString(&a[0][0], m, n, false /*rowMajor*/).string());
+#endif
+
+    // Apply the Gram-Schmidt process to A to obtain its QR decomposition.
+    float q[n][m]; // orthonormal basis, column-major order
+    float r[n][n]; // upper triangular matrix, row-major order
+    for (uint32_t j = 0; j < n; j++) {
+        for (uint32_t h = 0; h < m; h++) {
+            q[j][h] = a[j][h];
+        }
+        for (uint32_t i = 0; i < j; i++) {
+            float dot = vectorDot(&q[j][0], &q[i][0], m);
+            for (uint32_t h = 0; h < m; h++) {
+                q[j][h] -= dot * q[i][h];
+            }
+        }
+
+        float norm = vectorNorm(&q[j][0], m);
+        if (norm < 0.000001f) {
+            // vectors are linearly dependent or zero so no solution
+#if DEBUG_LEAST_SQUARES
+            LOGD("  - no solution, norm=%f", norm);
+#endif
+            return false;
+        }
+
+        float invNorm = 1.0f / norm;
+        for (uint32_t h = 0; h < m; h++) {
+            q[j][h] *= invNorm;
+        }
+        for (uint32_t i = 0; i < n; i++) {
+            r[j][i] = i < j ? 0 : vectorDot(&q[j][0], &a[i][0], m);
+        }
+    }
+#if DEBUG_LEAST_SQUARES
+    LOGD("  - q=%s", matrixToString(&q[0][0], m, n, false /*rowMajor*/).string());
+    LOGD("  - r=%s", matrixToString(&r[0][0], n, n, true /*rowMajor*/).string());
+
+    // calculate QR, if we factored A correctly then QR should equal A
+    float qr[n][m];
+    for (uint32_t h = 0; h < m; h++) {
+        for (uint32_t i = 0; i < n; i++) {
+            qr[i][h] = 0;
+            for (uint32_t j = 0; j < n; j++) {
+                qr[i][h] += q[j][h] * r[j][i];
+            }
+        }
+    }
+    LOGD("  - qr=%s", matrixToString(&qr[0][0], m, n, false /*rowMajor*/).string());
+#endif
+
+    // Solve R B = Qt Y to find B.  This is easy because R is upper triangular.
+    // We just work from bottom-right to top-left calculating B's coefficients.
+    for (uint32_t i = n; i-- != 0; ) {
+        outB[i] = vectorDot(&q[i][0], y, m);
+        for (uint32_t j = n - 1; j > i; j--) {
+            outB[i] -= r[i][j] * outB[j];
+        }
+        outB[i] /= r[i][i];
+    }
+#if DEBUG_LEAST_SQUARES
+    LOGD("  - b=%s", vectorToString(outB, n).string());
+#endif
+
+    // Calculate the coefficient of determination as 1 - (SSerr / SStot) where
+    // SSerr is the residual sum of squares (squared variance of the error),
+    // and SStot is the total sum of squares (squared variance of the data).
+    float ymean = 0;
+    for (uint32_t h = 0; h < m; h++) {
+        ymean += y[h];
+    }
+    ymean /= m;
+
+    float sserr = 0;
+    float sstot = 0;
+    for (uint32_t h = 0; h < m; h++) {
+        float err = y[h] - outB[0];
+        float term = 1;
+        for (uint32_t i = 1; i < n; i++) {
+            term *= x[h];
+            err -= term * outB[i];
+        }
+        sserr += err * err;
+        float var = y[h] - ymean;
+        sstot += var * var;
+    }
+    *outDet = sstot > 0.000001f ? 1.0f - (sserr / sstot) : 1;
+#if DEBUG_LEAST_SQUARES
+    LOGD("  - sserr=%f", sserr);
+    LOGD("  - sstot=%f", sstot);
+    LOGD("  - det=%f", *outDet);
+#endif
+    return true;
+}
+
+/* calculate RMS of given sample with numSamples of length */
+float calcRms(short* pcm, int numSamples)
+{
+    float energy = 0.0f;
+    for(int i = 0; i < numSamples; i++) {
+        float sample = (float)pcm[i];
+        energy += (sample * sample);
+    }
+    return sqrtf(energy);
+}
+
+/* There are numSignals int16 signals in pcms.  sampleCounts is an
+   integer array of length numSignals containing their respective
+   lengths in samples.  They are all sampled at sampleRate.  The pcms
+   are ordered by increasing stimulus level.  The level steps between
+   successive stimuli were of size dbStepSize dB.
+   The maximum deviation in linearity found
+   (in dB) is returned in maxDeviation.  The function returns 1 if
+   the measurements could be made, or a negative number that
+   indicates the error, as defined in LinearityTest.h */
+int linearityTestRms(short** pcms, int* sampleCounts, int numSignals,
+                  float sampleRate, float dbStepSize,
+                  float* maxDeviation) {
+    if (!(pcms && sampleCounts)) {
+        return ERROR_INPUT_SIGNAL_MISSING;
+    }
+    if (numSignals < 2) {
+      return ERROR_INPUT_SIGNAL_NUMBERS;
+    }
+    if (sampleRate <= 4000.0) {
+      return ERROR_SAMPLE_RATE_TOO_LOW;
+    }
+    if (dbStepSize <= 0.0) {
+        return ERROR_NEGATIVE_STEP_SIZE;
+    }
+
+    float* levels = new float[numSignals];
+    levels[0] = 1.0f;
+    float stepInMag = powf(10.0f, dbStepSize/20.0f);
+    for(int i = 1; i < numSignals; i++) {
+        levels[i] = levels[i - 1] * stepInMag;
+    }
+
+    float* rmsValues = new float[numSignals];
+    for (int i = 0; i < numSignals; i++) {
+        rmsValues[i] = calcRms(pcms[i], sampleCounts[i]);
+    }
+    const int NO_COEFFS = 2; // only line fitting
+    float coeffs[NO_COEFFS];
+    float outDet;
+    if(!solveLeastSquares(levels, rmsValues, numSignals, NO_COEFFS,
+                          coeffs, &outDet)) {
+        LOGI(" solveLeastSquares fails with det %f", outDet);
+        return ERROR_LINEAR_FITTING;
+    }
+    LOGI(" coeffs offset %f linear %f", coeffs[0], coeffs[1]);
+    float maxDev = 0.0f;
+    for(int i = 0; i < numSignals; i++) {
+        float residue = coeffs[0] + coeffs[1] * levels[i] - rmsValues[i];
+        // to make devInDb positive, add measured value itself
+        // then normalize
+        float devInDb = 20.0f * log10f((fabs(residue) + rmsValues[i])
+                                       / rmsValues[i]);
+        LOGI(" %d-th residue %f dB", i, devInDb);
+        if (devInDb > maxDev) {
+            maxDev = devInDb;
+        }
+    }
+    *maxDeviation = maxDev;
+
+    delete[] levels;
+    delete[] rmsValues;
+
+    return 1;
+}
diff --git a/apps/CtsVerifier/jni/audioquality/Wrapper.cpp b/apps/CtsVerifier/jni/audioquality/Wrapper.cpp
index bee15c6..438f0d8 100644
--- a/apps/CtsVerifier/jni/audioquality/Wrapper.cpp
+++ b/apps/CtsVerifier/jni/audioquality/Wrapper.cpp
@@ -57,6 +57,12 @@
             JNIEnv *env, jobject obj,
             jobjectArray jpcms,
             jfloat sampleRate, jfloat dbStepSize, jint referenceStim);
+
+    JNIEXPORT jfloat JNICALL
+        Java_com_android_cts_verifier_audioquality_Native_linearityTestRms(
+            JNIEnv *env, jobject obj,
+            jobjectArray jpcms,
+            jfloat sampleRate, jfloat dbStepSize);
 };
 
 /* Returns an array of sinusoidal samples.
@@ -241,3 +247,41 @@
 
     return maxDeviation;
 }
+
+
+/* Return maximum deviation from linearity in dB.
+   On failure returns:
+      -1.0 The input signals or sample counts are missing.
+      -2.0 The number of input signals is < 2.
+      -3.0 The specified sample rate is <= 4000.0
+      -4.0 The dB step size for the increase in stimulus level is <= 0.0
+      -6.0 One or more of the stimuli is too short in duration.
+*/
+JNIEXPORT jfloat JNICALL
+    Java_com_android_cts_verifier_audioquality_Native_linearityTestRms(
+        JNIEnv *env, jobject obj,
+        jobjectArray jpcms,
+        jfloat sampleRate, jfloat dbStepSize) {
+    int numSignals = env->GetArrayLength(jpcms);
+    int *sampleCounts = new int[numSignals];
+    short **pcms = new shortPtr[numSignals];
+    jshortArray ja;
+    for (int i = 0; i < numSignals; i++) {
+        ja = (jshortArray) env->GetObjectArrayElement(jpcms, i);
+        sampleCounts[i] = env->GetArrayLength(ja);
+        pcms[i] = new short[sampleCounts[i]];
+        env->GetShortArrayRegion(ja, 0, sampleCounts[i], pcms[i]);
+    }
+
+    float maxDeviation = -1.0;
+    int ret = linearityTestRms(pcms, sampleCounts, numSignals,
+            sampleRate, dbStepSize, &maxDeviation);
+    delete[] sampleCounts;
+    for (int i = 0; i < numSignals; i++) {
+        delete[] pcms[i];
+    }
+    delete[] pcms;
+    if (ret < 1) return ret;
+
+    return maxDeviation;
+}
diff --git a/apps/CtsVerifier/res/layout/pass_fail_list.xml b/apps/CtsVerifier/res/layout/pass_fail_list.xml
index 3c1f9d0..0b247f4 100644
--- a/apps/CtsVerifier/res/layout/pass_fail_list.xml
+++ b/apps/CtsVerifier/res/layout/pass_fail_list.xml
@@ -28,6 +28,7 @@
     <TextView android:id="@id/android:empty"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
+            android:layout_weight="1"
             />
 
     <include layout="@layout/pass_fail_buttons" />
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/AudioQualityVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/AudioQualityVerifierActivity.java
index 755b62d..af389a6 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/AudioQualityVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/AudioQualityVerifierActivity.java
@@ -134,7 +134,7 @@
         fillAdapter();
         mList.setAdapter(mAdapter);
         mList.setOnItemClickListener(this);
-        checkNotSilent();
+        adjustVolume();
     }
 
     @Override
@@ -142,18 +142,18 @@
         super.onResume();
         mAdapter.notifyDataSetChanged(); // Update List UI
         setVolumeControlStream(AudioManager.STREAM_MUSIC);
-        checkNotSilent();
+        adjustVolume();
     }
 
-    private void checkNotSilent() {
+    private void adjustVolume() {
         AudioManager mgr = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
         mgr.setStreamMute(PLAYBACK_STREAM, false);
         int volume = mgr.getStreamVolume(PLAYBACK_STREAM);
         int max = mgr.getStreamMaxVolume(PLAYBACK_STREAM);
+        int target = (max * 2) / 3;
         Log.i(TAG, "Volume " + volume + ", max " + max);
-        if (volume <= max / 10) {
-            // Volume level is silent or very quiet; increase to two-thirds
-            mgr.setStreamVolume(PLAYBACK_STREAM, (max * 2) / 3, AudioManager.FLAG_SHOW_UI);
+        if (volume != target) {
+            mgr.setStreamVolume(PLAYBACK_STREAM, target, AudioManager.FLAG_SHOW_UI);
         }
     }
 
@@ -188,6 +188,7 @@
     // Implements AdapterView.OnItemClickListener
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
         if (mRunningExperiment) return;
+        adjustVolume();
         runExperiment(position, false);
     }
 
@@ -207,6 +208,7 @@
 
     // Implements View.OnClickListener:
     public void onClick(View v) {
+        adjustVolume();
         if (v == mCalibrateButton) {
             Intent intent = new Intent(this, CalibrateVolumeActivity.class);
             startActivity(intent);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/Native.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/Native.java
index 87b11d1..cdb3e25 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/Native.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/Native.java
@@ -31,6 +31,8 @@
             float sampleRate);
     public native float linearityTest(short[][] pcms,
         float sampleRate, float dbStepSize, int referenceStim);
+    public native float linearityTestRms(short[][] pcms,
+        float sampleRate, float dbStepSize);
 
     // The following indexes must match those in wrapper.cc
     public static final int MEASURE_RMS_RMS = 0;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/Utils.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/Utils.java
index 704b1df..f2019c2 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/Utils.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/Utils.java
@@ -316,17 +316,17 @@
         return data.length / AudioQualityVerifierActivity.BYTES_PER_SAMPLE;
     }
 
-    public static void playRawFile(String filename) {
+    public static AudioTrack playRawFile(String filename) {
         byte[] data = readFile(filename);
         if (data == null) {
             Log.e(TAG, "Cannot read " + filename);
-            return;
+            return null;
         }
-        playRaw(data);
+        return playRaw(data);
     }
 
-    public static void playStim(Context context, int stimNum) {
-        Utils.playRaw(getStim(context, stimNum));
+    public static AudioTrack playStim(Context context, int stimNum) {
+        return Utils.playRaw(getStim(context, stimNum));
     }
 
     public static byte[] getStim(Context context, int stimNum) {
@@ -337,13 +337,15 @@
         return AudioAssets.getPinkNoise(context, ampl, duration);
     }
 
-    public static void playRaw(byte[] data) {
+    public static AudioTrack playRaw(byte[] data) {
         Log.i(TAG, "Playing " + data.length + " bytes of pre-recorded audio");
         AudioTrack at = new AudioTrack(AudioQualityVerifierActivity.PLAYBACK_STREAM, AudioQualityVerifierActivity.SAMPLE_RATE,
                 AudioFormat.CHANNEL_OUT_MONO, AudioQualityVerifierActivity.AUDIO_FORMAT,
                 data.length, AudioTrack.MODE_STREAM);
         writeAudio(at, data);
         at.play();
+
+        return at;
     }
 
     /**
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/GainLinearityExperiment.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/GainLinearityExperiment.java
index 05f1602..225df1a 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/GainLinearityExperiment.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/GainLinearityExperiment.java
@@ -66,9 +66,8 @@
         for (int i = 0; i < LEVELS; i++) {
             pcms[i] = Utils.byteToShortArray(record[i]);
         }
-        // We specify the middle stimulus (LEVELS / 2) as the "reference":
-        float deviation = mNative.linearityTest(pcms, AudioQualityVerifierActivity.SAMPLE_RATE,
-                DB_STEP_SIZE, LEVELS / 2);
+        float deviation = mNative.linearityTestRms(pcms, AudioQualityVerifierActivity.SAMPLE_RATE,
+                DB_STEP_SIZE);
         if (deviation < 0.0f) {
             setScore(getString(R.string.aq_fail));
             setReport(String.format(getString(R.string.aq_linearity_report_error), deviation));
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/LoopbackExperiment.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/LoopbackExperiment.java
index a5c41be..0817860 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/LoopbackExperiment.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/LoopbackExperiment.java
@@ -24,6 +24,7 @@
 import android.content.Context;
 import android.media.AudioFormat;
 import android.media.AudioRecord;
+import android.media.AudioTrack;
 import android.media.MediaRecorder;
 import android.util.Log;
 
@@ -74,13 +75,15 @@
         mRecorder.start();
         Utils.delay(END_DELAY_MS);
 
-        Utils.playRaw(playbackData);
+        AudioTrack track = Utils.playRaw(playbackData);
 
         int timeout = duration + 2 * END_DELAY_MS;
         try {
             mRecorder.join(timeout);
         } catch (InterruptedException e) {}
 
+        track.stop();
+        track.release();
         return recordedData;
     }
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/SpectrumShapeExperiment.java b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/SpectrumShapeExperiment.java
index 148fb47..df7919e 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/SpectrumShapeExperiment.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audioquality/experiments/SpectrumShapeExperiment.java
@@ -33,7 +33,7 @@
     private static final int DURATION = 3;
 
     public SpectrumShapeExperiment() {
-        super(true);
+        super(false); // disable temporarily
     }
 
     @Override
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/streamquality/StreamingVideoActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/streamquality/StreamingVideoActivity.java
index d575e5f..d122dec 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/streamquality/StreamingVideoActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/streamquality/StreamingVideoActivity.java
@@ -140,10 +140,10 @@
     private TestListAdapter getStreamAdapter() {
         ArrayTestListAdapter adapter = new ArrayTestListAdapter(this);
 
-        adapter.add(TestListItem.newCategory("RTSP"));
-        for (Stream stream : RTSP_STREAMS) {
-            addStreamToTests(adapter, stream);
-        }
+//        adapter.add(TestListItem.newCategory("RTSP"));
+//        for (Stream stream : RTSP_STREAMS) {
+//            addStreamToTests(adapter, stream);
+//        }
 
         adapter.add(TestListItem.newCategory("HTTP Progressive"));
         for (Stream stream : HTTP_STREAMS) {
diff --git a/development/ide/eclipse/.classpath b/development/ide/eclipse/.classpath
index 30c63d8..6f5bc69 100644
--- a/development/ide/eclipse/.classpath
+++ b/development/ide/eclipse/.classpath
@@ -4,6 +4,10 @@
     <classpathentry kind="lib" path="prebuilt/common/tradefed/tradefed-prebuilt.jar"/>
     <classpathentry kind="src" path="cts/apps/CtsVerifier/src"/>
     <classpathentry kind="src" path="cts/apps/CtsVerifier/tests/src"/>
+    <classpathentry kind="src" path="cts/tests/appsecurity/src"/>
+    <classpathentry kind="src" path="cts/tests/appsecurity/test-apps/AppWithData/src"/>
+    <classpathentry kind="src" path="cts/tests/appsecurity/test-apps/CtsMonkeyApp/src"/>
+    <classpathentry kind="src" path="cts/tests/appsecurity/test-apps/CtsMonkeyApp2/src"/>
     <classpathentry kind="src" path="cts/libs/vogar-expect/src"/>
     <classpathentry kind="src" path="cts/tests/ApiDemosReferenceTest/src"/>
     <classpathentry kind="src" path="cts/tests/ProcessTest/src"/>
@@ -13,8 +17,6 @@
     <classpathentry kind="src" path="cts/tests/SignatureTest/tests/src"/>
     <classpathentry kind="src" path="cts/tests/acceleration/src"/>
     <classpathentry kind="src" path="cts/tests/accessibilityservice/src"/>
-    <classpathentry kind="src" path="cts/tests/appsecurity-tests/src"/>
-    <classpathentry kind="src" path="cts/tests/appsecurity-tests/test-apps/AppWithData/src"/>
     <classpathentry kind="src" path="cts/tests/core/runner/src"/>
     <classpathentry kind="src" path="cts/tests/deviceadmin/src"/>
     <classpathentry kind="src" path="cts/tests/src"/>
@@ -32,12 +34,15 @@
     <classpathentry kind="src" path="cts/tests/tests/example/src"/>
     <classpathentry kind="src" path="cts/tests/tests/gesture/src"/>
     <classpathentry kind="src" path="cts/tests/tests/graphics/src"/>
+    <classpathentry kind="src" path="cts/tests/tests/graphics2/src"/>
     <classpathentry kind="src" path="cts/tests/tests/hardware/src"/>
     <classpathentry kind="src" path="cts/tests/tests/holo/src"/>
     <classpathentry kind="src" path="cts/tests/tests/jni/src"/>
     <classpathentry kind="src" path="cts/tests/tests/location/src"/>
     <classpathentry kind="src" path="cts/tests/tests/media/src"/>
+    <classpathentry kind="src" path="cts/tests/tests/mediastress/src"/>
     <classpathentry kind="src" path="cts/tests/tests/net/src"/>
+    <classpathentry kind="src" path="cts/tests/tests/openglperf/src"/>
     <classpathentry kind="src" path="cts/tests/tests/os/src"/>
     <classpathentry kind="src" path="cts/tests/tests/performance/src"/>
     <classpathentry kind="src" path="cts/tests/tests/performance2/src"/>
@@ -47,12 +52,14 @@
     <classpathentry kind="src" path="cts/tests/tests/permission/src"/>
     <classpathentry kind="src" path="cts/tests/tests/permission2/src"/>
     <classpathentry kind="src" path="cts/tests/tests/preference/src"/>
+    <classpathentry kind="src" path="cts/tests/tests/preference2/src"/>
     <classpathentry kind="src" path="cts/tests/tests/provider/src"/>
     <classpathentry kind="src" path="cts/tests/tests/renderscript/src"/>
     <classpathentry kind="src" path="cts/tests/tests/security/src"/>
     <classpathentry kind="src" path="cts/tests/tests/speech/src"/>
     <classpathentry kind="src" path="cts/tests/tests/telephony/src"/>
     <classpathentry kind="src" path="cts/tests/tests/text/src"/>
+    <classpathentry kind="src" path="cts/tests/tests/textureview/src"/>
     <classpathentry kind="src" path="cts/tests/tests/util/src"/>
     <classpathentry kind="src" path="cts/tests/tests/view/src"/>
     <classpathentry kind="src" path="cts/tests/tests/webkit/src"/>
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index 8fef728..22905e9 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -28,12 +28,14 @@
         <meta-data android:name="android.app.cts.float" android:value="100.1" />
         <meta-data android:name="android.app.cts.reference" android:resource="@xml/metadata" />
     </permission>
-
+    
     <uses-permission android:name="android.permission.GET_TASKS" />
     <uses-permission android:name="android.permission.SET_WALLPAPER" />
     <uses-permission android:name="android.permission.SET_TIME_ZONE" />
-    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
+    <uses-permission android:name="android.permission.WRITE_CONTACTS" />        
+    <uses-permission android:name="android.permission.WRITE_SOCIAL_STREAM" />    
     <uses-permission android:name="android.permission.READ_CONTACTS" />
+    <uses-permission android:name="android.permission.READ_SOCIAL_STREAM" />
     <uses-permission android:name="android.permission.WRITE_CALENDAR" />
     <uses-permission android:name="android.permission.READ_CALENDAR" />
     <uses-permission android:name="android.permission.DEVICE_POWER" />
@@ -114,6 +116,8 @@
     <application android:label="Android TestCase"
                 android:icon="@drawable/size_48x48" android:name="android.app.cts.MockApplication">
 
+        <activity android:name="android.app.cts.ActionBarActivity" />
+
         <activity android:name="android.media.cts.AudioManagerStub"
             android:label="AudioManagerStub"/>
         <activity android:name="android.media.cts.AudioManagerStubHelper"
@@ -169,7 +173,8 @@
         </activity>
 
         <activity android:name="android.app.cts.DialogStubActivity"
-            android:label="DialogStubActivity">
+            android:label="DialogStubActivity"
+            android:configChanges="keyboardHidden|orientation|screenSize">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
@@ -918,7 +923,7 @@
         <service android:name="android.app.cts.IntentServiceStub"/>
 
         <activity android:name="android.app.cts.LaunchpadActivity" 
-                  android:configChanges="keyboardHidden|orientation"
+                  android:configChanges="keyboardHidden|orientation|screenSize"
                   android:multiprocess="true">
         </activity>
 
diff --git a/tests/appsecurity-tests/src/com/android/cts/monkey/AbstractMonkeyTest.java b/tests/appsecurity-tests/src/com/android/cts/monkey/AbstractMonkeyTest.java
new file mode 100644
index 0000000..0bc2c10
--- /dev/null
+++ b/tests/appsecurity-tests/src/com/android/cts/monkey/AbstractMonkeyTest.java
@@ -0,0 +1,47 @@
+package com.android.cts.monkey;
+
+import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.io.File;
+
+abstract class AbstractMonkeyTest extends DeviceTestCase implements IBuildReceiver {
+
+    static final String[] PKGS = {"com.android.cts.monkey", "com.android.cts.monkey2"};
+    static final String[] APKS = {"CtsMonkeyApp.apk", "CtsMonkeyApp2.apk"};
+
+    CtsBuildHelper mBuild;
+    ITestDevice mDevice;
+
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mDevice = getDevice();
+        for (int i = 0; i < PKGS.length; i++) {
+            mDevice.uninstallPackage(PKGS[i]);
+            File app = mBuild.getTestApp(APKS[i]);
+            mDevice.installPackage(app, false);
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        for (int i = 0; i < PKGS.length; i++) {
+            mDevice.uninstallPackage(PKGS[i]);
+        }
+    }
+
+    void clearLogCat() throws DeviceNotAvailableException {
+        mDevice.executeAdbCommand("logcat", "-c");
+    }
+}
diff --git a/tests/appsecurity-tests/src/com/android/cts/monkey/CategoryTest.java b/tests/appsecurity-tests/src/com/android/cts/monkey/CategoryTest.java
new file mode 100644
index 0000000..3932653
--- /dev/null
+++ b/tests/appsecurity-tests/src/com/android/cts/monkey/CategoryTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.monkey;
+
+public class CategoryTest extends AbstractMonkeyTest {
+
+    public void testDefaultCategories() throws Exception {
+        String out = mDevice.executeShellCommand("monkey -v -p " + PKGS[0] + " 5000");
+        assertTrue(out.contains("cmp=com.android.cts.monkey/.MonkeyActivity"));
+        assertTrue(out.contains("cmp=com.android.cts.monkey/.BaboonActivity"));
+    }
+
+    public void testSingleCategory() throws Exception {
+        String out = mDevice.executeShellCommand("monkey -v -p " + PKGS[0]
+                + " -c android.intent.category.LAUNCHER 5000");
+        assertTrue(out.contains("cmp=com.android.cts.monkey/.MonkeyActivity"));
+        assertFalse(out.contains("cmp=com.android.cts.monkey/.BaboonActivity"));
+
+        out = mDevice.executeShellCommand("monkey -v -p " + PKGS[0]
+                + " -c android.intent.category.MONKEY 5000");
+        assertFalse(out.contains("cmp=com.android.cts.monkey/.MonkeyActivity"));
+        assertTrue(out.contains("cmp=com.android.cts.monkey/.BaboonActivity"));
+    }
+
+    public void testMultipleCategories() throws Exception {
+        String out = mDevice.executeShellCommand("monkey -v -p " + PKGS[0]
+                + " -c android.intent.category.LAUNCHER"
+                + " -c android.intent.category.MONKEY 5000");
+        assertTrue(out.contains("cmp=com.android.cts.monkey/.MonkeyActivity"));
+        assertTrue(out.contains("cmp=com.android.cts.monkey/.BaboonActivity"));
+    }
+}
diff --git a/tests/appsecurity-tests/src/com/android/cts/monkey/MonkeyTest.java b/tests/appsecurity-tests/src/com/android/cts/monkey/MonkeyTest.java
new file mode 100644
index 0000000..2bf27ed
--- /dev/null
+++ b/tests/appsecurity-tests/src/com/android/cts/monkey/MonkeyTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.monkey;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+
+import java.util.Scanner;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class MonkeyTest extends AbstractMonkeyTest {
+
+    private static final Pattern LOG_PATTERN =
+            Pattern.compile("I/MonkeyActivity\\([\\d ]+\\): (.*)");
+    private static final String MONKEY = "@(>.<)@";
+    private static final String HUMAN = "(^_^)";
+
+    public void testIsMonkey() throws Exception {
+        clearLogCat();
+        mDevice.executeShellCommand("monkey -p " + PKGS[0] + " 500");
+        assertIsUserAMonkey(true);
+    }
+
+    public void testNotMonkey() throws Exception {
+        clearLogCat();
+        mDevice.executeShellCommand("am start -W -a android.intent.action.MAIN "
+                + "-n com.android.cts.monkey/com.android.cts.monkey.MonkeyActivity");
+        assertIsUserAMonkey(false);
+    }
+
+    private void assertIsUserAMonkey(boolean isMonkey) throws DeviceNotAvailableException {
+        String logs = mDevice.executeAdbCommand("logcat", "-d", "MonkeyActivity:I", "*:S");
+        boolean monkeyLogsFound = false;
+        Scanner s = new Scanner(logs);
+        try {
+            while (s.hasNextLine()) {
+                String line = s.nextLine();
+                Matcher m = LOG_PATTERN.matcher(line);
+                if (m.matches()) {
+                    monkeyLogsFound = true;
+                    assertEquals(isMonkey ? MONKEY : HUMAN, m.group(1));
+                }
+            }
+            assertTrue(monkeyLogsFound);
+        } finally {
+            s.close();
+        }
+    }
+}
diff --git a/tests/appsecurity-tests/src/com/android/cts/monkey/PackageTest.java b/tests/appsecurity-tests/src/com/android/cts/monkey/PackageTest.java
new file mode 100644
index 0000000..aa6106b
--- /dev/null
+++ b/tests/appsecurity-tests/src/com/android/cts/monkey/PackageTest.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.monkey;
+
+public class PackageTest extends AbstractMonkeyTest {
+
+    public void testSinglePackage() throws Exception {
+        String out = mDevice.executeShellCommand("monkey -v -p " + PKGS[0] + " 5000");
+        assertTrue(out.contains("cmp=com.android.cts.monkey/.MonkeyActivity"));
+        assertFalse(out.contains("cmp=com.android.cts.monkey2/.ChimpActivity"));
+
+        out = mDevice.executeShellCommand("monkey -v -p " + PKGS[1] + " 5000");
+        assertFalse(out.contains("cmp=com.android.cts.monkey/.MonkeyActivity"));
+        assertTrue(out.contains("cmp=com.android.cts.monkey2/.ChimpActivity"));
+    }
+
+    public void testMultiplePackages() throws Exception {
+        String out = mDevice.executeShellCommand("monkey -v -p " + PKGS[0]
+                + " -p " + PKGS[1] + " 5000");
+        assertTrue(out.contains("cmp=com.android.cts.monkey/.MonkeyActivity"));
+        assertTrue(out.contains("cmp=com.android.cts.monkey2/.ChimpActivity"));
+    }
+}
diff --git a/tests/appsecurity-tests/src/com/android/cts/monkey/SeedTest.java b/tests/appsecurity-tests/src/com/android/cts/monkey/SeedTest.java
new file mode 100644
index 0000000..4f8f842
--- /dev/null
+++ b/tests/appsecurity-tests/src/com/android/cts/monkey/SeedTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.monkey;
+
+import java.util.Scanner;
+
+public class SeedTest extends AbstractMonkeyTest {
+
+    public void testSeed() throws Exception {
+        String cmd1 = "monkey -s 1337 -v -p " + PKGS[0] + " 500";
+        String out1 = mDevice.executeShellCommand(cmd1);
+        String out2 = mDevice.executeShellCommand(cmd1);
+        assertOutputs(out1, out2);
+
+        String cmd2 = "monkey -s 3007 -v -p " + PKGS[0] + " 125";
+        String out3 = mDevice.executeShellCommand(cmd2);
+        String out4 = mDevice.executeShellCommand(cmd2);
+        assertOutputs(out3, out4);
+    }
+
+    private void assertOutputs(String out1, String out2) {
+        Scanner s1 = new Scanner(out1);
+        Scanner s2 = new Scanner(out2);
+        int numEvents = 0;
+        while (true) {
+            String line1 = getNextLine(s1);
+            String line2 = getNextLine(s2);
+            if (line1 != null || line2 != null) {
+                assertEquals(line1, line2);
+                numEvents++;
+            } else {
+                break;
+            }
+        }
+        assertTrue(numEvents > 0);
+    }
+
+    private String getNextLine(Scanner sc) {
+        while (sc.hasNextLine()) {
+            String line = sc.nextLine().trim();
+            if (line.startsWith(":Sending")) {
+                return line;
+            }
+        }
+        return null;
+    }
+}
diff --git a/tests/appsecurity-tests/src/com/android/cts/monkey/VerbosityTest.java b/tests/appsecurity-tests/src/com/android/cts/monkey/VerbosityTest.java
new file mode 100644
index 0000000..2956191
--- /dev/null
+++ b/tests/appsecurity-tests/src/com/android/cts/monkey/VerbosityTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.monkey;
+
+public class VerbosityTest extends AbstractMonkeyTest {
+
+    public void testVerbosity() throws Exception {
+        String v0 = mDevice.executeShellCommand("monkey -s 1337 -p " + PKGS[0] + " 500");
+        assertTrue(v0.contains("Events injected"));
+        assertFalse(v0.contains("Sending Touch"));
+        assertFalse(v0.contains("Sending Trackball"));
+        assertFalse(v0.contains("Switch"));
+        assertFalse(v0.contains("Sleeping"));
+
+        String v1 = mDevice.executeShellCommand("monkey -v -p " + PKGS[0] + " 500");
+        assertTrue(v1.contains("Events injected"));
+        assertTrue(v1.contains("Sending Touch"));
+        assertTrue(v1.contains("Sending Trackball"));
+        assertTrue(v1.contains("Switch"));
+        assertFalse(v1.contains("Sleeping"));
+
+        String v2 = mDevice.executeShellCommand("monkey -v -v -p " + PKGS[0] + " 500");
+        assertTrue(v2.contains("Events injected"));
+        assertTrue(v2.contains("Sending Touch"));
+        assertTrue(v2.contains("Sending Trackball"));
+        assertTrue(v2.contains("Switch"));
+        assertTrue(v2.contains("Sleeping"));
+
+        assertTrue(v0.length() < v1.length());
+        assertTrue(v1.length() < v2.length());
+    }
+}
diff --git a/tests/appsecurity-tests/test-apps/CtsMonkeyApp/Android.mk b/tests/appsecurity-tests/test-apps/CtsMonkeyApp/Android.mk
new file mode 100644
index 0000000..85a82d8
--- /dev/null
+++ b/tests/appsecurity-tests/test-apps/CtsMonkeyApp/Android.mk
@@ -0,0 +1,27 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_SDK_VERSION := current
+
+LOCAL_PACKAGE_NAME := CtsMonkeyApp
+
+include $(BUILD_PACKAGE)
diff --git a/tests/appsecurity-tests/test-apps/CtsMonkeyApp/AndroidManifest.xml b/tests/appsecurity-tests/test-apps/CtsMonkeyApp/AndroidManifest.xml
new file mode 100644
index 0000000..55f3d6f
--- /dev/null
+++ b/tests/appsecurity-tests/test-apps/CtsMonkeyApp/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+       package="com.android.cts.monkey">
+
+    <application>
+
+        <activity android:name=".MonkeyActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        
+        <activity android:name=".BaboonActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.MONKEY" />
+            </intent-filter>
+        </activity>
+
+    </application>
+</manifest>
diff --git a/tests/appsecurity-tests/test-apps/CtsMonkeyApp/src/com/android/cts/monkey/BaboonActivity.java b/tests/appsecurity-tests/test-apps/CtsMonkeyApp/src/com/android/cts/monkey/BaboonActivity.java
new file mode 100644
index 0000000..f7b8f47
--- /dev/null
+++ b/tests/appsecurity-tests/test-apps/CtsMonkeyApp/src/com/android/cts/monkey/BaboonActivity.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.monkey;
+
+import android.app.Activity;
+
+public class BaboonActivity extends Activity {
+}
diff --git a/tests/appsecurity-tests/test-apps/CtsMonkeyApp/src/com/android/cts/monkey/MonkeyActivity.java b/tests/appsecurity-tests/test-apps/CtsMonkeyApp/src/com/android/cts/monkey/MonkeyActivity.java
new file mode 100644
index 0000000..fd792a7
--- /dev/null
+++ b/tests/appsecurity-tests/test-apps/CtsMonkeyApp/src/com/android/cts/monkey/MonkeyActivity.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.monkey;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.os.Bundle;
+import android.util.Log;
+
+/** @(>.<)@  I'm a monkey! */
+public class MonkeyActivity extends Activity {
+
+    private static final String TAG = "MonkeyActivity";
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Log.i(TAG, ActivityManager.isUserAMonkey() ? "@(>.<)@" : "(^_^)");
+    }
+}
diff --git a/tests/appsecurity-tests/test-apps/CtsMonkeyApp2/Android.mk b/tests/appsecurity-tests/test-apps/CtsMonkeyApp2/Android.mk
new file mode 100644
index 0000000..2f3abd2
--- /dev/null
+++ b/tests/appsecurity-tests/test-apps/CtsMonkeyApp2/Android.mk
@@ -0,0 +1,27 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_SDK_VERSION := current
+
+LOCAL_PACKAGE_NAME := CtsMonkeyApp2
+
+include $(BUILD_PACKAGE)
diff --git a/tests/appsecurity-tests/test-apps/CtsMonkeyApp2/AndroidManifest.xml b/tests/appsecurity-tests/test-apps/CtsMonkeyApp2/AndroidManifest.xml
new file mode 100644
index 0000000..34bca75
--- /dev/null
+++ b/tests/appsecurity-tests/test-apps/CtsMonkeyApp2/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+       package="com.android.cts.monkey2">
+
+    <application>
+
+        <activity android:name=".ChimpActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+    </application>
+</manifest>
diff --git a/tests/appsecurity-tests/test-apps/CtsMonkeyApp2/src/com/android/cts/monkey2/ChimpActivity.java b/tests/appsecurity-tests/test-apps/CtsMonkeyApp2/src/com/android/cts/monkey2/ChimpActivity.java
new file mode 100644
index 0000000..ef9fcc3
--- /dev/null
+++ b/tests/appsecurity-tests/test-apps/CtsMonkeyApp2/src/com/android/cts/monkey2/ChimpActivity.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.monkey2;
+
+import android.app.Activity;
+
+public class ChimpActivity extends Activity {
+}
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index 7d0ec98..b8621a7 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -8,12 +8,17 @@
   bug: 4371654
 },
 {
+  name: "android.openglperf.cts.GlVboPerfTest#testVboWithVaryingIndexBufferNumbers",
+  bug: 5898262
+},
+{
   name: "android.webkit.cts.WebViewTest#testRequestFocusNodeHref",
   bug: 3241968
 },
 {
   names: [
     "libcore.java.net.URLConnectionTest#testServerClosesSocket",
+    "libcore.java.net.URLConnectionTest#testServerShutdownInput",
     "libcore.java.net.URLConnectionTest#testServerShutdownOutput"
   ],
   bug: 5534202
diff --git a/tests/src/android/provider/cts/FileCopyHelper.java b/tests/src/android/provider/cts/FileCopyHelper.java
index 4ee93ac..114c3ad 100644
--- a/tests/src/android/provider/cts/FileCopyHelper.java
+++ b/tests/src/android/provider/cts/FileCopyHelper.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 
 import java.io.File;
+import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -57,36 +58,36 @@
      * @param fileName the file name
      *
      * @return the absolute path of the destination file
+     * @throws IOException
      */
-    public String copy(int resId, String fileName) {
-        InputStream source = null;
-        OutputStream target = null;
+    public String copy(int resId, String fileName) throws IOException {
+        InputStream source = mContext.getResources().openRawResource(resId);
+        OutputStream target = mContext.openFileOutput(fileName, Context.MODE_WORLD_READABLE);
+        copyFile(source, target);
+        mFilesList.add(fileName);
+        return mContext.getFileStreamPath(fileName).getAbsolutePath();
+    }
 
+    public void copyToExternalStorage(int resId, File path) throws IOException {
+        InputStream source = mContext.getResources().openRawResource(resId);
+        OutputStream target = new FileOutputStream(path);
+        copyFile(source, target);
+    }
+
+    private void copyFile(InputStream source, OutputStream target) throws IOException {
         try {
-            source = mContext.getResources().openRawResource(resId);
-            target = mContext.openFileOutput(fileName, Context.MODE_WORLD_READABLE);
-
             byte[] buffer = new byte[1024];
             for (int len = source.read(buffer); len > 0; len = source.read(buffer)) {
                 target.write(buffer, 0, len);
             }
-        } catch (IOException e) {
-            e.printStackTrace();
         } finally {
-            try {
-                if (source != null) {
-                    source.close();
-                }
-                if (target != null) {
-                    target.close();
-                }
-            } catch (IOException e) {
-                // Ignore the IOException.
+            if (source != null) {
+                source.close();
+            }
+            if (target != null) {
+                target.close();
             }
         }
-
-        mFilesList.add(fileName);
-        return mContext.getFileStreamPath(fileName).getAbsolutePath();
     }
 
     /**
diff --git a/tests/tests/animation/Android.mk b/tests/tests/animation/Android.mk
new file mode 100644
index 0000000..ed9874e
--- /dev/null
+++ b/tests/tests/animation/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2011 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsAnimationTestCases
+
+# Don't include this package in any target.
+LOCAL_MODULE_TAGS := optional
+
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+# All tests should include android.test.runner.
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_SDK_VERSION := current
+include $(BUILD_PACKAGE)
+
diff --git a/tests/tests/animation/AndroidManifest.xml b/tests/tests/animation/AndroidManifest.xml
new file mode 100644
index 0000000..f3fd898
--- /dev/null
+++ b/tests/tests/animation/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.cts.animation">
+
+    <application>
+        <activity android:name="android.animation.cts.AnimationActivity"
+            android:label="AnimationActivity"/>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+                     android:targetPackage="com.android.cts.animation"
+                     android:label="CTS tests for android.animation package"/>
+</manifest>
+
diff --git a/tests/tests/animation/res/layout/animation_main.xml b/tests/tests/animation/res/layout/animation_main.xml
new file mode 100644
index 0000000..81356a1
--- /dev/null
+++ b/tests/tests/animation/res/layout/animation_main.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical" >
+    <FrameLayout android:id="@+id/container" android:layout_width="fill_parent"
+            android:layout_height="fill_parent"/>
+</LinearLayout>
diff --git a/tests/tests/animation/src/android/animation/cts/AnimationActivity.java b/tests/tests/animation/src/android/animation/cts/AnimationActivity.java
new file mode 100644
index 0000000..43679c8
--- /dev/null
+++ b/tests/tests/animation/src/android/animation/cts/AnimationActivity.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.animation.cts;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ArgbEvaluator;
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.RadialGradient;
+import android.graphics.Shader;
+import android.graphics.drawable.ShapeDrawable;
+import android.graphics.drawable.shapes.OvalShape;
+import android.os.Bundle;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateInterpolator;
+import java.util.ArrayList;
+
+import com.android.cts.animation.R;
+
+public class AnimationActivity extends Activity {
+    private static final String BALL_HEIGHT = "ballwidth";
+    private static final String BALL_WIDTH = "ballheight";
+    private static final String STARTX = "startx";
+    private static final String STARTY = "starty";
+    private static final String DELTAX = "deltax";
+    private static final String DELTAY = "deltay";
+    private static final String DURATION = "duration";
+
+    float mBallHeight = 50f;
+    float mBallWidth = 50f;
+    float mStartX = 200f;
+    float mStartY = 200f;
+    float mDeltaX = 200f;
+    float mDeltaY = 200f;
+    long mDuration = 1000;
+    public AnimationView view = null;
+
+    @Override
+    public void onCreate(Bundle bundle){
+        super.onCreate(bundle);
+        Intent intent = this.getIntent();
+        Bundle extras = intent.getExtras();
+        if(extras != null) {
+            mBallHeight = extras.getFloat(BALL_HEIGHT);
+            mBallWidth = extras.getFloat(BALL_WIDTH);
+            mStartX = extras.getFloat(STARTX);
+            mStartY = extras.getFloat(STARTY);
+            mDeltaX = extras.getFloat(DELTAX);
+            mDeltaY = extras.getFloat(DELTAY);
+            mDuration = extras.getInt(DURATION);
+        }
+        setContentView(R.layout.animation_main);
+        view = new AnimationView(this);
+        ViewGroup viewGroup = (ViewGroup) findViewById(R.id.container);
+        viewGroup.addView(view);
+    }
+
+    public ValueAnimator createAnimator(Object object,String propertyName, long duration,
+            int repeatCount, int repeatMode,
+            TimeInterpolator timeInterpolator, float start, float end){
+        ValueAnimator valueAnimator = ObjectAnimator.ofFloat(object, propertyName, start,end);
+        valueAnimator.setDuration(duration);
+        valueAnimator.setRepeatCount(repeatCount);
+        valueAnimator.setInterpolator(timeInterpolator);
+        valueAnimator.setRepeatMode(repeatMode);
+        return valueAnimator;
+    }
+
+    public ValueAnimator createAnimatorWithRepeatMode(int repeatMode) {
+        return createAnimator(view.newBall, "y", 1000, ValueAnimator.INFINITE, repeatMode,
+                new AccelerateInterpolator(), mStartY, mStartY + mDeltaY);
+    }
+
+    public ValueAnimator createAnimatorWithRepeatCount(int repeatCount) {
+        return createAnimator(view.newBall, "y", 1000, repeatCount, ValueAnimator.REVERSE,
+                new AccelerateInterpolator(), mStartY, mStartY + mDeltaY);
+    }
+
+    public ValueAnimator createAnimatorWithDuration(long duration) {
+        return createAnimator(view.newBall, "y", duration ,ValueAnimator.INFINITE,
+                ValueAnimator.REVERSE,new AccelerateInterpolator(), mStartY, mStartY + mDeltaY);
+    }
+
+    public ValueAnimator createAnimatorWithInterpolator(TimeInterpolator interpolator){
+        return createAnimator(view.newBall, "y", 1000, ValueAnimator.INFINITE, ValueAnimator.REVERSE,
+                interpolator, mStartY, mStartY + mDeltaY);
+    }
+
+    public ValueAnimator createObjectAnimatorForInt(Object object,String propertyName,
+            long duration, int repeatCount, int repeatMode, TimeInterpolator timeInterpolator,
+            int start, int end) {
+        ObjectAnimator objAnimator = ObjectAnimator.ofInt(object, propertyName, start,end);
+        objAnimator.setDuration(duration);
+
+        objAnimator.setRepeatCount(repeatCount);
+        objAnimator.setInterpolator(timeInterpolator);
+        objAnimator.setRepeatMode(repeatMode);
+        return objAnimator;
+    }
+
+    public ValueAnimator createObjectAnimatorForInt() {
+        ObjectAnimator objAnimator = ObjectAnimator.ofInt(view.newBall, "y", (int)mStartY,
+            (int)(mStartY + mDeltaY));
+        objAnimator.setDuration(mDuration);
+
+        objAnimator.setRepeatCount(ValueAnimator.INFINITE);
+        objAnimator.setInterpolator(new AccelerateInterpolator());
+        objAnimator.setRepeatMode(ValueAnimator.REVERSE);
+        return objAnimator;
+    }
+
+    public void startAnimation(long duration){
+        ValueAnimator bounceAnimator = ObjectAnimator.ofFloat(view.newBall, "y", mStartY,
+            mStartY + mDeltaY);
+        bounceAnimator.setDuration(duration);
+        bounceAnimator.setRepeatCount(ValueAnimator.INFINITE);
+        bounceAnimator.setInterpolator(new AccelerateInterpolator());
+        bounceAnimator.setRepeatMode(ValueAnimator.REVERSE);
+        view.bounceAnimator = bounceAnimator;
+        view.startColorAnimator();
+        view.animateBall();
+    }
+
+    public void startAnimation(ValueAnimator valueAnimator){
+        view.bounceAnimator = valueAnimator;
+        view.startColorAnimator();
+        view.animateBall();
+    }
+
+    public void startAnimation(ObjectAnimator bounceAnimator) {
+        view.bounceAnimator = bounceAnimator;
+        view.startColorAnimator();
+        view.animateBall();
+    }
+
+    public void startAnimation(ObjectAnimator bounceAnimator, ObjectAnimator colorAnimator) {
+        view.bounceAnimator = bounceAnimator;
+        view.startColorAnimator(colorAnimator);
+        view.animateBall();
+    }
+
+    public void startColorAnimation(ValueAnimator colorAnimator){
+        view.startColorAnimator(colorAnimator);
+    }
+
+    public class AnimationView extends View {
+        public static final int RED = 0xffFF8080;
+        public static final int BLUE = 0xff8080FF;
+        public ShapeHolder newBall = null;
+        public final ArrayList<ShapeHolder> balls = new ArrayList<ShapeHolder>();
+        AnimatorSet animation = null;
+        public ValueAnimator bounceAnimator;
+        public ValueAnimator colorAnimator;
+
+        public AnimationView(Context context) {
+            super(context);
+            newBall = addBall(mBallHeight, mBallWidth);
+        }
+
+        public void startColorAnimator() {
+            colorAnimator = ObjectAnimator.ofInt(this, "backgroundColor", RED, BLUE);
+            colorAnimator.setDuration(1000);
+            colorAnimator.setEvaluator(new ArgbEvaluator());
+            colorAnimator.setRepeatCount(ValueAnimator.INFINITE);
+            colorAnimator.setRepeatMode(ValueAnimator.REVERSE);
+            colorAnimator.start();
+        }
+
+        public void startColorAnimator(ValueAnimator animator) {
+            this.colorAnimator = animator;
+            colorAnimator.start();
+        }
+
+        @Override
+        public boolean onTouchEvent(MotionEvent event) {
+            return true;
+        }
+
+        public void animateBall() {
+            float startY = mStartY;
+            float endY = startY + mDeltaY;
+            AnimatorSet bouncer = new AnimatorSet();
+            bouncer.play(bounceAnimator);
+            // Fading animation - remove the ball when the animation is done
+            ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
+            fadeAnim.setDuration(250);
+            fadeAnim.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    balls.remove(((ObjectAnimator)animation).getTarget());
+                }
+            });
+
+            // Sequence the two animations to play one after the other
+            AnimatorSet animatorSet = new AnimatorSet();
+            animatorSet.play(bouncer).before(fadeAnim);
+            animatorSet.start();
+        }
+
+        private ShapeHolder addBall(float x, float y) {
+            OvalShape circle = new OvalShape();
+            circle.resize(x, y);
+            ShapeDrawable drawable = new ShapeDrawable(circle);
+            ShapeHolder shapeHolder = new ShapeHolder(drawable);
+            shapeHolder.setX(x - 25f);
+            shapeHolder.setY(y - 25f);
+            Paint paint = drawable.getPaint();
+            shapeHolder.setPaint(paint);
+            int red = (int)(Math.random() * 255);
+            int green = (int)(Math.random() * 255);
+            int blue = (int)(Math.random() * 255);
+            int color = 0xff000000 | red << 16 | green << 8 | blue;
+            int darkColor = 0xff000000 | red/4 << 16 | green/4 << 8 | blue/4;
+            RadialGradient gradient = new RadialGradient(37.5f, 12.5f,
+                    50f, color, darkColor, Shader.TileMode.CLAMP);
+            paint.setShader(gradient);
+            balls.add(shapeHolder);
+            return shapeHolder;
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            for (int i = 0; i < balls.size(); ++i) {
+                ShapeHolder shapeHolder = balls.get(i);
+                canvas.save();
+                canvas.translate(shapeHolder.getX(), shapeHolder.getY());
+                shapeHolder.getShape().draw(canvas);
+                canvas.restore();
+            }
+        }
+    }
+}
diff --git a/tests/tests/animation/src/android/animation/cts/ArgbEvaluatorTest.java b/tests/tests/animation/src/android/animation/cts/ArgbEvaluatorTest.java
new file mode 100644
index 0000000..33c3716
--- /dev/null
+++ b/tests/tests/animation/src/android/animation/cts/ArgbEvaluatorTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.animation.cts;
+
+import android.animation.ArgbEvaluator;
+import android.graphics.Color;
+import android.test.InstrumentationTestCase;
+
+public class ArgbEvaluatorTest extends InstrumentationTestCase {
+    public void testEvaluate() throws Throwable {
+        final int RED =  0xffFF8080;
+        final int BLUE = 0xff8080FF;
+        int aRED = Color.alpha(RED);
+        int rRED = Color.red(RED);
+        int gRED = Color.green(RED);
+        int bRED = Color.blue(RED);
+        int aBLUE = Color.alpha(BLUE);
+        int rBLUE = Color.red(BLUE);
+        int gBLUE = Color.green(BLUE);
+        int bBLUE = Color.blue(BLUE);
+
+        final ArgbEvaluator evaluator = new ArgbEvaluator();
+        class AnimationRunnable implements Runnable{
+            int result;
+            public void run() {
+                result = (Integer) evaluator.evaluate(0.5f, RED, BLUE);
+            }
+        }
+        AnimationRunnable aRunnable = new AnimationRunnable();
+        this.runTestOnUiThread(aRunnable);
+        Thread.sleep(100);
+        int result = aRunnable.result;
+
+        int aResult = Color.alpha(result);
+        int rResult = Color.red(result);
+        int gResult = Color.green(result);
+        int bResult = Color.blue(result);
+        assertTrue(aResult >= aRED);
+        assertTrue(aResult <= aBLUE);
+        assertTrue(rResult <= rRED);
+        assertTrue(rResult >= rBLUE);
+        assertTrue(gResult >= gRED);
+        assertTrue(gResult <= gBLUE);
+        assertTrue(bResult >= bRED);
+        assertTrue(bResult <= bBLUE);
+    }
+}
+
diff --git a/tests/tests/animation/src/android/animation/cts/FloatEvaluatorTest.java b/tests/tests/animation/src/android/animation/cts/FloatEvaluatorTest.java
new file mode 100644
index 0000000..8cc1ffe
--- /dev/null
+++ b/tests/tests/animation/src/android/animation/cts/FloatEvaluatorTest.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.animation.cts;
+
+import android.animation.FloatEvaluator;
+import android.test.InstrumentationTestCase;
+
+public class FloatEvaluatorTest extends InstrumentationTestCase {
+    public void testEvaluate() {
+        float start = 0.0f;
+        float end = 1.0f;
+        float fraction = 0.5f;
+        FloatEvaluator floatEvaluator = new FloatEvaluator();
+        float result = floatEvaluator.evaluate(fraction, start, end);
+        assertTrue(result >= (fraction*start));
+        assertTrue(result <= (fraction*end));
+    }
+}
+
diff --git a/tests/tests/animation/src/android/animation/cts/IntEvaluatorTest.java b/tests/tests/animation/src/android/animation/cts/IntEvaluatorTest.java
new file mode 100644
index 0000000..11df20c
--- /dev/null
+++ b/tests/tests/animation/src/android/animation/cts/IntEvaluatorTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.animation.cts;
+
+import android.animation.IntEvaluator;
+import android.test.InstrumentationTestCase;
+
+public class IntEvaluatorTest extends InstrumentationTestCase {
+    public void testEvaluate() throws Throwable {
+        final int start = 0;
+        final int end = 100;
+        final float fraction = 0.5f;
+        final IntEvaluator intEvaluator = new IntEvaluator();
+        class AnimationRunnable implements Runnable{
+            int result;
+            public void run() {
+                result = intEvaluator.evaluate(fraction, start, end);
+            }
+        }
+        AnimationRunnable aRunnable = new AnimationRunnable();
+        this.runTestOnUiThread(aRunnable);
+        Thread.sleep(1);
+        int result = aRunnable.result;
+        assertTrue(result >= (fraction*start));
+        assertTrue(result <= (fraction*end));
+    }
+}
+
diff --git a/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java b/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java
new file mode 100644
index 0000000..be5c1d4
--- /dev/null
+++ b/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.animation.cts;
+
+import android.animation.ArgbEvaluator;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.ValueAnimator;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Property;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.Interpolator;
+
+public class ObjectAnimatorTest extends
+        ActivityInstrumentationTestCase2<AnimationActivity> {
+    private AnimationActivity mActivity;
+    private ObjectAnimator mObjectAnimator;
+    private long mDuration = 1000;
+
+    public ObjectAnimatorTest() {
+        super(AnimationActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        setActivityInitialTouchMode(false);
+        mActivity = getActivity();
+        mObjectAnimator = (ObjectAnimator) mActivity.createAnimatorWithDuration(mDuration);
+    }
+
+    public void testDuration() throws Throwable {
+        final long duration = 2000;
+        ObjectAnimator objectAnimatorLocal = (ObjectAnimator)mActivity.createAnimatorWithDuration(
+            duration);
+        startAnimation(objectAnimatorLocal);
+        assertEquals(duration, objectAnimatorLocal.getDuration());
+    }
+    public void testOfFloat() throws Throwable {
+        Object object = mActivity.view.newBall;
+        String property = "y";
+        float startY = mActivity.mStartY;
+        float endY = mActivity.mStartY + mActivity.mDeltaY;
+        ObjectAnimator objAnimator = ObjectAnimator.ofFloat(object, property, startY, endY);
+        assertTrue(objAnimator != null);
+        objAnimator.setDuration(mDuration);
+        objAnimator.setRepeatCount(ValueAnimator.INFINITE);
+        objAnimator.setInterpolator(new AccelerateInterpolator());
+        objAnimator.setRepeatMode(ValueAnimator.REVERSE);
+        startAnimation(objAnimator);
+        assertTrue(objAnimator != null);
+        Thread.sleep(100);
+        float x = mActivity.view.newBall.getX();
+        float y = mActivity.view.newBall.getY();
+        assertTrue( y >= startY);
+        assertTrue( y <= endY);
+    }
+
+    public void testOfFloatBase() throws Throwable {
+        Object object = mActivity.view.newBall;
+        String property = "y";
+        float startY = mActivity.mStartY;
+        float endY = mActivity.mStartY + mActivity.mDeltaY;
+        ObjectAnimator animator = ObjectAnimator.ofFloat(object, property, startY, endY);
+        ObjectAnimator objAnimator = new ObjectAnimator();
+        objAnimator.setTarget(object);
+        objAnimator.setPropertyName(property);
+        assertEquals(animator.getTarget(), objAnimator.getTarget());
+        assertEquals(animator.getPropertyName(), objAnimator.getPropertyName());
+    }
+
+    public void testOfInt() throws Throwable {
+        Object object = mActivity.view.newBall;
+        String property = "backgroundColor";
+        int startColor = mActivity.view.RED;
+        int endColor = mActivity.view.BLUE;
+
+        ObjectAnimator colorAnimator = ObjectAnimator.ofInt(object, property,
+                startColor, endColor);
+        colorAnimator.setDuration(1000);
+        colorAnimator.setEvaluator(new ArgbEvaluator());
+        colorAnimator.setRepeatCount(1);
+        colorAnimator.setRepeatMode(ValueAnimator.REVERSE);
+        colorAnimator.start();
+        startAnimation(mObjectAnimator, colorAnimator);
+        Thread.sleep(100);
+        Integer i = (Integer) colorAnimator.getAnimatedValue();
+        //We are going from less negative value to a more negative value
+        assertTrue(i.intValue() <= startColor);
+        assertTrue(endColor <= i.intValue());
+    }
+
+    public void testOfObject() throws Throwable {
+        Object object = mActivity.view.newBall;
+        String property = "backgroundColor";
+        int startColor = mActivity.view.RED;
+        int endColor = mActivity.view.BLUE;
+        Object[] values = {new Integer(startColor), new Integer(endColor)};
+        ArgbEvaluator evaluator = new ArgbEvaluator();
+        ObjectAnimator colorAnimator = ObjectAnimator.ofObject(object, property,
+                evaluator, values);
+        colorAnimator.setDuration(1000);
+        colorAnimator.setRepeatCount(1);
+        colorAnimator.setRepeatMode(ValueAnimator.REVERSE);
+        colorAnimator.start();
+        startAnimation(mObjectAnimator, colorAnimator);
+        Thread.sleep(100);
+        Integer i = (Integer) colorAnimator.getAnimatedValue();
+        //We are going from less negative value to a more negative value
+        assertTrue(i.intValue() <= startColor);
+        assertTrue(endColor <= i.intValue());
+    }
+
+    public void testOfPropertyValuesHolder() throws Throwable {
+        Object object = mActivity.view.newBall;
+        String propertyName = "backgroundColor";
+        int startColor = mActivity.view.RED;
+        int endColor = mActivity.view.BLUE;
+        int values[] = {startColor, endColor};
+        ArgbEvaluator evaluator = new ArgbEvaluator();
+        PropertyValuesHolder propertyValuesHolder = PropertyValuesHolder.ofInt(propertyName, values);
+        ObjectAnimator colorAnimator = ObjectAnimator.ofPropertyValuesHolder(object, 
+            propertyValuesHolder);
+        colorAnimator.setDuration(1000);
+        colorAnimator.setRepeatCount(1);
+        colorAnimator.setRepeatMode(ValueAnimator.REVERSE);
+        colorAnimator.start();
+        startAnimation(mObjectAnimator, colorAnimator);
+        Thread.sleep(100);
+        Integer i = (Integer) colorAnimator.getAnimatedValue();
+        //We are going from less negative value to a more negative value
+        assertTrue(i.intValue() <= startColor);
+        assertTrue(endColor <= i.intValue());
+    }
+
+    public void testGetPropertyName() throws Throwable {
+        Object object = mActivity.view.newBall;
+        String propertyName = "backgroundColor";
+        int startColor = mActivity.view.RED;
+        int endColor = mActivity.view.BLUE;
+        Object[] values = {new Integer(startColor), new Integer(endColor)};
+        ArgbEvaluator evaluator = new ArgbEvaluator();
+        ObjectAnimator colorAnimator = ObjectAnimator.ofObject(object, propertyName,
+                evaluator, values);
+        String actualPropertyName = colorAnimator.getPropertyName();
+        assertEquals(propertyName, actualPropertyName);
+    }
+
+    public void testSetCurrentPlayTime() throws Throwable {
+        Object object = mActivity.view.newBall;
+        String propertyName = "backgroundColor";
+        int startColor = mActivity.view.RED;
+        int endColor = mActivity.view.BLUE;
+        long playTime = 10000l;
+        Object[] values = {new Integer(startColor), new Integer(endColor)};
+        ArgbEvaluator evaluator = new ArgbEvaluator();
+        ObjectAnimator colorAnimator = ObjectAnimator.ofObject(object, propertyName,
+                evaluator, values);
+        colorAnimator.setCurrentPlayTime(playTime);
+        long actualPlayTime = colorAnimator.getCurrentPlayTime();
+        assertEquals(playTime, actualPlayTime);
+    }
+
+    public void testSetFloatValues() throws Throwable {
+        Object object = mActivity.view.newBall;
+        String property = "y";
+        float startY = mActivity.mStartY;
+        float endY = mActivity.mStartY + mActivity.mDeltaY;
+        float[] values = {startY, endY};
+        ObjectAnimator objAnimator = new ObjectAnimator();
+        objAnimator.setTarget(object);
+        objAnimator.setPropertyName(property);
+        objAnimator.setFloatValues(values);
+        objAnimator.setDuration(mDuration);
+        objAnimator.setRepeatCount(ValueAnimator.INFINITE);
+        objAnimator.setInterpolator(new AccelerateInterpolator());
+        objAnimator.setRepeatMode(ValueAnimator.REVERSE);
+        startAnimation(objAnimator);
+        Thread.sleep(100);
+        float y = mActivity.view.newBall.getY();
+        assertTrue( y >= startY);
+        assertTrue( y <= endY);
+    }
+
+    public void testGetTarget() throws Throwable {
+        Object object = mActivity.view.newBall;
+        String propertyName = "backgroundColor";
+        int startColor = mActivity.view.RED;
+        int endColor = mActivity.view.BLUE;
+        Object[] values = {new Integer(startColor), new Integer(endColor)};
+        ArgbEvaluator evaluator = new ArgbEvaluator();
+        ObjectAnimator colorAnimator = ObjectAnimator.ofObject(object, propertyName,
+                evaluator, values);
+        Object target = colorAnimator.getTarget();
+        assertEquals(object, target);
+    }
+
+    public void testClone() throws Throwable {
+        Object object = mActivity.view.newBall;
+        String property = "y";
+        float startY = mActivity.mStartY;
+        float endY = mActivity.mStartY + mActivity.mDeltaY;
+        Interpolator interpolator = new AccelerateInterpolator();
+        ObjectAnimator objAnimator = ObjectAnimator.ofFloat(object, property, startY, endY);
+        objAnimator.setDuration(mDuration);
+        objAnimator.setRepeatCount(ValueAnimator.INFINITE);
+        objAnimator.setInterpolator(interpolator);
+        objAnimator.setRepeatMode(ValueAnimator.REVERSE);
+        ObjectAnimator cloneAnimator = objAnimator.clone();
+
+        assertEquals(mDuration, cloneAnimator.getDuration());
+        assertEquals(ValueAnimator.INFINITE, cloneAnimator.getRepeatCount());
+        assertEquals(ValueAnimator.REVERSE, cloneAnimator.getRepeatMode());
+        assertEquals(object, cloneAnimator.getTarget());
+        assertEquals(property, cloneAnimator.getPropertyName());
+        assertEquals(interpolator, cloneAnimator.getInterpolator());
+    }
+
+    public void testIsStarted() throws Throwable {
+        Object object = mActivity.view.newBall;
+        String property = "y";
+        float startY = mActivity.mStartY;
+        float endY = mActivity.mStartY + mActivity.mDeltaY;
+        Interpolator interpolator = new AccelerateInterpolator();
+        ObjectAnimator objAnimator = ObjectAnimator.ofFloat(object, property, startY, endY);
+        objAnimator.setDuration(mDuration);
+        objAnimator.setRepeatCount(ValueAnimator.INFINITE);
+        objAnimator.setInterpolator(interpolator);
+        objAnimator.setRepeatMode(ValueAnimator.REVERSE);
+        startAnimation(objAnimator);
+        Thread.sleep(100);
+        assertTrue(objAnimator.isStarted());
+        Thread.sleep(100);
+    }
+
+    private void startAnimation(final ObjectAnimator mObjectAnimator) throws Throwable {
+        Thread mAnimationRunnable = new Thread() {
+            public void run() {
+                mActivity.startAnimation(mObjectAnimator);
+            }
+        };
+        this.runTestOnUiThread(mAnimationRunnable);
+    }
+    private void startAnimation(final ObjectAnimator mObjectAnimator, final
+            ObjectAnimator colorAnimator) throws Throwable {
+        Thread mAnimationRunnable = new Thread() {
+            public void run() {
+                mActivity.startAnimation(mObjectAnimator, colorAnimator);
+            }
+        };
+        this.runTestOnUiThread(mAnimationRunnable);
+    }
+}
+
+
diff --git a/tests/tests/animation/src/android/animation/cts/ShapeHolder.java b/tests/tests/animation/src/android/animation/cts/ShapeHolder.java
new file mode 100644
index 0000000..f8d5fa6
--- /dev/null
+++ b/tests/tests/animation/src/android/animation/cts/ShapeHolder.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.animation.cts;
+
+import android.graphics.drawable.ShapeDrawable;
+import android.graphics.drawable.shapes.Shape;
+import android.graphics.Paint;
+import android.graphics.RadialGradient;
+
+/**
+ * A data structure that holds a Shape and various properties that can be used to define
+ * how the shape is drawn.
+ */
+public class ShapeHolder {
+    private float mX = 0, mY = 0;
+    private ShapeDrawable mShape;
+    private int mColor;
+    private RadialGradient mGradient;
+    private float mAlpha = 1f;
+    private Paint mPaint;
+
+    public void setPaint(Paint value) {
+        mPaint = value;
+    }
+
+    public Paint getPaint() {
+        return mPaint;
+    }
+
+    public void setX(float value) {
+        mX = value;
+    }
+
+    public float getX() {
+        return mX;
+    }
+
+    public void setY(float value) {
+        mY = value;
+    }
+
+    public float getY() {
+        return mY;
+    }
+
+    public void setShape(ShapeDrawable value) {
+        mShape = value;
+    }
+
+    public ShapeDrawable getShape() {
+        return mShape;
+    }
+
+    public int getColor() {
+        return mColor;
+    }
+
+    public void setColor(int value) {
+        mShape.getPaint().setColor(value);
+        mColor = value;
+    }
+
+    public void setGradient(RadialGradient value) {
+        mGradient = value;
+    }
+    public RadialGradient getGradient() {
+        return mGradient;
+    }
+
+    public void setAlpha(float alpha) {
+        this.mAlpha = alpha;
+        mShape.setAlpha((int)((alpha * 255f) + .5f));
+    }
+
+    public float getWidth() {
+        return mShape.getShape().getWidth();
+    }
+
+    public void setWidth(float width) {
+        Shape s = mShape.getShape();
+        s.resize(width, s.getHeight());
+    }
+
+    public float getHeight() {
+        return mShape.getShape().getHeight();
+    }
+
+    public void setHeight(float height) {
+        Shape s = mShape.getShape();
+        s.resize(s.getWidth(), height);
+    }
+
+    public ShapeHolder(ShapeDrawable s) {
+        mShape = s;
+    }
+}
+
diff --git a/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java b/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java
new file mode 100644
index 0000000..a7626bc
--- /dev/null
+++ b/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.animation.cts;
+
+import android.animation.ArgbEvaluator;
+import android.animation.FloatEvaluator;
+import android.animation.IntEvaluator;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.test.ActivityInstrumentationTestCase2;
+import android.view.animation.AccelerateInterpolator;
+
+public class ValueAnimatorTest extends
+        ActivityInstrumentationTestCase2<AnimationActivity> {
+    private AnimationActivity mActivity;
+    private ValueAnimator mValueAnimator;
+    private long mDuration = 1000;
+
+    public ValueAnimatorTest() {
+        super(AnimationActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        setActivityInitialTouchMode(false);
+        mActivity = getActivity();
+        mValueAnimator = mActivity.createAnimatorWithDuration(mDuration);
+    }
+
+    public void testDuration() throws Throwable {
+        final long duration = 2000;
+        ValueAnimator valueAnimatorLocal = mActivity.createAnimatorWithDuration(duration);
+        startAnimation(valueAnimatorLocal);
+        assertEquals(duration, valueAnimatorLocal.getDuration());
+    }
+
+    public void testIsRunning() throws Throwable {
+        assertFalse(mValueAnimator.isRunning());
+        startAnimation(mValueAnimator);
+        ValueAnimator valueAnimatorReturned = mActivity.view.bounceAnimator;
+        assertTrue(valueAnimatorReturned.isRunning());
+    }
+
+    public void testIsStarted() throws Throwable {
+        assertFalse(mValueAnimator.isRunning());
+        assertFalse(mValueAnimator.isStarted());
+        long startDelay = 10000;
+        mValueAnimator.setStartDelay(startDelay);
+        startAnimation(mValueAnimator);
+        assertFalse(mValueAnimator.isRunning());
+        assertTrue(mValueAnimator.isStarted());
+    }
+
+    public void testRepeatMode() throws Throwable {
+        ValueAnimator mValueAnimator = mActivity.createAnimatorWithRepeatMode(ValueAnimator.RESTART);
+        startAnimation(mValueAnimator);
+        assertEquals(ValueAnimator.RESTART, mValueAnimator.getRepeatMode());
+    }
+
+    public void testRepeatCount() throws Throwable {
+        int repeatCount = 2;
+        ValueAnimator mValueAnimator = mActivity.createAnimatorWithRepeatCount(repeatCount);
+        startAnimation(mValueAnimator);
+        assertEquals(repeatCount, mValueAnimator.getRepeatCount());
+    }
+
+    public void testStartDelay() {
+        long startDelay = 1000;
+        mValueAnimator.setStartDelay(startDelay);
+        assertEquals(startDelay, mValueAnimator.getStartDelay());
+    }
+
+    public void testCurrentPlayTime() throws Throwable {
+        startAnimation(mValueAnimator);
+        Thread.sleep(100);
+        long currentPlayTime = mValueAnimator.getCurrentPlayTime();
+        assertTrue(currentPlayTime  >  0);
+    }
+
+    public void testGetFrameDelay() throws Throwable {
+        long frameDelay = 10;
+        mValueAnimator.setFrameDelay(frameDelay);
+        startAnimation(mValueAnimator);
+        Thread.sleep(100);
+        long actualFrameDelay = mValueAnimator.getFrameDelay();
+        assertEquals(frameDelay, actualFrameDelay);
+    }
+
+    public void testSetInterpolator() throws Throwable {
+        AccelerateInterpolator interpolator = new AccelerateInterpolator();
+        ValueAnimator mValueAnimator = mActivity.createAnimatorWithInterpolator(interpolator);
+        startAnimation(mValueAnimator);
+        assertTrue(interpolator.equals(mValueAnimator.getInterpolator()));
+    }
+
+    public void testCancel() throws Throwable {
+        startAnimation(mValueAnimator);
+        Thread.sleep(100);
+        mValueAnimator.cancel();
+        assertFalse(mValueAnimator.isRunning());
+    }
+
+    public void testEnd() throws Throwable {
+        Object object = mActivity.view.newBall;
+        String property = "y";
+        float startY = mActivity.mStartY;
+        float endY = mActivity.mStartY + mActivity.mDeltaY;
+        ObjectAnimator objAnimator = ObjectAnimator.ofFloat(object, property, startY, endY);
+        objAnimator.setDuration(mDuration);
+        objAnimator.setRepeatCount(ValueAnimator.INFINITE);
+        objAnimator.setInterpolator(new AccelerateInterpolator());
+        objAnimator.setRepeatMode(ValueAnimator.REVERSE);
+        startAnimation(objAnimator);
+        Thread.sleep(100);
+        endAnimation(objAnimator);
+        float y = mActivity.view.newBall.getY();
+        assertEquals(y, endY);
+    }
+
+    public void testGetAnimatedFraction() throws Throwable {
+        ValueAnimator objAnimator = getAnimator();
+        startAnimation(objAnimator);
+        assertNotNull(objAnimator);
+        float[] fractions = getValue(objAnimator, 10, "getAnimatedFraction()", 100l, null);
+        for(int j = 0; j < 9; j++){
+            assertTrue(fractions[j] >= 0.0);
+            assertTrue(fractions[j] <= 1.0);
+            assertTrue(fractions[j + 1] != fractions[j]);
+        }
+    }
+
+    public void testGetAnimatedValue() throws Throwable {
+        ValueAnimator objAnimator = getAnimator();
+        startAnimation(objAnimator);
+        assertNotNull(objAnimator);
+        float[] animatedValues = getValue(objAnimator, 10, "getAnimatedValue()", 100l, null);
+
+        for(int j = 0; j < 9; j++){
+            assertTrue(animatedValues[j + 1] != animatedValues[j]);
+        }
+    }
+    public void testGetAnimatedValue_PropertyName() throws Throwable {
+        String property = "y";
+
+        ValueAnimator objAnimator = getAnimator();
+        startAnimation(objAnimator);
+        assertNotNull(objAnimator);
+        float[] animatedValues = getValue(objAnimator, 10, "getAnimatedValue(property)", 100l,
+            property);
+        for(int j = 0; j < 9; j++){
+            assertTrue(animatedValues[j + 1] != animatedValues[j]);
+        }
+    }
+
+    public void testOfFloat() throws Throwable {
+        float start = 0.0f;
+        float end = 1.0f;
+        float[] values = {start, end};
+        final ValueAnimator valueAnimatorLocal = ValueAnimator.ofFloat(values);
+        valueAnimatorLocal.setDuration(mDuration);
+        valueAnimatorLocal.setRepeatCount(ValueAnimator.INFINITE);
+        valueAnimatorLocal.setInterpolator(new AccelerateInterpolator());
+        valueAnimatorLocal.setRepeatMode(ValueAnimator.RESTART);
+
+        this.runTestOnUiThread(new Runnable(){
+            public void run() {
+                valueAnimatorLocal.start();
+            }
+        });
+        Thread.sleep(100);
+        boolean isRunning = valueAnimatorLocal.isRunning();
+        assertTrue(isRunning);
+
+        Float animatedValue = (Float) valueAnimatorLocal.getAnimatedValue();
+        assertTrue(animatedValue >= start);
+        assertTrue(animatedValue <= end);
+    }
+
+    public void testOfInt() throws Throwable {
+        int start = 0;
+        int end = 10;
+        int[] values = {start, end};
+        final ValueAnimator valueAnimatorLocal = ValueAnimator.ofInt(values);
+        valueAnimatorLocal.setDuration(mDuration);
+        valueAnimatorLocal.setRepeatCount(ValueAnimator.INFINITE);
+        valueAnimatorLocal.setInterpolator(new AccelerateInterpolator());
+        valueAnimatorLocal.setRepeatMode(ValueAnimator.RESTART);
+
+        this.runTestOnUiThread(new Runnable(){
+            public void run() {
+                valueAnimatorLocal.start();
+            }
+        });
+        Thread.sleep(100);
+        boolean isRunning = valueAnimatorLocal.isRunning();
+        assertTrue(isRunning);
+
+        Integer animatedValue = (Integer) valueAnimatorLocal.getAnimatedValue();
+        assertTrue(animatedValue >= start);
+        assertTrue(animatedValue <= end);
+    }
+
+    private ValueAnimator getAnimator() {
+        Object object = mActivity.view.newBall;
+        String property = "y";
+        float startY = mActivity.mStartY;
+        float endY = mActivity.mStartY + mActivity.mDeltaY;
+        ValueAnimator objAnimator = ObjectAnimator.ofFloat(object, property, startY, endY);
+        objAnimator.setDuration(mDuration);
+        objAnimator.setRepeatCount(ValueAnimator.INFINITE);
+        objAnimator.setInterpolator(new AccelerateInterpolator());
+        objAnimator.setRepeatMode(ValueAnimator.REVERSE);
+        return objAnimator;
+    }
+
+    private float[] getValue(ValueAnimator animator, int n, String methodName, 
+            long sleepTime, String property) throws InterruptedException {
+        float[] values = new float[n];
+        for(int i = 0; i < (n-1); i++){
+            Thread.sleep(sleepTime);
+            float value = 0.0f;
+            if(methodName.equals("getAnimatedFraction()")) {
+                value = animator.getAnimatedFraction();
+            }else if(methodName.equals("getAnimatedValue()")) {
+              value = ((Float)animator.getAnimatedValue()).floatValue();
+            }else if(methodName.equals("getAnimatedValue(property)")) {
+              value = ((Float)animator.getAnimatedValue(property)).floatValue();
+            }
+            values[i] = value;
+        }
+        return values;
+    }
+    private void startAnimation(final ValueAnimator mValueAnimator) throws Throwable {
+        this.runTestOnUiThread(new Runnable(){
+            public void run() {
+                  mActivity.startAnimation(mValueAnimator);
+            }
+        });
+    }
+    private void endAnimation(final ValueAnimator mValueAnimator) throws Throwable {
+        Thread animationRunnable = new Thread() {
+            public void run() {
+                mValueAnimator.end();
+            }
+        };
+        this.runTestOnUiThread(animationRunnable);
+    }
+}
+
diff --git a/tests/tests/app/src/android/app/cts/ActionBarActivity.java b/tests/tests/app/src/android/app/cts/ActionBarActivity.java
new file mode 100644
index 0000000..11cee03
--- /dev/null
+++ b/tests/tests/app/src/android/app/cts/ActionBarActivity.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app.cts;
+
+import android.app.ActionBar;
+import android.app.Activity;
+import android.os.Bundle;
+
+public class ActionBarActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        ActionBar bar = getActionBar();
+        bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
+    }
+}
diff --git a/tests/tests/app/src/android/app/cts/ActionBarTest.java b/tests/tests/app/src/android/app/cts/ActionBarTest.java
new file mode 100644
index 0000000..796cd74
--- /dev/null
+++ b/tests/tests/app/src/android/app/cts/ActionBarTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app.cts;
+
+import android.app.ActionBar;
+import android.app.ActionBar.Tab;
+import android.app.ActionBar.TabListener;
+import android.app.FragmentTransaction;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+
+public class ActionBarTest extends ActivityInstrumentationTestCase2<ActionBarActivity> {
+
+    private ActionBarActivity mActivity;
+    private ActionBar mBar;
+
+    public ActionBarTest() {
+        super(ActionBarActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+        mBar = mActivity.getActionBar();
+    }
+
+    @UiThreadTest
+    public void testAddTab() {
+        assertEquals(0, mBar.getTabCount());
+
+        Tab t1 = createTab("Tab 1");
+        mBar.addTab(t1);
+        assertEquals(1, mBar.getTabCount());
+        assertEquals(t1, mBar.getSelectedTab());
+        assertEquals(t1, mBar.getTabAt(0));
+
+        Tab t2 = createTab("Tab 2");
+        mBar.addTab(t2);
+        assertEquals(2, mBar.getTabCount());
+        assertEquals(t1, mBar.getSelectedTab());
+        assertEquals(t2, mBar.getTabAt(1));
+
+        Tab t3 = createTab("Tab 3");
+        mBar.addTab(t3, true);
+        assertEquals(3, mBar.getTabCount());
+        assertEquals(t3, mBar.getSelectedTab());
+        assertEquals(t3, mBar.getTabAt(2));
+
+        Tab t4 = createTab("Tab 2.5");
+        mBar.addTab(t4, 2);
+        assertEquals(4, mBar.getTabCount());
+        assertEquals(t4, mBar.getTabAt(2));
+        assertEquals(t3, mBar.getTabAt(3));
+
+        Tab t5 = createTab("Tab 0.5");
+        mBar.addTab(t5, 0, true);
+        assertEquals(5, mBar.getTabCount());
+        assertEquals(t5, mBar.getSelectedTab());
+        assertEquals(t5, mBar.getTabAt(0));
+        assertEquals(t1, mBar.getTabAt(1));
+        assertEquals(t2, mBar.getTabAt(2));
+        assertEquals(t4, mBar.getTabAt(3));
+        assertEquals(t3, mBar.getTabAt(4));
+    }
+
+    private Tab createTab(String name) {
+        return mBar.newTab().setText("Tab 1").setTabListener(new TestTabListener());
+    }
+
+    static class TestTabListener implements TabListener {
+        @Override
+        public void onTabSelected(Tab tab, FragmentTransaction ft) {
+        }
+
+        @Override
+        public void onTabUnselected(Tab tab, FragmentTransaction ft) {
+        }
+
+        @Override
+        public void onTabReselected(Tab tab, FragmentTransaction ft) {
+        }
+    }
+}
diff --git a/tests/tests/app/src/android/app/cts/SystemFeaturesTest.java b/tests/tests/app/src/android/app/cts/SystemFeaturesTest.java
index 41a5224..a68cfb8 100644
--- a/tests/tests/app/src/android/app/cts/SystemFeaturesTest.java
+++ b/tests/tests/app/src/android/app/cts/SystemFeaturesTest.java
@@ -343,14 +343,17 @@
     }
 
     public void testWifiFeature() throws Exception {
+        if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)) {
+            // no WiFi, skip the test
+            return;
+        }
         boolean enabled = mWifiManager.isWifiEnabled();
         try {
-            // WifiManager is hard-coded to return true, but in other implementations this could
-            // return false for devices that don't have WiFi.
+            // WifiManager is hard-coded to return true,
+            // the case without WiFi is already handled,
+            // so this case MUST have WiFi.
             if (mWifiManager.setWifiEnabled(true)) {
                 assertAvailable(PackageManager.FEATURE_WIFI);
-            } else {
-                assertNotAvailable(PackageManager.FEATURE_WIFI);
             }
         } finally {
             if (!enabled) {
diff --git a/tests/tests/content/src/android/content/cts/ContentResolverSyncTestCase.java b/tests/tests/content/src/android/content/cts/ContentResolverSyncTestCase.java
index 1cc4cfb..2da0bfb 100644
--- a/tests/tests/content/src/android/content/cts/ContentResolverSyncTestCase.java
+++ b/tests/tests/content/src/android/content/cts/ContentResolverSyncTestCase.java
@@ -57,6 +57,9 @@
         // Need to clean up created account
         removeAccount(sAccountManager, ACCOUNT, null /* callback */);
 
+        // Need to cancel any sync that was started.
+        cancelSync(null, AUTHORITY, LATCH_TIMEOUT_MS);
+
         super.tearDown();
     }
 
@@ -87,8 +90,8 @@
     }
 
     private CountDownLatch setNewLatch(CountDownLatch latch) {
-        getMockSyncAdapter().setLatch(latch);
         getMockSyncAdapter().clearData();
+        getMockSyncAdapter().setLatch(latch);
         return latch;
     }
 
@@ -101,7 +104,9 @@
 
         // Wait with timeout for the callback to do its work
         try {
-            latch.await(latchTimeoutMs, TimeUnit.MILLISECONDS);
+            if (!latch.await(latchTimeoutMs, TimeUnit.MILLISECONDS)) {
+                fail("should not time out waiting on latch");
+            }
         } catch (InterruptedException e) {
             fail("should not throw an InterruptedException");
         }
diff --git a/tests/tests/dpi/AndroidManifest.xml b/tests/tests/dpi/AndroidManifest.xml
index 562579a..6e141ac 100644
--- a/tests/tests/dpi/AndroidManifest.xml
+++ b/tests/tests/dpi/AndroidManifest.xml
@@ -21,7 +21,7 @@
     <application>
         <uses-library android:name="android.test.runner" />
 
-        <activity android:name="android.dpi.cts.ConfigurationScreenLayoutActivity"
+        <activity android:name="android.dpi.cts.OrientationActivity"
                 android:configChanges="orientation" />
     </application>
 
diff --git a/tests/tests/dpi/src/android/dpi/cts/AspectRatioTest.java b/tests/tests/dpi/src/android/dpi/cts/AspectRatioTest.java
new file mode 100644
index 0000000..74a9f22
--- /dev/null
+++ b/tests/tests/dpi/src/android/dpi/cts/AspectRatioTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.dpi.cts;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.DisplayMetrics;
+import android.view.Display;
+import android.view.WindowManager;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class AspectRatioTest extends ActivityInstrumentationTestCase2<OrientationActivity> {
+
+    private static final int[] ORIENTATIONS = new int[] {
+        ActivityInfo.SCREEN_ORIENTATION_PORTRAIT,
+        ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE,
+    };
+
+    public AspectRatioTest() {
+        super(OrientationActivity.class);
+    }
+
+    /**
+     * Get all the aspect rations in different orientations. They could be
+     * different due to the system bar being different sizes. Test that
+     * one of the aspect ratios is within the range.
+     */
+    public void testAspectRatio() throws Exception {
+        List<Double> aspectRatios = getAllAspectRatios();
+        for (double aspectRatio : aspectRatios) {
+            if (aspectRatio >= 1.333 && aspectRatio <= 1.86) {
+                return;
+            }
+        }
+        fail("Aspect ratios were not between 1.333 and 1.86: " + aspectRatios);
+    }
+
+    private List<Double> getAllAspectRatios() throws Exception {
+        List<Double> aspectRatios = new ArrayList<Double>();
+        for (int i = 0; i < ORIENTATIONS.length; i++) {
+            Activity activity = startOrientationActivity(ORIENTATIONS[i]);
+            aspectRatios.add(getAspectRatio(activity));
+            tearDown();
+        }
+        return aspectRatios;
+    }
+
+    private double getAspectRatio(Context context) {
+        WindowManager windowManager =
+                (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+        Display display = windowManager.getDefaultDisplay();
+        DisplayMetrics metrics = new DisplayMetrics();
+        display.getMetrics(metrics);
+
+        int max = Math.max(metrics.widthPixels, metrics.heightPixels);
+        int min = Math.min(metrics.widthPixels, metrics.heightPixels);
+        return (double) max / min;
+    }
+
+    private Activity startOrientationActivity(int orientation) {
+        Intent intent = new Intent();
+        intent.putExtra(OrientationActivity.EXTRA_ORIENTATION, orientation);
+        setActivityIntent(intent);
+        return getActivity();
+    }
+}
diff --git a/tests/tests/dpi/src/android/dpi/cts/ConfigurationScreenLayoutTest.java b/tests/tests/dpi/src/android/dpi/cts/ConfigurationScreenLayoutTest.java
index 9fce9f1..d4c3611 100644
--- a/tests/tests/dpi/src/android/dpi/cts/ConfigurationScreenLayoutTest.java
+++ b/tests/tests/dpi/src/android/dpi/cts/ConfigurationScreenLayoutTest.java
@@ -27,7 +27,7 @@
 import android.view.WindowManager;
 
 public class ConfigurationScreenLayoutTest
-        extends ActivityInstrumentationTestCase2<ConfigurationScreenLayoutActivity> {
+        extends ActivityInstrumentationTestCase2<OrientationActivity> {
 
     private static final int[] ORIENTATIONS = new int[] {
             ActivityInfo.SCREEN_ORIENTATION_PORTRAIT,
@@ -37,7 +37,7 @@
     };
 
     public ConfigurationScreenLayoutTest() {
-        super(ConfigurationScreenLayoutActivity.class);
+        super(OrientationActivity.class);
     }
 
     public void testScreenLayout() throws Exception {
@@ -82,7 +82,7 @@
 
     private Activity startOrientationActivity(int orientation) {
         Intent intent = new Intent();
-        intent.putExtra(ConfigurationScreenLayoutActivity.EXTRA_ORIENTATION, orientation);
+        intent.putExtra(OrientationActivity.EXTRA_ORIENTATION, orientation);
         setActivityIntent(intent);
         return getActivity();
     }
diff --git a/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java b/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java
index df254d2..937d8f8 100644
--- a/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java
+++ b/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java
@@ -46,12 +46,6 @@
         double density = 160.0d * metrics.density;
         assertTrue("Screen density must be at least 100 dpi: " + density, density >= 100.0d);
 
-        int max = Math.max(metrics.widthPixels, metrics.heightPixels);
-        int min = Math.min(metrics.widthPixels, metrics.heightPixels);
-        double aspectRatio = (double) max / min;
-        assertTrue("Aspect ratio must be between 1.333 and 1.86. It was " + aspectRatio,
-                aspectRatio >= 1.333 && aspectRatio <= 1.86);
-
         Set<Integer> allowedDensities = new HashSet<Integer>();
         allowedDensities.add(DisplayMetrics.DENSITY_LOW);
         allowedDensities.add(DisplayMetrics.DENSITY_MEDIUM);
diff --git a/tests/tests/dpi/src/android/dpi/cts/ConfigurationScreenLayoutActivity.java b/tests/tests/dpi/src/android/dpi/cts/OrientationActivity.java
similarity index 94%
rename from tests/tests/dpi/src/android/dpi/cts/ConfigurationScreenLayoutActivity.java
rename to tests/tests/dpi/src/android/dpi/cts/OrientationActivity.java
index d4d268d..3bd76b6 100644
--- a/tests/tests/dpi/src/android/dpi/cts/ConfigurationScreenLayoutActivity.java
+++ b/tests/tests/dpi/src/android/dpi/cts/OrientationActivity.java
@@ -22,7 +22,7 @@
 import android.view.WindowManager;
 
 /** {@link Activity} that calls {@link #setRequestedOrientation(int)} with the extra value. */
-public class ConfigurationScreenLayoutActivity extends Activity {
+public class OrientationActivity extends Activity {
 
     static final String EXTRA_ORIENTATION = "orientation";
 
diff --git a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
index 42c5f58..169fb56 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
@@ -1247,6 +1247,18 @@
         assertMeasureText(text, textChars, textSpan, 4, 7, widths[4] + widths[5] + widths[6]);
     }
 
+    public void testMeasureTextWithLongText() {
+        final int MAX_COUNT = 65535;
+        char[] longText = new char[MAX_COUNT];
+        for (int n = 0; n < MAX_COUNT; n++) {
+            longText[n] = 'm';
+        }
+
+        Paint p = new Paint();
+        float width = p.measureText(longText, 0, 1);
+        assertEquals(true, width > 0);
+    }
+
     /** Tests that all four overloads of measureText are the same and match some value. */
     private void assertMeasureText(String text, char[] textChars, SpannedString textSpan,
             int start, int end, float expectedWidth) {
diff --git a/tests/tests/graphics2/Android.mk b/tests/tests/graphics2/Android.mk
new file mode 100644
index 0000000..d977ee8
--- /dev/null
+++ b/tests/tests/graphics2/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+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_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsGraphics2TestCases
+
+LOCAL_INSTRUMENTATION_FOR :=
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/tests/tests/graphics2/AndroidManifest.xml b/tests/tests/graphics2/AndroidManifest.xml
new file mode 100644
index 0000000..e26b962
--- /dev/null
+++ b/tests/tests/graphics2/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.cts.graphics2"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-permission android:name="android.permission.CAMERA" />
+    <uses-feature android:name="android.hardware.camera" />
+
+    <instrumentation
+        android:targetPackage="com.android.cts.graphics2"
+        android:name="android.test.InstrumentationTestRunner" />
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+        <activity android:name="android.graphics2.cts.TextureViewCameraActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
diff --git a/tests/tests/graphics2/src/android/graphics2/cts/TextureViewCameraActivity.java b/tests/tests/graphics2/src/android/graphics2/cts/TextureViewCameraActivity.java
new file mode 100644
index 0000000..d947565
--- /dev/null
+++ b/tests/tests/graphics2/src/android/graphics2/cts/TextureViewCameraActivity.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics2.cts;
+
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.SurfaceTexture;
+import android.hardware.Camera;
+import android.os.Bundle;
+import android.view.TextureView;
+import android.view.View;
+
+import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.Assert;
+
+
+public class TextureViewCameraActivity extends Activity implements
+        TextureView.SurfaceTextureListener {
+    private static final int CAPTURE_SCREEN_INTERVAL = 10;
+    private static final float SCREEN_ROTATION_RATE = 1.0f;
+    private static final int MAX_FRAME_UPDATE = 40;
+    private Camera mCamera;
+    private TextureView mTextureView;
+    private int mUpdateCounter = 0;
+    private int mWidth;
+    private int mHeight;
+    private float mRotation = 0f;
+    private final CountDownLatch mLatch = new CountDownLatch(1);
+
+    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
+        Assert.assertTrue(mTextureView.getLayerType() == View.LAYER_TYPE_HARDWARE);
+        Assert.assertTrue(mTextureView.isAvailable());
+        Assert.assertNotNull(mTextureView.getSurfaceTexture());
+        Assert.assertTrue(mTextureView.getSurfaceTextureListener() == this);
+        Assert.assertTrue(mTextureView.isOpaque());
+        mWidth = width;
+        mHeight = height;
+        mCamera = Camera.open();
+
+        try {
+            mCamera.setPreviewTexture(surface);
+            mCamera.startPreview();
+        } catch (IOException ioe) {
+            // Something bad happened
+            Assert.fail();
+        }
+    }
+
+    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+        mWidth = width;
+        mHeight = height;
+    }
+
+    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
+        mCamera.stopPreview();
+        mCamera.release();
+        return true;
+    }
+
+    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+        mUpdateCounter++;
+        if (mUpdateCounter % CAPTURE_SCREEN_INTERVAL == 0) {
+            Canvas canvas = mTextureView.lockCanvas();
+            canvas.drawColor(0xffff0000);
+            mTextureView.unlockCanvasAndPost(canvas);
+            Bitmap bitmap = mTextureView.getBitmap();
+            Assert.assertEquals(mHeight, bitmap.getHeight());
+            Assert.assertEquals(mWidth, bitmap.getWidth());
+            bitmap.recycle();
+            if (mUpdateCounter >= MAX_FRAME_UPDATE) {
+                mLatch.countDown();
+            }
+        }
+        Matrix transformMatrix =  mTextureView.getTransform(null);
+        mRotation += SCREEN_ROTATION_RATE;
+        transformMatrix.setRotate(mRotation, mWidth/2, mHeight/2);
+        mTextureView.setTransform(transformMatrix);
+    }
+
+    public boolean waitForCompletion(long timeoutInSecs) throws InterruptedException {
+        return mLatch.await(timeoutInSecs, TimeUnit.SECONDS);
+    }
+
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        mTextureView = new TextureView(this);
+        mTextureView.setSurfaceTextureListener(this);
+        mTextureView.setOpaque(true);
+        setContentView(mTextureView);
+    }
+}
diff --git a/tests/tests/graphics2/src/android/graphics2/cts/TextureViewTest.java b/tests/tests/graphics2/src/android/graphics2/cts/TextureViewTest.java
new file mode 100644
index 0000000..932a5d5
--- /dev/null
+++ b/tests/tests/graphics2/src/android/graphics2/cts/TextureViewTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics2.cts;
+
+import android.graphics2.cts.TextureViewCameraActivity;
+import android.test.ActivityInstrumentationTestCase2;
+
+
+public class TextureViewTest extends ActivityInstrumentationTestCase2<TextureViewCameraActivity> {
+    private static final long WAIT_TIMEOUT_IN_SECS = 10;
+    private TextureViewCameraActivity mActivity;
+    public TextureViewTest() {
+        super(TextureViewCameraActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+    }
+
+    public void testTextureViewActivity() throws InterruptedException {
+        assertTrue(mActivity.waitForCompletion(WAIT_TIMEOUT_IN_SECS));
+    }
+
+}
+
diff --git a/tests/tests/hardware/src/android/hardware/cts/CameraTest.java b/tests/tests/hardware/src/android/hardware/cts/CameraTest.java
index 3b29f6a..d70938c 100755
--- a/tests/tests/hardware/src/android/hardware/cts/CameraTest.java
+++ b/tests/tests/hardware/src/android/hardware/cts/CameraTest.java
@@ -1863,28 +1863,30 @@
                 // variance is averaged out.
 
                 // Check if the frame interval is too large or too small.
-                double intervalMargin = 30;  // ms
+                // x100 = percent, intervalMargin should be bigger than fpsMargin considering that
+                // fps will be in the order of 10.
+                double intervalMargin = 0.9;
                 long lastArrivalTime = mFrames.get(mFrames.size() - 1);
                 double interval = arrivalTime - lastArrivalTime;
                 if (LOGV) Log.v(TAG, "Frame interval=" + interval);
                 assertTrue("Frame interval (" + interval + "ms) is too large." +
                         " mMaxFrameInterval=" + mMaxFrameInterval + "ms",
-                        interval < mMaxFrameInterval + intervalMargin);
+                        interval < mMaxFrameInterval * (1.0 + intervalMargin));
                 assertTrue("Frame interval (" + interval + "ms) is too small." +
                         " mMinFrameInterval=" + mMinFrameInterval + "ms",
-                        interval > mMinFrameInterval - intervalMargin);
+                        interval > mMinFrameInterval * (1.0 - intervalMargin));
 
                 // Check if the fps is within range.
-                double fpsMargin = 0.05;
+                double fpsMargin = 0.5; // x100 = percent
                 double avgInterval = (double)(arrivalTime - mFrames.get(0))
                         / mFrames.size();
                 double fps = 1000.0 / avgInterval;
                 assertTrue("Actual fps (" + fps + ") should be larger than " +
                            "min fps (" + mMinFps + ")",
-                           fps >= mMinFps * (1 - fpsMargin));
+                           fps >= mMinFps * (1.0 - fpsMargin));
                 assertTrue("Actual fps (" + fps + ") should be smaller than " +
                            "max fps (" + mMaxFps + ")",
-                           fps <= mMaxFps * (1 + fpsMargin));
+                           fps <= mMaxFps * (1.0 + fpsMargin));
             }
             // Add the arrival time of this frame to the list.
             mFrames.add(arrivalTime);
diff --git a/tests/tests/holo/res/drawable-hdpi/holo_calendar_view_feb.png b/tests/tests/holo/res/drawable-hdpi/holo_calendar_view_feb.png
new file mode 100644
index 0000000..1421fbc
--- /dev/null
+++ b/tests/tests/holo/res/drawable-hdpi/holo_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-hdpi/holo_dialog_calendar_view_feb.png b/tests/tests/holo/res/drawable-hdpi/holo_dialog_calendar_view_feb.png
new file mode 100644
index 0000000..1421fbc
--- /dev/null
+++ b/tests/tests/holo/res/drawable-hdpi/holo_dialog_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-hdpi/holo_dialog_minwidth_calendar_view_feb.png b/tests/tests/holo/res/drawable-hdpi/holo_dialog_minwidth_calendar_view_feb.png
new file mode 100644
index 0000000..1421fbc
--- /dev/null
+++ b/tests/tests/holo/res/drawable-hdpi/holo_dialog_minwidth_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-hdpi/holo_dialog_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-hdpi/holo_dialog_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..1421fbc
--- /dev/null
+++ b/tests/tests/holo/res/drawable-hdpi/holo_dialog_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-hdpi/holo_dialog_noactionbar_minwidth_calendar_view_feb.png b/tests/tests/holo/res/drawable-hdpi/holo_dialog_noactionbar_minwidth_calendar_view_feb.png
new file mode 100644
index 0000000..1421fbc
--- /dev/null
+++ b/tests/tests/holo/res/drawable-hdpi/holo_dialog_noactionbar_minwidth_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-hdpi/holo_dialogwhenlarge_calendar_view_feb.png b/tests/tests/holo/res/drawable-hdpi/holo_dialogwhenlarge_calendar_view_feb.png
new file mode 100644
index 0000000..1421fbc
--- /dev/null
+++ b/tests/tests/holo/res/drawable-hdpi/holo_dialogwhenlarge_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-hdpi/holo_dialogwhenlarge_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-hdpi/holo_dialogwhenlarge_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..1421fbc
--- /dev/null
+++ b/tests/tests/holo/res/drawable-hdpi/holo_dialogwhenlarge_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-hdpi/holo_inputmethod_calendar_view_feb.png b/tests/tests/holo/res/drawable-hdpi/holo_inputmethod_calendar_view_feb.png
new file mode 100644
index 0000000..2c0619b
--- /dev/null
+++ b/tests/tests/holo/res/drawable-hdpi/holo_inputmethod_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-hdpi/holo_light_calendar_view_feb.png b/tests/tests/holo/res/drawable-hdpi/holo_light_calendar_view_feb.png
new file mode 100644
index 0000000..2c0619b
--- /dev/null
+++ b/tests/tests/holo/res/drawable-hdpi/holo_light_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-hdpi/holo_light_darkactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-hdpi/holo_light_darkactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..2c0619b
--- /dev/null
+++ b/tests/tests/holo/res/drawable-hdpi/holo_light_darkactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-hdpi/holo_light_dialog_calendar_view_feb.png b/tests/tests/holo/res/drawable-hdpi/holo_light_dialog_calendar_view_feb.png
new file mode 100644
index 0000000..2c0619b
--- /dev/null
+++ b/tests/tests/holo/res/drawable-hdpi/holo_light_dialog_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-hdpi/holo_light_dialog_minwidth_calendar_view_feb.png b/tests/tests/holo/res/drawable-hdpi/holo_light_dialog_minwidth_calendar_view_feb.png
new file mode 100644
index 0000000..2c0619b
--- /dev/null
+++ b/tests/tests/holo/res/drawable-hdpi/holo_light_dialog_minwidth_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-hdpi/holo_light_dialog_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-hdpi/holo_light_dialog_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..2c0619b
--- /dev/null
+++ b/tests/tests/holo/res/drawable-hdpi/holo_light_dialog_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-hdpi/holo_light_dialog_noactionbar_minwidth_calendar_view_feb.png b/tests/tests/holo/res/drawable-hdpi/holo_light_dialog_noactionbar_minwidth_calendar_view_feb.png
new file mode 100644
index 0000000..2c0619b
--- /dev/null
+++ b/tests/tests/holo/res/drawable-hdpi/holo_light_dialog_noactionbar_minwidth_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-hdpi/holo_light_dialogwhenlarge_calendar_view_feb.png b/tests/tests/holo/res/drawable-hdpi/holo_light_dialogwhenlarge_calendar_view_feb.png
new file mode 100644
index 0000000..2c0619b
--- /dev/null
+++ b/tests/tests/holo/res/drawable-hdpi/holo_light_dialogwhenlarge_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-hdpi/holo_light_dialogwhenlarge_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-hdpi/holo_light_dialogwhenlarge_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..2c0619b
--- /dev/null
+++ b/tests/tests/holo/res/drawable-hdpi/holo_light_dialogwhenlarge_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-hdpi/holo_light_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-hdpi/holo_light_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..2c0619b
--- /dev/null
+++ b/tests/tests/holo/res/drawable-hdpi/holo_light_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-hdpi/holo_light_noactionbar_fullscreen_calendar_view_feb.png b/tests/tests/holo/res/drawable-hdpi/holo_light_noactionbar_fullscreen_calendar_view_feb.png
new file mode 100644
index 0000000..2c0619b
--- /dev/null
+++ b/tests/tests/holo/res/drawable-hdpi/holo_light_noactionbar_fullscreen_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-hdpi/holo_light_panel_calendar_view_feb.png b/tests/tests/holo/res/drawable-hdpi/holo_light_panel_calendar_view_feb.png
new file mode 100644
index 0000000..2c0619b
--- /dev/null
+++ b/tests/tests/holo/res/drawable-hdpi/holo_light_panel_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-hdpi/holo_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-hdpi/holo_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..1421fbc
--- /dev/null
+++ b/tests/tests/holo/res/drawable-hdpi/holo_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-hdpi/holo_noactionbar_fullscreen_calendar_view_feb.png b/tests/tests/holo/res/drawable-hdpi/holo_noactionbar_fullscreen_calendar_view_feb.png
new file mode 100644
index 0000000..1421fbc
--- /dev/null
+++ b/tests/tests/holo/res/drawable-hdpi/holo_noactionbar_fullscreen_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-hdpi/holo_panel_calendar_view_feb.png b/tests/tests/holo/res/drawable-hdpi/holo_panel_calendar_view_feb.png
new file mode 100644
index 0000000..1421fbc
--- /dev/null
+++ b/tests/tests/holo/res/drawable-hdpi/holo_panel_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-hdpi/holo_wallpaper_calendar_view_feb.png b/tests/tests/holo/res/drawable-hdpi/holo_wallpaper_calendar_view_feb.png
new file mode 100644
index 0000000..1421fbc
--- /dev/null
+++ b/tests/tests/holo/res/drawable-hdpi/holo_wallpaper_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-hdpi/holo_wallpaper_notitlebar_calendar_view_feb.png b/tests/tests/holo/res/drawable-hdpi/holo_wallpaper_notitlebar_calendar_view_feb.png
new file mode 100644
index 0000000..1421fbc
--- /dev/null
+++ b/tests/tests/holo/res/drawable-hdpi/holo_wallpaper_notitlebar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-ldpi/holo_calendar_view_feb.png b/tests/tests/holo/res/drawable-ldpi/holo_calendar_view_feb.png
new file mode 100644
index 0000000..fc65b4a
--- /dev/null
+++ b/tests/tests/holo/res/drawable-ldpi/holo_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-ldpi/holo_dialog_calendar_view_feb.png b/tests/tests/holo/res/drawable-ldpi/holo_dialog_calendar_view_feb.png
new file mode 100644
index 0000000..fc65b4a
--- /dev/null
+++ b/tests/tests/holo/res/drawable-ldpi/holo_dialog_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-ldpi/holo_dialog_minwidth_calendar_view_feb.png b/tests/tests/holo/res/drawable-ldpi/holo_dialog_minwidth_calendar_view_feb.png
new file mode 100644
index 0000000..fc65b4a
--- /dev/null
+++ b/tests/tests/holo/res/drawable-ldpi/holo_dialog_minwidth_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-ldpi/holo_dialog_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-ldpi/holo_dialog_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..fc65b4a
--- /dev/null
+++ b/tests/tests/holo/res/drawable-ldpi/holo_dialog_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-ldpi/holo_dialog_noactionbar_minwidth_calendar_view_feb.png b/tests/tests/holo/res/drawable-ldpi/holo_dialog_noactionbar_minwidth_calendar_view_feb.png
new file mode 100644
index 0000000..fc65b4a
--- /dev/null
+++ b/tests/tests/holo/res/drawable-ldpi/holo_dialog_noactionbar_minwidth_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-ldpi/holo_dialogwhenlarge_calendar_view_feb.png b/tests/tests/holo/res/drawable-ldpi/holo_dialogwhenlarge_calendar_view_feb.png
new file mode 100644
index 0000000..fc65b4a
--- /dev/null
+++ b/tests/tests/holo/res/drawable-ldpi/holo_dialogwhenlarge_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-ldpi/holo_dialogwhenlarge_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-ldpi/holo_dialogwhenlarge_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..fc65b4a
--- /dev/null
+++ b/tests/tests/holo/res/drawable-ldpi/holo_dialogwhenlarge_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-ldpi/holo_inputmethod_calendar_view_feb.png b/tests/tests/holo/res/drawable-ldpi/holo_inputmethod_calendar_view_feb.png
new file mode 100644
index 0000000..f27f7d2
--- /dev/null
+++ b/tests/tests/holo/res/drawable-ldpi/holo_inputmethod_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-ldpi/holo_light_calendar_view_feb.png b/tests/tests/holo/res/drawable-ldpi/holo_light_calendar_view_feb.png
new file mode 100644
index 0000000..f27f7d2
--- /dev/null
+++ b/tests/tests/holo/res/drawable-ldpi/holo_light_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-ldpi/holo_light_darkactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-ldpi/holo_light_darkactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..f27f7d2
--- /dev/null
+++ b/tests/tests/holo/res/drawable-ldpi/holo_light_darkactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-ldpi/holo_light_dialog_calendar_view_feb.png b/tests/tests/holo/res/drawable-ldpi/holo_light_dialog_calendar_view_feb.png
new file mode 100644
index 0000000..f27f7d2
--- /dev/null
+++ b/tests/tests/holo/res/drawable-ldpi/holo_light_dialog_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-ldpi/holo_light_dialog_minwidth_calendar_view_feb.png b/tests/tests/holo/res/drawable-ldpi/holo_light_dialog_minwidth_calendar_view_feb.png
new file mode 100644
index 0000000..f27f7d2
--- /dev/null
+++ b/tests/tests/holo/res/drawable-ldpi/holo_light_dialog_minwidth_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-ldpi/holo_light_dialog_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-ldpi/holo_light_dialog_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..f27f7d2
--- /dev/null
+++ b/tests/tests/holo/res/drawable-ldpi/holo_light_dialog_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-ldpi/holo_light_dialog_noactionbar_minwidth_calendar_view_feb.png b/tests/tests/holo/res/drawable-ldpi/holo_light_dialog_noactionbar_minwidth_calendar_view_feb.png
new file mode 100644
index 0000000..f27f7d2
--- /dev/null
+++ b/tests/tests/holo/res/drawable-ldpi/holo_light_dialog_noactionbar_minwidth_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-ldpi/holo_light_dialogwhenlarge_calendar_view_feb.png b/tests/tests/holo/res/drawable-ldpi/holo_light_dialogwhenlarge_calendar_view_feb.png
new file mode 100644
index 0000000..f27f7d2
--- /dev/null
+++ b/tests/tests/holo/res/drawable-ldpi/holo_light_dialogwhenlarge_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-ldpi/holo_light_dialogwhenlarge_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-ldpi/holo_light_dialogwhenlarge_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..f27f7d2
--- /dev/null
+++ b/tests/tests/holo/res/drawable-ldpi/holo_light_dialogwhenlarge_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-ldpi/holo_light_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-ldpi/holo_light_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..f27f7d2
--- /dev/null
+++ b/tests/tests/holo/res/drawable-ldpi/holo_light_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-ldpi/holo_light_noactionbar_fullscreen_calendar_view_feb.png b/tests/tests/holo/res/drawable-ldpi/holo_light_noactionbar_fullscreen_calendar_view_feb.png
new file mode 100644
index 0000000..f27f7d2
--- /dev/null
+++ b/tests/tests/holo/res/drawable-ldpi/holo_light_noactionbar_fullscreen_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-ldpi/holo_light_panel_calendar_view_feb.png b/tests/tests/holo/res/drawable-ldpi/holo_light_panel_calendar_view_feb.png
new file mode 100644
index 0000000..f27f7d2
--- /dev/null
+++ b/tests/tests/holo/res/drawable-ldpi/holo_light_panel_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-ldpi/holo_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-ldpi/holo_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..fc65b4a
--- /dev/null
+++ b/tests/tests/holo/res/drawable-ldpi/holo_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-ldpi/holo_noactionbar_fullscreen_calendar_view_feb.png b/tests/tests/holo/res/drawable-ldpi/holo_noactionbar_fullscreen_calendar_view_feb.png
new file mode 100644
index 0000000..fc65b4a
--- /dev/null
+++ b/tests/tests/holo/res/drawable-ldpi/holo_noactionbar_fullscreen_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-ldpi/holo_panel_calendar_view_feb.png b/tests/tests/holo/res/drawable-ldpi/holo_panel_calendar_view_feb.png
new file mode 100644
index 0000000..fc65b4a
--- /dev/null
+++ b/tests/tests/holo/res/drawable-ldpi/holo_panel_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-ldpi/holo_wallpaper_calendar_view_feb.png b/tests/tests/holo/res/drawable-ldpi/holo_wallpaper_calendar_view_feb.png
new file mode 100644
index 0000000..fc65b4a
--- /dev/null
+++ b/tests/tests/holo/res/drawable-ldpi/holo_wallpaper_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-ldpi/holo_wallpaper_notitlebar_calendar_view_feb.png b/tests/tests/holo/res/drawable-ldpi/holo_wallpaper_notitlebar_calendar_view_feb.png
new file mode 100644
index 0000000..fc65b4a
--- /dev/null
+++ b/tests/tests/holo/res/drawable-ldpi/holo_wallpaper_notitlebar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-mdpi/holo_calendar_view_feb.png b/tests/tests/holo/res/drawable-mdpi/holo_calendar_view_feb.png
new file mode 100644
index 0000000..aed3bc0
--- /dev/null
+++ b/tests/tests/holo/res/drawable-mdpi/holo_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-mdpi/holo_dialog_calendar_view_feb.png b/tests/tests/holo/res/drawable-mdpi/holo_dialog_calendar_view_feb.png
new file mode 100644
index 0000000..aed3bc0
--- /dev/null
+++ b/tests/tests/holo/res/drawable-mdpi/holo_dialog_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-mdpi/holo_dialog_minwidth_calendar_view_feb.png b/tests/tests/holo/res/drawable-mdpi/holo_dialog_minwidth_calendar_view_feb.png
new file mode 100644
index 0000000..aed3bc0
--- /dev/null
+++ b/tests/tests/holo/res/drawable-mdpi/holo_dialog_minwidth_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-mdpi/holo_dialog_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-mdpi/holo_dialog_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..aed3bc0
--- /dev/null
+++ b/tests/tests/holo/res/drawable-mdpi/holo_dialog_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-mdpi/holo_dialog_noactionbar_minwidth_calendar_view_feb.png b/tests/tests/holo/res/drawable-mdpi/holo_dialog_noactionbar_minwidth_calendar_view_feb.png
new file mode 100644
index 0000000..aed3bc0
--- /dev/null
+++ b/tests/tests/holo/res/drawable-mdpi/holo_dialog_noactionbar_minwidth_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-mdpi/holo_dialogwhenlarge_calendar_view_feb.png b/tests/tests/holo/res/drawable-mdpi/holo_dialogwhenlarge_calendar_view_feb.png
new file mode 100644
index 0000000..aed3bc0
--- /dev/null
+++ b/tests/tests/holo/res/drawable-mdpi/holo_dialogwhenlarge_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-mdpi/holo_dialogwhenlarge_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-mdpi/holo_dialogwhenlarge_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..aed3bc0
--- /dev/null
+++ b/tests/tests/holo/res/drawable-mdpi/holo_dialogwhenlarge_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-mdpi/holo_inputmethod_calendar_view_feb.png b/tests/tests/holo/res/drawable-mdpi/holo_inputmethod_calendar_view_feb.png
new file mode 100644
index 0000000..a457bc3
--- /dev/null
+++ b/tests/tests/holo/res/drawable-mdpi/holo_inputmethod_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-mdpi/holo_light_calendar_view_feb.png b/tests/tests/holo/res/drawable-mdpi/holo_light_calendar_view_feb.png
new file mode 100644
index 0000000..a457bc3
--- /dev/null
+++ b/tests/tests/holo/res/drawable-mdpi/holo_light_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-mdpi/holo_light_darkactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-mdpi/holo_light_darkactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..a457bc3
--- /dev/null
+++ b/tests/tests/holo/res/drawable-mdpi/holo_light_darkactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-mdpi/holo_light_dialog_calendar_view_feb.png b/tests/tests/holo/res/drawable-mdpi/holo_light_dialog_calendar_view_feb.png
new file mode 100644
index 0000000..a457bc3
--- /dev/null
+++ b/tests/tests/holo/res/drawable-mdpi/holo_light_dialog_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-mdpi/holo_light_dialog_minwidth_calendar_view_feb.png b/tests/tests/holo/res/drawable-mdpi/holo_light_dialog_minwidth_calendar_view_feb.png
new file mode 100644
index 0000000..a457bc3
--- /dev/null
+++ b/tests/tests/holo/res/drawable-mdpi/holo_light_dialog_minwidth_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-mdpi/holo_light_dialog_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-mdpi/holo_light_dialog_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..a457bc3
--- /dev/null
+++ b/tests/tests/holo/res/drawable-mdpi/holo_light_dialog_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-mdpi/holo_light_dialog_noactionbar_minwidth_calendar_view_feb.png b/tests/tests/holo/res/drawable-mdpi/holo_light_dialog_noactionbar_minwidth_calendar_view_feb.png
new file mode 100644
index 0000000..a457bc3
--- /dev/null
+++ b/tests/tests/holo/res/drawable-mdpi/holo_light_dialog_noactionbar_minwidth_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-mdpi/holo_light_dialogwhenlarge_calendar_view_feb.png b/tests/tests/holo/res/drawable-mdpi/holo_light_dialogwhenlarge_calendar_view_feb.png
new file mode 100644
index 0000000..a457bc3
--- /dev/null
+++ b/tests/tests/holo/res/drawable-mdpi/holo_light_dialogwhenlarge_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-mdpi/holo_light_dialogwhenlarge_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-mdpi/holo_light_dialogwhenlarge_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..a457bc3
--- /dev/null
+++ b/tests/tests/holo/res/drawable-mdpi/holo_light_dialogwhenlarge_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-mdpi/holo_light_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-mdpi/holo_light_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..a457bc3
--- /dev/null
+++ b/tests/tests/holo/res/drawable-mdpi/holo_light_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-mdpi/holo_light_noactionbar_fullscreen_calendar_view_feb.png b/tests/tests/holo/res/drawable-mdpi/holo_light_noactionbar_fullscreen_calendar_view_feb.png
new file mode 100644
index 0000000..a457bc3
--- /dev/null
+++ b/tests/tests/holo/res/drawable-mdpi/holo_light_noactionbar_fullscreen_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-mdpi/holo_light_panel_calendar_view_feb.png b/tests/tests/holo/res/drawable-mdpi/holo_light_panel_calendar_view_feb.png
new file mode 100644
index 0000000..a457bc3
--- /dev/null
+++ b/tests/tests/holo/res/drawable-mdpi/holo_light_panel_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-mdpi/holo_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-mdpi/holo_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..aed3bc0
--- /dev/null
+++ b/tests/tests/holo/res/drawable-mdpi/holo_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-mdpi/holo_noactionbar_fullscreen_calendar_view_feb.png b/tests/tests/holo/res/drawable-mdpi/holo_noactionbar_fullscreen_calendar_view_feb.png
new file mode 100644
index 0000000..aed3bc0
--- /dev/null
+++ b/tests/tests/holo/res/drawable-mdpi/holo_noactionbar_fullscreen_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-mdpi/holo_panel_calendar_view_feb.png b/tests/tests/holo/res/drawable-mdpi/holo_panel_calendar_view_feb.png
new file mode 100644
index 0000000..aed3bc0
--- /dev/null
+++ b/tests/tests/holo/res/drawable-mdpi/holo_panel_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-mdpi/holo_wallpaper_calendar_view_feb.png b/tests/tests/holo/res/drawable-mdpi/holo_wallpaper_calendar_view_feb.png
new file mode 100644
index 0000000..aed3bc0
--- /dev/null
+++ b/tests/tests/holo/res/drawable-mdpi/holo_wallpaper_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-mdpi/holo_wallpaper_notitlebar_calendar_view_feb.png b/tests/tests/holo/res/drawable-mdpi/holo_wallpaper_notitlebar_calendar_view_feb.png
new file mode 100644
index 0000000..aed3bc0
--- /dev/null
+++ b/tests/tests/holo/res/drawable-mdpi/holo_wallpaper_notitlebar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-tvdpi/holo_calendar_view_feb.png b/tests/tests/holo/res/drawable-tvdpi/holo_calendar_view_feb.png
new file mode 100644
index 0000000..f6682f0
--- /dev/null
+++ b/tests/tests/holo/res/drawable-tvdpi/holo_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-tvdpi/holo_dialog_calendar_view_feb.png b/tests/tests/holo/res/drawable-tvdpi/holo_dialog_calendar_view_feb.png
new file mode 100644
index 0000000..f6682f0
--- /dev/null
+++ b/tests/tests/holo/res/drawable-tvdpi/holo_dialog_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-tvdpi/holo_dialog_minwidth_calendar_view_feb.png b/tests/tests/holo/res/drawable-tvdpi/holo_dialog_minwidth_calendar_view_feb.png
new file mode 100644
index 0000000..f6682f0
--- /dev/null
+++ b/tests/tests/holo/res/drawable-tvdpi/holo_dialog_minwidth_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-tvdpi/holo_dialog_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-tvdpi/holo_dialog_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..f6682f0
--- /dev/null
+++ b/tests/tests/holo/res/drawable-tvdpi/holo_dialog_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-tvdpi/holo_dialog_noactionbar_minwidth_calendar_view_feb.png b/tests/tests/holo/res/drawable-tvdpi/holo_dialog_noactionbar_minwidth_calendar_view_feb.png
new file mode 100644
index 0000000..f6682f0
--- /dev/null
+++ b/tests/tests/holo/res/drawable-tvdpi/holo_dialog_noactionbar_minwidth_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-tvdpi/holo_dialogwhenlarge_calendar_view_feb.png b/tests/tests/holo/res/drawable-tvdpi/holo_dialogwhenlarge_calendar_view_feb.png
new file mode 100644
index 0000000..f6682f0
--- /dev/null
+++ b/tests/tests/holo/res/drawable-tvdpi/holo_dialogwhenlarge_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-tvdpi/holo_dialogwhenlarge_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-tvdpi/holo_dialogwhenlarge_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..f6682f0
--- /dev/null
+++ b/tests/tests/holo/res/drawable-tvdpi/holo_dialogwhenlarge_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-tvdpi/holo_inputmethod_calendar_view_feb.png b/tests/tests/holo/res/drawable-tvdpi/holo_inputmethod_calendar_view_feb.png
new file mode 100644
index 0000000..afefcfb
--- /dev/null
+++ b/tests/tests/holo/res/drawable-tvdpi/holo_inputmethod_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-tvdpi/holo_light_calendar_view_feb.png b/tests/tests/holo/res/drawable-tvdpi/holo_light_calendar_view_feb.png
new file mode 100644
index 0000000..afefcfb
--- /dev/null
+++ b/tests/tests/holo/res/drawable-tvdpi/holo_light_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-tvdpi/holo_light_darkactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-tvdpi/holo_light_darkactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..afefcfb
--- /dev/null
+++ b/tests/tests/holo/res/drawable-tvdpi/holo_light_darkactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-tvdpi/holo_light_dialog_calendar_view_feb.png b/tests/tests/holo/res/drawable-tvdpi/holo_light_dialog_calendar_view_feb.png
new file mode 100644
index 0000000..afefcfb
--- /dev/null
+++ b/tests/tests/holo/res/drawable-tvdpi/holo_light_dialog_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-tvdpi/holo_light_dialog_minwidth_calendar_view_feb.png b/tests/tests/holo/res/drawable-tvdpi/holo_light_dialog_minwidth_calendar_view_feb.png
new file mode 100644
index 0000000..afefcfb
--- /dev/null
+++ b/tests/tests/holo/res/drawable-tvdpi/holo_light_dialog_minwidth_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-tvdpi/holo_light_dialog_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-tvdpi/holo_light_dialog_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..afefcfb
--- /dev/null
+++ b/tests/tests/holo/res/drawable-tvdpi/holo_light_dialog_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-tvdpi/holo_light_dialog_noactionbar_minwidth_calendar_view_feb.png b/tests/tests/holo/res/drawable-tvdpi/holo_light_dialog_noactionbar_minwidth_calendar_view_feb.png
new file mode 100644
index 0000000..afefcfb
--- /dev/null
+++ b/tests/tests/holo/res/drawable-tvdpi/holo_light_dialog_noactionbar_minwidth_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-tvdpi/holo_light_dialogwhenlarge_calendar_view_feb.png b/tests/tests/holo/res/drawable-tvdpi/holo_light_dialogwhenlarge_calendar_view_feb.png
new file mode 100644
index 0000000..afefcfb
--- /dev/null
+++ b/tests/tests/holo/res/drawable-tvdpi/holo_light_dialogwhenlarge_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-tvdpi/holo_light_dialogwhenlarge_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-tvdpi/holo_light_dialogwhenlarge_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..afefcfb
--- /dev/null
+++ b/tests/tests/holo/res/drawable-tvdpi/holo_light_dialogwhenlarge_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-tvdpi/holo_light_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-tvdpi/holo_light_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..afefcfb
--- /dev/null
+++ b/tests/tests/holo/res/drawable-tvdpi/holo_light_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-tvdpi/holo_light_noactionbar_fullscreen_calendar_view_feb.png b/tests/tests/holo/res/drawable-tvdpi/holo_light_noactionbar_fullscreen_calendar_view_feb.png
new file mode 100644
index 0000000..afefcfb
--- /dev/null
+++ b/tests/tests/holo/res/drawable-tvdpi/holo_light_noactionbar_fullscreen_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-tvdpi/holo_light_panel_calendar_view_feb.png b/tests/tests/holo/res/drawable-tvdpi/holo_light_panel_calendar_view_feb.png
new file mode 100644
index 0000000..afefcfb
--- /dev/null
+++ b/tests/tests/holo/res/drawable-tvdpi/holo_light_panel_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-tvdpi/holo_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-tvdpi/holo_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..f6682f0
--- /dev/null
+++ b/tests/tests/holo/res/drawable-tvdpi/holo_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-tvdpi/holo_noactionbar_fullscreen_calendar_view_feb.png b/tests/tests/holo/res/drawable-tvdpi/holo_noactionbar_fullscreen_calendar_view_feb.png
new file mode 100644
index 0000000..f6682f0
--- /dev/null
+++ b/tests/tests/holo/res/drawable-tvdpi/holo_noactionbar_fullscreen_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-tvdpi/holo_panel_calendar_view_feb.png b/tests/tests/holo/res/drawable-tvdpi/holo_panel_calendar_view_feb.png
new file mode 100644
index 0000000..f6682f0
--- /dev/null
+++ b/tests/tests/holo/res/drawable-tvdpi/holo_panel_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-tvdpi/holo_wallpaper_calendar_view_feb.png b/tests/tests/holo/res/drawable-tvdpi/holo_wallpaper_calendar_view_feb.png
new file mode 100644
index 0000000..f6682f0
--- /dev/null
+++ b/tests/tests/holo/res/drawable-tvdpi/holo_wallpaper_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-tvdpi/holo_wallpaper_notitlebar_calendar_view_feb.png b/tests/tests/holo/res/drawable-tvdpi/holo_wallpaper_notitlebar_calendar_view_feb.png
new file mode 100644
index 0000000..f6682f0
--- /dev/null
+++ b/tests/tests/holo/res/drawable-tvdpi/holo_wallpaper_notitlebar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-xhdpi/holo_calendar_view_feb.png b/tests/tests/holo/res/drawable-xhdpi/holo_calendar_view_feb.png
new file mode 100644
index 0000000..37f6f4f
--- /dev/null
+++ b/tests/tests/holo/res/drawable-xhdpi/holo_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-xhdpi/holo_dialog_calendar_view_feb.png b/tests/tests/holo/res/drawable-xhdpi/holo_dialog_calendar_view_feb.png
new file mode 100644
index 0000000..37f6f4f
--- /dev/null
+++ b/tests/tests/holo/res/drawable-xhdpi/holo_dialog_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-xhdpi/holo_dialog_minwidth_calendar_view_feb.png b/tests/tests/holo/res/drawable-xhdpi/holo_dialog_minwidth_calendar_view_feb.png
new file mode 100644
index 0000000..37f6f4f
--- /dev/null
+++ b/tests/tests/holo/res/drawable-xhdpi/holo_dialog_minwidth_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-xhdpi/holo_dialog_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-xhdpi/holo_dialog_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..37f6f4f
--- /dev/null
+++ b/tests/tests/holo/res/drawable-xhdpi/holo_dialog_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-xhdpi/holo_dialog_noactionbar_minwidth_calendar_view_feb.png b/tests/tests/holo/res/drawable-xhdpi/holo_dialog_noactionbar_minwidth_calendar_view_feb.png
new file mode 100644
index 0000000..37f6f4f
--- /dev/null
+++ b/tests/tests/holo/res/drawable-xhdpi/holo_dialog_noactionbar_minwidth_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-xhdpi/holo_dialogwhenlarge_calendar_view_feb.png b/tests/tests/holo/res/drawable-xhdpi/holo_dialogwhenlarge_calendar_view_feb.png
new file mode 100644
index 0000000..37f6f4f
--- /dev/null
+++ b/tests/tests/holo/res/drawable-xhdpi/holo_dialogwhenlarge_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-xhdpi/holo_dialogwhenlarge_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-xhdpi/holo_dialogwhenlarge_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..37f6f4f
--- /dev/null
+++ b/tests/tests/holo/res/drawable-xhdpi/holo_dialogwhenlarge_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-xhdpi/holo_inputmethod_calendar_view_feb.png b/tests/tests/holo/res/drawable-xhdpi/holo_inputmethod_calendar_view_feb.png
new file mode 100644
index 0000000..3e7e915
--- /dev/null
+++ b/tests/tests/holo/res/drawable-xhdpi/holo_inputmethod_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-xhdpi/holo_light_calendar_view_feb.png b/tests/tests/holo/res/drawable-xhdpi/holo_light_calendar_view_feb.png
new file mode 100644
index 0000000..3e7e915
--- /dev/null
+++ b/tests/tests/holo/res/drawable-xhdpi/holo_light_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-xhdpi/holo_light_darkactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-xhdpi/holo_light_darkactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..3e7e915
--- /dev/null
+++ b/tests/tests/holo/res/drawable-xhdpi/holo_light_darkactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-xhdpi/holo_light_dialog_calendar_view_feb.png b/tests/tests/holo/res/drawable-xhdpi/holo_light_dialog_calendar_view_feb.png
new file mode 100644
index 0000000..3e7e915
--- /dev/null
+++ b/tests/tests/holo/res/drawable-xhdpi/holo_light_dialog_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-xhdpi/holo_light_dialog_minwidth_calendar_view_feb.png b/tests/tests/holo/res/drawable-xhdpi/holo_light_dialog_minwidth_calendar_view_feb.png
new file mode 100644
index 0000000..3e7e915
--- /dev/null
+++ b/tests/tests/holo/res/drawable-xhdpi/holo_light_dialog_minwidth_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-xhdpi/holo_light_dialog_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-xhdpi/holo_light_dialog_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..3e7e915
--- /dev/null
+++ b/tests/tests/holo/res/drawable-xhdpi/holo_light_dialog_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-xhdpi/holo_light_dialog_noactionbar_minwidth_calendar_view_feb.png b/tests/tests/holo/res/drawable-xhdpi/holo_light_dialog_noactionbar_minwidth_calendar_view_feb.png
new file mode 100644
index 0000000..3e7e915
--- /dev/null
+++ b/tests/tests/holo/res/drawable-xhdpi/holo_light_dialog_noactionbar_minwidth_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-xhdpi/holo_light_dialogwhenlarge_calendar_view_feb.png b/tests/tests/holo/res/drawable-xhdpi/holo_light_dialogwhenlarge_calendar_view_feb.png
new file mode 100644
index 0000000..3e7e915
--- /dev/null
+++ b/tests/tests/holo/res/drawable-xhdpi/holo_light_dialogwhenlarge_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-xhdpi/holo_light_dialogwhenlarge_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-xhdpi/holo_light_dialogwhenlarge_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..3e7e915
--- /dev/null
+++ b/tests/tests/holo/res/drawable-xhdpi/holo_light_dialogwhenlarge_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-xhdpi/holo_light_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-xhdpi/holo_light_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..3e7e915
--- /dev/null
+++ b/tests/tests/holo/res/drawable-xhdpi/holo_light_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-xhdpi/holo_light_noactionbar_fullscreen_calendar_view_feb.png b/tests/tests/holo/res/drawable-xhdpi/holo_light_noactionbar_fullscreen_calendar_view_feb.png
new file mode 100644
index 0000000..3e7e915
--- /dev/null
+++ b/tests/tests/holo/res/drawable-xhdpi/holo_light_noactionbar_fullscreen_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-xhdpi/holo_light_panel_calendar_view_feb.png b/tests/tests/holo/res/drawable-xhdpi/holo_light_panel_calendar_view_feb.png
new file mode 100644
index 0000000..3e7e915
--- /dev/null
+++ b/tests/tests/holo/res/drawable-xhdpi/holo_light_panel_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-xhdpi/holo_noactionbar_calendar_view_feb.png b/tests/tests/holo/res/drawable-xhdpi/holo_noactionbar_calendar_view_feb.png
new file mode 100644
index 0000000..37f6f4f
--- /dev/null
+++ b/tests/tests/holo/res/drawable-xhdpi/holo_noactionbar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-xhdpi/holo_noactionbar_fullscreen_calendar_view_feb.png b/tests/tests/holo/res/drawable-xhdpi/holo_noactionbar_fullscreen_calendar_view_feb.png
new file mode 100644
index 0000000..37f6f4f
--- /dev/null
+++ b/tests/tests/holo/res/drawable-xhdpi/holo_noactionbar_fullscreen_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-xhdpi/holo_panel_calendar_view_feb.png b/tests/tests/holo/res/drawable-xhdpi/holo_panel_calendar_view_feb.png
new file mode 100644
index 0000000..37f6f4f
--- /dev/null
+++ b/tests/tests/holo/res/drawable-xhdpi/holo_panel_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-xhdpi/holo_wallpaper_calendar_view_feb.png b/tests/tests/holo/res/drawable-xhdpi/holo_wallpaper_calendar_view_feb.png
new file mode 100644
index 0000000..37f6f4f
--- /dev/null
+++ b/tests/tests/holo/res/drawable-xhdpi/holo_wallpaper_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/drawable-xhdpi/holo_wallpaper_notitlebar_calendar_view_feb.png b/tests/tests/holo/res/drawable-xhdpi/holo_wallpaper_notitlebar_calendar_view_feb.png
new file mode 100644
index 0000000..37f6f4f
--- /dev/null
+++ b/tests/tests/holo/res/drawable-xhdpi/holo_wallpaper_notitlebar_calendar_view_feb.png
Binary files differ
diff --git a/tests/tests/holo/res/values/strings.xml b/tests/tests/holo/res/values/strings.xml
index 61550cb..5eb7d82 100644
--- a/tests/tests/holo/res/values/strings.xml
+++ b/tests/tests/holo/res/values/strings.xml
@@ -40,7 +40,8 @@
 
     <string name="button">Button</string>
     <string name="button_pressed">Button Pressed</string>
-    <string name="calendarview">CalendarView</string>
+    <string name="calendarview_jan">CalendarView (January)</string>
+    <string name="calendarview_feb">CalendarView (February)</string>
     <string name="checkbox">CheckBox</string>
     <string name="checkbox_checked">CheckBox Checked</string>
     <string name="chronometer">Chronometer</string>
diff --git a/tests/tests/holo/src/android/holo/cts/AllThemesIterator.java b/tests/tests/holo/src/android/holo/cts/AllThemesIterator.java
index d403d8d..4ddc187 100644
--- a/tests/tests/holo/src/android/holo/cts/AllThemesIterator.java
+++ b/tests/tests/holo/src/android/holo/cts/AllThemesIterator.java
@@ -26,14 +26,17 @@
 class AllThemesIterator implements Iterator<Intent> {
 
     private final ThemeAdapter mThemeAdapter = new ThemeAdapter(null);
-    private final LayoutAdapter mLayoutAdapter = new LayoutAdapter(null);
+    private final LayoutAdapter mLayoutAdapter;
 
     private final int mTask;
+    private final int mAdapterMode;
     private int mThemeIndex;
     private int mLayoutIndex;
 
-    AllThemesIterator(int task) {
+    AllThemesIterator(int task, int adapterMode) {
         mTask = task;
+        mAdapterMode = adapterMode;
+        mLayoutAdapter = new LayoutAdapter(null, adapterMode);
     }
 
     @Override
@@ -46,6 +49,7 @@
         Intent intent = new Intent();
         intent.putExtra(LayoutTestActivity.EXTRA_THEME_INDEX, mThemeIndex);
         intent.putExtra(LayoutTestActivity.EXTRA_LAYOUT_INDEX, mLayoutIndex);
+        intent.putExtra(LayoutTestActivity.EXTRA_LAYOUT_ADAPTER_MODE, mAdapterMode);
         intent.putExtra(LayoutTestActivity.EXTRA_TASK, mTask);
 
         mLayoutIndex++;
diff --git a/tests/tests/holo/src/android/holo/cts/HoloTest.java b/tests/tests/holo/src/android/holo/cts/HoloTest.java
index e47cf01..f3e7e63 100644
--- a/tests/tests/holo/src/android/holo/cts/HoloTest.java
+++ b/tests/tests/holo/src/android/holo/cts/HoloTest.java
@@ -131,6 +131,7 @@
         Intent intent = new Intent();
         intent.putExtra(ThemeTestActivity.EXTRA_TASK, ThemeTestActivity.TASK_COMPARE_BITMAPS);
         intent.putExtra(ThemeTestActivity.EXTRA_THEME_INDEX, themeIndex);
+        intent.putExtra(ThemeTestActivity.EXTRA_LAYOUT_ADAPTER_MODE, LayoutAdapter.MODE_TESTING);
         setActivityIntent(intent);
 
         // Enable touch mode or else widgets will be highlighted causing bitmap
diff --git a/tests/tests/holo/src/android/holo/cts/HoloTestUtilitiesActivity.java b/tests/tests/holo/src/android/holo/cts/HoloTestUtilitiesActivity.java
index 3fa4184e4..3092490 100644
--- a/tests/tests/holo/src/android/holo/cts/HoloTestUtilitiesActivity.java
+++ b/tests/tests/holo/src/android/holo/cts/HoloTestUtilitiesActivity.java
@@ -137,6 +137,7 @@
     private void generateAllBitmaps() {
         Intent intent = new Intent(this, ThemeTestActivity.class);
         intent.putExtra(ThemeTestActivity.EXTRA_TASK, ThemeTestActivity.TASK_GENERATE_BITMAPS);
+        intent.putExtra(ThemeTestActivity.EXTRA_LAYOUT_ADAPTER_MODE, LayoutAdapter.MODE_TESTING);
         startActivity(intent);
     }
 
diff --git a/tests/tests/holo/src/android/holo/cts/LayoutAdapter.java b/tests/tests/holo/src/android/holo/cts/LayoutAdapter.java
index 539f4f8..d7732a9 100644
--- a/tests/tests/holo/src/android/holo/cts/LayoutAdapter.java
+++ b/tests/tests/holo/src/android/holo/cts/LayoutAdapter.java
@@ -22,7 +22,6 @@
 import android.holo.cts.modifiers.SearchViewModifier;
 import android.holo.cts.modifiers.TabHostModifier;
 import android.holo.cts.modifiers.TimePickerModifier;
-import android.holo.cts.modifiers.ViewPressedModifier;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -30,6 +29,7 @@
 import android.widget.TextView;
 
 import java.util.ArrayList;
+import java.util.Calendar;
 import java.util.List;
 
 /**
@@ -37,6 +37,12 @@
  */
 class LayoutAdapter extends BaseAdapter {
 
+    /** Mode where we are just viewing all the layouts. */
+    static final int MODE_VIEWING = 0;
+
+    /** Mode where we are testing and may not include some layouts based on the device state. */
+    static final int MODE_TESTING = 1;
+
     /** No timeout for widgets in layouts that aren't changed after inflation.  */
     private static final int NO_TIMEOUT_MS = 0;
 
@@ -92,7 +98,7 @@
 
     private final LayoutInflater mInflater;
 
-    LayoutAdapter(LayoutInflater inflater) {
+    LayoutAdapter(LayoutInflater inflater, int adapterMode) {
         mInflater = inflater;
 
         // Widgets
@@ -103,8 +109,7 @@
 //        addLayout(R.string.button_pressed, "button_pressed",
 //                R.layout.button, new ViewPressedModifier(), LONG_TIMEOUT_MS);
 
-        addLayout(R.string.calendarview, "calendar_view",
-                R.layout.calendarview, new CalendarViewModifier(), SHORT_TIMEOUT_MS);
+        addCalendarLayouts(adapterMode);
 
         addLayout(R.string.checkbox, "checkbox",
                 R.layout.checkbox, null, NO_TIMEOUT_MS);
@@ -214,8 +219,11 @@
         addLayout(R.string.togglebutton_checked, "toggle_button_checked",
                 R.layout.togglebutton_checked, null, NO_TIMEOUT_MS);
 
-        addLayout(R.string.zoomcontrols, "zoomcontrols",
-                R.layout.zoomcontrols, null, NO_TIMEOUT_MS);
+
+        // TODO: Zoom control hasn't been styled for Holo so don't test them.
+
+//        addLayout(R.string.zoomcontrols, "zoomcontrols",
+//                R.layout.zoomcontrols, null, NO_TIMEOUT_MS);
 
         // Dialogs
 
@@ -289,7 +297,31 @@
 
     private void addLayout(int displayName, String fileName, int layout, LayoutModifier modifier,
             long timeoutMs) {
-        mLayoutInfos.add(new LayoutInfo(displayName, fileName, layout, modifier, timeoutMs));
+        addLayout(new LayoutInfo(displayName, fileName, layout, modifier, timeoutMs));
+    }
+
+    private void addLayout(LayoutInfo info) {
+        mLayoutInfos.add(info);
+    }
+
+    private void addCalendarLayouts(int adapterMode) {
+        if (adapterMode == MODE_VIEWING || !CalendarViewModifier.isMonth(Calendar.JANUARY)) {
+            addLayout(getCalendarLayoutInfo());
+        }
+
+        if (adapterMode == MODE_VIEWING || !CalendarViewModifier.isMonth(Calendar.FEBRUARY)) {
+            addLayout(getFebruaryCalendarLayoutInfo());
+        }
+    }
+
+    private LayoutInfo getCalendarLayoutInfo() {
+        return new LayoutInfo(R.string.calendarview_jan, "calendar_view",
+            R.layout.calendarview, new CalendarViewModifier(true), SHORT_TIMEOUT_MS);
+    }
+
+    private LayoutInfo getFebruaryCalendarLayoutInfo() {
+        return new LayoutInfo(R.string.calendarview_feb, "calendar_view_feb",
+            R.layout.calendarview, new CalendarViewModifier(false), SHORT_TIMEOUT_MS);
     }
 
     @Override
diff --git a/tests/tests/holo/src/android/holo/cts/LayoutPickerActivity.java b/tests/tests/holo/src/android/holo/cts/LayoutPickerActivity.java
index 00c3af0..f808d59 100644
--- a/tests/tests/holo/src/android/holo/cts/LayoutPickerActivity.java
+++ b/tests/tests/holo/src/android/holo/cts/LayoutPickerActivity.java
@@ -38,7 +38,7 @@
         super.onCreate(savedInstanceState);
         mThemeIndex = getIntent().getIntExtra(EXTRA_THEME_INDEX, -1);
         mTestTask = getIntent().getIntExtra(EXTRA_TASK, -1);
-        setListAdapter(new LayoutAdapter(getLayoutInflater()));
+        setListAdapter(new LayoutAdapter(getLayoutInflater(), LayoutAdapter.MODE_VIEWING));
     }
 
     @Override
@@ -47,6 +47,7 @@
         intent.putExtra(ThemeTestActivity.EXTRA_THEME_INDEX, mThemeIndex);
         intent.putExtra(ThemeTestActivity.EXTRA_LAYOUT_INDEX, position);
         intent.putExtra(ThemeTestActivity.EXTRA_TASK, mTestTask);
+        intent.putExtra(ThemeTestActivity.EXTRA_LAYOUT_ADAPTER_MODE, LayoutAdapter.MODE_VIEWING);
         startActivity(intent);
     }
 }
diff --git a/tests/tests/holo/src/android/holo/cts/LayoutTestActivity.java b/tests/tests/holo/src/android/holo/cts/LayoutTestActivity.java
index 0377f9d..052ddea 100644
--- a/tests/tests/holo/src/android/holo/cts/LayoutTestActivity.java
+++ b/tests/tests/holo/src/android/holo/cts/LayoutTestActivity.java
@@ -47,6 +47,7 @@
     static final String EXTRA_THEME_INDEX = "themeIndex";
     static final String EXTRA_LAYOUT_INDEX = "layoutIndex";
     static final String EXTRA_TASK = "task";
+    static final String EXTRA_LAYOUT_ADAPTER_MODE = "layoutAdapterMode";
 
     // Output extras
     static final String EXTRA_BITMAP_NAME = "bitmapName";
@@ -64,10 +65,11 @@
 
         int themeIndex = getIntent().getIntExtra(EXTRA_THEME_INDEX, -1);
         int layoutIndex = getIntent().getIntExtra(EXTRA_LAYOUT_INDEX, -1);
+        int layoutMode = getIntent().getIntExtra(EXTRA_LAYOUT_ADAPTER_MODE, -1);
         int task = getIntent().getIntExtra(EXTRA_TASK, -1);
 
         ThemeAdapter themeAdapter = new ThemeAdapter(getLayoutInflater());
-        LayoutAdapter layoutAdapter = new LayoutAdapter(getLayoutInflater());
+        LayoutAdapter layoutAdapter = new LayoutAdapter(getLayoutInflater(), layoutMode);
 
         ThemeInfo themeInfo = themeAdapter.getItem(themeIndex);
         LayoutInfo layoutInfo = layoutAdapter.getItem(layoutIndex);
diff --git a/tests/tests/holo/src/android/holo/cts/SingleLayoutIterator.java b/tests/tests/holo/src/android/holo/cts/SingleLayoutIterator.java
index f50a872..afc0fbe 100644
--- a/tests/tests/holo/src/android/holo/cts/SingleLayoutIterator.java
+++ b/tests/tests/holo/src/android/holo/cts/SingleLayoutIterator.java
@@ -29,10 +29,12 @@
 
     private final int mTask;
     private final int mLayoutIndex;
+    private final int mLayoutAdapterMode;
     private int mThemeIndex;
 
-    SingleLayoutIterator(int layoutIndex, int task) {
+    SingleLayoutIterator(int layoutIndex, int task, int layoutAdapterMode) {
         mTask = task;
+        mLayoutAdapterMode = layoutAdapterMode;
         mLayoutIndex = layoutIndex;
     }
 
@@ -47,6 +49,7 @@
         intent.putExtra(LayoutTestActivity.EXTRA_THEME_INDEX, mThemeIndex);
         intent.putExtra(LayoutTestActivity.EXTRA_LAYOUT_INDEX, mLayoutIndex);
         intent.putExtra(LayoutTestActivity.EXTRA_TASK, mTask);
+        intent.putExtra(LayoutTestActivity.EXTRA_LAYOUT_ADAPTER_MODE, mLayoutAdapterMode);
 
         mThemeIndex++;
 
diff --git a/tests/tests/holo/src/android/holo/cts/SingleThemeIterator.java b/tests/tests/holo/src/android/holo/cts/SingleThemeIterator.java
index cdfbb8e..3c489ab 100644
--- a/tests/tests/holo/src/android/holo/cts/SingleThemeIterator.java
+++ b/tests/tests/holo/src/android/holo/cts/SingleThemeIterator.java
@@ -25,14 +25,17 @@
  */
 class SingleThemeIterator implements Iterator<Intent> {
 
-    private final LayoutAdapter mLayoutAdapter = new LayoutAdapter(null);
+    private final LayoutAdapter mLayoutAdapter;
 
     private final int mTask;
     private final int mThemeIndex;
+    private final int mLayoutAdapterMode;
     private int mLayoutIndex;
 
-    SingleThemeIterator(int themeIndex, int task) {
+    SingleThemeIterator(int themeIndex, int task, int layoutAdapterMode) {
         mTask = task;
+        mLayoutAdapterMode = layoutAdapterMode;
+        mLayoutAdapter = new LayoutAdapter(null, layoutAdapterMode);
         mThemeIndex = themeIndex;
     }
 
@@ -47,6 +50,7 @@
         intent.putExtra(LayoutTestActivity.EXTRA_THEME_INDEX, mThemeIndex);
         intent.putExtra(LayoutTestActivity.EXTRA_LAYOUT_INDEX, mLayoutIndex);
         intent.putExtra(LayoutTestActivity.EXTRA_TASK, mTask);
+        intent.putExtra(LayoutTestActivity.EXTRA_LAYOUT_ADAPTER_MODE, mLayoutAdapterMode);
 
         mLayoutIndex++;
 
diff --git a/tests/tests/holo/src/android/holo/cts/SingleThemeLayoutIterator.java b/tests/tests/holo/src/android/holo/cts/SingleThemeLayoutIterator.java
index e49c9f8..5fe5086 100644
--- a/tests/tests/holo/src/android/holo/cts/SingleThemeLayoutIterator.java
+++ b/tests/tests/holo/src/android/holo/cts/SingleThemeLayoutIterator.java
@@ -25,13 +25,15 @@
     private final int mThemeIndex;
     private final int mLayoutIndex;
     private final int mTask;
+    private final int mLayoutAdapterMode;
 
     private boolean hasNext = true;
 
-    SingleThemeLayoutIterator(int themeIndex, int layoutIndex, int task) {
+    SingleThemeLayoutIterator(int themeIndex, int layoutIndex, int task, int layoutAdapterMode) {
         mThemeIndex = themeIndex;
         mLayoutIndex = layoutIndex;
         mTask = task;
+        mLayoutAdapterMode = layoutAdapterMode;
     }
 
     @Override
@@ -45,6 +47,7 @@
         intent.putExtra(LayoutTestActivity.EXTRA_THEME_INDEX, mThemeIndex);
         intent.putExtra(LayoutTestActivity.EXTRA_LAYOUT_INDEX, mLayoutIndex);
         intent.putExtra(LayoutTestActivity.EXTRA_TASK, mTask);
+        intent.putExtra(LayoutTestActivity.EXTRA_LAYOUT_ADAPTER_MODE, mLayoutAdapterMode);
 
         hasNext = false;
 
diff --git a/tests/tests/holo/src/android/holo/cts/ThemeTestActivity.java b/tests/tests/holo/src/android/holo/cts/ThemeTestActivity.java
index 096c8ed..08659df 100644
--- a/tests/tests/holo/src/android/holo/cts/ThemeTestActivity.java
+++ b/tests/tests/holo/src/android/holo/cts/ThemeTestActivity.java
@@ -40,6 +40,7 @@
     static final String EXTRA_TASK = "task";
     static final String EXTRA_THEME_INDEX = "themeIndex";
     static final String EXTRA_LAYOUT_INDEX = "layoutIndex";
+    static final String EXTRA_LAYOUT_ADAPTER_MODE = "layoutAdapterMode";
 
     static final int TASK_VIEW_LAYOUTS = 1;
     static final int TASK_GENERATE_BITMAPS = 2;
@@ -82,17 +83,18 @@
 
         int themeIndex = getIntent().getIntExtra(EXTRA_THEME_INDEX, -1);
         int layoutIndex = getIntent().getIntExtra(EXTRA_LAYOUT_INDEX, -1);
+        int adapterMode = getIntent().getIntExtra(EXTRA_LAYOUT_ADAPTER_MODE, -1);
 
         Log.i(TAG, "Theme index: " + themeIndex + " Layout index: " + layoutIndex);
 
         if (themeIndex < 0 && layoutIndex < 0) {
-            mIterator = new AllThemesIterator(task);
+            mIterator = new AllThemesIterator(task, adapterMode);
         } else if (themeIndex >= 0 && layoutIndex >= 0) {
-            mIterator = new SingleThemeLayoutIterator(themeIndex, layoutIndex, task);
+            mIterator = new SingleThemeLayoutIterator(themeIndex, layoutIndex, task, adapterMode);
         } else if (layoutIndex >= 0) {
-            mIterator = new SingleLayoutIterator(layoutIndex, task);
+            mIterator = new SingleLayoutIterator(layoutIndex, task, adapterMode);
         } else if (themeIndex >= 0) {
-            mIterator = new SingleThemeIterator(themeIndex, task);
+            mIterator = new SingleThemeIterator(themeIndex, task, adapterMode);
         } else {
             throw new IllegalStateException();
         }
diff --git a/tests/tests/holo/src/android/holo/cts/modifiers/CalendarViewModifier.java b/tests/tests/holo/src/android/holo/cts/modifiers/CalendarViewModifier.java
index 36194c0..e27b6c1 100644
--- a/tests/tests/holo/src/android/holo/cts/modifiers/CalendarViewModifier.java
+++ b/tests/tests/holo/src/android/holo/cts/modifiers/CalendarViewModifier.java
@@ -20,6 +20,8 @@
 import android.view.View;
 import android.widget.CalendarView;
 
+import java.util.Calendar;
+import java.util.GregorianCalendar;
 import java.util.TimeZone;
 
 /**
@@ -30,16 +32,31 @@
      * Long representation of a date that is 30 years in milliseconds from
      * Unix epoch (January 1, 1970 00:00:00).
      */
-    private static final long DATE = 946707779241L;
+    private static final long JANUARY_DATE = 946707779241L;
+
+    private static final long FEBRUARY_DATE = 951033600000L;
+
+    private static final TimeZone TZ = TimeZone.getTimeZone("GMT+00:00");
+
+    private final boolean mJanuary;
+
+    public CalendarViewModifier(boolean january) {
+        mJanuary = january;
+    }
 
     @Override
     public void prepare() {
-        TimeZone.setDefault(TimeZone.getTimeZone("GMT+00:00"));
+        TimeZone.setDefault(TZ);
     }
 
     @Override
     public View modifyView(View view) {
-        ((CalendarView) view).setDate(DATE);
+        ((CalendarView) view).setDate(mJanuary ? JANUARY_DATE : FEBRUARY_DATE);
         return view;
     }
+
+    public static boolean isMonth(int month) {
+        Calendar cal = new GregorianCalendar(TZ);
+        return cal.get(Calendar.MONTH) == month;
+    }
 }
diff --git a/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java b/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java
index 0587f88..e34856c 100644
--- a/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java
+++ b/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java
@@ -21,6 +21,7 @@
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargets;
 
+import android.content.pm.PackageManager;
 import android.hardware.Camera;
 import android.hardware.Camera.Parameters;
 import android.hardware.Camera.Size;
@@ -237,6 +238,16 @@
         )
     })
     public void testGet() {
+        /*
+         * Device may not have rear camera for checkGet(-1).
+         * Checking PackageManager.FEATURE_CAMERA is included or not to decide the flow.
+         * Continue if the feature is included.
+         * Otherwise, exit test.
+         */
+        PackageManager pm = mContext.getPackageManager();
+        if (!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
+            return;
+        }
         checkGet(-1);
     }
 
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
index 9947592..9c03a0b 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
@@ -27,6 +27,7 @@
 import android.os.PowerManager;
 
 import java.io.File;
+import java.util.concurrent.CountDownLatch;
 
 /**
  * Tests for the MediaPlayer API and local video/audio playback.
@@ -36,6 +37,7 @@
  * Attribution 3.0 License at http://creativecommons.org/licenses/by/3.0/us/.
  */
 public class MediaPlayerTest extends MediaPlayerTestBase {
+
     public void testPlayNullSource() throws Exception {
         try {
             mMediaPlayer.setDataSource((String) null);
@@ -109,41 +111,51 @@
      * from the time setDisplay() was called
      */
     public void testVideoSurfaceResetting() throws Exception {
-        final int tolerance = 150;
+        final int tolerance = 66 * 3 / 2; /* Test video is 15fps... 66 ms per frame */
         final int seekPos = 1500;
 
-        playVideoTest(R.raw.testvideo, 352, 288);
+        final CountDownLatch seekDone = new CountDownLatch(1);
 
-        mMediaPlayer.start();
+        mMediaPlayer.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
+            @Override
+            public void onSeekComplete(MediaPlayer mp) {
+                seekDone.countDown();
+            }
+        });
+
+        loadResource(R.raw.testvideo);
+        playLoadedVideo(352, 288, -1);
+
         Thread.sleep(SLEEP_TIME);
 
         int posBefore = mMediaPlayer.getCurrentPosition();
         mMediaPlayer.setDisplay(getActivity().getSurfaceHolder2());
         int posAfter = mMediaPlayer.getCurrentPosition();
 
-        assertEquals(posAfter, posBefore);
+        assertEquals(posAfter, posBefore, tolerance);
         assertTrue(mMediaPlayer.isPlaying());
 
         Thread.sleep(SLEEP_TIME);
 
         mMediaPlayer.seekTo(seekPos);
+        seekDone.await();
         Thread.sleep(SLEEP_TIME / 2);
 
         posBefore = mMediaPlayer.getCurrentPosition();
         mMediaPlayer.setDisplay(null);
         posAfter = mMediaPlayer.getCurrentPosition();
 
-        assertEquals(posAfter, posBefore);
+        assertEquals(posAfter, posBefore, tolerance);
         assertEquals(seekPos + SLEEP_TIME / 2, posBefore, tolerance);
         assertTrue(mMediaPlayer.isPlaying());
 
         Thread.sleep(SLEEP_TIME);
 
         posBefore = mMediaPlayer.getCurrentPosition();
-        mMediaPlayer.setDisplay(getActivity().generateSurfaceHolder());
+        mMediaPlayer.setDisplay(getActivity().getSurfaceHolder());
         posAfter = mMediaPlayer.getCurrentPosition();
 
-        assertEquals(posAfter, posBefore);
+        assertEquals(posAfter, posBefore, tolerance);
         assertTrue(mMediaPlayer.isPlaying());
 
         Thread.sleep(SLEEP_TIME);
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java b/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
index 6b6f3d7..a594122 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
@@ -32,7 +32,7 @@
 
     protected static final int SLEEP_TIME = 1000;
     protected static final int LONG_SLEEP_TIME = 6000;
-    protected static final int STREAM_RETRIES = 5;
+    protected static final int STREAM_RETRIES = 20;
 
     public static class Monitor {
         private boolean signalled;
@@ -141,9 +141,13 @@
      *
      * @param width width of the video to verify, or null to skip verification
      * @param height height of the video to verify, or null to skip verification
-     * @param playTime length of time to play video, or 0 to play entire video
+     * @param playTime length of time to play video, or 0 to play entire video.
+     * with a non-negative value, this method stops the playback after the length of
+     * time or the duration the video is elapsed. With a value of -1,
+     * this method simply starts the video and returns immediately without
+     * stoping the video playback.
      */
-    private void playLoadedVideo(final Integer width, final Integer height, int playTime)
+    protected void playLoadedVideo(final Integer width, final Integer height, int playTime)
             throws Exception {
         final float leftVolume = 0.5f;
         final float rightVolume = 0.5f;
@@ -181,13 +185,16 @@
         mMediaPlayer.setVolume(leftVolume, rightVolume);
 
         // waiting to complete
-        if (playTime == 0) {
+        if (playTime == -1) {
+            return;
+        } else if (playTime == 0) {
             while (mMediaPlayer.isPlaying()) {
                 Thread.sleep(SLEEP_TIME);
             }
         } else {
             Thread.sleep(playTime);
         }
+        mMediaPlayer.stop();
     }
 
     private static class PrepareFailedException extends Exception {}
diff --git a/tests/tests/media/src/android/media/cts/MediaScannerNotificationTest.java b/tests/tests/media/src/android/media/cts/MediaScannerNotificationTest.java
index c753ff1..f6ceacf 100644
--- a/tests/tests/media/src/android/media/cts/MediaScannerNotificationTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaScannerNotificationTest.java
@@ -24,6 +24,7 @@
 import android.os.Environment;
 import android.test.AndroidTestCase;
 
+import java.io.File;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -52,7 +53,7 @@
 
     static class ScannerNotificationReceiver extends BroadcastReceiver {
 
-        private static final int TIMEOUT_MS = 30 * 1000;
+        private static final int TIMEOUT_MS = 4 * 60 * 1000;
 
         private final String mAction;
         private final CountDownLatch mLatch = new CountDownLatch(1);
@@ -69,8 +70,26 @@
         }
 
         public void waitForBroadcast() throws InterruptedException {
-            assertTrue("Failed to receive broadcast for " + mAction,
-                    mLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+            if (!mLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                int numFiles = countFiles(Environment.getExternalStorageDirectory());
+                fail("Failed to receive broadcast in " + TIMEOUT_MS + "ms for " + mAction
+                        + " while trying to scan " + numFiles + " files!");
+            }
+        }
+
+        private int countFiles(File dir) {
+            int count = 0;
+            File[] files = dir.listFiles();
+            if (files != null) {
+                for (File file : files) {
+                    if (file.isDirectory()) {
+                        count += countFiles(file);
+                    } else {
+                        count++;
+                    }
+                }
+            }
+            return count;
         }
     }
 }
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerStreamingTest.java b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
similarity index 98%
rename from tests/tests/media/src/android/media/cts/MediaPlayerStreamingTest.java
rename to tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
index 652c5bd..b8ccf22 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerStreamingTest.java
+++ b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
@@ -22,7 +22,7 @@
 /**
  * Tests of MediaPlayer streaming capabilities.
  */
-public class MediaPlayerStreamingTest extends MediaPlayerTestBase {
+public class StreamingMediaPlayerTest extends MediaPlayerTestBase {
     private CtsTestServer mServer;
 
     // Streaming RTSP video from YouTube
diff --git a/tests/tests/mediastress/Android.mk b/tests/tests/mediastress/Android.mk
new file mode 100644
index 0000000..4fa7fdb
--- /dev/null
+++ b/tests/tests/mediastress/Android.mk
@@ -0,0 +1,31 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsMediaStressTestCases
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/tests/tests/mediastress/AndroidManifest.xml b/tests/tests/mediastress/AndroidManifest.xml
new file mode 100644
index 0000000..5a4569c
--- /dev/null
+++ b/tests/tests/mediastress/AndroidManifest.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.cts.mediastress">
+
+    <uses-permission android:name="android.permission.CAMERA" />
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+        <activity android:label="@string/app_name"
+                android:name="android.mediastress.cts.MediaFrameworkTest"
+                android:screenOrientation="landscape">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+            android:targetPackage="com.android.cts.mediastress"
+            android:label="Media stress tests InstrumentationRunner" />
+
+</manifest>
diff --git a/tests/tests/mediastress/res/layout/surface_view.xml b/tests/tests/mediastress/res/layout/surface_view.xml
new file mode 100644
index 0000000..97f1dd4
--- /dev/null
+++ b/tests/tests/mediastress/res/layout/surface_view.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical">
+
+    <FrameLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+
+        <SurfaceView
+                android:id="@+id/surface_view"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_centerInParent="true" />
+
+        <ImageView android:id="@+id/overlay_layer"
+                android:layout_width="0dip"
+                android:layout_height="392dip"/>
+
+        <VideoView
+                android:id="@+id/video_view"
+                android:layout_width="320px"
+                android:layout_height="240px"  />
+
+    </FrameLayout>
+
+</LinearLayout>
diff --git a/tests/tests/mediastress/res/values/strings.xml b/tests/tests/mediastress/res/values/strings.xml
new file mode 100644
index 0000000..32c58e0
--- /dev/null
+++ b/tests/tests/mediastress/res/values/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <string name="app_name">MediaStressTest</string>
+    <string name="open_url">Open</string>
+</resources>
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/CodecTest.java b/tests/tests/mediastress/src/android/mediastress/cts/CodecTest.java
new file mode 100644
index 0000000..c349ac0
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/CodecTest.java
@@ -0,0 +1,817 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.mediastress.cts;
+
+import android.content.res.AssetFileDescriptor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.media.MediaMetadataRetriever;
+import android.media.MediaPlayer;
+import android.media.MediaRecorder;
+import android.os.Looper;
+import android.os.SystemClock;
+import android.util.Log;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Junit / Instrumentation test case for the media player api
+ */
+public class CodecTest {
+    private static String TAG = "CodecTest";
+    private static MediaPlayer mMediaPlayer;
+    private MediaPlayer.OnPreparedListener mOnPreparedListener;
+
+    private static int WAIT_FOR_COMMAND_TO_COMPLETE = 60000;  //1 min max.
+    private static boolean mInitialized = false;
+    private static boolean mPrepareReset = false;
+    private static Looper mLooper = null;
+    private static final Object mLock = new Object();
+    private static final Object mPrepareDone = new Object();
+    private static final Object mVideoSizeChanged = new Object();
+    private static final Object mOnCompletion = new Object();
+    private static boolean mOnPrepareSuccess = false;
+    private static final long PAUSE_WAIT_TIME = 3000;
+    private static final long WAIT_TIME = 2000;
+    private static final int SEEK_TIME = 10000;
+
+    public static boolean mOnCompleteSuccess = false;
+    public static boolean mPlaybackError = false;
+    public static int mMediaInfoUnknownCount = 0;
+    public static int mMediaInfoVideoTrackLaggingCount = 0;
+    public static int mMediaInfoBadInterleavingCount = 0;
+    public static int mMediaInfoNotSeekableCount = 0;
+    public static int mMediaInfoMetdataUpdateCount = 0;
+
+    public static String printCpuInfo() {
+        String cm = "dumpsys cpuinfo";
+        String cpuinfo = null;
+        int ch;
+        try {
+            Process  p = Runtime.getRuntime().exec(cm);
+            InputStream in = p.getInputStream();
+            StringBuffer sb = new StringBuffer(512);
+            while ( ( ch = in.read() ) != -1 ) {
+                sb.append((char) ch);
+            }
+            cpuinfo = sb.toString();
+        } catch (IOException e) {
+            Log.v(TAG, e.toString());
+        }
+        return cpuinfo;
+    }
+
+
+    public static int getDuration(String filePath) {
+        Log.v(TAG, "getDuration - " + filePath);
+        MediaPlayer mp = new MediaPlayer();
+        try {
+            mp.setDataSource(filePath);
+            mp.prepare();
+        } catch (Exception e) {
+            Log.v(TAG, e.toString());
+        }
+        int duration = mp.getDuration();
+        Log.v(TAG, "Duration " + duration);
+        mp.release();
+        Log.v(TAG, "release");
+        return duration;
+    }
+
+    public static boolean getCurrentPosition(String filePath) {
+        Log.v(TAG, "GetCurrentPosition - " + filePath);
+        int currentPosition = 0;
+        long t1=0;
+        long t2 =0;
+        MediaPlayer mp = new MediaPlayer();
+        try {
+            mp.setDataSource(filePath);
+            Log.v(TAG, "start playback");
+            mp.prepare();
+            mp.start();
+            t1=SystemClock.uptimeMillis();
+            Thread.sleep(10000);
+            mp.pause();
+            Thread.sleep(PAUSE_WAIT_TIME);
+            t2=SystemClock.uptimeMillis();
+        } catch (Exception e) {
+            Log.v(TAG, e.toString());
+        }
+        currentPosition = mp.getCurrentPosition();
+        mp.stop();
+        mp.release();
+        Log.v(TAG, "mp currentPositon = " + currentPosition + " play duration = " + (t2-t1));
+
+        if ((currentPosition < ((t2-t1) *1.2)) && (currentPosition > 0))
+            return true;
+        else
+            return false;
+    }
+
+    public static boolean seekTo(String filePath) {
+        Log.v(TAG, "seekTo " + filePath);
+        int currentPosition = 0;
+        MediaPlayer mp = new MediaPlayer();
+        try {
+            mp.setDataSource(filePath);
+            mp.prepare();
+            mp.start();
+            mp.seekTo(SEEK_TIME);
+            Thread.sleep(WAIT_TIME);
+            currentPosition = mp.getCurrentPosition();
+        } catch (Exception e) {
+            Log.v(TAG, e.getMessage());
+        }
+        mp.stop();
+        mp.release();
+        Log.v(TAG, "CurrentPosition = " + currentPosition);
+        //The currentposition should be at least greater than the 80% of seek time
+        if ((currentPosition > SEEK_TIME *0.8))
+            return true;
+        else
+            return false;
+    }
+
+    public static boolean setLooping(String filePath) {
+        int currentPosition = 0;
+        int duration = 0;
+        long t1 =0;
+        long t2 =0;
+        Log.v (TAG, "SetLooping - " + filePath);
+        MediaPlayer mp = new MediaPlayer();
+        try {
+            mp.setDataSource(filePath);
+            mp.prepare();
+            duration = mp.getDuration();
+            Log.v(TAG, "setLooping duration " + duration);
+            mp.setLooping(true);
+            mp.start();
+            Thread.sleep(5000);
+            mp.seekTo(duration - 5000);
+            t1=SystemClock.uptimeMillis();
+            Thread.sleep(20000);
+            t2=SystemClock.uptimeMillis();
+            Log.v(TAG, "pause");
+            //Bug# 1106852 - IllegalStateException will be thrown if pause is called
+            //in here
+            //mp.pause();
+            currentPosition = mp.getCurrentPosition();
+            Log.v(TAG, "looping position " + currentPosition + "duration = " + (t2-t1));
+        } catch (Exception e) {
+            Log.v(TAG, "Exception : " + e.toString());
+        }
+        mp.stop();
+        mp.release();
+        //The current position should be within 20% of the sleep time
+        //and should be greater than zero.
+        if ((currentPosition < ((t2-t1-5000)*1.2)) && currentPosition > 0)
+            return true;
+        else
+            return false;
+    }
+
+    public static boolean pause(String filePath) throws Exception {
+        Log.v(TAG, "pause - " + filePath);
+        boolean misPlaying = true;
+        boolean pauseResult = false;
+        long t1=0;
+        long t2=0;
+        MediaPlayer mp = new MediaPlayer();
+        mp.setDataSource(filePath);
+        mp.prepare();
+        int duration = mp.getDuration();
+        mp.start();
+        t1=SystemClock.uptimeMillis();
+        Thread.sleep(5000);
+        mp.pause();
+        Thread.sleep(PAUSE_WAIT_TIME);
+        t2=SystemClock.uptimeMillis();
+        misPlaying = mp.isPlaying();
+        int curPosition = mp.getCurrentPosition();
+        Log.v(TAG, filePath + " pause currentPositon " + curPosition);
+        Log.v(TAG, "isPlaying "+ misPlaying + " wait time " + (t2 - t1) );
+        String cpuinfo = printCpuInfo();
+        Log.v(TAG, cpuinfo);
+        if ((curPosition>0) && (curPosition < ((t2-t1) * 1.3)) && (misPlaying == false))
+            pauseResult = true;
+        mp.stop();
+        mp.release();
+        return pauseResult;
+    }
+
+    public static void prepareStopRelease(String filePath) throws Exception {
+        Log.v(TAG, "prepareStopRelease" + filePath);
+        MediaPlayer mp = new MediaPlayer();
+        mp.setDataSource(filePath);
+        mp.prepare();
+        mp.stop();
+        mp.release();
+    }
+
+    public static void preparePauseRelease(String filePath) throws Exception {
+        Log.v(TAG, "preparePauseRelease" + filePath);
+        MediaPlayer mp = new MediaPlayer();
+        mp.setDataSource(filePath);
+        mp.prepare();
+        mp.pause();
+        mp.release();
+    }
+
+    static MediaPlayer.OnVideoSizeChangedListener mOnVideoSizeChangedListener =
+        new MediaPlayer.OnVideoSizeChangedListener() {
+            public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
+                synchronized (mVideoSizeChanged) {
+                    Log.v(TAG, "sizechanged notification received ...");
+                    mVideoSizeChanged.notify();
+                }
+            }
+    };
+
+    //Register the videoSizeChanged listener
+    public static int videoHeight(String filePath) throws Exception {
+        Log.v(TAG, "videoHeight - " + filePath);
+        int videoHeight = 0;
+        synchronized (mLock) {
+            initializeMessageLooper();
+            try {
+                mLock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+            } catch(Exception e) {
+                Log.v(TAG, "looper was interrupted.");
+                return 0;
+            }
+        }
+        try {
+            mMediaPlayer.setDataSource(filePath);
+            mMediaPlayer.setDisplay(MediaFrameworkTest.getSurfaceView().getHolder());
+            mMediaPlayer.setOnVideoSizeChangedListener(mOnVideoSizeChangedListener);
+            synchronized (mVideoSizeChanged) {
+                try {
+                    mMediaPlayer.prepare();
+                    mMediaPlayer.start();
+                    mVideoSizeChanged.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+                } catch (Exception e) {
+                    Log.v(TAG, "wait was interrupted");
+                }
+            }
+            videoHeight = mMediaPlayer.getVideoHeight();
+            terminateMessageLooper();
+        } catch (Exception e) {
+            Log.e(TAG, e.getMessage());
+        }
+
+        return videoHeight;
+    }
+
+    //Register the videoSizeChanged listener
+    public static int videoWidth(String filePath) throws Exception {
+        Log.v(TAG, "videoWidth - " + filePath);
+        int videoWidth = 0;
+
+        synchronized (mLock) {
+            initializeMessageLooper();
+            try {
+                mLock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+            } catch(Exception e) {
+                Log.v(TAG, "looper was interrupted.");
+                return 0;
+            }
+        }
+        try {
+            mMediaPlayer.setDataSource(filePath);
+            mMediaPlayer.setDisplay(MediaFrameworkTest.getSurfaceView().getHolder());
+            mMediaPlayer.setOnVideoSizeChangedListener(mOnVideoSizeChangedListener);
+            synchronized (mVideoSizeChanged) {
+                try {
+                    mMediaPlayer.prepare();
+                    mMediaPlayer.start();
+                    mVideoSizeChanged.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+                } catch (Exception e) {
+                    Log.v(TAG, "wait was interrupted");
+                }
+            }
+            videoWidth = mMediaPlayer.getVideoWidth();
+            terminateMessageLooper();
+        } catch (Exception e) {
+            Log.e(TAG, e.getMessage());
+        }
+        return videoWidth;
+    }
+
+    //This also test the streaming video which may take a long
+    //time to start the playback.
+    public static boolean videoSeekTo(String filePath) throws Exception {
+        Log.v(TAG, "videoSeekTo - " + filePath);
+        int currentPosition = 0;
+        int duration = 0;
+        boolean videoResult = false;
+        MediaPlayer mp = new MediaPlayer();
+        mp.setDataSource(filePath);
+        mp.setDisplay(MediaFrameworkTest.getSurfaceView().getHolder());
+        mp.prepare();
+        mp.start();
+
+        Thread.sleep(5000);
+        duration = mp.getDuration();
+        Log.v(TAG, "video duration " + duration);
+        mp.pause();
+        Thread.sleep(PAUSE_WAIT_TIME);
+        mp.seekTo(duration - 20000 );
+        mp.start();
+        Thread.sleep(1000);
+        mp.pause();
+        Thread.sleep(PAUSE_WAIT_TIME);
+        mp.seekTo(duration/2);
+        mp.start();
+        Thread.sleep(10000);
+        currentPosition = mp.getCurrentPosition();
+        Log.v(TAG, "video currentPosition " + currentPosition);
+        mp.release();
+        if (currentPosition > (duration /2 )*0.9)
+            return true;
+        else
+            return false;
+
+    }
+
+    public static boolean seekToEnd(String filePath) {
+        Log.v(TAG, "seekToEnd - " + filePath);
+        int duration = 0;
+        int currentPosition = 0;
+        boolean isPlaying = false;
+        MediaPlayer mp = new MediaPlayer();
+        try {
+            mp.setDataSource(filePath);
+            Log.v(TAG, "start playback");
+            mp.prepare();
+            duration = mp.getDuration();
+            mp.seekTo(duration - 3000);
+            mp.start();
+            Thread.sleep(6000);
+        } catch (Exception e) {}
+        isPlaying = mp.isPlaying();
+        currentPosition = mp.getCurrentPosition();
+        Log.v(TAG, "seekToEnd currentPosition= " + currentPosition + " isPlaying = " + isPlaying);
+        mp.stop();
+        mp.release();
+        Log.v(TAG, "duration = " + duration);
+        if (currentPosition < 0.9 * duration || isPlaying)
+            return false;
+        else
+            return true;
+    }
+
+    public static boolean shortMediaStop(String filePath) {
+        Log.v(TAG, "shortMediaStop - " + filePath);
+        //This test is only for the short media file
+        int duration = 0;
+        int currentPosition = 0;
+        boolean isPlaying = false;
+        MediaPlayer mp = new MediaPlayer();
+        try {
+            mp.setDataSource(filePath);
+            Log.v(TAG, "start playback");
+            mp.prepare();
+            duration = mp.getDuration();
+            mp.start();
+            Thread.sleep(10000);
+        } catch (Exception e) {}
+        isPlaying = mp.isPlaying();
+        currentPosition = mp.getCurrentPosition();
+        Log.v(TAG, "seekToEnd currentPosition= " + currentPosition + " isPlaying = " + isPlaying);
+        mp.stop();
+        mp.release();
+        Log.v(TAG, "duration = " + duration);
+        if (currentPosition > duration || isPlaying)
+            return false;
+        else
+            return true;
+    }
+
+    public static boolean playToEnd(String filePath) {
+        Log.v(TAG, "shortMediaStop - " + filePath);
+        //This test is only for the short media file
+        int duration = 200000;
+        int updateDuration = 0;
+        int currentPosition = 0;
+        boolean isPlaying = false;
+        MediaPlayer mp = new MediaPlayer();
+        try {
+            Thread.sleep(5000);
+            mp.setDataSource(filePath);
+            Log.v(TAG, "start playback");
+            mp.prepare();
+            //duration = mp.getDuration();
+            mp.start();
+            Thread.sleep(50000);
+        } catch (Exception e){}
+        isPlaying = mp.isPlaying();
+        currentPosition = mp.getCurrentPosition();
+        //updateDuration = mp.getDuration();
+        Log.v(TAG, "seekToEnd currentPosition= " + currentPosition + " isPlaying = " + isPlaying);
+        mp.stop();
+        mp.release();
+        //Log.v(TAG, "duration = " + duration);
+        //Log.v(TAG, "Update duration = " + updateDuration);
+        if (currentPosition > duration || isPlaying)
+            return false;
+        else
+            return true;
+    }
+
+    public static boolean seektoBeforeStart(String filePath){
+        Log.v(TAG, "seektoBeforeStart - " + filePath);
+        //This test is only for the short media file
+        int duration = 0;
+        int currentPosition = 0;
+
+        MediaPlayer mp = new MediaPlayer();
+        try {
+            mp.setDataSource(filePath);
+            mp.prepare();
+            duration = mp.getDuration();
+            mp.seekTo(duration - 10000);
+            mp.start();
+            currentPosition=mp.getCurrentPosition();
+            mp.stop();
+            mp.release();
+        } catch (Exception e) {}
+        if (currentPosition < duration/2)
+            return false;
+        else
+            return true;
+    }
+
+    public static boolean mediaRecorderRecord(String filePath){
+        Log.v(TAG, "SoundRecording - " + filePath);
+        //This test is only for the short media file
+        int duration = 0;
+        try {
+            MediaRecorder mRecorder = new MediaRecorder();
+            mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
+            mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
+            mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
+            mRecorder.setOutputFile(filePath);
+            mRecorder.prepare();
+            mRecorder.start();
+            Thread.sleep(500);
+            mRecorder.stop();
+            Log.v(TAG, "sound recorded");
+            mRecorder.release();
+        } catch (Exception e) {
+            Log.v(TAG, e.toString());
+        }
+
+        //Verify the recorded file
+        MediaPlayer mp = new MediaPlayer();
+        try {
+            mp.setDataSource(filePath);
+            mp.prepare();
+            duration = mp.getDuration();
+            Log.v(TAG,"Duration " + duration);
+            mp.release();
+        } catch (Exception e) {}
+        //Check the record media file length is greate than zero
+        if (duration > 0)
+            return true;
+        else
+            return false;
+
+    }
+
+    //Test for mediaMeta Data Thumbnail
+    public static boolean getThumbnail(String filePath, String goldenPath) {
+        Log.v(TAG, "getThumbnail - " + filePath);
+
+        int goldenHeight = 0;
+        int goldenWidth = 0;
+        int outputWidth = 0;
+        int outputHeight = 0;
+
+        //This test is only for the short media file
+        try {
+            BitmapFactory mBitmapFactory = new BitmapFactory();
+
+            MediaMetadataRetriever mMediaMetadataRetriever = new MediaMetadataRetriever();
+            try {
+                mMediaMetadataRetriever.setDataSource(filePath);
+            } catch(Exception e) {
+                e.printStackTrace();
+                return false;
+            }
+            Bitmap outThumbnail = mMediaMetadataRetriever.getFrameAtTime(-1);
+
+            //Verify the thumbnail
+            Bitmap goldenBitmap = mBitmapFactory.decodeFile(goldenPath);
+            outputWidth = outThumbnail.getWidth();
+            outputHeight = outThumbnail.getHeight();
+            goldenHeight = goldenBitmap.getHeight();
+            goldenWidth = goldenBitmap.getWidth();
+
+            //check the image dimension
+            if ((outputWidth != goldenWidth) || (outputHeight != goldenHeight))
+                return false;
+
+            // Check half line of pixel
+            int x = goldenHeight / 2;
+            for (int j = 1; j < goldenWidth / 2; j++) {
+                if (goldenBitmap.getPixel(x, j) != outThumbnail.getPixel(x, j)) {
+                    Log.v(TAG, "pixel = " + goldenBitmap.getPixel(x, j));
+                    return false;
+                }
+           }
+        } catch (Exception e) {
+            Log.v(TAG, e.toString());
+            return false;
+        }
+        return true;
+    }
+
+    //Load midi file from resources
+    public static boolean resourcesPlayback(AssetFileDescriptor afd, int expectedDuration) {
+        int duration = 0;
+        try {
+            MediaPlayer mp = new MediaPlayer();
+            mp.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(), afd.getLength());
+            mp.prepare();
+            mp.start();
+            duration = mp.getDuration();
+            Thread.sleep(5000);
+            mp.release();
+        } catch (Exception e) {
+            Log.v(TAG,e.getMessage());
+        }
+        if (duration > expectedDuration)
+            return true;
+        else
+            return false;
+    }
+
+    public static boolean prepareAsyncReset(String filePath) {
+        //preparesAsync
+        try {
+            MediaPlayer mp = new MediaPlayer();
+            mp.setDataSource(filePath);
+            mp.prepareAsync();
+            mp.reset();
+            mp.release();
+        } catch (Exception e) {
+            Log.v(TAG,e.getMessage());
+            return false;
+        }
+        return true;
+    }
+
+
+    public static boolean isLooping(String filePath) {
+        MediaPlayer mp = null;
+
+        try {
+            mp = new MediaPlayer();
+            if (mp.isLooping()) {
+                Log.v(TAG, "MediaPlayer.isLooping() returned true after ctor");
+                return false;
+            }
+            mp.setDataSource(filePath);
+            mp.prepare();
+
+            mp.setLooping(true);
+            if (!mp.isLooping()) {
+                Log.v(TAG, "MediaPlayer.isLooping() returned false after setLooping(true)");
+                return false;
+            }
+
+            mp.setLooping(false);
+            if (mp.isLooping()) {
+                Log.v(TAG, "MediaPlayer.isLooping() returned true after setLooping(false)");
+                return false;
+            }
+        } catch (Exception e) {
+            Log.v(TAG, "Exception : " + e.toString());
+            return false;
+        } finally {
+            if (mp != null)
+                mp.release();
+        }
+
+        return true;
+    }
+
+    public static boolean isLoopingAfterReset(String filePath) {
+        MediaPlayer mp = null;
+        try {
+            mp = new MediaPlayer();
+            mp.setDataSource(filePath);
+            mp.prepare();
+
+            mp.setLooping(true);
+            mp.reset();
+            if (mp.isLooping()) {
+                Log.v(TAG, "MediaPlayer.isLooping() returned true after reset()");
+                return false;
+            }
+        } catch (Exception e){
+            Log.v(TAG, "Exception : " + e.toString());
+            return false;
+        } finally {
+            if (mp != null)
+                mp.release();
+        }
+
+        return true;
+    }
+
+    /*
+     * Initializes the message looper so that the mediaPlayer object can
+     * receive the callback messages.
+     */
+    private static void initializeMessageLooper() {
+        Log.v(TAG, "start looper");
+        new Thread() {
+            @Override
+            public void run() {
+                // Set up a looper to be used by camera.
+                Looper.prepare();
+                Log.v(TAG, "start loopRun");
+                // Save the looper so that we can terminate this thread
+                // after we are done with it.
+                mLooper = Looper.myLooper();
+                mMediaPlayer = new MediaPlayer();
+                synchronized (mLock) {
+                    mInitialized = true;
+                    mLock.notify();
+                }
+                Looper.loop();  // Blocks forever until Looper.quit() is called.
+                Log.v(TAG, "initializeMessageLooper: quit.");
+            }
+        }.start();
+    }
+
+    /*
+     * Terminates the message looper thread.
+     */
+    private static void terminateMessageLooper() {
+        mLooper.quit();
+        mMediaPlayer.release();
+    }
+
+    static MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() {
+        public void onPrepared(MediaPlayer mp) {
+            synchronized (mPrepareDone) {
+                if(mPrepareReset) {
+                    Log.v(TAG, "call Reset");
+                    mMediaPlayer.reset();
+                }
+                Log.v(TAG, "notify the prepare callback");
+                mPrepareDone.notify();
+                mOnPrepareSuccess = true;
+            }
+        }
+    };
+
+    public static boolean prepareAsyncCallback(String filePath, boolean reset) throws Exception {
+        //Added the PrepareReset flag which allow us to switch to different
+        //test case.
+        if (reset) {
+            mPrepareReset = true;
+        }
+
+        synchronized (mLock) {
+            initializeMessageLooper();
+            try {
+                mLock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+            } catch(Exception e) {
+                Log.v(TAG, "looper was interrupted.");
+                return false;
+            }
+        }
+        try{
+            mMediaPlayer.setOnPreparedListener(mPreparedListener);
+            mMediaPlayer.setDataSource(filePath);
+            mMediaPlayer.setDisplay(MediaFrameworkTest.getSurfaceView().getHolder());
+            mMediaPlayer.prepareAsync();
+            synchronized (mPrepareDone) {
+                try {
+                    mPrepareDone.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+                } catch (Exception e) {
+                    Log.v(TAG, "wait was interrupted.");
+                }
+            }
+            terminateMessageLooper();
+        }catch (Exception e) {
+            Log.v(TAG,e.getMessage());
+        }
+       return mOnPrepareSuccess;
+    }
+
+    static MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() {
+        public void onCompletion(MediaPlayer mp) {
+            synchronized (mOnCompletion) {
+                Log.v(TAG, "notify the completion callback");
+                mOnCompletion.notify();
+                mOnCompleteSuccess = true;
+            }
+        }
+    };
+
+    static MediaPlayer.OnErrorListener mOnErrorListener = new MediaPlayer.OnErrorListener() {
+        public boolean onError(MediaPlayer mp, int framework_err, int impl_err) {
+            Log.v(TAG, "playback error");
+            mPlaybackError = true;
+            mp.reset();
+            synchronized (mOnCompletion) {
+                Log.v(TAG, "notify the completion callback");
+                mOnCompletion.notify();
+                mOnCompleteSuccess = false;
+            }
+            return true;
+        }
+    };
+
+    static MediaPlayer.OnInfoListener mInfoListener = new MediaPlayer.OnInfoListener() {
+        public boolean onInfo(MediaPlayer mp, int what, int extra) {
+            switch (what) {
+                case MediaPlayer.MEDIA_INFO_UNKNOWN:
+                    mMediaInfoUnknownCount++;
+                    break;
+                case MediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING:
+                    mMediaInfoVideoTrackLaggingCount++;
+                    break;
+                case MediaPlayer.MEDIA_INFO_BAD_INTERLEAVING:
+                    mMediaInfoBadInterleavingCount++;
+                    break;
+                case MediaPlayer.MEDIA_INFO_NOT_SEEKABLE:
+                    mMediaInfoNotSeekableCount++;
+                    break;
+                case MediaPlayer.MEDIA_INFO_METADATA_UPDATE:
+                    mMediaInfoMetdataUpdateCount++;
+                    break;
+            }
+            return true;
+        }
+    };
+
+    public static boolean playMediaSample(String fileName) throws Exception {
+        int duration = 0;
+        int curPosition = 0;
+        int nextPosition = 0;
+        int waittime = 0;
+        mOnCompleteSuccess = false;
+        mMediaInfoUnknownCount = 0;
+        mMediaInfoVideoTrackLaggingCount = 0;
+        mMediaInfoBadInterleavingCount = 0;
+        mMediaInfoNotSeekableCount = 0;
+        mMediaInfoMetdataUpdateCount = 0;
+        mPlaybackError = false;
+
+        initializeMessageLooper();
+        synchronized (mLock) {
+            try {
+                mLock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+            } catch(Exception e) {
+                Log.v(TAG, "looper was interrupted.");
+                return false;
+            }
+        }
+        try {
+            mMediaPlayer.setOnCompletionListener(mCompletionListener);
+            mMediaPlayer.setOnErrorListener(mOnErrorListener);
+            mMediaPlayer.setOnInfoListener(mInfoListener);
+            Log.v(TAG, "playMediaSample: sample file name " + fileName);
+            mMediaPlayer.setDataSource(fileName);
+            mMediaPlayer.setDisplay(MediaFrameworkTest.getSurfaceView().getHolder());
+            mMediaPlayer.prepare();
+            duration = mMediaPlayer.getDuration();
+            Log.v(TAG, "duration of media " + duration);
+            // start to play
+            mMediaPlayer.start();
+            waittime = duration - mMediaPlayer.getCurrentPosition();
+            synchronized(mOnCompletion) {
+                try {
+                    mOnCompletion.wait(waittime + 2000);
+                } catch (Exception e) {
+                    Log.v(TAG, "playMediaSamples are interrupted");
+                    return false;
+                }
+            }
+            terminateMessageLooper();
+        } catch (Exception e) {
+            Log.v(TAG, "playMediaSample Exception:" + e.getMessage());
+        }
+        return mOnCompleteSuccess;
+    }
+}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/H263QcifLongPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/H263QcifLongPlayerTest.java
new file mode 100644
index 0000000..6e47fe1
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/H263QcifLongPlayerTest.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.mediastress.cts;
+
+public class H263QcifLongPlayerTest extends MediaPlayerStressTest {
+    private final static String VIDEO_PATH_MIDDLE = "bbb_full/176x144/3gp_h263_libfaac/";
+    private final String[] mMedias = { // indentation shortened due to long file name
+        "bbb_full.ffmpeg.176x144.3gp.h263_56kbps_12fps.libfaac_mono_24kbps_11025Hz.3gp"
+    };
+
+    public void testPlay00() throws Exception {
+        doTestVideoPlaybackLong(0);
+    }
+
+    @Override
+    protected String getFullVideoClipName(int mediaNumber) {
+        return VIDEO_TOP_DIR + VIDEO_PATH_MIDDLE + mMedias[mediaNumber];
+    }
+
+}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/H263QcifShortPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/H263QcifShortPlayerTest.java
new file mode 100644
index 0000000..2035869
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/H263QcifShortPlayerTest.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.mediastress.cts;
+
+public class H263QcifShortPlayerTest extends MediaPlayerStressTest {
+    private final static String VIDEO_PATH_MIDDLE = "bbb_short/176x144/3gp_h263_libfaac/";
+    private final String[] mMedias = {
+        "bbb_short.ffmpeg.176x144.3gp.h263_300kbps_12fps.libfaac_mono_24kbps_11025Hz.3gp",
+        "bbb_short.ffmpeg.176x144.3gp.h263_300kbps_12fps.libfaac_mono_24kbps_22050Hz.3gp",
+        "bbb_short.ffmpeg.176x144.3gp.h263_300kbps_12fps.libfaac_stereo_128kbps_11025Hz.3gp",
+        "bbb_short.ffmpeg.176x144.3gp.h263_300kbps_12fps.libfaac_stereo_128kbps_22050Hz.3gp",
+        "bbb_short.ffmpeg.176x144.3gp.h263_300kbps_12fps.libfaac_stereo_24kbps_11025Hz.3gp",
+        "bbb_short.ffmpeg.176x144.3gp.h263_300kbps_12fps.libfaac_stereo_24kbps_22050Hz.3gp",
+        "bbb_short.ffmpeg.176x144.3gp.h263_300kbps_25fps.libfaac_mono_24kbps_11025Hz.3gp",
+        "bbb_short.ffmpeg.176x144.3gp.h263_300kbps_25fps.libfaac_mono_24kbps_22050Hz.3gp",
+        "bbb_short.ffmpeg.176x144.3gp.h263_300kbps_25fps.libfaac_stereo_128kbps_11025Hz.3gp",
+        "bbb_short.ffmpeg.176x144.3gp.h263_300kbps_25fps.libfaac_stereo_128kbps_22050Hz.3gp",
+        "bbb_short.ffmpeg.176x144.3gp.h263_300kbps_25fps.libfaac_stereo_24kbps_11025Hz.3gp",
+        "bbb_short.ffmpeg.176x144.3gp.h263_300kbps_25fps.libfaac_stereo_24kbps_22050Hz.3gp",
+        "bbb_short.ffmpeg.176x144.3gp.h263_56kbps_12fps.libfaac_mono_24kbps_11025Hz.3gp",
+        "bbb_short.ffmpeg.176x144.3gp.h263_56kbps_12fps.libfaac_mono_24kbps_22050Hz.3gp",
+        "bbb_short.ffmpeg.176x144.3gp.h263_56kbps_12fps.libfaac_stereo_128kbps_11025Hz.3gp",
+        "bbb_short.ffmpeg.176x144.3gp.h263_56kbps_12fps.libfaac_stereo_128kbps_22050Hz.3gp",
+        "bbb_short.ffmpeg.176x144.3gp.h263_56kbps_12fps.libfaac_stereo_24kbps_11025Hz.3gp",
+        "bbb_short.ffmpeg.176x144.3gp.h263_56kbps_12fps.libfaac_stereo_24kbps_22050Hz.3gp",
+        "bbb_short.ffmpeg.176x144.3gp.h263_56kbps_25fps.libfaac_mono_24kbps_11025Hz.3gp",
+        "bbb_short.ffmpeg.176x144.3gp.h263_56kbps_25fps.libfaac_mono_24kbps_22050Hz.3gp",
+        "bbb_short.ffmpeg.176x144.3gp.h263_56kbps_25fps.libfaac_stereo_128kbps_11025Hz.3gp",
+        "bbb_short.ffmpeg.176x144.3gp.h263_56kbps_25fps.libfaac_stereo_128kbps_22050Hz.3gp",
+        "bbb_short.ffmpeg.176x144.3gp.h263_56kbps_25fps.libfaac_stereo_24kbps_11025Hz.3gp",
+        "bbb_short.ffmpeg.176x144.3gp.h263_56kbps_25fps.libfaac_stereo_24kbps_22050Hz.3gp"
+    };
+
+    public void testPlay00() throws Exception {
+        doTestVideoPlaybackShort(0);
+    }
+
+    public void testPlay01() throws Exception {
+        doTestVideoPlaybackShort(1);
+    }
+
+    public void testPlay02() throws Exception {
+        doTestVideoPlaybackShort(2);
+    }
+
+    public void testPlay03() throws Exception {
+        doTestVideoPlaybackShort(3);
+    }
+
+    public void testPlay04() throws Exception {
+        doTestVideoPlaybackShort(4);
+    }
+
+    public void testPlay05() throws Exception {
+        doTestVideoPlaybackShort(5);
+    }
+
+    public void testPlay06() throws Exception {
+        doTestVideoPlaybackShort(6);
+    }
+
+    public void testPlay07() throws Exception {
+        doTestVideoPlaybackShort(7);
+    }
+
+    public void testPlay08() throws Exception {
+        doTestVideoPlaybackShort(8);
+    }
+
+    public void testPlay09() throws Exception {
+        doTestVideoPlaybackShort(9);
+    }
+
+    public void testPlay10() throws Exception {
+        doTestVideoPlaybackShort(10);
+    }
+
+    public void testPlay11() throws Exception {
+        doTestVideoPlaybackShort(11);
+    }
+
+    public void testPlay12() throws Exception {
+        doTestVideoPlaybackShort(12);
+    }
+
+    public void testPlay13() throws Exception {
+        doTestVideoPlaybackShort(13);
+    }
+
+    public void testPlay14() throws Exception {
+        doTestVideoPlaybackShort(14);
+    }
+
+    public void testPlay15() throws Exception {
+        doTestVideoPlaybackShort(15);
+    }
+
+    public void testPlay16() throws Exception {
+        doTestVideoPlaybackShort(16);
+    }
+
+    public void testPlay17() throws Exception {
+        doTestVideoPlaybackShort(17);
+    }
+
+    public void testPlay18() throws Exception {
+        doTestVideoPlaybackShort(18);
+    }
+
+    public void testPlay19() throws Exception {
+        doTestVideoPlaybackShort(19);
+    }
+
+    public void testPlay20() throws Exception {
+        doTestVideoPlaybackShort(20);
+    }
+
+    public void testPlay21() throws Exception {
+        doTestVideoPlaybackShort(21);
+    }
+
+    public void testPlay22() throws Exception {
+        doTestVideoPlaybackShort(22);
+    }
+
+    public void testPlay23() throws Exception {
+        doTestVideoPlaybackShort(23);
+    }
+
+    @Override
+    protected String getFullVideoClipName(int mediaNumber) {
+        return VIDEO_TOP_DIR + VIDEO_PATH_MIDDLE + mMedias[mediaNumber];
+    }
+
+}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/H264R1080pAacLongPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/H264R1080pAacLongPlayerTest.java
new file mode 100644
index 0000000..b7f7564
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/H264R1080pAacLongPlayerTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.mediastress.cts;
+
+import android.media.CamcorderProfile;
+import android.media.MediaRecorder.AudioEncoder;
+import android.media.MediaRecorder.VideoEncoder;
+
+public class H264R1080pAacLongPlayerTest extends MediaPlayerStressTest {
+    private static final String VIDEO_PATH_MIDDLE = "bbb_full/1920x1080/mp4_libx264_libfaac/";
+    private final String[] mMedias = {
+        "bbb_full.ffmpeg.1920x1080.mp4.libx264_10000kbps_30fps.libfaac_stereo_192kbps_48000Hz.mp4"
+    };
+
+    public H264R1080pAacLongPlayerTest() {
+        super(CamcorderProfile.QUALITY_1080P, VideoEncoder.H264, AudioEncoder.AAC);
+    }
+
+    public void testPlay00() throws Exception {
+        doTestVideoPlaybackLong(0);
+    }
+
+    @Override
+    protected String getFullVideoClipName(int mediaNumber) {
+        return VIDEO_TOP_DIR + VIDEO_PATH_MIDDLE + mMedias[mediaNumber];
+    }
+
+}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/H264R1080pAacShortPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/H264R1080pAacShortPlayerTest.java
new file mode 100644
index 0000000..3b7da57
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/H264R1080pAacShortPlayerTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.mediastress.cts;
+
+import android.media.CamcorderProfile;
+import android.media.MediaRecorder.AudioEncoder;
+import android.media.MediaRecorder.VideoEncoder;
+
+public class H264R1080pAacShortPlayerTest extends MediaPlayerStressTest {
+    private static final String VIDEO_PATH_MIDDLE = "bbb_short/1920x1080/mp4_libx264_libfaac/";
+    private final String[] mMedias = {
+        "bbb_short.ffmpeg.1920x1080.mp4.libx264_10000kbps_30fps.libfaac_stereo_192kbps_48000Hz.mp4",
+        "bbb_short.ffmpeg.1920x1080.mp4.libx264_1750kbps_30fps.libfaac_stereo_192kbps_48000Hz.mp4",
+        "bbb_short.ffmpeg.1920x1080.mp4.libx264_5000kbps_30fps.libfaac_stereo_192kbps_48000Hz.mp4"
+    };
+
+    public H264R1080pAacShortPlayerTest() {
+        super(CamcorderProfile.QUALITY_1080P, VideoEncoder.H264, AudioEncoder.AAC);
+    }
+
+    public void testPlay00() throws Exception {
+        doTestVideoPlaybackShort(0);
+    }
+
+    public void testPlay01() throws Exception {
+        doTestVideoPlaybackShort(1);
+    }
+
+    public void testPlay02() throws Exception {
+        doTestVideoPlaybackShort(2);
+    }
+
+    @Override
+    protected String getFullVideoClipName(int mediaNumber) {
+        return VIDEO_TOP_DIR + VIDEO_PATH_MIDDLE + mMedias[mediaNumber];
+    }
+
+}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/H264R480pAacLongPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/H264R480pAacLongPlayerTest.java
new file mode 100644
index 0000000..f01aa75
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/H264R480pAacLongPlayerTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.mediastress.cts;
+
+import android.media.CamcorderProfile;
+import android.media.MediaRecorder.AudioEncoder;
+import android.media.MediaRecorder.VideoEncoder;
+
+public class H264R480pAacLongPlayerTest extends MediaPlayerStressTest {
+    private static final String VIDEO_PATH_MIDDLE = "bbb_full/720x480/mp4_libx264_libfaac/";
+    private final String[] mMedias = {
+        "bbb_full.ffmpeg.720x480.mp4.libx264_500kbps_25fps.libfaac_stereo_128kbps_44100Hz.mp4"
+    };
+
+    public H264R480pAacLongPlayerTest() {
+        super(CamcorderProfile.QUALITY_480P, VideoEncoder.H264, AudioEncoder.AAC);
+    }
+
+    public void testPlay00() throws Exception {
+        doTestVideoPlaybackLong(0);
+    }
+
+    @Override
+    protected String getFullVideoClipName(int mediaNumber) {
+        return VIDEO_TOP_DIR + VIDEO_PATH_MIDDLE + mMedias[mediaNumber];
+    }
+
+}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/H264R480pAacShortPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/H264R480pAacShortPlayerTest.java
new file mode 100644
index 0000000..81b80e5
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/H264R480pAacShortPlayerTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.mediastress.cts;
+
+import android.media.CamcorderProfile;
+import android.media.MediaRecorder.AudioEncoder;
+import android.media.MediaRecorder.VideoEncoder;
+
+public class H264R480pAacShortPlayerTest extends MediaPlayerStressTest {
+    private static final String VIDEO_PATH_MIDDLE = "bbb_short/720x480/mp4_libx264_libfaac/";
+    private final String[] mMedias = {
+        "bbb_short.ffmpeg.720x480.mp4.libx264_1000kbps_25fps.libfaac_stereo_128kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.720x480.mp4.libx264_1000kbps_25fps.libfaac_stereo_192kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.720x480.mp4.libx264_1000kbps_30fps.libfaac_stereo_128kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.720x480.mp4.libx264_1000kbps_30fps.libfaac_stereo_192kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.720x480.mp4.libx264_1350kbps_25fps.libfaac_stereo_128kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.720x480.mp4.libx264_1350kbps_25fps.libfaac_stereo_192kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.720x480.mp4.libx264_1350kbps_30fps.libfaac_stereo_128kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.720x480.mp4.libx264_1350kbps_30fps.libfaac_stereo_192kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.720x480.mp4.libx264_500kbps_25fps.libfaac_stereo_128kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.720x480.mp4.libx264_500kbps_25fps.libfaac_stereo_192kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.720x480.mp4.libx264_500kbps_30fps.libfaac_stereo_128kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.720x480.mp4.libx264_500kbps_30fps.libfaac_stereo_192kbps_44100Hz.mp4"
+    };
+
+    public H264R480pAacShortPlayerTest() {
+        super(CamcorderProfile.QUALITY_480P, VideoEncoder.H264, AudioEncoder.AAC);
+    }
+
+    public void testPlay00() throws Exception {
+        doTestVideoPlaybackShort(0);
+    }
+
+    public void testPlay01() throws Exception {
+        doTestVideoPlaybackShort(1);
+    }
+
+    public void testPlay02() throws Exception {
+        doTestVideoPlaybackShort(2);
+    }
+
+    public void testPlay03() throws Exception {
+        doTestVideoPlaybackShort(3);
+    }
+
+    public void testPlay04() throws Exception {
+        doTestVideoPlaybackShort(4);
+    }
+
+    public void testPlay05() throws Exception {
+        doTestVideoPlaybackShort(5);
+    }
+
+    public void testPlay06() throws Exception {
+        doTestVideoPlaybackShort(6);
+    }
+
+    public void testPlay07() throws Exception {
+        doTestVideoPlaybackShort(7);
+    }
+
+    public void testPlay08() throws Exception {
+        doTestVideoPlaybackShort(8);
+    }
+
+    public void testPlay09() throws Exception {
+        doTestVideoPlaybackShort(9);
+    }
+
+    public void testPlay10() throws Exception {
+        doTestVideoPlaybackShort(10);
+    }
+
+    public void testPlay11() throws Exception {
+        doTestVideoPlaybackShort(11);
+    }
+
+    @Override
+    protected String getFullVideoClipName(int mediaNumber) {
+        return VIDEO_TOP_DIR + VIDEO_PATH_MIDDLE + mMedias[mediaNumber];
+    }
+
+}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/H264R480x360AacShortPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/H264R480x360AacShortPlayerTest.java
new file mode 100644
index 0000000..12e8f6d
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/H264R480x360AacShortPlayerTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.mediastress.cts;
+
+public class H264R480x360AacShortPlayerTest extends MediaPlayerStressTest {
+    private static final String VIDEO_PATH_MIDDLE = "bbb_short/480x360/mp4_libx264_libfaac/";
+    private final String[] mMedias = {
+        "bbb_short.ffmpeg.480x360.mp4.libx264_1000kbps_25fps.libfaac_stereo_128kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.480x360.mp4.libx264_1000kbps_25fps.libfaac_stereo_192kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.480x360.mp4.libx264_1000kbps_30fps.libfaac_stereo_128kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.480x360.mp4.libx264_1000kbps_30fps.libfaac_stereo_192kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.480x360.mp4.libx264_1350kbps_25fps.libfaac_stereo_128kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.480x360.mp4.libx264_1350kbps_25fps.libfaac_stereo_192kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.480x360.mp4.libx264_1350kbps_30fps.libfaac_stereo_128kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.480x360.mp4.libx264_1350kbps_30fps.libfaac_stereo_192kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.480x360.mp4.libx264_500kbps_25fps.libfaac_stereo_128kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.480x360.mp4.libx264_500kbps_25fps.libfaac_stereo_192kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.480x360.mp4.libx264_500kbps_30fps.libfaac_stereo_128kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.480x360.mp4.libx264_500kbps_30fps.libfaac_stereo_192kbps_44100Hz.mp4"
+    };
+
+    public void testPlay00() throws Exception {
+        doTestVideoPlaybackShort(0);
+    }
+
+    public void testPlay01() throws Exception {
+        doTestVideoPlaybackShort(1);
+    }
+
+    public void testPlay02() throws Exception {
+        doTestVideoPlaybackShort(2);
+    }
+
+    public void testPlay03() throws Exception {
+        doTestVideoPlaybackShort(3);
+    }
+
+    public void testPlay04() throws Exception {
+        doTestVideoPlaybackShort(4);
+    }
+
+    public void testPlay05() throws Exception {
+        doTestVideoPlaybackShort(5);
+    }
+
+    public void testPlay06() throws Exception {
+        doTestVideoPlaybackShort(6);
+    }
+
+    public void testPlay07() throws Exception {
+        doTestVideoPlaybackShort(7);
+    }
+
+    public void testPlay08() throws Exception {
+        doTestVideoPlaybackShort(8);
+    }
+
+    public void testPlay09() throws Exception {
+        doTestVideoPlaybackShort(9);
+    }
+
+    public void testPlay10() throws Exception {
+        doTestVideoPlaybackShort(10);
+    }
+
+    public void testPlay11() throws Exception {
+        doTestVideoPlaybackShort(11);
+    }
+
+    @Override
+    protected String getFullVideoClipName(int mediaNumber) {
+        return VIDEO_TOP_DIR + VIDEO_PATH_MIDDLE + mMedias[mediaNumber];
+    }
+
+}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/H264R720pAacLongPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/H264R720pAacLongPlayerTest.java
new file mode 100644
index 0000000..3efec62
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/H264R720pAacLongPlayerTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.mediastress.cts;
+
+import android.media.CamcorderProfile;
+import android.media.MediaRecorder.AudioEncoder;
+import android.media.MediaRecorder.VideoEncoder;
+
+public class H264R720pAacLongPlayerTest extends MediaPlayerStressTest {
+    private static final String VIDEO_PATH_MIDDLE = "bbb_full/1280x720/mp4_libx264_libfaac/";
+    private final String[] mMedias = {
+        "bbb_full.ffmpeg.1280x720.mp4.libx264_1350kbps_25fps.libfaac_stereo_128kbps_44100Hz.mp4",
+        "bbb_full.ffmpeg.1280x720.mp4.libx264_1750kbps_30fps.libfaac_stereo_192kbps_48000Hz.mp4"
+    };
+
+    public H264R720pAacLongPlayerTest() {
+        super(CamcorderProfile.QUALITY_720P, VideoEncoder.H264, AudioEncoder.AAC);
+    }
+
+    public void testPlay00() throws Exception {
+        doTestVideoPlaybackLong(0);
+    }
+
+    public void testPlay01() throws Exception {
+        doTestVideoPlaybackLong(1);
+    }
+
+    @Override
+    protected String getFullVideoClipName(int mediaNumber) {
+        return VIDEO_TOP_DIR + VIDEO_PATH_MIDDLE + mMedias[mediaNumber];
+    }
+
+}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/H264R720pAacShortPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/H264R720pAacShortPlayerTest.java
new file mode 100644
index 0000000..e919a35
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/H264R720pAacShortPlayerTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.mediastress.cts;
+
+import android.media.CamcorderProfile;
+import android.media.MediaRecorder.AudioEncoder;
+import android.media.MediaRecorder.VideoEncoder;
+
+public class H264R720pAacShortPlayerTest extends MediaPlayerStressTest {
+    private static final String VIDEO_PATH_MIDDLE = "bbb_short/1280x720/mp4_libx264_libfaac/";
+    private final String[] mMedias = {
+        "bbb_short.ffmpeg.1280x720.mp4.libx264_10000kbps_30fps.libfaac_stereo_192kbps_48000Hz.mp4",
+        "bbb_short.ffmpeg.1280x720.mp4.libx264_1000kbps_25fps.libfaac_stereo_128kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.1280x720.mp4.libx264_1000kbps_25fps.libfaac_stereo_192kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.1280x720.mp4.libx264_1000kbps_30fps.libfaac_stereo_128kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.1280x720.mp4.libx264_1000kbps_30fps.libfaac_stereo_192kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.1280x720.mp4.libx264_1350kbps_25fps.libfaac_stereo_128kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.1280x720.mp4.libx264_1350kbps_25fps.libfaac_stereo_192kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.1280x720.mp4.libx264_1350kbps_30fps.libfaac_stereo_128kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.1280x720.mp4.libx264_1350kbps_30fps.libfaac_stereo_192kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.1280x720.mp4.libx264_1750kbps_30fps.libfaac_stereo_192kbps_48000Hz.mp4",
+        "bbb_short.ffmpeg.1280x720.mp4.libx264_5000kbps_30fps.libfaac_stereo_192kbps_48000Hz.mp4",
+        "bbb_short.ffmpeg.1280x720.mp4.libx264_500kbps_25fps.libfaac_stereo_128kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.1280x720.mp4.libx264_500kbps_25fps.libfaac_stereo_192kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.1280x720.mp4.libx264_500kbps_30fps.libfaac_stereo_128kbps_44100Hz.mp4",
+        "bbb_short.ffmpeg.1280x720.mp4.libx264_500kbps_30fps.libfaac_stereo_192kbps_44100Hz.mp4"
+    };
+
+    public H264R720pAacShortPlayerTest() {
+        super(CamcorderProfile.QUALITY_720P, VideoEncoder.H264, AudioEncoder.AAC);
+    }
+
+    public void testPlay00() throws Exception {
+        doTestVideoPlaybackShort(0);
+    }
+
+    public void testPlay01() throws Exception {
+        doTestVideoPlaybackShort(1);
+    }
+
+    public void testPlay02() throws Exception {
+        doTestVideoPlaybackShort(2);
+    }
+
+    public void testPlay03() throws Exception {
+        doTestVideoPlaybackShort(3);
+    }
+
+    public void testPlay04() throws Exception {
+        doTestVideoPlaybackShort(4);
+    }
+
+    public void testPlay05() throws Exception {
+        doTestVideoPlaybackShort(5);
+    }
+
+    public void testPlay06() throws Exception {
+        doTestVideoPlaybackShort(6);
+    }
+
+    public void testPlay07() throws Exception {
+        doTestVideoPlaybackShort(7);
+    }
+
+    public void testPlay08() throws Exception {
+        doTestVideoPlaybackShort(8);
+    }
+
+    public void testPlay09() throws Exception {
+        doTestVideoPlaybackShort(9);
+    }
+
+    public void testPlay10() throws Exception {
+        doTestVideoPlaybackShort(10);
+    }
+
+    public void testPlay11() throws Exception {
+        doTestVideoPlaybackShort(11);
+    }
+
+    public void testPlay12() throws Exception {
+        doTestVideoPlaybackShort(12);
+    }
+
+    public void testPlay13() throws Exception {
+        doTestVideoPlaybackShort(13);
+    }
+
+    public void testPlay14() throws Exception {
+        doTestVideoPlaybackShort(14);
+    }
+
+    @Override
+    protected String getFullVideoClipName(int mediaNumber) {
+        return VIDEO_TOP_DIR + VIDEO_PATH_MIDDLE + mMedias[mediaNumber];
+    }
+
+}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/MediaFrameworkTest.java b/tests/tests/mediastress/src/android/mediastress/cts/MediaFrameworkTest.java
new file mode 100644
index 0000000..b8c67e4
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/MediaFrameworkTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.mediastress.cts;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.PowerManager;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+
+import com.android.cts.mediastress.R;
+
+public class MediaFrameworkTest extends Activity implements SurfaceHolder.Callback {
+    private static String TAG = "MediaFrameworkTest";
+    private static SurfaceView mSurfaceView;
+
+    private Bitmap mDestBitmap;
+    private ImageView mOverlayView;
+
+    private PowerManager.WakeLock mWakeLock = null;
+
+    public static SurfaceView getSurfaceView() {
+        return mSurfaceView;
+    }
+
+    /** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.surface_view);
+        mSurfaceView = (SurfaceView)findViewById(R.id.surface_view);
+        mOverlayView = (ImageView)findViewById(R.id.overlay_layer);
+        ViewGroup.LayoutParams lp = mSurfaceView.getLayoutParams();
+        mSurfaceView.getHolder().addCallback(this);
+
+        mOverlayView.setLayoutParams(lp);
+        mDestBitmap = Bitmap.createBitmap((int)640, (int)480, Bitmap.Config.ARGB_8888);
+        mOverlayView.setImageBitmap(mDestBitmap);
+
+        //Acquire the full wake lock to keep the device up
+        PowerManager pm = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "MediaFrameworkTest");
+        mWakeLock.acquire();
+    }
+
+    public void onStop(Bundle icicle) {
+        mWakeLock.release();
+        super.onStop();
+    }
+
+    public void surfaceDestroyed(SurfaceHolder holder) {
+        //Can do nothing in here. The test case will fail if the surface destroyed.
+        Log.v(TAG, "Test application surface destroyed");
+    }
+
+    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+        //Do nothing in here. Just print out the log
+        Log.v(TAG, "Test application surface changed");
+    }
+
+    public void surfaceCreated(SurfaceHolder holder) {
+        holder.addCallback(this);
+        Log.v(TAG, "Test application surface created");
+    }
+
+    public void startPlayback(String filename){
+      String mimetype = "audio/mpeg";
+      Uri path = Uri.parse(filename);
+      Intent intent = new Intent(Intent.ACTION_VIEW);
+      intent.setDataAndType(path, mimetype);
+      startActivity(intent);
+    }
+}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/MediaPlayerStressTest.java b/tests/tests/mediastress/src/android/mediastress/cts/MediaPlayerStressTest.java
new file mode 100644
index 0000000..3678811
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/MediaPlayerStressTest.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.mediastress.cts;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.media.CamcorderProfile;
+import android.media.MediaRecorder.AudioEncoder;
+import android.media.MediaRecorder.VideoEncoder;
+import android.os.Environment;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.Writer;
+
+import android.test.InstrumentationTestCase;
+
+/**
+ * Helper for implementing video playback stress test
+ */
+abstract class MediaPlayerStressTest extends InstrumentationTestCase {
+    protected static final String VIDEO_TOP_DIR = WorkDir.getMediaDirString();
+    protected static final int REPEAT_NUMBER_FOR_SHORT_CLIPS = 2;
+    protected static final int REPEAT_NUMBER_FOR_LONG_CLIPS = 1;
+    private static final String TAG = "MediaPlayerStressTest";
+    // whether a video format is supported or not.
+    private final boolean mSupported;
+
+    /**
+     * construct a test case with check of whether the format is supported or not.
+     * @param quality
+     * @param videoCodec
+     * @param audioCodec
+     */
+    protected MediaPlayerStressTest(int quality, int videoCodec, int audioCodec) {
+        mSupported = VideoPlayerCapability.formatSupported(quality, videoCodec, audioCodec);
+    }
+
+    protected MediaPlayerStressTest() {
+        mSupported = true; // supported if nothing specified
+    }
+
+    /**
+     * provides full path name of video clip for the given media number
+     * @param mediaNumber
+     * @return video file name
+     */
+    abstract protected String getFullVideoClipName(int mediaNumber);
+
+    private int mTotalPlaybackError;
+    private int mTotalComplete;
+    private int mTotalInfoUnknown;
+    private int mTotalVideoTrackLagging;
+    private int mTotalBadInterleaving;
+    private int mTotalNotSeekable;
+    private int mTotalMetaDataUpdate;
+
+    private void writeTestOutput(String filename, Writer output) throws Exception{
+        output.write("File Name: " + filename);
+        output.write(" Complete: " + CodecTest.mOnCompleteSuccess);
+        output.write(" Error: " + CodecTest.mPlaybackError);
+        output.write(" Unknown Info: " + CodecTest.mMediaInfoUnknownCount);
+        output.write(" Track Lagging: " +  CodecTest.mMediaInfoVideoTrackLaggingCount);
+        output.write(" Bad Interleaving: " + CodecTest.mMediaInfoBadInterleavingCount);
+        output.write(" Not Seekable: " + CodecTest.mMediaInfoNotSeekableCount);
+        output.write(" Info Meta data update: " + CodecTest.mMediaInfoMetdataUpdateCount);
+        output.write("\n");
+    }
+
+    private void writeTestSummary(Writer output) throws Exception{
+        output.write("Total Result:\n");
+        output.write("Total Complete: " + mTotalComplete + "\n");
+        output.write("Total Error: " + mTotalPlaybackError + "\n");
+        output.write("Total Unknown Info: " + mTotalInfoUnknown + "\n");
+        output.write("Total Track Lagging: " + mTotalVideoTrackLagging + "\n" );
+        output.write("Total Bad Interleaving: " + mTotalBadInterleaving + "\n");
+        output.write("Total Not Seekable: " + mTotalNotSeekable + "\n");
+        output.write("Total Info Meta data update: " + mTotalMetaDataUpdate + "\n");
+        output.write("\n");
+    }
+
+    private void updateTestResult(){
+        if (CodecTest.mOnCompleteSuccess){
+            mTotalComplete++;
+        }
+        else if (CodecTest.mPlaybackError){
+            mTotalPlaybackError++;
+        }
+        mTotalInfoUnknown += CodecTest.mMediaInfoUnknownCount;
+        mTotalVideoTrackLagging += CodecTest.mMediaInfoVideoTrackLaggingCount;
+        mTotalBadInterleaving += CodecTest.mMediaInfoBadInterleavingCount;
+        mTotalNotSeekable += CodecTest.mMediaInfoNotSeekableCount;
+        mTotalMetaDataUpdate += CodecTest.mMediaInfoMetdataUpdateCount;
+    }
+
+    /**
+     * runs video playback test for the given mediaNumber
+     * @param mediaNumber number of media to be used for playback.
+     *         This number is passed to getFullVideoClipName.
+     * @param  repeatCounter repeat playback for the given number
+     * @throws Exception
+     */
+    protected void doTestVideoPlayback(int mediaNumber, int repeatCounter) throws Exception {
+        if (!mSupported) {
+            return;
+        }
+
+        File playbackOutput = new File(WorkDir.getTopDir(), "PlaybackTestResult.txt");
+        Writer output = new BufferedWriter(new FileWriter(playbackOutput, true));
+
+        boolean testResult = true;
+        boolean onCompleteSuccess = false;
+
+        Instrumentation inst = getInstrumentation();
+        Intent intent = new Intent();
+
+        intent.setClass(inst.getTargetContext(), MediaFrameworkTest.class);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+        Activity act = inst.startActivitySync(intent);
+
+        String mediaName = getFullVideoClipName(mediaNumber);
+        for (int i = 0; i < repeatCounter; i++) {
+            Log.v(TAG, "start playing " + mediaName);
+            onCompleteSuccess =
+                CodecTest.playMediaSample(mediaName);
+            if (!onCompleteSuccess) {
+                //Don't fail the test right away, print out the failure file.
+                Log.v(TAG, "Failure File : " + mediaName);
+                testResult = false;
+            }
+        }
+        Thread.sleep(1000);
+
+        act.finish();
+        //Write test result to an output file
+        writeTestOutput(mediaName, output);
+        //Get the summary
+        updateTestResult();
+
+        writeTestSummary(output);
+        output.close();
+        assertTrue("playback " + mediaName, testResult);
+    }
+
+    protected void doTestVideoPlaybackShort(int mediaNumber) throws Exception {
+        doTestVideoPlayback(mediaNumber, REPEAT_NUMBER_FOR_SHORT_CLIPS);
+    }
+
+    protected void doTestVideoPlaybackLong(int mediaNumber) throws Exception {
+        doTestVideoPlayback(mediaNumber, REPEAT_NUMBER_FOR_LONG_CLIPS);
+    }
+}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/MediaRecorderStressTest.java b/tests/tests/mediastress/src/android/mediastress/cts/MediaRecorderStressTest.java
new file mode 100644
index 0000000..fd4e3b3
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/MediaRecorderStressTest.java
@@ -0,0 +1,382 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.mediastress.cts;
+
+import android.hardware.Camera;
+import android.media.CamcorderProfile;
+import android.media.MediaPlayer;
+import android.media.MediaRecorder;
+import android.os.Handler;
+import android.os.Looper;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+import android.view.SurfaceHolder;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.Writer;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+public class MediaRecorderStressTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
+
+    private static String TAG = "MediaRecorderStressTest";
+    private static final int NUMBER_OF_CAMERA_STRESS_LOOPS = 50;
+    private static final int NUMBER_OF_RECORDER_STRESS_LOOPS = 50;
+    private static final int NUMBER_OF_RECORDERANDPLAY_STRESS_LOOPS = 25;
+    private static final int NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER = 50;
+    private static final long WAIT_TIME_CAMERA_TEST = 3000;  // in ms
+    private static final long WAIT_TIME_RECORDER_TEST = 5000;  // in ms
+    private static final String OUTPUT_FILE = WorkDir.getTopDirString() + "temp";
+    private static final String OUTPUT_FILE_EXT = ".3gp";
+    private static final String MEDIA_STRESS_OUTPUT ="mediaStressOutput.txt";
+    private final CameraErrorCallback mCameraErrorCallback = new CameraErrorCallback();
+    private final RecorderErrorCallback mRecorderErrorCallback = new RecorderErrorCallback();
+    private final static int WAIT_TIMEOUT = 10000;
+
+    private MediaRecorder mRecorder;
+    private Camera mCamera;
+    private Thread mLooperThread;
+    private Handler mHandler;
+
+    private static int mCameraId;
+    private static int mProfileQuality = CamcorderProfile.QUALITY_HIGH;
+    private static CamcorderProfile profile =
+                        CamcorderProfile.get(mCameraId, mProfileQuality);
+
+    private int mVideoEncoder;
+    private int mAudioEncoder;
+    private int mFrameRate;
+    private int mVideoWidth;
+    private int mVideoHeight;
+    private int mBitRate;
+    private boolean mRemoveVideo = true;
+    private int mRecordDuration = 5000;
+
+    public MediaRecorderStressTest() {
+        super(MediaFrameworkTest.class);
+    }
+
+    protected void setUp() throws Exception {
+        int cameraId = 0;
+        CamcorderProfile profile = CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_HIGH);
+        mVideoEncoder = profile.videoCodec;
+        mAudioEncoder = profile.audioCodec;
+        mFrameRate = profile.videoFrameRate;
+        mVideoWidth = profile.videoFrameWidth;
+        mVideoHeight = profile.videoFrameHeight;
+        mBitRate = profile.videoBitRate;
+
+        final Semaphore sem = new Semaphore(0);
+        mLooperThread = new Thread() {
+            @Override
+            public void run() {
+                Log.v(TAG, "starting looper");
+                Looper.prepare();
+                mHandler = new Handler();
+                sem.release();
+                Looper.loop();
+                Log.v(TAG, "quit looper");
+            }
+        };
+        mLooperThread.start();
+        if (!sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
+            fail("Failed to start the looper.");
+        }
+
+        getActivity();
+        super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mHandler != null) {
+            mHandler.getLooper().quit();
+            mHandler = null;
+        }
+        if (mLooperThread != null) {
+            mLooperThread.join(WAIT_TIMEOUT);
+            if (mLooperThread.isAlive()) {
+                fail("Failed to stop the looper.");
+            }
+            mLooperThread = null;
+        }
+
+        super.tearDown();
+    }
+
+    private void runOnLooper(final Runnable command) throws InterruptedException {
+        final Semaphore sem = new Semaphore(0);
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    command.run();
+                } finally {
+                    sem.release();
+                }
+            }
+        });
+        if (! sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
+            fail("Failed to run the command on the looper.");
+        }
+    }
+
+    private final class CameraErrorCallback implements android.hardware.Camera.ErrorCallback {
+        public void onError(int error, android.hardware.Camera camera) {
+            assertTrue("Camera test mediaserver died", error !=
+                    android.hardware.Camera.CAMERA_ERROR_SERVER_DIED);
+        }
+    }
+
+    private final class RecorderErrorCallback implements MediaRecorder.OnErrorListener {
+        public void onError(MediaRecorder mr, int what, int extra) {
+            // fail the test case no matter what error come up
+            fail("mediaRecorder error");
+        }
+    }
+
+    //Test case for stressing the camera preview.
+    @LargeTest
+    public void testStressCamera() throws Exception {
+        SurfaceHolder mSurfaceHolder;
+        mSurfaceHolder = MediaFrameworkTest.getSurfaceView().getHolder();
+        File stressOutFile = new File(WorkDir.getTopDir(), MEDIA_STRESS_OUTPUT);
+        Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
+        output.write("Camera start preview stress:\n");
+        output.write("Total number of loops:" +
+                NUMBER_OF_CAMERA_STRESS_LOOPS + "\n");
+
+        Log.v(TAG, "Start preview");
+        output.write("No of loop: ");
+
+        for (int i = 0; i< NUMBER_OF_CAMERA_STRESS_LOOPS; i++) {
+            runOnLooper(new Runnable() {
+                @Override
+                public void run() {
+                    mCamera = Camera.open();
+                }
+            });
+            mCamera.setErrorCallback(mCameraErrorCallback);
+            mCamera.setPreviewDisplay(mSurfaceHolder);
+            mCamera.startPreview();
+            Thread.sleep(WAIT_TIME_CAMERA_TEST);
+            mCamera.stopPreview();
+            mCamera.release();
+            output.write(" ," + i);
+        }
+
+        output.write("\n\n");
+        output.close();
+    }
+
+    //Test case for stressing the camera preview.
+    @LargeTest
+    public void testStressRecorder() throws Exception {
+        String filename;
+        SurfaceHolder mSurfaceHolder;
+        mSurfaceHolder = MediaFrameworkTest.getSurfaceView().getHolder();
+        File stressOutFile = new File(WorkDir.getTopDir(), MEDIA_STRESS_OUTPUT);
+        Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
+        output.write("H263 video record- reset after prepare Stress test\n");
+        output.write("Total number of loops:" +
+                NUMBER_OF_RECORDER_STRESS_LOOPS + "\n");
+
+        output.write("No of loop: ");
+        Log.v(TAG, "Start preview");
+        for (int i = 0; i < NUMBER_OF_RECORDER_STRESS_LOOPS; i++) {
+            runOnLooper(new Runnable() {
+                @Override
+                public void run() {
+                    mRecorder = new MediaRecorder();
+                }
+            });
+            Log.v(TAG, "counter = " + i);
+            filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
+            Log.v(TAG, filename);
+            mRecorder.setOnErrorListener(mRecorderErrorCallback);
+            mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
+            mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
+            mRecorder.setOutputFile(filename);
+            mRecorder.setVideoFrameRate(mFrameRate);
+            mRecorder.setVideoSize(176,144);
+            Log.v(TAG, "setEncoder");
+            mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);
+            mSurfaceHolder = MediaFrameworkTest.getSurfaceView().getHolder();
+            Log.v(TAG, "setPreview");
+            mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
+            Log.v(TAG, "prepare");
+            mRecorder.prepare();
+            Log.v(TAG, "before release");
+            Thread.sleep(WAIT_TIME_RECORDER_TEST);
+            mRecorder.reset();
+            mRecorder.release();
+            output.write(", " + i);
+        }
+
+        output.write("\n\n");
+        output.close();
+    }
+
+    //Stress test case for switching camera and video recorder preview.
+    @LargeTest
+    public void testStressCameraSwitchRecorder() throws Exception {
+        String filename;
+        SurfaceHolder mSurfaceHolder;
+        mSurfaceHolder = MediaFrameworkTest.getSurfaceView().getHolder();
+        File stressOutFile = new File(WorkDir.getTopDir(), MEDIA_STRESS_OUTPUT);
+        Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
+        output.write("Camera and video recorder preview switching\n");
+        output.write("Total number of loops:"
+                + NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER + "\n");
+
+        Log.v(TAG, "Start preview");
+        output.write("No of loop: ");
+        for (int i = 0; i < NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER; i++) {
+            runOnLooper(new Runnable() {
+                @Override
+                public void run() {
+                    mCamera = Camera.open();
+                }
+            });
+            mCamera.setErrorCallback(mCameraErrorCallback);
+            mCamera.setPreviewDisplay(mSurfaceHolder);
+            mCamera.startPreview();
+            Thread.sleep(WAIT_TIME_CAMERA_TEST);
+            mCamera.stopPreview();
+            mCamera.release();
+            mCamera = null;
+            Log.v(TAG, "release camera");
+            filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
+            Log.v(TAG, filename);
+            runOnLooper(new Runnable() {
+                @Override
+                public void run() {
+                    mRecorder = new MediaRecorder();
+                }
+            });
+            mRecorder.setOnErrorListener(mRecorderErrorCallback);
+            mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
+            mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
+            mRecorder.setOutputFile(filename);
+            mRecorder.setVideoFrameRate(mFrameRate);
+            mRecorder.setVideoSize(176,144);
+            Log.v(TAG, "Media recorder setEncoder");
+            mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);
+            Log.v(TAG, "mediaRecorder setPreview");
+            mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
+            Log.v(TAG, "prepare");
+            mRecorder.prepare();
+            Log.v(TAG, "before release");
+            Thread.sleep(WAIT_TIME_CAMERA_TEST);
+            mRecorder.reset();
+            mRecorder.release();
+            Log.v(TAG, "release video recorder");
+            output.write(", " + i);
+        }
+
+        output.write("\n\n");
+        output.close();
+    }
+
+    public void validateRecordedVideo(String recordedFile) throws Exception {
+        MediaPlayer mp = new MediaPlayer();
+        mp.setDataSource(recordedFile);
+        mp.prepare();
+        int duration = mp.getDuration();
+        if (duration <= 0){
+            assertTrue("stressRecordAndPlayback", false);
+        }
+        mp.release();
+    }
+
+    public void removeRecodedVideo(String filename){
+        File video = new File(filename);
+        Log.v(TAG, "remove recorded video " + filename);
+        video.delete();
+    }
+
+    //Stress test case for record a video and play right away.
+    @LargeTest
+    public void testStressRecordVideoAndPlayback() throws Exception {
+        String filename;
+        SurfaceHolder mSurfaceHolder;
+        mSurfaceHolder = MediaFrameworkTest.getSurfaceView().getHolder();
+        File stressOutFile = new File(WorkDir.getTopDir(), MEDIA_STRESS_OUTPUT);
+        Writer output = new BufferedWriter(
+                new FileWriter(stressOutFile, true));
+        output.write("Video record and play back stress test:\n");
+        output.write("Total number of loops:"
+                + NUMBER_OF_RECORDERANDPLAY_STRESS_LOOPS + "\n");
+
+        output.write("No of loop: ");
+        for (int i = 0; i < NUMBER_OF_RECORDERANDPLAY_STRESS_LOOPS; i++){
+            filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
+            Log.v(TAG, filename);
+            runOnLooper(new Runnable() {
+                @Override
+                public void run() {
+                    mRecorder = new MediaRecorder();
+                }
+            });
+            Log.v(TAG, "iterations : " + i);
+            Log.v(TAG, "videoEncoder : " + mVideoEncoder);
+            Log.v(TAG, "audioEncoder : " + mAudioEncoder);
+            Log.v(TAG, "frameRate : " + mFrameRate);
+            Log.v(TAG, "videoWidth : " + mVideoWidth);
+            Log.v(TAG, "videoHeight : " + mVideoHeight);
+            Log.v(TAG, "bitRate : " + mBitRate);
+            Log.v(TAG, "recordDuration : " + mRecordDuration);
+
+            mRecorder.setOnErrorListener(mRecorderErrorCallback);
+            mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
+            mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
+            mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
+            mRecorder.setOutputFile(filename);
+            mRecorder.setVideoFrameRate(mFrameRate);
+            mRecorder.setVideoSize(mVideoWidth, mVideoHeight);
+            mRecorder.setVideoEncoder(mVideoEncoder);
+            mRecorder.setAudioEncoder(mAudioEncoder);
+            Log.v(TAG, "mediaRecorder setPreview");
+            mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
+            mRecorder.prepare();
+            mRecorder.start();
+            Thread.sleep(mRecordDuration);
+            Log.v(TAG, "Before stop");
+            mRecorder.stop();
+            mRecorder.release();
+            //start the playback
+            MediaPlayer mp = new MediaPlayer();
+            mp.setDataSource(filename);
+            mp.setDisplay(MediaFrameworkTest.getSurfaceView().getHolder());
+            mp.prepare();
+            mp.start();
+            Thread.sleep(mRecordDuration);
+            mp.release();
+            validateRecordedVideo(filename);
+            if (mRemoveVideo) {
+                removeRecodedVideo(filename);
+            }
+            output.write(", " + i);
+        }
+
+        output.write("\n\n");
+        output.close();
+    }
+}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/VideoPlayerCapability.java b/tests/tests/mediastress/src/android/mediastress/cts/VideoPlayerCapability.java
new file mode 100644
index 0000000..f8dd2aa
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/VideoPlayerCapability.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.mediastress.cts;
+
+import android.media.CamcorderProfile;
+import android.util.Log;
+
+import junit.framework.Assert;
+
+public class VideoPlayerCapability {
+    private static final String TAG = "VideoPlayCapability";
+
+    static boolean formatSupported(int quality, int videoCodec, int audioCodec) {
+        if (!CamcorderProfile.hasProfile(quality)) {
+            Log.i(TAG, "quality " + quality + " not supported");
+            return false;
+        }
+        CamcorderProfile profile = CamcorderProfile.get(quality);
+        Assert.assertNotNull(profile);
+        if ((profile.videoCodec == videoCodec) && (profile.audioCodec == audioCodec)) {
+            Log.i(TAG, "quality " + quality + " video codec " + videoCodec + " audio codec " +
+                    audioCodec + " supproted");
+            return true;
+        }
+        return false;
+    }
+
+}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/Vp8R480x360LongPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/Vp8R480x360LongPlayerTest.java
new file mode 100644
index 0000000..372f034
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/Vp8R480x360LongPlayerTest.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.mediastress.cts;
+
+public class Vp8R480x360LongPlayerTest extends MediaPlayerStressTest {
+    private static final String VIDEO_PATH_MIDDLE = "bbb_full/480x360/webm_libvpx_libvorbis/";
+    private final String[] mMedias = {
+        "bbb_full.ffmpeg.480x360.webm.libvpx_500kbps_25fps.libvorbis_stereo_128kbps_44100Hz.webm"
+    };
+
+    public void testPlay00() throws Exception {
+        doTestVideoPlaybackLong(0);
+    }
+
+    @Override
+    protected String getFullVideoClipName(int mediaNumber) {
+        return VIDEO_TOP_DIR + VIDEO_PATH_MIDDLE + mMedias[mediaNumber];
+    }
+
+}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/Vp8R480x360ShortPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/Vp8R480x360ShortPlayerTest.java
new file mode 100644
index 0000000..30b4d2e
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/Vp8R480x360ShortPlayerTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.mediastress.cts;
+
+public class Vp8R480x360ShortPlayerTest extends MediaPlayerStressTest {
+    private static final String VIDEO_PATH_MIDDLE = "bbb_short/480x360/webm_libvpx_libvorbis/";
+    private final String[] mMedias = {
+        "bbb_short.ffmpeg.480x360.webm.libvpx_1000kbps_25fps.libvorbis_stereo_128kbps_44100Hz.webm",
+        "bbb_short.ffmpeg.480x360.webm.libvpx_1000kbps_25fps.libvorbis_stereo_192kbps_44100Hz.webm",
+        "bbb_short.ffmpeg.480x360.webm.libvpx_1000kbps_30fps.libvorbis_stereo_128kbps_44100Hz.webm",
+        "bbb_short.ffmpeg.480x360.webm.libvpx_1000kbps_30fps.libvorbis_stereo_192kbps_44100Hz.webm",
+        "bbb_short.ffmpeg.480x360.webm.libvpx_1350kbps_25fps.libvorbis_stereo_128kbps_44100Hz.webm",
+        "bbb_short.ffmpeg.480x360.webm.libvpx_1350kbps_25fps.libvorbis_stereo_192kbps_44100Hz.webm",
+        "bbb_short.ffmpeg.480x360.webm.libvpx_1350kbps_30fps.libvorbis_stereo_128kbps_44100Hz.webm",
+        "bbb_short.ffmpeg.480x360.webm.libvpx_1350kbps_30fps.libvorbis_stereo_192kbps_44100Hz.webm",
+        "bbb_short.ffmpeg.480x360.webm.libvpx_500kbps_25fps.libvorbis_stereo_128kbps_44100Hz.webm",
+        "bbb_short.ffmpeg.480x360.webm.libvpx_500kbps_25fps.libvorbis_stereo_192kbps_44100Hz.webm",
+        "bbb_short.ffmpeg.480x360.webm.libvpx_500kbps_30fps.libvorbis_stereo_128kbps_44100Hz.webm",
+        "bbb_short.ffmpeg.480x360.webm.libvpx_500kbps_30fps.libvorbis_stereo_192kbps_44100Hz.webm"
+    };
+
+    public void testPlay00() throws Exception {
+        doTestVideoPlaybackShort(0);
+    }
+
+    public void testPlay01() throws Exception {
+        doTestVideoPlaybackShort(1);
+    }
+
+    public void testPlay02() throws Exception {
+        doTestVideoPlaybackShort(2);
+    }
+
+    public void testPlay03() throws Exception {
+        doTestVideoPlaybackShort(3);
+    }
+
+    public void testPlay04() throws Exception {
+        doTestVideoPlaybackShort(4);
+    }
+
+    public void testPlay05() throws Exception {
+        doTestVideoPlaybackShort(5);
+    }
+
+    public void testPlay06() throws Exception {
+        doTestVideoPlaybackShort(6);
+    }
+
+    public void testPlay07() throws Exception {
+        doTestVideoPlaybackShort(7);
+    }
+
+    public void testPlay08() throws Exception {
+        doTestVideoPlaybackShort(8);
+    }
+
+    public void testPlay09() throws Exception {
+        doTestVideoPlaybackShort(9);
+    }
+
+    public void testPlay10() throws Exception {
+        doTestVideoPlaybackShort(10);
+    }
+
+    public void testPlay11() throws Exception {
+        doTestVideoPlaybackShort(11);
+    }
+
+    @Override
+    protected String getFullVideoClipName(int mediaNumber) {
+        return VIDEO_TOP_DIR + VIDEO_PATH_MIDDLE + mMedias[mediaNumber];
+    }
+
+}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/WorkDir.java b/tests/tests/mediastress/src/android/mediastress/cts/WorkDir.java
new file mode 100644
index 0000000..4a40fad
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/WorkDir.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.mediastress.cts;
+
+import android.os.Environment;
+
+import java.io.File;
+
+import junit.framework.Assert;
+
+public class WorkDir {
+    static final File getTopDir() {
+        Assert.assertEquals(Environment.getExternalStorageState(), Environment.MEDIA_MOUNTED);
+        return Environment.getExternalStorageDirectory();
+    }
+
+    static final String getTopDirString() {
+        return (getTopDir().getAbsolutePath() + File.separator);
+    }
+
+    static final String getMediaDirString() {
+        return (getTopDirString() + "test/");
+    }
+}
diff --git a/tests/tests/net/Android.mk b/tests/tests/net/Android.mk
index 1fd9ba0..bf51890 100644
--- a/tests/tests/net/Android.mk
+++ b/tests/tests/net/Android.mk
@@ -23,12 +23,12 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+# include CtsTestServer as a temporary hack to free net.cts from cts.stub.
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+	../../src/android/webkit/cts/CtsTestServer.java
 
 LOCAL_PACKAGE_NAME := CtsNetTestCases
 
-LOCAL_INSTRUMENTATION_FOR := CtsTestStubs
-
 # uncomment when dalvik.annotation.Test* are removed or part of SDK
 #LOCAL_SDK_VERSION := current
 
diff --git a/tests/tests/net/AndroidManifest.xml b/tests/tests/net/AndroidManifest.xml
index a1f632e..4fa0565 100644
--- a/tests/tests/net/AndroidManifest.xml
+++ b/tests/tests/net/AndroidManifest.xml
@@ -18,12 +18,20 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.cts.net">
 
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
     <application>
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="com.android.cts.stub"
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+                     android:targetPackage="com.android.cts.net"
                      android:label="CTS tests of android.net"/>
 
 </manifest>
diff --git a/tests/tests/net/src/android/net/cts/VpnServiceTest.java b/tests/tests/net/src/android/net/cts/VpnServiceTest.java
new file mode 100644
index 0000000..9e35375
--- /dev/null
+++ b/tests/tests/net/src/android/net/cts/VpnServiceTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.net.cts;
+
+import android.content.Intent;
+import android.net.VpnService;
+import android.os.ParcelFileDescriptor;
+import android.test.AndroidTestCase;
+
+import java.io.File;
+import java.net.DatagramSocket;
+import java.net.Socket;
+
+/**
+ * VpnService API is built with security in mind. However, its security also
+ * blocks us from writing tests for positive cases. For now we only test for
+ * negative cases, and we will try to cover the rest in the future.
+ */
+public class VpnServiceTest extends AndroidTestCase {
+
+    private static final String TAG = VpnServiceTest.class.getSimpleName();
+
+    private VpnService mVpnService = new VpnService();
+
+    public void testPrepare() throws Exception {
+        // Should never return null since we are not prepared.
+        Intent intent = VpnService.prepare(mContext);
+        assertNotNull(intent);
+
+        // Should be always resolved by only one activity.
+        int count = mContext.getPackageManager().queryIntentActivities(intent, 0).size();
+        assertEquals(count, 1);
+    }
+
+    public void testEstablish() throws Exception {
+        ParcelFileDescriptor descriptor = null;
+        try {
+            // Should always return null since we are not prepared.
+            descriptor = mVpnService.new Builder().addAddress("8.8.8.8", 30).establish();
+            assertNull(descriptor);
+        } finally {
+            try {
+                descriptor.close();
+            } catch (Exception e) {
+                // ignore
+            }
+        }
+    }
+
+    public void testProtect_DatagramSocket() throws Exception {
+        DatagramSocket socket = new DatagramSocket();
+        try {
+            // Should always return false since we are not prepared.
+            assertFalse(mVpnService.protect(socket));
+        } finally {
+            try {
+                socket.close();
+            } catch (Exception e) {
+                // ignore
+            }
+        }
+    }
+
+    public void testProtect_Socket() throws Exception {
+        Socket socket = new Socket();
+        try {
+            // Should always return false since we are not prepared.
+            assertFalse(mVpnService.protect(socket));
+        } finally {
+            try {
+                socket.close();
+            } catch (Exception e) {
+                // ignore
+            }
+        }
+    }
+
+    public void testProtect_int() throws Exception {
+        DatagramSocket socket = new DatagramSocket();
+        ParcelFileDescriptor descriptor = ParcelFileDescriptor.fromDatagramSocket(socket);
+        try {
+            // Should always return false since we are not prepared.
+            assertFalse(mVpnService.protect(descriptor.getFd()));
+        } finally {
+            try {
+                descriptor.close();
+            } catch (Exception e) {
+                // ignore
+            }
+            try {
+                socket.close();
+            } catch (Exception e) {
+                // ignore
+            }
+        }
+    }
+
+    public void testTunDevice() throws Exception {
+        File file = new File("/dev/tun");
+        assertTrue(file.exists());
+        assertFalse(file.isFile());
+        assertFalse(file.isDirectory());
+        assertFalse(file.canExecute());
+        assertFalse(file.canRead());
+        assertFalse(file.canWrite());
+    }
+}
diff --git a/tests/tests/net/src/android/net/wifi/cts/ScanResultTest.java b/tests/tests/net/src/android/net/wifi/cts/ScanResultTest.java
index 0ab71c7..b7202d2 100644
--- a/tests/tests/net/src/android/net/wifi/cts/ScanResultTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/ScanResultTest.java
@@ -65,6 +65,10 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
         mMySync = new MySync();
         mIntentFilter = new IntentFilter();
         mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
@@ -90,6 +94,11 @@
 
     @Override
     protected void tearDown() throws Exception {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            super.tearDown();
+            return;
+        }
         mWifiLock.release();
         mContext.unregisterReceiver(mReceiver);
         if (!mWifiManager.isWifiEnabled())
@@ -115,6 +124,10 @@
         args = {}
     )
     public void testScanResultProperties() {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
         List<ScanResult> scanResults = mWifiManager.getScanResults();
         // this test case should in Wifi environment
         for (int i = 0; i < scanResults.size(); i++) {
diff --git a/tests/tests/net/src/android/net/wifi/cts/SupplicantStateTest.java b/tests/tests/net/src/android/net/wifi/cts/SupplicantStateTest.java
index 4e03f5e..88ecfe8 100644
--- a/tests/tests/net/src/android/net/wifi/cts/SupplicantStateTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/SupplicantStateTest.java
@@ -34,6 +34,10 @@
         )
     })
     public void testIsValidState() {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
         assertTrue(SupplicantState.isValidState(SupplicantState.DISCONNECTED));
         assertTrue(SupplicantState.isValidState(SupplicantState.INACTIVE));
         assertTrue(SupplicantState.isValidState(SupplicantState.SCANNING));
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiConfigurationTest.java b/tests/tests/net/src/android/net/wifi/cts/WifiConfigurationTest.java
index 3018907..f11aa4a 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiConfigurationTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiConfigurationTest.java
@@ -50,6 +50,10 @@
         )
     })
     public void testWifiConfiguration() {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
         List<WifiConfiguration> wifiConfigurations = mWifiManager.getConfiguredNetworks();
         for (int i = 0; i < wifiConfigurations.size(); i++) {
             WifiConfiguration wifiConfiguration = wifiConfigurations.get(i);
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiFeature.java b/tests/tests/net/src/android/net/wifi/cts/WifiFeature.java
new file mode 100644
index 0000000..d7a83c3
--- /dev/null
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiFeature.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.cts;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+public class WifiFeature {
+    static boolean isWifiSupported(Context context) {
+        PackageManager packageManager = context.getPackageManager();
+        return packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI);
+    }
+}
+
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiInfoTest.java b/tests/tests/net/src/android/net/wifi/cts/WifiInfoTest.java
index 44189cd..2713dfd 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiInfoTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiInfoTest.java
@@ -66,6 +66,10 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
         mMySync = new MySync();
         mIntentFilter = new IntentFilter();
         mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
@@ -84,6 +88,11 @@
 
     @Override
     protected void tearDown() throws Exception {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            super.tearDown();
+            return;
+        }
         mWifiLock.release();
         mContext.unregisterReceiver(mReceiver);
         if (!mWifiManager.isWifiEnabled())
@@ -161,6 +170,10 @@
         )
     })
     public void testWifiInfoProperties() throws Exception {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
         // this test case should in Wifi environment
         WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
 
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java b/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
index e2a583b..014f0ee 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
@@ -90,6 +90,10 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
         mMySync = new MySync();
         mIntentFilter = new IntentFilter();
         mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
@@ -115,6 +119,11 @@
 
     @Override
     protected void tearDown() throws Exception {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            super.tearDown();
+            return;
+        }
         mWifiLock.release();
         mContext.unregisterReceiver(mReceiver);
         if (!mWifiManager.isWifiEnabled())
@@ -230,6 +239,10 @@
         )
     })
     public void testWifiManagerActions() throws Exception {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
         assertTrue(mWifiManager.reconnect());
         assertTrue(mWifiManager.reassociate());
         assertTrue(mWifiManager.disconnect());
@@ -278,6 +291,10 @@
         )
     })
     public void testWifiManagerProperties() throws Exception {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
         setWifiEnabled(true);
         assertTrue(mWifiManager.isWifiEnabled());
         assertNotNull(mWifiManager.getDhcpInfo());
@@ -345,6 +362,10 @@
         )
     })
     public void testWifiManagerNetWork() throws Exception {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
         // store the list of enabled networks, so they can be re-enabled after test completes
         Set<String> enabledSsids = getEnabledNetworks(mWifiManager.getConfiguredNetworks());
         try {
@@ -441,6 +462,10 @@
         )
     })
     public void testSignal() {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
         final int numLevels = 9;
         int expectLevel = 0;
         assertEquals(expectLevel, WifiManager.calculateSignalLevel(MIN_RSSI, numLevels));
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiManager_WifiLockTest.java b/tests/tests/net/src/android/net/wifi/cts/WifiManager_WifiLockTest.java
index 53150c9..c1fc4ba 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiManager_WifiLockTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiManager_WifiLockTest.java
@@ -63,6 +63,10 @@
         )
     })
     public void testWifiLock() {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
         WifiManager wm = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
         WifiLock wl = wm.createWifiLock(WIFI_TAG);
 
diff --git a/tests/tests/openglperf/Android.mk b/tests/tests/openglperf/Android.mk
new file mode 100644
index 0000000..57e6ec3
--- /dev/null
+++ b/tests/tests/openglperf/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2011 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+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_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsOpenGlPerfTestCases
+
+LOCAL_INSTRUMENTATION_FOR := com.replica.replicaisland
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/tests/tests/openglperf/AndroidManifest.xml b/tests/tests/openglperf/AndroidManifest.xml
new file mode 100644
index 0000000..e47c0bc
--- /dev/null
+++ b/tests/tests/openglperf/AndroidManifest.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.cts.openglperf"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-feature android:glEsVersion="0x00020000" android:required="true" />
+    <uses-permission android:name="android.permission.GET_TASKS" />
+    <uses-permission android:name="android.permission.REORDER_TASKS" />
+    <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
+
+    <!-- Two activities are used -->
+    <instrumentation
+        android:targetPackage="com.replica.replicaisland"
+        android:name="android.test.InstrumentationTestRunner" />
+    <instrumentation
+        android:targetPackage="com.android.cts.openglperf"
+        android:name="android.test.InstrumentationTestRunner" />
+
+    <application
+        android:label="@string/app_name" >
+        <uses-library android:name="android.test.runner" />
+        <activity
+            android:name="android.openglperf.cts.GlPlanetsActivity"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity android:name="android.openglperf.cts.TextureTestActivity" />
+    </application>
+
+</manifest>
diff --git a/tests/tests/openglperf/assets/world_512_512.jpg b/tests/tests/openglperf/assets/world_512_512.jpg
new file mode 100644
index 0000000..b92bfae
--- /dev/null
+++ b/tests/tests/openglperf/assets/world_512_512.jpg
Binary files differ
diff --git a/tests/tests/openglperf/res/values/strings.xml b/tests/tests/openglperf/res/values/strings.xml
new file mode 100644
index 0000000..2cdba7f
--- /dev/null
+++ b/tests/tests/openglperf/res/values/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources>
+    <string name="app_name">OpenGlPerfTest</string>
+</resources>
\ No newline at end of file
diff --git a/tests/tests/openglperf/src/android/openglperf/cts/GlAppSwitchTest.java b/tests/tests/openglperf/src/android/openglperf/cts/GlAppSwitchTest.java
new file mode 100644
index 0000000..aa4ca49
--- /dev/null
+++ b/tests/tests/openglperf/src/android/openglperf/cts/GlAppSwitchTest.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.openglperf.cts;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.Instrumentation;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.test.ActivityInstrumentationTestCase2;
+
+import java.util.List;
+
+/**
+ * Tests OpenGl rendering after task switching to other GL-using application
+ * This test needs to control two applications and task switch between them to
+ * force losing and reclaiming GL context
+ */
+public class GlAppSwitchTest extends
+        ActivityInstrumentationTestCase2<GlPlanetsActivity> {
+
+    private static final String REPLICA_ISLAND_PACKAGE = "com.replica.replicaisland";
+    private static final String REPLICA_ISLAND_ACTIVITY = "AndouKun";
+    private static final long TASK_SWITCH_SLOW_WAIT_TIME_MS = 15 * 1000;
+    private static final int NUMBER_OF_TASK_SWITCHES_SLOW = 10;
+    private static final long TASK_SWITCH_FAST_WAIT_TIME_MS = 2000;
+    private static final int NUMBER_OF_TASK_SWITCHES_FAST = 50;
+    private static final String ERROR_REPLICA_ISLAND_DEAD = "replica island not running";
+    private static final int MAX_RUNNING_TASKS = 1000;
+
+    private ActivityManager mActivityManager;
+
+    private int mTaskIdSelf;
+    private int mTaskIdReplica;
+
+    public GlAppSwitchTest() {
+        super(GlPlanetsActivity.class);
+    }
+
+    public void testGlActivitySwitchingFast() throws InterruptedException {
+        runTaskSwitchTest(TASK_SWITCH_FAST_WAIT_TIME_MS, NUMBER_OF_TASK_SWITCHES_FAST);
+        // wait for more time at the last run to allow watch dog timer in replica island to kick
+        Thread.sleep(TASK_SWITCH_SLOW_WAIT_TIME_MS);
+        assertTrue(ERROR_REPLICA_ISLAND_DEAD, isReplicaIslandRunning());
+    }
+
+    public void testGlActivitySwitchingSlow() throws InterruptedException {
+        runTaskSwitchTest(TASK_SWITCH_SLOW_WAIT_TIME_MS, NUMBER_OF_TASK_SWITCHES_SLOW);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        Instrumentation instrument = getInstrumentation();
+        Context context = instrument.getContext();
+
+        mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+
+        Intent intentPlanets = new Intent();
+        intentPlanets.putExtra(GlPlanetsActivity.INTENT_EXTRA_NUM_FRAMES, 0); //runs forever
+        intentPlanets.putExtra(GlPlanetsActivity.INTENT_EXTRA_NUM_PLANETS, 4); // max load
+        setActivityIntent(intentPlanets);
+        Activity activity = getActivity();
+        instrument.waitForIdleSync();
+        mTaskIdSelf = activity.getTaskId();
+        // wait further to render some frames
+        Thread.sleep(1000);
+
+        Intent intentIsland = new Intent(Intent.ACTION_MAIN);
+        intentIsland.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intentIsland.addCategory(Intent.CATEGORY_LAUNCHER);
+        intentIsland.setComponent(new ComponentName(REPLICA_ISLAND_PACKAGE,
+                REPLICA_ISLAND_PACKAGE + "." + REPLICA_ISLAND_ACTIVITY));
+        context.startActivity(intentIsland);
+        // wait to render some frames
+        Thread.sleep(5000);
+
+        setReplicaIslandTask();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        showOrHideReplicaIsland(false);
+        super.tearDown();
+    }
+
+    /**
+     * run foreground / background task switching between replica island and GlPlanetsActivity.
+     * @param waitTimeMs time to wait after each task switching
+     * @param numberOfSwitches number of task switches to run
+     * @throws InterruptedException
+     */
+    private void runTaskSwitchTest(long waitTimeMs, int numberOfSwitches)
+            throws InterruptedException {
+        boolean replicaForeground = false;
+        assertTrue(ERROR_REPLICA_ISLAND_DEAD, isReplicaIslandRunning());
+        for (int i = 0; i < numberOfSwitches; i++ ) {
+            showOrHideReplicaIsland(replicaForeground);
+            replicaForeground = !replicaForeground;
+            Thread.sleep(waitTimeMs);
+            assertTrue(ERROR_REPLICA_ISLAND_DEAD, isReplicaIslandRunning());
+        }
+    }
+
+    private void setReplicaIslandTask() {
+        boolean foundReplica = false;
+        List<ActivityManager.RunningTaskInfo> tasks =
+                mActivityManager.getRunningTasks(MAX_RUNNING_TASKS);
+        for (ActivityManager.RunningTaskInfo info : tasks) {
+            String packageName = info.baseActivity.getPackageName();
+            if (packageName.contentEquals(REPLICA_ISLAND_PACKAGE)) {
+                foundReplica = true;
+                mTaskIdReplica = info.id;
+                break;
+            }
+        }
+        assertTrue("cannot find replica island running", foundReplica);
+    }
+
+    private boolean isReplicaIslandRunning() {
+        boolean foundReplica = false;
+        List<ActivityManager.RunningTaskInfo> tasks =
+                mActivityManager.getRunningTasks(MAX_RUNNING_TASKS);
+        for (ActivityManager.RunningTaskInfo info : tasks) {
+            String packageName = info.baseActivity.getPackageName();
+            if (packageName.contentEquals(REPLICA_ISLAND_PACKAGE)) {
+                foundReplica = true;
+                break;
+            }
+        }
+        return foundReplica;
+    }
+
+    /**
+     * send replica island to foreground (when show = true) or background
+     * requires both replica island and GlPlanetsActivity to be alive.
+     * @param show
+     */
+    private void showOrHideReplicaIsland(boolean show) {
+        mActivityManager.moveTaskToFront(show ? mTaskIdReplica : mTaskIdSelf, 0);
+    }
+}
diff --git a/tests/tests/openglperf/src/android/openglperf/cts/GlPlanetsActivity.java b/tests/tests/openglperf/src/android/openglperf/cts/GlPlanetsActivity.java
new file mode 100644
index 0000000..5a8c0a8
--- /dev/null
+++ b/tests/tests/openglperf/src/android/openglperf/cts/GlPlanetsActivity.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.openglperf.cts;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.WindowManager;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Activity which runs GL test and measure FPS with given parameters passed from
+ * Intent. For the meaning of parameters, check {@PlanetsRenderingParam}
+ */
+public class GlPlanetsActivity extends Activity implements
+        RenderCompletionListener {
+    public static final String INTENT_EXTRA_NUM_PLANETS = "numPlanets";
+    public static final String INTENT_EXTRA_USE_VBO_VERTICES = "useVboVertices";
+    public static final String INTENT_EXTRA_USE_VBO_INDICES = "useVboIndiices";
+    public static final String INTENT_EXTRA_NUM_FRAMES = "numFrames";
+    public static final String INTENT_EXTRA_INDICES_PER_VERTEX = "numIndicesPerVertex";
+
+    public static final String INTENT_RESULT_FPS = "fps";
+    public static final String INTENT_RESULT_NUM_TRIANGLES = "numTrigngles";
+
+    private final Semaphore mSem = new Semaphore(0);
+    private float mFps;
+    private int mNumTriangles;
+
+    private PlanetsSurfaceView mView;
+
+    public boolean waitForGlPlanetsCompletionWithTimeout(long timeoutInSecs)
+            throws InterruptedException {
+        return mSem.tryAcquire(timeoutInSecs, TimeUnit.SECONDS);
+    }
+
+    public float getFps() {
+        return mFps;
+    }
+
+    public int getNumTriangles() {
+        return mNumTriangles;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+        Intent intent = getIntent();
+        PlanetsRenderingParam param = new PlanetsRenderingParam();
+        param.mNumPlanets = intent.getIntExtra(INTENT_EXTRA_NUM_PLANETS, param.mNumPlanets);
+        param.mUseVboForVertices = intent.getBooleanExtra(INTENT_EXTRA_USE_VBO_VERTICES,
+                param.mUseVboForVertices);
+        param.mUseVboForIndices = intent.getBooleanExtra(INTENT_EXTRA_USE_VBO_INDICES,
+                param.mUseVboForIndices);
+        param.mNumFrames = intent.getIntExtra(INTENT_EXTRA_NUM_FRAMES, param.mNumFrames);
+        param.mNumIndicesPerVertex = intent.getIntExtra(INTENT_EXTRA_INDICES_PER_VERTEX,
+                param.mNumIndicesPerVertex);
+        mView = new PlanetsSurfaceView(this, param, this);
+        setContentView(mView);
+    }
+
+    @Override
+    public void onRenderCompletion(float fps, int numTriangles) {
+        mFps = fps;
+        mNumTriangles = numTriangles;
+        mSem.release();
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        mView.onResume();
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        mView.onPause();
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/openglperf/src/android/openglperf/cts/GlTextureCoordTest.java b/tests/tests/openglperf/src/android/openglperf/cts/GlTextureCoordTest.java
new file mode 100644
index 0000000..6a0a14e
--- /dev/null
+++ b/tests/tests/openglperf/src/android/openglperf/cts/GlTextureCoordTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.openglperf.cts;
+
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+
+/**
+ * check TextureTestRenderer for details
+ */
+public class GlTextureCoordTest extends
+        ActivityInstrumentationTestCase2<TextureTestActivity> {
+
+    public GlTextureCoordTest() {
+        super(TextureTestActivity.class);
+    }
+
+    public void testTextureCoord() throws InterruptedException {
+        getActivity();
+        Thread.sleep(3000); // give some time to render some frames
+    }
+}
diff --git a/tests/tests/openglperf/src/android/openglperf/cts/GlVboPerfTest.java b/tests/tests/openglperf/src/android/openglperf/cts/GlVboPerfTest.java
new file mode 100644
index 0000000..afd435c
--- /dev/null
+++ b/tests/tests/openglperf/src/android/openglperf/cts/GlVboPerfTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.openglperf.cts;
+
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+
+public class GlVboPerfTest extends
+        ActivityInstrumentationTestCase2<GlPlanetsActivity> {
+    private static final String TAG = "GlVboPerfTest";
+    private static final int NUM_FRAMES_TO_RENDER = 100;
+    private static final long RENDERING_TIMEOUT = 5 * 60;
+    // 10% of fps_no_vbo is allowed to compensate variations in measurement
+    private static final float FPS_COMPARISON_MARGIN = 0.1f;
+    // the worst case should be above 70% of the best case
+    private static final float FPS_MIN_MAX_COMPARISON_PERCENTILE = 0.7f;
+
+    private float mFps;
+    private int mNumTriangles;
+
+    public GlVboPerfTest() {
+        super(GlPlanetsActivity.class);
+    }
+
+    public void testVboWithVaryingIndexBufferNumbers() throws Exception {
+        final int[] numIndexBuffers = {1, 10, 100, 200, 400}; // per vertex buffer
+        float[] fpsVbo = new float[numIndexBuffers.length];
+        float[] fpsNonVbo = new float[numIndexBuffers.length];
+
+        for (int i = 0; i < numIndexBuffers.length; i++) {
+            runRendering(0, true, true, numIndexBuffers[i]);
+            fpsVbo[i] = mFps;
+            runRendering(0, true, false, numIndexBuffers[i]);
+            fpsNonVbo[i] = mFps;
+        }
+        StringBuilder msgIndex = new StringBuilder();
+        StringBuilder msgVbo = new StringBuilder();
+        StringBuilder msgNonVbo = new StringBuilder();
+        msgIndex.append("index buffer ");
+        msgVbo.append("Vbo ");
+        msgNonVbo.append("Non-Vbo ");
+        for (int i = 0; i < numIndexBuffers.length; i++) {
+            msgIndex.append(numIndexBuffers[i]).append(" ");
+            msgVbo.append(fpsVbo[i]).append(" ");
+            msgNonVbo.append(fpsNonVbo[i]).append(" ");
+        }
+        Log.i(TAG, msgIndex.toString());
+        Log.i(TAG, msgVbo.toString());
+        Log.i(TAG, msgNonVbo.toString());
+
+        float[] minMaxVbo = findMinMax(fpsVbo);
+        float[] minMaxNonVbo = findMinMax(fpsNonVbo);
+
+        float delta = minMaxVbo[1] - (1f - FPS_COMPARISON_MARGIN)
+                * minMaxNonVbo[1];
+        assertTrue("VBO performance worse than non-VBO " + msgVbo + msgNonVbo, delta > 0f);
+        assertTrue(
+                "Too much FPS drop for VBO case " + msgVbo,
+                minMaxVbo[0] > (FPS_MIN_MAX_COMPARISON_PERCENTILE * minMaxVbo[1]));
+        assertTrue(
+                "Too much FPS drop for No VBO case " + msgNonVbo,
+                minMaxNonVbo[0] > (FPS_MIN_MAX_COMPARISON_PERCENTILE * minMaxNonVbo[1]));
+    }
+
+    public void testVboVsNonVboPerfGeometry0() throws Exception {
+        doRunVboVsNonVboPerfTest(0);
+    }
+
+    public void testVboVsNonVboPerfGeometry1() throws Exception {
+        doRunVboVsNonVboPerfTest(4);
+    }
+
+    private void runRendering(int numPlanets, boolean useVboVertex, boolean useVboIndex,
+            int indicesPerVertex) throws Exception {
+        Intent intent = new Intent();
+        intent.putExtra(GlPlanetsActivity.INTENT_EXTRA_NUM_FRAMES,
+                NUM_FRAMES_TO_RENDER);
+        intent.putExtra(GlPlanetsActivity.INTENT_EXTRA_NUM_PLANETS, numPlanets);
+        intent.putExtra(GlPlanetsActivity.INTENT_EXTRA_USE_VBO_VERTICES, useVboVertex);
+        intent.putExtra(GlPlanetsActivity.INTENT_EXTRA_USE_VBO_INDICES, useVboIndex);
+        intent.putExtra(GlPlanetsActivity.INTENT_EXTRA_INDICES_PER_VERTEX, indicesPerVertex);
+
+        setActivityIntent(intent);
+        final GlPlanetsActivity activity = getActivity();
+        boolean waitResult = activity
+                .waitForGlPlanetsCompletionWithTimeout(RENDERING_TIMEOUT);
+        assertTrue("timeout while waiting for rendering completion", waitResult);
+
+        mFps = activity.getFps();
+        mNumTriangles = activity.getNumTriangles();
+
+        cleanUpActivity();
+    }
+
+    private void cleanUpActivity()  throws Exception {
+        // finish the current activity and do clean-up so that a new activity
+        // can be launched in the same test run
+        super.tearDown();
+        super.setUp();
+        // wait until clean-up / set-up finishes
+        getInstrumentation().waitForIdleSync();
+    }
+
+    private void doRunVboVsNonVboPerfTest(int numPlanets) throws Exception {
+        runRendering(numPlanets, true, true, 1); // VBO
+        int numTrianglesVbo = mNumTriangles;
+        float fpsVbo = mFps;
+        runRendering(numPlanets, false, false, 1); // non-VBO
+
+        assertTrue("Number of triangles mismatch",
+                numTrianglesVbo == mNumTriangles);
+
+        // Margin amount of error is allowed due to measuring irregularity
+        float delta = fpsVbo - (1f - FPS_COMPARISON_MARGIN) * mFps;
+        StringBuilder testMsg = new StringBuilder();
+        testMsg.append("VBO performance worse than non-VBO ").append(fpsVbo).append(" ");
+        testMsg.append(mFps);
+        assertTrue(testMsg.toString(), delta > 0f);
+    }
+
+    private float[] findMinMax(float[] data) {
+        float min = data[0];
+        float max = data[0];
+
+        for (int i = 1; i < data.length; i++) {
+            if (data[i] > max) max = data[i];
+            if (data[i] < min) min = data[i];
+        }
+        float[] result = {min, max};
+        return result;
+    }
+}
diff --git a/tests/tests/openglperf/src/android/openglperf/cts/PlanetsRenderer.java b/tests/tests/openglperf/src/android/openglperf/cts/PlanetsRenderer.java
new file mode 100644
index 0000000..5b90089
--- /dev/null
+++ b/tests/tests/openglperf/src/android/openglperf/cts/PlanetsRenderer.java
@@ -0,0 +1,429 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.openglperf.cts;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+import android.opengl.GLUtils;
+import android.opengl.Matrix;
+import android.util.Log;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.System;
+import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+
+public class PlanetsRenderer implements GLSurfaceView.Renderer {
+
+    private static final String TAG = "PlanetsRenderer";
+    // texture is from
+    // http://en.wikipedia.org/wiki/File:Mercator_projection_SW.jpg
+    private static final String TEXTURE_FILE = "world_512_512.jpg";
+
+    private final Context mContext;
+    private final PlanetsRenderingParam mParam;
+    private final RenderCompletionListener mListener;
+    private final RenderingWatchDog mWatchDog;
+
+    private final Sphere[] mSpheres;
+    private final int mNumSpheres;
+    private final int mNumIndices;
+    private final int mVboVertices[];
+    private final int mVboIndices[];
+
+    // configurations for sun and planets
+    private static final int SPHERE_SLICES = 180;
+    private static final float RADIUS_SUN = 0.4f;
+    private static final float RADIUS_PLANET = 0.08f;
+    private static final float RADIUS_ORBIT = 0.9f;
+
+    private int mWidth;
+    private int mHeight;
+
+    private int mFrameCount = 0;
+    private static final int FPS_DISPLAY_INTERVAL = 50;
+    private long mLastFPSTime;
+    // for total FPS measurement
+    private long mRenderingStartTime;
+    private long mMeasurementStartTime;
+
+    private int mProgram; // shader program
+    private int mMVPMatrixHandle;
+    private float[] mMVPMatrix = new float[16];
+    private float[] mMMatrix = new float[16];
+    private float[] mVMatrix = new float[16];
+    private float[] mProjMatrix = new float[16];
+
+    private int mOffsetHandle;
+    private static final float[] mDefaultOffset = { 0f, 0f, 0f, 1f };
+    private int mPositionHandle;
+    private int mTexCoord0Handle;
+    private int mTextureHandle;
+    private int mTextureId;
+
+    /**
+     * @param numSlices
+     *            complexity of sphere used. A sphere will have (numSlices + 1)
+     *            x (numSlices x 1) much of vertices
+     * @param useVbo
+     *            whether to use Vertex Buffer Object in rendering or not
+     * @param framesToGo
+     *            number of frames to render before calling completion to
+     *            listener
+     * @param listener
+     */
+    public PlanetsRenderer(Context context, PlanetsRenderingParam param,
+            RenderCompletionListener listener, RenderingWatchDog watchDog) {
+        resetTimer();
+        mContext = context;
+        mParam = param;
+        mWatchDog = watchDog;
+        mNumSpheres = mParam.mNumPlanets + 1; // 1 for sun
+        mNumIndices = mNumSpheres * mParam.mNumIndicesPerVertex;
+        mSpheres = new Sphere[mNumSpheres];
+
+        printParams();
+
+        // for big model, this construction phase takes time...
+        mSpheres[0] = new Sphere(SPHERE_SLICES, 0f, 0f, 0f, RADIUS_SUN,
+                mParam.mNumIndicesPerVertex);
+        for (int i = 1; i < mNumSpheres; i++) {
+            mSpheres[i] = new Sphere(SPHERE_SLICES,
+                    RADIUS_ORBIT * (float) Math.sin(((float) i) / (mNumSpheres - 1) * 2 * Math.PI),
+                    RADIUS_ORBIT * (float) Math.cos(((float) i) / (mNumSpheres - 1) * 2 * Math.PI),
+                    0f, RADIUS_PLANET, mParam.mNumIndicesPerVertex);
+        }
+        mVboVertices = new int[mNumSpheres];
+        mVboIndices = new int[mNumIndices];
+        mListener = listener;
+        measureTime("construction");
+    }
+
+    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
+        mProgram = createProgram(getVertexShader(), getFragmentShader());
+        if (mProgram == 0) {
+            // error, cannot proceed
+            throw new IllegalStateException("createProgram failed");
+        }
+        mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
+        mOffsetHandle = GLES20.glGetUniformLocation(mProgram, "uOffset");
+        mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
+        mTexCoord0Handle = GLES20.glGetAttribLocation(mProgram, "vTexCoord0");
+        mTextureHandle = GLES20.glGetUniformLocation(mProgram, "sTexture");
+
+        // Load the texture
+        mTextureId = createTexture2D();
+    }
+
+    public void onDrawFrame(GL10 glUnused) {
+        mWatchDog.reset();
+        long currentTime = System.currentTimeMillis();
+
+        mFrameCount++;
+        if ((mFrameCount % FPS_DISPLAY_INTERVAL == 0) && (mFrameCount != 0)) {
+            float fps = (((float) FPS_DISPLAY_INTERVAL)
+                    / ((float) (currentTime - mLastFPSTime)) * 1000.0f);
+            // FPS is not correct if activity is paused/resumed.
+            Log.i(TAG, "FPS " + fps);
+            mLastFPSTime = currentTime;
+        }
+
+        if ((mFrameCount == mParam.mNumFrames) && (mParam.mNumFrames > 0)) {
+            long timePassed = currentTime - mRenderingStartTime;
+            float fps = ((float) mParam.mNumFrames) / ((float) timePassed) * 1000.0f;
+            printGlInfos();
+            printParams();
+            int numTriangles = mNumSpheres * mSpheres[0].getTotalIndices() / 3;
+            Log.i(TAG, "Final FPS " + fps + " Num triangles " + numTriangles);
+            if (mListener != null) {
+                mListener.onRenderCompletion(fps, numTriangles);
+                return;
+            }
+        }
+
+        float angle = 0.090f * ((int) (currentTime % 4000L));
+        Matrix.setRotateM(mMMatrix, 0, angle, 0, 0, 1.0f);
+        Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0);
+        Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
+
+        GLES20.glUseProgram(mProgram);
+        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+        GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+
+        // Apply a ModelView Projection transformation
+        GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
+        GLES20.glUniform4f(mOffsetHandle, mDefaultOffset[0], mDefaultOffset[1],
+                mDefaultOffset[2], mDefaultOffset[3]);
+
+        GLES20.glEnableVertexAttribArray(mPositionHandle);
+        GLES20.glEnableVertexAttribArray(mTexCoord0Handle);
+
+        // Bind the texture
+        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
+        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureId);
+        // Set the sampler texture unit to 0
+        GLES20.glUniform1i(mTextureHandle, 0);
+
+        for (int i = 0; i < mNumSpheres; i++) {
+            if (mParam.mUseVboForVertices) {
+                // generating VBOs for each sphere is not efficient way for drawing
+                // multiple spheres
+                // But this is done for testing performance with big VBO buffers.
+                // So please do not copy this code as it is.
+                GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVboVertices[i]);
+                // Load the vertex position
+                GLES20.glVertexAttribPointer(mPositionHandle, 3,
+                        GLES20.GL_FLOAT, false, mSpheres[i].getVeticesStride(),
+                        0);
+                // Load the texture coordinate
+                GLES20.glVertexAttribPointer(mTexCoord0Handle, 3,
+                        GLES20.GL_FLOAT, false, mSpheres[i].getVeticesStride(),
+                        3 * Sphere.FLOAT_SIZE);
+            } else {
+                // Load the vertex position
+                GLES20.glVertexAttribPointer(mPositionHandle, 3,
+                        GLES20.GL_FLOAT, false, mSpheres[i].getVeticesStride(),
+                        mSpheres[i].getVertices());
+                // Load the texture coordinate
+                GLES20.glVertexAttribPointer(mTexCoord0Handle, 3,
+                        GLES20.GL_FLOAT, false, mSpheres[i].getVeticesStride(),
+                        mSpheres[i].getVertices().duplicate().position(3));
+            }
+            int[] numIndices = mSpheres[i].getNumIndices();
+            ShortBuffer[] indices = mSpheres[i].getIndices();
+            if (mParam.mUseVboForIndices) {
+                int indexVboBase = i * mParam.mNumIndicesPerVertex;
+                for (int j = 0; j < numIndices.length; j++) {
+                    GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER,
+                            mVboIndices[indexVboBase + j]);
+                    GLES20.glDrawElements(GLES20.GL_TRIANGLES,
+                            numIndices[j], GLES20.GL_UNSIGNED_SHORT,
+                            0);
+                }
+            } else {
+                for (int j = 0; j < numIndices.length; j++) {
+                    GLES20.glDrawElements(GLES20.GL_TRIANGLES,
+                            numIndices[j], GLES20.GL_UNSIGNED_SHORT,
+                            indices[j]);
+                }
+            }
+        }
+    }
+
+    public void onSurfaceChanged(GL10 glUnused, int width, int height) {
+        mWidth = width;
+        mHeight = height;
+        GLES20.glViewport(0, 0, width, height);
+        float ratio = (float) width / height;
+        Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
+        Matrix.setLookAtM(mVMatrix, 0, 0, 3, 3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
+
+        createVbo();
+
+        // reset timer to remove delays added for FPS calculation.
+        mLastFPSTime = System.currentTimeMillis();
+        mRenderingStartTime = System.currentTimeMillis();
+    }
+
+    protected final String getVertexShader() {
+        // simple shader with MVP matrix and text coord
+        final String vShaderStr =
+                  "uniform mat4 uMVPMatrix;                               \n"
+                + "uniform vec4 uOffset;                                  \n"
+                + "attribute vec4 vPosition;                              \n"
+                + "attribute vec2 vTexCoord0;                             \n"
+                + "varying vec2 vTexCoord;                                \n"
+                + "void main()                                            \n"
+                + "{                                                      \n"
+                + "   gl_Position = uMVPMatrix * (vPosition + uOffset);   \n"
+                + "   vTexCoord = vTexCoord0;                             \n"
+                + "}                                                      \n";
+        return vShaderStr;
+    }
+
+    protected final String getFragmentShader() {
+        // simple shader with one texture for color
+        final String fShaderStr =
+                  "precision mediump float;                          \n"
+                + "varying vec2 vTexCoord;                           \n"
+                + "uniform sampler2D sTexture;                       \n"
+                + "void main()                                       \n"
+                + "{                                                 \n"
+                + "  gl_FragColor = texture2D( sTexture, vTexCoord );\n"
+                + "}                                                 \n";
+        return fShaderStr;
+    }
+
+    private int loadShader(int shaderType, String source) {
+        int shader = GLES20.glCreateShader(shaderType);
+        if (shader != 0) {
+            GLES20.glShaderSource(shader, source);
+            GLES20.glCompileShader(shader);
+            int[] compiled = new int[1];
+            GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
+            if (compiled[0] == 0) {
+                Log.e(TAG, "Could not compile shader " + shaderType + ":");
+                Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
+                GLES20.glDeleteShader(shader);
+                shader = 0;
+            }
+        }
+        return shader;
+    }
+
+    private int createProgram(String vertexSource, String fragmentSource) {
+        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
+        if (vertexShader == 0) {
+            return 0;
+        }
+
+        int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
+        if (pixelShader == 0) {
+            return 0;
+        }
+
+        int program = GLES20.glCreateProgram();
+        if (program != 0) {
+            GLES20.glAttachShader(program, vertexShader);
+            checkGlError("glAttachShader");
+            GLES20.glAttachShader(program, pixelShader);
+            checkGlError("glAttachShader");
+            GLES20.glLinkProgram(program);
+            int[] linkStatus = new int[1];
+            GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
+            if (linkStatus[0] != GLES20.GL_TRUE) {
+                Log.e(TAG, "Could not link program: ");
+                Log.e(TAG, GLES20.glGetProgramInfoLog(program));
+                GLES20.glDeleteProgram(program);
+                program = 0;
+            }
+        }
+        return program;
+    }
+
+    private int createTexture2D() {
+        // Texture object handle
+        int[] textureId = new int[1];
+
+        InputStream in = null;
+        try {
+            in = mContext.getAssets().open(TEXTURE_FILE);
+            Bitmap bitmap = BitmapFactory.decodeStream(in);
+
+            // Generate a texture object
+            GLES20.glGenTextures(1, textureId, 0);
+
+            // Bind the texture object
+            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId[0]);
+            GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
+
+            // Set the filtering mode
+            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
+                    GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
+            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
+                    GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
+
+        } catch (IOException e) {
+            throw new IllegalStateException("Couldn't load texture '" + TEXTURE_FILE
+                    + "'", e);
+        } finally {
+            if (in != null)
+                try {
+                    in.close();
+                } catch (IOException e) {
+                }
+        }
+
+        return textureId[0];
+    }
+
+    private void checkGlError(String op) {
+        int error;
+        while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
+            Log.e(TAG, op + ": glError " + error);
+            throw new IllegalStateException(op + ": glError " + error);
+        }
+    }
+
+    private void createVbo() {
+        resetTimer();
+        if (mParam.mUseVboForVertices) {
+            GLES20.glGenBuffers(mNumSpheres, mVboVertices, 0);
+            checkGlError("glGenBuffers Vertex");
+            for (int i = 0; i < mNumSpheres; i++) {
+                GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVboVertices[i]);
+                checkGlError("glBindBuffer Vertex");
+                FloatBuffer vertices = mSpheres[i].getVertices();
+                GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertices.limit()
+                        * Sphere.FLOAT_SIZE, vertices, GLES20.GL_STATIC_DRAW);
+                checkGlError("glBufferData Vertex");
+            }
+        }
+        if (mParam.mUseVboForIndices) {
+            GLES20.glGenBuffers(mNumIndices, mVboIndices, 0);
+            checkGlError("glGenBuffers Index");
+            for (int i = 0; i < mNumSpheres; i++) {
+                int[] numIndices = mSpheres[i].getNumIndices();
+                ShortBuffer[] indices = mSpheres[i].getIndices();
+                int indexVboBase = i * mParam.mNumIndicesPerVertex;
+                for (int j = 0; j < numIndices.length; j++) {
+                    GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER,
+                            mVboIndices[indexVboBase + j]);
+                    GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER,
+                            indices[j].limit() * Sphere.SHORT_SIZE, indices[j],
+                            GLES20.GL_STATIC_DRAW);
+                    checkGlError("glBufferData Index");
+
+                }
+            }
+        }
+        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
+        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
+        measureTime("VBO creation");
+    }
+
+    private void resetTimer() {
+        mMeasurementStartTime = System.currentTimeMillis();
+    }
+
+    private void measureTime(String description) {
+        long currentTime = System.currentTimeMillis();
+        float timePassedInSecs = (float) (currentTime - mMeasurementStartTime) / 1000f;
+        Log.i(TAG, description + " time in secs: " + timePassedInSecs);
+    }
+
+    private void printGlInfos() {
+        Log.i(TAG, "Vendor " + GLES20.glGetString(GLES20.GL_VENDOR));
+        Log.i(TAG, "Version " + GLES20.glGetString(GLES20.GL_VERSION));
+        Log.i(TAG, "Renderer " + GLES20.glGetString(GLES20.GL_RENDERER));
+        Log.i(TAG, "Extensions " + GLES20.glGetString(GLES20.GL_EXTENSIONS));
+    }
+    private void printParams() {
+        Log.i(TAG, "UseVboForVertex " + mParam.mUseVboForVertices);
+        Log.i(TAG, "UseVboForIndex " + mParam.mUseVboForIndices);
+        Log.i(TAG, "No Spheres " + mNumSpheres);
+        Log.i(TAG, "No indices buffer per vertex " + mParam.mNumIndicesPerVertex);
+    }
+}
diff --git a/tests/tests/openglperf/src/android/openglperf/cts/PlanetsRenderingParam.java b/tests/tests/openglperf/src/android/openglperf/cts/PlanetsRenderingParam.java
new file mode 100644
index 0000000..5e2dfd0
--- /dev/null
+++ b/tests/tests/openglperf/src/android/openglperf/cts/PlanetsRenderingParam.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.openglperf.cts;
+
+public class PlanetsRenderingParam {
+    /** whether to use VBO for vertices data */
+    public boolean mUseVboForVertices = true;
+    /** whether to use VBO for indices data */
+    public boolean mUseVboForIndices = true;
+    /** number of indices buffer per one vertices buffer */
+    public int mNumIndicesPerVertex = 1;
+    /** number of planets to render. There is always a sun */
+    public int mNumPlanets = 0;
+    /** number of frames to render to calculate FPS and finish */
+    public int mNumFrames = 100;
+}
diff --git a/tests/tests/openglperf/src/android/openglperf/cts/PlanetsSurfaceView.java b/tests/tests/openglperf/src/android/openglperf/cts/PlanetsSurfaceView.java
new file mode 100644
index 0000000..2bfd001
--- /dev/null
+++ b/tests/tests/openglperf/src/android/openglperf/cts/PlanetsSurfaceView.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.openglperf.cts;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+
+class PlanetsSurfaceView extends GLSurfaceView {
+    private final long RENDERING_TIMEOUT = 1900; // in msec, close to 2 secs
+    private final RenderingWatchDog mWatchDog = new RenderingWatchDog(RENDERING_TIMEOUT);
+
+    public PlanetsSurfaceView(Context context, PlanetsRenderingParam param,
+            RenderCompletionListener listener) {
+        super(context);
+
+        setEGLContextClientVersion(2);
+        setRenderer(new PlanetsRenderer(context, param, listener, mWatchDog));
+    }
+
+    @Override
+    public void onPause() {
+        mWatchDog.stop();
+        super.onPause();
+        setRenderMode(RENDERMODE_WHEN_DIRTY);
+    }
+
+    @Override
+    public void onResume() {
+        mWatchDog.start();
+        setRenderMode(RENDERMODE_CONTINUOUSLY);
+        super.onResume();
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/openglperf/src/android/openglperf/cts/RenderCompletionListener.java b/tests/tests/openglperf/src/android/openglperf/cts/RenderCompletionListener.java
new file mode 100644
index 0000000..1643087
--- /dev/null
+++ b/tests/tests/openglperf/src/android/openglperf/cts/RenderCompletionListener.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.openglperf.cts;
+
+public interface RenderCompletionListener {
+    /**
+     * @param fps total frame rate
+     * @param numTriangles Number of triangles in geometric model
+     */
+    void onRenderCompletion(float fps, int numTriangles);
+
+}
diff --git a/tests/tests/openglperf/src/android/openglperf/cts/RenderingWatchDog.java b/tests/tests/openglperf/src/android/openglperf/cts/RenderingWatchDog.java
new file mode 100644
index 0000000..4872af2
--- /dev/null
+++ b/tests/tests/openglperf/src/android/openglperf/cts/RenderingWatchDog.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.openglperf.cts;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import android.util.Log;
+
+import junit.framework.Assert;
+
+/**
+ * class for checking if rendering function is alive or not.
+ * panic if watch-dog is not reset over certain amount of time
+ */
+public class RenderingWatchDog implements Runnable {
+    private static final String TAG = "RenderingWatchDog";
+    private Thread mThread;
+    private Semaphore mSemaphore;
+    private volatile boolean mStopRequested;
+    private final long mTimeoutInMilliSecs;
+
+    public RenderingWatchDog(long timeoutInMilliSecs) {
+        mTimeoutInMilliSecs = timeoutInMilliSecs;
+    }
+
+    /** start watch-dog */
+    public void start() {
+        Log.i(TAG, "start");
+        mStopRequested = false;
+        mSemaphore = new Semaphore(0);
+        mThread = new Thread(this);
+        mThread.start();
+    }
+
+    /** stop watch-dog */
+    public void stop() {
+        Log.i(TAG, "stop");
+        if (mThread == null) {
+            return; // already finished
+        }
+        mStopRequested = true;
+        mSemaphore.release();
+        try {
+            mThread.join();
+        } catch (InterruptedException e) {
+            // ignore
+        }
+        mThread = null;
+        mSemaphore = null;
+    }
+
+    /** resets watch-dog, thus prevent it from panic */
+    public void reset() {
+        if (!mStopRequested) { // stop requested, but rendering still on-going
+            mSemaphore.release();
+        }
+    }
+
+    @Override
+    public void run() {
+        while (!mStopRequested) {
+            try {
+                Assert.assertTrue("Watchdog timed-out",
+                        mSemaphore.tryAcquire(mTimeoutInMilliSecs, TimeUnit.MILLISECONDS));
+            } catch (InterruptedException e) {
+                // this thread will not be interrupted,
+                // but if it happens, just check the exit condition.
+            }
+        }
+    }
+}
diff --git a/tests/tests/openglperf/src/android/openglperf/cts/Sphere.java b/tests/tests/openglperf/src/android/openglperf/cts/Sphere.java
new file mode 100644
index 0000000..026ba97
--- /dev/null
+++ b/tests/tests/openglperf/src/android/openglperf/cts/Sphere.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.openglperf.cts;
+
+import java.lang.Math;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
+
+/*
+ * Class for generating a sphere model for given input params
+ * The generated class will have vertices and indices
+ * Vertices data is composed of vertex coordinates in x, y, z followed by
+ *  texture coordinates s, t for each vertex
+ * Indices store vertex indices for the whole sphere.
+ * Formula for generating sphere is originally coming from source code of
+ * OpenGL ES2.0 Programming guide
+ * which is available from http://code.google.com/p/opengles-book-samples/,
+ * but some changes were made to make texture look right.
+ */
+public class Sphere {
+    public static final int FLOAT_SIZE = 4;
+    public static final int SHORT_SIZE = 2;
+
+    private FloatBuffer mVertices;
+    private ShortBuffer[] mIndices;
+    private int[] mNumIndices;
+    private int mTotalIndices;
+
+    /*
+     * @param nSlices how many slice in horizontal direction.
+     *                The same slice for vertical direction is applied.
+     *                nSlices should be > 1 and should be <= 180
+     * @param x,y,z the origin of the sphere
+     * @param r the radius of the sphere
+     */
+    public Sphere(int nSlices, float x, float y, float z, float r, int indicesPerVertex) {
+
+        int iMax = nSlices + 1;
+        int nVertices = iMax * iMax;
+        if (nVertices > Short.MAX_VALUE) {
+            // this cannot be handled in one vertices / indices pair
+            throw new RuntimeException("nSlices " + nSlices + " too big for vertex");
+        }
+        mTotalIndices = nSlices * nSlices * 6;
+        float angleStepI = ((float) Math.PI / nSlices);
+        float angleStepJ = ((2.0f * (float) Math.PI) / nSlices);
+
+        // 3 vertex coords + 2 texture coords
+        mVertices = ByteBuffer.allocateDirect(nVertices * 5 * FLOAT_SIZE)
+                .order(ByteOrder.nativeOrder()).asFloatBuffer();
+        mIndices = new ShortBuffer[indicesPerVertex];
+        mNumIndices = new int[indicesPerVertex];
+        // first evenly distribute to n-1 buffers, then put remaining ones to the last one.
+        int noIndicesPerBuffer = (mTotalIndices / indicesPerVertex / 6) * 6;
+        for (int i = 0; i < indicesPerVertex - 1; i++) {
+            mNumIndices[i] = noIndicesPerBuffer;
+        }
+        mNumIndices[indicesPerVertex - 1] = mTotalIndices - noIndicesPerBuffer *
+                (indicesPerVertex - 1);
+
+        for (int i = 0; i < indicesPerVertex; i++) {
+            mIndices[i] = ByteBuffer.allocateDirect(mNumIndices[i] * SHORT_SIZE)
+                    .order(ByteOrder.nativeOrder()).asShortBuffer();
+        }
+        // calling put for each float took too much CPU time, so put by line instead
+        float[] vLineBuffer = new float[iMax * 5];
+        for (int i = 0; i < iMax; i++) {
+            for (int j = 0; j < iMax; j++) {
+                int vertexBase = j * 5;
+                float sini = (float) Math.sin(angleStepI * i);
+                float sinj = (float) Math.sin(angleStepJ * j);
+                float cosi = (float) Math.cos(angleStepI * i);
+                float cosj = (float) Math.cos(angleStepJ * j);
+                // vertex x,y,z
+                vLineBuffer[vertexBase + 0] = x + r * sini * sinj;
+                vLineBuffer[vertexBase + 1] = y + r * sini * cosj;
+                vLineBuffer[vertexBase + 2] = z + r * cosi;
+                // texture s,t
+                vLineBuffer[vertexBase + 3] = (float) j / (float) nSlices;
+                vLineBuffer[vertexBase + 4] = (1.0f - i) / (float)nSlices;
+            }
+            mVertices.put(vLineBuffer, 0, vLineBuffer.length);
+        }
+
+        short[] indexBuffer = new short[max(mNumIndices)];
+        int index = 0;
+        int bufferNum = 0;
+        for (int i = 0; i < nSlices; i++) {
+            for (int j = 0; j < nSlices; j++) {
+                int i1 = i + 1;
+                int j1 = j + 1;
+                if (index >= mNumIndices[bufferNum]) {
+                    // buffer ready for moving to target
+                    mIndices[bufferNum].put(indexBuffer, 0, mNumIndices[bufferNum]);
+                    // move to the next one
+                    index = 0;
+                    bufferNum++;
+                }
+                indexBuffer[index++] = (short) (i * iMax + j);
+                indexBuffer[index++] = (short) (i1 * iMax + j);
+                indexBuffer[index++] = (short) (i1 * iMax + j1);
+                indexBuffer[index++] = (short) (i * iMax + j);
+                indexBuffer[index++] = (short) (i1 * iMax + j1);
+                indexBuffer[index++] = (short) (i * iMax + j1);
+            }
+        }
+        mIndices[bufferNum].put(indexBuffer, 0, mNumIndices[bufferNum]);
+
+        mVertices.position(0);
+        for (int i = 0; i < indicesPerVertex; i++) {
+            mIndices[i].position(0);
+        }
+    }
+
+    public FloatBuffer getVertices() {
+        return mVertices;
+    }
+
+    public int getVeticesStride() {
+        return 5*FLOAT_SIZE;
+    }
+
+    public ShortBuffer[] getIndices() {
+        return mIndices;
+    }
+
+    public int[] getNumIndices() {
+        return mNumIndices;
+    }
+
+    public int getTotalIndices() {
+        return mTotalIndices;
+    }
+
+
+    private int max(int[] array) {
+        int max = array[0];
+        for (int i = 1; i < array.length; i++) {
+            if (array[i] > max) max = array[i];
+        }
+        return max;
+    }
+}
diff --git a/tests/tests/openglperf/src/android/openglperf/cts/TextureTestActivity.java b/tests/tests/openglperf/src/android/openglperf/cts/TextureTestActivity.java
new file mode 100644
index 0000000..4d7d641
--- /dev/null
+++ b/tests/tests/openglperf/src/android/openglperf/cts/TextureTestActivity.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.openglperf.cts;
+
+import android.app.Activity;
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+
+public class TextureTestActivity extends Activity {
+    private GLSurfaceView mGLView;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mGLView = new TextureTestSurfaceView(this);
+        setContentView(mGLView);
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        mGLView.onPause();
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        mGLView.onResume();
+    }
+}
+
+class TextureTestSurfaceView extends GLSurfaceView {
+
+    public TextureTestSurfaceView(Context context){
+        super(context);
+        setRenderer(new TextureTestRenderer());
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/openglperf/src/android/openglperf/cts/TextureTestRenderer.java b/tests/tests/openglperf/src/android/openglperf/cts/TextureTestRenderer.java
new file mode 100644
index 0000000..96b2e44
--- /dev/null
+++ b/tests/tests/openglperf/src/android/openglperf/cts/TextureTestRenderer.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.openglperf.cts;
+
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.opengl.GLSurfaceView;
+import android.opengl.GLU;
+import android.opengl.GLUtils;
+import android.util.Log;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+import javax.microedition.khronos.opengles.GL11;
+import javax.microedition.khronos.opengles.GL11Ext;
+
+import junit.framework.Assert;
+
+/**
+ * This test is for checking an issue
+ * mentioned in https://groups.google.com/group/android-developers/browse_thread/thread/
+ * 9c0ccb1a215586a8/2f28259213340eab?hl=en&lnk=gst&q=opengl+galaxy#2f28259213340eab
+ * The GPU driver seems to change texture coordinates inside glDrawTexfOES, and
+ * texture inside following drawing does not work as expected.
+ * The thread also mentions texture malfunctioning with rotation,
+ * but that was not observed, but the case will cover both.
+ */
+public class TextureTestRenderer implements GLSurfaceView.Renderer {
+    private static final String TAG = "TextureTest";
+    private static final float[] mVerticesData = {
+        // X, Y, Z, s, t
+        -1.0f, -1.0f, 0, 0.6f, 0.f,
+        1.0f, -1.0f, 0, 0.7f, 0.f,
+        -1.0f,  1.0f, 0, 0.6f, 0.1f,
+        1.0f,   1.0f, 0, 0.7f, 0.1f,
+    };
+    private static final int FLOAT_SIZE_BYTES = 4;
+    private static final int GEOMETRY_STRIDE = 20;
+
+    private final FloatBuffer mVertices;
+    private final Bitmap mBitmap;
+    private int mTextureID;
+    private boolean mOesDrawTextureSupported = false;
+    private int mWidth;
+    private int mHeight;
+    private float mRotationAngle = 0f;
+
+    public TextureTestRenderer() {
+        mVertices = ByteBuffer.allocateDirect(mVerticesData.length
+                * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
+        mVertices.put(mVerticesData).position(0);
+        // 4x4 texture with 4 colors
+        int[] colors = {
+                Color.RED, Color.RED, Color.BLUE, Color.BLUE,
+                Color.RED, Color.RED, Color.BLUE, Color.BLUE,
+                Color.GREEN, Color.GREEN, Color.CYAN, Color.CYAN,
+                Color.GREEN, Color.GREEN, Color.CYAN, Color.CYAN
+        };
+        mBitmap = Bitmap.createBitmap(colors, 4, 4, Bitmap.Config.ARGB_8888);
+    }
+
+    public void onDrawFrame(GL10 gl) {
+        // Redraw background color
+        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+
+        gl.glTexEnvx(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
+                GL10.GL_REPLACE);
+
+        // Set GL_MODELVIEW transformation mode
+        gl.glMatrixMode(GL10.GL_MODELVIEW);
+        gl.glLoadIdentity(); // reset the matrix to its default state
+
+        // When using GL_MODELVIEW, you must set the view point
+        GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
+
+        gl.glActiveTexture(GL10.GL_TEXTURE0);
+        gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
+        gl.glEnable(GL10.GL_TEXTURE_2D);
+
+        // red for default color
+        gl.glColor4f(1.0f, 0f, 0f, 1.0f);
+        gl.glVertexPointer(3, GL10.GL_FLOAT, GEOMETRY_STRIDE, mVertices);
+        gl.glTexCoordPointer(2, GL10.GL_FLOAT, GEOMETRY_STRIDE, mVertices
+                .duplicate().position(3));
+        if (mOesDrawTextureSupported) {
+            // left / bottom / width / height (negative w/h flip the image)
+            int crop[] = new int[] { 0, 0, 4, 4 };
+
+            ((GL11) gl).glTexParameteriv(GL10.GL_TEXTURE_2D,
+                    GL11Ext.GL_TEXTURE_CROP_RECT_OES, crop, 0);
+            // 4x4 drawing in left-bottom corner
+            ((GL11Ext) gl).glDrawTexfOES(0, 0, 0, 4, 4);
+        }
+        gl.glPushMatrix();
+        gl.glRotatef(mRotationAngle, 0f, 0f, 1f);
+        mRotationAngle += 10f;
+        if (mRotationAngle > 360f) {
+            mRotationAngle = 0f;
+        }
+        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
+        gl.glPopMatrix();
+        // for one pixel
+        IntBuffer pixel = ByteBuffer.allocateDirect(4).asIntBuffer();
+        gl.glReadPixels(mWidth / 2, mHeight / 2, 1, 1, GL10.GL_RGBA,
+                GL10.GL_UNSIGNED_BYTE, pixel);
+        pixel.position(0);
+        Log.i(TAG, "pixel read " + Integer.toHexString(pixel.get(0)));
+
+        Assert.assertEquals(0x0000ffff, pixel.get(0)); // BLUE in RGBA
+
+        checkGlError(gl, "onDrawFrame");
+    }
+
+    public void onSurfaceChanged(GL10 gl, int width, int height) {
+        mWidth = width;
+        mHeight = height;
+        gl.glViewport(0, 0, width, height);
+
+        // make adjustments for screen ratio
+        float ratio = (float) width / height;
+        gl.glMatrixMode(GL10.GL_PROJECTION); // set matrix to projection mode
+        gl.glLoadIdentity(); // reset the matrix to its default state
+        gl.glFrustumf(-2 * ratio, 2 * ratio, -2, 2, 3, 7);
+        checkGlError(gl, "onSurfaceChanged");
+    }
+
+    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+        String extensions = gl.glGetString(GL10.GL_EXTENSIONS);
+        Log.i(TAG, "extensions: " + extensions);
+        if (extensions.contains("GL_OES_draw_texture")) {
+            mOesDrawTextureSupported = true;
+        }
+        // Set the background frame color
+        gl.glClearColor(0f, 0f, 0f, 1.0f);
+        gl.glEnable(GL10.GL_TEXTURE_2D);
+
+        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
+        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
+
+        int[] textures = new int[1];
+        gl.glGenTextures(1, textures, 0);
+
+        mTextureID = textures[0];
+        gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
+
+        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
+                GL10.GL_NEAREST);
+        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
+                GL10.GL_NEAREST); // necessary due to low resolution texture
+
+        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
+                GL10.GL_CLAMP_TO_EDGE);
+        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
+                GL10.GL_CLAMP_TO_EDGE);
+        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, mBitmap, 0);
+        checkGlError(gl, "onSurfaceCreated");
+    }
+
+    private void checkGlError(GL10 gl, String op) {
+        int error;
+        while ((error = gl.glGetError()) != GL10.GL_NO_ERROR) {
+            Log.e(TAG, op + ": glError " + error);
+            throw new IllegalStateException(op + ": glError " + error);
+        }
+    }
+}
diff --git a/tests/tests/os/src/android/os/cts/BuildVersionTest.java b/tests/tests/os/src/android/os/cts/BuildVersionTest.java
index a317dce..6cb09bb 100644
--- a/tests/tests/os/src/android/os/cts/BuildVersionTest.java
+++ b/tests/tests/os/src/android/os/cts/BuildVersionTest.java
@@ -29,7 +29,7 @@
 
     private static final String LOG_TAG = "BuildVersionTest";
     private static final Set<String> EXPECTED_RELEASES =
-            new HashSet<String>(Arrays.asList("4.0.3"));
+            new HashSet<String>(Arrays.asList("4.0.3", "4.0.4"));
     private static final int EXPECTED_SDK = 15;
 
     @SuppressWarnings("deprecation")
diff --git a/tests/tests/os/src/android/os/cts/EnvironmentTest.java b/tests/tests/os/src/android/os/cts/EnvironmentTest.java
index 2081cba..711306e 100644
--- a/tests/tests/os/src/android/os/cts/EnvironmentTest.java
+++ b/tests/tests/os/src/android/os/cts/EnvironmentTest.java
@@ -70,4 +70,15 @@
         assertTrue(Environment.getDownloadCacheDirectory().isDirectory());
         assertTrue(Environment.getDataDirectory().isDirectory());
     }
+
+    /**
+     * TMPDIR being set prevents apps from asking to have temporary files
+     * placed in their own storage, instead forcing their location to
+     * something OS-defined. If TMPDIR points to a global shared directory,
+     * this could compromise the security of the files.
+     */
+    public void testNoTmpDir() {
+        assertNull("environment variable TMPDIR should not be set",
+                System.getenv("TMPDIR"));
+    }
 }
diff --git a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
index 2e3bbdb..4b86fbb 100644
--- a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
@@ -187,18 +187,26 @@
     private static final Set<String> OTHER_RANDOM_DIRECTORIES = new HashSet<String>(
             Arrays.asList(
                     "/app-cache/ciq/socket",
+                    "/cache/fotapkg",
+                    "/cache/fotapkg/tmp",
+                    "/data/amit",
                     "/data/anr",
                     "/data/app",
                     "/data/app-private",
                     "/data/backup",
+                    "/data/battd",
+                    "/data/bootlogo",
                     "/data/btips",
                     "/data/btips/TI",
                     "/data/btips/TI/opp",
+                    "/data/calibration",
+                    "/data/clp",
                     "/data/dalvik-cache",
                     "/data/data/.drm",
                     "/data/data/.drm/.wmdrm",
                     "/data/data/cw",
                     "/data/data/com.android.htcprofile",
+                    "/data/data/com.android.providers.drm/rights",
                     "/data/data/com.htc.android.qxdm2sd",
                     "/data/data/com.htc.android.qxdm2sd/bin",
                     "/data/data/com.htc.android.qxdm2sd/data",
@@ -211,13 +219,29 @@
                     "/data/data/com.htc.loggers/htclog",
                     "/data/data/com.htc.loggers/tmp",
                     "/data/data/com.htc.loggers/htcghost",
-                    "/data/data/com.android.providers.drm/rights",
+                    "/data/data/com.lge.ers/android",
+                    "/data/data/com.lge.ers/arm9",
+                    "/data/data/com.lge.ers/kernel",
+                    "/data/data/recovery",
                     "/data/dontpanic",
                     "/data/drm",
                     "/data/drm/rights",
                     "/data/dump",
+                    "/data/fota",
+                    "/data/emt",
+                    "/data/gpscfg",
+                    "/data/hwvefs",
                     "/data/htcfs",
+                    "/data/internal-device",
+                    "/data/internal-device/DCIM",
                     "/data/local",
+                    "/data/local/logs",
+                    "/data/local/logs/kernel",
+                    "/data/local/logs/logcat",
+                    "/data/local/logs/resetlog",
+                    "/data/local/logs/smem",
+                    "/data/local/rwsystag",
+                    "/data/local/tmp",
                     "/data/local/tmp/com.nuance.android.vsuite.vsuiteapp",
                     "/data/log",
                     "/data/lost+found",
@@ -226,13 +250,29 @@
                     "/data/misc/dhcp",
                     "/data/misc/wifi",
                     "/data/misc/wifi/sockets",
+                    "/data/misc/wpa_supplicant",
+                    "/data/nvcam",
+                    "/data/panicreports",
                     "/data/property",
+                    "/data/radio",
                     "/data/secure",
+                    "/data/sensors",
                     "/data/shared",
+                    "/data/simcom",
+                    "/data/simcom/btadd",
+                    "/data/simcom/simlog",
                     "/data/system",
+                    "/data/tombstones",
+                    "/data/tpapi",
+                    "/data/tpapi/etc",
+                    "/data/tpapi/etc/tpa",
+                    "/data/tpapi/etc/tpa/persistent",
+                    "/data/tpapi/user.bin",
+                    "/data/wapi",
                     "/data/wifi",
                     "/data/wiper",
                     "/data/wpstiles",
+                    "/data/xt9",
                     "/dbdata/databases",
                     "/efs/.android",
                     "/mnt_ext",
@@ -240,7 +280,13 @@
                     "/mnt_ext/badablk3",
                     "/mnt_ext/cache",
                     "/mnt_ext/data",
-                    "/system/etc/security/drm"
+                    "/system/etc/dhcpcd/dhcpcd-run-hooks",
+                    "/system/etc/security/drm",
+                    "/synthesis/hades",
+                    "/synthesis/chimaira",
+                    "/synthesis/shdisp",
+                    "/synthesis/hdmi",
+                    "/tmp"
             )
     );
 
diff --git a/tests/tests/permission2/AndroidManifest.xml b/tests/tests/permission2/AndroidManifest.xml
index e8d3a3a..8f77fad 100755
--- a/tests/tests/permission2/AndroidManifest.xml
+++ b/tests/tests/permission2/AndroidManifest.xml
@@ -39,6 +39,8 @@
     <!--  need app that has CALL_PHONE but not PROCESS_OUTGOING_CALL -->
     <uses-permission android:name="android.permission.CALL_PHONE"/>
 
+    <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
+
     <instrumentation android:name="android.test.InstrumentationTestRunner"
                      android:targetPackage="com.android.cts.permission2"
                      android:label="More CTS tests for permissions"/>
diff --git a/tests/tests/permission2/src/android/permission2/cts/ReadSocialStreamPermissionTest.java b/tests/tests/permission2/src/android/permission2/cts/ReadSocialStreamPermissionTest.java
new file mode 100644
index 0000000..eaf6fdf
--- /dev/null
+++ b/tests/tests/permission2/src/android/permission2/cts/ReadSocialStreamPermissionTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.permission2.cts;
+
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.net.Uri;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.RawContacts;
+import android.provider.ContactsContract.StreamItems;
+import android.test.AndroidTestCase;
+
+public class ReadSocialStreamPermissionTest extends AndroidTestCase {
+
+    private ContentResolver mResolver;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mResolver = mContext.getContentResolver();
+    }
+
+    public void testReadSocialStreamPermission_byRawContactId() throws Exception {
+        try {
+            mResolver.query(Uri.withAppendedPath(
+                    ContentUris.withAppendedId(RawContacts.CONTENT_URI, 1337),
+                    Contacts.StreamItems.CONTENT_DIRECTORY), null, null, null, null);
+            fail("Expected a READ_SOCIAL_STREAM exception");
+        } catch (SecurityException e) {
+            // Expect a READ_SOCIAL_STREAM exception.
+        }
+    }
+
+    public void testReadSocialStreamPermission_byContactId() throws Exception {
+        try {
+            mResolver.query(Uri.withAppendedPath(
+                    ContentUris.withAppendedId(Contacts.CONTENT_URI, 1337),
+                    Contacts.StreamItems.CONTENT_DIRECTORY), null, null, null, null);
+            fail("Expected a READ_SOCIAL_STREAM exception");
+        } catch (SecurityException e) {
+            // Expect a READ_SOCIAL_STREAM exception.
+        }
+    }
+
+    public void testReadSocialStreamPermission_byLookUpKey() throws Exception {
+        try {
+            mResolver.query(Contacts.CONTENT_LOOKUP_URI.buildUpon()
+                    .appendPath("lookDownKey")
+                    .appendPath(Contacts.StreamItems.CONTENT_DIRECTORY)
+                    .build(), null, null, null, null);
+            fail("Expected a READ_SOCIAL_STREAM exception");
+        } catch (SecurityException e) {
+            // Expect a READ_SOCIAL_STREAM exception.
+        }
+    }
+
+    public void testReadSocialStreamPermission_byStreamItemId() throws Exception {
+        try {
+            mResolver.query(ContentUris.withAppendedId(StreamItems.CONTENT_URI, 1337),
+                    null, null, null, null);
+            fail("Expected a READ_SOCIAL_STREAM exception");
+        } catch (SecurityException e) {
+            // Expect a READ_SOCIAL_STREAM exception.
+        }
+    }
+}
diff --git a/tests/tests/permission2/src/android/permission2/cts/WriteSocialStreamPermissionTest.java b/tests/tests/permission2/src/android/permission2/cts/WriteSocialStreamPermissionTest.java
new file mode 100644
index 0000000..262fcfa
--- /dev/null
+++ b/tests/tests/permission2/src/android/permission2/cts/WriteSocialStreamPermissionTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.permission2.cts;
+
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.net.Uri;
+import android.provider.ContactsContract.RawContacts;
+import android.provider.ContactsContract.StreamItems;
+import android.test.AndroidTestCase;
+
+public class WriteSocialStreamPermissionTest extends AndroidTestCase {
+
+    private ContentResolver mResolver;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mResolver = mContext.getContentResolver();
+    }
+
+    public void testWriteSocialStreamPermission_byContentDirectory() throws Exception {
+        try {
+            ContentValues values = new ContentValues();
+            mResolver.insert(Uri.withAppendedPath(
+                    ContentUris.withAppendedId(RawContacts.CONTENT_URI, 1337),
+                    RawContacts.StreamItems.CONTENT_DIRECTORY), values);
+            fail("Expected a WRITE_SOCIAL_STREAM exception");
+        } catch (SecurityException e) {
+            // Expect a WRITE_SOCIAL_STREAM exception.
+        }
+    }
+
+    public void testWriteSocialStreamPermission_byContentUri() throws Exception {
+        try {
+            ContentValues values = new ContentValues();
+            mResolver.insert(StreamItems.CONTENT_URI, values);
+            fail("Expected a WRITE_SOCIAL_STREAM exception");
+        } catch (SecurityException e) {
+            // Expect a WRITE_SOCIAL_STREAM exception.
+        }
+    }
+}
diff --git a/tests/tests/preference2/Android.mk b/tests/tests/preference2/Android.mk
new file mode 100644
index 0000000..4b7b2e5
--- /dev/null
+++ b/tests/tests/preference2/Android.mk
@@ -0,0 +1,31 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsPreference2TestCases
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/tests/tests/preference2/AndroidManifest.xml b/tests/tests/preference2/AndroidManifest.xml
new file mode 100644
index 0000000..5043e1f
--- /dev/null
+++ b/tests/tests/preference2/AndroidManifest.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.cts.preference2">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+        <activity
+            android:name="android.preference2.cts.PreferenceFragmentActivity" >
+        </activity>
+        <activity
+            android:name="android.preference2.cts.PreferenceStubActivity" >
+        </activity>
+        <activity
+            android:name="android.preference2.cts.PreferenceFromCodeActivity" >
+        </activity>
+        <activity android:name="android.preference2.cts.PreferencesFromXml" />
+        <activity android:name="android.preference2.cts.PreferenceWithHeaders" />
+    </application>
+
+    <!-- This is a self-instrumenting test package. -->
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+                     android:targetPackage="com.android.cts.preference2"
+                     android:label="CTS Test Cases for android.preference"/>
+
+</manifest>
+
diff --git a/tests/tests/preference2/res/drawable-hdpi/ic_launcher.png b/tests/tests/preference2/res/drawable-hdpi/ic_launcher.png
new file mode 100755
index 0000000..8074c4c
--- /dev/null
+++ b/tests/tests/preference2/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/tests/tests/preference2/res/drawable-ldpi/ic_launcher.png b/tests/tests/preference2/res/drawable-ldpi/ic_launcher.png
new file mode 100755
index 0000000..1095584
--- /dev/null
+++ b/tests/tests/preference2/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/tests/tests/preference2/res/drawable-mdpi/ic_launcher.png b/tests/tests/preference2/res/drawable-mdpi/ic_launcher.png
new file mode 100755
index 0000000..a07c69f
--- /dev/null
+++ b/tests/tests/preference2/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/tests/tests/preference2/res/drawable-mdpi/ic_settings_applications.png b/tests/tests/preference2/res/drawable-mdpi/ic_settings_applications.png
new file mode 100755
index 0000000..745ff2a
--- /dev/null
+++ b/tests/tests/preference2/res/drawable-mdpi/ic_settings_applications.png
Binary files differ
diff --git a/tests/tests/preference2/res/drawable-mdpi/ic_settings_display.png b/tests/tests/preference2/res/drawable-mdpi/ic_settings_display.png
new file mode 100755
index 0000000..85af393
--- /dev/null
+++ b/tests/tests/preference2/res/drawable-mdpi/ic_settings_display.png
Binary files differ
diff --git a/tests/tests/preference2/res/layout/main.xml b/tests/tests/preference2/res/layout/main.xml
new file mode 100755
index 0000000..a6b7f10
--- /dev/null
+++ b/tests/tests/preference2/res/layout/main.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical" >
+
+    <TextView
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        />
+
+</LinearLayout>
diff --git a/tests/tests/preference2/res/values/arrays.xml b/tests/tests/preference2/res/values/arrays.xml
new file mode 100755
index 0000000..198d989
--- /dev/null
+++ b/tests/tests/preference2/res/values/arrays.xml
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources>
+    <!-- Used in View/Spinner1.java -->
+    <string-array name="colors">
+        <item>red</item>
+        <item>orange</item>
+        <item>yellow</item>
+        <item>green</item>
+        <item>blue</item>
+        <item>violet</item>
+    </string-array>
+
+    <!-- Used in View/Spinner1.java -->
+    <string-array name="planets">
+        <item>Mercury</item>
+        <item>Venus</item>
+        <item>Earth</item>
+        <item>Mars</item>
+        <item>Jupiter</item>
+        <item>Saturn</item>
+        <item>Uranus</item>
+        <item>Neptune</item>
+        <item>Pluto</item>
+    </string-array>
+
+    <!-- Used in content/ClipboardSample.java -->
+    <string-array name="clip_data_types">
+        <item>No data in clipboard</item>
+        <item>Text clip</item>
+        <item>Intent clip</item>
+        <item>Uri clip</item>
+    </string-array>
+
+    <!-- Used in App/SearchInvoke.java -->
+    <string-array name="search_menuModes">
+        <item>Search Key</item>
+        <item>Menu Item</item>
+        <item>Type-To-Search</item>
+        <item>Disabled</item>
+    </string-array>
+
+    <!-- Used in app/dialog examples -->
+    <string-array name="select_dialog_items">
+        <item>Command one</item>
+        <item>Command two</item>
+        <item>Command three</item>
+        <item>Command four</item>
+    </string-array>
+
+    <string-array name="select_dialog_items2">
+        <item>Map</item>
+        <item>Satellite</item>
+        <item>Traffic</item>
+        <item>Street view</item>
+    </string-array>
+
+    <string-array name="select_dialog_items3">
+        <item>Every Monday</item>
+        <item>Every Tuesday</item>
+        <item>Every Wednesday</item>
+        <item>Every Thursday</item>
+        <item>Every Friday</item>
+        <item>Every Saturday</item>
+        <item>Every Sunday</item>
+    </string-array>
+
+    <!-- Used in app/menu examples -->
+    <string-array name="entries_list_preference">
+        <item>Alpha Option 01</item>
+        <item>Beta Option 02</item>
+        <item>Charlie Option 03</item>
+    </string-array>
+
+    <!-- Used in app/menu examples -->
+    <string-array name="entryvalues_list_preference">
+        <item>alpha</item>
+        <item>beta</item>
+        <item>charlie</item>
+    </string-array>
+
+    <!-- Used in app/Sample Device Admin -->
+    <string-array name="password_qualities">
+        <item>Unspecified</item>
+        <item>Something</item>
+        <item>Numeric</item>
+        <item>Alphabetic</item>
+        <item>Alphanumeric</item>
+        <item>Complex</item>
+    </string-array>
+
+    <!-- Used in app/Screen Orientation -->
+    <string-array name="screen_orientations">
+        <item>UNSPECIFIED</item>
+        <item>LANDSCAPE</item>
+        <item>PORTRAIT</item>
+        <item>USER</item>
+        <item>BEHIND</item>
+        <item>SENSOR</item>
+        <item>NOSENSOR</item>
+        <item>SENSOR_LANDSCAPE</item>
+        <item>SENSOR_PORTRAIT</item>
+        <item>REVERSE_LANDSCAPE</item>
+        <item>REVERSE_PORTRAIT</item>
+        <item>FULL_SENSOR</item>
+    </string-array>
+
+    <!-- Used in view/Secure View examples -->
+    <string-array name="secure_view_clicked">
+        <item>*bzzt*\nTransferred $1,000,000 to J. Phisher.  Thank you!</item>
+        <item>*bzzt*\nSending all life savings to the International Cabal of Evil Penguins.</item>
+        <item>*bzzt*\nOpening portal to R\'lyeh.  Long live Cthulhu!</item>
+        <item>*bzzt*\nYou\'re not very good at this, are you?</item>
+        <item>*bzzt*\nGo away...</item>
+    </string-array>
+
+    <!-- Used in view/Split Touch View example -->
+    <string-array name="cheese_responses">
+        <item>I\'m afraid we\'re fresh out.</item>
+        <item>I\'m afraid we never have that at the end of the week, sir.  We get it fresh on Monday.
+        </item>
+        <item>Ah. It\'s been on order, sir, for two weeks.  I was expecting it this morning.</item>
+        <item>Normally, sir, yes.  Today the van broke down.</item>
+        <item>No.</item>
+        <item>No.</item>
+        <item>No.</item>
+        <item>Yes, sir.  It\'s, ah ..... it\'s a bit runny.</item>
+        <item>Well, it\'s very runny, actually, sir.</item>
+        <item>I think it\'s a bit runnier than you\'ll like it, sir.</item>
+        <item>Oh... The cat\'s eaten it.</item>
+        <item>No.</item>
+        <item>No.</item>
+        <item>No.</item>
+        <item>Mmm... cheese.</item>
+    </string-array>
+</resources>
diff --git a/tests/tests/preference2/res/values/attrs.xml b/tests/tests/preference2/res/values/attrs.xml
new file mode 100755
index 0000000..e80e204
--- /dev/null
+++ b/tests/tests/preference2/res/values/attrs.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>

+<!-- Copyright (C) 2012 The Android Open Source Project

+

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

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

+     You may obtain a copy of the License at

+

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

+

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

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

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

+     See the License for the specific language governing permissions and

+     limitations under the License.

+-->

+<resources>

+     <declare-styleable name="CustPref">

+        <attr name="icon" format="integer"/>

+        <attr name="title" format="string"/>

+    </declare-styleable>

+</resources>

diff --git a/tests/tests/preference2/res/values/colors.xml b/tests/tests/preference2/res/values/colors.xml
new file mode 100755
index 0000000..bfcd0b4
--- /dev/null
+++ b/tests/tests/preference2/res/values/colors.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>

+<!-- Copyright (C) 2012 The Android Open Source Project

+

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

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

+     You may obtain a copy of the License at

+

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

+

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

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

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

+     See the License for the specific language governing permissions and

+     limitations under the License.

+-->

+<resources>

+    <color name="white">#FFFFFF</color>

+    <color name="android_orange">#FF9E18</color>

+    <color name="android_yellow">#F2E406</color>

+    <color name="black">#000000</color>

+    <color name="red">#FF0000</color>

+</resources>

diff --git a/tests/tests/preference2/res/values/strings.xml b/tests/tests/preference2/res/values/strings.xml
new file mode 100755
index 0000000..d43d3eb
--- /dev/null
+++ b/tests/tests/preference2/res/values/strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources>
+    <string name="app_name">CtsPreferenceTestCases</string>
+    <string name="test_prefs">Test Preferences</string>
+
+    <string name="preferences_from_xml">Preference/1. Preferences from XML</string>
+    <string name="launching_preferences">Preference/2. Launching preferences</string>
+    <string name="preference_dependencies">Preference/3. Preference dependencies</string>
+    <string name="default_values">Preference/4. Default values</string>
+    <string name="preferences_from_code">Preference/5. Preferences from code</string>
+    <string name="advanced_preferences">Preference/6. Advanced preferences</string>
+    <string name="fragment_preferences">Preference/7. Fragment</string>
+    <string name="preference_with_headers">Preference/8. Headers</string>
+
+    <string name="launch_preference_activity">Launch PreferenceActivity</string>
+    <string name="counter_value_is">The counter value is</string>
+
+    <string name="inline_preferences">In-line preferences</string>
+    <string name="dialog_based_preferences">Dialog-based preferences</string>
+    <string name="launch_preferences">Launch preferences</string>
+    <string name="preference_attributes">Preference attributes</string>
+
+    <string name="title_checkbox_preference">Checkbox preference</string>
+    <string name="summary_checkbox_preference">This is a checkbox</string>
+    <string name="summary_on_checkbox_preference">Checkbox preference On</string>
+    <string name="summary_off_checkbox_preference">Checkbox preference Off</string>
+
+    <string name="title_switch_preference">Switch preference</string>
+    <string name="summary_switch_preference">This is a switch</string>
+    <string name="summary_on_switch_preference">Switch Summary On</string>
+    <string name="summary_off_switch_preference">Switch Summary Off</string>
+     <string name="switchtext_on">Switch Text On</string>
+    <string name="switchtext_off">Switch Text Off</string>
+
+    <string name="summary_switch_preference_yes_no">This is a switch with custom text</string>
+
+    <string name="title_yesno_preference">Yes or no preference</string>
+    <string name="summary_yesno_preference">An example that uses a yes/no dialog</string>
+    <string name="dialog_title_yesno_preference">Do you like bananas?</string>
+
+    <string name="title_edittext_preference">Edit text preference</string>
+    <string name="summary_edittext_preference">An example that uses an edit text dialog</string>
+    <string name="dialog_title_edittext_preference">Enter your favorite animal</string>
+
+    <string name="title_list_preference">List preference</string>
+    <string name="summary_list_preference">An example that uses a list dialog</string>
+    <string name="dialog_title_list_preference">Choose one</string>
+
+    <string name="title_screen_preference">Screen preference</string>
+    <string name="summary_screen_preference">Shows another screen of preferences</string>
+
+    <string name="title_fragment_preference">Fragment preference</string>
+    <string name="summary_fragment_preference">Shows another fragment of preferences</string>
+
+    <string name="title_next_screen_toggle_preference">Toggle preference</string>
+    <string name="summary_next_screen_toggle_preference">
+    Preference that is on the next screen but same hierarchy</string>
+
+    <string name="title_intent_preference">Intent preference</string>
+    <string name="summary_intent_preference">Launches an Activity from an Intent</string>
+
+    <string name="title_my_preference">My preference</string>
+    <string name="summary_my_preference">This is a custom counter preference</string>
+
+    <string name="title_advanced_toggle_preference">Haunted preference</string>
+    <string name="summary_on_advanced_toggle_preference">I\'m on! :)</string>
+    <string name="summary_off_advanced_toggle_preference">I\'m off! :(</string>
+
+    <string name="title_parent_preference">Parent checkbox preference</string>
+    <string name="summary_parent_preference">This is visually a parent</string>
+    <string name="title_child_preference">Child checkbox preference</string>
+    <string name="summary_child_preference">This is visually a child</string>
+
+    <string name="example_preference_dependency">Example preference dependency</string>
+    <string name="title_wifi">WiFi</string>
+    <string name="title_wifi_settings">WiFi settings</string>
+
+    <string name="default_value_list_preference">beta</string>
+    <string name="default_value_edittext_preference">Default value</string>
+    <string name="text_edittext_preference">Edit Text</string>
+    <string name="preset_title">Preset Title</string>
+    <string name="dialog_message">"Dialog Message"</string>
+    
+    <string name="title_dialog_preference">Dialog preference</string>
+    <string name="dialogtitle_dialog_preference">Dialog Title</string>
+    <string name="summary_dialog_preference">An example that uses a dialog</string>
+    <string name="positive_button_text">"Accept"</string>
+    <string name="negative_button_text">"Decline"</string>
+
+    <string name="cust_title_dialog_preference">Custom Dialog preference</string>
+    <string name="cust_dialogtitle_dialog_preference">Custom Dialog Title</string>
+</resources>
diff --git a/tests/tests/preference2/res/xml/fragmented_preferences.xml b/tests/tests/preference2/res/xml/fragmented_preferences.xml
new file mode 100755
index 0000000..24537b4
--- /dev/null
+++ b/tests/tests/preference2/res/xml/fragmented_preferences.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- This is a primitive example showing the different types of preferences available. -->
+<PreferenceScreen
+        xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <PreferenceCategory
+            android:title="@string/inline_preferences">
+
+        <CheckBoxPreference
+                android:key="checkbox_preference"
+                android:title="@string/title_checkbox_preference"
+                android:summary="@string/summary_checkbox_preference" />
+
+        <SwitchPreference
+                android:key="checkbox_preference"
+                android:title="@string/title_switch_preference"
+                android:summary="@string/summary_switch_preference" />
+
+    </PreferenceCategory>
+
+    <PreferenceCategory
+            android:title="@string/dialog_based_preferences">
+
+        <EditTextPreference
+                android:key="edittext_preference"
+                android:title="@string/title_edittext_preference"
+                android:summary="@string/summary_edittext_preference"
+                android:dialogTitle="@string/dialog_title_edittext_preference" />
+
+        <ListPreference
+                android:key="list_preference"
+                android:title="@string/title_list_preference"
+                android:summary="@string/summary_list_preference"
+                android:entries="@array/entries_list_preference"
+                android:entryValues="@array/entryvalues_list_preference"
+                android:dialogTitle="@string/dialog_title_list_preference" />
+
+    </PreferenceCategory>
+
+    <PreferenceCategory
+            android:title="@string/launch_preferences">
+
+        <!-- This PreferenceScreen tag sends the user to a new fragment of
+             preferences.  If running in a large screen, they can be embedded
+             inside of the overall preferences UI. -->
+        <PreferenceScreen
+                android:fragment="
+                    com.example.android.apis.preference.PreferenceWithHeaders$Prefs1FragmentInner"
+                android:title="@string/title_fragment_preference"
+                android:summary="@string/summary_fragment_preference">
+            <!-- Arbitrary key/value pairs can be included for fragment arguments -->
+            <extra android:name="someKey" android:value="somePrefValue" />
+        </PreferenceScreen>
+
+        <!-- This PreferenceScreen tag sends the user to a completely different
+             activity, switching out of the current preferences UI. -->
+        <PreferenceScreen
+                android:title="@string/title_intent_preference"
+                android:summary="@string/summary_intent_preference">
+
+            <intent android:action="android.intent.action.VIEW"
+                    android:data="http://www.android.com" />
+
+        </PreferenceScreen>
+
+    </PreferenceCategory>
+
+    <PreferenceCategory
+            android:title="@string/preference_attributes">
+
+        <CheckBoxPreference
+                android:key="parent_checkbox_preference"
+                android:title="@string/title_parent_preference"
+                android:summary="@string/summary_parent_preference" />
+
+        <!-- The visual style of a child is defined by this styled theme attribute. -->
+        <CheckBoxPreference
+                android:key="child_checkbox_preference"
+                android:dependency="parent_checkbox_preference"
+                android:layout="?android:attr/preferenceLayoutChild"
+                android:title="@string/title_child_preference"
+                android:summary="@string/summary_child_preference" />
+
+    </PreferenceCategory>
+
+</PreferenceScreen>
+
diff --git a/tests/tests/preference2/res/xml/fragmented_preferences_inner.xml b/tests/tests/preference2/res/xml/fragmented_preferences_inner.xml
new file mode 100755
index 0000000..fe235db
--- /dev/null
+++ b/tests/tests/preference2/res/xml/fragmented_preferences_inner.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<PreferenceScreen
+        xmlns:android="http://schemas.android.com/apk/res/android">
+    <CheckBoxPreference
+            android:key="next_screen_checkbox_preference"
+            android:title="@string/title_next_screen_toggle_preference"
+            android:summary="@string/summary_next_screen_toggle_preference" />
+</PreferenceScreen>
+
diff --git a/tests/tests/preference2/res/xml/pref_cb.xml b/tests/tests/preference2/res/xml/pref_cb.xml
new file mode 100755
index 0000000..b5f77b9
--- /dev/null
+++ b/tests/tests/preference2/res/xml/pref_cb.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2012 The Android Open Source Project

+

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

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

+     You may obtain a copy of the License at

+

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

+

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

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

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

+     See the License for the specific language governing permissions and

+     limitations under the License.

+-->

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

+    xmlns:in="http://schemas.android.com/apk/res/com.android.cts.preference2" >

+

+    <PreferenceCategory android:title="@string/inline_preferences" >

+        <android.preference2.cts.CustomCheckBoxPreference

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

+            style="?android:attr/buttonStyleSmall"

+            android:layout_width="wrap_content"

+            android:layout_height="wrap_content"

+            android:layout_marginTop="25dp"

+            android:key="custom_checkbox_pref_1"

+            in:icon="@drawable/ic_launcher"

+            in:title="@string/preset_title" />

+        <android.preference2.cts.CustomSwitchPreference

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

+            style="?android:attr/buttonStyleSmall"

+            android:layout_width="wrap_content"

+            android:layout_height="wrap_content"

+            android:layout_marginTop="25dp"

+            android:key="custom_switch_pref_1"

+            in:icon="@drawable/ic_launcher"

+            in:title="@string/preset_title" />

+

+         <android.preference2.cts.CustomDialogPreference

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

+            style="?android:attr/buttonStyleSmall"

+            android:layout_width="wrap_content"

+            android:layout_height="wrap_content"

+            android:layout_marginTop="25dp"

+            android:key="custom_dialog_pref_1"

+            in:icon="@drawable/ic_launcher"

+            in:title="@string/preset_title" />

+

+         <android.preference2.cts.CustomEditTextPreference

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

+            style="?android:attr/buttonStyleSmall"

+            android:layout_width="wrap_content"

+            android:layout_height="wrap_content"

+            android:layout_marginTop="25dp"

+            android:key="custom_edittext_pref_1"

+            in:icon="@drawable/ic_launcher"

+            in:title="@string/preset_title" />

+    </PreferenceCategory>

+</PreferenceScreen>

diff --git a/tests/tests/preference2/res/xml/preference_dependencies.xml b/tests/tests/preference2/res/xml/preference_dependencies.xml
new file mode 100755
index 0000000..405cad6
--- /dev/null
+++ b/tests/tests/preference2/res/xml/preference_dependencies.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<PreferenceScreen
+        xmlns:android="http://schemas.android.com/apk/res/android">
+    <PreferenceCategory
+            android:title="@string/example_preference_dependency">
+        <CheckBoxPreference
+                android:key="wifi"
+                android:title="@string/title_wifi" />
+        <EditTextPreference
+                android:layout="?android:attr/preferenceLayoutChild"
+                android:title="@string/title_wifi_settings"
+                android:dependency="wifi" />
+    </PreferenceCategory>
+</PreferenceScreen>
diff --git a/tests/tests/preference2/res/xml/preference_headers.xml b/tests/tests/preference2/res/xml/preference_headers.xml
new file mode 100755
index 0000000..2465f7a
--- /dev/null
+++ b/tests/tests/preference2/res/xml/preference_headers.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<preference-headers
+        xmlns:android="http://schemas.android.com/apk/res/android">
+        
+    <header android:fragment="android.preference2.cts.PreferenceWithHeaders$PrefsOneFragment"
+            android:icon="@drawable/ic_settings_applications"
+            android:title="Prefs 1"
+            android:summary="An example of some preferences." />
+
+    <header android:icon="@drawable/ic_settings_display"
+            android:title="Intent"
+            android:summary="Launches an Intent.">
+        <intent android:action="android.intent.action.VIEW"
+                android:data="http://www.android.com" />
+    </header>
+
+</preference-headers>
diff --git a/tests/tests/preference2/res/xml/preferences.xml b/tests/tests/preference2/res/xml/preferences.xml
new file mode 100755
index 0000000..fa35107
--- /dev/null
+++ b/tests/tests/preference2/res/xml/preferences.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- This is a primitive example showing the different types of preferences available. -->
+
+<PreferenceScreen
+        xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <PreferenceCategory
+            android:title="@string/inline_preferences">
+ 
+        <CheckBoxPreference android:id="@+id/checkbox1"
+                android:key="checkbox_preference"
+                android:title="@string/title_checkbox_preference"
+                android:summary="@string/summary_checkbox_preference" />
+
+        <SwitchPreference
+                android:key="checkbox_preference"
+                android:title="@string/title_switch_preference"
+                android:summary="@string/summary_switch_preference" />
+
+        <SwitchPreference
+                android:key="checkbox_preference"
+                android:title="@string/title_switch_preference"
+                android:summary="@string/summary_switch_preference_yes_no"
+                android:switchTextOn = "YES"
+                android:switchTextOff = "NO" />
+    </PreferenceCategory>
+
+    <PreferenceCategory
+            android:title="@string/dialog_based_preferences">
+
+        <EditTextPreference
+                android:key="edittext_preference"
+                android:title="@string/title_edittext_preference"
+                android:summary="@string/summary_edittext_preference"
+                android:dialogTitle="@string/dialog_title_edittext_preference" />
+        <ListPreference
+                android:key="list_preference"
+                android:title="@string/title_list_preference"
+                android:summary="@string/summary_list_preference"
+                android:entries="@array/entries_list_preference"
+                android:entryValues="@array/entryvalues_list_preference"
+                android:dialogTitle="@string/dialog_title_list_preference" />
+
+    </PreferenceCategory>
+
+    <PreferenceCategory
+            android:title="@string/launch_preferences">
+
+        <!-- This PreferenceScreen tag serves as a screen break (similar to page break
+             in word processing). Like for other preference types, we assign a key
+             here so it is able to save and restore its instance state. -->
+        <PreferenceScreen
+                android:key="screen_preference"
+                android:title="@string/title_screen_preference"
+                android:summary="@string/summary_screen_preference">
+
+            <!-- You can place more preferences here that will be shown on the next screen. -->
+
+            <CheckBoxPreference
+                    android:key="next_screen_checkbox_preference"
+                    android:title="@string/title_next_screen_toggle_preference"
+                    android:summary="@string/summary_next_screen_toggle_preference" />
+
+        </PreferenceScreen>
+
+        <PreferenceScreen
+                android:title="@string/title_intent_preference"
+                android:summary="@string/summary_intent_preference">
+
+            <intent android:action="android.intent.action.VIEW"
+                    android:data="http://www.android.com" />
+
+        </PreferenceScreen>
+
+    </PreferenceCategory>
+
+    <PreferenceCategory
+            android:title="@string/preference_attributes">
+
+        <CheckBoxPreference
+                android:key="parent_checkbox_preference"
+                android:title="@string/title_parent_preference"
+                android:summary="@string/summary_parent_preference" />
+
+        <!-- The visual style of a child is defined by this styled theme attribute. -->
+        <CheckBoxPreference
+                android:key="child_checkbox_preference"
+                android:dependency="parent_checkbox_preference"
+                android:layout="?android:attr/preferenceLayoutChild"
+                android:title="@string/title_child_preference"
+                android:summary="@string/summary_child_preference" />
+    </PreferenceCategory>
+
+</PreferenceScreen>
+
diff --git a/tests/tests/preference2/src/android/preference2/cts/CheckBoxPreferenceTest.java b/tests/tests/preference2/src/android/preference2/cts/CheckBoxPreferenceTest.java
new file mode 100755
index 0000000..de129e0
--- /dev/null
+++ b/tests/tests/preference2/src/android/preference2/cts/CheckBoxPreferenceTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.preference2.cts;
+
+import android.preference.CheckBoxPreference;
+import android.test.ActivityInstrumentationTestCase2;
+
+import com.android.cts.preference2.R;
+
+public class CheckBoxPreferenceTest
+        extends ActivityInstrumentationTestCase2<PreferenceFromCodeActivity> {
+
+    private PreferenceFromCodeActivity mActivity;
+
+    public CheckBoxPreferenceTest() {
+        super(PreferenceFromCodeActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+    }
+
+    public void testNotNull() {
+        CheckBoxPreference checkBoxPref = (CheckBoxPreference) mActivity.findPreference(
+                    "checkbox_preference");
+        assertNotNull(checkBoxPref);
+    }
+
+    public void testGetSummary() {
+        CheckBoxPreference checkBoxPref = (CheckBoxPreference) mActivity.findPreference(
+                    "checkbox_preference");
+        String summary = (String) checkBoxPref.getSummary();
+        String summaryExp = mActivity.getResources().getString(
+            R.string.summary_checkbox_preference);
+        assertEquals(summaryExp, summary);
+    }
+}
diff --git a/tests/tests/preference2/src/android/preference2/cts/CustomCheckBoxPreference.java b/tests/tests/preference2/src/android/preference2/cts/CustomCheckBoxPreference.java
new file mode 100755
index 0000000..d51eddd
--- /dev/null
+++ b/tests/tests/preference2/src/android/preference2/cts/CustomCheckBoxPreference.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.preference2.cts;
+
+import com.android.cts.preference2.R;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.preference.CheckBoxPreference;
+import android.util.AttributeSet;
+
+public class CustomCheckBoxPreference extends CheckBoxPreference {
+    private Drawable mIcon;
+    private String mTitle;
+    public CustomCheckBoxPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init(attrs);
+        setIcon(mIcon);
+        this.setTitle(mTitle);
+    }
+
+    public CustomCheckBoxPreference(Context context) {
+        super(context);
+    }
+
+    public CustomCheckBoxPreference(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        init(attrs);
+        setIcon(mIcon);
+        this.setTitle(mTitle);
+    }
+
+    private void init(AttributeSet attrs) {
+        TypedArray a = getContext().obtainStyledAttributes(attrs,R.styleable.CustPref);
+        mTitle = a.getString(R.styleable.CustPref_title);
+        mIcon = a.getDrawable(R.styleable.CustPref_icon);
+    }
+}
diff --git a/tests/tests/preference2/src/android/preference2/cts/CustomCheckBoxPreferenceTest.java b/tests/tests/preference2/src/android/preference2/cts/CustomCheckBoxPreferenceTest.java
new file mode 100755
index 0000000..25ba3f3
--- /dev/null
+++ b/tests/tests/preference2/src/android/preference2/cts/CustomCheckBoxPreferenceTest.java
@@ -0,0 +1,44 @@
+ /*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.preference2.cts;
+
+import android.preference.CheckBoxPreference;
+import android.test.ActivityInstrumentationTestCase2;
+
+public class CustomCheckBoxPreferenceTest
+        extends ActivityInstrumentationTestCase2<PreferencesFromXml> {
+
+    private PreferencesFromXml mActivity;
+    private CheckBoxPreference mCheckBoxPref;
+
+    public CustomCheckBoxPreferenceTest() {
+        super(PreferencesFromXml.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+        mCheckBoxPref = (CheckBoxPreference) mActivity.findPreference(
+                "custom_checkbox_pref_1");
+    }
+
+    public void testNotNull() {
+        assertNotNull(mCheckBoxPref);
+    }
+
+}
diff --git a/tests/tests/preference2/src/android/preference2/cts/CustomDialogPreference.java b/tests/tests/preference2/src/android/preference2/cts/CustomDialogPreference.java
new file mode 100755
index 0000000..db584ac
--- /dev/null
+++ b/tests/tests/preference2/src/android/preference2/cts/CustomDialogPreference.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.preference2.cts;
+
+import com.android.cts.preference2.R;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.preference.DialogPreference;
+import android.util.AttributeSet;
+
+public class CustomDialogPreference extends DialogPreference {
+    private Drawable mIcon;
+    private String mTitle;
+    public CustomDialogPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init(attrs);
+        setIcon(mIcon);
+        this.setTitle(mTitle);
+    }
+
+    public CustomDialogPreference(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        init(attrs);
+        setIcon(mIcon);
+        this.setTitle(mTitle);
+    }
+
+    private void init(AttributeSet attrs) {
+        TypedArray a = getContext().obtainStyledAttributes(attrs,R.styleable.CustPref);
+        mTitle = a.getString(R.styleable.CustPref_title);
+        mIcon = a.getDrawable(R.styleable.CustPref_icon);
+    }
+}
diff --git a/tests/tests/preference2/src/android/preference2/cts/CustomDialogPreferenceTest.java b/tests/tests/preference2/src/android/preference2/cts/CustomDialogPreferenceTest.java
new file mode 100755
index 0000000..5384420
--- /dev/null
+++ b/tests/tests/preference2/src/android/preference2/cts/CustomDialogPreferenceTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.preference2.cts;
+
+import android.test.ActivityInstrumentationTestCase2;
+
+public class CustomDialogPreferenceTest
+        extends ActivityInstrumentationTestCase2<PreferencesFromXml> {
+
+    private PreferencesFromXml mActivity;
+    private CustomDialogPreference mDialogPref;
+
+    public CustomDialogPreferenceTest() {
+        super(PreferencesFromXml.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+        mDialogPref = (CustomDialogPreference) mActivity.findPreference(
+               "custom_dialog_pref_1");
+    }
+
+    public void testNotNull() {
+        assertNotNull(mDialogPref);
+    }
+}
diff --git a/tests/tests/preference2/src/android/preference2/cts/CustomEditTextPreference.java b/tests/tests/preference2/src/android/preference2/cts/CustomEditTextPreference.java
new file mode 100755
index 0000000..51fdf13
--- /dev/null
+++ b/tests/tests/preference2/src/android/preference2/cts/CustomEditTextPreference.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.preference2.cts;
+
+import com.android.cts.preference2.R;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.preference.EditTextPreference;
+import android.util.AttributeSet;
+
+public class CustomEditTextPreference extends EditTextPreference {
+    private Drawable mIcon;
+    private String mTitle;
+    public CustomEditTextPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init(attrs);
+        setIcon(mIcon);
+        this.setTitle(mTitle);
+    }
+
+    public CustomEditTextPreference(Context context) {
+        super(context);
+    }
+
+    public CustomEditTextPreference(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        init(attrs);
+        setIcon(mIcon);
+        this.setTitle(mTitle);
+    }
+
+    private void init(AttributeSet attrs) {
+        TypedArray a = getContext().obtainStyledAttributes(attrs,R.styleable.CustPref);
+        mTitle =a.getString(R.styleable.CustPref_title);
+        mIcon  = a.getDrawable(R.styleable.CustPref_icon);
+    }
+}
diff --git a/tests/tests/preference2/src/android/preference2/cts/CustomEditTextPreferenceTest.java b/tests/tests/preference2/src/android/preference2/cts/CustomEditTextPreferenceTest.java
new file mode 100755
index 0000000..c131539
--- /dev/null
+++ b/tests/tests/preference2/src/android/preference2/cts/CustomEditTextPreferenceTest.java
@@ -0,0 +1,42 @@
+ /*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.preference2.cts;
+
+import android.test.ActivityInstrumentationTestCase2;
+
+public class CustomEditTextPreferenceTest
+        extends ActivityInstrumentationTestCase2<PreferencesFromXml> {
+
+    private PreferencesFromXml mActivity;
+    private CustomEditTextPreference mEditTextPref;
+
+    public CustomEditTextPreferenceTest() {
+        super(PreferencesFromXml.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = (PreferencesFromXml)getActivity();
+        mEditTextPref = (CustomEditTextPreference) mActivity.findPreference(
+                "custom_edittext_pref_1");
+    }
+
+    public void testNotNull() {
+        assertNotNull(mEditTextPref);
+    }
+}
diff --git a/tests/tests/preference2/src/android/preference2/cts/CustomSwitchPreference.java b/tests/tests/preference2/src/android/preference2/cts/CustomSwitchPreference.java
new file mode 100755
index 0000000..54e7861
--- /dev/null
+++ b/tests/tests/preference2/src/android/preference2/cts/CustomSwitchPreference.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.preference2.cts;
+
+
+import com.android.cts.preference2.R;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.preference.SwitchPreference;
+import android.util.AttributeSet;
+
+public class CustomSwitchPreference extends SwitchPreference {
+    private Drawable mIcon;
+    private String mTitle;
+    public CustomSwitchPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init(attrs);
+        setIcon(mIcon);
+        this.setTitle(mTitle);
+    }
+
+    public CustomSwitchPreference(Context context) {
+        super(context);
+    }
+
+    public CustomSwitchPreference(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        init(attrs);
+        setIcon(mIcon);
+        this.setTitle(mTitle);
+    }
+    
+    private void init(AttributeSet attrs) {
+        TypedArray a = getContext().obtainStyledAttributes(attrs,R.styleable.CustPref);
+        mTitle =a.getString(R.styleable.CustPref_title);
+        mIcon  = a.getDrawable(R.styleable.CustPref_icon);
+    }
+}
diff --git a/tests/tests/preference2/src/android/preference2/cts/CustomSwitchPreferenceTest.java b/tests/tests/preference2/src/android/preference2/cts/CustomSwitchPreferenceTest.java
new file mode 100755
index 0000000..937e48f
--- /dev/null
+++ b/tests/tests/preference2/src/android/preference2/cts/CustomSwitchPreferenceTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.preference2.cts;
+
+import android.test.ActivityInstrumentationTestCase2;
+
+public class CustomSwitchPreferenceTest
+        extends ActivityInstrumentationTestCase2<PreferencesFromXml> {
+
+    private PreferencesFromXml mActivity;
+    private CustomSwitchPreference mSwitchPref;
+
+    public CustomSwitchPreferenceTest() {
+        super(PreferencesFromXml.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+        mSwitchPref = (CustomSwitchPreference) mActivity.findPreference(
+                "custom_switch_pref_1");
+    }
+
+    public void testNotNull() {
+        assertNotNull(mSwitchPref);
+    }
+}
diff --git a/tests/tests/preference2/src/android/preference2/cts/DialogPreferenceTest.java b/tests/tests/preference2/src/android/preference2/cts/DialogPreferenceTest.java
new file mode 100755
index 0000000..1136cee
--- /dev/null
+++ b/tests/tests/preference2/src/android/preference2/cts/DialogPreferenceTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.preference2.cts;
+
+import android.graphics.drawable.Drawable;
+import android.preference.DialogPreference;
+import android.test.ActivityInstrumentationTestCase2;
+
+import com.android.cts.preference2.R;
+
+public class DialogPreferenceTest
+        extends ActivityInstrumentationTestCase2<PreferenceFromCodeActivity> {
+
+    private PreferenceFromCodeActivity mActivity;
+    private DialogPreference mDialogPreference;
+
+    public DialogPreferenceTest() {
+        super(PreferenceFromCodeActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+        mDialogPreference = (DialogPreference)mActivity.findPreference(
+                "dialog_preference");
+    }
+
+    public void testGetTitle() {
+        String title = (String) mDialogPreference.getTitle();
+        String titleExp = mActivity.getResources().getString(R.string.title_dialog_preference);
+        assertEquals(titleExp, title);
+    }
+
+    public void testGetDialogTitle() {
+        String title = (String) mDialogPreference.getDialogTitle();
+        String titleExp = mActivity.getResources().getString(
+                R.string.dialogtitle_dialog_preference);
+        assertEquals(titleExp, title);
+    }
+
+    public void testGetDialogIcon() {
+        Drawable drawable = mDialogPreference.getDialogIcon();
+        Drawable drawableExp = mActivity.getResources().getDrawable(R.drawable.ic_launcher);
+        assertEquals(drawableExp.getBounds(), drawable.getBounds());
+    }
+
+    public void testGetDialogMessage() {
+        CharSequence dialogMessage = mDialogPreference.getDialogMessage();
+        CharSequence dialogMessageExp =  mActivity.getResources().getString(
+                R.string.dialog_message);
+        assertEquals(dialogMessageExp, dialogMessage);
+    }
+
+    public void testGetPositiveButtonText() {
+        CharSequence positiveButtonText = mDialogPreference.getPositiveButtonText();
+        CharSequence postiveButtonTextExp =  mActivity.getResources().getString(
+                R.string.positive_button_text);
+        assertEquals(positiveButtonText, postiveButtonTextExp);
+    }
+
+    public void testGetNegativeButtonText() {
+        CharSequence negativeButtonText = mDialogPreference.getNegativeButtonText();
+        CharSequence negativeButtonTextExp =  mActivity.getResources().getString(
+                R.string.negative_button_text);
+        assertEquals(negativeButtonText, negativeButtonTextExp);
+    }
+}
diff --git a/tests/tests/preference2/src/android/preference2/cts/EditTextPreferenceTest.java b/tests/tests/preference2/src/android/preference2/cts/EditTextPreferenceTest.java
new file mode 100755
index 0000000..e0d5c8c
--- /dev/null
+++ b/tests/tests/preference2/src/android/preference2/cts/EditTextPreferenceTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.preference2.cts;
+
+import android.preference.EditTextPreference;
+import android.test.ActivityInstrumentationTestCase2;
+import android.widget.EditText;
+
+public class EditTextPreferenceTest
+        extends ActivityInstrumentationTestCase2<PreferenceFromCodeActivity> {
+
+    private PreferenceFromCodeActivity mActivity;
+    private EditTextPreference mEditTextPref;
+
+    public EditTextPreferenceTest() {
+        super(PreferenceFromCodeActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+        mEditTextPref = (EditTextPreference) mActivity.findPreference(
+                "edittext_preference");
+    }
+
+    public void testGetEditText() {
+        EditText editText = mEditTextPref.getEditText();
+        assertNotNull(editText);
+    }
+}
diff --git a/tests/tests/preference2/src/android/preference2/cts/ListPreferenceTest.java b/tests/tests/preference2/src/android/preference2/cts/ListPreferenceTest.java
new file mode 100755
index 0000000..32596ff
--- /dev/null
+++ b/tests/tests/preference2/src/android/preference2/cts/ListPreferenceTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.preference2.cts;
+
+import android.preference.ListPreference;
+import android.test.ActivityInstrumentationTestCase2;
+
+import com.android.cts.preference2.R;
+
+public class ListPreferenceTest
+        extends ActivityInstrumentationTestCase2<PreferenceFromCodeActivity> {
+
+    private PreferenceFromCodeActivity mActivity;
+    private ListPreference mListPref;
+
+    public ListPreferenceTest() {
+        super(PreferenceFromCodeActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+        mListPref = (ListPreference) mActivity.findPreference("list_preference");
+    }
+
+    public void testGetEntries() {
+        String[] entries = convertToStringArray((CharSequence[]) mListPref.getEntries());
+        String[] entriesExp = mActivity.getResources().getStringArray(
+                R.array.entries_list_preference);
+        compareArrays(entriesExp, entries);
+    }
+
+    public void testGetEntryValues() {
+        String[] entryValues = convertToStringArray((CharSequence[]) mListPref.getEntryValues());
+        String[] entryValuesExp = mActivity.getResources().getStringArray(
+                R.array.entryvalues_list_preference);
+        compareArrays(entryValuesExp,entryValues);
+    }
+
+    public void testIsEnabled() {
+        boolean isEnabled = mListPref.isEnabled();
+        assertTrue(isEnabled);
+    }
+
+    private synchronized String[] convertToStringArray(CharSequence[] array){
+        String[] strArray = new String[array.length];
+        for(int i = 0; i < array.length; i++){
+            strArray[i] = (String) array[i];
+        }
+        return strArray;
+    }
+
+    private void compareArrays(String[] firstArray,String[] secArray){
+        assertEquals(firstArray.length, secArray.length);
+        for(int i = 0; i < firstArray.length; i++) {
+            assertEquals(firstArray[i], secArray[i]);
+        }
+    }
+}
diff --git a/tests/tests/preference2/src/android/preference2/cts/PreferenceCategoryTest.java b/tests/tests/preference2/src/android/preference2/cts/PreferenceCategoryTest.java
new file mode 100755
index 0000000..33adceb
--- /dev/null
+++ b/tests/tests/preference2/src/android/preference2/cts/PreferenceCategoryTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.preference2.cts;
+
+import android.preference.Preference;
+import android.test.ActivityInstrumentationTestCase2;
+
+public class PreferenceCategoryTest
+        extends ActivityInstrumentationTestCase2<PreferenceFromCodeActivity> {
+
+    private PreferenceFromCodeActivity mActivity;
+
+    public PreferenceCategoryTest() {
+        super(PreferenceFromCodeActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+    }
+
+    public void testPreferenceCategory() {
+         Preference prefCat = mActivity.findPreference("pref-1");
+         assertNotNull(prefCat);
+         assertTrue(!prefCat.isEnabled());
+
+    }
+}
diff --git a/tests/tests/preference2/src/android/preference2/cts/PreferenceFragmentActivity.java b/tests/tests/preference2/src/android/preference2/cts/PreferenceFragmentActivity.java
new file mode 100755
index 0000000..4f12d17
--- /dev/null
+++ b/tests/tests/preference2/src/android/preference2/cts/PreferenceFragmentActivity.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package android.preference2.cts;
+
+import android.app.Activity;
+import android.app.FragmentTransaction;
+import android.os.Bundle;
+import android.preference.PreferenceFragment;
+
+/**
+ * Demonstration of PreferenceFragment, showing a single fragment in an
+ * activity.
+ */
+public class PreferenceFragmentActivity extends Activity {
+
+    public PrefFragment prefFragment;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        prefFragment = new PrefFragment();
+
+        FragmentTransaction transaction = getFragmentManager().beginTransaction()
+                .replace(android.R.id.content, prefFragment, PrefFragment.TAG);
+        transaction.commit();
+    }
+
+    public class PrefFragment extends PreferenceFragment {
+        public static final String TAG = "Pref-1";
+
+        public PrefFragment() {
+
+        }
+    }
+}
diff --git a/tests/tests/preference2/src/android/preference2/cts/PreferenceFragmentTest.java b/tests/tests/preference2/src/android/preference2/cts/PreferenceFragmentTest.java
new file mode 100755
index 0000000..4c883c2
--- /dev/null
+++ b/tests/tests/preference2/src/android/preference2/cts/PreferenceFragmentTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.preference2.cts;
+
+import android.preference.PreferenceManager;
+import android.preference.PreferenceScreen;
+import android.preference2.cts.PreferenceFragmentActivity.PrefFragment;
+import android.test.ActivityInstrumentationTestCase2;
+
+public class PreferenceFragmentTest
+        extends ActivityInstrumentationTestCase2<PreferenceFragmentActivity> {
+
+    private PreferenceFragmentActivity mActivity;
+
+    public PreferenceFragmentTest() {
+        super(PreferenceFragmentActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+    }
+
+    public void testGetPreferenceManager() {
+        PrefFragment prefFragment =  (PrefFragment) mActivity.getFragmentManager().
+                findFragmentByTag(PrefFragment.TAG);
+        PreferenceManager prefManager = prefFragment.getPreferenceManager();
+        assertNotNull(prefManager);
+    }
+
+    public void testGetPreferenceScreen() {
+        PrefFragment prefsFragment = (PrefFragment) mActivity.getFragmentManager().
+            findFragmentByTag(PrefFragment.TAG);
+        PreferenceScreen prefScreen = prefsFragment.getPreferenceScreen();
+        assertNull(prefScreen);
+    }
+}
diff --git a/tests/tests/preference2/src/android/preference2/cts/PreferenceFromCodeActivity.java b/tests/tests/preference2/src/android/preference2/cts/PreferenceFromCodeActivity.java
new file mode 100755
index 0000000..ee0dde1
--- /dev/null
+++ b/tests/tests/preference2/src/android/preference2/cts/PreferenceFromCodeActivity.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.preference2.cts;
+
+import com.android.cts.preference2.R;
+
+import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.preference.EditTextPreference;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceCategory;
+import android.preference.PreferenceScreen;
+import android.preference.SwitchPreference;
+
+public class PreferenceFromCodeActivity extends PreferenceActivity {
+    private Preference mPref;
+    protected PreferenceScreen mPrefScreen;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mPrefScreen = getPreferenceManager().createPreferenceScreen(this);
+        addPreferenceCategory();
+        setPreferenceScreen(mPrefScreen);
+    }
+
+    private void addPreferenceCategory() {
+        PreferenceCategory prefCat = new PreferenceCategory(this);
+        prefCat.setTitle(R.string.inline_preferences);
+        prefCat.setKey("pref-1");
+        mPrefScreen.addPreference(prefCat);
+
+        //CheckBox Preference
+        CheckBoxPreference checkboxPref = new CheckBoxPreference(this);
+        checkboxPref.setKey("checkbox_preference");
+        checkboxPref.setTitle(R.string.title_checkbox_preference);
+        checkboxPref.setSummary(R.string.summary_checkbox_preference);
+        checkboxPref.setSummaryOn(R.string.summary_on_checkbox_preference);
+        checkboxPref.setSummaryOff(R.string.summary_off_checkbox_preference);
+        checkboxPref.setChecked(true);
+        checkboxPref.shouldDisableDependents();
+        prefCat.addPreference(checkboxPref);
+
+        // Switch preference
+        SwitchPreference switchPref = new SwitchPreference(this);
+        switchPref.setKey("switch_preference");
+        switchPref.setTitle(R.string.title_switch_preference);
+        switchPref.setSummary(R.string.summary_switch_preference);
+        switchPref.setSummaryOn(R.string.summary_on_switch_preference);
+        switchPref.setSummaryOff(R.string.summary_off_switch_preference);
+        switchPref.setSwitchTextOff(R.string.switchtext_off);
+        switchPref.setSwitchTextOn(R.string.switchtext_on);
+        prefCat.addPreference(switchPref);
+
+        SwitchPreference switchPref2 = new SwitchPreference(this);
+        switchPref2.setKey("switch_preference_2");
+        switchPref2.setTitle(R.string.title_switch_preference);
+        switchPref2.setSummary(R.string.summary_switch_preference);
+        switchPref2.setSummaryOn(R.string.summary_on_switch_preference);
+        switchPref2.setSummaryOff(R.string.summary_off_switch_preference);
+        prefCat.addPreference(switchPref2);
+
+        // Dialog based preferences
+        PreferenceCategory dialogBasedPrefCat = new PreferenceCategory(this);
+        dialogBasedPrefCat.setTitle(R.string.dialog_based_preferences);
+        mPrefScreen.addPreference(dialogBasedPrefCat);
+
+        // Edit text preference
+        EditTextPreference editTextPref = new EditTextPreference(this);
+        editTextPref.setDialogTitle(R.string.dialog_title_edittext_preference);
+        editTextPref.setKey("edittext_preference");
+        editTextPref.setTitle(R.string.title_edittext_preference);
+        editTextPref.setSummary(R.string.summary_edittext_preference);
+        editTextPref.setText(getResources().getString(R.string.text_edittext_preference));
+        dialogBasedPrefCat.addPreference(editTextPref);
+
+        EditTextPreference dialogPref = new EditTextPreference(this);
+        dialogPref.setDialogTitle(R.string.dialogtitle_dialog_preference);
+        dialogPref.setKey("dialog_preference");
+        dialogPref.setTitle(R.string.title_dialog_preference);
+        dialogPref.setSummary(R.string.summary_dialog_preference);
+        dialogPref.setDialogIcon(R.drawable.ic_launcher);
+        dialogPref.setDialogMessage(R.string.dialog_message);
+        dialogPref.setNegativeButtonText(R.string.negative_button_text);
+        dialogPref.setPositiveButtonText(R.string.positive_button_text);
+
+        dialogBasedPrefCat.addPreference(dialogPref);
+
+        ListPreference listPref = new ListPreference(this);
+        listPref.setEntries(R.array.entries_list_preference);
+        listPref.setEntryValues(R.array.entryvalues_list_preference);
+        listPref.setDialogTitle(R.string.dialog_title_list_preference);
+        listPref.setKey("list_preference");
+        listPref.setTitle(R.string.title_list_preference);
+        listPref.setSummary(R.string.summary_list_preference);
+        dialogBasedPrefCat.addPreference(listPref);
+    }
+}
diff --git a/tests/tests/preference2/src/android/preference2/cts/PreferenceWithHeaders.java b/tests/tests/preference2/src/android/preference2/cts/PreferenceWithHeaders.java
new file mode 100755
index 0000000..1059700
--- /dev/null
+++ b/tests/tests/preference2/src/android/preference2/cts/PreferenceWithHeaders.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.preference2.cts;
+
+import android.os.Bundle;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceFragment;
+import android.widget.Button;
+import com.android.cts.preference2.R;
+import java.util.List;
+
+/**
+ * Demonstration of PreferenceActivity to make a top-level preference
+ * panel with headers.
+ */
+
+public class PreferenceWithHeaders extends PreferenceActivity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        // Add a button to the header list.
+        if (hasHeaders()) {
+            Button button = new Button(this);
+            button.setText("Some action");
+            setListFooter(button);
+        }
+    }
+
+    /**
+     * Populate the activity with the top-level headers.
+     */
+    @Override
+    public void onBuildHeaders(List<Header> target) {
+        loadHeadersFromResource(R.xml.preference_headers, target);
+    }
+
+    public static class PrefsOneFragment extends PreferenceFragment {
+        @Override
+        public void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            addPreferencesFromResource(R.xml.preferences);
+        }
+    }
+}
+
diff --git a/tests/tests/preference2/src/android/preference2/cts/PreferenceWithHeadersTest.java b/tests/tests/preference2/src/android/preference2/cts/PreferenceWithHeadersTest.java
new file mode 100755
index 0000000..28bff81
--- /dev/null
+++ b/tests/tests/preference2/src/android/preference2/cts/PreferenceWithHeadersTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.preference2.cts;
+
+import android.test.ActivityInstrumentationTestCase2;
+
+public class PreferenceWithHeadersTest
+        extends ActivityInstrumentationTestCase2<PreferenceWithHeaders> {
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+    }
+
+    private PreferenceWithHeaders mActivity;
+
+    public PreferenceWithHeadersTest() {
+        super(PreferenceWithHeaders.class);
+    }
+
+    public void testHasHeaders() {
+        assertTrue(mActivity.hasHeaders());
+    }
+
+    public void testOnIsHidingHeaders() {
+        assertFalse(mActivity.onIsHidingHeaders());
+    }
+}
diff --git a/tests/tests/preference2/src/android/preference2/cts/PreferencesFromXml.java b/tests/tests/preference2/src/android/preference2/cts/PreferencesFromXml.java
new file mode 100755
index 0000000..0a61461
--- /dev/null
+++ b/tests/tests/preference2/src/android/preference2/cts/PreferencesFromXml.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.preference2.cts;
+
+import com.android.cts.preference2.R;
+import android.os.Bundle;
+import android.preference.PreferenceActivity;
+
+public class PreferencesFromXml extends PreferenceActivity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        addPreferencesFromResource(R.xml.pref_cb);
+    }
+}
diff --git a/tests/tests/preference2/src/android/preference2/cts/SwitchPreferenceTest.java b/tests/tests/preference2/src/android/preference2/cts/SwitchPreferenceTest.java
new file mode 100755
index 0000000..3bd42d2
--- /dev/null
+++ b/tests/tests/preference2/src/android/preference2/cts/SwitchPreferenceTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.preference2.cts;
+
+import 	android.content.res.Resources;
+import android.preference.SwitchPreference;
+import android.test.ActivityInstrumentationTestCase2;
+
+import com.android.cts.preference2.R;
+
+public class SwitchPreferenceTest
+        extends ActivityInstrumentationTestCase2<PreferenceFromCodeActivity> {
+
+    private PreferenceFromCodeActivity mActivity;
+    private SwitchPreference mSwitchPref;
+    private Resources mResources;
+
+    public SwitchPreferenceTest() {
+        super(PreferenceFromCodeActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+        mSwitchPref = (SwitchPreference) mActivity.findPreference(
+                "switch_preference");
+        mResources = mActivity.getResources();
+    }
+
+    public void testGetTitle() {
+        String title = (String) mSwitchPref.getTitle();
+        String titleExp = mResources.getString(R.string.title_switch_preference);
+        assertEquals(titleExp, title);
+    }
+
+    public void testGetSummary() {
+        String summary = (String) mSwitchPref.getSummary();
+        String summaryExp = mResources.getString(R.string.summary_switch_preference);  
+        assertEquals(summaryExp, summary);
+    }
+
+    public void testGetSummaryOn() {
+        String summaryOn = (String) mSwitchPref.getSummaryOn();
+        String summaryOnExp = mResources.getString(
+                R.string.summary_on_switch_preference);
+        assertEquals(summaryOnExp, summaryOn);
+    }
+
+    public void testSummaryOff() {
+        String summaryOff = (String) mSwitchPref.getSummaryOff();
+        String summaryOffExp = mResources.getString(
+                R.string.summary_off_switch_preference);
+        assertEquals(summaryOffExp, summaryOff);
+    }
+
+    public void testSetSwitchTextOff_One() throws Throwable {
+        final CharSequence switchOff = "SwitchedOff";
+        this.runTestOnUiThread(new Runnable() {
+            public void run() {
+                mSwitchPref.setSwitchTextOff(switchOff);
+            }
+        });
+        CharSequence switchOffExp = mSwitchPref.getSwitchTextOff();
+        assertEquals(switchOffExp, switchOff);
+    }
+
+    public void testSetSwitchTextOff_Two() throws Throwable {
+        final CharSequence switchOffExp = mResources.getString(
+                R.string.switchtext_off);
+        CharSequence switchOff = mSwitchPref.getSwitchTextOff();
+        assertEquals(switchOffExp, switchOff);
+    }
+
+    public void testSetSwitchTextOn_One() throws Throwable {
+        final CharSequence switchOn = "SwitchedOff";
+        this.runTestOnUiThread(new Runnable() {
+            public void run() {
+                mSwitchPref.setSwitchTextOn(switchOn);
+            }
+        }); 
+        CharSequence switchOnExp = mSwitchPref.getSwitchTextOn();
+        assertEquals(switchOnExp, switchOn);
+    }
+
+    public void testSetSwitchTextOn_Two() throws Throwable {
+        final CharSequence switchOnExp = mResources.getString(
+                R.string.switchtext_on);
+
+        CharSequence switchOn = mSwitchPref.getSwitchTextOn();
+        assertEquals(switchOnExp, switchOn);
+    }
+}
diff --git a/tests/tests/provider/src/android/provider/cts/CalendarTest.java b/tests/tests/provider/src/android/provider/cts/CalendarTest.java
index e453820..f8babeb 100644
--- a/tests/tests/provider/src/android/provider/cts/CalendarTest.java
+++ b/tests/tests/provider/src/android/provider/cts/CalendarTest.java
@@ -1912,7 +1912,8 @@
         String[] projection = new String[] { Instances.BEGIN };
 
         if (false) {
-            Cursor instances = getInstances(timeZone, rangeStart, rangeEnd, projection);
+            Cursor instances = getInstances(timeZone, rangeStart, rangeEnd, projection,
+                    new long[] { calendarId });
             dumpInstances(instances, timeZone, "all");
             instances.close();
         }
@@ -1923,28 +1924,28 @@
         // Find all matching "testevent".  The search matches on partial strings, so this
         // will also pick up "nontestevent".
         instances = getInstancesSearch(timeZone, rangeStart, rangeEnd,
-                "testevent", false, projection);
+                "testevent", false, projection, new long[] { calendarId });
         count = instances.getCount();
         instances.close();
         assertEquals(4, count);
 
         // Find all matching "fiddle" and "event".  Set the "by day" flag just to be different.
         instances = getInstancesSearch(timeZone, rangeStart, rangeEnd,
-                "fiddle event", true, projection);
+                "fiddle event", true, projection, new long[] { calendarId });
         count = instances.getCount();
         instances.close();
         assertEquals(2, count);
 
         // Find all matching "fiddle" and "baluchitherium".
         instances = getInstancesSearch(timeZone, rangeStart, rangeEnd,
-                "baluchitherium fiddle", false, projection);
+                "baluchitherium fiddle", false, projection, new long[] { calendarId });
         count = instances.getCount();
         instances.close();
         assertEquals(0, count);
 
         // Find all matching "event-two".
         instances = getInstancesSearch(timeZone, rangeStart, rangeEnd,
-                "event-two", false, projection);
+                "event-two", false, projection, new long[] { calendarId });
         count = instances.getCount();
         instances.close();
         assertEquals(1, count);
@@ -2231,10 +2232,10 @@
         // Check to see if we have the expected number of instances
         String timeZone = eventValues.getAsString(Events.EVENT_TIMEZONE);
         int instanceCount = getInstanceCount(timeZone, "2003-08-05T00:00:00",
-                "2003-08-31T11:59:59");
+                "2003-08-31T11:59:59", new long[] { calendarId });
         if (false) {
             Cursor instances = getInstances(timeZone, "2003-08-05T00:00:00", "2003-08-31T11:59:59",
-                    new String[] { Instances.BEGIN });
+                    new String[] { Instances.BEGIN }, new long[] { calendarId });
             dumpInstances(instances, timeZone, "initial");
             instances.close();
         }
@@ -2318,7 +2319,8 @@
         String testEnd = "1999-05-16T23:59:59";
         String[] projection = { Instances.BEGIN, Instances.START_MINUTE, Instances.END_MINUTE };
 
-        Cursor instances = getInstances(timeZone, testStart, testEnd, projection);
+        Cursor instances = getInstances(timeZone, testStart, testEnd, projection,
+                new long[] { calendarId });
         if (DEBUG_RECURRENCE) {
             dumpInstances(instances, timeZone, "initial");
         }
@@ -2363,7 +2365,8 @@
         // TODO: compare Reminders, Attendees, ExtendedProperties on one of the exception events
 
         // Re-query the instances and figure out if they look right.
-        instances = getInstances(timeZone, testStart, testEnd, projection);
+        instances = getInstances(timeZone, testStart, testEnd, projection,
+                new long[] { calendarId });
         if (DEBUG_RECURRENCE) {
             dumpInstances(instances, timeZone, "with DTSTART exceptions");
         }
@@ -2388,7 +2391,8 @@
         assertEquals("events deleted", 3, deleteCount);
 
         // Re-query the instances and figure out if they look right.
-        instances = getInstances(timeZone, testStart, testEnd, projection);
+        instances = getInstances(timeZone, testStart, testEnd, projection,
+                new long[] { calendarId });
         if (DEBUG_RECURRENCE) {
             dumpInstances(instances, timeZone, "post exception deletion");
         }
@@ -2409,7 +2413,8 @@
          * Repeat the test, this time modifying DURATION.
          */
 
-        instances = getInstances(timeZone, testStart, testEnd, projection);
+        instances = getInstances(timeZone, testStart, testEnd, projection,
+                new long[] { calendarId });
         if (DEBUG_RECURRENCE) {
             dumpInstances(instances, timeZone, "initial");
         }
@@ -2446,7 +2451,8 @@
         // TODO: make sure the selfAttendeeStatus change took
 
         // Re-query the instances and figure out if they look right.
-        instances = getInstances(timeZone, testStart, testEnd, projection);
+        instances = getInstances(timeZone, testStart, testEnd, projection,
+                new long[] { calendarId });
         if (DEBUG_RECURRENCE) {
             dumpInstances(instances, timeZone, "with DURATION exceptions");
         }
@@ -2502,7 +2508,8 @@
         // Add some attendees.
         addAttendees(account, eventId, seed);
 
-        Cursor instances = getInstances(timeZone, testStart, testEnd, projection);
+        Cursor instances = getInstances(timeZone, testStart, testEnd, projection,
+                new long[] { calendarId });
         if (DEBUG_RECURRENCE) {
             dumpInstances(instances, timeZone, "initial");
         }
@@ -2532,7 +2539,8 @@
         instances.close();
 
         // Re-query the instances and figure out if they look right.
-        instances = getInstances(timeZone, testStart, testEnd, projection);
+        instances = getInstances(timeZone, testStart, testEnd, projection,
+                new long[] { calendarId });
         if (DEBUG_RECURRENCE) {
             dumpInstances(instances, timeZone, "with exceptions");
         }
@@ -2669,7 +2677,8 @@
 
         // Check to see how many instances we get.  If the recurrence and the exception don't
         // get paired up correctly, we'll see too many instances.
-        Cursor instances = getInstances(timeZone, testStart, testEnd, projection);
+        Cursor instances = getInstances(timeZone, testStart, testEnd, projection,
+                new long[] { calendarId1, calendarId2 });
         if (DEBUG_RECURRENCE) {
             dumpInstances(instances, timeZone, "with exception");
         }
@@ -2756,7 +2765,8 @@
         String testEnd = "1999-01-29T23:59:59";
         String[] projection = { Instances.BEGIN, Instances.START_MINUTE };
 
-        Cursor instances = getInstances(timeZone, testStart, testEnd, projection);
+        Cursor instances = getInstances(timeZone, testStart, testEnd, projection,
+                new long[] { calendarId });
         if (DEBUG_RECURRENCE) {
             dumpInstances(instances, timeZone, "initial");
         }
@@ -2780,7 +2790,8 @@
 
 
         // Check to see if it took.
-        instances = getInstances(timeZone, testStart, testEnd, projection);
+        instances = getInstances(timeZone, testStart, testEnd, projection,
+                new long[] { calendarId });
         if (DEBUG_RECURRENCE) {
             dumpInstances(instances, timeZone, "with new rule");
         }
@@ -2849,7 +2860,8 @@
         String[] projection = { Instances.BEGIN, Instances.EVENT_LOCATION };
         String newLocation = "NEW!";
 
-        Cursor instances = getInstances(timeZone, testStart, testEnd, projection);
+        Cursor instances = getInstances(timeZone, testStart, testEnd, projection,
+                new long[] { calendarId });
         if (DEBUG_RECURRENCE) {
             dumpInstances(instances, timeZone, "initial");
         }
@@ -2867,7 +2879,8 @@
         // Check results.
         assertEquals("full update does not create new ID", eventId, excepEventId);
 
-        instances = getInstances(timeZone, testStart, testEnd, projection);
+        instances = getInstances(timeZone, testStart, testEnd, projection,
+                new long[] { calendarId });
         assertEquals("post-update instance count", 3, instances.getCount());
         while (instances.moveToNext()) {
             assertEquals("new location", newLocation, instances.getString(1));
@@ -2940,7 +2953,7 @@
      * @return Cursor with instances (caller should close when done)
      */
     private Cursor getInstances(String timeZone, String startWhen, String endWhen,
-            String[] projection) {
+            String[] projection, long[] calendarIds) {
         Time startTime = new Time(timeZone);
         startTime.parse3339(startWhen);
         long startMillis = startTime.toMillis(false);
@@ -2954,7 +2967,16 @@
         Uri uri = Uri.withAppendedPath(CalendarContract.Instances.CONTENT_URI,
                 startMillis + "/" + endMillis);
 
-        Cursor instances = mContentResolver.query(uri, projection, null, null,
+        String where = null;
+        for (int i = 0; i < calendarIds.length; i++) {
+            if (i > 0) {
+                where += " OR ";
+            } else {
+                where = "";
+            }
+            where += (Instances.CALENDAR_ID + "=" + calendarIds[i]);
+        }
+        Cursor instances = mContentResolver.query(uri, projection, where, null,
                 projection[0] + " ASC");
 
         return instances;
@@ -2975,7 +2997,7 @@
      * @return Cursor with instances (caller should close when done)
      */
     private Cursor getInstancesSearch(String timeZone, String startWhen, String endWhen,
-            String search, boolean searchByDay, String[] projection) {
+            String search, boolean searchByDay, String[] projection, long[] calendarIds) {
         Time startTime = new Time(timeZone);
         startTime.parse3339(startWhen);
         long startMillis = startTime.toMillis(false);
@@ -2996,10 +3018,19 @@
                     startMillis + "/" + endMillis + "/" + search);
         }
 
+        String where = null;
+        for (int i = 0; i < calendarIds.length; i++) {
+            if (i > 0) {
+                where += " OR ";
+            } else {
+                where = "";
+            }
+            where += (Instances.CALENDAR_ID + "=" + calendarIds[i]);
+        }
         // We want a list of instances that occur between the specified dates and that match
         // the search terms.
 
-        Cursor instances = mContentResolver.query(uri, projection, null, null,
+        Cursor instances = mContentResolver.query(uri, projection, where, null,
                 projection[0] + " ASC");
 
         return instances;
@@ -3031,9 +3062,10 @@
     /**
      * Counts the number of instances that appear between the specified start and end times.
      */
-    private int getInstanceCount(String timeZone, String startWhen, String endWhen) {
+    private int getInstanceCount(String timeZone, String startWhen, String endWhen,
+                long[] calendarIds) {
         Cursor instances = getInstances(timeZone, startWhen, endWhen,
-                new String[] { Instances._ID });
+                new String[] { Instances._ID }, calendarIds);
         int count = instances.getCount();
         instances.close();
         return count;
@@ -3194,7 +3226,8 @@
         assertTrue(eventId >= 0);
 
         String[] projection = { Instances.BEGIN, Instances.START_MINUTE };
-        Cursor instances = getInstances(timeZone, testStart, testEnd, projection);
+        Cursor instances = getInstances(timeZone, testStart, testEnd, projection,
+                new long[] { calendarId });
         if (DEBUG_RECURRENCE) {
             dumpInstances(instances, timeZone, "prep-create");
         }
@@ -3204,7 +3237,8 @@
         Uri eventUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventId);
         removeAndVerifyEvent(eventUri, new ContentValues(eventValues), account);
 
-        instances = getInstances(timeZone, testStart, testEnd, projection);
+        instances = getInstances(timeZone, testStart, testEnd, projection,
+                new long[] { calendarId });
         if (DEBUG_RECURRENCE) {
             dumpInstances(instances, timeZone, "prep-clear");
         }
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_EmailTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_EmailTest.java
new file mode 100644
index 0000000..3f4bd7e
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_EmailTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider.cts;
+
+import android.content.res.Resources;
+import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.test.AndroidTestCase;
+
+public class ContactsContract_CommonDataKinds_EmailTest extends AndroidTestCase {
+
+    private Resources mResources;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mResources = mContext.getResources();
+    }
+
+    public void testGetTypeLabel() {
+        assertGetTypeLabel(Email.TYPE_HOME);
+        assertGetTypeLabel(Email.TYPE_MOBILE);
+        assertGetTypeLabel(Email.TYPE_OTHER);
+        assertGetTypeLabel(Email.TYPE_WORK);
+        assertGetTypeLabel(Email.TYPE_CUSTOM);
+        assertCustomTypeLabel("Custom Label");
+    }
+
+    private void assertGetTypeLabel(int type) {
+        int res = Email.getTypeLabelResource(type);
+        assertTrue(res != 0);
+
+        String label = mResources.getString(res);
+        assertEquals(label, Email.getTypeLabel(mResources, type, ""));
+    }
+
+    private void assertCustomTypeLabel(String label) {
+        int res = Email.getTypeLabelResource(Email.TYPE_CUSTOM);
+        assertTrue(res != 0);
+        assertEquals(label, Email.getTypeLabel(mResources, Email.TYPE_CUSTOM, label));
+    }
+}
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_EventTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_EventTest.java
new file mode 100644
index 0000000..b996ad2
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_EventTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider.cts;
+
+import android.provider.ContactsContract.CommonDataKinds.Event;
+import android.test.AndroidTestCase;
+
+public class ContactsContract_CommonDataKinds_EventTest extends AndroidTestCase {
+
+    public void testGetTypeLabel() {
+        assertGetTypeLabel(Event.TYPE_ANNIVERSARY);
+        assertGetTypeLabel(Event.TYPE_BIRTHDAY);
+        assertGetTypeLabel(Event.TYPE_OTHER);
+        assertGetTypeLabel(Event.TYPE_CUSTOM);
+        assertGetTypeLabel(null);
+    }
+
+    private void assertGetTypeLabel(Integer type) {
+        int res = Event.getTypeResource(type);
+        assertTrue(res != 0);
+    }
+}
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_ImTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_ImTest.java
new file mode 100644
index 0000000..eacceaa
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_ImTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider.cts;
+
+import android.content.res.Resources;
+import android.provider.ContactsContract.CommonDataKinds.Im;
+import android.test.AndroidTestCase;
+
+public class ContactsContract_CommonDataKinds_ImTest extends AndroidTestCase {
+
+    private Resources mResources;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mResources = mContext.getResources();
+    }
+
+    public void testGetProtocolLabel() {
+        assertGetProtocolLabel(Im.PROTOCOL_AIM);
+        assertGetProtocolLabel(Im.PROTOCOL_CUSTOM);
+        assertGetProtocolLabel(Im.PROTOCOL_GOOGLE_TALK);
+        assertGetProtocolLabel(Im.PROTOCOL_ICQ);
+        assertGetProtocolLabel(Im.PROTOCOL_JABBER);
+        assertGetProtocolLabel(Im.PROTOCOL_MSN);
+        assertGetProtocolLabel(Im.PROTOCOL_NETMEETING);
+        assertGetProtocolLabel(Im.PROTOCOL_QQ);
+        assertGetProtocolLabel(Im.PROTOCOL_SKYPE);
+        assertGetProtocolLabel(Im.PROTOCOL_YAHOO);
+        assertCustomProtocolLabel("Custom Label");
+    }
+
+    public void testGetTypeLabel() {
+        assertGetTypeLabel(Im.TYPE_HOME);
+        assertGetTypeLabel(Im.TYPE_WORK);
+        assertGetTypeLabel(Im.TYPE_OTHER);
+        assertGetTypeLabel(Im.TYPE_CUSTOM);
+        assertCustomTypeLabel("Custom Label");
+    }
+
+    private void assertGetProtocolLabel(int type) {
+        int res = Im.getProtocolLabelResource(type);
+        assertTrue(res != 0);
+
+        String label = mResources.getString(res);
+        assertEquals(label, Im.getProtocolLabel(mResources, type, ""));
+    }
+
+    private void assertCustomProtocolLabel(String label) {
+        int res = Im.getProtocolLabelResource(Im.PROTOCOL_CUSTOM);
+        assertTrue(res != 0);
+        assertEquals(label, Im.getProtocolLabel(mResources, Im.PROTOCOL_CUSTOM, label));
+    }
+
+    private void assertGetTypeLabel(int type) {
+        int res = Im.getTypeLabelResource(type);
+        assertTrue(res != 0);
+
+        String label = mResources.getString(res);
+        assertEquals(label, Im.getTypeLabel(mResources, type, ""));
+    }
+
+    private void assertCustomTypeLabel(String label) {
+        int res = Im.getTypeLabelResource(Im.TYPE_CUSTOM);
+        assertTrue(res != 0);
+        assertEquals(label, Im.getTypeLabel(mResources, Im.TYPE_CUSTOM, label));
+    }
+}
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_OrganizationTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_OrganizationTest.java
new file mode 100644
index 0000000..2de3b05
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_OrganizationTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider.cts;
+
+import android.content.res.Resources;
+import android.provider.ContactsContract.CommonDataKinds.Im;
+import android.provider.ContactsContract.CommonDataKinds.Organization;
+import android.test.AndroidTestCase;
+
+public class ContactsContract_CommonDataKinds_OrganizationTest extends AndroidTestCase {
+
+    private Resources mResources;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mResources = mContext.getResources();
+    }
+
+    public void testGetTypeLabel() {
+        assertGetTypeLabel(Organization.TYPE_WORK);
+        assertGetTypeLabel(Organization.TYPE_OTHER);
+        assertGetTypeLabel(Organization.TYPE_CUSTOM);
+        assertCustomTypeLabel("Custom Label");
+    }
+
+    private void assertGetTypeLabel(int type) {
+        int res = Organization.getTypeLabelResource(type);
+        assertTrue(res != 0);
+
+        String label = mResources.getString(res);
+        assertEquals(label, Organization.getTypeLabel(mResources, type, ""));
+    }
+
+    private void assertCustomTypeLabel(String label) {
+        int res = Organization.getTypeLabelResource(Im.TYPE_CUSTOM);
+        assertTrue(res != 0);
+        assertEquals(label, Organization.getTypeLabel(mResources, Im.TYPE_CUSTOM, label));
+    }
+}
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_PhoneTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_PhoneTest.java
new file mode 100644
index 0000000..433a32e
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_PhoneTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider.cts;
+
+import android.content.res.Resources;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.test.AndroidTestCase;
+
+public class ContactsContract_CommonDataKinds_PhoneTest extends AndroidTestCase {
+
+    private Resources mResources;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mResources = mContext.getResources();
+    }
+
+    public void testGetTypeLabel() {
+        assertGetTypeLabel(Phone.TYPE_ASSISTANT);
+        assertGetTypeLabel(Phone.TYPE_CALLBACK);
+        assertGetTypeLabel(Phone.TYPE_CAR);
+        assertGetTypeLabel(Phone.TYPE_COMPANY_MAIN);
+        assertGetTypeLabel(Phone.TYPE_FAX_HOME);
+        assertGetTypeLabel(Phone.TYPE_FAX_WORK);
+        assertGetTypeLabel(Phone.TYPE_HOME);
+        assertGetTypeLabel(Phone.TYPE_ISDN);
+        assertGetTypeLabel(Phone.TYPE_MAIN);
+        assertGetTypeLabel(Phone.TYPE_MMS);
+        assertGetTypeLabel(Phone.TYPE_MOBILE);
+        assertGetTypeLabel(Phone.TYPE_OTHER);
+        assertGetTypeLabel(Phone.TYPE_OTHER_FAX);
+        assertGetTypeLabel(Phone.TYPE_PAGER);
+        assertGetTypeLabel(Phone.TYPE_RADIO);
+        assertGetTypeLabel(Phone.TYPE_TELEX);
+        assertGetTypeLabel(Phone.TYPE_TTY_TDD);
+        assertGetTypeLabel(Phone.TYPE_WORK);
+        assertGetTypeLabel(Phone.TYPE_WORK_MOBILE);
+        assertGetTypeLabel(Phone.TYPE_WORK_PAGER);
+        assertGetTypeLabel(Phone.TYPE_CUSTOM);
+        assertCustomTypeLabel("Custom Label");
+    }
+
+    private void assertGetTypeLabel(int type) {
+        int res = Phone.getTypeLabelResource(type);
+        assertTrue(res != 0);
+
+        String label = mResources.getString(res);
+        assertEquals(label, Phone.getTypeLabel(mResources, type, ""));
+    }
+
+    private void assertCustomTypeLabel(String label) {
+        int res = Phone.getTypeLabelResource(Phone.TYPE_CUSTOM);
+        assertTrue(res != 0);
+        assertEquals(label, Phone.getTypeLabel(mResources, Phone.TYPE_CUSTOM, label));
+    }
+}
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_RelationTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_RelationTest.java
new file mode 100644
index 0000000..f5e27ce
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_RelationTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider.cts;
+
+import android.content.res.Resources;
+import android.provider.ContactsContract.CommonDataKinds.Relation;
+import android.test.AndroidTestCase;
+
+public class ContactsContract_CommonDataKinds_RelationTest extends AndroidTestCase {
+
+    private Resources mResources;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mResources = mContext.getResources();
+    }
+
+    public void testGetTypeLabel() {
+        assertGetTypeLabel(Relation.TYPE_ASSISTANT);
+        assertGetTypeLabel(Relation.TYPE_BROTHER);
+        assertGetTypeLabel(Relation.TYPE_CHILD);
+        assertGetTypeLabel(Relation.TYPE_DOMESTIC_PARTNER);
+        assertGetTypeLabel(Relation.TYPE_FATHER);
+        assertGetTypeLabel(Relation.TYPE_FRIEND);
+        assertGetTypeLabel(Relation.TYPE_MANAGER);
+        assertGetTypeLabel(Relation.TYPE_MOTHER);
+        assertGetTypeLabel(Relation.TYPE_PARENT);
+        assertGetTypeLabel(Relation.TYPE_PARTNER);
+        assertGetTypeLabel(Relation.TYPE_REFERRED_BY);
+        assertGetTypeLabel(Relation.TYPE_RELATIVE);
+        assertGetTypeLabel(Relation.TYPE_SISTER);
+        assertGetTypeLabel(Relation.TYPE_SPOUSE);
+        assertGetTypeLabel(Relation.TYPE_CUSTOM);
+        assertCustomTypeLabel("Custom Label");
+    }
+
+    private void assertGetTypeLabel(int type) {
+        int res = Relation.getTypeLabelResource(type);
+        assertTrue(res != 0);
+
+        String label = mResources.getString(res);
+        assertEquals(label, Relation.getTypeLabel(mResources, type, ""));
+    }
+
+    private void assertCustomTypeLabel(String label) {
+        int res = Relation.getTypeLabelResource(Relation.TYPE_CUSTOM);
+        assertTrue(res != 0);
+        assertEquals(label, Relation.getTypeLabel(mResources, Relation.TYPE_CUSTOM, label));
+    }
+}
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_SipAddressTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_SipAddressTest.java
new file mode 100644
index 0000000..1406b40
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_SipAddressTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider.cts;
+
+import android.content.res.Resources;
+import android.provider.ContactsContract.CommonDataKinds.SipAddress;
+import android.test.AndroidTestCase;
+
+public class ContactsContract_CommonDataKinds_SipAddressTest extends AndroidTestCase {
+
+    private Resources mResources;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mResources = mContext.getResources();
+    }
+
+    public void testGetTypeLabel() {
+        assertGetTypeLabel(SipAddress.TYPE_HOME);
+        assertGetTypeLabel(SipAddress.TYPE_OTHER);
+        assertGetTypeLabel(SipAddress.TYPE_WORK);
+        assertGetTypeLabel(SipAddress.TYPE_CUSTOM);
+        assertCustomTypeLabel("Custom Label");
+    }
+
+    private void assertGetTypeLabel(int type) {
+        int res = SipAddress.getTypeLabelResource(type);
+        assertTrue(res != 0);
+
+        String label = mResources.getString(res);
+        assertEquals(label, SipAddress.getTypeLabel(mResources, type, ""));
+    }
+
+    private void assertCustomTypeLabel(String label) {
+        int res = SipAddress.getTypeLabelResource(SipAddress.TYPE_CUSTOM);
+        assertTrue(res != 0);
+        assertEquals(label, SipAddress.getTypeLabel(mResources, SipAddress.TYPE_CUSTOM, label));
+    }
+}
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_StructuredPostalTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_StructuredPostalTest.java
new file mode 100644
index 0000000..18a64ce
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_CommonDataKinds_StructuredPostalTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider.cts;
+
+import android.content.res.Resources;
+import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
+import android.test.AndroidTestCase;
+
+public class ContactsContract_CommonDataKinds_StructuredPostalTest extends AndroidTestCase {
+
+    private Resources mResources;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mResources = mContext.getResources();
+    }
+
+    public void testGetTypeLabel() {
+        assertGetTypeLabel(StructuredPostal.TYPE_HOME);
+        assertGetTypeLabel(StructuredPostal.TYPE_OTHER);
+        assertGetTypeLabel(StructuredPostal.TYPE_WORK);
+        assertGetTypeLabel(StructuredPostal.TYPE_CUSTOM);
+        assertCustomTypeLabel("Custom Label");
+    }
+
+    private void assertGetTypeLabel(int type) {
+        int res = StructuredPostal.getTypeLabelResource(type);
+        assertTrue(res != 0);
+
+        String label = mResources.getString(res);
+        assertEquals(label, StructuredPostal.getTypeLabel(mResources, type, ""));
+    }
+
+    private void assertCustomTypeLabel(String label) {
+        int res = StructuredPostal.getTypeLabelResource(StructuredPostal.TYPE_CUSTOM);
+        assertTrue(res != 0);
+        assertEquals(label, StructuredPostal.getTypeLabel(mResources,
+                StructuredPostal.TYPE_CUSTOM, label));
+    }
+}
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_ContactsTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_ContactsTest.java
index a3c6a25..2220d96 100644
--- a/tests/tests/provider/src/android/provider/cts/ContactsContract_ContactsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_ContactsTest.java
@@ -16,17 +16,15 @@
 
 package android.provider.cts;
 
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargetNew;
-
 import android.app.Instrumentation;
 import android.content.ContentResolver;
+import android.content.ContentUris;
 import android.content.Context;
 import android.content.IContentProvider;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.net.Uri;
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.Contacts;
 import android.provider.cts.ContactsContract_TestDataBuilder.TestContact;
@@ -35,7 +33,6 @@
 
 import java.util.List;
 
-@TestTargetClass(ContactsContract.Contacts.class)
 public class ContactsContract_ContactsTest extends InstrumentationTestCase {
     private ContentResolver mContentResolver;
     private ContactsContract_TestDataBuilder mBuilder;
@@ -54,12 +51,6 @@
         mBuilder.cleanup();
     }
 
-    @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            notes = "Test markAsContacted(ContentResolver resolver, long contactId)",
-            method = "markAsContacted",
-            args = {android.content.ContentResolver.class, long.class}
-    )
     public void testMarkAsContacted() throws Exception {
         TestRawContact rawContact = mBuilder.newRawContact().insert().load();
         TestContact contact = rawContact.getContact().load();
@@ -88,5 +79,24 @@
         assertFalse("Device does not support the activity intent: " + intent,
                 resolveInfos.isEmpty());
     }
+
+    public void testLookupUri() throws Exception {
+        TestRawContact rawContact = mBuilder.newRawContact().insert().load();
+        TestContact contact = rawContact.getContact().load();
+
+        Uri contactUri = contact.getUri();
+        long contactId = contact.getId();
+        String lookupKey = contact.getString(Contacts.LOOKUP_KEY);
+
+        Uri lookupUri = Contacts.getLookupUri(contactId, lookupKey);
+        assertEquals(ContentUris.withAppendedId(Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI,
+                lookupKey), contactId), lookupUri);
+
+        Uri lookupUri2 = Contacts.getLookupUri(mContentResolver, contactUri);
+        assertEquals(lookupUri, lookupUri2);
+
+        Uri contactUri2 = Contacts.lookupContact(mContentResolver, lookupUri);
+        assertEquals(contactUri, contactUri2);
+    }
 }
 
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_PhotoTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_PhotoTest.java
index 68ed1b8..edab42f 100644
--- a/tests/tests/provider/src/android/provider/cts/ContactsContract_PhotoTest.java
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_PhotoTest.java
@@ -22,6 +22,8 @@
 import android.content.IContentProvider;
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.CommonDataKinds.Photo;
+import android.provider.ContactsContract.Contacts;
+import android.provider.cts.ContactsContract_TestDataBuilder.TestContact;
 import android.provider.cts.ContactsContract_TestDataBuilder.TestData;
 import android.provider.cts.ContactsContract_TestDataBuilder.TestRawContact;
 import android.test.InstrumentationTestCase;
@@ -35,12 +37,13 @@
 
     private static final byte[] EMPTY_TEST_PHOTO_DATA = "".getBytes();
 
+    private ContentResolver mResolver;
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        ContentResolver contentResolver =
-                getInstrumentation().getTargetContext().getContentResolver();
-        IContentProvider provider = contentResolver.acquireProvider(ContactsContract.AUTHORITY);
+        mResolver = getInstrumentation().getTargetContext().getContentResolver();
+        IContentProvider provider = mResolver.acquireProvider(ContactsContract.AUTHORITY);
         mBuilder = new ContactsContract_TestDataBuilder(provider);
     }
 
@@ -51,7 +54,13 @@
     }
 
     public void testAddPhoto() throws Exception {
-        TestRawContact rawContact = mBuilder.newRawContact().insert();
+        TestRawContact rawContact = mBuilder.newRawContact().insert().load();
+        TestContact contact = rawContact.getContact().load();
+
+        assertNull(Contacts.openContactPhotoInputStream(mResolver, contact.getUri()));
+        assertNull(Contacts.openContactPhotoInputStream(mResolver, contact.getUri(), true));
+        assertNull(Contacts.openContactPhotoInputStream(mResolver, contact.getUri(), false));
+
         TestData photoData = rawContact.newDataRow(Photo.CONTENT_ITEM_TYPE)
                 .with(Photo.PHOTO, getTestPhotoData())
                 .insert();
@@ -59,14 +68,28 @@
         photoData.load();
         photoData.assertColumn(Photo.RAW_CONTACT_ID, rawContact.getId());
         photoData.assertBlobColumnNotNull(Photo.PHOTO);
+
+        assertPhotoStream(Contacts.openContactPhotoInputStream(mResolver, contact.getUri()));
+        assertPhotoStream(Contacts.openContactPhotoInputStream(mResolver, contact.getUri(), true));
+        assertPhotoStream(Contacts.openContactPhotoInputStream(mResolver, contact.getUri(), false));
     }
 
     public void testAddEmptyPhoto() throws Exception {
-        TestRawContact rawContact = mBuilder.newRawContact().insert();
+        TestRawContact rawContact = mBuilder.newRawContact().insert().load();
+        TestContact contact = rawContact.getContact().load();
+
+        assertNull(Contacts.openContactPhotoInputStream(mResolver, contact.getUri()));
+        assertNull(Contacts.openContactPhotoInputStream(mResolver, contact.getUri(), true));
+        assertNull(Contacts.openContactPhotoInputStream(mResolver, contact.getUri(), false));
+
         TestData photoData = rawContact.newDataRow(Photo.CONTENT_ITEM_TYPE)
                 .with(Photo.PHOTO, EMPTY_TEST_PHOTO_DATA)
                 .insert();
         assertNotNull(photoData.load());
+
+        assertNull(Contacts.openContactPhotoInputStream(mResolver, contact.getUri()));
+        assertNull(Contacts.openContactPhotoInputStream(mResolver, contact.getUri(), true));
+        assertNull(Contacts.openContactPhotoInputStream(mResolver, contact.getUri(), false));
     }
 
     private byte[] getTestPhotoData() {
@@ -89,5 +112,17 @@
         }
         return os.toByteArray();
     }
+
+    private void assertPhotoStream(InputStream photoStream) throws IOException {
+        try {
+            assertNotNull(photoStream);
+            byte[] actualBytes = readInputStreamFully(photoStream);
+            assertTrue(actualBytes.length > 0);
+        } finally {
+            if (photoStream != null) {
+                photoStream.close();
+            }
+        }
+    }
 }
 
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_StatusUpdatesTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_StatusUpdatesTest.java
new file mode 100644
index 0000000..2f3cdeb
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_StatusUpdatesTest.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider.cts;
+
+import android.content.ContentProviderOperation;
+import android.content.ContentProviderResult;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.CommonDataKinds.Im;
+import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.RawContacts;
+import android.provider.ContactsContract.StatusUpdates;
+import android.test.AndroidTestCase;
+
+import java.util.ArrayList;
+
+public class ContactsContract_StatusUpdatesTest extends AndroidTestCase {
+
+    private static final String ACCOUNT_TYPE = "com.android.cts.provider";
+    private static final String ACCOUNT_NAME = "ContactsContract_StatusUpdatesTest";
+
+    private ContentResolver mResolver;
+    private long dataId;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mResolver = mContext.getContentResolver();
+
+        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
+
+        ops.add(ContentProviderOperation.newInsert(RawContacts.CONTENT_URI)
+                .withValue(RawContacts.ACCOUNT_TYPE, ACCOUNT_TYPE)
+                .withValue(RawContacts.ACCOUNT_NAME, ACCOUNT_NAME)
+                .build());
+
+        ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI)
+                .withValueBackReference(Data.RAW_CONTACT_ID, 0)
+                .withValue(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE)
+                .withValue(Im.TYPE, Im.TYPE_HOME)
+                .withValue(Im.PROTOCOL, Im.PROTOCOL_GOOGLE_TALK)
+                .build());
+
+        ContentProviderResult[] results = mResolver.applyBatch(ContactsContract.AUTHORITY, ops);
+        assertNotNull(results[0].uri);
+        assertNotNull(results[1].uri);
+
+        dataId = ContentUris.parseId(results[1].uri);
+    }
+
+    public void testInsertStatus() throws Exception {
+        Uri uri = insertStatusUpdate(dataId, StatusUpdates.DO_NOT_DISTURB, null, null);
+        assertPresence(uri, StatusUpdates.DO_NOT_DISTURB);
+        assertStatus(uri, null);
+        assertHasTimestamp(uri, false);
+        assertRowCount(uri, 1);
+
+        Uri uri2 = insertStatusUpdate(dataId, StatusUpdates.AVAILABLE, null, null);
+        assertEquals(uri, uri2);
+
+        assertPresence(uri, StatusUpdates.AVAILABLE);
+        assertStatus(uri, null);
+        assertHasTimestamp(uri, false);
+        assertRowCount(uri, 1);
+
+        Uri uri3 = insertStatusUpdate(dataId, StatusUpdates.AWAY, "Grabbing a byte", null);
+        assertEquals(uri2, uri3);
+
+        assertPresence(uri, StatusUpdates.AWAY);
+        assertStatus(uri, "Grabbing a byte");
+        assertHasTimestamp(uri, false);
+        assertRowCount(uri, 1);
+
+        // Inserting a new status message causes a timestamp to be inserted
+        Uri uri4 = insertStatusUpdate(dataId, StatusUpdates.IDLE, "Taking a bit of a break", null);
+        assertEquals(uri3, uri4);
+
+        assertPresence(uri, StatusUpdates.IDLE);
+        assertStatus(uri, "Taking a bit of a break");
+        assertHasTimestamp(uri, true);
+        assertRowCount(uri, 1);
+    }
+
+    private Uri insertStatusUpdate(long dataId, int presence, String status, Long timestamp)
+            throws Exception {
+        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
+        ops.add(ContentProviderOperation.newInsert(StatusUpdates.CONTENT_URI)
+                .withValue(StatusUpdates.DATA_ID, dataId)
+                .withValue(StatusUpdates.PRESENCE, presence)
+                .withValue(StatusUpdates.STATUS, status)
+                .withValue(StatusUpdates.STATUS_TIMESTAMP, timestamp)
+                .withValue(StatusUpdates.PROTOCOL, Im.PROTOCOL_GOOGLE_TALK)
+                .withValue(StatusUpdates.IM_HANDLE, "mrBugDroid1337")
+                .build());
+
+        ContentProviderResult[] results = mResolver.applyBatch(ContactsContract.AUTHORITY, ops);
+        assertNotNull(results[0].uri);
+        return results[0].uri;
+    }
+
+    private void assertRowCount(Uri uri, int count) throws Exception {
+        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
+        ops.add(ContentProviderOperation.newAssertQuery(uri)
+                .withExpectedCount(count)
+                .build());
+
+        mResolver.applyBatch(ContactsContract.AUTHORITY, ops);
+    }
+
+    private void assertPresence(Uri uri, int status) throws Exception {
+        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
+        ops.add(ContentProviderOperation.newAssertQuery(uri)
+                .withValue(StatusUpdates.PRESENCE, status)
+                .withExpectedCount(1)
+                .build());
+
+        mResolver.applyBatch(ContactsContract.AUTHORITY, ops);
+    }
+
+    private void assertStatus(Uri uri, String status) throws Exception {
+        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
+        ops.add(ContentProviderOperation.newAssertQuery(uri)
+                .withValue(StatusUpdates.STATUS, status)
+                .withExpectedCount(1)
+                .build());
+
+        mResolver.applyBatch(ContactsContract.AUTHORITY, ops);
+    }
+
+    private void assertHasTimestamp(Uri uri, boolean hasTimestmap) throws Exception {
+        Cursor cursor = mResolver.query(uri, null, null, null, null);
+        try {
+            assertTrue(cursor.moveToNext());
+
+            if (hasTimestmap) {
+                assertNotNull(cursor.getString(cursor.getColumnIndexOrThrow(
+                        StatusUpdates.STATUS_TIMESTAMP)));
+            } else {
+                assertNull(cursor.getString(cursor.getColumnIndexOrThrow(
+                        StatusUpdates.STATUS_TIMESTAMP)));
+            }
+        } finally {
+            cursor.close();
+        }
+    }
+
+    public void testGetPresencePrecedence() {
+        assertPrecedence(StatusUpdates.AVAILABLE);
+        assertPrecedence(StatusUpdates.AWAY);
+        assertPrecedence(StatusUpdates.DO_NOT_DISTURB);
+        assertPrecedence(StatusUpdates.IDLE);
+        assertPrecedence(StatusUpdates.INVISIBLE);
+        assertPrecedence(StatusUpdates.OFFLINE);
+    }
+
+    private void assertPrecedence(int status) {
+        assertTrue(StatusUpdates.getPresencePrecedence(status) >= 0);
+    }
+
+    public void testGetPresenceIconresourceId() {
+        assertResource(StatusUpdates.AVAILABLE);
+        assertResource(StatusUpdates.AWAY);
+        assertResource(StatusUpdates.DO_NOT_DISTURB);
+        assertResource(StatusUpdates.IDLE);
+        assertResource(StatusUpdates.INVISIBLE);
+        assertResource(StatusUpdates.OFFLINE);
+    }
+
+    private void assertResource(int status) {
+        assertTrue(0 != StatusUpdates.getPresenceIconResourceId(status));
+    }
+}
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_StreamItemsTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_StreamItemsTest.java
new file mode 100644
index 0000000..5ca04ab
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_StreamItemsTest.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider.cts;
+
+import android.content.ContentProviderOperation;
+import android.content.ContentProviderResult;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.RawContacts;
+import android.provider.ContactsContract.StreamItems;
+import android.test.AndroidTestCase;
+
+import java.util.ArrayList;
+
+public class ContactsContract_StreamItemsTest extends AndroidTestCase {
+
+    private static final String ACCOUNT_TYPE = "com.android.cts";
+    private static final String ACCOUNT_NAME = "ContactsContract_StreamItemsTest";
+
+    private static final String INSERT_TEXT = "Wrote a test for the StreamItems class";
+    private static final long INSERT_TIMESTAMP = 3007;
+    private static final String INSERT_COMMENTS = "1337 people reshared this";
+
+    private static final String UPDATE_TEXT = "Wrote more tests for the StreamItems class";
+    private static final long UPDATE_TIMESTAMP = 8008;
+    private static final String UPDATE_COMMENTS = "3007 people reshared this";
+
+    private ContentResolver mResolver;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mResolver = mContext.getContentResolver();
+    }
+
+    public void testContentDirectoryUri() throws Exception {
+        // Create a contact to attach the stream item to it.
+        ContentValues values = new ContentValues();
+        values.put(RawContacts.ACCOUNT_TYPE, ACCOUNT_TYPE);
+        values.put(RawContacts.ACCOUNT_NAME, ACCOUNT_NAME);
+
+        Uri contactUri = mResolver.insert(RawContacts.CONTENT_URI, values);
+        long rawContactId = ContentUris.parseId(contactUri);
+        assertTrue(rawContactId != -1);
+
+        // Attach a stream item to the contact.
+        values.clear();
+        values.put(RawContacts.ACCOUNT_TYPE, ACCOUNT_TYPE);
+        values.put(RawContacts.ACCOUNT_NAME, ACCOUNT_NAME);
+        values.put(StreamItems.TEXT, INSERT_TEXT);
+        values.put(StreamItems.TIMESTAMP, INSERT_TIMESTAMP);
+        values.put(StreamItems.COMMENTS, INSERT_COMMENTS);
+
+        Uri contactStreamUri = Uri.withAppendedPath(
+                ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId),
+                RawContacts.StreamItems.CONTENT_DIRECTORY);
+        Uri streamItemUri = mResolver.insert(contactStreamUri, values);
+        long streamItemId = ContentUris.parseId(streamItemUri);
+        assertTrue(streamItemId != -1);
+
+        // Check that the provider returns the stream id in it's URI.
+        assertEquals(streamItemUri,
+                ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId).buildUpon()
+                        .appendPath(RawContacts.StreamItems.CONTENT_DIRECTORY)
+                        .appendPath(Long.toString(streamItemId))
+                        .build());
+
+        // Check that the provider stored what we put into it.
+        assertInsertedItem(streamItemUri);
+
+        // Update the stream item.
+        values.clear();
+        values.put(Data.RAW_CONTACT_ID, rawContactId);
+        values.put(RawContacts.ACCOUNT_TYPE, ACCOUNT_TYPE);
+        values.put(RawContacts.ACCOUNT_NAME, ACCOUNT_NAME);
+        values.put(StreamItems.TEXT, UPDATE_TEXT);
+        values.put(StreamItems.TIMESTAMP, UPDATE_TIMESTAMP);
+        values.put(StreamItems.COMMENTS, UPDATE_COMMENTS);
+
+        assertEquals(1, mResolver.update(streamItemUri, values, null, null));
+        assertUpdatedItem(streamItemUri);
+    }
+
+    public void testContentUri() throws Exception {
+        // Create a contact with one stream item in it.
+        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
+
+        ops.add(ContentProviderOperation.newInsert(RawContacts.CONTENT_URI)
+                .withValue(RawContacts.ACCOUNT_TYPE, ACCOUNT_TYPE)
+                .withValue(RawContacts.ACCOUNT_NAME, ACCOUNT_NAME)
+                .build());
+
+        ops.add(ContentProviderOperation.newInsert(StreamItems.CONTENT_URI)
+                .withValueBackReference(Data.RAW_CONTACT_ID, 0)
+                .withValue(RawContacts.ACCOUNT_TYPE, ACCOUNT_TYPE)
+                .withValue(RawContacts.ACCOUNT_NAME, ACCOUNT_NAME)
+                .withValue(StreamItems.TEXT, INSERT_TEXT)
+                .withValue(StreamItems.TIMESTAMP, INSERT_TIMESTAMP)
+                .withValue(StreamItems.COMMENTS, INSERT_COMMENTS)
+                .build());
+
+        ContentProviderResult[] results = mResolver.applyBatch(ContactsContract.AUTHORITY, ops);
+        long rawContactId = ContentUris.parseId(results[0].uri);
+        assertTrue(rawContactId != -1);
+
+        Uri streamItemUri = results[1].uri;
+        long streamItemId = ContentUris.parseId(streamItemUri);
+        assertTrue(streamItemId != -1);
+
+        // Check that the provider returns the stream id in it's URI.
+        assertEquals(streamItemUri,
+                ContentUris.withAppendedId(StreamItems.CONTENT_URI, streamItemId));
+
+        // Check that the provider stored what we put into it.
+        assertInsertedItem(streamItemUri);
+
+        // Update the stream item.
+        ops.clear();
+        ops.add(ContentProviderOperation.newUpdate(streamItemUri)
+                .withValue(Data.RAW_CONTACT_ID, rawContactId)
+                .withValue(RawContacts.ACCOUNT_TYPE, ACCOUNT_TYPE)
+                .withValue(RawContacts.ACCOUNT_NAME, ACCOUNT_NAME)
+                .withValue(StreamItems.TEXT, UPDATE_TEXT)
+                .withValue(StreamItems.TIMESTAMP, UPDATE_TIMESTAMP)
+                .withValue(StreamItems.COMMENTS, UPDATE_COMMENTS)
+                .build());
+
+        results = mResolver.applyBatch(ContactsContract.AUTHORITY, ops);
+        assertEquals(Integer.valueOf(1), results[0].count);
+        assertUpdatedItem(streamItemUri);
+    }
+
+    private void assertInsertedItem(Uri itemUri) {
+        assertStreamItem(itemUri, INSERT_TEXT, INSERT_TIMESTAMP, INSERT_COMMENTS);
+    }
+
+    private void assertUpdatedItem(Uri itemUri) {
+        assertStreamItem(itemUri, UPDATE_TEXT, UPDATE_TIMESTAMP, UPDATE_COMMENTS);
+    }
+
+    private void assertStreamItem(Uri uri, String text, long timestamp, String comments) {
+        Cursor cursor = mResolver.query(uri, null, null, null, null);
+        try {
+            assertTrue(cursor.moveToFirst());
+            assertEquals(text, cursor.getString(
+                    cursor.getColumnIndexOrThrow(StreamItems.TEXT)));
+            assertEquals(timestamp, cursor.getLong(
+                    cursor.getColumnIndexOrThrow(StreamItems.TIMESTAMP)));
+            assertEquals(comments, cursor.getString(
+                    cursor.getColumnIndexOrThrow(StreamItems.COMMENTS)));
+        } finally {
+            cursor.close();
+        }
+    }
+}
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_TestDataBuilder.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_TestDataBuilder.java
index c73830e..e1feda6 100644
--- a/tests/tests/provider/src/android/provider/cts/ContactsContract_TestDataBuilder.java
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_TestDataBuilder.java
@@ -198,6 +198,10 @@
             return mCursor.getLong(mCursor.getColumnIndex(columnName));
         }
 
+        public String getString(String columnName) {
+            return mCursor.getString(mCursor.getColumnIndex(columnName));
+        }
+
         public void assertColumn(String columnName, long value) {
             assertEquals(value, mCursor.getLong(getColumnIndex(columnName)));
         }
diff --git a/tests/tests/provider/src/android/provider/cts/Contacts_PeopleTest.java b/tests/tests/provider/src/android/provider/cts/Contacts_PeopleTest.java
index 0f36626..b9d26e6 100644
--- a/tests/tests/provider/src/android/provider/cts/Contacts_PeopleTest.java
+++ b/tests/tests/provider/src/android/provider/cts/Contacts_PeopleTest.java
@@ -40,6 +40,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.List;
 
 @TestTargetClass(android.provider.Contacts.People.class)
 public class Contacts_PeopleTest extends InstrumentationTestCase {
@@ -209,9 +210,16 @@
             cursor.close();
             mRowsAdded.add(People.addToGroup(mContentResolver, personId, groupId));
             cursor = People.queryGroups(mContentResolver, personId);
-            cursor.moveToFirst();
-            assertEquals(personId, cursor.getInt(MEMBERSHIP_PERSON_ID_INDEX));
-            assertEquals(groupId, cursor.getInt(MEMBERSHIP_GROUP_ID_INDEX));
+            boolean found = false;
+            while (cursor.moveToNext()) {
+                assertEquals(personId, cursor.getInt(MEMBERSHIP_PERSON_ID_INDEX));
+                if (cursor.getInt(MEMBERSHIP_GROUP_ID_INDEX) == groupId) {
+                    found = true;
+                    break;
+                }
+            }
+            assertTrue(found);
+
             cursor.close();
 
             // People: test_people_2, Group: test_group_1
@@ -223,14 +231,24 @@
             String groupName = "test_group_1";
             mRowsAdded.add(People.addToGroup(mContentResolver, personId, groupName));
             cursor = People.queryGroups(mContentResolver, personId);
-            cursor.moveToFirst();
-            assertEquals(personId, cursor.getInt(MEMBERSHIP_PERSON_ID_INDEX));
-            groupId = cursor.getInt(MEMBERSHIP_GROUP_ID_INDEX);
+            List<Integer> groupIds = new ArrayList<Integer>();
+            while (cursor.moveToNext()) {
+                assertEquals(personId, cursor.getInt(MEMBERSHIP_PERSON_ID_INDEX));
+                groupIds.add(cursor.getInt(MEMBERSHIP_GROUP_ID_INDEX));
+            }
             cursor.close();
-            cursor = mProvider.query(Groups.CONTENT_URI, GROUPS_PROJECTION,
-                    Groups._ID + "=" + groupId, null, null);
-            cursor.moveToFirst();
-            assertEquals(groupName, cursor.getString(GROUPS_NAME_INDEX));
+
+            found = false;
+            for (int id : groupIds) {
+                cursor = mProvider.query(Groups.CONTENT_URI, GROUPS_PROJECTION,
+                        Groups._ID + "=" + id, null, null);
+                cursor.moveToFirst();
+                if (groupName.equals(cursor.getString(GROUPS_NAME_INDEX))) {
+                    found = true;
+                    break;
+                }
+            }
+            assertTrue(found);
             cursor.close();
         } catch (RemoteException e) {
             fail("Unexpected RemoteException");
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStoreTest.java b/tests/tests/provider/src/android/provider/cts/MediaStoreTest.java
index 717b468..7d78bd6 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStoreTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStoreTest.java
@@ -16,10 +16,6 @@
 
 package android.provider.cts;
 
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargetNew;
-
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.database.Cursor;
@@ -27,7 +23,6 @@
 import android.provider.MediaStore;
 import android.test.InstrumentationTestCase;
 
-@TestTargetClass(MediaStore.class)
 public class MediaStoreTest extends InstrumentationTestCase {
     private static final String TEST_VOLUME_NAME = "volume_for_cts";
 
@@ -62,11 +57,7 @@
         super.tearDown();
     }
 
-    @TestTargetNew(
-      level = TestLevel.COMPLETE,
-      method = "getMediaScannerUri",
-      args = {}
-    )
+
     public void testGetMediaScannerUri() {
         ContentValues values = new ContentValues();
         String selection = MediaStore.MEDIA_SCANNER_VOLUME + "=?";
@@ -93,4 +84,9 @@
         assertEquals(1, mContentResolver.delete(mScannerUri, null, null));
         assertNull(mContentResolver.query(mScannerUri, PROJECTION, null, null, null));
     }
+
+    public void testGetVersion() {
+        // Could be a version string or null...just check it doesn't blow up.
+        MediaStore.getVersion(getInstrumentation().getTargetContext());
+    }
 }
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_GenresTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_GenresTest.java
index 4e343cc..1138233 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_GenresTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_GenresTest.java
@@ -16,20 +16,18 @@
 
 package android.provider.cts;
 
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargetNew;
-import dalvik.annotation.ToBeFixed;
-
 import android.content.ContentResolver;
+import android.content.ContentUris;
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.database.SQLException;
 import android.net.Uri;
 import android.provider.MediaStore.Audio.Genres;
+import android.provider.MediaStore.Audio.Media;
+import android.provider.MediaStore.Audio.Genres.Members;
+import android.provider.cts.MediaStoreAudioTestHelper.Audio1;
 import android.test.InstrumentationTestCase;
 
-@TestTargetClass(Genres.class)
 public class MediaStore_Audio_GenresTest extends InstrumentationTestCase {
     private ContentResolver mContentResolver;
 
@@ -40,14 +38,6 @@
         mContentResolver = getInstrumentation().getContext().getContentResolver();
     }
 
-    @TestTargetNew(
-      level = TestLevel.COMPLETE,
-      method = "getContentUri",
-      args = {String.class}
-    )
-    @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete. There is no "
-            + "document related to the possible values of param volumeName. @throw clause "
-            + "should be added in to javadoc when getting uri for internal volume.")
     public void testGetContentUri() {
         assertNotNull(mContentResolver.query(
                 Genres.getContentUri(MediaStoreAudioTestHelper.EXTERNAL_VOLUME_NAME), null, null,
@@ -103,4 +93,44 @@
         Uri uri = mContentResolver.insert(Genres.INTERNAL_CONTENT_URI, values);
         assertNull(uri);
     }
+
+    public void testGetContentUriForAudioId() {
+        // Insert an audio file into the content provider.
+        ContentValues values = Audio1.getInstance().getContentValues(true);
+        Uri audioUri = mContentResolver.insert(Media.EXTERNAL_CONTENT_URI, values);
+        long audioId = ContentUris.parseId(audioUri);
+        assertTrue(audioId != -1);
+
+        // Insert a genre into the content provider.
+        values.clear();
+        values.put(Genres.NAME, "Soda Pop");
+        Uri genreUri = mContentResolver.insert(Genres.EXTERNAL_CONTENT_URI, values);
+        long genreId = ContentUris.parseId(genreUri);
+        assertTrue(genreId != -1);
+
+        Cursor cursor = null;
+        try {
+            String volumeName = MediaStoreAudioTestHelper.EXTERNAL_VOLUME_NAME;
+
+            // Check that the audio file has no genres yet.
+            Uri audioGenresUri = Genres.getContentUriForAudioId(volumeName, (int) audioId);
+            cursor = mContentResolver.query(audioGenresUri, null, null, null, null);
+            assertFalse(cursor.moveToNext());
+
+            // Link the audio file to the genre.
+            values.clear();
+            values.put(Members.AUDIO_ID, audioId);
+            Uri membersUri = Members.getContentUri(volumeName, genreId);
+            assertNotNull(mContentResolver.insert(membersUri, values));
+
+            // Check that the audio file has the genre it was linked to.
+            cursor = mContentResolver.query(audioGenresUri, null, null, null, null);
+            assertTrue(cursor.moveToNext());
+            assertEquals(genreId, cursor.getLong(cursor.getColumnIndex(Genres._ID)));
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+    }
 }
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java
new file mode 100644
index 0000000..9432066
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider.cts;
+
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.MediaStore;
+import android.provider.MediaStore.MediaColumns;
+import android.test.AndroidTestCase;
+
+public class MediaStore_FilesTest extends AndroidTestCase {
+
+    private ContentResolver mResolver;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mResolver = mContext.getContentResolver();
+    }
+
+    public void testGetContentUri() {
+        String volumeName = MediaStoreAudioTestHelper.EXTERNAL_VOLUME_NAME;
+        Uri allFilesUri = MediaStore.Files.getContentUri(volumeName);
+
+        // Get the current file count. We will check if this increases after
+        // adding a file to the provider.
+        int fileCount = getFileCount(allFilesUri);
+
+        // Check that inserting empty values causes an exception.
+        ContentValues values = new ContentValues();
+        try {
+            mResolver.insert(allFilesUri, values);
+            fail("Should throw an exception");
+        } catch (IllegalArgumentException e) {
+            // Expecting an exception
+        }
+
+        // Add a path for a file and check that the returned uri appends a
+        // path properly.
+        String dataPath = "does_not_really_exist.txt";
+        values.put(MediaColumns.DATA, dataPath);
+        Uri fileUri = mResolver.insert(allFilesUri, values);
+        long fileId = ContentUris.parseId(fileUri);
+        assertEquals(fileUri, ContentUris.withAppendedId(allFilesUri, fileId));
+
+        // Check that getContentUri with the file id produces the same url
+        Uri rowUri = MediaStore.Files.getContentUri(volumeName, fileId);
+        assertEquals(fileUri, rowUri);
+
+        // Check that the file count has increased.
+        int newFileCount = getFileCount(allFilesUri);
+        assertEquals(fileCount + 1, newFileCount);
+
+        // Check that the path we inserted was stored properly.
+        assertStringColumn(fileUri, MediaColumns.DATA, dataPath);
+
+        // Update the path and check that the database changed.
+        String updatedPath = "still_does_not_exist.txt";
+        values.put(MediaColumns.DATA, updatedPath);
+        assertEquals(1, mResolver.update(fileUri, values, null, null));
+        assertStringColumn(fileUri, MediaColumns.DATA, updatedPath);
+
+        // Delete the file and observe that the file count decreased.
+        assertEquals(1, mResolver.delete(fileUri, null, null));
+        assertEquals(fileCount, getFileCount(allFilesUri));
+
+        // Make sure the deleted file is not returned by the cursor.
+        Cursor cursor = mResolver.query(fileUri, null, null, null, null);
+        try {
+            assertFalse(cursor.moveToNext());
+        } finally {
+            cursor.close();
+        }
+    }
+
+    private int getFileCount(Uri uri) {
+        Cursor cursor = mResolver.query(uri, null, null, null, null);
+        try {
+            return cursor.getCount();
+        } finally {
+            cursor.close();
+        }
+    }
+
+    private void assertStringColumn(Uri fileUri, String columnName, String expectedValue) {
+        Cursor cursor = mResolver.query(fileUri, null, null, null, null);
+        try {
+            assertTrue(cursor.moveToNext());
+            int index = cursor.getColumnIndexOrThrow(columnName);
+            assertEquals(expectedValue, cursor.getString(index));
+        } finally {
+            cursor.close();
+        }
+    }
+}
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Images_MediaTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Images_MediaTest.java
index 8e8d650..5203326 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Images_MediaTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Images_MediaTest.java
@@ -18,11 +18,6 @@
 
 import com.android.cts.stub.R;
 
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargetNew;
-import dalvik.annotation.TestTargets;
-
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
@@ -31,18 +26,14 @@
 import android.graphics.BitmapFactory;
 import android.net.Uri;
 import android.os.Environment;
-import android.provider.MediaStore;
 import android.provider.MediaStore.Images.Media;
 import android.provider.MediaStore.Images.Thumbnails;
 import android.test.InstrumentationTestCase;
 
 import java.io.File;
 import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
 import java.util.ArrayList;
 
-@TestTargetClass(MediaStore.Images.Media.class)
 public class MediaStore_Images_MediaTest extends InstrumentationTestCase {
     private static final String MIME_TYPE_JPEG = "image/jpeg";
 
@@ -87,33 +78,7 @@
         mRowsAdded = new ArrayList<Uri>();
     }
 
-    @TestTargets({
-      @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "This test will fail if there is no sdcard attached because the method "
-                    + "{@link Images#Media#insertImage(ContentResolver, String, String, String)} "
-                    + "will store images on the sdcard",
-        method = "insertImage",
-        args = {ContentResolver.class, String.class, String.class, String.class}
-      ),
-      @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        method = "query",
-        args = {ContentResolver.class, Uri.class, String[].class}
-      ),
-      @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        method = "query",
-        args = {ContentResolver.class, Uri.class, String[].class, String.class, String.class}
-      ),
-      @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        method = "query",
-        args = {ContentResolver.class, Uri.class, String[].class,  String.class, String[].class,
-                String.class}
-      )
-    })
-    public void testInsertImageWithImagePath() {
+    public void testInsertImageWithImagePath() throws Exception {
         Cursor c = Media.query(mContentResolver, Media.EXTERNAL_CONTENT_URI, null, null,
                 "_id ASC");
         int previousCount = c.getCount();
@@ -184,21 +149,7 @@
         c.close();
     }
 
-    @TestTargets({
-      @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "This test will fail if there is no sdcard attached because the method "
-                + "will store images on the sdcard",
-        method = "insertImage",
-        args = {ContentResolver.class, Bitmap.class, String.class, String.class}
-      ),
-      @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        method = "getBitmap",
-        args = {ContentResolver.class, Uri.class}
-      )
-    })
-    public void testInsertImageWithBitmap() {
+    public void testInsertImageWithBitmap() throws Exception {
         // insert the image by bitmap
         Bitmap src = BitmapFactory.decodeResource(mContext.getResources(), R.raw.scenery);
         String stringUrl = null;
@@ -215,27 +166,15 @@
                 null, "_id ASC");
         c.moveToFirst();
         // get the bimap by the path
-        Bitmap result = null;
-        try {
-            result = Media.getBitmap(mContentResolver,
+        Bitmap result = Media.getBitmap(mContentResolver,
                     Uri.fromFile(new File(c.getString(c.getColumnIndex(Media.DATA)))));
-        } catch (FileNotFoundException e) {
-            fail(e.getMessage());
-        } catch (IOException e) {
-            fail(e.getMessage());
-        }
+
         // can not check the identity between the result and source bitmap because
         // source bitmap is compressed before it is saved as result bitmap
-        assertNotNull(result);
         assertEquals(src.getWidth(), result.getWidth());
         assertEquals(src.getHeight(), result.getHeight());
     }
 
-    @TestTargetNew(
-      level = TestLevel.COMPLETE,
-      method = "getContentUri",
-      args = {String.class}
-    )
     public void testGetContentUri() {
         assertNotNull(mContentResolver.query(Media.getContentUri("internal"), null, null, null,
                 null));
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Images_ThumbnailsTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Images_ThumbnailsTest.java
index 98ad62e..7ec7937 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Images_ThumbnailsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Images_ThumbnailsTest.java
@@ -18,11 +18,6 @@
 
 import com.android.cts.stub.R;
 
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargetNew;
-import dalvik.annotation.TestTargets;
-
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
@@ -31,15 +26,12 @@
 import android.graphics.BitmapFactory;
 import android.net.Uri;
 import android.os.Environment;
-import android.provider.MediaStore;
 import android.provider.MediaStore.Images.Media;
 import android.provider.MediaStore.Images.Thumbnails;
 import android.test.InstrumentationTestCase;
-import android.util.Log;
 
 import java.util.ArrayList;
 
-@TestTargetClass(MediaStore.Images.Thumbnails.class)
 public class MediaStore_Images_ThumbnailsTest extends InstrumentationTestCase {
     private ArrayList<Uri> mRowsAdded;
 
@@ -75,19 +67,7 @@
         mRowsAdded = new ArrayList<Uri>();
     }
 
-    @TestTargets({
-      @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        method = "queryMiniThumbnails",
-        args = {ContentResolver.class, Uri.class, int.class, String[].class}
-      ),
-      @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        method = "query",
-        args = {ContentResolver.class, Uri.class, String[].class}
-      )
-    })
-    public void testQueryInternalThumbnails() {
+    public void testQueryInternalThumbnails() throws Exception {
         Cursor c = Thumbnails.queryMiniThumbnails(mContentResolver,
                 Thumbnails.INTERNAL_CONTENT_URI, Thumbnails.MICRO_KIND, null);
         int previousMicroKindCount = c.getCount();
@@ -125,18 +105,6 @@
         c.close();
     }
 
-    @TestTargets({
-      @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        method = "queryMiniThumbnail",
-        args = {ContentResolver.class, long.class, int.class, String[].class}
-      ),
-      @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        method = "query",
-        args = {ContentResolver.class, Uri.class, String[].class}
-      )
-    })
     public void testQueryExternalMiniThumbnails() {
         // insert the image by bitmap
         Bitmap src = BitmapFactory.decodeResource(mContext.getResources(), R.raw.scenery);
@@ -174,11 +142,6 @@
         c.close();
     }
 
-    @TestTargetNew(
-      level = TestLevel.COMPLETE,
-      method = "getContentUri",
-      args = {String.class}
-    )
     public void testGetContentUri() {
         assertNotNull(mContentResolver.query(Thumbnails.getContentUri("internal"), null, null,
                 null, null));
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_VideoTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_VideoTest.java
index 31d9f2c..366fc57 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_VideoTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_VideoTest.java
@@ -18,23 +18,17 @@
 
 import com.android.cts.stub.R;
 
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargetNew;
-
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
 import android.database.Cursor;
 import android.net.Uri;
-import android.provider.MediaStore;
 import android.provider.MediaStore.Video;
 import android.provider.MediaStore.Video.VideoColumns;
 import android.test.InstrumentationTestCase;
 
 import java.util.ArrayList;
 
-@TestTargetClass(MediaStore.Video.class)
 public class MediaStore_VideoTest extends InstrumentationTestCase {
     private static final String TEST_VIDEO_3GP = "testVideo.3gp";
 
@@ -64,12 +58,7 @@
         mRowsAdded = new ArrayList<Uri>();
     }
 
-    @TestTargetNew(
-      level = TestLevel.COMPLETE,
-      method = "query",
-      args = {ContentResolver.class, Uri.class, String[].class}
-    )
-    public void testQuery() {
+    public void testQuery() throws Exception {
         ContentValues values = new ContentValues();
         String valueOfData = mHelper.copy(R.raw.testvideo, TEST_VIDEO_3GP);
         values.put(VideoColumns.DATA, valueOfData);
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Video_ThumbnailsTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Video_ThumbnailsTest.java
new file mode 100644
index 0000000..935b255
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Video_ThumbnailsTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider.cts;
+
+import com.android.cts.stub.R;
+
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Environment;
+import android.provider.MediaStore.Video.Media;
+import android.provider.MediaStore.Video.Thumbnails;
+import android.provider.MediaStore.Video.VideoColumns;
+import android.test.AndroidTestCase;
+
+import java.io.File;
+import java.io.IOException;
+
+public class MediaStore_Video_ThumbnailsTest extends AndroidTestCase {
+
+    private ContentResolver mResolver;
+
+    private FileCopyHelper mFileHelper;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mResolver = mContext.getContentResolver();
+        mFileHelper = new FileCopyHelper(mContext);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mFileHelper.clear();
+        super.tearDown();
+    }
+
+    public void testGetContentUri() {
+        Uri internalUri = Thumbnails.getContentUri(MediaStoreAudioTestHelper.INTERNAL_VOLUME_NAME);
+        Uri externalUri = Thumbnails.getContentUri(MediaStoreAudioTestHelper.EXTERNAL_VOLUME_NAME);
+        assertEquals(Thumbnails.INTERNAL_CONTENT_URI, internalUri);
+        assertEquals(Thumbnails.EXTERNAL_CONTENT_URI, externalUri);
+    }
+
+    public void testGetThumbnail() throws Exception {
+        // Insert a video into the provider.
+        Uri videoUri = insertVideo();
+        long videoId = ContentUris.parseId(videoUri);
+        assertTrue(videoId != -1);
+        assertEquals(ContentUris.withAppendedId(Media.EXTERNAL_CONTENT_URI, videoId),
+                videoUri);
+
+        // Get the current thumbnail count for future comparison.
+        int count = getThumbnailCount(Thumbnails.EXTERNAL_CONTENT_URI);
+
+        // Calling getThumbnail should generate a new thumbnail.
+        assertNotNull(Thumbnails.getThumbnail(mResolver, videoId, Thumbnails.MINI_KIND, null));
+        assertNotNull(Thumbnails.getThumbnail(mResolver, videoId, Thumbnails.MICRO_KIND, null));
+
+        try {
+            Thumbnails.getThumbnail(mResolver, videoId, Thumbnails.FULL_SCREEN_KIND, null);
+            fail();
+        } catch (IllegalArgumentException e) {
+            // Full screen thumbnails not supported by getThumbnail...
+        }
+
+        // Check that an additional thumbnails have been registered.
+        int count2 = getThumbnailCount(Thumbnails.EXTERNAL_CONTENT_URI);
+        assertTrue(count2 > count);
+    }
+
+    private Uri insertVideo() throws IOException {
+        File file = new File(Environment.getExternalStorageDirectory(), "testVideo.3gp");
+        mFileHelper.copyToExternalStorage(R.raw.testvideo, file);
+
+        ContentValues values = new ContentValues();
+        values.put(VideoColumns.DATA, file.getAbsolutePath());
+        return mResolver.insert(Media.EXTERNAL_CONTENT_URI, values);
+    }
+
+    private int getThumbnailCount(Uri uri) {
+        Cursor cursor = mResolver.query(uri, null, null, null, null);
+        try {
+            return cursor.getCount();
+        } finally {
+            cursor.close();
+        }
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/PackageSignatureTest.java b/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
index 3822035..f278b0f 100644
--- a/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
+++ b/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
@@ -83,7 +83,13 @@
             "android.tests.devicesetup",
 
             // APK for the Android core tests runner used only during CTS
-            "android.core.tests.runner"
+            "android.core.tests.runner",
+
+            // Wifi test utility used by Tradefed...
+            "com.android.tradefed.utils.wifi",
+
+            // Game used for CTS testing...
+            "com.replica.replicaisland"
             ));
 
     private boolean isWhitelistedPackage(String packageName) {
diff --git a/tests/tests/security/src/android/security/cts/VoldExploitTest.java b/tests/tests/security/src/android/security/cts/VoldExploitTest.java
index ab14f12..d4ea884 100644
--- a/tests/tests/security/src/android/security/cts/VoldExploitTest.java
+++ b/tests/tests/security/src/android/security/cts/VoldExploitTest.java
@@ -269,12 +269,18 @@
 
     /**
      * Poll /proc/net/netlink until all the "Rmem" fields contain
-     * "0".  This indicates that there are no outstanding unreceived
-     * netlink messages.
+     * "0" or approximately 10 seconds have passed.
+     *
+     * This indicates that either the netlink message was received,
+     * or the process took too long to process the incoming netlink
+     * message.
+     *
+     * See http://code.google.com/p/android/issues/detail?id=25099
+     * for information on why the timeout is needed.
      */
     private static void confirmNetlinkMsgReceived() {
         try {
-            while(true) {
+            for (int ct = 0; ct < 200; ct++) {
                 boolean foundAllZeros = true;
                 for (List<String> i : parseNetlink()) {
                     // Column 5 is the "Rmem" field, which is the
diff --git a/tests/tests/telephony/src/android/telephony/cts/PhoneNumberUtilsTest.java b/tests/tests/telephony/src/android/telephony/cts/PhoneNumberUtilsTest.java
index 1c45735..23891e0 100644
--- a/tests/tests/telephony/src/android/telephony/cts/PhoneNumberUtilsTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/PhoneNumberUtilsTest.java
@@ -455,11 +455,6 @@
 
         // Test isWellFormedSmsAddress
         assertTrue(PhoneNumberUtils.isWellFormedSmsAddress("+17005554141"));
-        // KT allow a to be a dialable character, the network portion of 'android' is 'a'
-        if (TelephonyUtils.isKt(tm)) {
-            assertTrue(PhoneNumberUtils.isWellFormedSmsAddress("android"));
-        } else {
-            assertFalse(PhoneNumberUtils.isWellFormedSmsAddress("android"));
-        }
+        assertFalse(PhoneNumberUtils.isWellFormedSmsAddress("android"));
     }
 }
diff --git a/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java b/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java
index c0c26ef..6c9a152 100755
--- a/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java
@@ -84,7 +84,8 @@
                     "302370",   // Fido
                     "30237",    // Fido
                     "311490",   // Virgin Mobile
-                    "310000"    // Tracfone
+                    "310000",   // Tracfone
+                    "46003"     // China Telecom
             );
 
     // List of network operators that doesn't support Data(binary) SMS message
@@ -158,19 +159,24 @@
         assertNotNull(dividedMessages);
         int numParts;
         if (TelephonyUtils.isSkt(mTelephonyManager)) {
-            numParts = 5;
+            assertTrue(isComplete(dividedMessages, 5) || isComplete(dividedMessages, 3));
         } else if (TelephonyUtils.isKt(mTelephonyManager)) {
-            numParts = 4;
+            assertTrue(isComplete(dividedMessages, 4) || isComplete(dividedMessages, 3));
         } else {
-            numParts = 3;
+            assertTrue(isComplete(dividedMessages, 3));
         }
-        assertEquals(numParts, dividedMessages.size());
+    }
+
+    private boolean isComplete(List<String> dividedMessages, int numParts) {
+        if (dividedMessages.size() != numParts) {
+            return false;
+        }
 
         String actualMessage = "";
         for (int i = 0; i < numParts; i++) {
             actualMessage += dividedMessages.get(i);
         }
-        assertEquals(LONG_TEXT, actualMessage);
+        return LONG_TEXT.equals(actualMessage);
     }
 
     @TestTargets({
diff --git a/tests/tests/telephony/src/android/telephony/cts/SmsMessageTest.java b/tests/tests/telephony/src/android/telephony/cts/SmsMessageTest.java
index 27f290b..4b5b55a 100644
--- a/tests/tests/telephony/src/android/telephony/cts/SmsMessageTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/SmsMessageTest.java
@@ -65,6 +65,8 @@
     private static final int STATUS_ON_ICC_DEF = -1;
     private static final int TPLAYER_LENGTH_FOR_PDU = 23;
     private static final long TIMESTAMP_MILLIS = 1149631383000l;
+    private static final int SEPTETS_SKT = 80;
+    private static final int SEPTETS_KT = 90;
 
     @Override
     protected void setUp() throws Exception {
@@ -188,7 +190,7 @@
         int[] result = SmsMessage.calculateLength(sms.getMessageBody(), true);
         assertEquals(SMS_NUMBER1, result[0]);
         assertEquals(sms.getMessageBody().length(), result[1]);
-        assertEquals(getNumSeptets() - sms.getMessageBody().length(), result[2]);
+        assertRemaining(sms.getMessageBody().length(), result[2]);
         assertEquals(SmsMessage.ENCODING_7BIT, result[3]);
         assertEquals(pdu, toHexString(sms.getPdu()));
 
@@ -220,7 +222,7 @@
         result = SmsMessage.calculateLength(msgBody, false);
         assertEquals(SMS_NUMBER2, result[0]);
         assertEquals(sms.getMessageBody().length(), result[1]);
-        assertEquals(getNumSeptets() - sms.getMessageBody().length(), result[2]);
+        assertRemaining(sms.getMessageBody().length(), result[2]);
         assertEquals(SmsMessage.ENCODING_7BIT, result[3]);
 
         // Test createFromPdu Ucs to Sms
@@ -231,20 +233,26 @@
         result = SmsMessage.calculateLength(sms.getMessageBody(), true);
         assertEquals(SMS_NUMBER3, result[0]);
         assertEquals(sms.getMessageBody().length(), result[1]);
-        assertEquals(getNumSeptets() - sms.getMessageBody().length(), result[2]);
+        assertRemaining(sms.getMessageBody().length(), result[2]);
         assertEquals(SmsMessage.ENCODING_7BIT, result[3]);
     }
 
-    private int getNumSeptets() {
+    private void assertRemaining(int messageLength, int remaining) {
         if (TelephonyUtils.isSkt(mTelephonyManager)) {
-            return 80;
+            assertTrue(checkRemaining(SEPTETS_SKT, messageLength, remaining)
+                    || checkRemaining(SmsMessage.MAX_USER_DATA_SEPTETS, messageLength, remaining));
         } else if (TelephonyUtils.isKt(mTelephonyManager)) {
-            return 90;
+            assertTrue(checkRemaining(SEPTETS_KT, messageLength, remaining)
+                    || checkRemaining(SmsMessage.MAX_USER_DATA_SEPTETS, messageLength, remaining));
         } else {
-            return SmsMessage.MAX_USER_DATA_SEPTETS;
+            assertTrue(checkRemaining(SmsMessage.MAX_USER_DATA_SEPTETS, messageLength, remaining));
         }
     }
 
+    private boolean checkRemaining(int total, int messageLength, int remaining) {
+        return total - messageLength == remaining;
+    }
+
     @TestTargets({
         @TestTargetNew(
             level = TestLevel.COMPLETE,
diff --git a/tests/tests/text/src/android/text/cts/TextUtilsTest.java b/tests/tests/text/src/android/text/cts/TextUtilsTest.java
index 2e675ff..e85424f 100755
--- a/tests/tests/text/src/android/text/cts/TextUtilsTest.java
+++ b/tests/tests/text/src/android/text/cts/TextUtilsTest.java
@@ -1197,7 +1197,7 @@
     @ToBeFixed(bug = "1695243", explanation = "the javadoc for htmlEncode() is incomplete." +
             "1. doesn't discuss the case that parameter is expectional.")
     public void testHtmlEncode() {
-        assertEquals("&lt;_html_&gt;\\ &amp;&quot;&apos;string&apos;&quot;",
+        assertEquals("&lt;_html_&gt;\\ &amp;&quot;&#39;string&#39;&quot;",
                 TextUtils.htmlEncode("<_html_>\\ &\"'string'\""));
 
          try {
diff --git a/tests/tests/textureview/Android.mk b/tests/tests/textureview/Android.mk
new file mode 100644
index 0000000..d379e66
--- /dev/null
+++ b/tests/tests/textureview/Android.mk
@@ -0,0 +1,32 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+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_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsTextureViewTestCases
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/tests/tests/textureview/AndroidManifest.xml b/tests/tests/textureview/AndroidManifest.xml
new file mode 100644
index 0000000..0ed1d46
--- /dev/null
+++ b/tests/tests/textureview/AndroidManifest.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.cts.textureview"
+    >
+
+    <uses-feature android:glEsVersion="0x00020000" android:required="true" />
+    <uses-permission android:name="android.permission.GET_TASKS" />
+    <uses-permission android:name="android.permission.REORDER_TASKS" />
+    <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
+
+    <instrumentation
+        android:targetPackage="com.android.cts.textureview"
+        android:name="android.test.InstrumentationTestRunner" />
+
+    <application
+        android:label="@string/app_name"
+        android:hardwareAccelerated="true">
+        <activity
+            android:name="android.textureview.cts.TextureViewTestActivity"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+</manifest>
diff --git a/tests/tests/textureview/res/values/strings.xml b/tests/tests/textureview/res/values/strings.xml
new file mode 100644
index 0000000..f4d9f96
--- /dev/null
+++ b/tests/tests/textureview/res/values/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources>
+    <string name="app_name">TextureViewTest</string>
+</resources>
diff --git a/tests/tests/textureview/src/android/textureview/cts/GLProducerThread.java b/tests/tests/textureview/src/android/textureview/cts/GLProducerThread.java
new file mode 100644
index 0000000..3248597
--- /dev/null
+++ b/tests/tests/textureview/src/android/textureview/cts/GLProducerThread.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.textureview.cts;
+
+import android.graphics.SurfaceTexture;
+import android.opengl.GLUtils;
+
+import java.lang.Thread;
+import java.util.concurrent.Semaphore;
+
+import junit.framework.Assert;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+import javax.microedition.khronos.egl.EGLSurface;
+import javax.microedition.khronos.opengles.GL;
+
+import static android.opengl.GLES20.*;
+
+public class GLProducerThread extends Thread {
+    private Thread mProducerThread;
+    private final int mFrames;
+    private final int mDelayMs;
+    private final Semaphore mSemaphore;
+    private final SurfaceTexture mSurfaceTexture;
+
+    private EGL10 mEgl;
+    private EGLDisplay mEglDisplay = EGL10.EGL_NO_DISPLAY;
+    private EGLContext mEglContext = EGL10.EGL_NO_CONTEXT;
+    private EGLSurface mEglSurface = EGL10.EGL_NO_SURFACE;
+    private GL mGl;
+
+    private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
+    private static final int EGL_OPENGL_ES2_BIT = 4;
+
+    GLProducerThread(SurfaceTexture surfaceTexture, int frames, int delayMs, Semaphore semaphore) {
+        mFrames = frames;
+        mDelayMs = delayMs;
+        mSemaphore = semaphore;
+        mSurfaceTexture = surfaceTexture;
+    }
+
+    private void initGL() {
+        mEgl = (EGL10) EGLContext.getEGL();
+
+        mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+        if (mEglDisplay == EGL10.EGL_NO_DISPLAY) {
+            throw new RuntimeException("eglGetDisplay() failed "
+                                       + GLUtils.getEGLErrorString(mEgl.eglGetError()));
+        }
+
+        int[] version = new int[2];
+        if (!mEgl.eglInitialize(mEglDisplay, version)) {
+            throw new RuntimeException("eglInitialize() failed " +
+                                       GLUtils.getEGLErrorString(mEgl.eglGetError()));
+        }
+
+        int[] configAttribs = {
+            EGL10.EGL_BUFFER_SIZE, 32,
+            EGL10.EGL_ALPHA_SIZE, 8,
+            EGL10.EGL_BLUE_SIZE, 8,
+            EGL10.EGL_GREEN_SIZE, 8,
+            EGL10.EGL_RED_SIZE, 8,
+            EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+            EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT,
+            EGL10.EGL_NONE
+        };
+
+        int[] numConfigs = new int[1];
+        EGLConfig[] configs = new EGLConfig[1];
+        if (!mEgl.eglChooseConfig(mEglDisplay, configAttribs, configs, 1, numConfigs) || numConfigs[0] == 0) {
+            throw new RuntimeException("eglChooseConfig() failed");
+        }
+
+        int[] contextAttribs = {
+            EGL_CONTEXT_CLIENT_VERSION, 2,
+            EGL10.EGL_NONE };
+
+        mEglContext = mEgl.eglCreateContext(mEglDisplay, configs[0], EGL10.EGL_NO_CONTEXT, contextAttribs);
+
+        mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, configs[0], mSurfaceTexture, null);
+
+        if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) {
+            int error = mEgl.eglGetError();
+            if (error == EGL10.EGL_BAD_NATIVE_WINDOW) {
+                throw new RuntimeException("eglCreateWindowSurface() returned EGL_BAD_NATIVE_WINDOW.");
+            }
+            throw new RuntimeException("eglCreateWindowSurface() failed "
+                                       + GLUtils.getEGLErrorString(error));
+        }
+
+        if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
+            throw new RuntimeException("eglMakeCurrent() failed "
+                                       + GLUtils.getEGLErrorString(mEgl.eglGetError()));
+        }
+
+        mGl = mEglContext.getGL();
+    }
+
+    void destroyGL() {
+        mEgl.eglDestroyContext(mEglDisplay, mEglContext);
+        mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
+        mEglContext = EGL10.EGL_NO_CONTEXT;
+        mEglSurface = EGL10.EGL_NO_SURFACE;
+    }
+
+    @Override
+    public void run() {
+        initGL();
+        final int numColors = 4;
+        final float[][] color =
+            { { 1.0f, 0.0f, 0.0f },
+              { 0.0f, 1.0f, 0.0f },
+              { 0.0f, 0.0f, 1.0f },
+              { 1.0f, 1.0f, 1.0f } };
+
+        for (int index = 0, frame = 0;
+             frame < mFrames; index = (index + 1) % numColors, frame++) {
+            glClearColor(color[index][0], color[index][1], color[index][2], 1.0f);
+            glClear(GL_COLOR_BUFFER_BIT);
+            mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
+            Assert.assertEquals(EGL10.EGL_SUCCESS, mEgl.eglGetError());
+            try {
+                sleep(mDelayMs);
+            } catch (InterruptedException e) {
+            }
+        }
+
+        mSemaphore.release();
+        destroyGL();
+    }
+}
diff --git a/tests/tests/textureview/src/android/textureview/cts/TextureViewTest.java b/tests/tests/textureview/src/android/textureview/cts/TextureViewTest.java
new file mode 100644
index 0000000..ee5ab71
--- /dev/null
+++ b/tests/tests/textureview/src/android/textureview/cts/TextureViewTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.textureview.cts;
+
+import android.test.ActivityInstrumentationTestCase2;
+
+public class TextureViewTest extends
+        ActivityInstrumentationTestCase2<TextureViewTestActivity> {
+
+    public TextureViewTest() {
+        super(TextureViewTestActivity.class);
+    }
+
+    public void testTextureViewStress48Hz() {
+        TextureViewTestActivity.mFrames = 600;
+        TextureViewTestActivity.mDelayMs = 1000/48;
+        if (!getActivity().waitForCompletion())
+            fail("Did not complete 48Hz test.");
+    }
+
+    public void testTextureViewStress60Hz() {
+        TextureViewTestActivity.mFrames = 600;
+        TextureViewTestActivity.mDelayMs = 1000/60;
+        if (!getActivity().waitForCompletion())
+            fail("Did not complete 60Hz test.");
+    }
+
+    public void testTextureViewStress70Hz()  {
+        TextureViewTestActivity.mFrames = 600;
+        TextureViewTestActivity.mDelayMs = 1000/70;
+        if (!getActivity().waitForCompletion())
+            fail("Did not complete 70Hz test.");
+    }
+
+    public void testTextureViewStress200Hz() {
+        TextureViewTestActivity.mFrames = 600;
+        TextureViewTestActivity.mDelayMs = 1000/200;
+        if (!getActivity().waitForCompletion())
+            fail("Did not complete 200Hz test.");
+    }
+
+}
diff --git a/tests/tests/textureview/src/android/textureview/cts/TextureViewTestActivity.java b/tests/tests/textureview/src/android/textureview/cts/TextureViewTestActivity.java
new file mode 100644
index 0000000..f2a698b
--- /dev/null
+++ b/tests/tests/textureview/src/android/textureview/cts/TextureViewTestActivity.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.textureview.cts;
+
+import android.animation.ObjectAnimator;
+import android.animation.AnimatorSet;
+import android.app.Activity;
+import android.graphics.SurfaceTexture;
+import android.os.Bundle;
+import android.view.TextureView;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import junit.framework.Assert;
+
+public class TextureViewTestActivity extends Activity implements TextureView.SurfaceTextureListener {
+    public static int mFrames = -1;
+    public static int mDelayMs = -1;
+
+    private TextureView mTexView;
+    private Thread mProducerThread;
+    private final Semaphore mSemaphore = new Semaphore(0);
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Assert.assertTrue(mFrames > 0);
+        Assert.assertTrue(mDelayMs > 0);
+        mTexView = new TextureView(this);
+        mTexView.setSurfaceTextureListener(this);
+        setContentView(mTexView);
+        ObjectAnimator rotate = ObjectAnimator.ofFloat(mTexView, "rotationY", 180);
+        ObjectAnimator fadeIn = ObjectAnimator.ofFloat(mTexView, "alpha", 0.3f, 1f);
+        ObjectAnimator scaleY = ObjectAnimator.ofFloat(mTexView, "scaleY", 0.3f, 1f);
+        AnimatorSet animSet = new AnimatorSet();
+        animSet.play(rotate).with(fadeIn).with(scaleY);
+        animSet.setDuration(mFrames * mDelayMs);
+        animSet.start();
+    }
+
+    public Boolean waitForCompletion() {
+        Boolean success = false;
+        int timeout = mFrames * mDelayMs * 4;
+        try {
+            success = mSemaphore.tryAcquire(timeout, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+            Assert.fail();
+        }
+        return success;
+    }
+
+    @Override
+    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
+        mProducerThread = new GLProducerThread(surface, mFrames, mDelayMs, mSemaphore);
+        mProducerThread.start();
+    }
+
+    @Override
+    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+    }
+
+    @Override
+    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
+        mProducerThread = null;
+        return true;
+    }
+
+    @Override
+    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+    }
+}
diff --git a/tests/tests/view/src/android/view/cts/View_AnimationTest.java b/tests/tests/view/src/android/view/cts/View_AnimationTest.java
index 144e670..d06bf31 100644
--- a/tests/tests/view/src/android/view/cts/View_AnimationTest.java
+++ b/tests/tests/view/src/android/view/cts/View_AnimationTest.java
@@ -161,8 +161,11 @@
                 return mAnimation.hasStarted();
             }
         }.run();
-
-        view.clearAnimation();
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                view.clearAnimation();
+            }
+        });
         Thread.sleep(TIME_OUT);
         assertTrue(mAnimation.hasStarted());
         assertTrue(mAnimation.hasEnded());
diff --git a/tests/tests/view/src/android/view/inputmethod/cts/InputMethodManagerTest.java b/tests/tests/view/src/android/view/inputmethod/cts/InputMethodManagerTest.java
index 92ef3fe..f997c13 100755
--- a/tests/tests/view/src/android/view/inputmethod/cts/InputMethodManagerTest.java
+++ b/tests/tests/view/src/android/view/inputmethod/cts/InputMethodManagerTest.java
@@ -28,7 +28,6 @@
 import android.os.IBinder;
 import android.os.ResultReceiver;
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.UiThreadTest;
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.Window;
@@ -146,16 +145,21 @@
             args = {IBinder.class, int.class, int.class}
         )
     })
-    @UiThreadTest
-    public void testInputMethodManager() {
+    public void testInputMethodManager() throws Throwable {
         Window window = mActivity.getWindow();
-        EditText view = (EditText) window.findViewById(R.id.entry);
-        assertTrue(view.requestFocus());
+        final EditText view = (EditText) window.findViewById(R.id.entry);
+        runTestOnUiThread(new Runnable() {
+           @Override
+            public void run() {
+               view.requestFocus();
+            }
+        });
+        getInstrumentation().waitForIdleSync();
         assertTrue(view.isFocused());
 
         BaseInputConnection connection = new BaseInputConnection(view, false);
         Context context = mInstrumentation.getTargetContext();
-        InputMethodManager imManager = (InputMethodManager) context
+        final InputMethodManager imManager = (InputMethodManager) context
                 .getSystemService(Context.INPUT_METHOD_SERVICE);
         assertTrue(imManager.isActive());
         assertTrue(imManager.isAcceptingText());
@@ -166,34 +170,40 @@
         connection.reportFullscreenMode(true);
         assertTrue(imManager.isFullscreenMode());
 
-        IBinder token = view.getWindowToken();
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                IBinder token = view.getWindowToken();
 
-        // Show and hide input method.
-        assertTrue(imManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT));
-        assertTrue(imManager.hideSoftInputFromWindow(token, 0));
+                // Show and hide input method.
+                assertTrue(imManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT));
+                assertTrue(imManager.hideSoftInputFromWindow(token, 0));
 
-        Handler handler = new Handler();
-        ResultReceiver receiver = new ResultReceiver(handler);
-        assertTrue(imManager.showSoftInput(view, 0, receiver));
-        receiver = new ResultReceiver(handler);
-        assertTrue(imManager.hideSoftInputFromWindow(token, 0, receiver));
+                Handler handler = new Handler();
+                ResultReceiver receiver = new ResultReceiver(handler);
+                assertTrue(imManager.showSoftInput(view, 0, receiver));
+                receiver = new ResultReceiver(handler);
+                assertTrue(imManager.hideSoftInputFromWindow(token, 0, receiver));
 
-        imManager.showSoftInputFromInputMethod(token, InputMethodManager.SHOW_FORCED);
-        imManager.hideSoftInputFromInputMethod(token, InputMethodManager.HIDE_NOT_ALWAYS);
+                imManager.showSoftInputFromInputMethod(token, InputMethodManager.SHOW_FORCED);
+                imManager.hideSoftInputFromInputMethod(token, InputMethodManager.HIDE_NOT_ALWAYS);
 
-        // status: hide to show to hide
-        imManager.toggleSoftInputFromWindow(token, 0, InputMethodManager.HIDE_NOT_ALWAYS);
-        imManager.toggleSoftInputFromWindow(token, 0, InputMethodManager.HIDE_NOT_ALWAYS);
+                // status: hide to show to hide
+                imManager.toggleSoftInputFromWindow(token, 0, InputMethodManager.HIDE_NOT_ALWAYS);
+                imManager.toggleSoftInputFromWindow(token, 0, InputMethodManager.HIDE_NOT_ALWAYS);
 
-        List<InputMethodInfo> enabledImList = imManager.getEnabledInputMethodList();
-        if (enabledImList != null && enabledImList.size() > 0) {
-            imManager.setInputMethod(token, enabledImList.get(0).getId());
-            // cannot test whether setting was successful
-        }
+                List<InputMethodInfo> enabledImList = imManager.getEnabledInputMethodList();
+                if (enabledImList != null && enabledImList.size() > 0) {
+                    imManager.setInputMethod(token, enabledImList.get(0).getId());
+                    // cannot test whether setting was successful
+                }
 
-        List<InputMethodInfo> imList = imManager.getInputMethodList();
-        if (imList != null && enabledImList != null) {
-            assertTrue(imList.size() >= enabledImList.size());
-        }
+                List<InputMethodInfo> imList = imManager.getInputMethodList();
+                if (imList != null && enabledImList != null) {
+                    assertTrue(imList.size() >= enabledImList.size());
+                }
+            }
+        });
+        getInstrumentation().waitForIdleSync();
     }
 }
diff --git a/tests/tests/webkit/src/android/webkit/cts/TestHtmlConstants.java b/tests/tests/webkit/src/android/webkit/cts/TestHtmlConstants.java
index b2bdfc8..a31e0c0 100644
--- a/tests/tests/webkit/src/android/webkit/cts/TestHtmlConstants.java
+++ b/tests/tests/webkit/src/android/webkit/cts/TestHtmlConstants.java
@@ -56,6 +56,12 @@
 
     public static final String EXT_WEB_URL1 = "http://www.example.com/";
 
+    public static final String LOCAL_FILESYSTEM_URL = "file:///etc/hosts";
+
+    // Must match the title of the page at
+    // android/frameworks/base/core/res/res/raw/loaderror.html
+    public static final String WEBPAGE_NOT_AVAILABLE_TITLE = "Webpage not available";
+
     public static final String getFileUrl(String assetName) {
         if (assetName.contains(":") || assetName.startsWith("/")) {
             throw new IllegalArgumentException();
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java b/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
index 639f795..05e668b 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
@@ -214,7 +214,6 @@
             args = {boolean.class}
         )
     })
-    @ToBeFixed(explanation = "Cannot block file access using setAllowFileAccess(false)")
     public void testAccessAllowFileAccess() {
         assertTrue(mSettings.getAllowFileAccess());
 
@@ -225,11 +224,15 @@
         fileUrl = TestHtmlConstants.getFileUrl(TestHtmlConstants.BR_TAG_URL);
         mSettings.setAllowFileAccess(false);
         assertFalse(mSettings.getAllowFileAccess());
+
         loadUrl(fileUrl);
-        // direct file:// access still works with access disabled
+        // android_asset URLs should still be loaded when even with file access
+        // disabled.
         assertEquals(TestHtmlConstants.BR_TAG_TITLE, mWebView.getTitle());
 
-        // ToBeFixed: How does this API prevent file access?
+        // Files on the file system should not be loaded.
+        loadUrl(TestHtmlConstants.LOCAL_FILESYSTEM_URL);
+        assertEquals(TestHtmlConstants.WEBPAGE_NOT_AVAILABLE_TITLE, mWebView.getTitle());
     }
 
     @TestTargets({
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index c714d8a..a091c05 100755
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -19,8 +19,6 @@
 import com.android.cts.stub.R;
 import com.android.internal.util.FastMath;
 
-import android.graphics.Path;
-import android.graphics.RectF;
 import dalvik.annotation.TestLevel;
 import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
@@ -38,7 +36,9 @@
 import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.graphics.Paint;
+import android.graphics.Path;
 import android.graphics.Rect;
+import android.graphics.RectF;
 import android.graphics.Typeface;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
@@ -56,8 +56,8 @@
 import android.text.SpannableString;
 import android.text.TextPaint;
 import android.text.TextUtils;
-import android.text.TextWatcher;
 import android.text.TextUtils.TruncateAt;
+import android.text.TextWatcher;
 import android.text.method.ArrowKeyMovementMethod;
 import android.text.method.DateKeyListener;
 import android.text.method.DateTimeKeyListener;
@@ -70,22 +70,22 @@
 import android.text.method.QwertyKeyListener;
 import android.text.method.SingleLineTransformationMethod;
 import android.text.method.TextKeyListener;
+import android.text.method.TextKeyListener.Capitalize;
 import android.text.method.TimeKeyListener;
 import android.text.method.TransformationMethod;
-import android.text.method.TextKeyListener.Capitalize;
 import android.text.style.URLSpan;
 import android.text.style.cts.MockURLSpanTestActivity;
 import android.text.util.Linkify;
 import android.util.DisplayMetrics;
 import android.util.TypedValue;
 import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
 import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.View;
-import android.view.ViewGroup;
-import android.view.ContextMenu.ContextMenuInfo;
 import android.view.View.OnCreateContextMenuListener;
 import android.view.View.OnLongClickListener;
+import android.view.ViewGroup;
 import android.view.animation.cts.DelayedCheck;
 import android.view.inputmethod.BaseInputConnection;
 import android.view.inputmethod.EditorInfo;
@@ -3972,16 +3972,21 @@
         method = "isInputMethodTarget",
         args = {}
     )
-    @UiThreadTest
-    public void testIsInputMethodTarget() {
+    public void testIsInputMethodTarget() throws Throwable {
         mTextView = findTextView(R.id.textview_text);
         assertFalse(mTextView.isInputMethodTarget());
 
         assertFalse(mTextView.isFocused());
-        mTextView.setFocusable(true);
-        mTextView.requestFocus();
-        assertTrue(mTextView.isFocused());
+        runTestOnUiThread(new Runnable() {
+           @Override
+            public void run() {
+               mTextView.setFocusable(true);
+               mTextView.requestFocus();
+            }
+        });
+        mInstrumentation.waitForIdleSync();
 
+        assertTrue(mTextView.isFocused());
         assertTrue(mTextView.isInputMethodTarget());
     }
 
diff --git a/tools/cts-native-xml-generator/src/com/android/cts/nativexml/Generator.java b/tools/cts-native-xml-generator/src/com/android/cts/nativexml/Generator.java
index 3a75e49..7c074b8 100644
--- a/tools/cts-native-xml-generator/src/com/android/cts/nativexml/Generator.java
+++ b/tools/cts-native-xml-generator/src/com/android/cts/nativexml/Generator.java
@@ -59,9 +59,12 @@
         if (mOutputPath != null) {
             File outputFile = new File(mOutputPath);
             File outputDir = outputFile.getParentFile();
-            if (!outputDir.exists() && !outputDir.mkdirs()) {
-                System.err.println("Couldn't make output directory: " + mOutputPath);
-                System.exit(1);
+            if (!outputDir.exists()) {
+                outputDir.mkdirs();
+                if (!outputDir.exists()) {
+                    System.err.println("Couldn't make output directory: " + outputDir);
+                    System.exit(1);
+                }
             }
             output = new FileOutputStream(outputFile);
         }
diff --git a/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoConstants.java b/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoConstants.java
index dd9681a..c06c21e 100644
--- a/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoConstants.java
+++ b/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoConstants.java
@@ -30,7 +30,7 @@
     public static final String OPEN_GL_ES_VERSION = "openGlEsVersion";
     public static final String PROCESSES = "processes";
     public static final String FEATURES = "features";
-    public static final String PHONE_NUMBER = "phoneNumber";
+    public static final String PHONE_NUMBER = "subscriberId";
     public static final String LOCALES = "locales";
     public static final String IMSI = "imsi";
     public static final String IMEI = "imei";
diff --git a/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoInstrument.java b/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoInstrument.java
index ca0c803..c9fcc83 100644
--- a/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoInstrument.java
+++ b/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoInstrument.java
@@ -185,6 +185,10 @@
                 screenSize = "large";
                 break;
 
+            case Configuration.SCREENLAYOUT_SIZE_XLARGE:
+                screenSize = "xlarge";
+                break;
+
             case Configuration.SCREENLAYOUT_SIZE_UNDEFINED:
                 screenSize = "undefined";
                 break;
@@ -200,10 +204,13 @@
             case DisplayMetrics.DENSITY_MEDIUM:
                 return "mdpi";
 
+            case DisplayMetrics.DENSITY_TV:
+                return "tvdpi";
+
             case DisplayMetrics.DENSITY_HIGH:
                 return "hdpi";
 
-            case 320:
+            case DisplayMetrics.DENSITY_XHIGH:
                 return "xdpi";
 
             default:
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
index c28631b..b536102 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
@@ -31,7 +31,7 @@
     @Option(name="cts-install-path", description="the path to the cts installation to use")
     private String mCtsRootDirPath = System.getProperty("CTS_ROOT");
 
-    public static final String CTS_BUILD_VERSION = "4.0.3_r1";
+    public static final String CTS_BUILD_VERSION = "4.0.3_r2";
 
     /**
      * {@inheritDoc}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/command/CtsConsole.java b/tools/tradefed-host/src/com/android/cts/tradefed/command/CtsConsole.java
index 82fa0d7..bd7a983 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/command/CtsConsole.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/command/CtsConsole.java
@@ -203,7 +203,8 @@
     private void listResults(CtsBuildHelper ctsBuild) {
         TableFormatter tableFormatter = new TableFormatter();
         List<List<String>> table = new ArrayList<List<String>>();
-        table.add(Arrays.asList("Session","Pass", "Fail","Not Executed","Start time","Plan name"));
+        table.add(Arrays.asList("Session","Pass", "Fail","Not Executed","Start time","Plan name",
+                "Device serial(s)"));
         ITestResultRepo testResultRepo = new TestResultRepo(ctsBuild.getResultsDir());
         for (ITestSummary result : testResultRepo.getSummaries()) {
             table.add(Arrays.asList(Integer.toString(result.getId()),
@@ -211,7 +212,8 @@
                     Integer.toString(result.getNumFailed()),
                     Integer.toString(result.getNumIncomplete()),
                     result.getTimestamp(),
-                    result.getTestPlan()));
+                    result.getTestPlan(),
+                    result.getDeviceSerials()));
         }
         tableFormatter.displayTable(table, new PrintWriter(System.out, true));
     }
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java
index 855c209..686c90a 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java
@@ -84,6 +84,9 @@
     @Option(name = "quiet-output", description = "Mute display of test results.")
     private boolean mQuietOutput = false;
 
+    @Option(name = "result-server", description = "Server to publish test results.")
+    private String mResultServer;
+
     protected IBuildInfo mBuildInfo;
     private String mStartTime;
     private String mDeviceSerial;
@@ -254,9 +257,18 @@
             CLog.w("Unable to create XML report");
             return;
         }
-        createXmlResult(mReportDir, mStartTime, elapsedTime);
+
+        File reportFile = getResultFile(mReportDir);
+        createXmlResult(reportFile, mStartTime, elapsedTime);
         copyFormattingFiles(mReportDir);
         zipResults(mReportDir);
+
+        try {
+            ResultReporter reporter = new ResultReporter(mResultServer, reportFile);
+            reporter.reportResult();
+        } catch (IOException e) {
+            CLog.e(e);
+        }
     }
 
     private void logResult(String format, Object... args) {
@@ -281,12 +293,11 @@
     /**
      * Creates a report file and populates it with the report data from the completed tests.
      */
-    private void createXmlResult(File reportDir, String startTimestamp, long elapsedTime) {
+    private void createXmlResult(File reportFile, String startTimestamp, long elapsedTime) {
         String endTime = getTimestamp();
-
         OutputStream stream = null;
         try {
-            stream = createOutputResultStream(reportDir);
+            stream = createOutputResultStream(reportFile);
             KXmlSerializer serializer = new KXmlSerializer();
             serializer.setOutput(stream, "UTF-8");
             serializer.startDocument("UTF-8", false);
@@ -331,11 +342,14 @@
         //serializer.endTag(ns, RESULT_TAG);
     }
 
+    private File getResultFile(File reportDir) {
+        return new File(reportDir, TEST_RESULT_FILE_NAME);
+    }
+
     /**
      * Creates the output stream to use for test results. Exposed for mocking.
      */
-    OutputStream createOutputResultStream(File reportDir) throws IOException {
-        File reportFile = new File(reportDir, TEST_RESULT_FILE_NAME);
+    OutputStream createOutputResultStream(File reportFile) throws IOException {
         logResult("Created xml report file at file://%s", reportFile.getAbsolutePath());
         return new FileOutputStream(reportFile);
     }
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/DeviceInfoResult.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/DeviceInfoResult.java
index d5f4530..17b62ca 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/DeviceInfoResult.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/DeviceInfoResult.java
@@ -39,7 +39,7 @@
 class DeviceInfoResult extends AbstractXmlPullParser {
     static final String TAG = "DeviceInfo";
     private static final String ns = CtsXmlResultReporter.ns;
-    private static final String BUILD_TAG = "BuildInfo";
+    static final String BUILD_TAG = "BuildInfo";
     private static final String PHONE_TAG = "PhoneSubInfo";
     private static final String SCREEN_TAG = "Screen";
     private static final String FEATURE_INFO_TAG = "FeatureInfo";
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/ITestSummary.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/ITestSummary.java
index 509e564..98494ee 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/ITestSummary.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/ITestSummary.java
@@ -57,4 +57,9 @@
      */
     String getStartTime();
 
+    /**
+     * @return a comma separated list of device serials associated with result
+     */
+    String getDeviceSerials();
+
 }
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/IssueReporter.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/IssueReporter.java
index 8ee9c0f..9d903dd 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/IssueReporter.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/IssueReporter.java
@@ -28,11 +28,6 @@
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.net.HttpURLConnection;
-import java.net.URL;
 import java.util.Map;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutorService;
@@ -46,7 +41,6 @@
  */
 public class IssueReporter implements ITestInvocationListener {
 
-    private static final String FORM_DATA_BOUNDARY = "C75I55u3R3p0r73r";
     private static final int BUGREPORT_SIZE = 500 * 1024;
 
     private static final String PRODUCT_NAME_KEY = "buildName";
@@ -87,22 +81,42 @@
      */
     private void setBugReport(InputStreamSource dataStream) throws IOException {
         if (mCurrentIssue != null) {
-            InputStream input = dataStream.createInputStream();
-            ByteArrayOutputStream byteOutput = new ByteArrayOutputStream(BUGREPORT_SIZE);
-            GZIPOutputStream gzipOutput = new GZIPOutputStream(byteOutput);
-            for (byte[] buffer = new byte[1024]; input.read(buffer) >= 0; ) {
-                gzipOutput.write(buffer);
-            }
-            gzipOutput.close();
-
             // Only one bug report can be stored at a time and they are gzipped to
             // about 0.5 MB so there shoudn't be any memory leak bringing down CTS.
-            mCurrentIssue.mBugReport = byteOutput.toByteArray();
+            InputStream input = null;
+            try {
+                input = dataStream.createInputStream();
+                mCurrentIssue.mBugReport = getBytes(input, BUGREPORT_SIZE);
+            } finally {
+                if (input != null) {
+                    input.close();
+                }
+            }
         } else {
             CLog.e("setBugReport is getting called on an empty issue...");
         }
     }
 
+    /**
+     * @param input that will be gzipped and returne as a byte array
+     * @param size of the output expected
+     * @return the byte array with the input's data
+     * @throws IOException
+     */
+    static byte[] getBytes(InputStream input, int size) throws IOException {
+        ByteArrayOutputStream byteOutput = new ByteArrayOutputStream(size);
+        GZIPOutputStream gzipOutput = new GZIPOutputStream(byteOutput);
+        for (byte[] buffer = new byte[1024]; ; ) {
+            int numRead = input.read(buffer);
+            if (numRead < 0) {
+                break;
+            }
+            gzipOutput.write(buffer, 0, numRead);
+        }
+        gzipOutput.close();
+        return byteOutput.toByteArray();
+    }
+
     @Override
     public void testEnded(TestIdentifier test, Map<String, String> testMetrics) {
         if (mCurrentIssue != null) {
@@ -158,32 +172,14 @@
                 return null;
             }
 
-            HttpURLConnection connection = null;
-
-            try {
-                URL url = new URL(mServerUrl);
-                connection = (HttpURLConnection) url.openConnection();
-                connection.setRequestMethod("POST");
-                connection.setDoOutput(true);
-                connection.setRequestProperty("Content-Type",
-                        "multipart/form-data; boundary=" + FORM_DATA_BOUNDARY);
-
-                byte[] body = getContentBody();
-                connection.setRequestProperty("Content-Length", Integer.toString(body.length));
-
-                OutputStream output = connection.getOutputStream();
-                output.write(body);
-                output.close();
-
-                // Open the stream to get a response. Otherwise request will be cancelled.
-                InputStream input = connection.getInputStream();
-                input.close();
-
-            } finally {
-                if (connection != null) {
-                    connection.disconnect();
-                }
-            }
+            new MultipartForm(mServerUrl)
+                    .addFormValue("productName", mProductName)
+                    .addFormValue("buildType", mBuildType)
+                    .addFormValue("buildId", mBuildId)
+                    .addFormValue("testName", mTestName)
+                    .addFormValue("stackTrace", mStackTrace)
+                    .addFormFile("bugReport", "bugreport.txt.gz", mBugReport)
+                    .submit();
 
             return null;
         }
@@ -191,43 +187,6 @@
         private boolean isEmpty(String value) {
             return value == null || value.trim().isEmpty();
         }
-
-        private byte[] getContentBody() throws IOException {
-            ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
-            PrintWriter writer = new PrintWriter(new OutputStreamWriter(byteOutput));
-            writer.println();
-            writeFormField(writer, "productName", mProductName);
-            writeFormField(writer, "buildType", mBuildType);
-            writeFormField(writer, "buildId", mBuildId);
-            writeFormField(writer, "testName", mTestName);
-            writeFormField(writer, "stackTrace", mStackTrace);
-            if (mBugReport != null) {
-                writeFormFileHeader(writer, "bugReport", "bugReport.txt.gz");
-                writer.flush(); // Must flush here before writing to the byte stream!
-                byteOutput.write(mBugReport);
-                writer.println();
-            }
-            writer.append("--").append(FORM_DATA_BOUNDARY).println("--");
-            writer.flush();
-            writer.close();
-            return byteOutput.toByteArray();
-        }
-
-        private void writeFormField(PrintWriter writer, String name, String value) {
-            writer.append("--").println(FORM_DATA_BOUNDARY);
-            writer.append("Content-Disposition: form-data; name=\"").append(name).println("\"");
-            writer.println();
-            writer.println(value);
-        }
-
-        private void writeFormFileHeader(PrintWriter writer, String name, String fileName) {
-            writer.append("--").println(FORM_DATA_BOUNDARY);
-            writer.append("Content-Disposition: form-data; name=\"").append(name);
-            writer.append("\"; filename=\"").append(fileName).println("\"");
-            writer.println("Content-Type: application/x-gzip");
-            writer.println("Content-Transfer-Encoding: binary");
-            writer.println();
-        }
     }
 
     @Override
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/MultipartForm.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/MultipartForm.java
new file mode 100644
index 0000000..f3ef0bb
--- /dev/null
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/MultipartForm.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.tradefed.result;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+/** MultipartForm builds a multipart form and submits it. */
+class MultipartForm {
+
+    private static final String FORM_DATA_BOUNDARY = "C75I55u3R3p0r73r";
+
+    private final String mServerUrl;
+
+    private final Map<String, String> mFormValues = new HashMap<String, String>();
+
+    private String mName;
+    private String mFileName;
+    private byte[] mData;
+
+    public MultipartForm(String serverUrl) {
+        mServerUrl = serverUrl;
+    }
+
+    public MultipartForm addFormValue(String name, String value) {
+        mFormValues.put(name, value);
+        return this;
+    }
+
+    public MultipartForm addFormFile(String name, String fileName, byte[] data) {
+        mName = name;
+        mFileName = fileName;
+        mData = data;
+        return this;
+    }
+
+    public void submit() throws IOException {
+        String redirectUrl = submitForm(mServerUrl);
+        if (redirectUrl != null) {
+            submitForm(redirectUrl);
+        }
+    }
+
+    /**
+     * @param serverUrl to post the data to
+     * @return a url if the server redirected to another url
+     * @throws IOException
+     */
+    private String submitForm(String serverUrl) throws IOException {
+        HttpURLConnection connection = null;
+        try {
+            URL url = new URL(serverUrl);
+            connection = (HttpURLConnection) url.openConnection();
+            connection.setInstanceFollowRedirects(false);
+            connection.setRequestMethod("POST");
+            connection.setDoOutput(true);
+            connection.setRequestProperty("Content-Type",
+                    "multipart/form-data; boundary=" + FORM_DATA_BOUNDARY);
+
+            byte[] body = getContentBody();
+            connection.setRequestProperty("Content-Length", Integer.toString(body.length));
+
+            OutputStream output = connection.getOutputStream();
+            try {
+                output.write(body);
+            } finally {
+                output.close();
+            }
+
+            // Open the stream to get a response. Otherwise request will be cancelled.
+            InputStream input = connection.getInputStream();
+            input.close();
+
+            if (connection.getResponseCode() == 302) {
+                return connection.getHeaderField("Location");
+            }
+        } finally {
+            if (connection != null) {
+                connection.disconnect();
+            }
+        }
+
+        return null;
+    }
+
+    private byte[] getContentBody() throws IOException {
+        ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
+        PrintWriter writer = new PrintWriter(new OutputStreamWriter(byteOutput));
+        writer.println();
+
+        for (Map.Entry<String, String> formValue : mFormValues.entrySet()) {
+            writeFormField(writer, formValue.getKey(), formValue.getValue());
+        }
+
+        if (mData != null) {
+            writeFormFileHeader(writer, mName, mFileName);
+            writer.flush(); // Must flush here before writing to the byte stream!
+            byteOutput.write(mData);
+            writer.println();
+        }
+        writer.append("--").append(FORM_DATA_BOUNDARY).println("--");
+        writer.flush();
+        writer.close();
+        return byteOutput.toByteArray();
+    }
+
+    private void writeFormField(PrintWriter writer, String name, String value) {
+        writer.append("--").println(FORM_DATA_BOUNDARY);
+        writer.append("Content-Disposition: form-data; name=\"").append(name).println("\"");
+        writer.println();
+        writer.println(value);
+    }
+
+    private void writeFormFileHeader(PrintWriter writer, String name, String fileName) {
+        writer.append("--").println(FORM_DATA_BOUNDARY);
+        writer.append("Content-Disposition: form-data; name=\"").append(name);
+        writer.append("\"; filename=\"").append(fileName).println("\"");
+        writer.println("Content-Type: application/x-gzip");
+        writer.println("Content-Transfer-Encoding: binary");
+        writer.println();
+    }
+}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/ResultReporter.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/ResultReporter.java
new file mode 100644
index 0000000..05192c9
--- /dev/null
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/ResultReporter.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.tradefed.result;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Class that sends a HTTP POST multipart/form-data request containing
+ * the test result XML.
+ */
+class ResultReporter {
+
+    private static final int RESULT_XML_BYTES = 500 * 1024;
+
+    private final String mServerUrl;
+
+    private final File mReportFile;
+
+    ResultReporter(String serverUrl, File reportFile) {
+        mServerUrl = serverUrl;
+        mReportFile = reportFile;
+    }
+
+    public void reportResult() throws IOException {
+        if (isEmpty(mServerUrl)) {
+            return;
+        }
+
+        InputStream input = new FileInputStream(mReportFile);
+        try {
+            byte[] data = IssueReporter.getBytes(input, RESULT_XML_BYTES);
+            new MultipartForm(mServerUrl)
+                    .addFormFile("resultXml", "testResult.xml.gz", data)
+                    .submit();
+        } finally {
+            input.close();
+        }
+    }
+
+    private boolean isEmpty(String value) {
+        return value == null || value.trim().isEmpty();
+    }
+}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/TestSummaryXml.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestSummaryXml.java
index af37184..36f3297 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/TestSummaryXml.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestSummaryXml.java
@@ -20,6 +20,8 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
+import android.tests.getinfo.DeviceInfoConstants;
+
 import java.io.FileNotFoundException;
 import java.io.IOException;
 
@@ -35,6 +37,7 @@
     private int mNumPassed = 0;
     private String mPlan = "NA";
     private String mStartTime = "unknown";
+    private String mDeviceSerials = "unknown";
 
     /**
      * @param id
@@ -105,13 +108,17 @@
                 mPlan = getAttribute(parser, CtsXmlResultReporter.PLAN_ATTR);
                 mStartTime = getAttribute(parser, CtsXmlResultReporter.STARTTIME_ATTR);
             } else if (eventType == XmlPullParser.START_TAG && parser.getName().equals(
+                    DeviceInfoResult.BUILD_TAG)) {
+                mDeviceSerials = getAttribute(parser, DeviceInfoConstants.SERIAL_NUMBER);
+            } else if (eventType == XmlPullParser.START_TAG && parser.getName().equals(
                     TestResults.SUMMARY_TAG)) {
                 mNumFailed = parseIntAttr(parser, TestResults.FAILED_ATTR) +
                     parseIntAttr(parser, TestResults.TIMEOUT_ATTR);
                 mNumNotExecuted = parseIntAttr(parser, TestResults.NOT_EXECUTED_ATTR);
                 mNumPassed = parseIntAttr(parser, TestResults.PASS_ATTR);
+                // abort after parsing Summary, which should be the last tag
                 return;
-              }
+             }
             eventType = parser.next();
         }
         throw new XmlPullParserException("Could not find Summary tag");
@@ -124,5 +131,12 @@
     public String getStartTime() {
         return mStartTime;
     }
-}
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String getDeviceSerials() {
+        return mDeviceSerials;
+    }
+}
diff --git a/tools/utils/buildCts.py b/tools/utils/buildCts.py
index 3e83343..98978fd 100755
--- a/tools/utils/buildCts.py
+++ b/tools/utils/buildCts.py
@@ -106,14 +106,11 @@
       packages.append(doc.GetAttr('TestPackage', 'appPackageName'))
 
     plan = tools.TestPlan(packages)
-    plan.Exclude(r'android\.core\.vm-tests-tf')
-    plan.Exclude('android\.performance.*')
-    self.__WritePlan(plan, 'CTS')
-
     plan.Exclude('android\.core\.vm-tests')
     plan.Exclude('android\.performance.*')
     plan.Include(r'android\.core\.vm-tests-tf')
     self.__WritePlan(plan, 'CTS-TF')
+    self.__WritePlan(plan, 'CTS')
 
     plan.Exclude(r'android\.tests\.sigtest')
     plan.Exclude(r'android\.core.*')
@@ -124,11 +121,6 @@
     self.__WritePlan(plan, 'Java')
 
     plan = tools.TestPlan(packages)
-    plan.Include(r'android\.core\.vm-tests')
-    plan.Exclude(r'android\.core\.vm-tests-tf')
-    self.__WritePlan(plan, 'VM')
-
-    plan = tools.TestPlan(packages)
     plan.Include(r'android\.core\.vm-tests-tf')
     self.__WritePlan(plan, 'VM-TF')